diff --git a/parmys/parmys-plugin/parmys.cc b/parmys/parmys-plugin/parmys.cc index 158db0253b8..a73c285ac49 100644 --- a/parmys/parmys-plugin/parmys.cc +++ b/parmys/parmys-plugin/parmys.cc @@ -1099,8 +1099,11 @@ struct ParMYSPass : public Pass { log("Updating the Design\n"); Pass::call(design, "delete"); - + std::vector modules_to_remove; for (auto module : design->modules()) { + modules_to_remove.push_back(module); + } + for (auto module : modules_to_remove) { design->remove(module); } diff --git a/parmys/parmys-plugin/parmys_update.cc b/parmys/parmys-plugin/parmys_update.cc index ef55213c5a3..4e4d6dd15af 100644 --- a/parmys/parmys-plugin/parmys_update.cc +++ b/parmys/parmys-plugin/parmys_update.cc @@ -506,9 +506,9 @@ void define_logical_function_yosys(nnode_t *node, Module *module) lutptr = &cell->parameters.at(ID::LUT); for (int i = 0; i < (1 << node->num_input_pins); i++) { if (i == 3 || i == 5 || i == 6 || i == 7) //"011 1\n101 1\n110 1\n111 1\n" - lutptr->bits.at(i) = RTLIL::State::S1; + lutptr->bits().at(i) = RTLIL::State::S1; else - lutptr->bits.at(i) = RTLIL::State::S0; + lutptr->bits().at(i) = RTLIL::State::S0; } } else { cell->parameters[ID::A_WIDTH] = RTLIL::Const(int(node->num_input_pins)); diff --git a/parmys/regression_test/benchmark/task/freecores/synthesis_result.json b/parmys/regression_test/benchmark/task/freecores/synthesis_result.json index f987e7cb0e6..09150fb4887 100644 --- a/parmys/regression_test/benchmark/task/freecores/synthesis_result.json +++ b/parmys/regression_test/benchmark/task/freecores/synthesis_result.json @@ -479,20 +479,20 @@ "Multiplier": 1, "Memory": 8, "generic logic size": 4, - "Longest Path": 274, + "Longest Path": 275, "Average Path": 3, "Estimated LUTs": 4777, "Total Node": 1957, - "Wires": 5591, - "Wire Bits": 10025, + "Wires": 5594, + "Wire Bits": 10106, "Public Wires": 240, "Public Wire Bits": 240, - "Total Cells": 8185, + "Total Cells": 8190, "MUX": 2164, "XOR": 40, - "OR": 2836, - "AND": 1451, - "NOT": 637, + "OR": 2837, + "AND": 1453, + "NOT": 639, "DFFs": [ "$_DFF_P_ 645" ], @@ -534,7 +534,7 @@ "Estimated LUTs": 41888, "Total Node": 5344, "Wires": 9777, - "Wire Bits": 102242, + "Wire Bits": 102228, "Public Wires": 391, "Public Wire Bits": 391, "Total Cells": 31999, @@ -585,8 +585,8 @@ "Average Path": 3, "Estimated LUTs": 42386, "Total Node": 5593, - "Wires": 10796, - "Wire Bits": 103210, + "Wires": 10808, + "Wire Bits": 103300, "Public Wires": 648, "Public Wire Bits": 648, "Total Cells": 32995, @@ -832,28 +832,28 @@ "synthesis_time(ms)": 13, "Pi": 96, "Po": 115, - "logic element": 2439, - "Adder": 426, + "logic element": 2425, + "Adder": 412, "Memory": 96, "generic logic size": 4, - "Longest Path": 473, + "Longest Path": 476, "Average Path": 4, - "Estimated LUTs": 4564, - "Total Node": 2961, - "Wires": 6934, - "Wire Bits": 11506, - "Public Wires": 501, - "Public Wire Bits": 501, + "Estimated LUTs": 4550, + "Total Node": 2933, + "Wires": 6977, + "Wire Bits": 11482, + "Public Wires": 487, + "Public Wire Bits": 487, "Total Cells": 8955, - "MUX": 2605, - "XOR": 311, - "OR": 1861, - "AND": 1683, - "NOT": 672, + "MUX": 2601, + "XOR": 295, + "OR": 1926, + "AND": 1684, + "NOT": 678, "DFFs": [ - "$_DFF_P_ 1312" + "$_DFF_P_ 1310" ], - "adder": 415, + "adder": 365, "dual_port_ram": 64, "single_port_ram": 32 }, diff --git a/parmys/regression_test/benchmark/task/keywords/and/synthesis_result.json b/parmys/regression_test/benchmark/task/keywords/and/synthesis_result.json index cf59de4c2ac..f147d906941 100644 --- a/parmys/regression_test/benchmark/task/keywords/and/synthesis_result.json +++ b/parmys/regression_test/benchmark/task/keywords/and/synthesis_result.json @@ -95,21 +95,21 @@ "test_name": "and/replicate_and_int_wide/no_arch", "exit": 1, "errors": [ - "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2686." + "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2754." ] }, "and/replicate_and_ultra_wide/no_arch": { "test_name": "and/replicate_and_ultra_wide/no_arch", "exit": 1, "errors": [ - "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2686." + "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2754." ] }, "and/replicate_and_wide/no_arch": { "test_name": "and/replicate_and_wide/no_arch", "exit": 1, "errors": [ - "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2686." + "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2754." ] }, "DEFAULT": { diff --git a/parmys/regression_test/benchmark/task/keywords/else/synthesis_result.json b/parmys/regression_test/benchmark/task/keywords/else/synthesis_result.json index 3e4591cff63..baa9a7f8f95 100644 --- a/parmys/regression_test/benchmark/task/keywords/else/synthesis_result.json +++ b/parmys/regression_test/benchmark/task/keywords/else/synthesis_result.json @@ -19,16 +19,16 @@ "Average Path": 4, "Estimated LUTs": 4, "Total Node": 4, - "Wires": 9, - "Wire Bits": 9, + "Wires": 11, + "Wire Bits": 11, "Public Wires": 4, "Public Wire Bits": 4, - "Total Cells": 7, + "Total Cells": 9, "MUX": 1, "XOR": 2, - "OR": 1, + "OR": 2, "AND": 1, - "NOT": 2 + "NOT": 3 }, "else/if_else/no_arch": { "test_name": "else/if_else/no_arch", diff --git a/parmys/regression_test/benchmark/task/keywords/nand/synthesis_result.json b/parmys/regression_test/benchmark/task/keywords/nand/synthesis_result.json index bf5a84407fe..b6797a1cc0e 100644 --- a/parmys/regression_test/benchmark/task/keywords/nand/synthesis_result.json +++ b/parmys/regression_test/benchmark/task/keywords/nand/synthesis_result.json @@ -94,21 +94,21 @@ "test_name": "nand/replicate_nand_int_wide/no_arch", "exit": 1, "errors": [ - "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2686." + "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2754." ] }, "nand/replicate_nand_ultra_wide/no_arch": { "test_name": "nand/replicate_nand_ultra_wide/no_arch", "exit": 1, "errors": [ - "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2686." + "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2754." ] }, "nand/replicate_nand_wide/no_arch": { "test_name": "nand/replicate_nand_wide/no_arch", "exit": 1, "errors": [ - "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2686." + "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2754." ] }, "DEFAULT": { diff --git a/parmys/regression_test/benchmark/task/keywords/nor/synthesis_result.json b/parmys/regression_test/benchmark/task/keywords/nor/synthesis_result.json index 7cf8c497b1a..087cf87210b 100644 --- a/parmys/regression_test/benchmark/task/keywords/nor/synthesis_result.json +++ b/parmys/regression_test/benchmark/task/keywords/nor/synthesis_result.json @@ -100,21 +100,21 @@ "test_name": "nor/replicate_nor_int_wide/no_arch", "exit": 1, "errors": [ - "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2686." + "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2754." ] }, "nor/replicate_nor_ultra_wide/no_arch": { "test_name": "nor/replicate_nor_ultra_wide/no_arch", "exit": 1, "errors": [ - "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2686." + "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2754." ] }, "nor/replicate_nor_wide/no_arch": { "test_name": "nor/replicate_nor_wide/no_arch", "exit": 1, "errors": [ - "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2686." + "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2754." ] }, "DEFAULT": { diff --git a/parmys/regression_test/benchmark/task/keywords/or/synthesis_result.json b/parmys/regression_test/benchmark/task/keywords/or/synthesis_result.json index 1910b31c09b..75c2146c39a 100644 --- a/parmys/regression_test/benchmark/task/keywords/or/synthesis_result.json +++ b/parmys/regression_test/benchmark/task/keywords/or/synthesis_result.json @@ -95,21 +95,21 @@ "test_name": "or/replicate_or_int_wide/no_arch", "exit": 1, "errors": [ - "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2686." + "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2754." ] }, "or/replicate_or_ultra_wide/no_arch": { "test_name": "or/replicate_or_ultra_wide/no_arch", "exit": 1, "errors": [ - "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2686." + "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2754." ] }, "or/replicate_or_wide/no_arch": { "test_name": "or/replicate_or_wide/no_arch", "exit": 1, "errors": [ - "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2686." + "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2754." ] }, "DEFAULT": { diff --git a/parmys/regression_test/benchmark/task/keywords/xnor/synthesis_result.json b/parmys/regression_test/benchmark/task/keywords/xnor/synthesis_result.json index e225f1235cd..0c0aa976123 100644 --- a/parmys/regression_test/benchmark/task/keywords/xnor/synthesis_result.json +++ b/parmys/regression_test/benchmark/task/keywords/xnor/synthesis_result.json @@ -54,21 +54,21 @@ "test_name": "xnor/replicate_xnor_int_wide/no_arch", "exit": 1, "errors": [ - "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2686." + "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2754." ] }, "xnor/replicate_xnor_ultra_wide/no_arch": { "test_name": "xnor/replicate_xnor_ultra_wide/no_arch", "exit": 1, "errors": [ - "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2686." + "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2754." ] }, "xnor/replicate_xnor_wide/no_arch": { "test_name": "xnor/replicate_xnor_wide/no_arch", "exit": 1, "errors": [ - "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2686." + "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2754." ] }, "xnor/xnor_indexed_port/no_arch": { diff --git a/parmys/regression_test/benchmark/task/keywords/xor/synthesis_result.json b/parmys/regression_test/benchmark/task/keywords/xor/synthesis_result.json index 759ed77af6f..97a3636fba4 100644 --- a/parmys/regression_test/benchmark/task/keywords/xor/synthesis_result.json +++ b/parmys/regression_test/benchmark/task/keywords/xor/synthesis_result.json @@ -51,21 +51,21 @@ "test_name": "xor/replicate_xor_int_wide/no_arch", "exit": 1, "errors": [ - "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2686." + "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2754." ] }, "xor/replicate_xor_ultra_wide/no_arch": { "test_name": "xor/replicate_xor_ultra_wide/no_arch", "exit": 1, "errors": [ - "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2686." + "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2754." ] }, "xor/replicate_xor_wide/no_arch": { "test_name": "xor/replicate_xor_wide/no_arch", "exit": 1, "errors": [ - "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2686." + "Assert `new_cell->children.at(0)->type == AST_CELLTYPE' failed in frontends/ast/simplify.cc:2754." ] }, "xor/xor_indexed_port/no_arch": { diff --git a/parmys/regression_test/benchmark/task/koios/koios_medium/synthesis_result.json b/parmys/regression_test/benchmark/task/koios/koios_medium/synthesis_result.json index 4ff3586159b..a47ba833bc1 100644 --- a/parmys/regression_test/benchmark/task/koios/koios_medium/synthesis_result.json +++ b/parmys/regression_test/benchmark/task/koios/koios_medium/synthesis_result.json @@ -94,16 +94,16 @@ "Average Path": 3, "Estimated LUTs": 28425, "Total Node": 16656, - "Wires": 58023, - "Wire Bits": 81442, + "Wires": 58017, + "Wire Bits": 81436, "Public Wires": 8453, "Public Wire Bits": 8453, - "Total Cells": 42044, + "Total Cells": 42029, "MUX": 10563, "XOR": 326, - "OR": 3618, - "AND": 418, - "NOT": 6483, + "OR": 3612, + "AND": 415, + "NOT": 6477, "DFFs": [ "$_DFF_P_ 8096" ], @@ -175,14 +175,14 @@ "Average Path": 2, "Estimated LUTs": 62945, "Total Node": 90815, - "Wires": 258254, - "Wire Bits": 264014, + "Wires": 260046, + "Wire Bits": 267214, "Public Wires": 29781, "Public Wire Bits": 29781, - "Total Cells": 173152, + "Total Cells": 176096, "MUX": 55029, - "OR": 259, - "AND": 2248, + "OR": 1923, + "AND": 3528, "NOT": 6166, "DFFs": [ "$_DFF_P_ 52402" @@ -357,16 +357,15 @@ "Average Path": 4, "Estimated LUTs": 20367, "Total Node": 3582, - "Wires": 25202, - "Wire Bits": 56222, + "Wires": 20576, + "Wire Bits": 30944, "Public Wires": 5264, "Public Wire Bits": 5264, - "Total Cells": 29499, - "MUX": 15873, - "XOR": 6, - "OR": 3216, - "AND": 5100, - "NOT": 966, + "Total Cells": 18849, + "MUX": 7815, + "OR": 2118, + "AND": 3807, + "NOT": 771, "DFFs": [ "$_DFF_P_ 3345" ], @@ -559,27 +558,27 @@ "Pi": 91, "Po": 65, "logic element": 1876, - "Adder": 2024, + "Adder": 2023, "Memory": 896, "generic logic size": 4, "Longest Path": 107, "Average Path": 5, "Estimated LUTs": 15571, - "Total Node": 4796, - "Wires": 45912, - "Wire Bits": 49616, + "Total Node": 4795, + "Wires": 45931, + "Wire Bits": 49668, "Public Wires": 5161, "Public Wire Bits": 5161, - "Total Cells": 42880, + "Total Cells": 42904, "MUX": 22203, "XOR": 15, - "OR": 2976, - "AND": 2632, - "NOT": 252, + "OR": 2990, + "AND": 2640, + "NOT": 255, "DFFs": [ "$_DFF_P_ 11798" ], - "adder": 2024, + "adder": 2023, "dual_port_ram": 896, "mac_int_18x19": 84 }, @@ -1020,16 +1019,16 @@ "Average Path": 4, "Estimated LUTs": 48603, "Total Node": 34434, - "Wires": 187300, - "Wire Bits": 206982, + "Wires": 187072, + "Wire Bits": 207294, "Public Wires": 7467, "Public Wire Bits": 7467, - "Total Cells": 166461, + "Total Cells": 166749, "MUX": 46810, "XOR": 4788, - "OR": 1209, - "AND": 8339, - "NOT": 3426, + "OR": 1257, + "AND": 8531, + "NOT": 3474, "DFFs": [ "$_DFF_P_ 75245" ], @@ -1081,15 +1080,15 @@ "Average Path": 5, "Estimated LUTs": 5476, "Total Node": 2369, - "Wires": 16619, - "Wire Bits": 20690, + "Wires": 16661, + "Wire Bits": 20756, "Public Wires": 3705, "Public Wire Bits": 3705, - "Total Cells": 16665, + "Total Cells": 16735, "MUX": 6310, "XOR": 96, - "OR": 1635, - "AND": 2178, + "OR": 1675, + "AND": 2208, "NOT": 166, "DFFs": [ "$_DFF_P_ 4435" @@ -1127,16 +1126,16 @@ "Average Path": 3, "Estimated LUTs": 11429, "Total Node": 5611, - "Wires": 23476, - "Wire Bits": 36833, + "Wires": 23477, + "Wire Bits": 36834, "Public Wires": 2102, "Public Wire Bits": 2102, - "Total Cells": 31479, + "Total Cells": 31480, "MUX": 11207, "XOR": 2213, "OR": 2367, "AND": 6380, - "NOT": 2353, + "NOT": 2354, "DFFs": [ "$_DFF_P_ 2383" ], @@ -1222,16 +1221,16 @@ "Average Path": 4, "Estimated LUTs": 13223, "Total Node": 5602, - "Wires": 28845, - "Wire Bits": 50523, + "Wires": 28994, + "Wire Bits": 50685, "Public Wires": 3999, "Public Wire Bits": 3999, - "Total Cells": 42292, + "Total Cells": 42439, "MUX": 11266, "XOR": 3492, - "OR": 5673, - "AND": 8416, - "NOT": 3121, + "OR": 5746, + "AND": 8418, + "NOT": 3193, "DFFs": [ "$_DFF_P_ 6976" ], @@ -1323,16 +1322,16 @@ "Average Path": 6, "Estimated LUTs": 19996, "Total Node": 2823, - "Wires": 16436, - "Wire Bits": 66380, + "Wires": 16598, + "Wire Bits": 66539, "Public Wires": 1608, "Public Wire Bits": 1608, - "Total Cells": 25311, + "Total Cells": 25303, "MUX": 8606, "XOR": 322, - "OR": 10495, - "AND": 843, - "NOT": 1951, + "OR": 10524, + "AND": 823, + "NOT": 1934, "DFFs": [ "$_DFF_P_ 2525" ], @@ -1420,15 +1419,15 @@ "Average Path": 4, "Estimated LUTs": 6918, "Total Node": 7979, - "Wires": 25579, - "Wire Bits": 33142, + "Wires": 25578, + "Wire Bits": 33141, "Public Wires": 4755, "Public Wire Bits": 4755, - "Total Cells": 21954, + "Total Cells": 21953, "MUX": 8368, "XOR": 1413, "OR": 1380, - "AND": 1133, + "AND": 1132, "NOT": 848, "DFFs": [ "$_DFF_P_ 4009" @@ -2293,15 +2292,15 @@ "Average Path": 3, "Estimated LUTs": 25350, "Total Node": 2859, - "Wires": 68020, - "Wire Bits": 73227, + "Wires": 68173, + "Wire Bits": 73604, "Public Wires": 38946, "Public Wire Bits": 38946, - "Total Cells": 29737, + "Total Cells": 29826, "MUX": 16691, "XOR": 3, - "OR": 1674, - "AND": 1527, + "OR": 1755, + "AND": 1535, "NOT": 730, "DFFs": [ "$_DFF_P_ 8028" @@ -5185,16 +5184,16 @@ "Average Path": 3, "Estimated LUTs": 26601, "Total Node": 5142, - "Wires": 65236, - "Wire Bits": 80097, + "Wires": 65369, + "Wire Bits": 80597, "Public Wires": 39529, "Public Wire Bits": 39529, - "Total Cells": 33387, + "Total Cells": 33570, "MUX": 13126, "XOR": 408, - "OR": 4888, - "AND": 4147, - "NOT": 993, + "OR": 4962, + "AND": 4171, + "NOT": 1078, "DFFs": [ "$_DFF_P_ 7390" ], diff --git a/parmys/regression_test/benchmark/task/koios/koios_medium_no_hb/synthesis_result.json b/parmys/regression_test/benchmark/task/koios/koios_medium_no_hb/synthesis_result.json index 9a69f2195d6..ff4d11e6d29 100644 --- a/parmys/regression_test/benchmark/task/koios/koios_medium_no_hb/synthesis_result.json +++ b/parmys/regression_test/benchmark/task/koios/koios_medium_no_hb/synthesis_result.json @@ -169,16 +169,16 @@ "Average Path": 3, "Estimated LUTs": 28720, "Total Node": 16803, - "Wires": 58024, - "Wire Bits": 81592, + "Wires": 58018, + "Wire Bits": 81586, "Public Wires": 8454, "Public Wire Bits": 8454, - "Total Cells": 42044, + "Total Cells": 42029, "MUX": 10563, "XOR": 326, - "OR": 3618, - "AND": 418, - "NOT": 6483, + "OR": 3612, + "AND": 415, + "NOT": 6477, "DFFs": [ "$_DFF_P_ 8096" ], @@ -250,14 +250,14 @@ "Average Path": 2, "Estimated LUTs": 62945, "Total Node": 90815, - "Wires": 258254, - "Wire Bits": 264014, + "Wires": 260046, + "Wire Bits": 267214, "Public Wires": 29781, "Public Wire Bits": 29781, - "Total Cells": 173152, + "Total Cells": 176096, "MUX": 55029, - "OR": 259, - "AND": 2248, + "OR": 1923, + "AND": 3528, "NOT": 6166, "DFFs": [ "$_DFF_P_ 52402" @@ -463,16 +463,16 @@ "Average Path": 4, "Estimated LUTs": 22752, "Total Node": 5094, - "Wires": 28654, - "Wire Bits": 62943, + "Wires": 24045, + "Wire Bits": 37311, "Public Wires": 5228, "Public Wire Bits": 5228, - "Total Cells": 34741, - "MUX": 17334, - "XOR": 252, - "OR": 4240, - "AND": 6360, - "NOT": 1623, + "Total Cells": 24019, + "MUX": 9276, + "XOR": 246, + "OR": 3133, + "AND": 5013, + "NOT": 1419, "DFFs": [ "$_DFF_P_ 3345" ], @@ -662,28 +662,28 @@ "Pi": 91, "Po": 65, "logic element": 1912, - "Adder": 3608, + "Adder": 3607, "Multiplier": 84, "Memory": 896, "generic logic size": 4, "Longest Path": 108, "Average Path": 5, "Estimated LUTs": 16387, - "Total Node": 6500, - "Wires": 57036, - "Wire Bits": 60740, + "Total Node": 6499, + "Wires": 57055, + "Wire Bits": 60792, "Public Wires": 2053, "Public Wire Bits": 2053, - "Total Cells": 50991, + "Total Cells": 51015, "MUX": 26043, "XOR": 15, - "OR": 2975, - "AND": 2632, - "NOT": 252, + "OR": 2989, + "AND": 2640, + "NOT": 255, "DFFs": [ "$_DFF_P_ 14486" ], - "adder": 3608, + "adder": 3607, "dual_port_ram": 896, "multiply": 84 }, @@ -1120,16 +1120,16 @@ "Average Path": 4, "Estimated LUTs": 47955, "Total Node": 36666, - "Wires": 203716, - "Wire Bits": 223398, + "Wires": 203488, + "Wire Bits": 223710, "Public Wires": 2139, "Public Wire Bits": 2139, - "Total Cells": 178701, + "Total Cells": 178989, "MUX": 51994, "XOR": 4788, - "OR": 1209, - "AND": 8339, - "NOT": 3426, + "OR": 1257, + "AND": 8531, + "NOT": 3474, "DFFs": [ "$_DFF_P_ 80429" ], @@ -1227,16 +1227,16 @@ "Average Path": 5, "Estimated LUTs": 13699, "Total Node": 7769, - "Wires": 29635, - "Wire Bits": 41808, + "Wires": 29721, + "Wire Bits": 41696, "Public Wires": 3147, "Public Wire Bits": 3147, - "Total Cells": 33495, + "Total Cells": 33385, "MUX": 8974, "XOR": 624, - "OR": 4205, - "AND": 5632, - "NOT": 1707, + "OR": 4219, + "AND": 5530, + "NOT": 1685, "DFFs": [ "$_DFF_P_ 8160" ], @@ -1272,16 +1272,16 @@ "Average Path": 3, "Estimated LUTs": 11429, "Total Node": 5611, - "Wires": 23476, - "Wire Bits": 36833, + "Wires": 23477, + "Wire Bits": 36834, "Public Wires": 2102, "Public Wire Bits": 2102, - "Total Cells": 31479, + "Total Cells": 31480, "MUX": 11207, "XOR": 2213, "OR": 2367, "AND": 6380, - "NOT": 2353, + "NOT": 2354, "DFFs": [ "$_DFF_P_ 2383" ], @@ -1335,16 +1335,16 @@ "Average Path": 4, "Estimated LUTs": 13223, "Total Node": 5602, - "Wires": 28852, - "Wire Bits": 50506, + "Wires": 28999, + "Wire Bits": 50657, "Public Wires": 3999, "Public Wire Bits": 3999, - "Total Cells": 42243, + "Total Cells": 42389, "MUX": 11266, "XOR": 3492, - "OR": 5621, + "OR": 5695, "AND": 8419, - "NOT": 3121, + "NOT": 3193, "DFFs": [ "$_DFF_P_ 6976" ], @@ -1467,16 +1467,16 @@ "Average Path": 8, "Estimated LUTs": 37160, "Total Node": 11295, - "Wires": 46219, - "Wire Bits": 118261, + "Wires": 46405, + "Wire Bits": 117654, "Public Wires": 1513, "Public Wire Bits": 1513, - "Total Cells": 70962, + "Total Cells": 70238, "MUX": 22023, "XOR": 1594, - "OR": 17567, - "AND": 10886, - "NOT": 5545, + "OR": 17552, + "AND": 10572, + "NOT": 5150, "DFFs": [ "$_DFF_P_ 9256" ], @@ -1567,11 +1567,11 @@ "Wire Bits": 33013, "Public Wires": 4691, "Public Wire Bits": 4691, - "Total Cells": 21825, + "Total Cells": 21826, "MUX": 8305, "XOR": 1413, "OR": 1380, - "AND": 1131, + "AND": 1132, "NOT": 848, "DFFs": [ "$_DFF_P_ 3977" @@ -2171,15 +2171,15 @@ "Average Path": 3, "Estimated LUTs": 22982, "Total Node": 9499, - "Wires": 75193, - "Wire Bits": 81429, + "Wires": 75346, + "Wire Bits": 81806, "Public Wires": 1314, "Public Wire Bits": 1314, - "Total Cells": 57394, + "Total Cells": 57483, "MUX": 23987, "XOR": 3, - "OR": 3475, - "AND": 1527, + "OR": 3556, + "AND": 1535, "NOT": 730, "DFFs": [ "$_DFF_P_ 22236" @@ -4987,16 +4987,16 @@ "Average Path": 3, "Estimated LUTs": 26483, "Total Node": 11204, - "Wires": 83520, - "Wire Bits": 99654, + "Wires": 83717, + "Wire Bits": 100256, "Public Wires": 1897, "Public Wire Bits": 1897, - "Total Cells": 74399, + "Total Cells": 74621, "MUX": 36836, "XOR": 408, - "OR": 7218, - "AND": 4693, - "NOT": 1006, + "OR": 7327, + "AND": 4721, + "NOT": 1091, "DFFs": [ "$_DFF_P_ 19643" ], diff --git a/parmys/regression_test/benchmark/task/micro/synthesis_result.json b/parmys/regression_test/benchmark/task/micro/synthesis_result.json index a53cf006365..c479ea68818 100644 --- a/parmys/regression_test/benchmark/task/micro/synthesis_result.json +++ b/parmys/regression_test/benchmark/task/micro/synthesis_result.json @@ -530,14 +530,14 @@ "Average Path": 5, "Estimated LUTs": 714, "Total Node": 693, - "Wires": 1083, - "Wire Bits": 1395, + "Wires": 1086, + "Wire Bits": 1399, "Public Wires": 127, "Public Wire Bits": 127, - "Total Cells": 1206, + "Total Cells": 1210, "MUX": 538, "XOR": 386, - "AND": 228, + "AND": 232, "DFFs": [ "$_DFF_P_ 54" ] @@ -608,14 +608,14 @@ "Average Path": 5, "Estimated LUTs": 693, "Total Node": 693, - "Wires": 1083, - "Wire Bits": 1395, + "Wires": 1086, + "Wire Bits": 1399, "Public Wires": 127, "Public Wire Bits": 127, - "Total Cells": 1206, + "Total Cells": 1210, "MUX": 538, "XOR": 386, - "AND": 228, + "AND": 232, "DFFs": [ "$_DFF_P_ 54" ] @@ -3929,8 +3929,8 @@ "Average Path": 3, "Estimated LUTs": 53, "Total Node": 10, - "Wires": 45, - "Wire Bits": 128, + "Wires": 46, + "Wire Bits": 130, "Public Wires": 11, "Public Wire Bits": 11, "Total Cells": 61, @@ -3960,8 +3960,8 @@ "Average Path": 3, "Estimated LUTs": 37, "Total Node": 10, - "Wires": 45, - "Wire Bits": 128, + "Wires": 46, + "Wire Bits": 130, "Public Wires": 11, "Public Wire Bits": 11, "Total Cells": 61, @@ -3991,8 +3991,8 @@ "Average Path": 3, "Estimated LUTs": 37, "Total Node": 10, - "Wires": 45, - "Wire Bits": 128, + "Wires": 46, + "Wire Bits": 130, "Public Wires": 11, "Public Wire Bits": 11, "Total Cells": 61, @@ -4020,8 +4020,8 @@ "Average Path": 3, "Estimated LUTs": 10, "Total Node": 10, - "Wires": 45, - "Wire Bits": 128, + "Wires": 46, + "Wire Bits": 130, "Public Wires": 11, "Public Wire Bits": 11, "Total Cells": 61, @@ -4052,15 +4052,15 @@ "Average Path": 5, "Estimated LUTs": 7, "Total Node": 19, - "Wires": 55, - "Wire Bits": 62, + "Wires": 53, + "Wire Bits": 59, "Public Wires": 19, "Public Wire Bits": 19, - "Total Cells": 33, + "Total Cells": 26, "MUX": 4, - "OR": 3, - "AND": 4, - "NOT": 5, + "OR": 1, + "AND": 3, + "NOT": 1, "adder": 17 }, "micro/bm_DL_BCD_adder/k6_N10_40nm": { @@ -4085,16 +4085,16 @@ "Average Path": 4, "Estimated LUTs": 31, "Total Node": 27, - "Wires": 50, - "Wire Bits": 60, + "Wires": 49, + "Wire Bits": 61, "Public Wires": 19, "Public Wire Bits": 19, - "Total Cells": 48, + "Total Cells": 42, "MUX": 18, "XOR": 15, - "OR": 3, - "AND": 6, - "NOT": 6 + "OR": 1, + "AND": 5, + "NOT": 3 }, "micro/bm_DL_BCD_adder/k6_N10_mem32K_40nm": { "test_name": "micro/bm_DL_BCD_adder/k6_N10_mem32K_40nm", @@ -4118,16 +4118,16 @@ "Average Path": 4, "Estimated LUTs": 31, "Total Node": 27, - "Wires": 50, - "Wire Bits": 60, + "Wires": 49, + "Wire Bits": 61, "Public Wires": 19, "Public Wire Bits": 19, - "Total Cells": 48, + "Total Cells": 42, "MUX": 18, "XOR": 15, - "OR": 3, - "AND": 6, - "NOT": 6 + "OR": 1, + "AND": 5, + "NOT": 3 }, "micro/bm_DL_BCD_adder/no_arch": { "test_name": "micro/bm_DL_BCD_adder/no_arch", @@ -4149,16 +4149,16 @@ "Average Path": 4, "Estimated LUTs": 27, "Total Node": 27, - "Wires": 50, - "Wire Bits": 60, + "Wires": 49, + "Wire Bits": 61, "Public Wires": 19, "Public Wire Bits": 19, - "Total Cells": 48, + "Total Cells": 42, "MUX": 18, "XOR": 15, - "OR": 3, - "AND": 6, - "NOT": 6 + "OR": 1, + "AND": 5, + "NOT": 3 }, "micro/bm_DL_behavioural_full_adder/k6_frac_N10_frac_chain_mem32K_40nm": { "test_name": "micro/bm_DL_behavioural_full_adder/k6_frac_N10_frac_chain_mem32K_40nm", @@ -5133,14 +5133,14 @@ "Average Path": 3, "Estimated LUTs": 644, "Total Node": 218, - "Wires": 1459, - "Wire Bits": 1956, + "Wires": 1458, + "Wire Bits": 1955, "Public Wires": 814, "Public Wire Bits": 814, - "Total Cells": 1387, + "Total Cells": 1386, "XNOR": 63, "XOR": 191, - "OR": 257, + "OR": 256, "AND": 310, "NOT": 133, "DFFs": [ @@ -5170,15 +5170,15 @@ "Average Path": 3, "Estimated LUTs": 623, "Total Node": 307, - "Wires": 1633, - "Wire Bits": 2225, + "Wires": 1600, + "Wire Bits": 2254, "Public Wires": 751, "Public Wire Bits": 751, - "Total Cells": 1748, + "Total Cells": 1746, "MUX": 267, "XNOR": 63, - "XOR": 378, - "OR": 259, + "XOR": 377, + "OR": 258, "AND": 311, "NOT": 135, "DFFs": [ @@ -5207,15 +5207,15 @@ "Average Path": 3, "Estimated LUTs": 623, "Total Node": 307, - "Wires": 1633, - "Wire Bits": 2225, + "Wires": 1600, + "Wire Bits": 2254, "Public Wires": 751, "Public Wire Bits": 751, - "Total Cells": 1748, + "Total Cells": 1746, "MUX": 267, "XNOR": 63, - "XOR": 378, - "OR": 259, + "XOR": 377, + "OR": 258, "AND": 311, "NOT": 135, "DFFs": [ @@ -5242,15 +5242,15 @@ "Average Path": 3, "Estimated LUTs": 307, "Total Node": 307, - "Wires": 1633, - "Wire Bits": 2225, + "Wires": 1600, + "Wire Bits": 2254, "Public Wires": 751, "Public Wire Bits": 751, - "Total Cells": 1748, + "Total Cells": 1746, "MUX": 267, "XNOR": 63, - "XOR": 378, - "OR": 259, + "XOR": 377, + "OR": 258, "AND": 311, "NOT": 135, "DFFs": [ @@ -5281,16 +5281,16 @@ "Average Path": 3, "Estimated LUTs": 201, "Total Node": 94, - "Wires": 354, - "Wire Bits": 816, + "Wires": 360, + "Wire Bits": 829, "Public Wires": 105, "Public Wire Bits": 105, - "Total Cells": 470, + "Total Cells": 471, "MUX": 66, "XOR": 8, - "OR": 158, - "AND": 118, - "NOT": 47, + "OR": 159, + "AND": 119, + "NOT": 46, "DFFs": [ "$_DFF_P_ 25" ], @@ -5319,16 +5319,16 @@ "Average Path": 3, "Estimated LUTs": 404, "Total Node": 308, - "Wires": 596, - "Wire Bits": 1160, + "Wires": 601, + "Wire Bits": 1169, "Public Wires": 89, "Public Wire Bits": 89, - "Total Cells": 905, + "Total Cells": 906, "MUX": 295, "XOR": 178, - "OR": 160, - "AND": 198, - "NOT": 49, + "OR": 161, + "AND": 199, + "NOT": 48, "DFFs": [ "$_DFF_P_ 25" ] @@ -5356,16 +5356,16 @@ "Average Path": 3, "Estimated LUTs": 221, "Total Node": 126, - "Wires": 390, - "Wire Bits": 884, + "Wires": 395, + "Wire Bits": 899, "Public Wires": 89, "Public Wire Bits": 89, - "Total Cells": 578, + "Total Cells": 579, "MUX": 150, "XOR": 74, - "OR": 160, - "AND": 119, - "NOT": 49, + "OR": 161, + "AND": 120, + "NOT": 48, "DFFs": [ "$_DFF_P_ 25" ], @@ -5391,16 +5391,16 @@ "Average Path": 3, "Estimated LUTs": 308, "Total Node": 308, - "Wires": 596, - "Wire Bits": 1160, + "Wires": 601, + "Wire Bits": 1169, "Public Wires": 89, "Public Wire Bits": 89, - "Total Cells": 905, + "Total Cells": 906, "MUX": 295, "XOR": 178, - "OR": 160, - "AND": 198, - "NOT": 49, + "OR": 161, + "AND": 199, + "NOT": 48, "DFFs": [ "$_DFF_P_ 25" ] @@ -5580,13 +5580,13 @@ "Average Path": 4, "Estimated LUTs": 14, "Total Node": 12, - "Wires": 37, - "Wire Bits": 42, + "Wires": 36, + "Wire Bits": 41, "Public Wires": 13, "Public Wire Bits": 13, - "Total Cells": 30, + "Total Cells": 29, "MUX": 6, - "OR": 6, + "OR": 5, "AND": 3, "NOT": 6, "DFFs": [ @@ -5618,13 +5618,13 @@ "Average Path": 4, "Estimated LUTs": 14, "Total Node": 12, - "Wires": 37, - "Wire Bits": 42, + "Wires": 36, + "Wire Bits": 41, "Public Wires": 13, "Public Wire Bits": 13, - "Total Cells": 30, + "Total Cells": 29, "MUX": 6, - "OR": 6, + "OR": 5, "AND": 3, "NOT": 6, "DFFs": [ @@ -5656,13 +5656,13 @@ "Average Path": 4, "Estimated LUTs": 14, "Total Node": 12, - "Wires": 37, - "Wire Bits": 42, + "Wires": 36, + "Wire Bits": 41, "Public Wires": 13, "Public Wire Bits": 13, - "Total Cells": 30, + "Total Cells": 29, "MUX": 6, - "OR": 6, + "OR": 5, "AND": 3, "NOT": 6, "DFFs": [ @@ -5692,13 +5692,13 @@ "Average Path": 4, "Estimated LUTs": 12, "Total Node": 12, - "Wires": 37, - "Wire Bits": 42, + "Wires": 36, + "Wire Bits": 41, "Public Wires": 13, "Public Wire Bits": 13, - "Total Cells": 30, + "Total Cells": 29, "MUX": 6, - "OR": 6, + "OR": 5, "AND": 3, "NOT": 6, "DFFs": [ @@ -5895,7 +5895,7 @@ "Estimated LUTs": 407, "Total Node": 264, "Wires": 739, - "Wire Bits": 1076, + "Wire Bits": 1045, "Public Wires": 322, "Public Wire Bits": 322, "Total Cells": 943, @@ -5923,7 +5923,7 @@ "Estimated LUTs": 407, "Total Node": 264, "Wires": 739, - "Wire Bits": 1076, + "Wire Bits": 1045, "Public Wires": 322, "Public Wire Bits": 322, "Total Cells": 943, @@ -5949,7 +5949,7 @@ "Estimated LUTs": 264, "Total Node": 264, "Wires": 739, - "Wire Bits": 1076, + "Wire Bits": 1045, "Public Wires": 322, "Public Wire Bits": 322, "Total Cells": 943, @@ -6222,14 +6222,14 @@ "Average Path": 6, "Estimated LUTs": 1086, "Total Node": 1076, - "Wires": 1786, - "Wire Bits": 2273, + "Wires": 1787, + "Wire Bits": 2274, "Public Wires": 155, "Public Wire Bits": 155, - "Total Cells": 2039, + "Total Cells": 2040, "MUX": 949, "XOR": 679, - "AND": 365, + "AND": 366, "DFFs": [ "$_DFF_P_ 46" ] @@ -6290,14 +6290,14 @@ "Average Path": 6, "Estimated LUTs": 1076, "Total Node": 1076, - "Wires": 1786, - "Wire Bits": 2273, + "Wires": 1787, + "Wire Bits": 2274, "Public Wires": 155, "Public Wire Bits": 155, - "Total Cells": 2039, + "Total Cells": 2040, "MUX": 949, "XOR": 679, - "AND": 365, + "AND": 366, "DFFs": [ "$_DFF_P_ 46" ] @@ -6359,14 +6359,14 @@ "Average Path": 3, "Estimated LUTs": 334, "Total Node": 324, - "Wires": 627, - "Wire Bits": 768, + "Wires": 625, + "Wire Bits": 766, "Public Wires": 110, "Public Wire Bits": 110, - "Total Cells": 665, + "Total Cells": 663, "MUX": 304, "XOR": 221, - "AND": 94, + "AND": 92, "DFFs": [ "$_DFF_P_ 46" ] @@ -6427,14 +6427,14 @@ "Average Path": 3, "Estimated LUTs": 324, "Total Node": 324, - "Wires": 627, - "Wire Bits": 768, + "Wires": 625, + "Wire Bits": 766, "Public Wires": 110, "Public Wire Bits": 110, - "Total Cells": 665, + "Total Cells": 663, "MUX": 304, "XOR": 221, - "AND": 94, + "AND": 92, "DFFs": [ "$_DFF_P_ 46" ] @@ -6497,13 +6497,13 @@ "Estimated LUTs": 710, "Total Node": 700, "Wires": 1284, - "Wire Bits": 1601, + "Wire Bits": 1602, "Public Wires": 269, "Public Wire Bits": 269, - "Total Cells": 1317, + "Total Cells": 1319, "MUX": 598, "XOR": 425, - "AND": 241, + "AND": 243, "DFFs": [ "$_DFF_P_ 53" ] @@ -6565,13 +6565,13 @@ "Estimated LUTs": 700, "Total Node": 700, "Wires": 1284, - "Wire Bits": 1601, + "Wire Bits": 1602, "Public Wires": 269, "Public Wire Bits": 269, - "Total Cells": 1317, + "Total Cells": 1319, "MUX": 598, "XOR": 425, - "AND": 241, + "AND": 243, "DFFs": [ "$_DFF_P_ 53" ] @@ -6770,14 +6770,14 @@ "Average Path": 5, "Estimated LUTs": 563, "Total Node": 557, - "Wires": 931, - "Wire Bits": 1164, + "Wires": 932, + "Wire Bits": 1165, "Public Wires": 110, "Public Wire Bits": 110, - "Total Cells": 1019, + "Total Cells": 1020, "MUX": 468, "XOR": 339, - "AND": 184, + "AND": 185, "DFFs": [ "$_DFF_P_ 28" ] @@ -6838,14 +6838,14 @@ "Average Path": 5, "Estimated LUTs": 557, "Total Node": 557, - "Wires": 931, - "Wire Bits": 1164, + "Wires": 932, + "Wire Bits": 1165, "Public Wires": 110, "Public Wire Bits": 110, - "Total Cells": 1019, + "Total Cells": 1020, "MUX": 468, "XOR": 339, - "AND": 184, + "AND": 185, "DFFs": [ "$_DFF_P_ 28" ] @@ -7206,8 +7206,8 @@ "Average Path": 3, "Estimated LUTs": 83, "Total Node": 24, - "Wires": 78, - "Wire Bits": 202, + "Wires": 77, + "Wire Bits": 200, "Public Wires": 32, "Public Wire Bits": 32, "Total Cells": 82, @@ -7240,8 +7240,8 @@ "Average Path": 3, "Estimated LUTs": 65, "Total Node": 24, - "Wires": 78, - "Wire Bits": 202, + "Wires": 77, + "Wire Bits": 200, "Public Wires": 32, "Public Wire Bits": 32, "Total Cells": 82, @@ -7274,8 +7274,8 @@ "Average Path": 3, "Estimated LUTs": 65, "Total Node": 24, - "Wires": 78, - "Wire Bits": 202, + "Wires": 77, + "Wire Bits": 200, "Public Wires": 32, "Public Wire Bits": 32, "Total Cells": 82, @@ -7306,8 +7306,8 @@ "Average Path": 3, "Estimated LUTs": 24, "Total Node": 24, - "Wires": 78, - "Wire Bits": 202, + "Wires": 77, + "Wire Bits": 200, "Public Wires": 32, "Public Wire Bits": 32, "Total Cells": 82, @@ -7340,8 +7340,8 @@ "Average Path": 3, "Estimated LUTs": 43, "Total Node": 13, - "Wires": 44, - "Wire Bits": 90, + "Wires": 45, + "Wire Bits": 92, "Public Wires": 22, "Public Wire Bits": 22, "Total Cells": 47, @@ -7374,8 +7374,8 @@ "Average Path": 3, "Estimated LUTs": 31, "Total Node": 13, - "Wires": 44, - "Wire Bits": 90, + "Wires": 45, + "Wire Bits": 92, "Public Wires": 22, "Public Wire Bits": 22, "Total Cells": 47, @@ -7408,8 +7408,8 @@ "Average Path": 3, "Estimated LUTs": 31, "Total Node": 13, - "Wires": 44, - "Wire Bits": 90, + "Wires": 45, + "Wire Bits": 92, "Public Wires": 22, "Public Wire Bits": 22, "Total Cells": 47, @@ -7440,8 +7440,8 @@ "Average Path": 3, "Estimated LUTs": 13, "Total Node": 13, - "Wires": 44, - "Wire Bits": 90, + "Wires": 45, + "Wire Bits": 92, "Public Wires": 22, "Public Wire Bits": 22, "Total Cells": 47, @@ -7474,8 +7474,8 @@ "Average Path": 4, "Estimated LUTs": 76, "Total Node": 17, - "Wires": 52, - "Wire Bits": 176, + "Wires": 53, + "Wire Bits": 178, "Public Wires": 11, "Public Wire Bits": 11, "Total Cells": 74, @@ -7508,8 +7508,8 @@ "Average Path": 4, "Estimated LUTs": 58, "Total Node": 17, - "Wires": 52, - "Wire Bits": 176, + "Wires": 53, + "Wire Bits": 178, "Public Wires": 11, "Public Wire Bits": 11, "Total Cells": 74, @@ -7542,8 +7542,8 @@ "Average Path": 4, "Estimated LUTs": 58, "Total Node": 17, - "Wires": 52, - "Wire Bits": 176, + "Wires": 53, + "Wire Bits": 178, "Public Wires": 11, "Public Wire Bits": 11, "Total Cells": 74, @@ -7574,8 +7574,8 @@ "Average Path": 4, "Estimated LUTs": 17, "Total Node": 17, - "Wires": 52, - "Wire Bits": 176, + "Wires": 53, + "Wire Bits": 178, "Public Wires": 11, "Public Wire Bits": 11, "Total Cells": 74, @@ -8032,14 +8032,14 @@ "Average Path": 4, "Estimated LUTs": 18, "Total Node": 18, - "Wires": 26, - "Wire Bits": 28, + "Wires": 24, + "Wire Bits": 26, "Public Wires": 16, "Public Wire Bits": 16, - "Total Cells": 20, + "Total Cells": 18, "MUX": 2, "XOR": 4, - "AND": 14 + "AND": 12 }, "micro/multiply_hard_block/k6_N10_mem32K_40nm": { "test_name": "micro/multiply_hard_block/k6_N10_mem32K_40nm", @@ -8058,14 +8058,14 @@ "Average Path": 4, "Estimated LUTs": 18, "Total Node": 18, - "Wires": 26, - "Wire Bits": 28, + "Wires": 24, + "Wire Bits": 26, "Public Wires": 16, "Public Wire Bits": 16, - "Total Cells": 20, + "Total Cells": 18, "MUX": 2, "XOR": 4, - "AND": 14 + "AND": 12 }, "micro/multiply_hard_block/no_arch": { "test_name": "micro/multiply_hard_block/no_arch", @@ -8076,14 +8076,14 @@ "Average Path": 4, "Estimated LUTs": 18, "Total Node": 18, - "Wires": 26, - "Wire Bits": 28, + "Wires": 24, + "Wire Bits": 26, "Public Wires": 16, "Public Wire Bits": 16, - "Total Cells": 20, + "Total Cells": 18, "MUX": 2, "XOR": 4, - "AND": 14 + "AND": 12 }, "micro/parameter_2/k6_frac_N10_frac_chain_mem32K_40nm": { "test_name": "micro/parameter_2/k6_frac_N10_frac_chain_mem32K_40nm", diff --git a/parmys/regression_test/benchmark/task/mixing_optimization/config_file_half/synthesis_result.json b/parmys/regression_test/benchmark/task/mixing_optimization/config_file_half/synthesis_result.json index 296cbd53d9f..4952ffb3bbf 100644 --- a/parmys/regression_test/benchmark/task/mixing_optimization/config_file_half/synthesis_result.json +++ b/parmys/regression_test/benchmark/task/mixing_optimization/config_file_half/synthesis_result.json @@ -28,14 +28,14 @@ "Average Path": 4, "Estimated LUTs": 384, "Total Node": 354, - "Wires": 675, - "Wire Bits": 820, + "Wires": 677, + "Wire Bits": 822, "Public Wires": 127, "Public Wire Bits": 127, - "Total Cells": 680, + "Total Cells": 682, "MUX": 269, "XOR": 194, - "AND": 160, + "AND": 162, "DFFs": [ "$_DFF_P_ 55" ], @@ -72,14 +72,14 @@ "Average Path": 5, "Estimated LUTs": 714, "Total Node": 693, - "Wires": 1083, - "Wire Bits": 1395, + "Wires": 1086, + "Wire Bits": 1399, "Public Wires": 127, "Public Wire Bits": 127, - "Total Cells": 1206, + "Total Cells": 1210, "MUX": 538, "XOR": 386, - "AND": 228, + "AND": 232, "DFFs": [ "$_DFF_P_ 54" ] @@ -218,14 +218,14 @@ "Average Path": 6, "Estimated LUTs": 1086, "Total Node": 1076, - "Wires": 1786, - "Wire Bits": 2273, + "Wires": 1787, + "Wire Bits": 2274, "Public Wires": 155, "Public Wire Bits": 155, - "Total Cells": 2039, + "Total Cells": 2040, "MUX": 949, "XOR": 679, - "AND": 365, + "AND": 366, "DFFs": [ "$_DFF_P_ 46" ] @@ -253,14 +253,14 @@ "Average Path": 3, "Estimated LUTs": 253, "Total Node": 286, - "Wires": 562, - "Wire Bits": 650, + "Wires": 560, + "Wire Bits": 648, "Public Wires": 110, "Public Wire Bits": 110, - "Total Cells": 512, + "Total Cells": 510, "MUX": 190, "XOR": 135, - "AND": 91, + "AND": 89, "DFFs": [ "$_DFF_P_ 46" ], @@ -288,14 +288,14 @@ "Average Path": 3, "Estimated LUTs": 334, "Total Node": 324, - "Wires": 627, - "Wire Bits": 768, + "Wires": 625, + "Wire Bits": 766, "Public Wires": 110, "Public Wire Bits": 110, - "Total Cells": 665, + "Total Cells": 663, "MUX": 304, "XOR": 221, - "AND": 94, + "AND": 92, "DFFs": [ "$_DFF_P_ 46" ] @@ -363,13 +363,13 @@ "Estimated LUTs": 710, "Total Node": 700, "Wires": 1284, - "Wire Bits": 1601, + "Wire Bits": 1602, "Public Wires": 269, "Public Wire Bits": 269, - "Total Cells": 1317, + "Total Cells": 1319, "MUX": 598, "XOR": 425, - "AND": 241, + "AND": 243, "DFFs": [ "$_DFF_P_ 53" ] @@ -489,14 +489,14 @@ "Average Path": 4, "Estimated LUTs": 18, "Total Node": 18, - "Wires": 26, - "Wire Bits": 28, + "Wires": 24, + "Wire Bits": 26, "Public Wires": 16, "Public Wire Bits": 16, - "Total Cells": 20, + "Total Cells": 18, "MUX": 2, "XOR": 4, - "AND": 14 + "AND": 12 }, "config_file_half/twobits_arithmetic_multiply/k6_frac_N10_frac_chain_mem32K_40nm": { "test_name": "config_file_half/twobits_arithmetic_multiply/k6_frac_N10_frac_chain_mem32K_40nm", @@ -596,14 +596,14 @@ "Average Path": 4, "Estimated LUTs": 378, "Total Node": 354, - "Wires": 675, - "Wire Bits": 820, + "Wires": 677, + "Wire Bits": 822, "Public Wires": 127, "Public Wire Bits": 127, - "Total Cells": 680, + "Total Cells": 682, "MUX": 269, "XOR": 194, - "AND": 160, + "AND": 162, "DFFs": [ "$_DFF_P_ 55" ], @@ -638,14 +638,14 @@ "Average Path": 4, "Estimated LUTs": 373, "Total Node": 354, - "Wires": 675, - "Wire Bits": 820, + "Wires": 677, + "Wire Bits": 822, "Public Wires": 127, "Public Wire Bits": 127, - "Total Cells": 680, + "Total Cells": 682, "MUX": 269, "XOR": 194, - "AND": 160, + "AND": 162, "DFFs": [ "$_DFF_P_ 55" ], @@ -813,14 +813,14 @@ "Average Path": 3, "Estimated LUTs": 335, "Total Node": 324, - "Wires": 627, - "Wire Bits": 768, + "Wires": 625, + "Wire Bits": 766, "Public Wires": 110, "Public Wire Bits": 110, - "Total Cells": 665, + "Total Cells": 663, "MUX": 304, "XOR": 221, - "AND": 94, + "AND": 92, "DFFs": [ "$_DFF_P_ 46" ] @@ -844,14 +844,14 @@ "Average Path": 3, "Estimated LUTs": 334, "Total Node": 324, - "Wires": 627, - "Wire Bits": 768, + "Wires": 625, + "Wire Bits": 766, "Public Wires": 110, "Public Wire Bits": 110, - "Total Cells": 665, + "Total Cells": 663, "MUX": 304, "XOR": 221, - "AND": 94, + "AND": 92, "DFFs": [ "$_DFF_P_ 46" ] diff --git a/parmys/regression_test/benchmark/task/mixing_optimization/mults_auto_full/synthesis_result.json b/parmys/regression_test/benchmark/task/mixing_optimization/mults_auto_full/synthesis_result.json index 92debe8a3bd..a791cd2c2c4 100644 --- a/parmys/regression_test/benchmark/task/mixing_optimization/mults_auto_full/synthesis_result.json +++ b/parmys/regression_test/benchmark/task/mixing_optimization/mults_auto_full/synthesis_result.json @@ -67,14 +67,14 @@ "Average Path": 5, "Estimated LUTs": 714, "Total Node": 693, - "Wires": 1083, - "Wire Bits": 1395, + "Wires": 1086, + "Wire Bits": 1399, "Public Wires": 127, "Public Wire Bits": 127, - "Total Cells": 1206, + "Total Cells": 1210, "MUX": 538, "XOR": 386, - "AND": 228, + "AND": 232, "DFFs": [ "$_DFF_P_ 54" ] @@ -203,14 +203,14 @@ "Average Path": 6, "Estimated LUTs": 1086, "Total Node": 1076, - "Wires": 1786, - "Wire Bits": 2273, + "Wires": 1787, + "Wire Bits": 2274, "Public Wires": 155, "Public Wire Bits": 155, - "Total Cells": 2039, + "Total Cells": 2040, "MUX": 949, "XOR": 679, - "AND": 365, + "AND": 366, "DFFs": [ "$_DFF_P_ 46" ] @@ -272,14 +272,14 @@ "Average Path": 3, "Estimated LUTs": 334, "Total Node": 324, - "Wires": 627, - "Wire Bits": 768, + "Wires": 625, + "Wire Bits": 766, "Public Wires": 110, "Public Wire Bits": 110, - "Total Cells": 665, + "Total Cells": 663, "MUX": 304, "XOR": 221, - "AND": 94, + "AND": 92, "DFFs": [ "$_DFF_P_ 46" ] @@ -342,13 +342,13 @@ "Estimated LUTs": 710, "Total Node": 700, "Wires": 1284, - "Wire Bits": 1601, + "Wire Bits": 1602, "Public Wires": 269, "Public Wire Bits": 269, - "Total Cells": 1317, + "Total Cells": 1319, "MUX": 598, "XOR": 425, - "AND": 241, + "AND": 243, "DFFs": [ "$_DFF_P_ 53" ] @@ -459,14 +459,14 @@ "Average Path": 4, "Estimated LUTs": 18, "Total Node": 18, - "Wires": 26, - "Wire Bits": 28, + "Wires": 24, + "Wire Bits": 26, "Public Wires": 16, "Public Wire Bits": 16, - "Total Cells": 20, + "Total Cells": 18, "MUX": 2, "XOR": 4, - "AND": 14 + "AND": 12 }, "mults_auto_full/twobits_arithmetic_multiply/k6_frac_N10_frac_chain_mem32K_40nm": { "test_name": "mults_auto_full/twobits_arithmetic_multiply/k6_frac_N10_frac_chain_mem32K_40nm", @@ -953,14 +953,14 @@ "Average Path": 4, "Estimated LUTs": 18, "Total Node": 18, - "Wires": 26, - "Wire Bits": 28, + "Wires": 24, + "Wire Bits": 26, "Public Wires": 16, "Public Wire Bits": 16, - "Total Cells": 20, + "Total Cells": 18, "MUX": 2, "XOR": 4, - "AND": 14 + "AND": 12 }, "mults_auto_full/multiply_hard_block/k6_N10_mem32K_40nm": { "test_name": "mults_auto_full/multiply_hard_block/k6_N10_mem32K_40nm", @@ -976,14 +976,14 @@ "Average Path": 4, "Estimated LUTs": 18, "Total Node": 18, - "Wires": 26, - "Wire Bits": 28, + "Wires": 24, + "Wire Bits": 26, "Public Wires": 16, "Public Wire Bits": 16, - "Total Cells": 20, + "Total Cells": 18, "MUX": 2, "XOR": 4, - "AND": 14 + "AND": 12 }, "mults_auto_full/twobits_arithmetic_multiply/k6_frac_N10_mem32K_40nm": { "test_name": "mults_auto_full/twobits_arithmetic_multiply/k6_frac_N10_mem32K_40nm", diff --git a/parmys/regression_test/benchmark/task/mixing_optimization/mults_auto_half/synthesis_result.json b/parmys/regression_test/benchmark/task/mixing_optimization/mults_auto_half/synthesis_result.json index e203b322e51..29265c90b72 100644 --- a/parmys/regression_test/benchmark/task/mixing_optimization/mults_auto_half/synthesis_result.json +++ b/parmys/regression_test/benchmark/task/mixing_optimization/mults_auto_half/synthesis_result.json @@ -28,14 +28,14 @@ "Average Path": 4, "Estimated LUTs": 717, "Total Node": 687, - "Wires": 788, - "Wire Bits": 948, + "Wires": 790, + "Wire Bits": 950, "Public Wires": 127, "Public Wire Bits": 127, - "Total Cells": 680, + "Total Cells": 682, "MUX": 269, "XOR": 194, - "AND": 160, + "AND": 162, "DFFs": [ "$_DFF_P_ 55" ], @@ -69,14 +69,14 @@ "Average Path": 5, "Estimated LUTs": 714, "Total Node": 693, - "Wires": 1083, - "Wire Bits": 1395, + "Wires": 1086, + "Wire Bits": 1399, "Public Wires": 127, "Public Wire Bits": 127, - "Total Cells": 1206, + "Total Cells": 1210, "MUX": 538, "XOR": 386, - "AND": 228, + "AND": 232, "DFFs": [ "$_DFF_P_ 54" ] @@ -211,14 +211,14 @@ "Average Path": 6, "Estimated LUTs": 1086, "Total Node": 1076, - "Wires": 1786, - "Wire Bits": 2273, + "Wires": 1787, + "Wire Bits": 2274, "Public Wires": 155, "Public Wire Bits": 155, - "Total Cells": 2039, + "Total Cells": 2040, "MUX": 949, "XOR": 679, - "AND": 365, + "AND": 366, "DFFs": [ "$_DFF_P_ 46" ] @@ -246,14 +246,14 @@ "Average Path": 3, "Estimated LUTs": 480, "Total Node": 513, - "Wires": 562, - "Wire Bits": 668, + "Wires": 560, + "Wire Bits": 666, "Public Wires": 110, "Public Wire Bits": 110, - "Total Cells": 512, + "Total Cells": 510, "MUX": 190, "XOR": 135, - "AND": 91, + "AND": 89, "DFFs": [ "$_DFF_P_ 46" ], @@ -281,14 +281,14 @@ "Average Path": 3, "Estimated LUTs": 334, "Total Node": 324, - "Wires": 627, - "Wire Bits": 768, + "Wires": 625, + "Wire Bits": 766, "Public Wires": 110, "Public Wire Bits": 110, - "Total Cells": 665, + "Total Cells": 663, "MUX": 304, "XOR": 221, - "AND": 94, + "AND": 92, "DFFs": [ "$_DFF_P_ 46" ] @@ -354,13 +354,13 @@ "Estimated LUTs": 710, "Total Node": 700, "Wires": 1284, - "Wire Bits": 1601, + "Wire Bits": 1602, "Public Wires": 269, "Public Wire Bits": 269, - "Total Cells": 1317, + "Total Cells": 1319, "MUX": 598, "XOR": 425, - "AND": 241, + "AND": 243, "DFFs": [ "$_DFF_P_ 53" ] @@ -474,14 +474,14 @@ "Average Path": 4, "Estimated LUTs": 18, "Total Node": 18, - "Wires": 26, - "Wire Bits": 28, + "Wires": 24, + "Wire Bits": 26, "Public Wires": 16, "Public Wire Bits": 16, - "Total Cells": 20, + "Total Cells": 18, "MUX": 2, "XOR": 4, - "AND": 14 + "AND": 12 }, "mults_auto_half/twobits_arithmetic_multiply/k6_frac_N10_frac_chain_mem32K_40nm": { "test_name": "mults_auto_half/twobits_arithmetic_multiply/k6_frac_N10_frac_chain_mem32K_40nm", @@ -582,14 +582,14 @@ "Average Path": 4, "Estimated LUTs": 711, "Total Node": 687, - "Wires": 788, - "Wire Bits": 948, + "Wires": 790, + "Wire Bits": 950, "Public Wires": 127, "Public Wire Bits": 127, - "Total Cells": 680, + "Total Cells": 682, "MUX": 269, "XOR": 194, - "AND": 160, + "AND": 162, "DFFs": [ "$_DFF_P_ 55" ], @@ -621,14 +621,14 @@ "Average Path": 4, "Estimated LUTs": 706, "Total Node": 687, - "Wires": 788, - "Wire Bits": 948, + "Wires": 790, + "Wire Bits": 950, "Public Wires": 127, "Public Wire Bits": 127, - "Total Cells": 680, + "Total Cells": 682, "MUX": 269, "XOR": 194, - "AND": 160, + "AND": 162, "DFFs": [ "$_DFF_P_ 55" ], @@ -785,14 +785,14 @@ "Average Path": 3, "Estimated LUTs": 562, "Total Node": 551, - "Wires": 627, - "Wire Bits": 771, + "Wires": 625, + "Wire Bits": 769, "Public Wires": 110, "Public Wire Bits": 110, - "Total Cells": 665, + "Total Cells": 663, "MUX": 304, "XOR": 221, - "AND": 94, + "AND": 92, "DFFs": [ "$_DFF_P_ 46" ] @@ -816,14 +816,14 @@ "Average Path": 3, "Estimated LUTs": 561, "Total Node": 551, - "Wires": 627, - "Wire Bits": 771, + "Wires": 625, + "Wire Bits": 769, "Public Wires": 110, "Public Wire Bits": 110, - "Total Cells": 665, + "Total Cells": 663, "MUX": 304, "XOR": 221, - "AND": 94, + "AND": 92, "DFFs": [ "$_DFF_P_ 46" ] @@ -974,14 +974,14 @@ "Average Path": 4, "Estimated LUTs": 18, "Total Node": 18, - "Wires": 26, - "Wire Bits": 28, + "Wires": 24, + "Wire Bits": 26, "Public Wires": 16, "Public Wire Bits": 16, - "Total Cells": 20, + "Total Cells": 18, "MUX": 2, "XOR": 4, - "AND": 14 + "AND": 12 }, "mults_auto_half/multiply_hard_block/k6_N10_mem32K_40nm": { "test_name": "mults_auto_half/multiply_hard_block/k6_N10_mem32K_40nm", @@ -997,14 +997,14 @@ "Average Path": 4, "Estimated LUTs": 18, "Total Node": 18, - "Wires": 26, - "Wire Bits": 28, + "Wires": 24, + "Wire Bits": 26, "Public Wires": 16, "Public Wire Bits": 16, - "Total Cells": 20, + "Total Cells": 18, "MUX": 2, "XOR": 4, - "AND": 14 + "AND": 12 }, "mults_auto_half/twobits_arithmetic_multiply/k6_frac_N10_mem32K_40nm": { "test_name": "mults_auto_half/twobits_arithmetic_multiply/k6_frac_N10_mem32K_40nm", diff --git a/parmys/regression_test/benchmark/task/mixing_optimization/mults_auto_none/synthesis_result.json b/parmys/regression_test/benchmark/task/mixing_optimization/mults_auto_none/synthesis_result.json index a55448e2339..cbe8da15518 100644 --- a/parmys/regression_test/benchmark/task/mixing_optimization/mults_auto_none/synthesis_result.json +++ b/parmys/regression_test/benchmark/task/mixing_optimization/mults_auto_none/synthesis_result.json @@ -27,14 +27,14 @@ "Average Path": 5, "Estimated LUTs": 1394, "Total Node": 1362, - "Wires": 1083, - "Wire Bits": 1398, + "Wires": 1086, + "Wire Bits": 1402, "Public Wires": 127, "Public Wire Bits": 127, - "Total Cells": 1206, + "Total Cells": 1210, "MUX": 538, "XOR": 386, - "AND": 228, + "AND": 232, "DFFs": [ "$_DFF_P_ 54" ] @@ -67,14 +67,14 @@ "Average Path": 5, "Estimated LUTs": 714, "Total Node": 693, - "Wires": 1083, - "Wire Bits": 1395, + "Wires": 1086, + "Wire Bits": 1399, "Public Wires": 127, "Public Wire Bits": 127, - "Total Cells": 1206, + "Total Cells": 1210, "MUX": 538, "XOR": 386, - "AND": 228, + "AND": 232, "DFFs": [ "$_DFF_P_ 54" ] @@ -170,14 +170,14 @@ "Average Path": 6, "Estimated LUTs": 1860, "Total Node": 1921, - "Wires": 1672, - "Wire Bits": 2096, + "Wires": 1674, + "Wire Bits": 2098, "Public Wires": 155, "Public Wire Bits": 155, - "Total Cells": 1785, + "Total Cells": 1786, "MUX": 760, "XOR": 540, - "AND": 361, + "AND": 362, "DFFs": [ "$_DFF_P_ 46" ], @@ -205,14 +205,14 @@ "Average Path": 6, "Estimated LUTs": 1086, "Total Node": 1076, - "Wires": 1786, - "Wire Bits": 2273, + "Wires": 1787, + "Wire Bits": 2274, "Public Wires": 155, "Public Wire Bits": 155, - "Total Cells": 2039, + "Total Cells": 2040, "MUX": 949, "XOR": 679, - "AND": 365, + "AND": 366, "DFFs": [ "$_DFF_P_ 46" ] @@ -240,14 +240,14 @@ "Average Path": 3, "Estimated LUTs": 480, "Total Node": 513, - "Wires": 562, - "Wire Bits": 668, + "Wires": 560, + "Wire Bits": 666, "Public Wires": 110, "Public Wire Bits": 110, - "Total Cells": 512, + "Total Cells": 510, "MUX": 190, "XOR": 135, - "AND": 91, + "AND": 89, "DFFs": [ "$_DFF_P_ 46" ], @@ -275,14 +275,14 @@ "Average Path": 3, "Estimated LUTs": 334, "Total Node": 324, - "Wires": 627, - "Wire Bits": 768, + "Wires": 625, + "Wire Bits": 766, "Public Wires": 110, "Public Wire Bits": 110, - "Total Cells": 665, + "Total Cells": 663, "MUX": 304, "XOR": 221, - "AND": 94, + "AND": 92, "DFFs": [ "$_DFF_P_ 46" ] @@ -310,8 +310,8 @@ "Average Path": 4, "Estimated LUTs": 1255, "Total Node": 1274, - "Wires": 1230, - "Wire Bits": 1516, + "Wires": 1229, + "Wire Bits": 1515, "Public Wires": 269, "Public Wire Bits": 269, "Total Cells": 1191, @@ -346,13 +346,13 @@ "Estimated LUTs": 710, "Total Node": 700, "Wires": 1284, - "Wire Bits": 1601, + "Wire Bits": 1602, "Public Wires": 269, "Public Wire Bits": 269, - "Total Cells": 1317, + "Total Cells": 1319, "MUX": 598, "XOR": 425, - "AND": 241, + "AND": 243, "DFFs": [ "$_DFF_P_ 53" ] @@ -464,14 +464,14 @@ "Average Path": 4, "Estimated LUTs": 18, "Total Node": 18, - "Wires": 26, - "Wire Bits": 28, + "Wires": 24, + "Wire Bits": 26, "Public Wires": 16, "Public Wire Bits": 16, - "Total Cells": 20, + "Total Cells": 18, "MUX": 2, "XOR": 4, - "AND": 14 + "AND": 12 }, "mults_auto_none/twobits_arithmetic_multiply/k6_frac_N10_frac_chain_mem32K_40nm": { "test_name": "mults_auto_none/twobits_arithmetic_multiply/k6_frac_N10_frac_chain_mem32K_40nm", @@ -571,14 +571,14 @@ "Average Path": 5, "Estimated LUTs": 1388, "Total Node": 1362, - "Wires": 1083, - "Wire Bits": 1398, + "Wires": 1086, + "Wire Bits": 1402, "Public Wires": 127, "Public Wire Bits": 127, - "Total Cells": 1206, + "Total Cells": 1210, "MUX": 538, "XOR": 386, - "AND": 228, + "AND": 232, "DFFs": [ "$_DFF_P_ 54" ] @@ -608,14 +608,14 @@ "Average Path": 5, "Estimated LUTs": 1383, "Total Node": 1362, - "Wires": 1083, - "Wire Bits": 1398, + "Wires": 1086, + "Wire Bits": 1402, "Public Wires": 127, "Public Wire Bits": 127, - "Total Cells": 1206, + "Total Cells": 1210, "MUX": 538, "XOR": 386, - "AND": 228, + "AND": 232, "DFFs": [ "$_DFF_P_ 54" ] @@ -701,14 +701,14 @@ "Average Path": 6, "Estimated LUTs": 1995, "Total Node": 1984, - "Wires": 1786, - "Wire Bits": 2246, + "Wires": 1787, + "Wire Bits": 2247, "Public Wires": 155, "Public Wire Bits": 155, - "Total Cells": 2039, + "Total Cells": 2040, "MUX": 949, "XOR": 679, - "AND": 365, + "AND": 366, "DFFs": [ "$_DFF_P_ 46" ] @@ -732,14 +732,14 @@ "Average Path": 6, "Estimated LUTs": 1994, "Total Node": 1984, - "Wires": 1786, - "Wire Bits": 2246, + "Wires": 1787, + "Wire Bits": 2247, "Public Wires": 155, "Public Wire Bits": 155, - "Total Cells": 2039, + "Total Cells": 2040, "MUX": 949, "XOR": 679, - "AND": 365, + "AND": 366, "DFFs": [ "$_DFF_P_ 46" ] @@ -763,14 +763,14 @@ "Average Path": 3, "Estimated LUTs": 562, "Total Node": 551, - "Wires": 627, - "Wire Bits": 771, + "Wires": 625, + "Wire Bits": 769, "Public Wires": 110, "Public Wire Bits": 110, - "Total Cells": 665, + "Total Cells": 663, "MUX": 304, "XOR": 221, - "AND": 94, + "AND": 92, "DFFs": [ "$_DFF_P_ 46" ] @@ -794,14 +794,14 @@ "Average Path": 3, "Estimated LUTs": 561, "Total Node": 551, - "Wires": 627, - "Wire Bits": 771, + "Wires": 625, + "Wire Bits": 769, "Public Wires": 110, "Public Wire Bits": 110, - "Total Cells": 665, + "Total Cells": 663, "MUX": 304, "XOR": 221, - "AND": 94, + "AND": 92, "DFFs": [ "$_DFF_P_ 46" ] @@ -826,13 +826,13 @@ "Estimated LUTs": 1322, "Total Node": 1309, "Wires": 1284, - "Wire Bits": 1601, + "Wire Bits": 1602, "Public Wires": 269, "Public Wire Bits": 269, - "Total Cells": 1317, + "Total Cells": 1319, "MUX": 598, "XOR": 425, - "AND": 241, + "AND": 243, "DFFs": [ "$_DFF_P_ 53" ] @@ -857,13 +857,13 @@ "Estimated LUTs": 1319, "Total Node": 1309, "Wires": 1284, - "Wire Bits": 1601, + "Wire Bits": 1602, "Public Wires": 269, "Public Wire Bits": 269, - "Total Cells": 1317, + "Total Cells": 1319, "MUX": 598, "XOR": 425, - "AND": 241, + "AND": 243, "DFFs": [ "$_DFF_P_ 53" ] @@ -944,14 +944,14 @@ "Average Path": 4, "Estimated LUTs": 18, "Total Node": 18, - "Wires": 26, - "Wire Bits": 28, + "Wires": 24, + "Wire Bits": 26, "Public Wires": 16, "Public Wire Bits": 16, - "Total Cells": 20, + "Total Cells": 18, "MUX": 2, "XOR": 4, - "AND": 14 + "AND": 12 }, "mults_auto_none/multiply_hard_block/k6_N10_mem32K_40nm": { "test_name": "mults_auto_none/multiply_hard_block/k6_N10_mem32K_40nm", @@ -967,14 +967,14 @@ "Average Path": 4, "Estimated LUTs": 18, "Total Node": 18, - "Wires": 26, - "Wire Bits": 28, + "Wires": 24, + "Wire Bits": 26, "Public Wires": 16, "Public Wire Bits": 16, - "Total Cells": 20, + "Total Cells": 18, "MUX": 2, "XOR": 4, - "AND": 14 + "AND": 12 }, "mults_auto_none/twobits_arithmetic_multiply/k6_frac_N10_mem32K_40nm": { "test_name": "mults_auto_none/twobits_arithmetic_multiply/k6_frac_N10_mem32K_40nm", diff --git a/parmys/regression_test/benchmark/task/operators/synthesis_result.json b/parmys/regression_test/benchmark/task/operators/synthesis_result.json index 631b4a6c938..b99a53d5197 100644 --- a/parmys/regression_test/benchmark/task/operators/synthesis_result.json +++ b/parmys/regression_test/benchmark/task/operators/synthesis_result.json @@ -559,16 +559,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 13, - "Wire Bits": 13, + "Wires": 15, + "Wire Bits": 15, "Public Wires": 6, "Public Wire Bits": 6, - "Total Cells": 8, + "Total Cells": 10, "MUX": 1, "XOR": 1, - "OR": 2, + "OR": 3, "AND": 1, - "NOT": 2, + "NOT": 3, "DFFs": [ "$_DFF_P_ 1" ] @@ -597,16 +597,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 13, - "Wire Bits": 13, + "Wires": 15, + "Wire Bits": 15, "Public Wires": 6, "Public Wire Bits": 6, - "Total Cells": 8, + "Total Cells": 10, "MUX": 1, "XOR": 1, - "OR": 2, + "OR": 3, "AND": 1, - "NOT": 2, + "NOT": 3, "DFFs": [ "$_DFF_P_ 1" ] @@ -635,16 +635,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 13, - "Wire Bits": 13, + "Wires": 15, + "Wire Bits": 15, "Public Wires": 6, "Public Wire Bits": 6, - "Total Cells": 8, + "Total Cells": 10, "MUX": 1, "XOR": 1, - "OR": 2, + "OR": 3, "AND": 1, - "NOT": 2, + "NOT": 3, "DFFs": [ "$_DFF_P_ 1" ] @@ -671,16 +671,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 13, - "Wire Bits": 13, + "Wires": 15, + "Wire Bits": 15, "Public Wires": 6, "Public Wire Bits": 6, - "Total Cells": 8, + "Total Cells": 10, "MUX": 1, "XOR": 1, - "OR": 2, + "OR": 3, "AND": 1, - "NOT": 2, + "NOT": 3, "DFFs": [ "$_DFF_P_ 1" ] @@ -709,16 +709,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 12, - "Wire Bits": 12, + "Wires": 14, + "Wire Bits": 14, "Public Wires": 6, "Public Wire Bits": 6, - "Total Cells": 7, + "Total Cells": 9, "MUX": 1, "XOR": 1, - "OR": 1, + "OR": 2, "AND": 1, - "NOT": 2, + "NOT": 3, "DFFs": [ "$_DFF_P_ 1" ] @@ -747,16 +747,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 12, - "Wire Bits": 12, + "Wires": 14, + "Wire Bits": 14, "Public Wires": 6, "Public Wire Bits": 6, - "Total Cells": 7, + "Total Cells": 9, "MUX": 1, "XOR": 1, - "OR": 1, + "OR": 2, "AND": 1, - "NOT": 2, + "NOT": 3, "DFFs": [ "$_DFF_P_ 1" ] @@ -785,16 +785,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 12, - "Wire Bits": 12, + "Wires": 14, + "Wire Bits": 14, "Public Wires": 6, "Public Wire Bits": 6, - "Total Cells": 7, + "Total Cells": 9, "MUX": 1, "XOR": 1, - "OR": 1, + "OR": 2, "AND": 1, - "NOT": 2, + "NOT": 3, "DFFs": [ "$_DFF_P_ 1" ] @@ -821,16 +821,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 12, - "Wire Bits": 12, + "Wires": 14, + "Wire Bits": 14, "Public Wires": 6, "Public Wire Bits": 6, - "Total Cells": 7, + "Total Cells": 9, "MUX": 1, "XOR": 1, - "OR": 1, + "OR": 2, "AND": 1, - "NOT": 2, + "NOT": 3, "DFFs": [ "$_DFF_P_ 1" ] @@ -859,16 +859,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 15, - "Wire Bits": 15, + "Wires": 13, + "Wire Bits": 13, "Public Wires": 6, "Public Wire Bits": 6, - "Total Cells": 10, + "Total Cells": 8, "MUX": 1, "XOR": 1, - "OR": 3, + "OR": 2, "AND": 1, - "NOT": 3, + "NOT": 2, "DFFs": [ "$_DFF_P_ 1" ] @@ -897,16 +897,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 15, - "Wire Bits": 15, + "Wires": 13, + "Wire Bits": 13, "Public Wires": 6, "Public Wire Bits": 6, - "Total Cells": 10, + "Total Cells": 8, "MUX": 1, "XOR": 1, - "OR": 3, + "OR": 2, "AND": 1, - "NOT": 3, + "NOT": 2, "DFFs": [ "$_DFF_P_ 1" ] @@ -935,16 +935,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 15, - "Wire Bits": 15, + "Wires": 13, + "Wire Bits": 13, "Public Wires": 6, "Public Wire Bits": 6, - "Total Cells": 10, + "Total Cells": 8, "MUX": 1, "XOR": 1, - "OR": 3, + "OR": 2, "AND": 1, - "NOT": 3, + "NOT": 2, "DFFs": [ "$_DFF_P_ 1" ] @@ -971,16 +971,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 15, - "Wire Bits": 15, + "Wires": 13, + "Wire Bits": 13, "Public Wires": 6, "Public Wire Bits": 6, - "Total Cells": 10, + "Total Cells": 8, "MUX": 1, "XOR": 1, - "OR": 3, + "OR": 2, "AND": 1, - "NOT": 3, + "NOT": 2, "DFFs": [ "$_DFF_P_ 1" ] @@ -1009,16 +1009,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 14, - "Wire Bits": 14, + "Wires": 12, + "Wire Bits": 12, "Public Wires": 6, "Public Wire Bits": 6, - "Total Cells": 9, + "Total Cells": 7, "MUX": 1, "XOR": 1, - "OR": 2, + "OR": 1, "AND": 1, - "NOT": 3, + "NOT": 2, "DFFs": [ "$_DFF_P_ 1" ] @@ -1047,16 +1047,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 14, - "Wire Bits": 14, + "Wires": 12, + "Wire Bits": 12, "Public Wires": 6, "Public Wire Bits": 6, - "Total Cells": 9, + "Total Cells": 7, "MUX": 1, "XOR": 1, - "OR": 2, + "OR": 1, "AND": 1, - "NOT": 3, + "NOT": 2, "DFFs": [ "$_DFF_P_ 1" ] @@ -1085,16 +1085,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 14, - "Wire Bits": 14, + "Wires": 12, + "Wire Bits": 12, "Public Wires": 6, "Public Wire Bits": 6, - "Total Cells": 9, + "Total Cells": 7, "MUX": 1, "XOR": 1, - "OR": 2, + "OR": 1, "AND": 1, - "NOT": 3, + "NOT": 2, "DFFs": [ "$_DFF_P_ 1" ] @@ -1121,16 +1121,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 14, - "Wire Bits": 14, + "Wires": 12, + "Wire Bits": 12, "Public Wires": 6, "Public Wire Bits": 6, - "Total Cells": 9, + "Total Cells": 7, "MUX": 1, "XOR": 1, - "OR": 2, + "OR": 1, "AND": 1, - "NOT": 3, + "NOT": 2, "DFFs": [ "$_DFF_P_ 1" ] @@ -3419,16 +3419,16 @@ "Average Path": 4, "Estimated LUTs": 7, "Total Node": 2, - "Wires": 175, - "Wire Bits": 627, + "Wires": 183, + "Wire Bits": 628, "Public Wires": 19, "Public Wire Bits": 19, - "Total Cells": 339, + "Total Cells": 345, "MUX": 40, "XOR": 53, - "OR": 70, - "AND": 126, - "NOT": 42, + "OR": 75, + "AND": 129, + "NOT": 40, "DFFs": [ "$_DFF_P_ 8" ] @@ -3451,16 +3451,16 @@ "Average Path": 4, "Estimated LUTs": 6, "Total Node": 2, - "Wires": 175, - "Wire Bits": 627, + "Wires": 183, + "Wire Bits": 628, "Public Wires": 19, "Public Wire Bits": 19, - "Total Cells": 339, + "Total Cells": 345, "MUX": 40, "XOR": 53, - "OR": 70, - "AND": 126, - "NOT": 42, + "OR": 75, + "AND": 129, + "NOT": 40, "DFFs": [ "$_DFF_P_ 8" ] @@ -3483,16 +3483,16 @@ "Average Path": 4, "Estimated LUTs": 6, "Total Node": 2, - "Wires": 175, - "Wire Bits": 627, + "Wires": 183, + "Wire Bits": 628, "Public Wires": 19, "Public Wire Bits": 19, - "Total Cells": 339, + "Total Cells": 345, "MUX": 40, "XOR": 53, - "OR": 70, - "AND": 126, - "NOT": 42, + "OR": 75, + "AND": 129, + "NOT": 40, "DFFs": [ "$_DFF_P_ 8" ] @@ -3513,16 +3513,16 @@ "Average Path": 4, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 175, - "Wire Bits": 627, + "Wires": 183, + "Wire Bits": 628, "Public Wires": 19, "Public Wire Bits": 19, - "Total Cells": 339, + "Total Cells": 345, "MUX": 40, "XOR": 53, - "OR": 70, - "AND": 126, - "NOT": 42, + "OR": 75, + "AND": 129, + "NOT": 40, "DFFs": [ "$_DFF_P_ 8" ] @@ -3691,15 +3691,15 @@ "Average Path": 3, "Estimated LUTs": 4, "Total Node": 2, - "Wires": 46, - "Wire Bits": 97, + "Wires": 44, + "Wire Bits": 87, "Public Wires": 10, "Public Wire Bits": 10, - "Total Cells": 62, + "Total Cells": 57, "MUX": 9, - "XOR": 9, + "XOR": 7, "OR": 11, - "AND": 17, + "AND": 14, "NOT": 13, "DFFs": [ "$_DFF_P_ 3" @@ -3723,15 +3723,15 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 46, - "Wire Bits": 97, + "Wires": 44, + "Wire Bits": 87, "Public Wires": 10, "Public Wire Bits": 10, - "Total Cells": 62, + "Total Cells": 57, "MUX": 9, - "XOR": 9, + "XOR": 7, "OR": 11, - "AND": 17, + "AND": 14, "NOT": 13, "DFFs": [ "$_DFF_P_ 3" @@ -3755,15 +3755,15 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 46, - "Wire Bits": 97, + "Wires": 44, + "Wire Bits": 87, "Public Wires": 10, "Public Wire Bits": 10, - "Total Cells": 62, + "Total Cells": 57, "MUX": 9, - "XOR": 9, + "XOR": 7, "OR": 11, - "AND": 17, + "AND": 14, "NOT": 13, "DFFs": [ "$_DFF_P_ 3" @@ -3785,15 +3785,15 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 46, - "Wire Bits": 97, + "Wires": 44, + "Wire Bits": 87, "Public Wires": 10, "Public Wire Bits": 10, - "Total Cells": 62, + "Total Cells": 57, "MUX": 9, - "XOR": 9, + "XOR": 7, "OR": 11, - "AND": 17, + "AND": 14, "NOT": 13, "DFFs": [ "$_DFF_P_ 3" @@ -4108,16 +4108,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 17, - "Wire Bits": 21, + "Wires": 19, + "Wire Bits": 23, "Public Wires": 8, "Public Wire Bits": 8, - "Total Cells": 14, + "Total Cells": 16, "MUX": 1, "XOR": 2, - "OR": 3, + "OR": 4, "AND": 4, - "NOT": 3, + "NOT": 4, "DFFs": [ "$_DFF_P_ 1" ] @@ -4146,16 +4146,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 17, - "Wire Bits": 21, + "Wires": 19, + "Wire Bits": 23, "Public Wires": 8, "Public Wire Bits": 8, - "Total Cells": 14, + "Total Cells": 16, "MUX": 1, "XOR": 2, - "OR": 3, + "OR": 4, "AND": 4, - "NOT": 3, + "NOT": 4, "DFFs": [ "$_DFF_P_ 1" ] @@ -4184,16 +4184,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 17, - "Wire Bits": 21, + "Wires": 19, + "Wire Bits": 23, "Public Wires": 8, "Public Wire Bits": 8, - "Total Cells": 14, + "Total Cells": 16, "MUX": 1, "XOR": 2, - "OR": 3, + "OR": 4, "AND": 4, - "NOT": 3, + "NOT": 4, "DFFs": [ "$_DFF_P_ 1" ] @@ -4220,16 +4220,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 17, - "Wire Bits": 21, + "Wires": 19, + "Wire Bits": 23, "Public Wires": 8, "Public Wire Bits": 8, - "Total Cells": 14, + "Total Cells": 16, "MUX": 1, "XOR": 2, - "OR": 3, + "OR": 4, "AND": 4, - "NOT": 3, + "NOT": 4, "DFFs": [ "$_DFF_P_ 1" ] @@ -4258,16 +4258,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 15, - "Wire Bits": 19, + "Wires": 18, + "Wire Bits": 22, "Public Wires": 8, "Public Wire Bits": 8, - "Total Cells": 12, + "Total Cells": 15, "MUX": 1, "XOR": 2, - "OR": 2, - "AND": 3, - "NOT": 3, + "OR": 3, + "AND": 4, + "NOT": 4, "DFFs": [ "$_DFF_P_ 1" ] @@ -4296,16 +4296,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 15, - "Wire Bits": 19, + "Wires": 18, + "Wire Bits": 22, "Public Wires": 8, "Public Wire Bits": 8, - "Total Cells": 12, + "Total Cells": 15, "MUX": 1, "XOR": 2, - "OR": 2, - "AND": 3, - "NOT": 3, + "OR": 3, + "AND": 4, + "NOT": 4, "DFFs": [ "$_DFF_P_ 1" ] @@ -4334,16 +4334,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 15, - "Wire Bits": 19, + "Wires": 18, + "Wire Bits": 22, "Public Wires": 8, "Public Wire Bits": 8, - "Total Cells": 12, + "Total Cells": 15, "MUX": 1, "XOR": 2, - "OR": 2, - "AND": 3, - "NOT": 3, + "OR": 3, + "AND": 4, + "NOT": 4, "DFFs": [ "$_DFF_P_ 1" ] @@ -4370,16 +4370,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 15, - "Wire Bits": 19, + "Wires": 18, + "Wire Bits": 22, "Public Wires": 8, "Public Wire Bits": 8, - "Total Cells": 12, + "Total Cells": 15, "MUX": 1, "XOR": 2, - "OR": 2, - "AND": 3, - "NOT": 3, + "OR": 3, + "AND": 4, + "NOT": 4, "DFFs": [ "$_DFF_P_ 1" ] @@ -4408,16 +4408,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 19, - "Wire Bits": 23, + "Wires": 17, + "Wire Bits": 21, "Public Wires": 8, "Public Wire Bits": 8, - "Total Cells": 16, + "Total Cells": 14, "MUX": 1, "XOR": 2, - "OR": 4, + "OR": 3, "AND": 4, - "NOT": 4, + "NOT": 3, "DFFs": [ "$_DFF_P_ 1" ] @@ -4446,16 +4446,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 19, - "Wire Bits": 23, + "Wires": 17, + "Wire Bits": 21, "Public Wires": 8, "Public Wire Bits": 8, - "Total Cells": 16, + "Total Cells": 14, "MUX": 1, "XOR": 2, - "OR": 4, + "OR": 3, "AND": 4, - "NOT": 4, + "NOT": 3, "DFFs": [ "$_DFF_P_ 1" ] @@ -4484,16 +4484,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 19, - "Wire Bits": 23, + "Wires": 17, + "Wire Bits": 21, "Public Wires": 8, "Public Wire Bits": 8, - "Total Cells": 16, + "Total Cells": 14, "MUX": 1, "XOR": 2, - "OR": 4, + "OR": 3, "AND": 4, - "NOT": 4, + "NOT": 3, "DFFs": [ "$_DFF_P_ 1" ] @@ -4520,16 +4520,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 19, - "Wire Bits": 23, + "Wires": 17, + "Wire Bits": 21, "Public Wires": 8, "Public Wire Bits": 8, - "Total Cells": 16, + "Total Cells": 14, "MUX": 1, "XOR": 2, - "OR": 4, + "OR": 3, "AND": 4, - "NOT": 4, + "NOT": 3, "DFFs": [ "$_DFF_P_ 1" ] @@ -4558,16 +4558,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 18, - "Wire Bits": 22, + "Wires": 15, + "Wire Bits": 19, "Public Wires": 8, "Public Wire Bits": 8, - "Total Cells": 15, + "Total Cells": 12, "MUX": 1, "XOR": 2, - "OR": 3, - "AND": 4, - "NOT": 4, + "OR": 2, + "AND": 3, + "NOT": 3, "DFFs": [ "$_DFF_P_ 1" ] @@ -4596,16 +4596,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 18, - "Wire Bits": 22, + "Wires": 15, + "Wire Bits": 19, "Public Wires": 8, "Public Wire Bits": 8, - "Total Cells": 15, + "Total Cells": 12, "MUX": 1, "XOR": 2, - "OR": 3, - "AND": 4, - "NOT": 4, + "OR": 2, + "AND": 3, + "NOT": 3, "DFFs": [ "$_DFF_P_ 1" ] @@ -4634,16 +4634,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 18, - "Wire Bits": 22, + "Wires": 15, + "Wire Bits": 19, "Public Wires": 8, "Public Wire Bits": 8, - "Total Cells": 15, + "Total Cells": 12, "MUX": 1, "XOR": 2, - "OR": 3, - "AND": 4, - "NOT": 4, + "OR": 2, + "AND": 3, + "NOT": 3, "DFFs": [ "$_DFF_P_ 1" ] @@ -4670,16 +4670,16 @@ "Average Path": 3, "Estimated LUTs": 2, "Total Node": 2, - "Wires": 18, - "Wire Bits": 22, + "Wires": 15, + "Wire Bits": 19, "Public Wires": 8, "Public Wire Bits": 8, - "Total Cells": 15, + "Total Cells": 12, "MUX": 1, "XOR": 2, - "OR": 3, - "AND": 4, - "NOT": 4, + "OR": 2, + "AND": 3, + "NOT": 3, "DFFs": [ "$_DFF_P_ 1" ] diff --git a/parmys/regression_test/benchmark/task/syntax/synthesis_result.json b/parmys/regression_test/benchmark/task/syntax/synthesis_result.json index 8a198e0c1ce..5d55155c1f5 100644 --- a/parmys/regression_test/benchmark/task/syntax/synthesis_result.json +++ b/parmys/regression_test/benchmark/task/syntax/synthesis_result.json @@ -1081,7 +1081,7 @@ "Multiplier": 38, "generic logic size": 4, "Longest Path": 441, - "Average Path": 16, + "Average Path": 14, "Estimated LUTs": 22893, "Total Node": 3791, "Wires": 26829, @@ -1103,7 +1103,7 @@ "test_name": "syntax/cf_fft_1024_16/no_arch", "exit": 1, "errors": [ - "BUF_NODE" + "[PARSE_TO_AST] Cannot create soft multiplier with multiplicand width of 1." ], "warnings": [ "Ignoring module cf_fft_1024_16 because it contains processes (run 'proc' command first).", @@ -1247,13 +1247,13 @@ "Average Path": 5, "Estimated LUTs": 168, "Total Node": 232, - "Wires": 458, - "Wire Bits": 515, + "Wires": 459, + "Wire Bits": 517, "Public Wires": 433, "Public Wire Bits": 433, - "Total Cells": 435, + "Total Cells": 434, "OR": 124, - "AND": 227, + "AND": 226, "NOT": 20, "DFFs": [ "$_DFF_P_ 64" @@ -1393,16 +1393,16 @@ "Average Path": 2, "Estimated LUTs": 244, "Total Node": 217, - "Wires": 1472, - "Wire Bits": 1654, + "Wires": 1491, + "Wire Bits": 1647, "Public Wires": 322, "Public Wire Bits": 322, - "Total Cells": 978, + "Total Cells": 971, "MUX": 386, "XOR": 32, - "OR": 34, - "AND": 96, - "NOT": 100, + "OR": 33, + "AND": 91, + "NOT": 99, "DFFs": [ "$_DFF_P_ 193" ], @@ -2081,14 +2081,14 @@ "Average Path": 5, "Estimated LUTs": 693, "Total Node": 693, - "Wires": 1083, - "Wire Bits": 1395, + "Wires": 1086, + "Wire Bits": 1399, "Public Wires": 127, "Public Wire Bits": 127, - "Total Cells": 1206, + "Total Cells": 1210, "MUX": 538, "XOR": 386, - "AND": 228, + "AND": 232, "DFFs": [ "$_DFF_P_ 54" ] @@ -2160,15 +2160,15 @@ "Average Path": 5, "Estimated LUTs": 693, "Total Node": 693, - "Wires": 1091, - "Wire Bits": 1404, + "Wires": 1095, + "Wire Bits": 1408, "Public Wires": 127, "Public Wire Bits": 127, - "Total Cells": 1215, + "Total Cells": 1219, "MUX": 538, "XOR": 386, "OR": 8, - "AND": 228, + "AND": 232, "DFFs": [ "$_DFF_P_ 55" ] @@ -2239,14 +2239,14 @@ "Average Path": 5, "Estimated LUTs": 693, "Total Node": 693, - "Wires": 1083, - "Wire Bits": 1395, + "Wires": 1086, + "Wire Bits": 1399, "Public Wires": 127, "Public Wire Bits": 127, - "Total Cells": 1206, + "Total Cells": 1210, "MUX": 538, "XOR": 386, - "AND": 228, + "AND": 232, "DFFs": [ "$_DFF_P_ 54" ] @@ -2883,14 +2883,14 @@ "Average Path": 7, "Estimated LUTs": 1095, "Total Node": 1607, - "Wires": 3385, - "Wire Bits": 3751, + "Wires": 3405, + "Wire Bits": 3777, "Public Wires": 3211, "Public Wire Bits": 3211, - "Total Cells": 3207, + "Total Cells": 3227, "MUX": 32, "OR": 992, - "AND": 1587, + "AND": 1607, "NOT": 52, "DFFs": [ "$_DFF_P_ 544" @@ -2924,8 +2924,8 @@ "Average Path": 4, "Estimated LUTs": 101, "Total Node": 67, - "Wires": 212, - "Wire Bits": 268, + "Wires": 213, + "Wire Bits": 269, "Public Wires": 177, "Public Wire Bits": 177, "Total Cells": 145, @@ -2964,8 +2964,8 @@ "Average Path": 5, "Estimated LUTs": 25938, "Total Node": 34130, - "Wires": 76077, - "Wire Bits": 84563, + "Wires": 76078, + "Wire Bits": 84564, "Public Wires": 75169, "Public Wire Bits": 75169, "Total Cells": 59068, @@ -3294,15 +3294,15 @@ "Average Path": 5, "Estimated LUTs": 693, "Total Node": 693, - "Wires": 1091, - "Wire Bits": 1404, + "Wires": 1095, + "Wire Bits": 1408, "Public Wires": 127, "Public Wire Bits": 127, - "Total Cells": 1215, + "Total Cells": 1219, "MUX": 538, "XOR": 386, "OR": 8, - "AND": 228, + "AND": 232, "DFFs": [ "$_DFF_P_ 55" ] @@ -3673,14 +3673,14 @@ "Estimated LUTs": 1475, "Total Node": 647, "Wires": 3776, - "Wire Bits": 4164, + "Wire Bits": 4155, "Public Wires": 32, "Public Wire Bits": 32, - "Total Cells": 2949, + "Total Cells": 2947, "MUX": 1513, "XOR": 470, - "OR": 268, - "AND": 72, + "OR": 269, + "AND": 69, "NOT": 65, "DFFs": [ "$_DFF_P_ 517" @@ -3797,15 +3797,15 @@ "Average Path": 5, "Estimated LUTs": 1050, "Total Node": 1050, - "Wires": 3337, - "Wire Bits": 3876, + "Wires": 3339, + "Wire Bits": 3865, "Public Wires": 20, "Public Wire Bits": 20, - "Total Cells": 3518, + "Total Cells": 3524, "MUX": 1639, "XOR": 692, - "OR": 265, - "AND": 337, + "OR": 266, + "AND": 342, "NOT": 68, "DFFs": [ "$_DFF_P_ 517" @@ -3903,16 +3903,16 @@ "Average Path": 4, "Estimated LUTs": 6802, "Total Node": 939, - "Wires": 4689, - "Wire Bits": 14487, + "Wires": 4692, + "Wire Bits": 14481, "Public Wires": 51, "Public Wire Bits": 51, - "Total Cells": 6551, + "Total Cells": 6554, "MUX": 1856, "XOR": 394, - "OR": 3021, + "OR": 3023, "AND": 63, - "NOT": 551, + "NOT": 552, "DFFs": [ "$_DFF_P_ 616" ], @@ -4007,16 +4007,16 @@ "Average Path": 5, "Estimated LUTs": 1934, "Total Node": 1934, - "Wires": 5450, + "Wires": 5453, "Wire Bits": 15657, "Public Wires": 32, "Public Wire Bits": 32, - "Total Cells": 8193, + "Total Cells": 8196, "MUX": 2432, "XOR": 985, - "OR": 3014, + "OR": 3016, "AND": 592, - "NOT": 554, + "NOT": 555, "DFFs": [ "$_DFF_P_ 616" ] @@ -4048,8 +4048,8 @@ "Average Path": 4, "Estimated LUTs": 101, "Total Node": 33, - "Wires": 103, - "Wire Bits": 168, + "Wires": 104, + "Wire Bits": 169, "Public Wires": 71, "Public Wire Bits": 71, "Total Cells": 111, @@ -4086,8 +4086,8 @@ "Average Path": 4, "Estimated LUTs": 33, "Total Node": 33, - "Wires": 103, - "Wire Bits": 168, + "Wires": 104, + "Wire Bits": 169, "Public Wires": 71, "Public Wire Bits": 71, "Total Cells": 111, @@ -4345,15 +4345,15 @@ "Average Path": 4, "Estimated LUTs": 8744, "Total Node": 12840, - "Wires": 25832, - "Wire Bits": 30207, + "Wires": 25838, + "Wire Bits": 30231, "Public Wires": 25146, "Public Wire Bits": 25146, - "Total Cells": 25944, + "Total Cells": 25949, "MUX": 14, "XOR": 7, "OR": 8176, - "AND": 13379, + "AND": 13384, "NOT": 264, "DFFs": [ "$_DFF_P_ 4104" diff --git a/parmys/regression_test/benchmark/task/ultraembedded/synthesis_result.json b/parmys/regression_test/benchmark/task/ultraembedded/synthesis_result.json index 35fc0362bcc..f919a7fac1c 100644 --- a/parmys/regression_test/benchmark/task/ultraembedded/synthesis_result.json +++ b/parmys/regression_test/benchmark/task/ultraembedded/synthesis_result.json @@ -58,16 +58,16 @@ "Average Path": 4, "Estimated LUTs": 1517, "Total Node": 1023, - "Wires": 2658, - "Wire Bits": 3780, + "Wires": 2701, + "Wire Bits": 3806, "Public Wires": 415, "Public Wire Bits": 415, - "Total Cells": 3034, + "Total Cells": 3051, "MUX": 983, "XOR": 425, - "OR": 414, - "AND": 324, - "NOT": 208, + "OR": 428, + "AND": 337, + "NOT": 198, "DFFs": [ "$_DFF_P_ 445" ], @@ -112,26 +112,26 @@ "synthesis_time(ms)": 4.3, "Pi": 63, "Po": 187, - "logic element": 801, - "Adder": 359, + "logic element": 866, + "Adder": 434, "Memory": 32, "generic logic size": 4, "Longest Path": 109, "Average Path": 2, - "Estimated LUTs": 2118, - "Total Node": 1192, - "Wires": 4506, - "Wire Bits": 8715, - "Public Wires": 597, - "Public Wire Bits": 597, - "Total Cells": 5099, - "MUX": 2110, - "XOR": 34, - "OR": 906, - "AND": 538, - "NOT": 273, + "Estimated LUTs": 2183, + "Total Node": 1332, + "Wires": 4367, + "Wire Bits": 6013, + "Public Wires": 662, + "Public Wire Bits": 662, + "Total Cells": 4581, + "MUX": 1801, + "XOR": 20, + "OR": 908, + "AND": 482, + "NOT": 203, "DFFs": [ - "$_DFF_P_ 847" + "$_DFF_P_ 776" ], "adder": 359, "dual_port_ram": 32 @@ -181,13 +181,13 @@ "Estimated LUTs": 2659, "Total Node": 1092, "Wires": 4952, - "Wire Bits": 7400, + "Wire Bits": 7406, "Public Wires": 792, "Public Wire Bits": 792, - "Total Cells": 5992, + "Total Cells": 5993, "MUX": 1794, "XOR": 129, - "OR": 1347, + "OR": 1348, "AND": 1157, "NOT": 353, "DFFs": [ @@ -225,30 +225,30 @@ "Pi": 135, "Po": 119, "logic element": 627, - "Adder": 446, - "Multiplier": 3, + "Adder": 388, + "Multiplier": 1, "Memory": 32, "generic logic size": 4, "Longest Path": 182, "Average Path": 4, "Estimated LUTs": 3309, - "Total Node": 1108, - "Wires": 5361, - "Wire Bits": 7965, + "Total Node": 1048, + "Wires": 5183, + "Wire Bits": 7792, "Public Wires": 459, "Public Wire Bits": 459, - "Total Cells": 6329, + "Total Cells": 6351, "MUX": 2960, - "XOR": 189, - "OR": 864, - "AND": 983, - "NOT": 371, + "XOR": 221, + "OR": 893, + "AND": 1037, + "NOT": 338, "DFFs": [ "$_DFF_P_ 514" ], - "adder": 413, + "adder": 355, "dual_port_ram": 32, - "multiply": 3 + "multiply": 1 }, "ultraembedded/usb_uart_core/k6_frac_N10_frac_chain_mem32K_40nm": { "test_name": "ultraembedded/usb_uart_core/k6_frac_N10_frac_chain_mem32K_40nm", @@ -318,15 +318,15 @@ "Average Path": 2, "Estimated LUTs": 2852, "Total Node": 1381, - "Wires": 3621, - "Wire Bits": 5292, + "Wires": 3620, + "Wire Bits": 5288, "Public Wires": 119, "Public Wire Bits": 119, - "Total Cells": 4101, + "Total Cells": 4097, "MUX": 1258, "XOR": 139, - "OR": 1192, - "AND": 362, + "OR": 1190, + "AND": 360, "NOT": 421, "DFFs": [ "$_DFF_P_ 524" diff --git a/parmys/regression_test/benchmark/task/vexriscv/synthesis_result.json b/parmys/regression_test/benchmark/task/vexriscv/synthesis_result.json index f381e55300e..99742919bd1 100644 --- a/parmys/regression_test/benchmark/task/vexriscv/synthesis_result.json +++ b/parmys/regression_test/benchmark/task/vexriscv/synthesis_result.json @@ -408,20 +408,20 @@ "Multiplier": 4, "Memory": 242, "generic logic size": 4, - "Longest Path": 843, + "Longest Path": 863, "Average Path": 4, "Estimated LUTs": 8043, "Total Node": 4065, - "Wires": 14732, - "Wire Bits": 20401, + "Wires": 14723, + "Wire Bits": 20361, "Public Wires": 877, "Public Wire Bits": 877, - "Total Cells": 17372, + "Total Cells": 17350, "MUX": 6882, "XOR": 454, - "OR": 2559, - "AND": 1970, - "NOT": 935, + "OR": 2548, + "AND": 1968, + "NOT": 926, "DFFs": [ "$_DFF_N_ 1", "$_DFF_P_ 3386" @@ -1068,14 +1068,14 @@ "Average Path": 4, "Estimated LUTs": 3240, "Total Node": 1609, - "Wires": 5542, - "Wire Bits": 8275, + "Wires": 5551, + "Wire Bits": 8226, "Public Wires": 421, "Public Wire Bits": 421, - "Total Cells": 6824, + "Total Cells": 6825, "MUX": 2581, "XOR": 144, - "OR": 1090, + "OR": 1091, "AND": 870, "NOT": 382, "DFFs": [ @@ -1231,8 +1231,8 @@ "Average Path": 3, "Estimated LUTs": 3582, "Total Node": 1645, - "Wires": 5925, - "Wire Bits": 8729, + "Wires": 5932, + "Wire Bits": 8679, "Public Wires": 464, "Public Wire Bits": 464, "Total Cells": 7324, @@ -1591,14 +1591,14 @@ "Average Path": 4, "Estimated LUTs": 4666, "Total Node": 1960, - "Wires": 8366, - "Wire Bits": 11552, + "Wires": 8365, + "Wire Bits": 11515, "Public Wires": 584, "Public Wire Bits": 584, - "Total Cells": 9681, + "Total Cells": 9682, "MUX": 4359, "XOR": 268, - "OR": 1386, + "OR": 1387, "AND": 866, "NOT": 524, "DFFs": [ @@ -1654,14 +1654,14 @@ "Estimated LUTs": 3806, "Total Node": 1594, "Wires": 7020, - "Wire Bits": 9661, + "Wire Bits": 9597, "Public Wires": 580, "Public Wire Bits": 580, - "Total Cells": 7825, + "Total Cells": 7824, "MUX": 3715, "XOR": 135, "OR": 1007, - "AND": 666, + "AND": 665, "NOT": 456, "DFFs": [ "$_DFF_P_ 1262" @@ -1716,7 +1716,7 @@ "Estimated LUTs": 3906, "Total Node": 1703, "Wires": 7427, - "Wire Bits": 10069, + "Wire Bits": 10005, "Public Wires": 694, "Public Wire Bits": 694, "Total Cells": 8164, @@ -1759,8 +1759,8 @@ "Average Path": 5, "Estimated LUTs": 3318, "Total Node": 1264, - "Wires": 5957, - "Wire Bits": 8371, + "Wires": 5960, + "Wire Bits": 8305, "Public Wires": 361, "Public Wire Bits": 361, "Total Cells": 6640, @@ -1818,16 +1818,16 @@ "Average Path": 3, "Estimated LUTs": 6611, "Total Node": 2574, - "Wires": 10967, - "Wire Bits": 15099, + "Wires": 10970, + "Wire Bits": 15142, "Public Wires": 583, "Public Wire Bits": 583, - "Total Cells": 13098, + "Total Cells": 13096, "MUX": 5888, "XOR": 331, - "OR": 1996, - "AND": 1247, - "NOT": 673, + "OR": 1994, + "AND": 1246, + "NOT": 674, "DFFs": [ "$_DFF_P_ 2303" ], @@ -1865,16 +1865,16 @@ "Average Path": 3, "Estimated LUTs": 7117, "Total Node": 3035, - "Wires": 11995, - "Wire Bits": 16356, + "Wires": 12002, + "Wire Bits": 16343, "Public Wires": 699, "Public Wire Bits": 699, - "Total Cells": 14060, + "Total Cells": 14057, "MUX": 6209, "XOR": 392, - "OR": 2172, - "AND": 1325, - "NOT": 726, + "OR": 2170, + "AND": 1323, + "NOT": 727, "DFFs": [ "$_DFF_P_ 2455" ], @@ -2159,8 +2159,8 @@ "Average Path": 4, "Estimated LUTs": 3513, "Total Node": 1415, - "Wires": 6616, - "Wire Bits": 8860, + "Wires": 6614, + "Wire Bits": 8797, "Public Wires": 478, "Public Wire Bits": 478, "Total Cells": 7100, @@ -2220,16 +2220,16 @@ "Average Path": 4, "Estimated LUTs": 8969, "Total Node": 2639, - "Wires": 13233, - "Wire Bits": 18788, + "Wires": 13230, + "Wire Bits": 18722, "Public Wires": 674, "Public Wire Bits": 674, - "Total Cells": 16344, + "Total Cells": 16338, "MUX": 6669, "XOR": 1029, - "OR": 2808, - "AND": 1918, - "NOT": 780, + "OR": 2804, + "AND": 1917, + "NOT": 779, "DFFs": [ "$_DFF_P_ 2391" ], @@ -2269,7 +2269,7 @@ "Estimated LUTs": 2048, "Total Node": 748, "Wires": 3124, - "Wire Bits": 4665, + "Wire Bits": 4601, "Public Wires": 349, "Public Wire Bits": 349, "Total Cells": 3750, @@ -2315,7 +2315,7 @@ "Estimated LUTs": 2023, "Total Node": 693, "Wires": 2983, - "Wire Bits": 4490, + "Wire Bits": 4427, "Public Wires": 253, "Public Wire Bits": 253, "Total Cells": 3623, @@ -2360,8 +2360,8 @@ "Average Path": 5, "Estimated LUTs": 1535, "Total Node": 673, - "Wires": 2397, - "Wire Bits": 3929, + "Wires": 2398, + "Wire Bits": 3869, "Public Wires": 253, "Public Wire Bits": 253, "Total Cells": 3009, @@ -2407,7 +2407,7 @@ "Estimated LUTs": 1190, "Total Node": 537, "Wires": 1958, - "Wire Bits": 3461, + "Wire Bits": 3396, "Public Wires": 250, "Public Wire Bits": 250, "Total Cells": 2564, diff --git a/parmys/regression_test/benchmark/verilog/keywords/.generic/replicate_any_width_binary_test.v b/parmys/regression_test/benchmark/verilog/keywords/.generic/replicate_any_width_binary_test.v index 0801edc518c..4f22d49250a 100644 --- a/parmys/regression_test/benchmark/verilog/keywords/.generic/replicate_any_width_binary_test.v +++ b/parmys/regression_test/benchmark/verilog/keywords/.generic/replicate_any_width_binary_test.v @@ -7,8 +7,8 @@ module simple_op(a,b,out); input `RANGE a; - input `RANGE b; + input `RANGE b; output `RANGE out; `operator ar`RANGE(out,a,b); -endmodule \ No newline at end of file +endmodule diff --git a/parmys/regression_test/benchmark/verilog/keywords/and/replicate_and_int_wide.vh b/parmys/regression_test/benchmark/verilog/keywords/and/replicate_and_int_wide.vh index bbe393d5193..4a025bd61ad 100644 --- a/parmys/regression_test/benchmark/verilog/keywords/and/replicate_and_int_wide.vh +++ b/parmys/regression_test/benchmark/verilog/keywords/and/replicate_and_int_wide.vh @@ -4,4 +4,4 @@ `define WIDTH 32 `define operator and -`include "../.generic/replicate_any_width_binary_test.v" \ No newline at end of file +`include "../.generic/replicate_any_width_binary_test.v" diff --git a/parmys/regression_test/benchmark/verilog/keywords/and/replicate_and_ultra_wide.vh b/parmys/regression_test/benchmark/verilog/keywords/and/replicate_and_ultra_wide.vh index 22f1b507569..21297694f4d 100644 --- a/parmys/regression_test/benchmark/verilog/keywords/and/replicate_and_ultra_wide.vh +++ b/parmys/regression_test/benchmark/verilog/keywords/and/replicate_and_ultra_wide.vh @@ -4,4 +4,4 @@ `define WIDTH 256 `define operator and -`include "../.generic/replicate_any_width_binary_test.v" \ No newline at end of file +`include "../.generic/replicate_any_width_binary_test.v" diff --git a/parmys/regression_test/benchmark/verilog/keywords/and/replicate_and_wide.vh b/parmys/regression_test/benchmark/verilog/keywords/and/replicate_and_wide.vh index 0f225c81970..43901cbd82b 100644 --- a/parmys/regression_test/benchmark/verilog/keywords/and/replicate_and_wide.vh +++ b/parmys/regression_test/benchmark/verilog/keywords/and/replicate_and_wide.vh @@ -4,4 +4,4 @@ `define WIDTH 3 `define operator and -`include "../.generic/replicate_any_width_binary_test.v" \ No newline at end of file +`include "../.generic/replicate_any_width_binary_test.v" diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_basic/basic_no_timing/config/golden_results.txt b/vtr_flow/tasks/regression_tests/vtr_reg_basic/basic_no_timing/config/golden_results.txt index 2af379bd870..9033d3d9875 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_basic/basic_no_timing/config/golden_results.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_basic/basic_no_timing/config/golden_results.txt @@ -1,5 +1,5 @@ arch circuit script_params vtr_flow_elapsed_time vtr_max_mem_stage vtr_max_mem error odin_synth_time max_odin_mem parmys_synth_time max_parmys_mem abc_depth abc_synth_time abc_cec_time abc_sec_time max_abc_mem ace_time max_ace_mem num_clb num_io num_memories num_mult vpr_status vpr_revision vpr_build_info vpr_compiler vpr_compiled hostname rundir max_vpr_mem num_primary_inputs num_primary_outputs num_pre_packed_nets num_pre_packed_blocks num_netlist_clocks num_post_packed_nets num_post_packed_blocks device_width device_height device_grid_tiles device_limiting_resources device_name pack_mem pack_time initial_placed_wirelength_est placed_wirelength_est total_swap accepted_swap rejected_swap aborted_swap place_mem place_time place_quench_time min_chan_width routed_wirelength min_chan_width_route_success_iteration logic_block_area_total logic_block_area_used min_chan_width_routing_area_total min_chan_width_routing_area_per_tile min_chan_width_route_time -k4_N10_memSize16384_memData64.xml ch_intrinsics.v common 1.20 vpr 63.47 MiB -1 -1 0.21 18728 3 0.06 -1 -1 32696 -1 -1 72 99 1 0 success v8.0.0-12648-g259ceba57-dirty release IPO VTR_ASSERT_LEVEL=2 Clang 18.1.3 on Linux-6.8.0-58-generic x86_64 2025-05-06T12:34:13 betzgrp-wintermute /home/zhan6738/VTR/vtr-verilog-to-routing/vtr_flow/tasks 64996 99 130 353 483 1 220 302 13 13 169 clb auto 23.7 MiB 0.03 1748 641 31674 5814 13912 11948 63.5 MiB 0.03 0.00 36 1209 9 3.33e+06 2.28e+06 481319. 2848.04 0.18 -k4_N10_memSize16384_memData64.xml diffeq1.v common 2.73 vpr 66.43 MiB -1 -1 0.30 23332 23 0.24 -1 -1 33444 -1 -1 78 162 0 5 success v8.0.0-12648-g259ceba57-dirty release IPO VTR_ASSERT_LEVEL=2 Clang 18.1.3 on Linux-6.8.0-58-generic x86_64 2025-05-06T12:34:13 betzgrp-wintermute /home/zhan6738/VTR/vtr-verilog-to-routing/vtr_flow/tasks 68020 162 96 1200 1141 1 690 341 14 14 196 clb auto 26.8 MiB 0.11 8696 5304 81261 22686 53433 5142 66.4 MiB 0.09 0.00 46 10726 18 4.32e+06 2.79e+06 735717. 3753.66 1.03 -k4_N10_memSize16384_memData64.xml single_wire.v common 0.51 vpr 61.51 MiB -1 -1 0.06 17188 1 0.02 -1 -1 29568 -1 -1 0 1 0 0 success v8.0.0-12648-g259ceba57-dirty release IPO VTR_ASSERT_LEVEL=2 Clang 18.1.3 on Linux-6.8.0-58-generic x86_64 2025-05-06T12:34:13 betzgrp-wintermute /home/zhan6738/VTR/vtr-verilog-to-routing/vtr_flow/tasks 62988 1 1 1 2 0 1 2 3 3 9 -1 auto 22.9 MiB 0.00 2 2 3 0 3 0 61.5 MiB 0.00 0.00 2 1 1 30000 0 1489.46 165.495 0.00 -k4_N10_memSize16384_memData64.xml single_ff.v common 0.51 vpr 61.52 MiB -1 -1 0.06 17188 1 0.02 -1 -1 29584 -1 -1 1 2 0 0 success v8.0.0-12648-g259ceba57-dirty release IPO VTR_ASSERT_LEVEL=2 Clang 18.1.3 on Linux-6.8.0-58-generic x86_64 2025-05-06T12:34:13 betzgrp-wintermute /home/zhan6738/VTR/vtr-verilog-to-routing/vtr_flow/tasks 63000 2 1 3 4 1 3 4 3 3 9 -1 auto 22.9 MiB 0.00 6 6 9 6 0 3 61.5 MiB 0.00 0.00 16 5 1 30000 30000 2550.78 283.420 0.00 +k4_N10_memSize16384_memData64.xml ch_intrinsics.v common 1.07 vpr 64.88 MiB -1 -1 0.15 28236 3 0.06 -1 -1 36544 -1 -1 72 99 1 0 success v8.0.0-12799-g50a644d78 release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-10T17:21:16 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 66436 99 130 353 483 1 222 302 13 13 169 clb auto 25.3 MiB 0.03 1748.73 707 29650 4654 11713 13283 64.9 MiB 0.02 0.00 26 1506 9 3.33e+06 2.28e+06 360896. 2135.48 0.38 +k4_N10_memSize16384_memData64.xml diffeq1.v common 2.66 vpr 67.86 MiB -1 -1 0.19 32844 23 0.23 -1 -1 37316 -1 -1 74 162 0 5 success v8.0.0-12799-g50a644d78 release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-10T17:21:16 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 69484 162 96 1186 1127 1 667 337 13 13 169 clb auto 28.2 MiB 0.10 7906.16 4859 81205 21212 54650 5343 67.9 MiB 0.08 0.00 50 9091 14 3.33e+06 2.67e+06 641417. 3795.37 1.37 +k4_N10_memSize16384_memData64.xml single_wire.v common 0.31 vpr 62.98 MiB -1 -1 0.05 25804 1 0.01 -1 -1 33044 -1 -1 0 1 0 0 success v8.0.0-12799-g50a644d78 release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-10T17:21:16 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 64496 1 1 1 2 0 1 2 3 3 9 -1 auto 24.5 MiB 0.00 2 2 3 0 3 0 63.0 MiB 0.00 0.00 2 1 1 30000 0 1489.46 165.495 0.00 +k4_N10_memSize16384_memData64.xml single_ff.v common 0.41 vpr 63.02 MiB -1 -1 0.08 26064 1 0.01 -1 -1 33064 -1 -1 1 2 0 0 success v8.0.0-12799-g50a644d78 release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-10T17:21:16 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 64532 2 1 3 4 1 3 4 3 3 9 -1 auto 24.7 MiB 0.00 6 6 9 6 0 3 63.0 MiB 0.00 0.00 16 5 1 30000 30000 2550.78 283.420 0.00 diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_cin_tie_off/config/golden_results.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_cin_tie_off/config/golden_results.txt index 5f3bbb09c0f..768975e60b9 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_cin_tie_off/config/golden_results.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_cin_tie_off/config/golden_results.txt @@ -1,3 +1,3 @@ arch circuit script_params vtr_flow_elapsed_time vtr_max_mem_stage vtr_max_mem error odin_synth_time max_odin_mem parmys_synth_time max_parmys_mem abc_depth abc_synth_time abc_cec_time abc_sec_time max_abc_mem ace_time max_ace_mem num_clb num_io num_memories num_mult vpr_status vpr_revision vpr_build_info vpr_compiler vpr_compiled hostname rundir max_vpr_mem num_primary_inputs num_primary_outputs num_pre_packed_nets num_pre_packed_blocks num_netlist_clocks num_post_packed_nets num_post_packed_blocks device_width device_height device_grid_tiles device_limiting_resources device_name pack_mem pack_time initial_placed_wirelength_est placed_wirelength_est total_swap accepted_swap rejected_swap aborted_swap place_mem place_time place_quench_time initial_placed_CPD_est placed_CPD_est placed_setup_TNS_est placed_setup_WNS_est placed_geomean_nonvirtual_intradomain_critical_path_delay_est place_delay_matrix_lookup_time place_quench_timing_analysis_time place_quench_sta_time place_total_timing_analysis_time place_total_sta_time ap_mem ap_time ap_full_legalizer_mem ap_full_legalizer_time min_chan_width routed_wirelength min_chan_width_route_success_iteration logic_block_area_total logic_block_area_used min_chan_width_routing_area_total min_chan_width_routing_area_per_tile min_chan_width_route_time min_chan_width_total_timing_analysis_time min_chan_width_total_sta_time crit_path_num_rr_graph_nodes crit_path_num_rr_graph_edges crit_path_collapsed_nodes crit_path_routed_wirelength crit_path_route_success_iteration crit_path_total_nets_routed crit_path_total_connections_routed crit_path_total_heap_pushes crit_path_total_heap_pops critical_path_delay geomean_nonvirtual_intradomain_critical_path_delay setup_TNS setup_WNS hold_TNS hold_WNS crit_path_routing_area_total crit_path_routing_area_per_tile router_lookahead_computation_time crit_path_route_time crit_path_create_rr_graph_time crit_path_create_intra_cluster_rr_graph_time crit_path_tile_lookahead_computation_time crit_path_router_lookahead_computation_time crit_path_total_timing_analysis_time crit_path_total_sta_time num_le num_luts num_add_blocks max_add_chain_length num_sub_blocks max_sub_chain_length -k6_frac_N10_4add_2chains_tie_off_depop50_mem20K_22nm.xml mult_4x4.v common 1.12 vpr 64.71 MiB -1 -1 0.07 17596 1 0.02 -1 -1 30072 -1 -1 3 9 0 -1 success v8.0.0-12648-g259ceba57-dirty release IPO VTR_ASSERT_LEVEL=2 Clang 18.1.3 on Linux-6.8.0-58-generic x86_64 2025-05-06T12:34:13 betzgrp-wintermute /home/zhan6738/VTR/vtr-verilog-to-routing/vtr_flow/tasks 66268 9 8 75 70 1 34 20 5 5 25 clb auto 25.5 MiB 0.37 114 98 74 21 50 3 64.7 MiB 0.00 0.00 2.48207 2.48207 -27.0891 -2.48207 2.48207 0.01 0.000107575 9.8776e-05 0.00110372 0.00106107 -1 -1 -1 -1 38 138 12 151211 75605.7 48493.3 1939.73 0.06 0.0197476 0.0166644 2100 8065 -1 119 12 82 91 2625 1383 2.45975 2.45975 -29.6014 -2.45975 0 0 61632.8 2465.31 0.00 0.01 0.00 -1 -1 0.00 0.00468675 0.00431297 13 18 -1 -1 -1 -1 -k6_frac_N10_4add_2chains_tie_off_depop50_mem20K_22nm.xml mult_9x9.v common 4.60 vpr 65.51 MiB -1 -1 0.09 18364 1 0.03 -1 -1 30608 -1 -1 9 19 0 -1 success v8.0.0-12648-g259ceba57-dirty release IPO VTR_ASSERT_LEVEL=2 Clang 18.1.3 on Linux-6.8.0-58-generic x86_64 2025-05-06T12:34:13 betzgrp-wintermute /home/zhan6738/VTR/vtr-verilog-to-routing/vtr_flow/tasks 67084 19 18 308 249 1 135 46 6 6 36 clb auto 26.2 MiB 3.56 587 468 1358 299 1048 11 65.5 MiB 0.02 0.00 4.87574 4.8546 -99.0856 -4.8546 4.8546 0.02 0.000300463 0.000275416 0.00787823 0.00739934 -1 -1 -1 -1 40 1040 31 403230 226817 88484.8 2457.91 0.20 0.07778 0.0678958 3734 16003 -1 750 18 631 1001 35065 15346 5.69994 5.69994 -115.447 -5.69994 0 0 110337. 3064.92 0.00 0.02 0.01 -1 -1 0.00 0.0168321 0.0154848 54 83 -1 -1 -1 -1 +k6_frac_N10_4add_2chains_tie_off_depop50_mem20K_22nm.xml mult_4x4.v common 0.89 vpr 65.80 MiB -1 -1 0.05 27108 1 0.02 -1 -1 33612 -1 -1 3 9 0 -1 success v8.0.0-12803-g53682df9f release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-13T11:40:41 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 67384 9 8 75 70 1 34 20 5 5 25 clb auto 26.7 MiB 0.39 114.248 92 155 44 110 1 65.8 MiB 0.00 0.00 2.48207 2.48207 -27.0782 -2.48207 2.48207 0.01 7.1364e-05 6.3195e-05 0.00104595 0.00098359 -1 -1 -1 -1 38 140 10 151211 75605.7 48493.3 1939.73 0.04 0.0154863 0.0131988 2100 8065 -1 120 11 134 148 5218 2750 2.45975 2.45975 -29.8384 -2.45975 0 0 61632.8 2465.31 0.00 0.01 0.00 -1 -1 0.00 0.00364913 0.00339208 13 18 -1 -1 -1 -1 +k6_frac_N10_4add_2chains_tie_off_depop50_mem20K_22nm.xml mult_9x9.v common 4.56 vpr 66.91 MiB -1 -1 0.06 27748 1 0.02 -1 -1 34108 -1 -1 7 19 0 -1 success v8.0.0-12803-g53682df9f release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-13T11:40:41 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 68516 19 18 308 249 1 134 44 6 6 36 clb auto 27.5 MiB 3.68 555.076 430 2046 450 1581 15 66.9 MiB 0.02 0.00 4.92757 4.85986 -99.585 -4.85986 4.85986 0.02 0.000225507 0.000204339 0.0085582 0.00790585 -1 -1 -1 -1 58 765 33 403230 176413 123560. 3432.22 0.28 0.0977172 0.085077 4154 22415 -1 636 15 496 821 27967 11304 4.85226 4.85226 -102.581 -4.85226 0 0 154963. 4304.53 0.00 0.02 0.01 -1 -1 0.00 0.0135629 0.0126796 53 83 -1 -1 -1 -1 diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_cluster_seed_type/config/golden_results.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_cluster_seed_type/config/golden_results.txt index 1f4a52232c1..521cf95afcc 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_cluster_seed_type/config/golden_results.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_cluster_seed_type/config/golden_results.txt @@ -1,7 +1,7 @@ arch circuit script_params vtr_flow_elapsed_time vtr_max_mem_stage vtr_max_mem error odin_synth_time max_odin_mem parmys_synth_time max_parmys_mem abc_depth abc_synth_time abc_cec_time abc_sec_time max_abc_mem ace_time max_ace_mem num_clb num_io num_memories num_mult vpr_status vpr_revision vpr_build_info vpr_compiler vpr_compiled hostname rundir max_vpr_mem num_primary_inputs num_primary_outputs num_pre_packed_nets num_pre_packed_blocks num_netlist_clocks num_post_packed_nets num_post_packed_blocks device_width device_height device_grid_tiles device_limiting_resources device_name pack_mem pack_time initial_placed_wirelength_est placed_wirelength_est total_swap accepted_swap rejected_swap aborted_swap place_mem place_time place_quench_time initial_placed_CPD_est placed_CPD_est placed_setup_TNS_est placed_setup_WNS_est placed_geomean_nonvirtual_intradomain_critical_path_delay_est place_delay_matrix_lookup_time place_quench_timing_analysis_time place_quench_sta_time place_total_timing_analysis_time place_total_sta_time ap_mem ap_time ap_full_legalizer_mem ap_full_legalizer_time min_chan_width routed_wirelength min_chan_width_route_success_iteration logic_block_area_total logic_block_area_used min_chan_width_routing_area_total min_chan_width_routing_area_per_tile min_chan_width_route_time min_chan_width_total_timing_analysis_time min_chan_width_total_sta_time crit_path_num_rr_graph_nodes crit_path_num_rr_graph_edges crit_path_collapsed_nodes crit_path_routed_wirelength crit_path_route_success_iteration crit_path_total_nets_routed crit_path_total_connections_routed crit_path_total_heap_pushes crit_path_total_heap_pops critical_path_delay geomean_nonvirtual_intradomain_critical_path_delay setup_TNS setup_WNS hold_TNS hold_WNS crit_path_routing_area_total crit_path_routing_area_per_tile router_lookahead_computation_time crit_path_route_time crit_path_create_rr_graph_time crit_path_create_intra_cluster_rr_graph_time crit_path_tile_lookahead_computation_time crit_path_router_lookahead_computation_time crit_path_total_timing_analysis_time crit_path_total_sta_time -EArch.xml diffeq2.v common_--cluster_seed_type_blend 15.64 vpr 71.20 MiB -1 -1 0.22 24604 5 0.10 -1 -1 37404 -1 -1 19 66 0 5 success v8.0.0-12967-gc1fb06539f release VTR_ASSERT_LEVEL=3 GNU 13.3.0 on Linux-6.8.0-58-generic x86_64 2025-06-09T22:53:51 srivatsan-Precision-Tower-5810 /home/alex/vtr-verilog-to-routing 72904 66 96 778 595 1 450 186 16 16 256 mult_36 auto 32.1 MiB 0.68 6675.15 3790 44176 15630 27997 549 71.2 MiB 0.69 0.01 13.022 12.0577 -746.776 -12.0577 12.0577 0.56 0.00288518 0.00263477 0.267106 0.245392 -1 -1 -1 -1 44 10345 47 1.21132e+07 3.00399e+06 751766. 2936.59 11.60 1.22018 1.12261 27376 157980 -1 8309 20 4168 8066 1469857 405043 13.2731 13.2731 -895.158 -13.2731 0 0 979172. 3824.89 0.04 0.32 0.14 -1 -1 0.04 0.0762285 0.0707975 -EArch.xml diffeq2.v common_--cluster_seed_type_timing 10.43 vpr 70.56 MiB -1 -1 0.39 24604 5 0.09 -1 -1 37404 -1 -1 19 66 0 5 success v8.0.0-12967-gc1fb06539f release VTR_ASSERT_LEVEL=3 GNU 13.3.0 on Linux-6.8.0-58-generic x86_64 2025-06-09T22:53:51 srivatsan-Precision-Tower-5810 /home/alex/vtr-verilog-to-routing 72256 66 96 778 595 1 450 186 16 16 256 mult_36 auto 31.3 MiB 0.38 6015.41 3710 44176 13016 30202 958 70.6 MiB 0.34 0.01 12.9223 11.8949 -747.083 -11.8949 11.8949 0.32 0.00143517 0.0012914 0.135016 0.122517 -1 -1 -1 -1 62 8716 30 1.21132e+07 3.00399e+06 1.04918e+06 4098.38 7.36 0.813199 0.741128 30184 211102 -1 6880 22 3560 7162 1408754 410607 12.634 12.634 -828.912 -12.634 0 0 1.29183e+06 5046.22 0.05 0.32 0.19 -1 -1 0.05 0.0871991 0.0811534 -EArch.xml diffeq2.v common_--cluster_seed_type_max_inputs 11.71 vpr 70.27 MiB -1 -1 0.39 24432 5 0.10 -1 -1 37024 -1 -1 19 66 0 5 success v8.0.0-12967-gc1fb06539f release VTR_ASSERT_LEVEL=3 GNU 13.3.0 on Linux-6.8.0-58-generic x86_64 2025-06-09T22:53:51 srivatsan-Precision-Tower-5810 /home/alex/vtr-verilog-to-routing 71956 66 96 778 595 1 449 186 16 16 256 mult_36 auto 31.1 MiB 0.50 6049.48 3706 42056 11301 30225 530 70.3 MiB 0.33 0.01 12.7131 11.8714 -738.04 -11.8714 11.8714 0.32 0.00165678 0.00150511 0.130607 0.118453 -1 -1 -1 -1 52 8409 27 1.21132e+07 3.00399e+06 870783. 3401.49 8.56 0.872075 0.794724 28652 182587 -1 7517 22 2952 5864 1148041 333936 13.03 13.03 -852.047 -13.03 0 0 1.14646e+06 4478.35 0.05 0.29 0.16 -1 -1 0.05 0.0863763 0.0803076 -EArch.xml diffeq2.v common_--cluster_seed_type_max_pins 11.70 vpr 71.11 MiB -1 -1 0.39 24604 5 0.16 -1 -1 37404 -1 -1 18 66 0 5 success v8.0.0-12967-gc1fb06539f release VTR_ASSERT_LEVEL=3 GNU 13.3.0 on Linux-6.8.0-58-generic x86_64 2025-06-09T22:53:51 srivatsan-Precision-Tower-5810 /home/alex/vtr-verilog-to-routing 72820 66 96 778 595 1 451 185 16 16 256 mult_36 auto 32.0 MiB 0.78 6111.16 3608 38057 10673 26480 904 71.1 MiB 0.56 0.01 12.9974 12.169 -743.127 -12.169 12.169 0.55 0.00297039 0.00273122 0.225542 0.207494 -1 -1 -1 -1 60 8768 20 1.21132e+07 2.95009e+06 1.01260e+06 3955.47 7.39 1.13909 1.05271 29928 206364 -1 7378 21 2689 5009 919027 265897 12.9752 12.9752 -842.836 -12.9752 0 0 1.26536e+06 4942.82 0.05 0.24 0.19 -1 -1 0.05 0.0830927 0.0772513 -EArch.xml diffeq2.v common_--cluster_seed_type_max_input_pins 17.18 vpr 71.23 MiB -1 -1 0.39 24688 5 0.16 -1 -1 37280 -1 -1 18 66 0 5 success v8.0.0-12967-gc1fb06539f release VTR_ASSERT_LEVEL=3 GNU 13.3.0 on Linux-6.8.0-58-generic x86_64 2025-06-09T22:53:51 srivatsan-Precision-Tower-5810 /home/alex/vtr-verilog-to-routing 72944 66 96 778 595 1 451 185 16 16 256 mult_36 auto 31.9 MiB 0.82 6031.25 4018 37005 11119 25078 808 71.2 MiB 0.54 0.01 12.9974 11.878 -748.86 -11.878 11.878 0.56 0.00305051 0.00280179 0.220974 0.203118 -1 -1 -1 -1 52 9339 48 1.21132e+07 2.95009e+06 870783. 3401.49 12.89 1.20118 1.1032 28652 182587 -1 7851 20 3011 5787 1219158 361977 12.9938 12.9938 -855.957 -12.9938 0 0 1.14646e+06 4478.35 0.05 0.28 0.16 -1 -1 0.05 0.0762721 0.0707323 -EArch.xml diffeq2.v common_--cluster_seed_type_blend2 14.36 vpr 71.31 MiB -1 -1 0.21 24608 5 0.10 -1 -1 37280 -1 -1 19 66 0 5 success v8.0.0-12967-gc1fb06539f release VTR_ASSERT_LEVEL=3 GNU 13.3.0 on Linux-6.8.0-58-generic x86_64 2025-06-09T22:53:51 srivatsan-Precision-Tower-5810 /home/alex/vtr-verilog-to-routing 73020 66 96 778 595 1 450 186 16 16 256 mult_36 auto 32.2 MiB 0.68 6783.04 3667 45236 13440 30583 1213 71.3 MiB 0.64 0.01 13.8108 11.9163 -742.181 -11.9163 11.9163 0.55 0.00286798 0.00263061 0.271337 0.249766 -1 -1 -1 -1 50 9502 49 1.21132e+07 3.00399e+06 843554. 3295.13 10.40 1.36875 1.26045 28144 172338 -1 7445 21 3518 7008 1194202 366119 13.1722 13.1722 -849.129 -13.1722 0 0 1.08719e+06 4246.82 0.04 0.28 0.15 -1 -1 0.04 0.0815325 0.0757153 +EArch.xml diffeq2.v common_--cluster_seed_type_blend 7.77 vpr 70.11 MiB -1 -1 0.13 30276 4 0.09 -1 -1 37792 -1 -1 22 66 0 5 success v8.0.0-12803-g53682df9f release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-13T11:40:41 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 71792 66 96 778 595 1 467 189 16 16 256 mult_36 auto 30.9 MiB 0.18 6722.15 3891 46259 15236 26537 4486 70.1 MiB 0.21 0.00 13.5168 11.9463 -726.84 -11.9463 11.9463 0.17 0.000859881 0.000798767 0.0863921 0.0798929 -1 -1 -1 -1 50 9393 37 1.21132e+07 3.16567e+06 843554. 3295.13 5.97 0.44117 0.406703 28144 172338 -1 8041 25 4342 9182 1554645 412555 13.3426 13.3426 -843.398 -13.3426 0 0 1.08719e+06 4246.82 0.03 0.23 0.08 -1 -1 0.03 0.0535264 0.0503363 +EArch.xml diffeq2.v common_--cluster_seed_type_timing 6.38 vpr 70.26 MiB -1 -1 0.13 30528 4 0.09 -1 -1 37520 -1 -1 22 66 0 5 success v8.0.0-12803-g53682df9f release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-13T11:40:41 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 71944 66 96 778 595 1 467 189 16 16 256 mult_36 auto 31.2 MiB 0.17 6551.83 3838 46801 14809 27260 4732 70.3 MiB 0.20 0.00 12.92 11.8188 -739.714 -11.8188 11.8188 0.17 0.000840177 0.000779322 0.0790155 0.0732691 -1 -1 -1 -1 50 10463 42 1.21132e+07 3.16567e+06 843554. 3295.13 4.51 0.457076 0.422458 28144 172338 -1 8387 41 5076 10467 1996440 537771 13.1972 13.1972 -879.638 -13.1972 0 0 1.08719e+06 4246.82 0.03 0.32 0.08 -1 -1 0.03 0.0798874 0.0744191 +EArch.xml diffeq2.v common_--cluster_seed_type_max_inputs 7.20 vpr 70.34 MiB -1 -1 0.12 30656 4 0.09 -1 -1 37772 -1 -1 22 66 0 5 success v8.0.0-12803-g53682df9f release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-13T11:40:41 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 72032 66 96 778 595 1 464 189 16 16 256 mult_36 auto 31.3 MiB 0.25 6680.33 3925 37045 11183 22036 3826 70.3 MiB 0.17 0.00 13.2078 11.9632 -729.997 -11.9632 11.9632 0.16 0.000875262 0.000812788 0.0668861 0.0621859 -1 -1 -1 -1 52 9408 33 1.21132e+07 3.16567e+06 870783. 3401.49 5.41 0.430744 0.397471 28652 182587 -1 8138 20 3194 6396 1293703 361722 12.8462 12.8462 -830.388 -12.8462 0 0 1.14646e+06 4478.35 0.03 0.20 0.08 -1 -1 0.03 0.0458738 0.0432342 +EArch.xml diffeq2.v common_--cluster_seed_type_max_pins 7.55 vpr 70.20 MiB -1 -1 0.13 30400 4 0.08 -1 -1 37520 -1 -1 22 66 0 5 success v8.0.0-12803-g53682df9f release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-13T11:40:41 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 71884 66 96 778 595 1 464 189 16 16 256 mult_36 auto 30.9 MiB 0.23 6732.23 3752 39755 12672 22689 4394 70.2 MiB 0.17 0.00 13.2056 11.8674 -727.569 -11.8674 11.8674 0.18 0.000872064 0.000808698 0.0715952 0.0665154 -1 -1 -1 -1 52 9250 27 1.21132e+07 3.16567e+06 870783. 3401.49 5.74 0.447948 0.413218 28652 182587 -1 7736 22 2979 5812 1155240 362581 13.0686 13.0686 -838.735 -13.0686 0 0 1.14646e+06 4478.35 0.03 0.19 0.09 -1 -1 0.03 0.0490747 0.046101 +EArch.xml diffeq2.v common_--cluster_seed_type_max_input_pins 7.36 vpr 70.11 MiB -1 -1 0.12 30528 4 0.08 -1 -1 37772 -1 -1 22 66 0 5 success v8.0.0-12803-g53682df9f release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-13T11:40:41 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 71796 66 96 778 595 1 464 189 16 16 256 mult_36 auto 31.0 MiB 0.22 6715.25 3821 40297 13390 22454 4453 70.1 MiB 0.17 0.00 13.2056 11.8674 -725.598 -11.8674 11.8674 0.18 0.000846957 0.00078446 0.0716309 0.0664961 -1 -1 -1 -1 50 10106 49 1.21132e+07 3.16567e+06 843554. 3295.13 5.54 0.517553 0.477711 28144 172338 -1 8142 24 3444 6839 1323290 405007 13.0114 13.0114 -845.755 -13.0114 0 0 1.08719e+06 4246.82 0.03 0.23 0.08 -1 -1 0.03 0.056047 0.052474 +EArch.xml diffeq2.v common_--cluster_seed_type_blend2 8.81 vpr 70.51 MiB -1 -1 0.12 30272 4 0.08 -1 -1 37516 -1 -1 22 66 0 5 success v8.0.0-12803-g53682df9f release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-13T11:40:41 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 72200 66 96 778 595 1 467 189 16 16 256 mult_36 auto 31.2 MiB 0.17 7184.04 3684 46259 15600 25711 4948 70.5 MiB 0.19 0.00 13.8986 11.944 -730.881 -11.944 11.944 0.17 0.000832081 0.000772639 0.078257 0.0727817 -1 -1 -1 -1 48 10862 50 1.21132e+07 3.16567e+06 817991. 3195.28 7.00 0.427889 0.394385 27888 167588 -1 8045 27 4765 10132 1863741 545928 13.4757 13.4757 -892.652 -13.4757 0 0 1.04918e+06 4098.38 0.03 0.28 0.08 -1 -1 0.03 0.0577349 0.0541417 diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_diff_mux_for_inc_dec_wires/config/golden_results.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_diff_mux_for_inc_dec_wires/config/golden_results.txt index eb67e75c426..492cbdbb15f 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_diff_mux_for_inc_dec_wires/config/golden_results.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_diff_mux_for_inc_dec_wires/config/golden_results.txt @@ -1,3 +1,3 @@ arch circuit script_params vtr_flow_elapsed_time vtr_max_mem_stage vtr_max_mem error odin_synth_time max_odin_mem parmys_synth_time max_parmys_mem abc_depth abc_synth_time abc_cec_time abc_sec_time max_abc_mem ace_time max_ace_mem num_clb num_io num_memories num_mult vpr_status vpr_revision vpr_build_info vpr_compiler vpr_compiled hostname rundir max_vpr_mem num_primary_inputs num_primary_outputs num_pre_packed_nets num_pre_packed_blocks num_netlist_clocks num_post_packed_nets num_post_packed_blocks device_width device_height device_grid_tiles device_limiting_resources device_name pack_mem pack_time initial_placed_wirelength_est placed_wirelength_est total_swap accepted_swap rejected_swap aborted_swap place_mem place_time place_quench_time initial_placed_CPD_est placed_CPD_est placed_setup_TNS_est placed_setup_WNS_est placed_geomean_nonvirtual_intradomain_critical_path_delay_est place_delay_matrix_lookup_time place_quench_timing_analysis_time place_quench_sta_time place_total_timing_analysis_time place_total_sta_time ap_mem ap_time ap_full_legalizer_mem ap_full_legalizer_time min_chan_width routed_wirelength min_chan_width_route_success_iteration logic_block_area_total logic_block_area_used min_chan_width_routing_area_total min_chan_width_routing_area_per_tile min_chan_width_route_time min_chan_width_total_timing_analysis_time min_chan_width_total_sta_time crit_path_num_rr_graph_nodes crit_path_num_rr_graph_edges crit_path_collapsed_nodes crit_path_routed_wirelength crit_path_route_success_iteration crit_path_total_nets_routed crit_path_total_connections_routed crit_path_total_heap_pushes crit_path_total_heap_pops critical_path_delay geomean_nonvirtual_intradomain_critical_path_delay setup_TNS setup_WNS hold_TNS hold_WNS crit_path_routing_area_total crit_path_routing_area_per_tile router_lookahead_computation_time crit_path_route_time crit_path_create_rr_graph_time crit_path_create_intra_cluster_rr_graph_time crit_path_tile_lookahead_computation_time crit_path_router_lookahead_computation_time crit_path_total_timing_analysis_time crit_path_total_sta_time -k6_N10_40nm.xml stereovision0.v common 72.53 vpr 246.70 MiB -1 -1 8.23 120932 5 28.98 -1 -1 65024 -1 -1 1352 169 -1 -1 success v8.0.0-12648-g259ceba57-dirty release IPO VTR_ASSERT_LEVEL=2 Clang 18.1.3 on Linux-6.8.0-58-generic x86_64 2025-05-06T12:34:13 betzgrp-wintermute /home/zhan6738/VTR/vtr-verilog-to-routing/vtr_flow/tasks 252616 169 197 21117 21314 1 6509 1718 39 39 1521 clb auto 132.6 MiB 3.02 188600 47945 958223 329930 610922 17371 246.7 MiB 6.36 0.07 7.48908 3.85395 -15165.3 -3.85395 3.85395 3.42 0.0181451 0.0155648 1.86364 1.5515 -1 -1 -1 -1 36 61910 50 2.4642e+07 2.4336e+07 4.11737e+06 2707.01 12.81 6.8221 5.66675 115990 821377 -1 57410 21 30914 66833 2643745 477357 3.6821 3.6821 -15912.4 -3.6821 0 0 5.03985e+06 3313.51 0.18 1.66 0.40 -1 -1 0.18 1.17936 1.0401 -k6_N10_40nm_diff_switch_for_inc_dec_wires.xml stereovision0.v common 70.91 vpr 248.29 MiB -1 -1 7.52 121112 5 28.19 -1 -1 65024 -1 -1 1363 169 -1 -1 success v8.0.0-12648-g259ceba57-dirty release IPO VTR_ASSERT_LEVEL=2 Clang 18.1.3 on Linux-6.8.0-58-generic x86_64 2025-05-06T12:34:13 betzgrp-wintermute /home/zhan6738/VTR/vtr-verilog-to-routing/vtr_flow/tasks 254252 169 197 21117 21314 1 6565 1729 39 39 1521 clb auto 131.8 MiB 2.87 190099 51107 987164 353007 612737 21420 248.3 MiB 6.23 0.06 9.87654 3.59906 -14959.3 -3.59906 3.59906 3.27 0.0160602 0.0137781 1.82077 1.51774 -1 -1 -1 -1 38 67057 39 7.37824e+07 7.3459e+07 4.16760e+06 2740.04 13.11 6.23411 5.17893 119030 845795 -1 61286 30 33152 70295 2804113 519856 3.34587 3.34587 -15492.9 -3.34587 0 0 5.22668e+06 3436.35 0.18 1.99 0.42 -1 -1 0.18 1.42002 1.25013 +k6_N10_40nm.xml stereovision0.v common 56.80 vpr 262.38 MiB -1 -1 4.78 124120 5 14.93 -1 -1 69252 -1 -1 1378 169 -1 -1 success v8.0.0-12803-g53682df9f release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-13T11:40:41 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 268672 169 197 21353 21550 1 6641 1744 40 40 1600 clb auto 135.6 MiB 3.13 196542 49632 998579 348826 629739 20014 262.4 MiB 5.97 0.07 9.18492 4.17823 -16108.4 -4.17823 4.17823 2.84 0.0126732 0.010553 1.38908 1.1369 -1 -1 -1 -1 40 62686 43 2.5992e+07 2.4804e+07 4.69761e+06 2936.01 16.69 7.59565 6.30478 126844 962625 -1 59483 20 29424 63880 2562291 448912 4.36855 4.36855 -16884.5 -4.36855 0 0 5.88705e+06 3679.40 0.20 1.18 0.43 -1 -1 0.20 0.866729 0.776807 +k6_N10_40nm_diff_switch_for_inc_dec_wires.xml stereovision0.v common 56.28 vpr 241.62 MiB -1 -1 4.67 123360 5 14.39 -1 -1 69516 -1 -1 1395 169 -1 -1 success v8.0.0-12803-g53682df9f release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-13T11:40:41 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 247420 169 197 21353 21550 1 6728 1761 40 40 1600 clb auto 135.4 MiB 3.08 201893 52706 1032871 365463 646816 20592 241.2 MiB 6.21 0.06 8.95263 3.62361 -15063.3 -3.62361 3.62361 3.00 0.0121626 0.0100032 1.42449 1.16028 -1 -1 -1 -1 42 66494 39 7.78246e+07 7.51837e+07 4.73427e+06 2958.92 16.23 7.57973 6.24979 128444 955862 -1 63179 24 32153 72795 2778365 503801 3.42381 3.42381 -15716.6 -3.42381 0 0 5.90781e+06 3692.38 0.20 1.39 0.44 -1 -1 0.20 0.987378 0.877839 diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_routing_constraints/config/golden_results.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_routing_constraints/config/golden_results.txt index 30111b74667..81c0e03b9ea 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_routing_constraints/config/golden_results.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_routing_constraints/config/golden_results.txt @@ -1,7 +1,7 @@ arch circuit script_params vtr_flow_elapsed_time vtr_max_mem_stage vtr_max_mem error odin_synth_time max_odin_mem parmys_synth_time max_parmys_mem abc_depth abc_synth_time abc_cec_time abc_sec_time max_abc_mem ace_time max_ace_mem num_clb num_io num_memories num_mult vpr_status vpr_revision vpr_build_info vpr_compiler vpr_compiled hostname rundir max_vpr_mem num_primary_inputs num_primary_outputs num_pre_packed_nets num_pre_packed_blocks num_netlist_clocks num_post_packed_nets num_post_packed_blocks device_width device_height device_grid_tiles device_limiting_resources device_name pack_mem pack_time initial_placed_wirelength_est placed_wirelength_est total_swap accepted_swap rejected_swap aborted_swap place_mem place_time place_quench_time initial_placed_CPD_est placed_CPD_est placed_setup_TNS_est placed_setup_WNS_est placed_geomean_nonvirtual_intradomain_critical_path_delay_est place_delay_matrix_lookup_time place_quench_timing_analysis_time place_quench_sta_time place_total_timing_analysis_time place_total_sta_time ap_mem ap_time ap_full_legalizer_mem ap_full_legalizer_time min_chan_width routed_wirelength min_chan_width_route_success_iteration logic_block_area_total logic_block_area_used min_chan_width_routing_area_total min_chan_width_routing_area_per_tile min_chan_width_route_time min_chan_width_total_timing_analysis_time min_chan_width_total_sta_time crit_path_num_rr_graph_nodes crit_path_num_rr_graph_edges crit_path_collapsed_nodes crit_path_routed_wirelength crit_path_route_success_iteration crit_path_total_nets_routed crit_path_total_connections_routed crit_path_total_heap_pushes crit_path_total_heap_pops critical_path_delay geomean_nonvirtual_intradomain_critical_path_delay setup_TNS setup_WNS hold_TNS hold_WNS crit_path_routing_area_total crit_path_routing_area_per_tile router_lookahead_computation_time crit_path_route_time crit_path_create_rr_graph_time crit_path_create_intra_cluster_rr_graph_time crit_path_tile_lookahead_computation_time crit_path_router_lookahead_computation_time crit_path_total_timing_analysis_time crit_path_total_sta_time num_global_nets num_routed_nets -timing/k6_frac_N10_frac_chain_mem32K_htree0_40nm.xml verilog/multiclock_output_and_latch.v common_--target_utilization_0.01_--two_stage_clock_routing_-read_vpr_constraints_tasks/regression_tests/vtr_reg_strong/strong_routing_constraints/multi_clock_routing_constraints.xml_--clock_modeling_dedicated_network 1.46 vpr 65.00 MiB -1 -1 0.08 17308 1 0.04 -1 -1 31584 -1 -1 2 6 0 0 success v8.0.0-12648-g259ceba57-dirty release IPO VTR_ASSERT_LEVEL=2 Clang 18.1.3 on Linux-6.8.0-58-generic x86_64 2025-05-06T12:34:13 betzgrp-wintermute /home/zhan6738/VTR/vtr-verilog-to-routing/vtr_flow/tasks 66564 6 1 16 17 2 10 9 17 17 289 -1 auto 26.4 MiB 0.01 128 30 162 45 109 8 65.0 MiB 0.00 0.00 2.32203 1.4327 -4.13089 -1.4327 0.805 0.21 2.6931e-05 1.6557e-05 0.000584509 0.000451852 -1 -1 -1 -1 20 95 2 1.34605e+07 107788 411619. 1424.29 0.15 0.00187029 0.00164769 24098 82050 -1 103 2 14 14 8045 3790 2.67718 0.805 -5.78255 -2.67718 -1.39285 -0.696976 535376. 1852.51 0.02 0.07 0.04 -1 -1 0.02 0.00128046 0.00121058 1 9 -timing/k6_frac_N10_frac_chain_mem32K_htree0_40nm.xml verilog/and_latch.v common_--target_utilization_0.01_--two_stage_clock_routing_-read_vpr_constraints_tasks/regression_tests/vtr_reg_strong/strong_routing_constraints/multi_clock_routing_constraints.xml_--clock_modeling_dedicated_network 0.95 vpr 64.76 MiB -1 -1 0.07 17312 1 0.02 -1 -1 29984 -1 -1 1 3 0 0 success v8.0.0-12648-g259ceba57-dirty release IPO VTR_ASSERT_LEVEL=2 Clang 18.1.3 on Linux-6.8.0-58-generic x86_64 2025-05-06T12:34:13 betzgrp-wintermute /home/zhan6738/VTR/vtr-verilog-to-routing/vtr_flow/tasks 66316 3 1 5 6 1 4 5 13 13 169 -1 auto 26.5 MiB 0.00 38 25 12 5 6 1 64.8 MiB 0.00 0.00 1.12186 0.96686 -1.43992 -0.96686 0.96686 0.11 1.176e-05 7.373e-06 9.5504e-05 7.1942e-05 -1 -1 -1 -1 20 46 1 6.63067e+06 53894 227243. 1344.63 0.08 0.00102566 0.000948714 13251 44387 -1 49 1 4 4 2037 1117 1.60624 1.60624 -1.60624 -1.60624 -0.386566 -0.386566 294987. 1745.49 0.01 0.04 0.02 -1 -1 0.01 0.000916629 0.000875809 0 4 -timing/k6_frac_N10_frac_chain_mem32K_htree0_routedCLK_40nm.xml verilog/multiclock_output_and_latch.v common_--target_utilization_0.01_--two_stage_clock_routing_-read_vpr_constraints_tasks/regression_tests/vtr_reg_strong/strong_routing_constraints/multi_clock_routing_constraints.xml_--clock_modeling_dedicated_network 1.43 vpr 65.00 MiB -1 -1 0.08 17312 1 0.03 -1 -1 31592 -1 -1 2 6 0 0 success v8.0.0-12648-g259ceba57-dirty release IPO VTR_ASSERT_LEVEL=2 Clang 18.1.3 on Linux-6.8.0-58-generic x86_64 2025-05-06T12:34:13 betzgrp-wintermute /home/zhan6738/VTR/vtr-verilog-to-routing/vtr_flow/tasks 66556 6 1 16 17 2 10 9 17 17 289 -1 auto 26.4 MiB 0.01 128 30 162 45 109 8 65.0 MiB 0.00 0.00 2.32504 1.43377 -4.13192 -1.43377 0.805 0.21 2.2762e-05 1.6724e-05 0.000573962 0.000444673 -1 -1 -1 -1 20 96 2 1.34605e+07 107788 424167. 1467.71 0.15 0.00187733 0.00165636 24098 84646 -1 93 2 14 14 7618 3614 2.36211 0.805 -5.14799 -2.36211 -1.39063 -0.695869 547923. 1895.93 0.02 0.07 0.04 -1 -1 0.02 0.0012306 0.00116318 1 9 -timing/k6_frac_N10_frac_chain_mem32K_htree0_routedCLK_40nm.xml verilog/and_latch.v common_--target_utilization_0.01_--two_stage_clock_routing_-read_vpr_constraints_tasks/regression_tests/vtr_reg_strong/strong_routing_constraints/multi_clock_routing_constraints.xml_--clock_modeling_dedicated_network 0.98 vpr 64.72 MiB -1 -1 0.06 17312 1 0.02 -1 -1 29240 -1 -1 1 3 0 0 success v8.0.0-12648-g259ceba57-dirty release IPO VTR_ASSERT_LEVEL=2 Clang 18.1.3 on Linux-6.8.0-58-generic x86_64 2025-05-06T12:34:13 betzgrp-wintermute /home/zhan6738/VTR/vtr-verilog-to-routing/vtr_flow/tasks 66272 3 1 5 6 1 4 5 13 13 169 -1 auto 25.9 MiB 0.00 38 25 12 5 6 1 64.7 MiB 0.00 0.00 1.12186 0.96686 -1.43992 -0.96686 0.96686 0.11 2.7322e-05 6.969e-06 0.000108399 6.8796e-05 -1 -1 -1 -1 20 50 1 6.63067e+06 53894 235789. 1395.20 0.08 0.00104947 0.000960311 13251 46155 -1 48 1 4 4 2008 1087 1.59583 1.59583 -1.59583 -1.59583 -0.386566 -0.386566 303533. 1796.05 0.01 0.04 0.02 -1 -1 0.01 0.000933815 0.000894029 0 4 -timing/k6_frac_N10_frac_chain_mem32K_htree0short_40nm.xml verilog/multiclock_output_and_latch.v common_--target_utilization_0.01_--two_stage_clock_routing_-read_vpr_constraints_tasks/regression_tests/vtr_reg_strong/strong_routing_constraints/multi_clock_routing_constraints.xml_--clock_modeling_dedicated_network 1.43 vpr 65.00 MiB -1 -1 0.08 17308 1 0.03 -1 -1 31608 -1 -1 2 6 0 0 success v8.0.0-12648-g259ceba57-dirty release IPO VTR_ASSERT_LEVEL=2 Clang 18.1.3 on Linux-6.8.0-58-generic x86_64 2025-05-06T12:34:13 betzgrp-wintermute /home/zhan6738/VTR/vtr-verilog-to-routing/vtr_flow/tasks 66560 6 1 16 17 2 10 9 17 17 289 -1 auto 26.8 MiB 0.01 128 30 162 45 109 8 65.0 MiB 0.00 0.00 2.32203 1.4327 -4.13089 -1.4327 0.805 0.21 2.2521e-05 1.65e-05 0.000581369 0.000454157 -1 -1 -1 -1 20 573 2 1.34605e+07 107788 408865. 1414.76 0.14 0.00184821 0.00163011 24098 82150 -1 581 2 13 13 6290 3262 3.57936 0.805 -7.58692 -3.57936 -3.19721 -1.59916 532630. 1843.01 0.02 0.07 0.04 -1 -1 0.02 0.00119849 0.00113118 1 9 -timing/k6_frac_N10_frac_chain_mem32K_htree0short_40nm.xml verilog/and_latch.v common_--target_utilization_0.01_--two_stage_clock_routing_-read_vpr_constraints_tasks/regression_tests/vtr_reg_strong/strong_routing_constraints/multi_clock_routing_constraints.xml_--clock_modeling_dedicated_network 1.00 vpr 65.00 MiB -1 -1 0.07 17308 1 0.02 -1 -1 29972 -1 -1 1 3 0 0 success v8.0.0-12648-g259ceba57-dirty release IPO VTR_ASSERT_LEVEL=2 Clang 18.1.3 on Linux-6.8.0-58-generic x86_64 2025-05-06T12:34:13 betzgrp-wintermute /home/zhan6738/VTR/vtr-verilog-to-routing/vtr_flow/tasks 66560 3 1 5 6 1 4 5 13 13 169 -1 auto 26.8 MiB 0.00 38 25 12 5 6 1 65.0 MiB 0.00 0.00 1.12186 0.96686 -1.43992 -0.96686 0.96686 0.12 1.2422e-05 7.808e-06 9.6046e-05 7.2011e-05 -1 -1 -1 -1 20 177 1 6.63067e+06 53894 225153. 1332.26 0.08 0.00102812 0.000944896 13251 44463 -1 180 1 4 4 885 322 2.22548 2.22548 -2.22548 -2.22548 -1.0058 -1.0058 292904. 1733.16 0.01 0.04 0.02 -1 -1 0.01 0.000967633 0.00090832 0 4 +timing/k6_frac_N10_frac_chain_mem32K_htree0_40nm.xml verilog/multiclock_output_and_latch.v common_--target_utilization_0.01_--two_stage_clock_routing_-read_vpr_constraints_tasks/regression_tests/vtr_reg_strong/strong_routing_constraints/multi_clock_routing_constraints.xml_--clock_modeling_dedicated_network 1.12 vpr 66.68 MiB -1 -1 0.06 26836 1 0.03 -1 -1 35768 -1 -1 2 6 0 0 success v8.0.0-12803-g53682df9f release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-13T11:40:41 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 68284 6 1 16 17 2 10 9 17 17 289 -1 auto 28.3 MiB 0.01 118 71 27 13 14 0 66.7 MiB 0.00 0.00 2.15593 1.81373 -4.90335 -1.81373 0.805 0.18 3.9972e-05 3.3363e-05 0.00020106 0.000171531 -1 -1 -1 -1 20 126 3 1.34605e+07 107788 411619. 1424.29 0.14 0.00142296 0.00127231 24098 82050 -1 124 2 10 10 4740 1924 2.44995 0.805 -5.31064 -2.44995 -0.657256 -0.367156 535376. 1852.51 0.02 0.06 0.04 -1 -1 0.02 0.00107316 0.00101955 1 9 +timing/k6_frac_N10_frac_chain_mem32K_htree0_40nm.xml verilog/and_latch.v common_--target_utilization_0.01_--two_stage_clock_routing_-read_vpr_constraints_tasks/regression_tests/vtr_reg_strong/strong_routing_constraints/multi_clock_routing_constraints.xml_--clock_modeling_dedicated_network 0.74 vpr 66.75 MiB -1 -1 0.05 26836 1 0.01 -1 -1 33804 -1 -1 1 3 0 0 success v8.0.0-12803-g53682df9f release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-13T11:40:41 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 68348 3 1 5 6 1 4 5 13 13 169 -1 auto 28.3 MiB 0.00 38 25 12 6 6 0 66.7 MiB 0.00 0.00 1.29226 1.06427 -1.32032 -1.06427 1.06427 0.10 1.7571e-05 1.0314e-05 8.4903e-05 6.2361e-05 -1 -1 -1 -1 20 44 2 6.63067e+06 53894 227243. 1344.63 0.09 0.000941255 0.000871294 13251 44387 -1 45 1 4 4 2400 1643 1.76603 1.76603 -1.76603 -1.76603 -0.685145 -0.685145 294987. 1745.49 0.01 0.04 0.02 -1 -1 0.01 0.000862466 0.000838856 0 4 +timing/k6_frac_N10_frac_chain_mem32K_htree0_routedCLK_40nm.xml verilog/multiclock_output_and_latch.v common_--target_utilization_0.01_--two_stage_clock_routing_-read_vpr_constraints_tasks/regression_tests/vtr_reg_strong/strong_routing_constraints/multi_clock_routing_constraints.xml_--clock_modeling_dedicated_network 1.13 vpr 67.06 MiB -1 -1 0.06 26812 1 0.03 -1 -1 35900 -1 -1 2 6 0 0 success v8.0.0-12803-g53682df9f release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-13T11:40:41 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 68668 6 1 16 17 2 10 9 17 17 289 -1 auto 28.7 MiB 0.01 118 71 27 13 14 0 67.1 MiB 0.00 0.00 2.15759 1.81595 -4.90722 -1.81595 0.805 0.19 2.5093e-05 1.8349e-05 0.000186523 0.000155431 -1 -1 -1 -1 20 126 3 1.34605e+07 107788 424167. 1467.71 0.14 0.00140027 0.00128386 24098 84646 -1 124 2 11 11 6930 2763 2.46633 0.805 -5.34451 -2.46633 -0.656149 -0.367155 547923. 1895.93 0.02 0.06 0.04 -1 -1 0.02 0.00104446 0.000992013 1 9 +timing/k6_frac_N10_frac_chain_mem32K_htree0_routedCLK_40nm.xml verilog/and_latch.v common_--target_utilization_0.01_--two_stage_clock_routing_-read_vpr_constraints_tasks/regression_tests/vtr_reg_strong/strong_routing_constraints/multi_clock_routing_constraints.xml_--clock_modeling_dedicated_network 0.75 vpr 66.80 MiB -1 -1 0.06 26964 1 0.01 -1 -1 33720 -1 -1 1 3 0 0 success v8.0.0-12803-g53682df9f release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-13T11:40:41 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 68408 3 1 5 6 1 4 5 13 13 169 -1 auto 28.3 MiB 0.00 38 25 12 6 6 0 66.8 MiB 0.00 0.00 1.29226 1.06427 -1.32032 -1.06427 1.06427 0.10 1.1976e-05 7.638e-06 8.2232e-05 6.3068e-05 -1 -1 -1 -1 20 41 2 6.63067e+06 53894 235789. 1395.20 0.08 0.000930329 0.000867297 13251 46155 -1 53 1 4 4 2622 1701 2.05791 2.05791 -2.05791 -2.05791 -0.685145 -0.685145 303533. 1796.05 0.01 0.04 0.02 -1 -1 0.01 0.000809155 0.000785008 0 4 +timing/k6_frac_N10_frac_chain_mem32K_htree0short_40nm.xml verilog/multiclock_output_and_latch.v common_--target_utilization_0.01_--two_stage_clock_routing_-read_vpr_constraints_tasks/regression_tests/vtr_reg_strong/strong_routing_constraints/multi_clock_routing_constraints.xml_--clock_modeling_dedicated_network 1.14 vpr 66.93 MiB -1 -1 0.05 26836 1 0.03 -1 -1 35772 -1 -1 2 6 0 0 success v8.0.0-12803-g53682df9f release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-13T11:40:41 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 68536 6 1 16 17 2 10 9 17 17 289 -1 auto 28.5 MiB 0.01 118 71 27 13 14 0 66.9 MiB 0.00 0.00 2.15593 1.81373 -4.90335 -1.81373 0.805 0.19 4.0238e-05 3.3628e-05 0.000195866 0.000165856 -1 -1 -1 -1 20 604 3 1.34605e+07 107788 408865. 1414.76 0.15 0.00137068 0.0012537 24098 82150 -1 602 2 10 10 5274 2200 3.39125 0.805 -7.19406 -3.39125 -2.53986 -1.30846 532630. 1843.01 0.02 0.06 0.04 -1 -1 0.02 0.00108698 0.00103557 1 9 +timing/k6_frac_N10_frac_chain_mem32K_htree0short_40nm.xml verilog/and_latch.v common_--target_utilization_0.01_--two_stage_clock_routing_-read_vpr_constraints_tasks/regression_tests/vtr_reg_strong/strong_routing_constraints/multi_clock_routing_constraints.xml_--clock_modeling_dedicated_network 0.73 vpr 67.05 MiB -1 -1 0.05 26952 1 0.01 -1 -1 33808 -1 -1 1 3 0 0 success v8.0.0-12803-g53682df9f release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-13T11:40:41 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 68664 3 1 5 6 1 4 5 13 13 169 -1 auto 28.7 MiB 0.00 38 25 12 6 6 0 67.1 MiB 0.00 0.00 1.29226 1.06427 -1.32032 -1.06427 1.06427 0.10 1.1582e-05 7.332e-06 7.7384e-05 5.8792e-05 -1 -1 -1 -1 20 175 2 6.63067e+06 53894 225153. 1332.26 0.08 0.000947248 0.000884355 13251 44463 -1 176 1 4 4 1566 696 2.34964 2.34964 -2.34964 -2.34964 -1.26876 -1.26876 292904. 1733.16 0.01 0.03 0.02 -1 -1 0.01 0.00083991 0.000816053 0 4 diff --git a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_soft_multipliers/config/golden_results.txt b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_soft_multipliers/config/golden_results.txt index 6e62fc65a75..95cabd17846 100644 --- a/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_soft_multipliers/config/golden_results.txt +++ b/vtr_flow/tasks/regression_tests/vtr_reg_strong/strong_soft_multipliers/config/golden_results.txt @@ -1,7 +1,7 @@ arch circuit script_params vtr_flow_elapsed_time vtr_max_mem_stage vtr_max_mem error odin_synth_time max_odin_mem parmys_synth_time max_parmys_mem abc_depth abc_synth_time abc_cec_time abc_sec_time max_abc_mem ace_time max_ace_mem num_clb num_io num_memories num_mult vpr_status vpr_revision vpr_build_info vpr_compiler vpr_compiled hostname rundir max_vpr_mem num_primary_inputs num_primary_outputs num_pre_packed_nets num_pre_packed_blocks num_netlist_clocks num_post_packed_nets num_post_packed_blocks device_width device_height device_grid_tiles device_limiting_resources device_name pack_mem pack_time initial_placed_wirelength_est placed_wirelength_est total_swap accepted_swap rejected_swap aborted_swap place_mem place_time place_quench_time initial_placed_CPD_est placed_CPD_est placed_setup_TNS_est placed_setup_WNS_est placed_geomean_nonvirtual_intradomain_critical_path_delay_est place_delay_matrix_lookup_time place_quench_timing_analysis_time place_quench_sta_time place_total_timing_analysis_time place_total_sta_time ap_mem ap_time ap_full_legalizer_mem ap_full_legalizer_time min_chan_width routed_wirelength min_chan_width_route_success_iteration logic_block_area_total logic_block_area_used min_chan_width_routing_area_total min_chan_width_routing_area_per_tile min_chan_width_route_time min_chan_width_total_timing_analysis_time min_chan_width_total_sta_time crit_path_num_rr_graph_nodes crit_path_num_rr_graph_edges crit_path_collapsed_nodes crit_path_routed_wirelength crit_path_route_success_iteration crit_path_total_nets_routed crit_path_total_connections_routed crit_path_total_heap_pushes crit_path_total_heap_pops critical_path_delay geomean_nonvirtual_intradomain_critical_path_delay setup_TNS setup_WNS hold_TNS hold_WNS crit_path_routing_area_total crit_path_routing_area_per_tile router_lookahead_computation_time crit_path_route_time crit_path_create_rr_graph_time crit_path_create_intra_cluster_rr_graph_time crit_path_tile_lookahead_computation_time crit_path_router_lookahead_computation_time crit_path_total_timing_analysis_time crit_path_total_sta_time num_le num_luts num_add_blocks max_add_chain_length num_sub_blocks max_sub_chain_length -k6_frac_N10_4add_2chains_depop50_mem20K_22nm.xml mult_4x4.v common 1.10 vpr 64.34 MiB -1 -1 0.07 17596 1 0.02 -1 -1 30128 -1 -1 3 9 0 -1 success v8.0.0-12648-g259ceba57-dirty release IPO VTR_ASSERT_LEVEL=2 Clang 18.1.3 on Linux-6.8.0-58-generic x86_64 2025-05-06T12:34:13 betzgrp-wintermute /home/zhan6738/VTR/vtr-verilog-to-routing/vtr_flow/tasks 65888 9 8 75 70 1 34 20 5 5 25 clb auto 25.2 MiB 0.37 116 87 425 142 281 2 64.3 MiB 0.01 0.00 2.64007 2.48207 -26.067 -2.48207 2.48207 0.01 9.3228e-05 8.39e-05 0.0022793 0.00210862 -1 -1 -1 -1 26 268 23 151211 75605.7 37105.9 1484.24 0.04 0.015438 0.0132379 1908 5841 -1 135 7 69 74 2147 1228 2.87707 2.87707 -32.0609 -2.87707 0 0 45067.1 1802.68 0.00 0.01 0.00 -1 -1 0.00 0.00462719 0.00432137 13 18 -1 -1 -1 -1 -k6_frac_N10_4add_2chains_depop50_mem20K_22nm.xml mult_5x5.v common 2.34 vpr 64.48 MiB -1 -1 0.08 17592 1 0.02 -1 -1 30088 -1 -1 2 11 0 -1 success v8.0.0-12648-g259ceba57-dirty release IPO VTR_ASSERT_LEVEL=2 Clang 18.1.3 on Linux-6.8.0-58-generic x86_64 2025-05-06T12:34:13 betzgrp-wintermute /home/zhan6738/VTR/vtr-verilog-to-routing/vtr_flow/tasks 66028 11 10 108 97 1 48 23 4 4 16 clb auto 25.6 MiB 1.57 142 127 279 85 156 38 64.5 MiB 0.00 0.00 3.45122 3.45122 -42.3331 -3.45122 3.45122 0.01 0.000120597 0.000109581 0.00222065 0.00210236 -1 -1 -1 -1 34 218 18 50403.8 50403.8 21558.4 1347.40 0.07 0.0281563 0.0239356 1020 3049 -1 142 9 139 176 4698 2930 3.29429 3.29429 -44.332 -3.29429 0 0 26343.3 1646.46 0.00 0.01 0.00 -1 -1 0.00 0.00541739 0.00503817 14 27 -1 -1 -1 -1 -k6_frac_N10_4add_2chains_depop50_mem20K_22nm.xml mult_6x6.v common 3.61 vpr 64.09 MiB -1 -1 0.08 17596 1 0.02 -1 -1 30140 -1 -1 7 13 0 -1 success v8.0.0-12648-g259ceba57-dirty release IPO VTR_ASSERT_LEVEL=2 Clang 18.1.3 on Linux-6.8.0-58-generic x86_64 2025-05-06T12:34:13 betzgrp-wintermute /home/zhan6738/VTR/vtr-verilog-to-routing/vtr_flow/tasks 65632 13 12 149 129 1 68 32 6 6 36 clb auto 24.5 MiB 2.75 257 197 732 245 474 13 64.1 MiB 0.01 0.00 3.49758 3.49758 -52.6672 -3.49758 3.49758 0.02 0.000156374 0.000142533 0.00392726 0.00368989 -1 -1 -1 -1 48 388 31 403230 176413 104013. 2889.24 0.11 0.0414693 0.0356383 3910 18599 -1 284 17 330 478 14391 6422 3.69853 3.69853 -57.0037 -3.69853 0 0 131137. 3642.71 0.00 0.01 0.01 -1 -1 0.00 0.00915593 0.00833327 25 38 -1 -1 -1 -1 -k6_frac_N10_4add_2chains_depop50_mem20K_22nm.xml mult_7x7.v common 2.32 vpr 65.20 MiB -1 -1 0.08 17980 1 0.02 -1 -1 30160 -1 -1 6 15 0 -1 success v8.0.0-12648-g259ceba57-dirty release IPO VTR_ASSERT_LEVEL=2 Clang 18.1.3 on Linux-6.8.0-58-generic x86_64 2025-05-06T12:34:13 betzgrp-wintermute /home/zhan6738/VTR/vtr-verilog-to-routing/vtr_flow/tasks 66768 15 14 196 165 1 93 35 5 5 25 clb auto 25.2 MiB 1.42 387 299 1118 289 798 31 65.2 MiB 0.01 0.00 3.70693 3.64998 -62.024 -3.64998 3.64998 0.01 0.000202129 0.0001848 0.00594995 0.00555165 -1 -1 -1 -1 38 642 42 151211 151211 48493.3 1939.73 0.14 0.0566763 0.0489294 2100 8065 -1 443 21 562 836 28073 13943 4.5307 4.5307 -77.3289 -4.5307 0 0 61632.8 2465.31 0.00 0.02 0.00 -1 -1 0.00 0.0127536 0.0115505 36 51 -1 -1 -1 -1 -k6_frac_N10_4add_2chains_depop50_mem20K_22nm.xml mult_8x8.v common 4.33 vpr 65.36 MiB -1 -1 0.09 17596 1 0.03 -1 -1 30128 -1 -1 5 17 0 -1 success v8.0.0-12648-g259ceba57-dirty release IPO VTR_ASSERT_LEVEL=2 Clang 18.1.3 on Linux-6.8.0-58-generic x86_64 2025-05-06T12:34:13 betzgrp-wintermute /home/zhan6738/VTR/vtr-verilog-to-routing/vtr_flow/tasks 66932 17 16 251 206 1 120 38 5 5 25 clb auto 25.7 MiB 3.40 485 430 227 58 164 5 65.4 MiB 0.01 0.00 3.91442 3.88071 -76.4934 -3.88071 3.88071 0.01 0.000245396 0.000224553 0.00332248 0.00320063 -1 -1 -1 -1 46 639 28 151211 126010 57775.2 2311.01 0.15 0.061068 0.0527302 2220 9391 -1 566 15 540 892 27101 12502 4.50773 4.50773 -92.5696 -4.50773 0 0 73020.3 2920.81 0.00 0.02 0.01 -1 -1 0.00 0.0138066 0.0127692 45 66 -1 -1 -1 -1 -k6_frac_N10_4add_2chains_depop50_mem20K_22nm.xml mult_9x9.v common 4.46 vpr 65.57 MiB -1 -1 0.09 18360 1 0.03 -1 -1 30076 -1 -1 9 19 0 -1 success v8.0.0-12648-g259ceba57-dirty release IPO VTR_ASSERT_LEVEL=2 Clang 18.1.3 on Linux-6.8.0-58-generic x86_64 2025-05-06T12:34:13 betzgrp-wintermute /home/zhan6738/VTR/vtr-verilog-to-routing/vtr_flow/tasks 67144 19 18 308 249 1 134 46 6 6 36 clb auto 25.9 MiB 3.44 628 450 3408 877 2509 22 65.6 MiB 0.03 0.00 5.19392 4.85986 -99.9643 -4.85986 4.85986 0.02 0.000293829 0.000269579 0.0149755 0.0138941 -1 -1 -1 -1 56 839 22 403230 226817 117789. 3271.93 0.17 0.0794032 0.0696928 4086 21443 -1 597 17 428 696 24582 10181 4.89622 4.89622 -97.5059 -4.89622 0 0 149557. 4154.36 0.00 0.02 0.01 -1 -1 0.00 0.0165564 0.0152987 54 83 -1 -1 -1 -1 +k6_frac_N10_4add_2chains_depop50_mem20K_22nm.xml mult_4x4.v common 0.84 vpr 65.48 MiB -1 -1 0.05 26980 1 0.02 -1 -1 33484 -1 -1 3 9 0 -1 success v8.0.0-12803-g53682df9f release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-13T11:40:41 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 67048 9 8 75 70 1 34 20 5 5 25 clb auto 26.4 MiB 0.38 116 85 344 99 240 5 65.5 MiB 0.00 0.00 2.64007 2.48207 -26.0196 -2.48207 2.48207 0.01 6.6112e-05 5.8999e-05 0.00167679 0.00155293 -1 -1 -1 -1 26 204 17 151211 75605.7 37105.9 1484.24 0.03 0.011023 0.0095606 1908 5841 -1 161 10 122 131 4886 2844 2.87707 2.87707 -34.6679 -2.87707 0 0 45067.1 1802.68 0.00 0.00 0.00 -1 -1 0.00 0.00346766 0.0032271 13 18 -1 -1 -1 -1 +k6_frac_N10_4add_2chains_depop50_mem20K_22nm.xml mult_5x5.v common 2.04 vpr 66.05 MiB -1 -1 0.06 27108 1 0.02 -1 -1 33836 -1 -1 2 11 0 -1 success v8.0.0-12803-g53682df9f release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-13T11:40:41 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 67632 11 10 108 97 1 48 23 4 4 16 clb auto 26.8 MiB 1.51 145.745 133 119 39 59 21 66.0 MiB 0.00 0.00 3.45122 3.45122 -42.3331 -3.45122 3.45122 0.00 0.000119903 0.000111011 0.00130651 0.00125462 -1 -1 -1 -1 38 191 15 50403.8 50403.8 23356.0 1459.75 0.08 0.0284744 0.0243039 1064 3436 -1 144 12 192 250 5607 3262 3.40193 3.40193 -44.9365 -3.40193 0 0 29887.0 1867.94 0.00 0.01 0.00 -1 -1 0.00 0.00598011 0.0054933 14 27 -1 -1 -1 -1 +k6_frac_N10_4add_2chains_depop50_mem20K_22nm.xml mult_6x6.v common 3.47 vpr 66.36 MiB -1 -1 0.06 27108 1 0.02 -1 -1 33772 -1 -1 7 13 0 -1 success v8.0.0-12803-g53682df9f release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-13T11:40:41 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 67948 13 12 149 129 1 68 32 6 6 36 clb auto 26.8 MiB 2.79 259.236 201 732 259 462 11 66.4 MiB 0.01 0.00 3.49758 3.49758 -52.7688 -3.49758 3.49758 0.02 0.000150498 0.000138695 0.00331829 0.00312412 -1 -1 -1 -1 40 446 26 403230 176413 88484.8 2457.91 0.18 0.0504928 0.0430388 3734 16003 -1 342 16 317 392 12125 5632 3.97158 3.97158 -59.4686 -3.97158 0 0 110337. 3064.92 0.00 0.01 0.01 -1 -1 0.00 0.00717342 0.00662621 25 38 -1 -1 -1 -1 +k6_frac_N10_4add_2chains_depop50_mem20K_22nm.xml mult_7x7.v common 2.13 vpr 66.76 MiB -1 -1 0.06 27236 1 0.02 -1 -1 33528 -1 -1 7 15 0 -1 success v8.0.0-12803-g53682df9f release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-13T11:40:41 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 68360 15 14 196 165 1 92 36 6 6 36 clb auto 27.1 MiB 1.38 339.362 305 508 139 354 15 66.8 MiB 0.01 0.00 3.66013 3.62628 -64.5833 -3.62628 3.62628 0.02 0.000154443 0.000139798 0.00287334 0.00271603 -1 -1 -1 -1 52 611 24 403230 176413 110337. 3064.92 0.23 0.06632 0.0570381 4014 20275 -1 521 17 495 717 23250 9709 4.46116 4.46116 -82.3083 -4.46116 0 0 143382. 3982.83 0.00 0.01 0.01 -1 -1 0.00 0.00920014 0.00850543 37 51 -1 -1 -1 -1 +k6_frac_N10_4add_2chains_depop50_mem20K_22nm.xml mult_8x8.v common 4.36 vpr 66.51 MiB -1 -1 0.06 27492 1 0.02 -1 -1 33668 -1 -1 5 17 0 -1 success v8.0.0-12803-g53682df9f release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-13T11:40:41 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 68108 17 16 251 206 1 117 38 5 5 25 clb auto 27.1 MiB 3.62 488.93 399 1739 445 1279 15 66.5 MiB 0.02 0.00 3.8942 3.8942 -74.1495 -3.8942 3.8942 0.01 0.000244402 0.00022672 0.00837558 0.00779412 -1 -1 -1 -1 50 667 35 151211 126010 61632.8 2465.31 0.21 0.080226 0.0697113 2268 9834 -1 593 17 620 1026 32976 15549 4.7753 4.7753 -100.063 -4.7753 0 0 77226.2 3089.05 0.00 0.02 0.01 -1 -1 0.00 0.0114886 0.0106626 44 66 -1 -1 -1 -1 +k6_frac_N10_4add_2chains_depop50_mem20K_22nm.xml mult_9x9.v common 4.39 vpr 67.08 MiB -1 -1 0.06 27620 1 0.02 -1 -1 34084 -1 -1 7 19 0 -1 success v8.0.0-12803-g53682df9f release IPO VTR_ASSERT_LEVEL=2 GNU 11.4.0 on Linux-6.8.0-60-generic x86_64 2025-06-13T11:40:41 llavign1-OptiPlex-7070 /home/llavign1/Gits/vtr-clone/vtr_flow/tasks 68692 19 18 308 249 1 134 44 6 6 36 clb auto 27.6 MiB 3.52 669.263 466 3355 832 2503 20 67.1 MiB 0.02 0.00 5.1706 4.8546 -99.3278 -4.8546 4.8546 0.02 0.000220135 0.000199241 0.0118792 0.0109162 -1 -1 -1 -1 68 718 21 403230 176413 143382. 3982.83 0.28 0.0997638 0.0871492 4366 25715 -1 645 19 546 899 32759 12243 4.7387 4.7387 -97.8117 -4.7387 0 0 176130. 4892.50 0.00 0.03 0.01 -1 -1 0.00 0.0188763 0.0173585 53 83 -1 -1 -1 -1 diff --git a/yosys/.editorconfig b/yosys/.editorconfig index f5444d81a74..572b73bd2ed 100644 --- a/yosys/.editorconfig +++ b/yosys/.editorconfig @@ -10,3 +10,7 @@ insert_final_newline = true indent_style = space indent_size = 2 trim_trailing_whitespace = false + +[*.yml] +indent_style = space +indent_size = 2 diff --git a/yosys/.gitcommit b/yosys/.gitcommit index 6c5826ed776..6828f88dcb0 100644 --- a/yosys/.gitcommit +++ b/yosys/.gitcommit @@ -1 +1 @@ -dac5bd1983a +$Format:%H$ diff --git a/yosys/.github/actions/setup-build-env/action.yml b/yosys/.github/actions/setup-build-env/action.yml index 345b6db8ada..dfdcd88c0f4 100644 --- a/yosys/.github/actions/setup-build-env/action.yml +++ b/yosys/.github/actions/setup-build-env/action.yml @@ -8,13 +8,14 @@ runs: shell: bash run: | sudo apt-get update - sudo apt-get install gperf build-essential bison flex libreadline-dev gawk tcl-dev libffi-dev git graphviz xdot pkg-config python3 libboost-system-dev libboost-python-dev libboost-filesystem-dev zlib1g-dev + sudo apt-get install gperf build-essential bison flex libreadline-dev gawk tcl-dev libffi-dev git graphviz xdot pkg-config python3 libboost-system-dev libboost-python-dev libboost-filesystem-dev zlib1g-dev libbz2-dev - name: Install macOS Dependencies if: runner.os == 'macOS' shell: bash run: | - HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install bison flex gawk libffi pkg-config bash autoconf + HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew update + HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 brew install bison flex gawk libffi pkg-config bash autoconf llvm lld || true - name: Linux runtime environment if: runner.os == 'Linux' @@ -28,6 +29,7 @@ runs: shell: bash run: | echo "${{ github.workspace }}/.local/bin" >> $GITHUB_PATH + echo "$(brew --prefix llvm)/bin" >> $GITHUB_PATH echo "$(brew --prefix bison)/bin" >> $GITHUB_PATH echo "$(brew --prefix flex)/bin" >> $GITHUB_PATH echo "procs=$(sysctl -n hw.ncpu)" >> $GITHUB_ENV diff --git a/yosys/.github/workflows/codeql.yml b/yosys/.github/workflows/codeql.yml index 24ae7c89883..75d799fe114 100644 --- a/yosys/.github/workflows/codeql.yml +++ b/yosys/.github/workflows/codeql.yml @@ -16,7 +16,9 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 with: - submodules: true + submodules: true + persist-credentials: false + - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: diff --git a/yosys/.github/workflows/extra-builds.yml b/yosys/.github/workflows/extra-builds.yml index d7c6e13ff06..0c3146e41d4 100644 --- a/yosys/.github/workflows/extra-builds.yml +++ b/yosys/.github/workflows/extra-builds.yml @@ -25,7 +25,8 @@ jobs: steps: - uses: actions/checkout@v4 with: - submodules: true + submodules: true + persist-credentials: false - name: Build run: make vcxsrc YOSYS_VER=latest - uses: actions/upload-artifact@v4 @@ -59,7 +60,8 @@ jobs: steps: - uses: actions/checkout@v4 with: - submodules: true + submodules: true + persist-credentials: false - name: Build run: | WASI_SDK=wasi-sdk-19.0 @@ -86,12 +88,17 @@ jobs: name: "Build nix flake" needs: pre_job if: needs.pre_job.outputs.should_skip != 'true' - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + fail-fast: false steps: - uses: actions/checkout@v4 with: submodules: true + persist-credentials: false - uses: cachix/install-nix-action@v26 with: install_url: https://releases.nixos.org/nix/nix-2.18.1/install - - run: nix build .?submodules=1 + - run: nix build .?submodules=1 -L diff --git a/yosys/.github/workflows/prepare-docs.yml b/yosys/.github/workflows/prepare-docs.yml new file mode 100644 index 00000000000..fb1fab42613 --- /dev/null +++ b/yosys/.github/workflows/prepare-docs.yml @@ -0,0 +1,83 @@ +name: Build docs artifact with Verific + +on: [push, pull_request] + +jobs: + check_docs_rebuild: + runs-on: ubuntu-latest + outputs: + skip_check: ${{ steps.skip_check.outputs.should_skip }} + docs_export: ${{ steps.docs_var.outputs.docs_export }} + env: + docs_export: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/docs-preview') || startsWith(github.ref, 'refs/tags/') }} + steps: + - id: skip_check + uses: fkirc/skip-duplicate-actions@v5 + with: + paths_ignore: '["**/README.md"]' + # don't cancel in case we're updating docs + cancel_others: 'false' + # only run on push *or* pull_request, not both + concurrent_skipping: ${{ env.docs_export && 'never' || 'same_content_newer'}} + - id: docs_var + run: echo "docs_export=${docs_export}" >> $GITHUB_OUTPUT + + prepare-docs: + # docs builds are needed for anything on main, any tagged versions, and any tag + # or branch starting with docs-preview + needs: check_docs_rebuild + if: ${{ needs.check_docs_rebuild.outputs.should_skip != 'true' }} + runs-on: [self-hosted, linux, x64, fast] + steps: + - name: Checkout Yosys + uses: actions/checkout@v4 + with: + persist-credentials: false + submodules: true + + - name: Runtime environment + run: | + echo "procs=$(nproc)" >> $GITHUB_ENV + + - name: Build Yosys + run: | + make config-clang + echo "ENABLE_VERIFIC := 1" >> Makefile.conf + echo "ENABLE_VERIFIC_EDIF := 1" >> Makefile.conf + echo "ENABLE_VERIFIC_LIBERTY := 1" >> Makefile.conf + echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 1" >> Makefile.conf + echo "ENABLE_CCACHE := 1" >> Makefile.conf + make -j$procs ENABLE_LTO=1 + + - name: Prepare docs + shell: bash + run: + make docs/prep -j$procs TARGETS= EXTRA_TARGETS= + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: cmd-ref-${{ github.sha }} + path: | + docs/source/cmd + docs/source/generated + docs/source/_images + docs/source/code_examples + + - name: Install doc prereqs + shell: bash + run: | + make docs/reqs + + - name: Test build docs + shell: bash + run: | + make -C docs html -j$procs TARGETS= EXTRA_TARGETS= + + - name: Trigger RTDs build + if: ${{ needs.check_docs_rebuild.outputs.docs_export == 'true' }} + uses: dfm/rtds-action@v1.1.0 + with: + webhook_url: ${{ secrets.RTDS_WEBHOOK_URL }} + webhook_token: ${{ secrets.RTDS_WEBHOOK_TOKEN }} + commit_ref: ${{ github.ref }} diff --git a/yosys/.github/workflows/source-vendor.yml b/yosys/.github/workflows/source-vendor.yml new file mode 100644 index 00000000000..dc9480ef6e1 --- /dev/null +++ b/yosys/.github/workflows/source-vendor.yml @@ -0,0 +1,34 @@ +name: Create source archive with vendored dependencies + +on: [push, workflow_dispatch] + +jobs: + vendor-sources: + runs-on: ubuntu-latest + steps: + - name: Checkout repository with submodules + uses: actions/checkout@v4 + with: + submodules: 'recursive' + persist-credentials: false + + - name: Create clean tarball + run: | + git archive --format=tar HEAD -o yosys-src-vendored.tar + git submodule foreach ' + git archive --format=tar --prefix="${sm_path}/" HEAD --output=${toplevel}/vendor-${name}.tar + ' + + # 2008 bug https://lists.gnu.org/archive/html/bug-tar/2008-08/msg00002.html + for file in vendor-*.tar; do + tar --concatenate --file=yosys-src-vendored.tar "$file" + done + + gzip yosys-src-vendored.tar + + - name: Store tarball artifact + uses: actions/upload-artifact@v4 + with: + name: vendored-sources + path: yosys-src-vendored.tar.gz + retention-days: 1 diff --git a/yosys/.github/workflows/test-build.yml b/yosys/.github/workflows/test-build.yml index bf95688a15c..b88662f0fc5 100644 --- a/yosys/.github/workflows/test-build.yml +++ b/yosys/.github/workflows/test-build.yml @@ -46,6 +46,7 @@ jobs: uses: actions/checkout@v4 with: submodules: true + persist-credentials: false - name: Setup environment uses: ./.github/actions/setup-build-env @@ -56,7 +57,8 @@ jobs: mkdir build cd build make -f ../Makefile config-$CC - make -f ../Makefile -j$procs + echo 'SANITIZER = undefined' >> Makefile.conf + make -f ../Makefile -j$procs ENABLE_LTO=1 - name: Log yosys-config output run: | @@ -82,6 +84,7 @@ jobs: if: needs.pre_job.outputs.should_skip != 'true' env: CC: clang + UBSAN_OPTIONS: halt_on_error=1 strategy: matrix: os: [ubuntu-latest, macos-latest] @@ -89,6 +92,8 @@ jobs: steps: - name: Checkout Yosys uses: actions/checkout@v4 + with: + persist-credentials: false - name: Setup environment uses: ./.github/actions/setup-build-env @@ -100,12 +105,22 @@ jobs: cd iverilog echo "IVERILOG_GIT=$(git rev-parse HEAD)" >> $GITHUB_ENV + - name: Get vcd2fst + shell: bash + run: | + git clone https://github.com/mmicko/libwave.git + mkdir -p ${{ github.workspace }}/.local/ + cd libwave + cmake . -DCMAKE_INSTALL_PREFIX=${{ github.workspace }}/.local + make -j$procs + make install + - name: Cache iverilog id: cache-iverilog uses: actions/cache@v4 with: path: .local/ - key: ${{ matrix.os }}-${{ env.IVERILOG_GIT }} + key: ${{ matrix.os }}-${IVERILOG_GIT} - name: Build iverilog if: steps.cache-iverilog.outputs.cache-hit != 'true' @@ -157,6 +172,8 @@ jobs: steps: - name: Checkout Yosys uses: actions/checkout@v4 + with: + persist-credentials: false - name: Setup environment uses: ./.github/actions/setup-build-env @@ -178,4 +195,47 @@ jobs: - name: Run tests shell: bash run: | - make -C docs test -j${{ env.procs }} + make -C docs test -j$procs + + test-docs-build: + name: Try build docs + runs-on: [self-hosted, linux, x64, fast] + needs: [pre_docs_job] + if: needs.pre_docs_job.outputs.should_skip != 'true' + strategy: + matrix: + docs-target: [html, latexpdf] + fail-fast: false + steps: + - name: Checkout Yosys + uses: actions/checkout@v4 + with: + submodules: true + persist-credentials: false + + - name: Runtime environment + run: | + echo "procs=$(nproc)" >> $GITHUB_ENV + + - name: Build Yosys + run: | + make config-clang + echo "ENABLE_CCACHE := 1" >> Makefile.conf + make -j$procs + + - name: Install doc prereqs + shell: bash + run: | + make docs/reqs + + - name: Build docs + shell: bash + run: | + make docs DOC_TARGET=${{ matrix.docs-target }} -j$procs + + - name: Store docs build artifact + uses: actions/upload-artifact@v4 + with: + name: docs-build-${{ matrix.docs-target }} + path: docs/build/ + retention-days: 7 diff --git a/yosys/.github/workflows/test-compile.yml b/yosys/.github/workflows/test-compile.yml index a892c91ceca..7a706e69a36 100644 --- a/yosys/.github/workflows/test-compile.yml +++ b/yosys/.github/workflows/test-compile.yml @@ -30,24 +30,22 @@ jobs: - ubuntu-latest compiler: # oldest supported - - 'clang-14' + - 'clang-10' - 'gcc-10' - # newest - - 'clang' - - 'gcc' + # newest, make sure to update maximum standard step to match + - 'clang-19' + - 'gcc-13' include: # macOS - os: macos-13 compiler: 'clang' - # oldest clang not available on ubuntu-latest - - os: ubuntu-22.04 - compiler: 'clang-11' fail-fast: false steps: - name: Checkout Yosys uses: actions/checkout@v4 with: submodules: true + persist-credentials: false - name: Setup environment uses: ./.github/actions/setup-build-env @@ -72,7 +70,7 @@ jobs: # maximum standard, only on newest compilers - name: Build C++20 - if: ${{ matrix.compiler == 'clang' || matrix.compiler == 'gcc'}} + if: ${{ matrix.compiler == 'clang-19' || matrix.compiler == 'gcc-13' }} shell: bash run: | make config-$CC_SHORT diff --git a/yosys/.github/workflows/test-verific.yml b/yosys/.github/workflows/test-verific.yml index 54d9487acfb..013c9f8ca1a 100644 --- a/yosys/.github/workflows/test-verific.yml +++ b/yosys/.github/workflows/test-verific.yml @@ -3,7 +3,7 @@ name: Build and run tests with Verific (Linux) on: [push, pull_request] jobs: - pre_job: + pre-job: runs-on: ubuntu-latest outputs: should_skip: ${{ steps.skip_check.outputs.should_skip }} @@ -11,18 +11,16 @@ jobs: - id: skip_check uses: fkirc/skip-duplicate-actions@v5 with: - paths_ignore: '["**/README.md"]' - # don't cancel previous builds + paths_ignore: '["**/README.md", "docs/**", "guidelines/**"]' + # cancel previous builds if a new commit is pushed cancel_others: 'true' # only run on push *or* pull_request, not both concurrent_skipping: 'same_content_newer' - # we have special actions when running on main, so this should be off - skip_after_successful_duplicate: 'false' test-verific: - needs: pre_job - if: needs.pre_job.outputs.should_skip != 'true' - runs-on: [self-hosted, linux, x64] + needs: pre-job + if: needs.pre-job.outputs.should_skip != 'true' + runs-on: [self-hosted, linux, x64, fast] steps: - name: Checkout Yosys uses: actions/checkout@v4 @@ -39,42 +37,21 @@ jobs: echo "ENABLE_VERIFIC := 1" >> Makefile.conf echo "ENABLE_VERIFIC_EDIF := 1" >> Makefile.conf echo "ENABLE_VERIFIC_LIBERTY := 1" >> Makefile.conf + echo "ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 1" >> Makefile.conf echo "ENABLE_CCACHE := 1" >> Makefile.conf - make -j${{ env.procs }} + echo "ENABLE_FUNCTIONAL_TESTS := 1" >> Makefile.conf + make -j$procs ENABLE_LTO=1 - name: Install Yosys run: | make install DESTDIR=${GITHUB_WORKSPACE}/.local PREFIX= - - name: Checkout Documentation - if: ${{ github.ref == 'refs/heads/main' }} - uses: actions/checkout@v4 - with: - path: 'yosys-cmd-ref' - repository: 'YosysHQ-Docs/yosys-cmd-ref' - fetch-depth: 0 - token: ${{ secrets.CI_DOCS_UPDATE_PAT }} - persist-credentials: true - - - name: Update documentation - if: ${{ github.ref == 'refs/heads/main' }} - run: | - make docs - rm -rf docs/build - cd yosys-cmd-ref - rm -rf * - git checkout README.md - cp -R ../docs/* . - rm -rf util/__pycache__ - git add -A . - git diff-index --quiet HEAD || git commit -m "Update" - git push - - name: Checkout SBY uses: actions/checkout@v4 with: repository: 'YosysHQ/sby' path: 'sby' + persist-credentials: false - name: Build SBY run: | @@ -82,7 +59,7 @@ jobs: - name: Run Yosys tests run: | - make -j${{ env.procs }} test + make -j$procs test - name: Run Verific specific Yosys tests run: | diff --git a/yosys/.github/workflows/update-flake-lock.yml b/yosys/.github/workflows/update-flake-lock.yml index c7aa6ecab70..de7ef04d627 100644 --- a/yosys/.github/workflows/update-flake-lock.yml +++ b/yosys/.github/workflows/update-flake-lock.yml @@ -10,6 +10,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + with: + persist-credentials: false - name: Install Nix uses: DeterminateSystems/nix-installer-action@main - name: Update flake.lock diff --git a/yosys/.github/workflows/version.yml b/yosys/.github/workflows/version.yml index f73c68bdf12..26dcba4a4a1 100644 --- a/yosys/.github/workflows/version.yml +++ b/yosys/.github/workflows/version.yml @@ -14,6 +14,7 @@ jobs: with: fetch-depth: 0 submodules: true + persist-credentials: false - name: Take last commit id: log run: echo "message=$(git log --no-merges -1 --oneline)" >> $GITHUB_OUTPUT diff --git a/yosys/.github/workflows/wheels.yml b/yosys/.github/workflows/wheels.yml new file mode 100644 index 00000000000..b01ce6b3ab9 --- /dev/null +++ b/yosys/.github/workflows/wheels.yml @@ -0,0 +1,137 @@ +name: Build Wheels for PyPI + +# run every Sunday at 10 AM +on: + workflow_dispatch: + schedule: + - cron: '0 10 * * 0' + +jobs: + build_wheels: + strategy: + fail-fast: false + matrix: + os: [ + { + name: "Ubuntu 22.04", + family: "linux", + runner: "ubuntu-22.04", + archs: "x86_64", + }, + { + name: "Ubuntu 22.04", + family: "linux", + runner: "ubuntu-22.04-arm", + archs: "aarch64", + }, + { + name: "macOS 13", + family: "macos", + runner: "macos-13", + archs: "x86_64", + }, + { + name: "macOS 14", + family: "macos", + runner: "macos-14", + archs: "arm64", + }, + ## Windows is disabled because of an issue with compiling FFI as + ## under MinGW in the GitHub Actions environment (SHELL variable has + ## whitespace.) + # { + # name: "Windows Server 2019", + # family: "windows", + # runner: "windows-2019", + # archs: "AMD64", + # }, + ] + name: Build Wheels | ${{ matrix.os.name }} | ${{ matrix.os.archs }} + runs-on: ${{ matrix.os.runner }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + submodules: true + persist-credentials: false + - if: ${{ matrix.os.family == 'linux' }} + name: "[Linux] Set up QEMU" + uses: docker/setup-qemu-action@v3 + - uses: actions/setup-python@v5 + - name: Get Boost Source + shell: bash + run: | + mkdir -p boost + curl -L https://github.com/boostorg/boost/releases/download/boost-1.86.0/boost-1.86.0-b2-nodocs.tar.gz | tar --strip-components=1 -xzC boost + - name: Get FFI + shell: bash + run: | + mkdir -p ffi + curl -L https://github.com/libffi/libffi/releases/download/v3.4.6/libffi-3.4.6.tar.gz | tar --strip-components=1 -xzC ffi + ## Software installed by default in GitHub Action Runner VMs: + ## https://github.com/actions/runner-images + - if: ${{ matrix.os.family == 'macos' }} + name: "[macOS] Flex/Bison" + run: | + brew install flex bison + echo "PATH=$(brew --prefix flex)/bin:$PATH" >> $GITHUB_ENV + echo "PATH=$(brew --prefix bison)/bin:$PATH" >> $GITHUB_ENV + - if: ${{ matrix.os.family == 'windows' }} + name: "[Windows] Flex/Bison" + run: | + choco install winflexbison3 + - if: ${{ matrix.os.family == 'macos' && matrix.os.archs == 'arm64' }} + name: "[macOS/arm64] Install Python 3.8 (see: https://cibuildwheel.pypa.io/en/stable/faq/#macos-building-cpython-38-wheels-on-arm64)" + uses: actions/setup-python@v5 + with: + python-version: 3.8 + - name: Build wheels + uses: pypa/cibuildwheel@v2.21.1 + env: + # * APIs not supported by PyPy + # * Musllinux disabled because it increases build time from 48m to ~3h + CIBW_SKIP: > + pp* + *musllinux* + CIBW_ARCHS: ${{ matrix.os.archs }} + CIBW_BUILD_VERBOSITY: "1" + # manylinux2014 (default) does not have a modern enough C++ compiler for Yosys + CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28 + CIBW_MANYLINUX_AARCH64_IMAGE: manylinux_2_28 + CIBW_BEFORE_ALL: bash ./.github/workflows/wheels/cibw_before_all.sh + CIBW_ENVIRONMENT: > + CXXFLAGS=-I./boost/pfx/include + LINKFLAGS=-L./boost/pfx/lib + PKG_CONFIG_PATH=./ffi/pfx/lib/pkgconfig + makeFlags='BOOST_PYTHON_LIB=./boost/pfx/lib/libboost_python*.a' + CIBW_ENVIRONMENT_MACOS: > + CXXFLAGS=-I./boost/pfx/include + LINKFLAGS=-L./boost/pfx/lib + PKG_CONFIG_PATH=./ffi/pfx/lib/pkgconfig + MACOSX_DEPLOYMENT_TARGET=11 + makeFlags='BOOST_PYTHON_LIB=./boost/pfx/lib/libboost_python*.a CONFIG=clang' + CIBW_BEFORE_BUILD: bash ./.github/workflows/wheels/cibw_before_build.sh + CIBW_TEST_COMMAND: python3 {project}/tests/arch/ecp5/add_sub.py + - uses: actions/upload-artifact@v4 + with: + name: python-wheels-${{ matrix.os.runner }} + path: ./wheelhouse/*.whl + upload_wheels: + name: Upload Wheels + runs-on: ubuntu-latest + needs: build_wheels + steps: + - uses: actions/download-artifact@v4 + with: + path: "." + pattern: python-wheels-* + merge-multiple: true + - run: | + ls + mkdir -p ./dist + mv *.whl ./dist + - name: Publish + uses: pypa/gh-action-pypi-publish@release/v1 + with: + password: ${{ secrets.PYPI_TOKEN }} + repository-url: ${{ vars.PYPI_INDEX || 'https://upload.pypi.org/legacy/' }} diff --git a/yosys/.github/workflows/wheels/_run_cibw_linux.py b/yosys/.github/workflows/wheels/_run_cibw_linux.py new file mode 100644 index 00000000000..894470a5a8d --- /dev/null +++ b/yosys/.github/workflows/wheels/_run_cibw_linux.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +# Copyright (C) 2024 Efabless Corporation +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +""" +This runs the cibuildwheel step from the wheels workflow locally. +""" + +import os +import yaml +import platform +import subprocess + +__dir__ = os.path.dirname(os.path.abspath(__file__)) + + +workflow = yaml.safe_load(open(os.path.join(os.path.dirname(__dir__), "wheels.yml"))) + +env = os.environ.copy() + +steps = workflow["jobs"]["build_wheels"]["steps"] +cibw_step = None +for step in steps: + if (step.get("uses") or "").startswith("pypa/cibuildwheel"): + cibw_step = step + break + +for key, value in cibw_step["env"].items(): + if key.endswith("WIN") or key.endswith("MAC"): + continue + env[key] = value + +env["CIBW_ARCHS"] = os.getenv("CIBW_ARCHS") or platform.machine() +subprocess.check_call(["cibuildwheel"], env=env) diff --git a/yosys/.github/workflows/wheels/cibw_before_all.sh b/yosys/.github/workflows/wheels/cibw_before_all.sh new file mode 100644 index 00000000000..fbb8dcad830 --- /dev/null +++ b/yosys/.github/workflows/wheels/cibw_before_all.sh @@ -0,0 +1,23 @@ +set -e +set -x + +# Build-time dependencies +## Linux Docker Images +if command -v yum &> /dev/null; then + yum install -y flex bison +fi + +if command -v apk &> /dev/null; then + apk add flex bison +fi + +## macOS/Windows -- installed in GitHub Action itself, not container + +# Build Static FFI (platform-dependent but not Python version dependent) +cd ffi +## Ultimate libyosys.so will be shared, so we need fPIC for the static libraries +CFLAGS=-fPIC CXXFLAGS=-fPIC ./configure --prefix=$PWD/pfx +## Without this, SHELL has a space in its path which breaks the makefile +make install -j$(getconf _NPROCESSORS_ONLN 2>/dev/null || sysctl -n hw.ncpu) +## Forces static library to be used in all situations +sed -i.bak 's@-L${toolexeclibdir} -lffi@${toolexeclibdir}/libffi.a@' ./pfx/lib/pkgconfig/libffi.pc diff --git a/yosys/.github/workflows/wheels/cibw_before_build.sh b/yosys/.github/workflows/wheels/cibw_before_build.sh new file mode 100644 index 00000000000..018b0e0df96 --- /dev/null +++ b/yosys/.github/workflows/wheels/cibw_before_build.sh @@ -0,0 +1,34 @@ +set -e +set -x + +# Don't use objects from previous compiles on Windows/macOS +make clean + +# DEBUG: show python3 and python3-config outputs +if [ "$(uname)" != "Linux" ]; then + # https://github.com/pypa/cibuildwheel/issues/2021 + ln -s $(dirname $(readlink -f $(which python3)))/python3-config $(dirname $(which python3))/python3-config +fi +python3 --version +python3-config --includes + +# Build boost +cd ./boost +## Delete the artefacts from previous builds (if any) +rm -rf ./pfx +## Bootstrap bjam +./bootstrap.sh --prefix=./pfx +## Build Boost against current version of Python, only for +## static linkage (Boost is statically linked because system boost packages +## wildly vary in versions, including the libboost_python3 version) +./b2\ + -j$(getconf _NPROCESSORS_ONLN 2>/dev/null || sysctl -n hw.ncpu)\ + --prefix=./pfx\ + --with-filesystem\ + --with-system\ + --with-python\ + cxxflags="$(python3-config --includes) -std=c++17 -fPIC"\ + cflags="$(python3-config --includes) -fPIC"\ + link=static\ + variant=release\ + install diff --git a/yosys/.gitignore b/yosys/.gitignore index e82343e8947..7b4a1fb1ee1 100644 --- a/yosys/.gitignore +++ b/yosys/.gitignore @@ -7,6 +7,7 @@ *.gcno *~ __pycache__ +/.cache /.cproject /.project /.settings @@ -15,6 +16,7 @@ __pycache__ /qtcreator.config /qtcreator.creator /qtcreator.creator.user +/compile_commands.json /coverage.info /coverage_html /Makefile.conf @@ -45,4 +47,11 @@ __pycache__ /tests/unit/bintest/ /tests/unit/objtest/ /tests/ystests -/result \ No newline at end of file +/result +/dist +/*.egg-info +/build +/venv +/boost +/ffi +/*.whl diff --git a/yosys/.gitmodules b/yosys/.gitmodules index d88d4b1e5e9..94717c75641 100644 --- a/yosys/.gitmodules +++ b/yosys/.gitmodules @@ -1,3 +1,7 @@ [submodule "abc"] path = abc url = https://github.com/YosysHQ/abc +# Don't use paths as names to avoid git archive problems +#[submodule "cxxopts"] + #path = libs/cxxopts + #url = https://github.com/jarro2783/cxxopts diff --git a/yosys/.mailmap b/yosys/.mailmap index 78afe1b6cc9..2d9f424d441 100644 --- a/yosys/.mailmap +++ b/yosys/.mailmap @@ -1,6 +1,6 @@ -Marcelina KoÅ›cielnicka -Marcelina KoÅ›cielnicka -Marcelina KoÅ›cielnicka +Wanda Phinode +Wanda Phinode +Wanda Phinode Claire Xenia Wolf Claire Xenia Wolf Claire Xenia Wolf diff --git a/yosys/.readthedocs.yaml b/yosys/.readthedocs.yaml new file mode 100644 index 00000000000..4a04219de98 --- /dev/null +++ b/yosys/.readthedocs.yaml @@ -0,0 +1,20 @@ +# .readthedocs.yaml +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: '3.12' + +formats: + - pdf + +sphinx: + configuration: docs/source/conf.py + fail_on_warning: true + +python: + install: + - requirements: docs/source/requirements.txt diff --git a/yosys/Brewfile b/yosys/Brewfile index b50c70a4b0e..3696e40b084 100644 --- a/yosys/Brewfile +++ b/yosys/Brewfile @@ -9,4 +9,6 @@ brew "python3" brew "tcl-tk" brew "xdot" brew "bash" -brew 'boost-python3' +brew "boost-python3" +brew "llvm" +brew "lld" diff --git a/yosys/CHANGELOG b/yosys/CHANGELOG index d8e13b041e5..bdf30260eea 100644 --- a/yosys/CHANGELOG +++ b/yosys/CHANGELOG @@ -2,9 +2,179 @@ List of major changes and improvements between releases ======================================================= -Yosys 0.42 .. Yosys 0.43-dev +Yosys 0.53 .. Yosys 0.54-dev -------------------------- +Yosys 0.52 .. Yosys 0.53 +-------------------------- + * New commands and options + - Added "constmap" pass for technology mapping of coarse constant value. + - Added "timeest" pass to estimate the critical path in clock domain. + - Added "-blackbox" option to "cutpoint" pass to cut all instances of + blackboxes. + - Added "-noscopeinfo" option to "cutpoint" pass. + - Added "-nocleanup" option to "flatten" pass to prevent removal of + unused submodules. + - Added "-declockgate" option to "formalff" pass that turns clock + gating into clock enables. + + * Various + - Added "$scopeinfo" cells to preserve information during "cutpoint" pass. + - Added dataflow tracking documentation. + - share: Restrict activation patterns to potentially relevant signal. + - liberty: More robust parsing. + - verific: bit blast RAM if using mem2reg attribute. + +Yosys 0.51 .. Yosys 0.52 +-------------------------- + * New commands and options + - Added "-pattern-limit" option to "share" pass to limit analysis effort. + - Added "libcache" pass to control caching of technology library + data parsed from liberty files. + - Added "read_verilog_file_list" to parse verilog file list. + + * Various + - Added $macc_v2 cell. + - Improve lexer performance and zlib support for "read_liberty". + - opt_expr: optimize pow of 2 cells. + + +Yosys 0.50 .. Yosys 0.51 +-------------------------- + * New commands and options + - Added "abstract" pass to allow reducing and never increasing + the constraints on a circuit's behavior in a formal verification setting. + + * Various + - "splitcells" pass now splits "aldff" cells. + - FunctionalIR documentation + + * QuickLogic support + - Added IOFF inference for qlf_k6n10f + + * Intel support + - Fixed RAM and DSP support. + - Overall performance improvement for "synth_intel". + +Yosys 0.49 .. Yosys 0.50 +-------------------------- + * Various + - "write_verilog" emits "$check" cell names as labels. + +Yosys 0.48 .. Yosys 0.49 +-------------------------- + * Various + - "$scopeinfo" cells are now part of JSON export by default. + - Added option to specify hierarchical separator for "flatten". + - Improved "wreduce" to handle more cases of operator size reduction. + - Updated hashing interface, see docs/source/yosys_internals/hashing.rst + for breaking API changes. + + * New commands and options + - Added "-noscopeinfo" option to "json" and "write_json" pass. + +Yosys 0.47 .. Yosys 0.48 +-------------------------- + * Various + - Removed "read_ilang" deprecated pass. + - Enhanced boxing features in the experimental "abc_new" command. + - Added new Tcl methods for design inspection. + - Added clock enable inference to "dfflibmap". + - Added a Han-Carlson and Sklansky option for $lcu mapping. + + * New commands and options + - Added "-nopeepopt" option to "clk2fflogic" pass. + - Added "-liberty" and "-dont_use" options to "clockgate" pass. + - Added "-ignore_buses" option to "read_liberty" pass. + - Added "-dont_map" option to "techmap" pass. + - Added "-selected" option to "write_json" pass. + - Added "wrapcell" command for creating wrapper modules + around selected cells. + - Added "portarcs" command for deriving propagation timing arcs. + - Added "setenv" command for setting environment variables. + + * Gowin support + - Added "-family" option to "synth_gowin" pass. + - Cell definitions split by family. + + * Verific support + - Improved blackbox support. + +Yosys 0.46 .. Yosys 0.47 +-------------------------- + * Various + - Added cxxopts library for handling command line arguments. + - Added docs generation from cells help output. + + * New commands and options + - Added "-json" option to "synth_xilinx" pass. + - Added "-derive_luts" option to "cellmatch" pass. + - Added "t:@" syntax to "select" pass. + - Added "-list-mod" option to "select" pass. + - Removed deprecated "qwp" pass. + + * Verific support + - Initial state handling for VHDL assertions. + +Yosys 0.45 .. Yosys 0.46 +-------------------------- + * Various + - Added new "functional backend" infrastructure with three example + backends (C++, SMTLIB and Rosette). + - Added new coarse-grain buffer cell type "$buf" to RTLIL. + - Added "-y" command line option to execute a Python script with + libyosys available as a built-in module. + - Added support for casting to type in Verilog frontend. + + * New commands and options + - Added "clockgate" pass for automatic clock gating cell insertion. + - Added "bufnorm" experimental pass to convert design into + buffered-normalized form. + - Added experimental "aiger2" and "xaiger2" backends, and an + experimental "abc_new" command + - Added "-force-detailed-loop-check" option to "check" pass. + - Added "-unit_delay" option to "read_liberty" pass. + + * Verific support + - Added left and right bound properties to wires when using + specific VHDL types. + +Yosys 0.44 .. Yosys 0.45 +-------------------------- + * Various + - Added cell types help messages. + + * New back-ends + - Added initial NG-Ultra support. ( synth_nanoxplore ) + +Yosys 0.43 .. Yosys 0.44 +-------------------------- + * Various + - Added ENABLE_LTO compile option to enable link time + optimizations. + - Build support for Haiku OS. + + * New commands and options + - Added "keep_hierarchy" pass to add attribute with + same name to modules based on cost. + - Added options "-noopt","-bloat" and "-check_cost" to + "test_cell" pass. + + * New back-ends + - Added initial PolarFire support. ( synth_microchip ) + +Yosys 0.42 .. Yosys 0.43 +-------------------------- + * Various + - C++ compiler with C++17 support is required. + - Support for IO liberty files for verification. + - Limit padding from shiftadd for "peepopt" pass. + + * Verific support + - Support building Yosys with various Verific library + configurations. Can be built now without YosysHQ + specific patch and extension library. + Yosys 0.41 .. Yosys 0.42 -------------------------- * New commands and options diff --git a/yosys/CODE_OF_CONDUCT.md b/yosys/CODE_OF_CONDUCT.md new file mode 100644 index 00000000000..ad29106307f --- /dev/null +++ b/yosys/CODE_OF_CONDUCT.md @@ -0,0 +1,128 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at contact@yosyshq.com and/or +claire@clairexen.net. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. diff --git a/yosys/CONTRIBUTING.md b/yosys/CONTRIBUTING.md new file mode 100644 index 00000000000..6c4376cc486 --- /dev/null +++ b/yosys/CONTRIBUTING.md @@ -0,0 +1,73 @@ +# Introduction + +Thanks for thinking about contributing to the Yosys project. If this is your +first time contributing to an open source project, please take a look at the +following guide: +https://opensource.guide/how-to-contribute/#orienting-yourself-to-a-new-project. + +Information about the Yosys coding style is available on our Read the Docs: +https://yosys.readthedocs.io/en/latest/yosys_internals/extending_yosys/contributing.html. + +# Using the issue tracker + +The [issue tracker](https://github.com/YosysHQ/yosys/issues) is used for +tracking bugs or other problems with Yosys or its documentation. It is also the +place to go for requesting new features. +When [creating a new issue](https://github.com/YosysHQ/yosys/issues/new/choose), +we have a few templates available. Please make use of these! It will make it +much easier for someone to respond and help. + +### Bug reports + +Before you submit an issue, please have a search of the existing issues in case +one already exists. Making sure that you have a minimal, complete and +verifiable example (MVCE) is a great way to quickly check an existing issue +against a new one. Stack overflow has a guide on [how to create an +MVCE](https://stackoverflow.com/help/minimal-reproducible-example). The +[`bugpoint` +command](https://yosyshq.readthedocs.io/projects/yosys/en/latest/cmd/bugpoint.html) +in Yosys can be helpful for this process. + + +# Using pull requests + +If you are working on something to add to Yosys, or fix something that isn't +working quite right, make a [PR](https://github.com/YosysHQ/yosys/pulls)! An +open PR, even as a draft, tells everyone that you're working on it and they +don't have to. It can also be a useful way to solicit feedback on in-progress +changes. See below to find the best way to [ask us +questions](#asking-questions). + +In general, all changes to the code are done as a PR, with [Continuous +Integration (CI)](https://github.com/YosysHQ/yosys/actions) tools that +automatically run the full suite of tests compiling and running Yosys. Please +make use of this! If you're adding a feature: add a test! Not only does it +verify that your feature is working as expected, but it can also be a handy way +for people to see how the feature is used. If you're fixing a bug: add a test! +If you can, do this first; it's okay if the test starts off failing - you +already know there is a bug. CI also helps to make sure that your changes still +work under a range of compilers, settings, and targets. + + +### Labels + +We use [labels](https://github.com/YosysHQ/yosys/labels) to help categorise +issues and PRs. If a label seems relevant to your work, please do add it; this +also includes the labels beggining with 'status-'. The 'merge-' labels are used +by maintainers for tracking and communicating which PRs are ready and pending +merge; please do not use these labels if you are not a maintainer. + + +# Asking questions + +If you have a question about how to use Yosys, please ask on our [discussions +page](https://github.com/YosysHQ/yosys/discussions) or in our [community +slack](https://join.slack.com/t/yosyshq/shared_invite/zt-1aopkns2q-EiQ97BeQDt_pwvE41sGSuA). +The slack is also a great place to ask questions about developing or +contributing to Yosys. + +We have open dev 'jour fixe' (JF) meetings where developers from YosysHQ and the +community come together to discuss open issues and PRs. This is also a good +place to talk to us about how to implement larger PRs. Please join the +community slack if you would like to join the next meeting, the link is +available in the description of the #devel-discuss channel. diff --git a/yosys/COPYING b/yosys/COPYING index e8b123be234..2d962dddc80 100644 --- a/yosys/COPYING +++ b/yosys/COPYING @@ -1,6 +1,6 @@ ISC License -Copyright (C) 2012 - 2020 Claire Xenia Wolf +Copyright (C) 2012 - 2025 Claire Xenia Wolf Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above diff --git a/yosys/Dockerfile b/yosys/Dockerfile index 549c73c9712..9806696e051 100644 --- a/yosys/Dockerfile +++ b/yosys/Dockerfile @@ -8,6 +8,7 @@ RUN apt-get update -qq \ && DEBIAN_FRONTEND=noninteractive apt-get -y install --no-install-recommends \ ca-certificates \ clang \ + lld \ curl \ libffi-dev \ libreadline-dev \ diff --git a/yosys/Makefile b/yosys/Makefile index 313de44d56d..74857d3a88d 100644 --- a/yosys/Makefile +++ b/yosys/Makefile @@ -2,9 +2,7 @@ CONFIG := none # CONFIG := clang # CONFIG := gcc -# CONFIG := afl-gcc # CONFIG := wasi -# CONFIG := mxe # CONFIG := msys2-32 # CONFIG := msys2-64 @@ -20,7 +18,7 @@ ENABLE_VERIFIC := 0 ENABLE_VERIFIC_SYSTEMVERILOG := 1 ENABLE_VERIFIC_VHDL := 1 ENABLE_VERIFIC_HIER_TREE := 1 -ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 1 +ENABLE_VERIFIC_YOSYSHQ_EXTENSIONS := 0 ENABLE_VERIFIC_EDIF := 0 ENABLE_VERIFIC_LIBERTY := 0 ENABLE_COVER := 1 @@ -34,10 +32,11 @@ ENABLE_PYOSYS := 0 ENABLE_GCOV := 0 ENABLE_GPROF := 0 ENABLE_DEBUG := 0 -ENABLE_NDEBUG := 0 +ENABLE_LTO := 0 ENABLE_CCACHE := 0 # sccache is not always a drop-in replacement for ccache in practice ENABLE_SCCACHE := 0 +ENABLE_FUNCTIONAL_TESTS := 0 LINK_CURSES := 0 LINK_TERMCAP := 0 LINK_ABC := 0 @@ -53,6 +52,11 @@ SANITIZER = # SANITIZER = undefined # SANITIZER = cfi +# Prefer using ENABLE_DEBUG over setting these +OPT_LEVEL := -O3 +GCC_LTO := +CLANG_LTO := -flto=thin + PROGRAM_PREFIX := OS := $(shell uname -s) @@ -98,6 +102,7 @@ LIBS := $(LIBS) -lstdc++ -lm PLUGIN_LINKFLAGS := PLUGIN_LIBS := EXE_LINKFLAGS := +EXE_LIBS := ifeq ($(OS), MINGW) EXE_LINKFLAGS := -Wl,--export-all-symbols -Wl,--out-implib,libyosys_exe.a PLUGIN_LINKFLAGS += -L"$(LIBDIR)" @@ -110,16 +115,23 @@ BISON ?= bison STRIP ?= strip AWK ?= awk +ifneq ($(shell :; command -v rsync),) +RSYNC_CP ?= rsync -rc +else +RSYNC_CP ?= cp -ru +endif + ifeq ($(OS), Darwin) PLUGIN_LINKFLAGS += -undefined dynamic_lookup +LINKFLAGS += -rdynamic # homebrew search paths ifneq ($(shell :; command -v brew),) BREW_PREFIX := $(shell brew --prefix)/opt $(info $$BREW_PREFIX is [${BREW_PREFIX}]) ifeq ($(ENABLE_PYOSYS),1) -CXXFLAGS += -I$(BREW_PREFIX)/boost/include/boost -LINKFLAGS += -L$(BREW_PREFIX)/boost/lib +CXXFLAGS += -I$(BREW_PREFIX)/boost/include +LINKFLAGS += -L$(BREW_PREFIX)/boost/lib -L$(BREW_PREFIX)/boost-python3/lib endif CXXFLAGS += -I$(BREW_PREFIX)/readline/include LINKFLAGS += -L$(BREW_PREFIX)/readline/lib @@ -143,14 +155,26 @@ LIBS += -lrt endif endif -YOSYS_VER := 0.42+40 +ifeq ($(OS), Haiku) +# Allow usage of non-posix vasprintf, mkstemps functions +CXXFLAGS += -D_DEFAULT_SOURCE +endif + +YOSYS_VER := 0.53+49 +YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1) +YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1) +YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2) +CXXFLAGS += -DYOSYS_VER=\\"$(YOSYS_VER)\\" \ + -DYOSYS_MAJOR=$(YOSYS_MAJOR) \ + -DYOSYS_MINOR=$(YOSYS_MINOR) \ + -DYOSYS_COMMIT=$(YOSYS_COMMIT) # Note: We arrange for .gitcommit to contain the (short) commit hash in # tarballs generated with git-archive(1) using .gitattributes. The git repo # will have this file in its unexpanded form tough, in which case we fall # back to calling git directly. TARBALL_GIT_REV := $(shell cat $(YOSYS_SRC)/.gitcommit) -ifeq ($(TARBALL_GIT_REV),$$Format:%h$$) +ifneq ($(findstring Format:,$(TARBALL_GIT_REV)),) GIT_REV := $(shell GIT_DIR=$(YOSYS_SRC)/.git git rev-parse --short=9 HEAD || echo UNKNOWN) else GIT_REV := $(TARBALL_GIT_REV) @@ -159,7 +183,7 @@ endif OBJS = kernel/version_$(GIT_REV).o bumpversion: - sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 9b6afcf.. | wc -l`/;" Makefile + sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 53c22ab.. | wc -l`/;" Makefile ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 ABC_USE_NAMESPACE=abc VERBOSE=$(Q) @@ -180,17 +204,17 @@ endif include Makefile.conf endif -PYTHON_EXECUTABLE := $(shell if python3 -c ""; then echo "python3"; else echo "python"; fi) +PYTHON_EXECUTABLE ?= $(shell if python3 -c ""; then echo "python3"; else echo "python"; fi) ifeq ($(ENABLE_PYOSYS),1) PYTHON_VERSION_TESTCODE := "import sys;t='{v[0]}.{v[1]}'.format(v=list(sys.version_info[:2]));print(t)" PYTHON_VERSION := $(shell $(PYTHON_EXECUTABLE) -c ""$(PYTHON_VERSION_TESTCODE)"") PYTHON_MAJOR_VERSION := $(shell echo $(PYTHON_VERSION) | cut -f1 -d.) -ENABLE_PYTHON_CONFIG_EMBED ?= $(shell $(PYTHON_EXECUTABLE)-config --embed --libs > /dev/null && echo 1) -ifeq ($(ENABLE_PYTHON_CONFIG_EMBED),1) -PYTHON_CONFIG := $(PYTHON_EXECUTABLE)-config --embed -else PYTHON_CONFIG := $(PYTHON_EXECUTABLE)-config +PYTHON_CONFIG_FOR_EXE := $(PYTHON_CONFIG) +PYTHON_CONFIG_EMBED_AVAILABLE ?= $(shell $(PYTHON_EXECUTABLE)-config --embed --libs > /dev/null && echo 1) +ifeq ($(PYTHON_CONFIG_EMBED_AVAILABLE),1) +PYTHON_CONFIG_FOR_EXE := $(PYTHON_CONFIG) --embed endif PYTHON_DESTDIR := $(shell $(PYTHON_EXECUTABLE) -c "import site; print(site.getsitepackages()[-1]);") @@ -207,10 +231,17 @@ ifeq ($(OS), OpenBSD) ABC_ARCHFLAGS += "-DABC_NO_RLIMIT" endif +# This gets overridden later. +LTOFLAGS := $(GCC_LTO) + ifeq ($(CONFIG),clang) CXX = clang++ -CXXFLAGS += -std=$(CXXSTD) -Os +CXXFLAGS += -std=$(CXXSTD) $(OPT_LEVEL) +ifeq ($(ENABLE_LTO),1) +LINKFLAGS += -fuse-ld=lld +endif ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H $(ABC_ARCHFLAGS)" +LTOFLAGS := $(CLANG_LTO) ifneq ($(SANITIZER),) $(info [Clang Sanitizer] $(SANITIZER)) @@ -226,35 +257,26 @@ endif ifneq ($(findstring cfi,$(SANITIZER)),) CXXFLAGS += -flto LINKFLAGS += -flto +LTOFLAGS = endif endif else ifeq ($(CONFIG),gcc) CXX = g++ -CXXFLAGS += -std=$(CXXSTD) -Os +CXXFLAGS += -std=$(CXXSTD) $(OPT_LEVEL) ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H $(ABC_ARCHFLAGS)" else ifeq ($(CONFIG),gcc-static) LINKFLAGS := $(filter-out -rdynamic,$(LINKFLAGS)) -static LIBS := $(filter-out -lrt,$(LIBS)) CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS)) -CXXFLAGS += -std=$(CXXSTD) -Os +CXXFLAGS += -std=$(CXXSTD) $(OPT_LEVEL) ABCMKARGS = CC="$(CC)" CXX="$(CXX)" LD="$(CXX)" ABC_USE_LIBSTDCXX=1 LIBS="-lm -lpthread -static" OPTFLAGS="-O" \ ARCHFLAGS="-DABC_USE_STDINT_H -DABC_NO_DYNAMIC_LINKING=1 -Wno-unused-but-set-variable $(ARCHFLAGS)" ABC_USE_NO_READLINE=1 ifeq ($(DISABLE_ABC_THREADS),1) ABCMKARGS += "ABC_USE_NO_PTHREADS=1" endif -else ifeq ($(CONFIG),afl-gcc) -CXX = AFL_QUIET=1 AFL_HARDEN=1 afl-gcc -CXXFLAGS += -std=$(CXXSTD) -Os -ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H" - -else ifeq ($(CONFIG),cygwin) -CXX = g++ -CXXFLAGS += -std=gnu++11 -Os -ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H" - else ifeq ($(CONFIG),wasi) ifeq ($(WASI_SDK),) CXX = clang++ @@ -267,7 +289,7 @@ AR = $(WASI_SDK)/bin/ar RANLIB = $(WASI_SDK)/bin/ranlib WASIFLAGS := --sysroot $(WASI_SDK)/share/wasi-sysroot $(WASIFLAGS) endif -CXXFLAGS := $(WASIFLAGS) -std=$(CXXSTD) -Os -D_WASI_EMULATED_PROCESS_CLOCKS $(filter-out -fPIC,$(CXXFLAGS)) +CXXFLAGS := $(WASIFLAGS) -std=$(CXXSTD) $(OPT_LEVEL) -D_WASI_EMULATED_PROCESS_CLOCKS $(filter-out -fPIC,$(CXXFLAGS)) LINKFLAGS := $(WASIFLAGS) -Wl,-z,stack-size=1048576 $(filter-out -rdynamic,$(LINKFLAGS)) LIBS := -lwasi-emulated-process-clocks $(filter-out -lrt,$(LIBS)) ABCMKARGS += AR="$(AR)" RANLIB="$(RANLIB)" @@ -282,44 +304,39 @@ LINK_ABC := 1 DISABLE_ABC_THREADS := 1 endif -else ifeq ($(CONFIG),mxe) -PKG_CONFIG = /usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-pkg-config -CXX = /usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-g++ -CXXFLAGS += -std=$(CXXSTD) -Os -D_POSIX_SOURCE -DYOSYS_MXE_HACKS -Wno-attributes -CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS)) -LINKFLAGS := $(filter-out -rdynamic,$(LINKFLAGS)) -s -LIBS := $(filter-out -lrt,$(LIBS)) -ABCMKARGS += ARCHFLAGS="-DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w" -# TODO: Try to solve pthread linking issue in more appropriate way -ABCMKARGS += LIBS="lib/x86/pthreadVC2.lib -s" LINKFLAGS="-Wl,--allow-multiple-definition" ABC_USE_NO_READLINE=1 CC="/usr/local/src/mxe/usr/bin/i686-w64-mingw32.static-gcc" -EXE = .exe - else ifeq ($(CONFIG),msys2-32) CXX = i686-w64-mingw32-g++ -CXXFLAGS += -std=$(CXXSTD) -Os -D_POSIX_SOURCE -DYOSYS_WIN32_UNIX_DIR +CXXFLAGS += -std=$(CXXSTD) $(OPT_LEVEL) -D_POSIX_SOURCE -DYOSYS_WIN32_UNIX_DIR CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS)) LINKFLAGS := $(filter-out -rdynamic,$(LINKFLAGS)) -s LIBS := $(filter-out -lrt,$(LIBS)) -ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w" +ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DWIN32_NO_DLL -DWIN32 -DHAVE_STRUCT_TIMESPEC -fpermissive -w" ABCMKARGS += LIBS="-lpthread -lshlwapi -s" ABC_USE_NO_READLINE=0 CC="i686-w64-mingw32-gcc" CXX="$(CXX)" EXE = .exe else ifeq ($(CONFIG),msys2-64) CXX = x86_64-w64-mingw32-g++ -CXXFLAGS += -std=$(CXXSTD) -Os -D_POSIX_SOURCE -DYOSYS_WIN32_UNIX_DIR +CXXFLAGS += -std=$(CXXSTD) $(OPT_LEVEL) -D_POSIX_SOURCE -DYOSYS_WIN32_UNIX_DIR CXXFLAGS := $(filter-out -fPIC,$(CXXFLAGS)) LINKFLAGS := $(filter-out -rdynamic,$(LINKFLAGS)) -s LIBS := $(filter-out -lrt,$(LIBS)) -ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DWIN32_NO_DLL -DHAVE_STRUCT_TIMESPEC -fpermissive -w" +ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H -DWIN32_NO_DLL -DWIN32 -DHAVE_STRUCT_TIMESPEC -fpermissive -w" ABCMKARGS += LIBS="-lpthread -lshlwapi -s" ABC_USE_NO_READLINE=0 CC="x86_64-w64-mingw32-gcc" CXX="$(CXX)" EXE = .exe else ifeq ($(CONFIG),none) -CXXFLAGS += -std=$(CXXSTD) -Os +CXXFLAGS += -std=$(CXXSTD) $(OPT_LEVEL) ABCMKARGS += ARCHFLAGS="-DABC_USE_STDINT_H $(ABC_ARCHFLAGS)" +LTOFLAGS = else -$(error Invalid CONFIG setting '$(CONFIG)'. Valid values: clang, gcc, mxe, msys2-32, msys2-64, none) +$(error Invalid CONFIG setting '$(CONFIG)'. Valid values: clang, gcc, msys2-32, msys2-64, none) +endif + + +ifeq ($(ENABLE_LTO),1) +CXXFLAGS += $(LTOFLAGS) +LINKFLAGS += $(LTOFLAGS) endif ifeq ($(ENABLE_LIBYOSYS),1) @@ -327,8 +344,14 @@ TARGETS += libyosys.so endif ifeq ($(ENABLE_PYOSYS),1) +# python-config --ldflags includes -l and -L, but LINKFLAGS is only -L +LINKFLAGS += $(filter-out -l%,$(shell $(PYTHON_CONFIG) --ldflags)) +LIBS += $(shell $(PYTHON_CONFIG) --libs) +EXE_LIBS += $(filter-out $(LIBS),$(shell $(PYTHON_CONFIG_FOR_EXE) --libs)) +CXXFLAGS += $(shell $(PYTHON_CONFIG) --includes) -DWITH_PYTHON + # Detect name of boost_python library. Some distros use boost_python-py, other boost_python, some only use the major version number, some a concatenation of major and minor version numbers -CHECK_BOOST_PYTHON = (echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(shell $(PYTHON_CONFIG) --ldflags) -l$(1) - > /dev/null 2>&1 && echo "-l$(1)") +CHECK_BOOST_PYTHON = (echo "int main(int argc, char ** argv) {return 0;}" | $(CXX) -xc -o /dev/null $(LINKFLAGS) $(EXE_LIBS) $(LIBS) -l$(1) - > /dev/null 2>&1 && echo "-l$(1)") BOOST_PYTHON_LIB ?= $(shell \ $(call CHECK_BOOST_PYTHON,boost_python-py$(subst .,,$(PYTHON_VERSION))) || \ $(call CHECK_BOOST_PYTHON,boost_python-py$(PYTHON_MAJOR_VERSION)) || \ @@ -340,15 +363,11 @@ ifeq ($(BOOST_PYTHON_LIB),) $(error BOOST_PYTHON_LIB could not be detected. Please define manually) endif -LIBS += $(shell $(PYTHON_CONFIG) --libs) $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem -# python-config --ldflags includes LIBS for some reason -LINKFLAGS += $(filter-out -l%,$(shell $(PYTHON_CONFIG) --ldflags)) -CXXFLAGS += $(shell $(PYTHON_CONFIG) --includes) -DWITH_PYTHON - +LIBS += $(BOOST_PYTHON_LIB) -lboost_system -lboost_filesystem PY_WRAPPER_FILE = kernel/python_wrappers OBJS += $(PY_WRAPPER_FILE).o PY_GEN_SCRIPT= py_wrap_generator -PY_WRAP_INCLUDES := $(shell python$(PYTHON_VERSION) -c "from misc import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).print_includes()") +PY_WRAP_INCLUDES := $(shell $(PYTHON_EXECUTABLE) -c "from misc import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).print_includes()") endif # ENABLE_PYOSYS ifeq ($(ENABLE_READLINE),1) @@ -365,22 +384,22 @@ ifeq ($(LINK_TERMCAP),1) LIBS += -ltermcap ABCMKARGS += "ABC_READLINE_LIBRARIES=-lreadline -ltermcap" endif -ifeq ($(CONFIG),mxe) -LIBS += -ltermcap -endif else ifeq ($(ENABLE_EDITLINE),1) CXXFLAGS += -DYOSYS_ENABLE_EDITLINE -LIBS += -ledit -ltinfo -lbsd -else -ABCMKARGS += "ABC_USE_NO_READLINE=1" +LIBS += -ledit endif +ABCMKARGS += "ABC_USE_NO_READLINE=1" endif ifeq ($(DISABLE_ABC_THREADS),1) ABCMKARGS += "ABC_USE_NO_PTHREADS=1" endif +ifeq ($(LINK_ABC),1) +ABCMKARGS += "ABC_USE_PIC=1" +endif + ifeq ($(DISABLE_SPAWN),1) CXXFLAGS += -DYOSYS_DISABLE_SPAWN endif @@ -417,12 +436,10 @@ TCL_INCLUDE ?= /usr/include/$(TCL_VERSION) TCL_LIBS ?= -l$(TCL_VERSION) endif -ifeq ($(CONFIG),mxe) -CXXFLAGS += -DYOSYS_ENABLE_TCL -LIBS += -ltcl86 -lwsock32 -lws2_32 -lnetapi32 -lz -luserenv -else CXXFLAGS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --cflags tcl || echo -I$(TCL_INCLUDE)) -DYOSYS_ENABLE_TCL LIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --libs tcl || echo $(TCL_LIBS)) +ifneq (,$(findstring TCL_WITH_EXTERNAL_TOMMATH,$(CXXFLAGS))) +LIBS += $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) $(PKG_CONFIG) --silence-errors --libs libtommath || echo) endif endif @@ -436,16 +453,8 @@ CXXFLAGS += -pg LINKFLAGS += -pg endif -ifeq ($(ENABLE_NDEBUG),1) -CXXFLAGS := -O3 -DNDEBUG $(filter-out -Os -ggdb,$(CXXFLAGS)) -endif - ifeq ($(ENABLE_DEBUG),1) -ifeq ($(CONFIG),clang) -CXXFLAGS := -O0 -DDEBUG $(filter-out -Os,$(CXXFLAGS)) -else -CXXFLAGS := -Og -DDEBUG $(filter-out -Os,$(CXXFLAGS)) -endif +CXXFLAGS := -Og -DDEBUG $(filter-out $(OPT_LEVEL),$(CXXFLAGS)) endif ifeq ($(ENABLE_ABC),1) @@ -574,12 +583,14 @@ S = endif $(eval $(call add_include_file,kernel/binding.h)) +$(eval $(call add_include_file,kernel/bitpattern.h)) $(eval $(call add_include_file,kernel/cellaigs.h)) $(eval $(call add_include_file,kernel/celledges.h)) $(eval $(call add_include_file,kernel/celltypes.h)) $(eval $(call add_include_file,kernel/consteval.h)) $(eval $(call add_include_file,kernel/constids.inc)) $(eval $(call add_include_file,kernel/cost.h)) +$(eval $(call add_include_file,kernel/drivertools.h)) $(eval $(call add_include_file,kernel/ff.h)) $(eval $(call add_include_file,kernel/ffinit.h)) $(eval $(call add_include_file,kernel/ffmerge.h)) @@ -587,7 +598,9 @@ $(eval $(call add_include_file,kernel/fmt.h)) ifeq ($(ENABLE_ZLIB),1) $(eval $(call add_include_file,kernel/fstdata.h)) endif +$(eval $(call add_include_file,kernel/gzip.h)) $(eval $(call add_include_file,kernel/hashlib.h)) +$(eval $(call add_include_file,kernel/io.h)) $(eval $(call add_include_file,kernel/json.h)) $(eval $(call add_include_file,kernel/log.h)) $(eval $(call add_include_file,kernel/macc.h)) @@ -598,6 +611,7 @@ $(eval $(call add_include_file,kernel/register.h)) $(eval $(call add_include_file,kernel/rtlil.h)) $(eval $(call add_include_file,kernel/satgen.h)) $(eval $(call add_include_file,kernel/scopeinfo.h)) +$(eval $(call add_include_file,kernel/sexpr.h)) $(eval $(call add_include_file,kernel/sigtools.h)) $(eval $(call add_include_file,kernel/timinginfo.h)) $(eval $(call add_include_file,kernel/utils.h)) @@ -617,9 +631,10 @@ $(eval $(call add_include_file,frontends/ast/ast_binding.h)) $(eval $(call add_include_file,frontends/blif/blifparse.h)) $(eval $(call add_include_file,backends/rtlil/rtlil_backend.h)) -OBJS += kernel/driver.o kernel/register.o kernel/rtlil.o kernel/log.o kernel/calc.o kernel/yosys.o -OBJS += kernel/binding.o -OBJS += kernel/cellaigs.o kernel/celledges.o kernel/satgen.o kernel/scopeinfo.o kernel/qcsat.o kernel/mem.o kernel/ffmerge.o kernel/ff.o kernel/yw.o kernel/json.o kernel/fmt.o +OBJS += kernel/driver.o kernel/register.o kernel/rtlil.o kernel/log.o kernel/calc.o kernel/yosys.o kernel/io.o kernel/gzip.o +OBJS += kernel/binding.o kernel/tclapi.o +OBJS += kernel/cellaigs.o kernel/celledges.o kernel/cost.o kernel/satgen.o kernel/scopeinfo.o kernel/qcsat.o kernel/mem.o kernel/ffmerge.o kernel/ff.o kernel/yw.o kernel/json.o kernel/fmt.o kernel/sexpr.o +OBJS += kernel/drivertools.o kernel/functional.o ifeq ($(ENABLE_ZLIB),1) OBJS += kernel/fstdata.o endif @@ -658,6 +673,9 @@ OBJS += libs/fst/fastlz.o OBJS += libs/fst/lz4.o endif +techlibs/%_pm.h: passes/pmgen/pmgen.py techlibs/%.pmg + $(P) mkdir -p $(dir $@) && $(PYTHON_EXECUTABLE) $< -o $@ -p $(notdir $*) $(filter-out $<,$^) + ifneq ($(SMALL),1) OBJS += libs/subcircuit/subcircuit.o @@ -715,12 +733,18 @@ compile-only: $(OBJS) $(GENFILES) $(EXTRA_TARGETS) @echo " Compile successful." @echo "" +.PHONY: share +share: $(EXTRA_TARGETS) + @echo "" + @echo " Share directory created." + @echo "" + $(PROGRAM_PREFIX)yosys$(EXE): $(OBJS) - $(P) $(CXX) -o $(PROGRAM_PREFIX)yosys$(EXE) $(EXE_LINKFLAGS) $(LINKFLAGS) $(OBJS) $(LIBS) $(LIBS_VERIFIC) + $(P) $(CXX) -o $(PROGRAM_PREFIX)yosys$(EXE) $(EXE_LINKFLAGS) $(LINKFLAGS) $(OBJS) $(EXE_LIBS) $(LIBS) $(LIBS_VERIFIC) libyosys.so: $(filter-out kernel/driver.o,$(OBJS)) ifeq ($(OS), Darwin) - $(P) $(CXX) -o libyosys.so -shared -Wl,-install_name,$(LIBDIR)/libyosys.so $(LINKFLAGS) $^ $(LIBS) $(LIBS_VERIFIC) + $(P) $(CXX) -o libyosys.so -shared -undefined dynamic_lookup -Wl,-install_name,$(LIBDIR)/libyosys.so $(LINKFLAGS) $^ $(LIBS) $(LIBS_VERIFIC) else $(P) $(CXX) -o libyosys.so -shared -Wl,-soname,$(LIBDIR)/libyosys.so $(LINKFLAGS) $^ $(LIBS) $(LIBS_VERIFIC) endif @@ -736,7 +760,7 @@ endif ifeq ($(ENABLE_PYOSYS),1) $(PY_WRAPPER_FILE).cc: misc/$(PY_GEN_SCRIPT).py $(PY_WRAP_INCLUDES) $(Q) mkdir -p $(dir $@) - $(P) python$(PYTHON_VERSION) -c "from misc import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).gen_wrappers(\"$(PY_WRAPPER_FILE).cc\")" + $(P) $(PYTHON_EXECUTABLE) -c "from misc import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).gen_wrappers(\"$(PY_WRAPPER_FILE).cc\")" endif %.o: %.cpp @@ -767,16 +791,25 @@ $(PROGRAM_PREFIX)yosys-config: misc/yosys-config.in $(YOSYS_SRC)/Makefile .PHONY: check-git-abc check-git-abc: - @if [ ! -d "$(YOSYS_SRC)/abc" ]; then \ + @if [ ! -d "$(YOSYS_SRC)/abc" ] && git -C "$(YOSYS_SRC)" status >/dev/null 2>&1; then \ echo "Error: The 'abc' directory does not exist."; \ echo "Initialize the submodule: Run 'git submodule update --init' to set up 'abc' as a submodule."; \ exit 1; \ elif git -C "$(YOSYS_SRC)" submodule status abc 2>/dev/null | grep -q '^ '; then \ exit 0; \ - elif [ -f "$(YOSYS_SRC)/abc/.gitcommit" ] && ! grep -q '\$$Format:%h\$$' "$(YOSYS_SRC)/abc/.gitcommit"; then \ + elif [ -f "$(YOSYS_SRC)/abc/.gitcommit" ] && ! grep -q '\$$Format:%[hH]\$$' "$(YOSYS_SRC)/abc/.gitcommit"; then \ echo "'abc' comes from a tarball. Continuing."; \ exit 0; \ - elif [ -f "$(YOSYS_SRC)/abc/.gitcommit" ] && grep -q '\$$Format:%h\$$' "$(YOSYS_SRC)/abc/.gitcommit"; then \ + elif git -C "$(YOSYS_SRC)" submodule status abc 2>/dev/null | grep -q '^+'; then \ + echo "'abc' submodule does not match expected commit."; \ + echo "Run 'git submodule update' to check out the correct version."; \ + echo "Note: If testing a different version of abc, call 'git commit abc' in the Yosys source directory to update the expected commit."; \ + exit 1; \ + elif git -C "$(YOSYS_SRC)" submodule status abc 2>/dev/null | grep -q '^U'; then \ + echo "'abc' submodule has merge conflicts."; \ + echo "Please resolve merge conflicts before continuing."; \ + exit 1; \ + elif [ -f "$(YOSYS_SRC)/abc/.gitcommit" ] && grep -q '\$$Format:%[hH]\$$' "$(YOSYS_SRC)/abc/.gitcommit"; then \ echo "Error: 'abc' is not configured as a git submodule."; \ echo "To resolve this:"; \ echo "1. Back up your changes: Save any modifications from the 'abc' directory to another location."; \ @@ -784,12 +817,18 @@ check-git-abc: echo "3. Initialize the submodule: Run 'git submodule update --init' to set up 'abc' as a submodule."; \ echo "4. Reapply your changes: Move your saved changes back to the 'abc' directory, if necessary."; \ exit 1; \ + elif ! git -C "$(YOSYS_SRC)" status >/dev/null 2>&1; then \ + echo "$(realpath $(YOSYS_SRC)) is not configured as a git repository, and 'abc' folder is missing."; \ + echo "If you already have ABC, set 'ABCEXTERNAL' make variable to point to ABC executable."; \ + echo "Otherwise, download release archive 'yosys.tar.gz' from https://github.com/YosysHQ/yosys/releases."; \ + echo " ('Source code' archive does not contain submodules.)"; \ + exit 1; \ else \ echo "Initialize the submodule: Run 'git submodule update --init' to set up 'abc' as a submodule."; \ exit 1; \ fi -abc/abc$(EXE) abc/libabc.a: check-git-abc +abc/abc$(EXE) abc/libabc.a: | check-git-abc $(P) $(Q) mkdir -p abc && $(MAKE) -C $(PROGRAM_PREFIX)abc -f "$(realpath $(YOSYS_SRC)/abc/Makefile)" ABCSRC="$(realpath $(YOSYS_SRC)/abc/)" $(S) $(ABCMKARGS) $(if $(filter %.a,$@),PROG="abc",PROG="abc$(EXE)") MSG_PREFIX="$(eval P_OFFSET = 5)$(call P_SHOW)$(eval P_OFFSET = 10) ABC: " $(if $(filter %.a,$@),libabc.a) @@ -811,66 +850,103 @@ else ABCOPT="" endif -# When YOSYS_NOVERIFIC is set as a make variable, also export it to the -# enviornment, so that `YOSYS_NOVERIFIC=1 make test` _and_ -# `make test YOSYS_NOVERIFIC=1` will run with verific disabled. -ifeq ($(YOSYS_NOVERIFIC),1) -export YOSYS_NOVERIFIC -endif - -test: $(TARGETS) $(EXTRA_TARGETS) +# Tests that generate .mk with tests/gen-tests-makefile.sh +MK_TEST_DIRS = +MK_TEST_DIRS += tests/arch/anlogic +MK_TEST_DIRS += tests/arch/ecp5 +MK_TEST_DIRS += tests/arch/efinix +MK_TEST_DIRS += tests/arch/gatemate +MK_TEST_DIRS += tests/arch/gowin +MK_TEST_DIRS += tests/arch/ice40 +MK_TEST_DIRS += tests/arch/intel_alm +MK_TEST_DIRS += tests/arch/machxo2 +MK_TEST_DIRS += tests/arch/microchip +MK_TEST_DIRS += tests/arch/nanoxplore +MK_TEST_DIRS += tests/arch/nexus +MK_TEST_DIRS += tests/arch/quicklogic/pp3 +MK_TEST_DIRS += tests/arch/quicklogic/qlf_k6n10f +MK_TEST_DIRS += tests/arch/xilinx +MK_TEST_DIRS += tests/opt +MK_TEST_DIRS += tests/sat +MK_TEST_DIRS += tests/sim +MK_TEST_DIRS += tests/svtypes +MK_TEST_DIRS += tests/techmap +MK_TEST_DIRS += tests/various ifeq ($(ENABLE_VERIFIC),1) -ifeq ($(YOSYS_NOVERIFIC),1) - @echo - @echo "Running tests without verific support due to YOSYS_NOVERIFIC=1" - @echo -else - +cd tests/verific && bash run-test.sh $(SEEDOPT) -endif -endif - +cd tests/simple && bash run-test.sh $(SEEDOPT) - +cd tests/simple_abc9 && bash run-test.sh $(SEEDOPT) - +cd tests/hana && bash run-test.sh $(SEEDOPT) - +cd tests/asicworld && bash run-test.sh $(SEEDOPT) - # +cd tests/realmath && bash run-test.sh $(SEEDOPT) - +cd tests/share && bash run-test.sh $(SEEDOPT) - +cd tests/opt_share && bash run-test.sh $(SEEDOPT) - +cd tests/fsm && bash run-test.sh $(SEEDOPT) - +cd tests/techmap && bash run-test.sh - +cd tests/memories && bash run-test.sh $(ABCOPT) $(SEEDOPT) - +cd tests/memlib && bash run-test.sh $(SEEDOPT) - +cd tests/bram && bash run-test.sh $(SEEDOPT) - +cd tests/various && bash run-test.sh - +cd tests/select && bash run-test.sh - +cd tests/sat && bash run-test.sh - +cd tests/sim && bash run-test.sh - +cd tests/svinterfaces && bash run-test.sh $(SEEDOPT) - +cd tests/svtypes && bash run-test.sh $(SEEDOPT) - +cd tests/proc && bash run-test.sh - +cd tests/blif && bash run-test.sh - +cd tests/opt && bash run-test.sh - +cd tests/aiger && bash run-test.sh $(ABCOPT) - +cd tests/arch && bash run-test.sh - +cd tests/arch/ice40 && bash run-test.sh $(SEEDOPT) - +cd tests/arch/xilinx && bash run-test.sh $(SEEDOPT) - +cd tests/arch/ecp5 && bash run-test.sh $(SEEDOPT) - +cd tests/arch/machxo2 && bash run-test.sh $(SEEDOPT) - +cd tests/arch/efinix && bash run-test.sh $(SEEDOPT) - +cd tests/arch/anlogic && bash run-test.sh $(SEEDOPT) - +cd tests/arch/gowin && bash run-test.sh $(SEEDOPT) - +cd tests/arch/intel_alm && bash run-test.sh $(SEEDOPT) - +cd tests/arch/nexus && bash run-test.sh $(SEEDOPT) - +cd tests/arch/quicklogic/pp3 && bash run-test.sh $(SEEDOPT) - +cd tests/arch/quicklogic/qlf_k6n10f && bash run-test.sh $(SEEDOPT) - +cd tests/arch/gatemate && bash run-test.sh $(SEEDOPT) - +cd tests/rpc && bash run-test.sh - +cd tests/memfile && bash run-test.sh - +cd tests/verilog && bash run-test.sh - +cd tests/xprop && bash run-test.sh $(SEEDOPT) - +cd tests/fmt && bash run-test.sh - +cd tests/cxxrtl && bash run-test.sh +ifneq ($(YOSYS_NOVERIFIC),1) +MK_TEST_DIRS += tests/verific +endif +endif +MK_TEST_DIRS += tests/verilog + +# Tests that don't generate .mk +SH_TEST_DIRS = +SH_TEST_DIRS += tests/simple +SH_TEST_DIRS += tests/simple_abc9 +SH_TEST_DIRS += tests/hana +SH_TEST_DIRS += tests/asicworld +# SH_TEST_DIRS += tests/realmath +SH_TEST_DIRS += tests/share +SH_TEST_DIRS += tests/opt_share +SH_TEST_DIRS += tests/fsm +SH_TEST_DIRS += tests/memlib +SH_TEST_DIRS += tests/bram +SH_TEST_DIRS += tests/svinterfaces +SH_TEST_DIRS += tests/xprop +SH_TEST_DIRS += tests/select +SH_TEST_DIRS += tests/peepopt +SH_TEST_DIRS += tests/proc +SH_TEST_DIRS += tests/blif +SH_TEST_DIRS += tests/arch +SH_TEST_DIRS += tests/rpc +SH_TEST_DIRS += tests/memfile +SH_TEST_DIRS += tests/fmt +SH_TEST_DIRS += tests/cxxrtl +SH_TEST_DIRS += tests/liberty +ifeq ($(ENABLE_FUNCTIONAL_TESTS),1) +SH_TEST_DIRS += tests/functional +endif + +# Tests that don't generate .mk and need special args +SH_ABC_TEST_DIRS = +SH_ABC_TEST_DIRS += tests/memories +SH_ABC_TEST_DIRS += tests/aiger +SH_ABC_TEST_DIRS += tests/alumacc + +# seed-tests/ is a dummy string, not a directory +.PHONY: seed-tests +seed-tests: $(SH_TEST_DIRS:%=seed-tests/%) +.PHONY: seed-tests/% +seed-tests/%: %/run-test.sh $(TARGETS) $(EXTRA_TARGETS) + +cd $* && bash run-test.sh $(SEEDOPT) + +@echo "...passed tests in $*" + +# abcopt-tests/ is a dummy string, not a directory +.PHONY: abcopt-tests +abcopt-tests: $(SH_ABC_TEST_DIRS:%=abcopt-tests/%) +abcopt-tests/%: %/run-test.sh $(TARGETS) $(EXTRA_TARGETS) + +cd $* && bash run-test.sh $(ABCOPT) $(SEEDOPT) + +@echo "...passed tests in $*" + +# makefile-tests/ is a dummy string, not a directory +.PHONY: makefile-tests +makefile-tests: $(MK_TEST_DIRS:%=makefile-tests/%) +# this target actually emits .mk files +%.mk: + +cd $(dir $*) && bash run-test.sh +# this one spawns submake on each +makefile-tests/%: %/run-test.mk $(TARGETS) $(EXTRA_TARGETS) + $(MAKE) -C $* -f run-test.mk + +@echo "...passed tests in $*" + +test: makefile-tests abcopt-tests seed-tests @echo "" @echo " Passed \"make test\"." +ifeq ($(ENABLE_VERIFIC),1) +ifeq ($(YOSYS_NOVERIFIC),1) + @echo " Ran tests without verific support due to YOSYS_NOVERIFIC=1." +endif +endif @echo "" VALGRIND ?= valgrind --error-exitcode=1 --leak-check=full --show-reachable=yes --errors-for-leak-kinds=all @@ -897,8 +973,8 @@ ystests: $(TARGETS) $(EXTRA_TARGETS) # Unit test unit-test: libyosys.so - @$(MAKE) -C $(UNITESTPATH) CXX="$(CXX)" CPPFLAGS="$(CPPFLAGS)" \ - CXXFLAGS="$(CXXFLAGS)" LIBS="$(LIBS)" ROOTPATH="$(CURDIR)" + @$(MAKE) -C $(UNITESTPATH) CXX="$(CXX)" CC="$(CC)" CPPFLAGS="$(CPPFLAGS)" \ + CXXFLAGS="$(CXXFLAGS)" LINKFLAGS="$(LINKFLAGS)" LIBS="$(LIBS)" ROOTPATH="$(CURDIR)" clean-unit-test: @$(MAKE) -C $(UNITESTPATH) clean @@ -924,6 +1000,10 @@ ifeq ($(ENABLE_LIBYOSYS),1) ifeq ($(ENABLE_PYOSYS),1) $(INSTALL_SUDO) mkdir -p $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys $(INSTALL_SUDO) cp libyosys.so $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/libyosys.so + $(INSTALL_SUDO) cp -r share $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys +ifeq ($(ENABLE_ABC),1) + $(INSTALL_SUDO) cp yosys-abc $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/yosys-abc +endif $(INSTALL_SUDO) cp misc/__init__.py $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/ endif endif @@ -948,27 +1028,46 @@ endif # also others, but so long as it doesn't fail this is enough to know we tried docs/source/cmd/abc.rst: $(TARGETS) $(EXTRA_TARGETS) - mkdir -p docs/source/cmd - ./$(PROGRAM_PREFIX)yosys -p 'help -write-rst-command-reference-manual' - -PHONY: docs/gen_examples docs/gen_images docs/guidelines docs/usage docs/reqs -docs/gen_examples: - $(Q) $(MAKE) -C docs examples - -docs/gen_images: - $(Q) $(MAKE) -C docs images - -DOCS_GUIDELINE_FILES := GettingStarted CodingStyle -docs/guidelines docs/source/generated: + $(Q) mkdir -p docs/source/cmd + $(Q) mkdir -p temp/docs/source/cmd + $(Q) cd temp && ./../$(PROGRAM_PREFIX)yosys -p 'help -write-rst-command-reference-manual' + $(Q) $(RSYNC_CP) temp/docs/source/cmd docs/source + $(Q) rm -rf temp +docs/source/cell/word_add.rst: $(TARGETS) $(EXTRA_TARGETS) + $(Q) mkdir -p docs/source/cell + $(Q) mkdir -p temp/docs/source/cell + $(Q) cd temp && ./../$(PROGRAM_PREFIX)yosys -p 'help -write-rst-cells-manual' + $(Q) $(RSYNC_CP) temp/docs/source/cell docs/source + $(Q) rm -rf temp + +docs/source/generated/cells.json: docs/source/generated $(TARGETS) $(EXTRA_TARGETS) + $(Q) ./$(PROGRAM_PREFIX)yosys -p 'help -dump-cells-json $@' + +docs/source/generated/%.cc: backends/%.cc + $(Q) mkdir -p $(@D) + $(Q) cp $< $@ + +# diff returns exit code 1 if the files are different, but it's not an error +docs/source/generated/functional/rosette.diff: backends/functional/smtlib.cc backends/functional/smtlib_rosette.cc + $(Q) mkdir -p $(@D) + $(Q) diff -U 20 $^ > $@ || exit 0 + +PHONY: docs/gen/functional_ir +docs/gen/functional_ir: docs/source/generated/functional/smtlib.cc docs/source/generated/functional/rosette.diff + +PHONY: docs/gen docs/usage docs/reqs +docs/gen: $(TARGETS) + $(Q) $(MAKE) -C docs gen + +docs/source/generated: $(Q) mkdir -p docs/source/generated - $(Q) cp -f $(addprefix guidelines/,$(DOCS_GUIDELINE_FILES)) docs/source/generated # some commands return an error and print the usage text to stderr define DOC_USAGE_STDERR -docs/source/generated/$(1): $(PROGRAM_PREFIX)$(1) docs/source/generated - -$(Q) ./$$< --help 2> $$@ +docs/source/generated/$(1): $(TARGETS) docs/source/generated FORCE + -$(Q) ./$(PROGRAM_PREFIX)$(1) --help 2> $$@ endef -DOCS_USAGE_STDERR := yosys-config yosys-filterlib +DOCS_USAGE_STDERR := yosys-filterlib # The in-tree ABC (yosys-abc) is only built when ABCEXTERNAL is not set. ifeq ($(ABCEXTERNAL),) @@ -979,10 +1078,10 @@ $(foreach usage,$(DOCS_USAGE_STDERR),$(eval $(call DOC_USAGE_STDERR,$(usage)))) # others print to stdout define DOC_USAGE_STDOUT -docs/source/generated/$(1): $(PROGRAM_PREFIX)$(1) docs/source/generated - $(Q) ./$$< --help > $$@ +docs/source/generated/$(1): $(TARGETS) docs/source/generated + $(Q) ./$(PROGRAM_PREFIX)$(1) --help > $$@ || rm $$@ endef -DOCS_USAGE_STDOUT := yosys yosys-smtbmc yosys-witness +DOCS_USAGE_STDOUT := yosys yosys-smtbmc yosys-witness yosys-config $(foreach usage,$(DOCS_USAGE_STDOUT),$(eval $(call DOC_USAGE_STDOUT,$(usage)))) docs/usage: $(addprefix docs/source/generated/,$(DOCS_USAGE_STDOUT) $(DOCS_USAGE_STDERR)) @@ -990,8 +1089,11 @@ docs/usage: $(addprefix docs/source/generated/,$(DOCS_USAGE_STDOUT) $(DOCS_USAGE docs/reqs: $(Q) $(MAKE) -C docs reqs +.PHONY: docs/prep +docs/prep: docs/source/cmd/abc.rst docs/source/generated/cells.json docs/gen docs/usage docs/gen/functional_ir + DOC_TARGET ?= html -docs: docs/source/cmd/abc.rst docs/gen_examples docs/gen_images docs/guidelines docs/usage docs/reqs +docs: docs/prep $(Q) $(MAKE) -C docs $(DOC_TARGET) clean: @@ -999,6 +1101,7 @@ clean: rm -rf kernel/*.pyh rm -f $(OBJS) $(GENFILES) $(TARGETS) $(EXTRA_TARGETS) $(EXTRA_OBJS) $(PY_WRAP_INCLUDES) $(PY_WRAPPER_FILE).cc rm -f kernel/version_*.o kernel/version_*.cc + rm -f kernel/python_wrappers.o rm -f libs/*/*.d frontends/*/*.d passes/*/*.d backends/*/*.d kernel/*.d techlibs/*/*.d rm -rf tests/asicworld/*.out tests/asicworld/*.log rm -rf tests/hana/*.out tests/hana/*.log @@ -1009,9 +1112,11 @@ clean: rm -rf vloghtb/Makefile vloghtb/refdat vloghtb/rtl vloghtb/scripts vloghtb/spec vloghtb/check_yosys vloghtb/vloghammer_tb.tar.bz2 vloghtb/temp vloghtb/log_test_* rm -f tests/svinterfaces/*.log_stdout tests/svinterfaces/*.log_stderr tests/svinterfaces/dut_result.txt tests/svinterfaces/reference_result.txt tests/svinterfaces/a.out tests/svinterfaces/*_syn.v tests/svinterfaces/*.diff rm -f tests/tools/cmp_tbdata + rm -f $(addsuffix /run-test.mk,$(MK_TEST_DIRS)) -$(MAKE) -C docs clean - -$(MAKE) -C docs/images clean rm -rf docs/source/cmd docs/util/__pycache__ + rm -f *.whl + rm -f libyosys.so clean-abc: $(MAKE) -C abc DEP= clean @@ -1026,6 +1131,16 @@ coverage: lcov --capture -d . --no-external -o coverage.info genhtml coverage.info --output-directory coverage_html +clean_coverage: + find . -name "*.gcda" -type f -delete + +FUNC_KERNEL := functional.cc functional.h sexpr.cc sexpr.h compute_graph.h +FUNC_INCLUDES := $(addprefix --include *,functional/* $(FUNC_KERNEL)) +coverage_functional: + rm -rf coverage.info coverage_html + lcov --capture -d backends/functional -d kernel $(FUNC_INCLUDES) --no-external -o coverage.info + genhtml coverage.info --output-directory coverage_html + qtcreator: echo "$(CXXFLAGS)" | grep -o '\-D[^ ]*' | tr ' ' '\n' | sed 's/-D/#define /' | sed 's/=/ /'> qtcreator.config { for file in $(basename $(OBJS)); do \ @@ -1038,25 +1153,13 @@ vcxsrc: $(GENFILES) $(EXTRA_TARGETS) rm -rf yosys-win32-vcxsrc-$(YOSYS_VER){,.zip} set -e; for f in `ls $(filter %.cc %.cpp,$(GENFILES)) $(addsuffix .cc,$(basename $(OBJS))) $(addsuffix .cpp,$(basename $(OBJS))) 2> /dev/null`; do \ echo "Analyse: $$f" >&2; cpp -std=c++17 -MM -I. -D_YOSYS_ $$f; done | sed 's,.*:,,; s,//*,/,g; s,/[^/]*/\.\./,/,g; y, \\,\n\n,;' | grep '^[^/]' | sort -u | grep -v kernel/version_ > srcfiles.txt + echo "libs/fst/fst_win_unistd.h" >> srcfiles.txt bash misc/create_vcxsrc.sh yosys-win32-vcxsrc $(YOSYS_VER) $(GIT_REV) echo "namespace Yosys { extern const char *yosys_version_str; const char *yosys_version_str=\"Yosys (Version Information Unavailable)\"; }" > kernel/version.cc zip yosys-win32-vcxsrc-$(YOSYS_VER)/genfiles.zip $(GENFILES) kernel/version.cc zip -r yosys-win32-vcxsrc-$(YOSYS_VER).zip yosys-win32-vcxsrc-$(YOSYS_VER)/ rm -f srcfiles.txt kernel/version.cc -ifeq ($(CONFIG),mxe) -mxebin: $(TARGETS) $(EXTRA_TARGETS) - rm -rf yosys-win32-mxebin-$(YOSYS_VER){,.zip} - mkdir -p yosys-win32-mxebin-$(YOSYS_VER) - cp -r $(PROGRAM_PREFIX)yosys.exe share/ yosys-win32-mxebin-$(YOSYS_VER)/ -ifeq ($(ENABLE_ABC),1) - cp -r $(PROGRAM_PREFIX)yosys-abc.exe abc/lib/x86/pthreadVC2.dll yosys-win32-mxebin-$(YOSYS_VER)/ -endif - echo -en 'This is Yosys $(YOSYS_VER) for Win32.\r\n' > yosys-win32-mxebin-$(YOSYS_VER)/readme.txt - echo -en 'Documentation at https://yosyshq.net/yosys/.\r\n' >> yosys-win32-mxebin-$(YOSYS_VER)/readme.txt - zip -r yosys-win32-mxebin-$(YOSYS_VER).zip yosys-win32-mxebin-$(YOSYS_VER)/ -endif - config-clean: clean rm -f Makefile.conf @@ -1072,9 +1175,6 @@ config-gcc-static: clean echo 'ENABLE_READLINE := 0' >> Makefile.conf echo 'ENABLE_TCL := 0' >> Makefile.conf -config-afl-gcc: clean - echo 'CONFIG := afl-gcc' > Makefile.conf - config-wasi: clean echo 'CONFIG := wasi' > Makefile.conf echo 'ENABLE_TCL := 0' >> Makefile.conf @@ -1083,10 +1183,6 @@ config-wasi: clean echo 'ENABLE_READLINE := 0' >> Makefile.conf echo 'ENABLE_ZLIB := 0' >> Makefile.conf -config-mxe: clean - echo 'CONFIG := mxe' > Makefile.conf - echo 'ENABLE_PLUGINS := 0' >> Makefile.conf - config-msys2-32: clean echo 'CONFIG := msys2-32' > Makefile.conf echo "PREFIX := $(MINGW_PREFIX)" >> Makefile.conf @@ -1095,9 +1191,6 @@ config-msys2-64: clean echo 'CONFIG := msys2-64' > Makefile.conf echo "PREFIX := $(MINGW_PREFIX)" >> Makefile.conf -config-cygwin: clean - echo 'CONFIG := cygwin' > Makefile.conf - config-gcov: clean echo 'CONFIG := gcc' > Makefile.conf echo 'ENABLE_GCOV := 1' >> Makefile.conf @@ -1126,5 +1219,7 @@ echo-cxx: -include kernel/*.d -include techlibs/*/*.d -.PHONY: all top-all abc test install install-abc docs clean mrproper qtcreator coverage vcxsrc mxebin -.PHONY: config-clean config-clang config-gcc config-gcc-static config-afl-gcc config-gprof config-sudo +FORCE: + +.PHONY: all top-all abc test install install-abc docs clean mrproper qtcreator coverage vcxsrc +.PHONY: config-clean config-clang config-gcc config-gcc-static config-gprof config-sudo diff --git a/yosys/README.md b/yosys/README.md index bb1c4d443e4..71d47d76c21 100644 --- a/yosys/README.md +++ b/yosys/README.md @@ -1,22 +1,3 @@ -``` -yosys -- Yosys Open SYnthesis Suite - -Copyright (C) 2012 - 2024 Claire Xenia Wolf - -Permission to use, copy, modify, and/or distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -``` - - yosys – Yosys Open SYnthesis Suite =================================== @@ -33,6 +14,10 @@ Yosys is free software licensed under the ISC license (a GPL compatible license that is similar in terms to the MIT license or the 2-clause BSD license). +Third-party software distributed alongside this software +is licensed under compatible licenses. +Please refer to `abc` and `libs` subdirectories for their license terms. + Web Site and Other Resources ============================ @@ -40,17 +25,14 @@ Web Site and Other Resources More information and documentation can be found on the Yosys web site: - https://yosyshq.net/yosys/ -The "Documentation" page on the web site contains links to more resources, -including a manual that even describes some of the Yosys internals: -- https://yosyshq.net/yosys/documentation.html - -The directory `guidelines` contains additional information -for people interested in using the Yosys C++ APIs. +Documentation from this repository is automatically built and available on Read +the Docs: +- https://yosyshq.readthedocs.io/projects/yosys -Users interested in formal verification might want to use the formal verification -front-end for Yosys, SymbiYosys: -- https://symbiyosys.readthedocs.io/en/latest/ -- https://github.com/YosysHQ/SymbiYosys +Users interested in formal verification might want to use the formal +verification front-end for Yosys, SBY: +- https://yosyshq.readthedocs.io/projects/sby/ +- https://github.com/YosysHQ/sby Installation @@ -68,9 +50,25 @@ For more information about the difference between Tabby CAD Suite and the OSS CA Many Linux distributions also provide Yosys binaries, some more up to date than others. Check with your package manager! + Building from Source ==================== +For more details, and instructions for other platforms, check [building from +source](https://yosyshq.readthedocs.io/projects/yosys/en/latest/getting_started/installation.html#building-from-source) +on Read the Docs. + +When cloning Yosys, some required libraries are included as git submodules. Make +sure to call e.g. + + $ git clone --recurse-submodules https://github.com/YosysHQ/yosys.git + +or + + $ git clone https://github.com/YosysHQ/yosys.git + $ cd yosys + $ git submodule update --init --recursive + You need a C++ compiler with C++17 support (up-to-date CLANG or GCC is recommended) and some standard tools such as GNU Flex, GNU Bison, and GNU Make. TCL, readline and libffi are optional (see ``ENABLE_*`` settings in Makefile). @@ -79,46 +77,27 @@ Xdot (graphviz) is used by the ``show`` command in yosys to display schematics. For example on Ubuntu Linux 16.04 LTS the following commands will install all prerequisites for building yosys: - $ sudo apt-get install build-essential clang bison flex \ + $ sudo apt-get install build-essential clang lld bison flex \ libreadline-dev gawk tcl-dev libffi-dev git \ graphviz xdot pkg-config python3 libboost-system-dev \ libboost-python-dev libboost-filesystem-dev zlib1g-dev -Similarily, on Mac OS X Homebrew can be used to install dependencies (from within cloned yosys repository): - - $ brew tap Homebrew/bundle && brew bundle - -or MacPorts: - - $ sudo port install bison flex readline gawk libffi \ - git graphviz pkgconfig python36 boost zlib tcl - -On FreeBSD use the following command to install all prerequisites: - - # pkg install bison flex readline gawk libffi\ - git graphviz pkgconf python3 python36 tcl-wrapper boost-libs - -On FreeBSD system use gmake instead of make. To run tests use: - % MAKE=gmake CC=cc gmake test - -For Cygwin use the following command to install all prerequisites, or select these additional packages: - - setup-x86_64.exe -q --packages=bison,flex,gcc-core,gcc-g++,git,libffi-devel,libreadline-devel,make,pkg-config,python3,tcl-devel,boost-build,zlib-devel - The environment variable `CXX` can be used to control the C++ compiler used, or -run one of the following: +run one of the following to override it: $ make config-clang $ make config-gcc -Note that these will result in `make` ignoring the `CXX` environment variable, -unless `CXX` is assigned in the call to make, e.g. +The Makefile has many variables influencing the build process. These can be +adjusted by modifying the Makefile.conf file which is created at the `make +config-...` step (see above), or they can be set by passing an option to the +make command directly: $ make CXX=$CXX -For other compilers and build configurations it might be -necessary to make some changes to the config section of the -Makefile. +For other compilers and build configurations it might be necessary to make some +changes to the config section of the Makefile. It's also an alternative way to +set the make variables mentioned above. $ vi Makefile # ..or.. $ vi Makefile.conf @@ -128,10 +107,9 @@ To build Yosys simply type 'make' in this directory. $ make $ sudo make install -Note that this also downloads, builds and installs ABC (using yosys-abc -as executable name). - -Tests are located in the tests subdirectory and can be executed using the test target. Note that you need gawk as well as a recent version of iverilog (i.e. build from git). Then, execute tests via: +Tests are located in the tests subdirectory and can be executed using the test +target. Note that you need gawk as well as a recent version of iverilog (i.e. +build from git). Then, execute tests via: $ make test @@ -142,6 +120,7 @@ To use a separate (out-of-tree) build directory, provide a path to the Makefile. Out-of-tree builds require a clean source tree. + Getting Started =============== @@ -246,365 +225,14 @@ The command ``prep`` provides a good default word-level synthesis script, as used in SMT-based formal verification. -Unsupported Verilog-2005 Features -================================= - -The following Verilog-2005 features are not supported by -Yosys and there are currently no plans to add support -for them: - -- Non-synthesizable language features as defined in - IEC 62142(E):2005 / IEEE Std. 1364.1(E):2002 - -- The ``tri``, ``triand`` and ``trior`` net types - -- The ``config`` and ``disable`` keywords and library map files - - -Verilog Attributes and non-standard features -============================================ - -- The ``full_case`` attribute on case statements is supported - (also the non-standard ``// synopsys full_case`` directive) - -- The ``parallel_case`` attribute on case statements is supported - (also the non-standard ``// synopsys parallel_case`` directive) - -- The ``// synopsys translate_off`` and ``// synopsys translate_on`` - directives are also supported (but the use of ``` `ifdef .. `endif ``` - is strongly recommended instead). - -- The ``nomem2reg`` attribute on modules or arrays prohibits the - automatic early conversion of arrays to separate registers. This - is potentially dangerous. Usually the front-end has good reasons - for converting an array to a list of registers. Prohibiting this - step will likely result in incorrect synthesis results. - -- The ``mem2reg`` attribute on modules or arrays forces the early - conversion of arrays to separate registers. - -- The ``nomeminit`` attribute on modules or arrays prohibits the - creation of initialized memories. This effectively puts ``mem2reg`` - on all memories that are written to in an ``initial`` block and - are not ROMs. - -- The ``nolatches`` attribute on modules or always-blocks - prohibits the generation of logic-loops for latches. Instead - all not explicitly assigned values default to x-bits. This does - not affect clocked storage elements such as flip-flops. - -- The ``nosync`` attribute on registers prohibits the generation of a - storage element. The register itself will always have all bits set - to 'x' (undefined). The variable may only be used as blocking assigned - temporary variable within an always block. This is mostly used internally - by Yosys to synthesize Verilog functions and access arrays. +Additional information +====================== -- The ``nowrshmsk`` attribute on a register prohibits the generation of - shift-and-mask type circuits for writing to bit slices of that register. - -- The ``onehot`` attribute on wires mark them as one-hot state register. This - is used for example for memory port sharing and set by the fsm_map pass. - -- The ``blackbox`` attribute on modules is used to mark empty stub modules - that have the same ports as the real thing but do not contain information - on the internal configuration. This modules are only used by the synthesis - passes to identify input and output ports of cells. The Verilog backend - also does not output blackbox modules on default. ``read_verilog``, unless - called with ``-noblackbox`` will automatically set the blackbox attribute - on any empty module it reads. - -- The ``noblackbox`` attribute set on an empty module prevents ``read_verilog`` - from automatically setting the blackbox attribute on the module. - -- The ``whitebox`` attribute on modules triggers the same behavior as - ``blackbox``, but is for whitebox modules, i.e. library modules that - contain a behavioral model of the cell type. - -- The ``lib_whitebox`` attribute overwrites ``whitebox`` when ``read_verilog`` - is run in `-lib` mode. Otherwise it's automatically removed. - -- The ``dynports`` attribute is used by the Verilog front-end to mark modules - that have ports with a width that depends on a parameter. - -- The ``hdlname`` attribute is used by some passes to document the original - (HDL) name of a module when renaming a module. It should contain a single - name, or, when describing a hierarchical name in a flattened design, multiple - names separated by a single space character. - -- The ``keep`` attribute on cells and wires is used to mark objects that should - never be removed by the optimizer. This is used for example for cells that - have hidden connections that are not part of the netlist, such as IO pads. - Setting the ``keep`` attribute on a module has the same effect as setting it - on all instances of the module. - -- The ``keep_hierarchy`` attribute on cells and modules keeps the ``flatten`` - command from flattening the indicated cells and modules. - -- The ``init`` attribute on wires is set by the frontend when a register is - initialized "FPGA-style" with ``reg foo = val``. It can be used during - synthesis to add the necessary reset logic. - -- The ``top`` attribute on a module marks this module as the top of the - design hierarchy. The ``hierarchy`` command sets this attribute when called - with ``-top``. Other commands, such as ``flatten`` and various backends - use this attribute to determine the top module. - -- The ``src`` attribute is set on cells and wires created by to the string - ``:`` by the HDL front-end and is then carried - through the synthesis. When entities are combined, a new |-separated - string is created that contains all the string from the original entities. - -- The ``defaultvalue`` attribute is used to store default values for - module inputs. The attribute is attached to the input wire by the HDL - front-end when the input is declared with a default value. - -- The ``parameter`` and ``localparam`` attributes are used to mark wires - that represent module parameters or localparams (when the HDL front-end - is run in ``-pwires`` mode). - -- Wires marked with the ``hierconn`` attribute are connected to wires with the - same name (format ``cell_name.identifier``) when they are imported from - sub-modules by ``flatten``. - -- The ``clkbuf_driver`` attribute can be set on an output port of a blackbox - module to mark it as a clock buffer output, and thus prevent ``clkbufmap`` - from inserting another clock buffer on a net driven by such output. - -- The ``clkbuf_sink`` attribute can be set on an input port of a module to - request clock buffer insertion by the ``clkbufmap`` pass. - -- The ``clkbuf_inv`` attribute can be set on an output port of a module - with the value set to the name of an input port of that module. When - the ``clkbufmap`` would otherwise insert a clock buffer on this output, - it will instead try inserting the clock buffer on the input port (this - is used to implement clock inverter cells that clock buffer insertion - will "see through"). - -- The ``clkbuf_inhibit`` is the default attribute to set on a wire to prevent - automatic clock buffer insertion by ``clkbufmap``. This behaviour can be - overridden by providing a custom selection to ``clkbufmap``. - -- The ``invertible_pin`` attribute can be set on a port to mark it as - invertible via a cell parameter. The name of the inversion parameter - is specified as the value of this attribute. The value of the inversion - parameter must be of the same width as the port, with 1 indicating - an inverted bit and 0 indicating a non-inverted bit. - -- The ``iopad_external_pin`` attribute on a blackbox module's port marks - it as the external-facing pin of an I/O pad, and prevents ``iopadmap`` - from inserting another pad cell on it. - -- The module attribute ``abc9_lut`` is an integer attribute indicating to - `abc9` that this module describes a LUT with an area cost of this value, and - propagation delays described using `specify` statements. - -- The module attribute ``abc9_box`` is a boolean specifying a black/white-box - definition, with propagation delays described using `specify` statements, for - use by `abc9`. - -- The port attribute ``abc9_carry`` marks the carry-in (if an input port) and - carry-out (if output port) ports of a box. This information is necessary for - `abc9` to preserve the integrity of carry-chains. Specifying this attribute - onto a bus port will affect only its most significant bit. - -- The module attribute ``abc9_flop`` is a boolean marking the module as a - flip-flop. This allows `abc9` to analyse its contents in order to perform - sequential synthesis. - -- The frontend sets attributes ``always_comb``, ``always_latch`` and - ``always_ff`` on processes derived from SystemVerilog style always blocks - according to the type of the always. These are checked for correctness in - ``proc_dlatch``. - -- The cell attribute ``wildcard_port_conns`` represents wildcard port - connections (SystemVerilog ``.*``). These are resolved to concrete - connections to matching wires in ``hierarchy``. - -- In addition to the ``(* ... *)`` attribute syntax, Yosys supports - the non-standard ``{* ... *}`` attribute syntax to set default attributes - for everything that comes after the ``{* ... *}`` statement. (Reset - by adding an empty ``{* *}`` statement.) - -- In module parameter and port declarations, and cell port and parameter - lists, a trailing comma is ignored. This simplifies writing Verilog code - generators a bit in some cases. - -- Modules can be declared with ``module mod_name(...);`` (with three dots - instead of a list of module ports). With this syntax it is sufficient - to simply declare a module port as 'input' or 'output' in the module - body. - -- When defining a macro with `define, all text between triple double quotes - is interpreted as macro body, even if it contains unescaped newlines. The - triple double quotes are removed from the macro body. For example: - - `define MY_MACRO(a, b) """ - assign a = 23; - assign b = 42; - """ - -- The attribute ``via_celltype`` can be used to implement a Verilog task or - function by instantiating the specified cell type. The value is the name - of the cell type to use. For functions the name of the output port can - be specified by appending it to the cell type separated by a whitespace. - The body of the task or function is unused in this case and can be used - to specify a behavioral model of the cell type for simulation. For example: - - module my_add3(A, B, C, Y); - parameter WIDTH = 8; - input [WIDTH-1:0] A, B, C; - output [WIDTH-1:0] Y; - ... - endmodule - - module top; - ... - (* via_celltype = "my_add3 Y" *) - (* via_celltype_defparam_WIDTH = 32 *) - function [31:0] add3; - input [31:0] A, B, C; - begin - add3 = A + B + C; - end - endfunction - ... - endmodule - -- The ``wiretype`` attribute is added by the verilog parser for wires of a - typedef'd type to indicate the type identifier. - -- Various ``enum_value_{value}`` attributes are added to wires of an enumerated type - to give a map of possible enum items to their values. - -- The ``enum_base_type`` attribute is added to enum items to indicate which - enum they belong to (enums -- anonymous and otherwise -- are - automatically named with an auto-incrementing counter). Note that enums - are currently not strongly typed. - -- A limited subset of DPI-C functions is supported. The plugin mechanism - (see ``help plugin``) can be used to load .so files with implementations - of DPI-C routines. As a non-standard extension it is possible to specify - a plugin alias using the ``:`` syntax. For example: - - module dpitest; - import "DPI-C" function foo:round = real my_round (real); - parameter real r = my_round(12.345); - endmodule - - $ yosys -p 'plugin -a foo -i /lib/libm.so; read_verilog dpitest.v' - -- Sized constants (the syntax ``'s?[bodh]``) support constant - expressions as ````. If the expression is not a simple identifier, it - must be put in parentheses. Examples: ``WIDTH'd42``, ``(4+2)'b101010`` - -- The system tasks ``$finish``, ``$stop`` and ``$display`` are supported in - initial blocks in an unconditional context (only if/case statements on - expressions over parameters and constant values are allowed). The intended - use for this is synthesis-time DRC. - -- There is limited support for converting ``specify`` .. ``endspecify`` - statements to special ``$specify2``, ``$specify3``, and ``$specrule`` cells, - for use in blackboxes and whiteboxes. Use ``read_verilog -specify`` to - enable this functionality. (By default these blocks are ignored.) - -- The ``reprocess_after`` internal attribute is used by the Verilog frontend to - mark cells with bindings which might depend on the specified instantiated - module. Modules with such cells will be reprocessed during the ``hierarchy`` - pass once the referenced module definition(s) become available. - -- The ``smtlib2_module`` attribute can be set on a blackbox module to specify a - formal model directly using SMT-LIB 2. For such a module, the - ``smtlib2_comb_expr`` attribute can be used on output ports to define their - value using an SMT-LIB 2 expression. For example: - - (* blackbox *) - (* smtlib2_module *) - module submod(a, b); - input [7:0] a; - (* smtlib2_comb_expr = "(bvnot a)" *) - output [7:0] b; - endmodule - -Non-standard or SystemVerilog features for formal verification -============================================================== - -- Support for ``assert``, ``assume``, ``restrict``, and ``cover`` is enabled - when ``read_verilog`` is called with ``-formal``. - -- The system task ``$initstate`` evaluates to 1 in the initial state and - to 0 otherwise. - -- The system function ``$anyconst`` evaluates to any constant value. This is - equivalent to declaring a reg as ``rand const``, but also works outside - of checkers. (Yosys also supports ``rand const`` outside checkers.) - -- The system function ``$anyseq`` evaluates to any value, possibly a different - value in each cycle. This is equivalent to declaring a reg as ``rand``, - but also works outside of checkers. (Yosys also supports ``rand`` - variables outside checkers.) - -- The system functions ``$allconst`` and ``$allseq`` can be used to construct - formal exist-forall problems. Assumptions only hold if the trace satisfies - the assumption for all ``$allconst/$allseq`` values. For assertions and cover - statements it is sufficient if just one ``$allconst/$allseq`` value triggers - the property (similar to ``$anyconst/$anyseq``). - -- Wires/registers declared using the ``anyconst/anyseq/allconst/allseq`` attribute - (for example ``(* anyconst *) reg [7:0] foobar;``) will behave as if driven - by a ``$anyconst/$anyseq/$allconst/$allseq`` function. - -- The SystemVerilog tasks ``$past``, ``$stable``, ``$rose`` and ``$fell`` are - supported in any clocked block. - -- The syntax ``@($global_clock)`` can be used to create FFs that have no - explicit clock input (``$ff`` cells). The same can be achieved by using - ``@(posedge )`` or ``@(negedge )`` when ```` - is marked with the ``(* gclk *)`` Verilog attribute. - - -Supported features from SystemVerilog -===================================== - -When ``read_verilog`` is called with ``-sv``, it accepts some language features -from SystemVerilog: - -- The ``assert`` statement from SystemVerilog is supported in its most basic - form. In module context: ``assert property ();`` and within an - always block: ``assert();``. It is transformed to an ``$assert`` cell. - -- The ``assume``, ``restrict``, and ``cover`` statements from SystemVerilog are - also supported. The same limitations as with the ``assert`` statement apply. - -- The keywords ``always_comb``, ``always_ff`` and ``always_latch``, ``logic`` - and ``bit`` are supported. - -- Declaring free variables with ``rand`` and ``rand const`` is supported. - -- Checkers without a port list that do not need to be instantiated (but instead - behave like a named block) are supported. - -- SystemVerilog packages are supported. Once a SystemVerilog file is read - into a design with ``read_verilog``, all its packages are available to - SystemVerilog files being read into the same design afterwards. - -- typedefs are supported (including inside packages) - - type casts are currently not supported - -- enums are supported (including inside packages) - - but are currently not strongly typed - -- packed structs and unions are supported - - arrays of packed structs/unions are currently not supported - - structure literals are currently not supported - -- multidimensional arrays are supported - - array assignment of unpacked arrays is currently not supported - - array literals are currently not supported - -- SystemVerilog interfaces (SVIs) are supported. Modports for specifying whether - ports are inputs or outputs are supported. - -- Assignments within expressions are supported. +The ``read_verilog`` command, used by default when calling ``read`` with Verilog +source input, does not perform syntax checking. You should instead lint your +source with another tool such as +[Verilator](https://www.veripool.org/verilator/) first, e.g. by calling +``verilator --lint-only``. Building the documentation @@ -618,11 +246,21 @@ following are used for building the website: $ sudo apt install pdf2svg faketime +Or for MacOS, using homebrew: + + $ brew install pdf2svg libfaketime + PDFLaTeX, included with most LaTeX distributions, is also needed during the build process for the website. Or, run the following: $ sudo apt install texlive-latex-base texlive-latex-extra latexmk +Or for MacOS, using homebrew: + + $ brew install basictex + $ sudo tlmgr update --self + $ sudo tlmgr install collection-latexextra latexmk tex-gyre + The Python package, Sphinx, is needed along with those listed in `docs/source/requirements.txt`: diff --git a/yosys/abc/.gitattributes b/yosys/abc/.gitattributes new file mode 100644 index 00000000000..93b5c8649ae --- /dev/null +++ b/yosys/abc/.gitattributes @@ -0,0 +1,33 @@ +/.gitcommit export-subst +* text=auto + +*.c text +*.cpp text +*.h text + +*.py text +*.sh text + +*.make text +Makefile text + +*.txt text +*.md text +*.html text + +readmeaig text +LICENSE text +license text +CHANGES text +README text + +.hgignore text +.gitignore text +.gitattributes text + +*.dsp text eol=crlf +*.dsw text eol=crlf + +*.aig binary +*.lib binary +*.dll binary diff --git a/yosys/abc/.gitcommit b/yosys/abc/.gitcommit new file mode 100644 index 00000000000..6828f88dcb0 --- /dev/null +++ b/yosys/abc/.gitcommit @@ -0,0 +1 @@ +$Format:%H$ diff --git a/yosys/abc/.github/workflows/build-posix-cmake.yml b/yosys/abc/.github/workflows/build-posix-cmake.yml new file mode 100644 index 00000000000..f8ccde47dfc --- /dev/null +++ b/yosys/abc/.github/workflows/build-posix-cmake.yml @@ -0,0 +1,66 @@ +name: Build Posix CMake + +on: + push: + pull_request: + +jobs: + + build-posix-cmake: + strategy: + matrix: + os: [macos-latest, ubuntu-latest] + use_namespace: [false, true] + + runs-on: ${{ matrix.os }} + + env: + CMAKE_ARGS: ${{ matrix.use_namespace && '-DABC_USE_NAMESPACE=xxx' || '' }} + DEMO_ARGS: ${{ matrix.use_namespace && '-DABC_NAMESPACE=xxx' || '' }} + DEMO_GCC: ${{ matrix.use_namespace && 'g++ -x c++' || 'gcc' }} + + steps: + + - name: Git Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install brew dependencies + run: | + HOMEBREW_NO_AUTO_UPDATE=1 brew install readline ninja + if: ${{ contains(matrix.os, 'macos') }} + + - name: Install APT dependencies + run: | + sudo apt install -y libreadline-dev ninja-build + if: ${{ !contains(matrix.os, 'macos') }} + + - name: Configure CMake + run: | + cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ${CMAKE_ARGS} -B build + + - name: Build CMake + run: | + cmake --build build + + - name: Test Executable + run: | + ./build/abc -c "r i10.aig; b; ps; b; rw -l; rw -lz; b; rw -lz; b; ps; cec" + + - name: Test Library + run: | + ${DEMO_GCC} ${DEMO_ARGS} -Wall -c src/demo.c -o demo.o + g++ -o demo demo.o build/libabc.a -lm -ldl -lreadline -lpthread + ./demo i10.aig + + - name: Stage Executable + run: | + mkdir staging + cp build/abc build/libabc.a staging/ + + - name: Upload pacakge artifact + uses: actions/upload-artifact@v4 + with: + name: package-cmake-${{ matrix.os }}-${{ matrix.use_namespace }} + path: staging/ diff --git a/yosys/abc/.github/workflows/build-posix.yml b/yosys/abc/.github/workflows/build-posix.yml new file mode 100644 index 00000000000..080c6e0453f --- /dev/null +++ b/yosys/abc/.github/workflows/build-posix.yml @@ -0,0 +1,66 @@ +name: Build Posix + +on: + push: + pull_request: + +jobs: + + build-posix: + strategy: + matrix: + os: [macos-latest, ubuntu-latest] + use_namespace: [false, true] + + runs-on: ${{ matrix.os }} + + env: + MAKE_ARGS: ${{ matrix.use_namespace && 'ABC_USE_NAMESPACE=xxx' || '' }} + DEMO_ARGS: ${{ matrix.use_namespace && '-DABC_NAMESPACE=xxx' || '' }} + DEMO_GCC: ${{ matrix.use_namespace && 'g++ -x c++' || 'gcc' }} + + steps: + + - name: Git Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install brew dependencies + run: | + HOMEBREW_NO_AUTO_UPDATE=1 brew install readline + if: ${{ contains(matrix.os, 'macos') }} + + - name: Install APT dependencies + run: | + sudo apt install -y libreadline-dev + if: ${{ !contains(matrix.os, 'macos') }} + + - name: Build Executable + run: | + make -j3 ${MAKE_ARGS} abc + + - name: Test Executable + run: | + ./abc -c "r i10.aig; b; ps; b; rw -l; rw -lz; b; rw -lz; b; ps; cec" + + - name: Build Library + run: | + make -j3 ${MAKE_ARGS} libabc.a + + - name: Test Library + run: | + ${DEMO_GCC} ${DEMO_ARGS} -Wall -c src/demo.c -o demo.o + g++ -o demo demo.o libabc.a -lm -ldl -lreadline -lpthread + ./demo i10.aig + + - name: Stage Executable + run: | + mkdir staging + cp abc libabc.a staging/ + + - name: Upload pacakge artifact + uses: actions/upload-artifact@v4 + with: + name: package-posix-${{ matrix.os }}-${{ matrix.use_namespace }} + path: staging/ diff --git a/yosys/abc/.github/workflows/build-windows.yml b/yosys/abc/.github/workflows/build-windows.yml new file mode 100644 index 00000000000..2d089436487 --- /dev/null +++ b/yosys/abc/.github/workflows/build-windows.yml @@ -0,0 +1,52 @@ +name: Build Windows + +on: + push: + pull_request: + +jobs: + + build-windows: + + runs-on: windows-2019 + + steps: + + - name: Git Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Process project files to compile on Github Actions + run: | + sed -i 's#ABC_USE_PTHREADS\"#ABC_DONT_USE_PTHREADS\" /D \"_ALLOW_KEYWORD_MACROS=1\"#g' *.dsp + awk 'BEGIN { del=0; } /# Begin Group "uap"/ { del=1; } /# End Group/ { if( del > 0 ) {del=0; next;} } del==0 {print;} ' abclib.dsp > tmp.dsp + copy tmp.dsp abclib.dsp + del tmp.dsp + unix2dos *.dsp + + - name: Prepare MSVC + uses: bus1/cabuild/action/msdevshell@v1 + with: + architecture: x86 + + - name: Upgrade project files to latest Visual Studio, ignoring upgrade errors, and build + run: | + devenv abcspace.dsw /upgrade ; if (-not $? ) { cat UpgradeLog.htm } + msbuild abcspace.sln /m /nologo /p:Configuration=Release /p:PlatformTarget=x86 + + - name: Test Executable + run: | + _TEST\abc.exe -c "r i10.aig; b; ps; b; rw -l; rw -lz; b; rw -lz; b; ps; cec" + + - name: Stage Executable + run: | + mkdir staging + copy _TEST/abc.exe staging/ + copy UpgradeLog.htm staging/ + + - name: Upload pacakge artifact + uses: actions/upload-artifact@v4 + with: + name: package-windows + path: staging/ diff --git a/yosys/abc/.gitignore b/yosys/abc/.gitignore new file mode 100644 index 00000000000..9bd049424a8 --- /dev/null +++ b/yosys/abc/.gitignore @@ -0,0 +1,66 @@ +DebugLib/ +DebugExe/ +DebugExt/ + +ReleaseLib/ +ReleaseExe/ +ReleaseExt/ + +_/ +_TEST/ +lib/abc* +lib/m114* +lib/bip* +docs/ +.vscode/ +.cache/ + +src/ext* +src/xxx/ +src/aig/au/ +src/aig/ssm/ +src/aig/ddb/ + +*~ +*.orig + +*.[od] + +*.ncb +*.opt +*.plg + +*.zip +*.DS_Store + +abcspaceext.dsw +abcext.dsp + +abcexe.vcproj* +abclib.vcproj* +abcspace.sln +abcspace.suo + +*.pyc + +src/python/build +src/python/bdist +src/python/pyabc.py +src/python/pyabc_wrap.* + +.idea/ +build/ + +*.rej +*.orig + +tags + +/libabc.a +/abc + +/arch_flags + +/cmake +/cscope +abc.history diff --git a/yosys/abc/.hgignore b/yosys/abc/.hgignore new file mode 100644 index 00000000000..f5d4784c8d4 --- /dev/null +++ b/yosys/abc/.hgignore @@ -0,0 +1,65 @@ +syntax:glob + +DebugLib/ +DebugExe/ +DebugExt/ + +ReleaseLib/ +ReleaseExe/ +ReleaseExt/ + +_TEST/ +lib/abc* +lib/m114* +lib/bip* +docs/ + +src/ext* +src/xxx/ +src/aig/au/ +src/aig/ssm/ +src/aig/ddb/ + +*~ +*.orig + +*.[od] + +*.ncb +*.opt +*.plg + +*.zip + +abcspaceext.dsw +abcext.dsp + +abcexe.vcproj* +abclib.vcproj* +abcspace.sln +abcspace.suo + +*.pyc + +src/python/build +src/python/bdist +src/python/pyabc.py +src/python/pyabc_wrap.* + +.idea/ +build/ + +*.rej +*.orig + +tags + +syntax: regexp + +^libabc.a$ +^abc$ + +^arch_flags$ + +^cmake +^cscope diff --git a/yosys/abc/Makefile b/yosys/abc/Makefile new file mode 100644 index 00000000000..50cff2d1704 --- /dev/null +++ b/yosys/abc/Makefile @@ -0,0 +1,244 @@ + +CC := gcc +CXX := g++ +AR := ar +LD := $(CXX) + +MSG_PREFIX ?= +ABCSRC ?= . +VPATH = $(ABCSRC) + +$(info $(MSG_PREFIX)Using CC=$(CC)) +$(info $(MSG_PREFIX)Using CXX=$(CXX)) +$(info $(MSG_PREFIX)Using AR=$(AR)) +$(info $(MSG_PREFIX)Using LD=$(LD)) + +PROG := abc +OS := $(shell uname -s) + +MODULES := \ + $(wildcard src/ext*) \ + src/base/abc src/base/abci src/base/cmd src/base/io src/base/main src/base/exor \ + src/base/ver src/base/wlc src/base/wln src/base/acb src/base/bac src/base/cba src/base/pla src/base/test \ + src/map/mapper src/map/mio src/map/super src/map/if src/map/if/acd \ + src/map/amap src/map/cov src/map/scl src/map/mpm \ + src/misc/extra src/misc/mvc src/misc/st src/misc/util src/misc/nm \ + src/misc/vec src/misc/hash src/misc/tim src/misc/bzlib src/misc/zlib \ + src/misc/mem src/misc/bar src/misc/bbl src/misc/parse \ + src/opt/cut src/opt/fxu src/opt/fxch src/opt/rwr src/opt/mfs src/opt/sim \ + src/opt/ret src/opt/fret src/opt/res src/opt/lpk src/opt/nwk src/opt/rwt src/opt/rar \ + src/opt/cgt src/opt/csw src/opt/dar src/opt/dau src/opt/dsc src/opt/sfm src/opt/sbd src/opt/eslim \ + src/sat/bsat src/sat/xsat src/sat/satoko src/sat/csat src/sat/msat src/sat/psat src/sat/cnf src/sat/bmc src/sat/glucose src/sat/glucose2 src/sat/kissat src/sat/cadical \ + src/bool/bdc src/bool/deco src/bool/dec src/bool/kit src/bool/lucky \ + src/bool/rsb src/bool/rpo \ + src/proof/pdr src/proof/abs src/proof/live src/proof/ssc src/proof/int \ + src/proof/cec src/proof/acec src/proof/dch src/proof/fraig src/proof/fra src/proof/ssw \ + src/aig/aig src/aig/saig src/aig/gia src/aig/ioa src/aig/ivy src/aig/hop \ + src/aig/miniaig + +all: $(PROG) +default: $(PROG) + +ARCHFLAGS_EXE ?= ./arch_flags + +$(ARCHFLAGS_EXE) : arch_flags.c + $(CC) $< -o $(ARCHFLAGS_EXE) + +INCLUDES += -I$(ABCSRC)/src + +# Use C99 stdint.h header for platform-dependent types +ifdef ABC_USE_STDINT_H + ARCHFLAGS ?= -DABC_USE_STDINT_H=1 +else + ARCHFLAGS ?= $(shell $(CC) $(ABCSRC)/arch_flags.c -o $(ARCHFLAGS_EXE) && $(ARCHFLAGS_EXE)) +endif + +ARCHFLAGS := $(ARCHFLAGS) + +OPTFLAGS ?= -g -O + +CFLAGS += -Wall -Wno-unused-function -Wno-write-strings -Wno-sign-compare $(ARCHFLAGS) +ifneq ($(findstring arm,$(shell uname -m)),) + CFLAGS += -DABC_MEMALIGN=4 +endif + +# compile ABC using the C++ compiler and put everything in the namespace $(ABC_NAMESPACE) +ifdef ABC_USE_NAMESPACE + CFLAGS += -DABC_NAMESPACE=$(ABC_USE_NAMESPACE) -fpermissive -x c++ + CC := $(CXX) + $(info $(MSG_PREFIX)Compiling in namespace $(ABC_NAMESPACE)) +endif + +# compile CUDD with ABC +ifndef ABC_USE_NO_CUDD + CFLAGS += -DABC_USE_CUDD=1 + MODULES += src/bdd/cudd src/bdd/extrab src/bdd/dsd src/bdd/epd src/bdd/mtr src/bdd/reo src/bdd/cas src/bdd/bbr src/bdd/llb + $(info $(MSG_PREFIX)Compiling with CUDD) +endif + +ABC_READLINE_INCLUDES ?= +ABC_READLINE_LIBRARIES ?= -lreadline + +# whether to use libreadline +ifndef ABC_USE_NO_READLINE + CFLAGS += -DABC_USE_READLINE $(ABC_READLINE_INCLUDES) + LIBS += $(ABC_READLINE_LIBRARIES) + ifeq ($(OS), FreeBSD) + CFLAGS += -I/usr/local/include + LDFLAGS += -L/usr/local/lib + endif + $(info $(MSG_PREFIX)Using libreadline) +endif + +# whether to compile with thread support +ifndef ABC_USE_NO_PTHREADS + CFLAGS += -DABC_USE_PTHREADS + LIBS += -lpthread + $(info $(MSG_PREFIX)Using pthreads) +endif + +# whether to compile into position independent code +ifdef ABC_USE_PIC + CFLAGS += -fPIC + LIBS += -fPIC + $(info $(MSG_PREFIX)Compiling position independent code) +endif + +# whether to echo commands while building +ifdef ABC_MAKE_VERBOSE + VERBOSE= +else + VERBOSE=@ +endif + +# Set -Wno-unused-bug-set-variable for GCC 4.6.0 and greater only +ifneq ($(or $(findstring gcc,$(CC)),$(findstring g++,$(CC))),) +empty:= +space:=$(empty) $(empty) + +GCC_VERSION=$(shell $(CC) -dumpversion) +GCC_MAJOR=$(word 1,$(subst .,$(space),$(GCC_VERSION))) +GCC_MINOR=$(word 2,$(subst .,$(space),$(GCC_VERSION))) + +$(info $(MSG_PREFIX)Found GCC_VERSION $(GCC_VERSION)) +ifeq ($(findstring $(GCC_MAJOR),0 1 2 3),) +ifeq ($(GCC_MAJOR),4) +$(info $(MSG_PREFIX)Found GCC_MAJOR==4) +ifeq ($(findstring $(GCC_MINOR),0 1 2 3 4 5),) +$(info $(MSG_PREFIX)Found GCC_MINOR>=6) +CFLAGS += -Wno-unused-but-set-variable +endif +else +$(info $(MSG_PREFIX)Found GCC_MAJOR>=5) +CFLAGS += -Wno-unused-but-set-variable +endif +endif + +endif + +# LIBS := -ldl -lrt +LIBS += -lm +ifneq ($(OS), $(filter $(OS), FreeBSD OpenBSD NetBSD)) + LIBS += -ldl +endif + +ifneq ($(OS), $(filter $(OS), FreeBSD OpenBSD NetBSD Darwin)) + LIBS += -lrt +endif + +ifdef ABC_USE_LIBSTDCXX + LIBS += -lstdc++ + $(info $(MSG_PREFIX)Using explicit -lstdc++) +endif + +$(info $(MSG_PREFIX)Using CFLAGS=$(CFLAGS)) +CXXFLAGS += $(CFLAGS) -std=c++17 -fno-exceptions + +SRC := +GARBAGE := core core.* *.stackdump ./tags $(PROG) arch_flags + +.PHONY: all default tags clean docs cmake_info + +include $(patsubst %, $(ABCSRC)/%/module.make, $(MODULES)) + +OBJ := \ + $(patsubst %.cc, %.o, $(filter %.cc, $(SRC))) \ + $(patsubst %.cpp, %.o, $(filter %.cpp, $(SRC))) \ + $(patsubst %.c, %.o, $(filter %.c, $(SRC))) \ + $(patsubst %.y, %.o, $(filter %.y, $(SRC))) + +LIBOBJ := $(filter-out src/base/main/main.o,$(OBJ)) + +DEP := $(OBJ:.o=.d) + +# implicit rules + +%.o: %.c + @mkdir -p $(dir $@) + @echo "$(MSG_PREFIX)\`\` Compiling:" $(LOCAL_PATH)/$< + $(VERBOSE)$(CC) -c $(OPTFLAGS) $(INCLUDES) $(CFLAGS) $< -o $@ + +%.o: %.cc + @mkdir -p $(dir $@) + @echo "$(MSG_PREFIX)\`\` Compiling:" $(LOCAL_PATH)/$< + $(VERBOSE)$(CXX) -c $(OPTFLAGS) $(INCLUDES) $(CXXFLAGS) $< -o $@ + +%.o: %.cpp + @mkdir -p $(dir $@) + @echo "$(MSG_PREFIX)\`\` Compiling:" $(LOCAL_PATH)/$< + $(VERBOSE)$(CXX) -c $(OPTFLAGS) $(INCLUDES) $(CXXFLAGS) $< -o $@ + +%.d: %.c + @mkdir -p $(dir $@) + @echo "$(MSG_PREFIX)\`\` Generating dependency:" $(LOCAL_PATH)/$< + $(VERBOSE)$(ABCSRC)/depends.sh "$(CC)" `dirname $*.c` $(OPTFLAGS) $(INCLUDES) $(CFLAGS) $< > $@ + +%.d: %.cc + @mkdir -p $(dir $@) + @echo "$(MSG_PREFIX)\`\` Generating dependency:" $(LOCAL_PATH)/$< + $(VERBOSE)$(ABCSRC)/depends.sh "$(CXX)" `dirname $*.cc` $(OPTFLAGS) $(INCLUDES) $(CXXFLAGS) $< > $@ + +%.d: %.cpp + @mkdir -p $(dir $@) + @echo "$(MSG_PREFIX)\`\` Generating dependency:" $(LOCAL_PATH)/$< + $(VERBOSE)$(ABCSRC)/depends.sh "$(CXX)" `dirname $*.cpp` $(OPTFLAGS) $(INCLUDES) $(CXXFLAGS) $< > $@ + +ifndef ABC_MAKE_NO_DEPS +-include $(DEP) +endif + +# Actual targets + +depend: $(DEP) + +clean: + @echo "$(MSG_PREFIX)\`\` Cleaning up..." + $(VERBOSE)rm -rvf $(PROG) lib$(PROG).a + $(VERBOSE)rm -rvf $(OBJ) + $(VERBOSE)rm -rvf $(GARBAGE) + $(VERBOSE)rm -rvf $(OBJ:.o=.d) + +tags: + etags `find . -type f -regex '.*\.\(c\|h\)'` + +$(PROG): $(OBJ) + @echo "$(MSG_PREFIX)\`\` Building binary:" $(notdir $@) + $(VERBOSE)$(LD) -o $@ $^ $(LDFLAGS) $(LIBS) + +lib$(PROG).a: $(LIBOBJ) + @echo "$(MSG_PREFIX)\`\` Linking:" $(notdir $@) + $(VERBOSE)$(AR) rsv $@ $? + +lib$(PROG).so: $(LIBOBJ) + @echo "$(MSG_PREFIX)\`\` Linking:" $(notdir $@) + $(VERBOSE)$(CXX) -shared -o $@ $^ $(LIBS) + +docs: + @echo "$(MSG_PREFIX)\`\` Building documentation." $(notdir $@) + $(VERBOSE)doxygen doxygen.conf + +cmake_info: + @echo SEPARATOR_CFLAGS $(CFLAGS) SEPARATOR_CFLAGS + @echo SEPARATOR_CXXFLAGS $(CXXFLAGS) SEPARATOR_CXXFLAGS + @echo SEPARATOR_LIBS $(LIBS) SEPARATOR_LIBS + @echo SEPARATOR_SRC $(SRC) SEPARATOR_SRC diff --git a/yosys/abc/README.md b/yosys/abc/README.md new file mode 100644 index 00000000000..2bb34cd036f --- /dev/null +++ b/yosys/abc/README.md @@ -0,0 +1,125 @@ +[![.github/workflows/build-posix.yml](https://github.com/berkeley-abc/abc/actions/workflows/build-posix.yml/badge.svg)](https://github.com/berkeley-abc/abc/actions/workflows/build-posix.yml) +[![.github/workflows/build-windows.yml](https://github.com/berkeley-abc/abc/actions/workflows/build-windows.yml/badge.svg)](https://github.com/berkeley-abc/abc/actions/workflows/build-windows.yml) +[![.github/workflows/build-posix-cmake.yml](https://github.com/berkeley-abc/abc/actions/workflows/build-posix-cmake.yml/badge.svg)](https://github.com/berkeley-abc/abc/actions/workflows/build-posix-cmake.yml) + +# ABC: System for Sequential Logic Synthesis and Formal Verification + +ABC is always changing but the current snapshot is believed to be stable. + +## ABC fork with new features + +Here is a [fork](https://github.com/yongshiwo/abc.git) of ABC containing Agdmap, a novel technology mapper for LUT-based FPGAs. Agdmap is based on a technology mapping algorithm with adaptive gate decomposition [1]. It is a cut enumeration based mapping algorithm with bin packing for simultaneous wide gate decomposition, which is a patent pending technology. + +The mapper is developed and maintained by Longfei Fan and Prof. Chang Wu at Fudan University in Shanghai, China. The experimental results presented in [1] indicate that Agdmap can substantially improve area (by 10% or more) when compared against the best LUT mapping solutions in ABC, such as command "if". + +The source code is provided for research and evaluation only. For commercial usage, please contact Prof. Chang Wu at wuchang@fudan.edu.cn. + +References: + +[1] L. Fan and C. Wu, "FPGA technology mapping with adaptive gate decompostion", ACM/SIGDA FPGA International Symposium on FPGAs, 2023. + +## Compiling: + +To compile ABC as a binary, download and unzip the code, then type `make`. +To compile ABC as a static library, type `make libabc.a`. + +When ABC is used as a static library, two additional procedures, `Abc_Start()` +and `Abc_Stop()`, are provided for starting and quitting the ABC framework in +the calling application. A simple demo program (file src/demo.c) shows how to +create a stand-alone program performing DAG-aware AIG rewriting, by calling +APIs of ABC compiled as a static library. + +To build the demo program + + * Copy demo.c and libabc.a to the working directory + * Run `gcc -Wall -g -c demo.c -o demo.o` + * Run `g++ -g -o demo demo.o libabc.a -lm -ldl -lreadline -lpthread` + +To run the demo program, give it a file with the logic network in AIGER or BLIF. For example: + + [...] ~/abc> demo i10.aig + i10 : i/o = 257/ 224 lat = 0 and = 2396 lev = 37 + i10 : i/o = 257/ 224 lat = 0 and = 1851 lev = 35 + Networks are equivalent. + Reading = 0.00 sec Rewriting = 0.18 sec Verification = 0.41 sec + +The same can be produced by running the binary in the command-line mode: + + [...] ~/abc> ./abc + UC Berkeley, ABC 1.01 (compiled Oct 6 2012 19:05:18) + abc 01> r i10.aig; b; ps; b; rw -l; rw -lz; b; rw -lz; b; ps; cec + i10 : i/o = 257/ 224 lat = 0 and = 2396 lev = 37 + i10 : i/o = 257/ 224 lat = 0 and = 1851 lev = 35 + Networks are equivalent. + +or in the batch mode: + + [...] ~/abc> ./abc -c "r i10.aig; b; ps; b; rw -l; rw -lz; b; rw -lz; b; ps; cec" + ABC command line: "r i10.aig; b; ps; b; rw -l; rw -lz; b; rw -lz; b; ps; cec". + i10 : i/o = 257/ 224 lat = 0 and = 2396 lev = 37 + i10 : i/o = 257/ 224 lat = 0 and = 1851 lev = 35 + Networks are equivalent. + +## Compiling as C or C++ + +The current version of ABC can be compiled with C compiler or C++ compiler. + + * To compile as C code (default): make sure that `CC=gcc` and `ABC_NAMESPACE` is not defined. + * To compile as C++ code without namespaces: make sure that `CC=g++` and `ABC_NAMESPACE` is not defined. + * To compile as C++ code with namespaces: make sure that `CC=g++` and `ABC_NAMESPACE` is set to + the name of the requested namespace. For example, add `-DABC_NAMESPACE=xxx` to OPTFLAGS. + +## Building a shared library + + * Compile the code as position-independent by adding `ABC_USE_PIC=1`. + * Build the `libabc.so` target: + + make ABC_USE_PIC=1 libabc.so + +## Bug reporting: + +Please try to reproduce all the reported bugs and unexpected features using the latest +version of ABC available from https://github.com/berkeley-abc/abc + +If the bug still persists, please provide the following information: + + 1. ABC version (when it was downloaded from GitHub) + 1. Linux distribution and version (32-bit or 64-bit) + 1. The exact command-line and error message when trying to run the tool + 1. The output of the `ldd` command run on the exeutable (e.g. `ldd abc`). + 1. Versions of relevant tools or packages used. + + +## Troubleshooting: + + 1. If compilation does not start because of the cyclic dependency check, +try touching all files as follows: `find ./ -type f -exec touch "{}" \;` + 1. If compilation fails because readline is missing, install 'readline' library or +compile with `make ABC_USE_NO_READLINE=1` + 1. If compilation fails because pthreads are missing, install 'pthread' library or +compile with `make ABC_USE_NO_PTHREADS=1` + * See http://sourceware.org/pthreads-win32/ for pthreads on Windows + * Precompiled DLLs are available from ftp://sourceware.org/pub/pthreads-win32/dll-latest + 1. If compilation fails in file "src/base/main/libSupport.c", try the following: + * Remove "src/base/main/libSupport.c" from "src/base/main/module.make" + * Comment out calls to `Libs_Init()` and `Libs_End()` in "src/base/main/mainInit.c" + 1. On some systems, readline requires adding '-lcurses' to Makefile. + +The following comment was added by Krish Sundaresan: + +"I found that the code does compile correctly on Solaris if gcc is used (instead of +g++ that I was using for some reason). Also readline which is not available by default +on most Sol10 systems, needs to be installed. I downloaded the readline-5.2 package +from sunfreeware.com and installed it locally. Also modified CFLAGS to add the local +include files for readline and LIBS to add the local libreadline.a. Perhaps you can +add these steps in the readme to help folks compiling this on Solaris." + +The following tutorial is kindly offered by Ana Petkovska from EPFL: +https://www.dropbox.com/s/qrl9svlf0ylxy8p/ABC_GettingStarted.pdf + +## Final remarks: + +Unfortunately, there is no comprehensive regression test. Good luck! + +This system is maintained by Alan Mishchenko . Consider also +using ZZ framework developed by Niklas Een: https://bitbucket.org/niklaseen/abc-zz (or https://github.com/berkeley-abc/abc-zz) diff --git a/yosys/abc/abc.rc b/yosys/abc/abc.rc new file mode 100644 index 00000000000..c87e70b4ba7 --- /dev/null +++ b/yosys/abc/abc.rc @@ -0,0 +1,150 @@ +# global parameters +set check # checks intermediate networks +#set checkfio # prints warnings when fanins/fanouts are duplicated +#unset checkread # does not check new networks after reading from file +#set backup # saves backup networks retrived by "undo" and "recall" +#set savesteps 1 # sets the maximum number of backup networks to save +#set progressbar # display the progress bar + +# program names for internal calls +set dotwin dot.exe +set dotunix dot +set gsviewwin gsview32.exe +set gsviewunix gv +set siswin sis.exe +set sisunix sis +set mvsiswin mvsis.exe +set mvsisunix mvsis +set capowin MetaPl-Capo10.1-Win32.exe +set capounix MetaPl-Capo10.1 +set gnuplotwin wgnuplot.exe +set gnuplotunix gnuplot + +# Niklas Een's commands +#load_plugin C:\_projects\abc\lib\bip_win.exe "BIP" + +# standard aliases +alias hi history +alias b balance +alias cg clockgate +alias cl cleanup +alias clp collapse +alias cs care_set +alias el eliminate +alias esd ext_seq_dcs +alias f fraig +alias fs fraig_sweep +alias fsto fraig_store +alias fres fraig_restore +alias fr fretime +alias ft fraig_trust +alias ic indcut +alias lp lutpack +alias pcon print_cone +alias pd print_dsd +alias pex print_exdc -d +alias pf print_factor +alias pfan print_fanio +alias pg print_gates +alias pl print_level +alias plat print_latch +alias pio print_io +alias pk print_kmap +alias pm print_miter +alias ps print_stats +alias psb print_stats -b +alias psu print_supp +alias psy print_symm +alias pun print_unate +alias q quit +alias r read +alias ra read_aiger +alias r3 retime -M 3 +alias r3f retime -M 3 -f +alias r3b retime -M 3 -b +alias ren renode +alias rh read_hie +alias ri read_init +alias rl read_blif +alias rb read_bench +alias ret retime +alias dret dretime +alias rp read_pla +alias rt read_truth +alias rv read_verilog +alias rvl read_verlib +alias rsup read_super mcnc5_old.super +alias rlib read_library +alias rlibc read_library cadence.genlib +alias rty read_liberty +alias rlut read_lut +alias rw rewrite +alias rwz rewrite -z +alias rf refactor +alias rfz refactor -z +alias re restructure +alias rez restructure -z +alias rs resub +alias rsz resub -z +alias sa set autoexec ps +alias scl scleanup +alias sif if -s +alias so source -x +alias st strash +alias sw sweep +alias ssw ssweep +alias tr0 trace_start +alias tr1 trace_check +alias trt "r c.blif; st; tr0; b; tr1" +alias u undo +alias w write +alias wa write_aiger +alias wb write_bench +alias wc write_cnf +alias wh write_hie +alias wl write_blif +alias wp write_pla +alias wv write_verilog + +# standard scripts +alias resyn "b; rw; rwz; b; rwz; b" +alias resyn2 "b; rw; rf; b; rw; rwz; b; rfz; rwz; b" +alias resyn2a "b; rw; b; rw; rwz; b; rwz; b" +alias resyn3 "b; rs; rs -K 6; b; rsz; rsz -K 6; b; rsz -K 5; b" +alias compress "b -l; rw -l; rwz -l; b -l; rwz -l; b -l" +alias compress2 "b -l; rw -l; rf -l; b -l; rw -l; rwz -l; b -l; rfz -l; rwz -l; b -l" +alias choice "fraig_store; resyn; fraig_store; resyn2; fraig_store; fraig_restore" +alias choice2 "fraig_store; balance; fraig_store; resyn; fraig_store; resyn2; fraig_store; resyn2; fraig_store; fraig_restore" +alias rwsat "st; rw -l; b -l; rw -l; rf -l" +alias drwsat2 "st; drw; b -l; drw; drf; ifraig -C 20; drw; b -l; drw; drf" +alias share "st; multi -m; sop; fx; resyn2" +alias addinit "read_init; undc; strash; zero" +alias blif2aig "undc; strash; zero" +alias v2p "&vta_gla; &ps; &gla_derive; &put; w 1.aig; pdr -v" +alias g2p "&ps; &gla_derive; &put; w 2.aig; pdr -v" +alias &sw_ "&put; sweep; st; &get" +alias &fx_ "&put; sweep; sop; fx; st; &get" +alias &dc3 "&b; &jf -K 6; &b; &jf -K 4; &b" +alias &dc4 "&b; &jf -K 7; &fx; &b; &jf -K 5; &fx; &b" + +# resubstitution scripts for the IWLS paper +alias src_rw "st; rw -l; rwz -l; rwz -l" +alias src_rs "st; rs -K 6 -N 2 -l; rs -K 9 -N 2 -l; rs -K 12 -N 2 -l" +alias src_rws "st; rw -l; rs -K 6 -N 2 -l; rwz -l; rs -K 9 -N 2 -l; rwz -l; rs -K 12 -N 2 -l" +alias resyn2rs "b; rs -K 6; rw; rs -K 6 -N 2; rf; rs -K 8; b; rs -K 8 -N 2; rw; rs -K 10; rwz; rs -K 10 -N 2; b; rs -K 12; rfz; rs -K 12 -N 2; rwz; b" +alias r2rs "b; rs -K 6; rw; rs -K 6 -N 2; rf; rs -K 8; b; rs -K 8 -N 2; rw; rs -K 10; rwz; rs -K 10 -N 2; b; rs -K 12; rfz; rs -K 12 -N 2; rwz; b" +alias compress2rs "b -l; rs -K 6 -l; rw -l; rs -K 6 -N 2 -l; rf -l; rs -K 8 -l; b -l; rs -K 8 -N 2 -l; rw -l; rs -K 10 -l; rwz -l; rs -K 10 -N 2 -l; b -l; rs -K 12 -l; rfz -l; rs -K 12 -N 2 -l; rwz -l; b -l" +alias c2rs "b -l; rs -K 6 -l; rw -l; rs -K 6 -N 2 -l; rf -l; rs -K 8 -l; b -l; rs -K 8 -N 2 -l; rw -l; rs -K 10 -l; rwz -l; rs -K 10 -N 2 -l; b -l; rs -K 12 -l; rfz -l; rs -K 12 -N 2 -l; rwz -l; b -l" +alias &resyn2rs "&put; resyn2rs; &get" +alias &compress2rs "&put; compress2rs; &get" + +# use this script to convert 1-valued and DC-valued flops for an AIG +alias fix_aig "logic; undc; strash; zero" + +# use this script to convert 1-valued and DC-valued flops for a logic network coming from BLIF +alias fix_blif "undc; strash; zero" + +# lazy man's synthesis +alias recadd3 "st; rec_add3; b; rec_add3; dc2; rec_add3; if -K 8; bidec; st; rec_add3; dc2; rec_add3; if -g -K 6; st; rec_add3" + + diff --git a/yosys/abc/abcexe.dsp b/yosys/abc/abcexe.dsp new file mode 100644 index 00000000000..9d5152fc2ba --- /dev/null +++ b/yosys/abc/abcexe.dsp @@ -0,0 +1,103 @@ +# Microsoft Developer Studio Project File - Name="abcexe" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=abcexe - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "abcexe.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "abcexe.mak" CFG="abcexe - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "abcexe - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "abcexe - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "abcexe - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ReleaseExe" +# PROP BASE Intermediate_Dir "ReleaseExe" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "ReleaseExe" +# PROP Intermediate_Dir "ReleaseExe" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "src" /D "WIN32" /D "WINDOWS" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D ABC_DLL=ABC_DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /D "ABC_USE_PTHREADS" /D "ABC_USE_CUDD" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib lib\x86\pthreadVC2.lib /nologo /subsystem:console /incremental:yes /debug /machine:I386 /out:"_TEST/abc.exe" +# SUBTRACT LINK32 /profile + +!ELSEIF "$(CFG)" == "abcexe - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "DebugExe" +# PROP BASE Intermediate_Dir "DebugExe" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "DebugExe" +# PROP Intermediate_Dir "DebugExe" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "src" /D "WIN32" /D "WINDOWS" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D ABC_DLL=ABC_DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /D "ABC_USE_PTHREADS" /D "ABC_USE_CUDD" /FR /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib lib\x86\pthreadVC2.lib /nologo /subsystem:console /debug /machine:I386 /out:"_TEST/abc.exe" + +!ENDIF + +# Begin Target + +# Name "abcexe - Win32 Release" +# Name "abcexe - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\src\base\main\main.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/yosys/abc/abclib.dsp b/yosys/abc/abclib.dsp new file mode 100644 index 00000000000..2bcb6e1b85f --- /dev/null +++ b/yosys/abc/abclib.dsp @@ -0,0 +1,7180 @@ +# Microsoft Developer Studio Project File - Name="abclib" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=abclib - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "abclib.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "abclib.mak" CFG="abclib - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "abclib - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "abclib - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "abclib - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "ReleaseLib" +# PROP BASE Intermediate_Dir "ReleaseLib" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "ReleaseLib" +# PROP Intermediate_Dir "ReleaseLib" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "src" /D "WIN32" /D "WINDOWS" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D ABC_DLL=ABC_DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /D "ABC_USE_PTHREADS" /D "ABC_USE_CUDD" /FR /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"lib\abcr.lib" + +!ELSEIF "$(CFG)" == "abclib - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "DebugLib" +# PROP BASE Intermediate_Dir "DebugLib" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "DebugLib" +# PROP Intermediate_Dir "DebugLib" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "src" /D "WIN32" /D "WINDOWS" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D ABC_DLL=ABC_DLLEXPORT /D "_CRT_SECURE_NO_DEPRECATE" /D "ABC_USE_PTHREADS" /D "ABC_USE_CUDD" /FR /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"lib\abcd.lib" + +!ENDIF + +# Begin Target + +# Name "abclib - Win32 Release" +# Name "abclib - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Group "base" + +# PROP Default_Filter "" +# Begin Group "abc" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\abc\abc.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcAig.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcBarBuf.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcBlifMv.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcCheck.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcDfs.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcFanio.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcFanOrder.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcFunc.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcHie.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcHieCec.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcHieGia.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcHieNew.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcLatch.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcLib.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcMinBase.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcNames.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcNetlist.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcNtk.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcObj.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcRefs.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcShow.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcSop.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abc\abcUtil.c +# End Source File +# End Group +# Begin Group "abci" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\abci\abc.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcAttach.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcAuto.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcBalance.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcBidec.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcBm.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcBmc.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcCas.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcCascade.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcCollapse.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcDar.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcDebug.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcDec.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcDetect.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcDress.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcDress2.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcDress3.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcDsd.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcEco.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcExact.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcExtract.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcFraig.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcFx.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcFxu.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcGen.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcHaig.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcIf.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcIfif.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcIfMux.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcIvy.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcLog.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcLut.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcLutmin.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcMap.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcMeasure.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcMerge.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcMffc.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcMfs.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcMini.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcMiter.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcMulti.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcMv.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcNpn.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcNpnSave.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcNtbdd.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcOdc.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcOrder.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcOrchestration.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcPart.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcPrint.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcProve.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcQbf.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcQuant.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcReach.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcRec3.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcReconv.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcRefactor.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcRenode.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcReorder.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcRestruct.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcResub.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcRewrite.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcRpo.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcRr.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcRunGen.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcSaucy.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcScorr.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcSense.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcSpeedup.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcStrash.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcSweep.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcSymm.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcTim.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcTiming.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcUnate.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcUnreach.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcVerify.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\abci\abcXsim.c +# End Source File +# End Group +# Begin Group "cmd" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\cmd\cmd.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmd.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmdAlias.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmdApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmdAuto.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmdFlag.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmdHist.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmdInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmdLoad.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmdPlugin.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmdStarter.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cmd\cmdUtils.c +# End Source File +# End Group +# Begin Group "io" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\io\io.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioabc.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioJson.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadAiger.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadBaf.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadBblif.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadBench.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadBlif.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadBlifAig.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadBlifMv.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadDsd.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadEdif.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadEqn.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadPla.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadPlaMo.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioReadVerilog.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteAiger.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteBaf.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteBblif.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteBench.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteBlif.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteBlifMv.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteBook.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteCnf.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteDot.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteEdgelist.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteEqn.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteGml.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteHMetis.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteList.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWritePla.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteSmv.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\io\ioWriteVerilog.c +# End Source File +# End Group +# Begin Group "main" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\main\abcapis.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\main\libSupport.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\main\main.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\main\mainFrame.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\main\mainInit.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\main\mainInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\main\mainLib.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\main\mainReal.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\main\mainUtils.c +# End Source File +# End Group +# Begin Group "ver" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\ver\ver.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\ver\verCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\ver\verFormula.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\ver\verParse.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\ver\verStream.c +# End Source File +# End Group +# Begin Group "test" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\test\test.c +# End Source File +# End Group +# Begin Group "wlc" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\wlc\wlc.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wlc\wlc.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\wlc\wlcAbc.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wlc\wlcAbs.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wlc\wlcAbs2.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wlc\wlcBlast.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wlc\wlcCom.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wlc\wlcGraft.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wlc\wlcJson.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wlc\wlcMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wlc\wlcNdr.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wlc\wlcNtk.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wlc\wlcPth.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wlc\wlcReadSmt.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wlc\wlcReadVer.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wlc\wlcShow.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wlc\wlcSim.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wlc\wlcStdin.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wlc\wlcUif.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wlc\wlcWin.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wlc\wlcWriteVer.c +# End Source File +# End Group +# Begin Group "pla" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\pla\pla.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\pla\plaCom.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\pla\plaHash.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\pla\plaMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\pla\plaMerge.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\pla\plaRead.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\pla\plaSimple.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\pla\plaWrite.c +# End Source File +# End Group +# Begin Group "bac" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\bac\bac.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\bac\bac.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\bac\bacBac.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\bac\bacBlast.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\bac\bacCom.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\bac\bacLib.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\bac\bacNtk.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\bac\bacOper.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\bac\bacPrs.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\bac\bacPrsBuild.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\bac\bacPrsTrans.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\bac\bacPtr.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\bac\bacPtrAbc.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\bac\bacReadBlif.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\bac\bacReadSmt.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\bac\bacReadVer.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\bac\bacWriteBlif.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\bac\bacWriteSmt.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\bac\bacWriteVer.c +# End Source File +# End Group +# Begin Group "cba" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\cba\cba.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cba\cba.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\cba\cbaBlast.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cba\cbaCba.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cba\cbaCom.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cba\cbaNtk.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cba\cbaPrs.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\cba\cbaReadBlif.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cba\cbaReadVer.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cba\cbaTypes.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\cba\cbaWriteBlif.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\cba\cbaWriteVer.c +# End Source File +# End Group +# Begin Group "exor" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\exor\exor.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\exor\exor.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\exor\exorBits.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\exor\exorCubes.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\exor\exorLink.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\exor\exorList.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\exor\exorUtil.c +# End Source File +# End Group +# Begin Group "acb" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\acb\acb.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\acb\acb.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\acb\acbAbc.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\acb\acbAig.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\acb\acbCom.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\acb\acbFunc.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\acb\acbMfs.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\acb\acbPar.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\acb\acbPush.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\acb\acbSets.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\acb\acbSets.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\acb\acbTest.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\acb\acbUtil.c +# End Source File +# End Group +# Begin Group "wln" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\base\wln\wln.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wln.h +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wlnBlast.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wlnCom.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wlnGuide.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wlnMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wlnNdr.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wlnNtk.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wlnObj.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wlnRead.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wlnRetime.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wlnRtl.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wlnWlc.c +# End Source File +# Begin Source File + +SOURCE=.\src\base\wln\wlnWriteVer.c +# End Source File +# End Group +# End Group +# Begin Group "bdd" + +# PROP Default_Filter "" +# Begin Group "extrab" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bdd\extrab\extraBdd.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\extrab\extraLutCas.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\extrab\extraBddAuto.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\extrab\extraBddCas.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\extrab\extraBddImage.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\extrab\extraBddKmap.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\extrab\extraBddMaxMin.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\extrab\extraBddMisc.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\extrab\extraBddSet.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\extrab\extraBddSymm.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\extrab\extraBddThresh.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\extrab\extraBddTime.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\extrab\extraBddUnate.c +# End Source File +# End Group +# Begin Group "llb" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bdd\llb\llb.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llb1Cluster.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llb1Constr.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llb1Core.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llb1Group.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llb1Hint.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llb1Man.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llb1Matrix.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llb1Pivot.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llb1Reach.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llb1Sched.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llb2Bad.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llb2Core.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llb2Driver.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llb2Dump.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llb2Flow.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llb2Image.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llb3Image.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llb3Nonlin.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llb4Cex.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llb4Cluster.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llb4Image.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llb4Map.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llb4Nonlin.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llb4Sweep.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\llb\llbInt.h +# End Source File +# End Group +# Begin Group "bbr" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bdd\bbr\bbr.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\bbr\bbrCex.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\bbr\bbrImage.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\bbr\bbrNtbdd.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\bbr\bbrReach.c +# End Source File +# End Group +# Begin Group "cas" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bdd\cas\cas.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cas\casCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cas\casDec.c +# End Source File +# End Group +# Begin Group "reo" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bdd\reo\reo.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoProfile.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoShuffle.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoSift.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoSwap.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoTest.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoTransfer.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\reo\reoUnits.c +# End Source File +# End Group +# Begin Group "dsd" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bdd\dsd\dsd.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\dsd\dsdApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\dsd\dsdCheck.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\dsd\dsdInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\dsd\dsdLocal.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\dsd\dsdMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\dsd\dsdProc.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\dsd\dsdTree.c +# End Source File +# End Group +# Begin Group "mtr" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bdd\mtr\mtr.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\mtr\mtrBasic.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\mtr\mtrGroup.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\mtr\mtrInt.h +# End Source File +# End Group +# Begin Group "epd" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bdd\epd\epd.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\epd\epd.h +# End Source File +# End Group +# Begin Group "cudd" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bdd\cudd\cudd.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAddAbs.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAddApply.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAddFind.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAddInv.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAddIte.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAddNeg.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAddWalsh.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAndAbs.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAnneal.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddApa.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddAPI.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddApprox.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddBddAbs.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddBddCorr.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddBddIte.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddBridge.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddCache.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddCheck.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddClip.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddCof.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddCompose.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddDecomp.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddEssent.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddExact.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddExport.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddGenCof.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddGenetic.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddGroup.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddHarwell.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddInit.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddInteract.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddLCache.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddLevelQ.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddLinear.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddLiteral.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddMatMult.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddPriority.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddRead.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddRef.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddReorder.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddSign.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddSolve.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddSplit.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddSubsetHB.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddSubsetSP.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddSymmetry.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddTable.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddWindow.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddCount.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddFuncs.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddGroup.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddIsop.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddLin.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddMisc.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddPort.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddReord.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddSetop.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddSymm.c +# End Source File +# Begin Source File + +SOURCE=.\src\bdd\cudd\cuddZddUtil.c +# End Source File +# End Group +# End Group +# Begin Group "sat" + +# PROP Default_Filter "" +# Begin Group "msat" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\msat\msat.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatActivity.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatClause.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatClauseVec.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatOrderH.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatQueue.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatRead.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatSolverApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatSolverCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatSolverIo.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatSolverSearch.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatSort.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\msat\msatVec.c +# End Source File +# End Group +# Begin Group "csat" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\csat\csat_apis.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\csat\csat_apis.h +# End Source File +# End Group +# Begin Group "bsat" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\bsat\satClause.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satInter.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satInterA.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satInterB.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satInterP.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satMem.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satProof.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satProof2.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satSolver.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satSolver.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satSolver2.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satSolver2.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satSolver2i.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satSolver3.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satSolver3.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satStore.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satStore.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satTrace.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satTruth.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satTruth.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bsat\satVec.h +# End Source File +# End Group +# Begin Group "proof" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\proof\pr.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\proof\pr.h +# End Source File +# End Group +# Begin Group "psat" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\psat\m114p.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\psat\m114p_types.h +# End Source File +# End Group +# Begin Group "lsat" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\lsat\solver.h +# End Source File +# End Group +# Begin Group "cnf" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\cnf\cnf.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cnf\cnfCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cnf\cnfCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cnf\cnfData.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cnf\cnfFast.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cnf\cnfMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cnf\cnfMap.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cnf\cnfPost.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cnf\cnfUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cnf\cnfWrite.c +# End Source File +# End Group +# Begin Group "bmc" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\bmc\bmc.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmc.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcBCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcBmc.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcBmc2.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcBmc3.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcBmcAnd.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcBmcG.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcBmci.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcBmcS.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcCexCare.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcCexCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcCexDepth.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcCexMin1.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcCexMin2.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcCexTools.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcChain.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcClp.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcEco.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcExpand.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcFault.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcFx.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcGen.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcICheck.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcInse.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcLoad.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcMaj.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcMaj2.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcMaj3.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcMaxi.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcMesh.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcMesh2.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcMulti.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\bmc\bmcUnroll.c +# End Source File +# End Group +# Begin Group "bsat2" + +# PROP Default_Filter "" +# End Group +# Begin Group "satoko" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\satoko\act_clause.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\satoko\act_var.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\satoko\utils\b_queue.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\satoko\cdb.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\satoko\clause.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\satoko\cnf_reader.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\satoko\utils\heap.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\satoko\utils\mem.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\satoko\utils\misc.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\satoko\satoko.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\satoko\utils\sdbl.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\satoko\solver.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\satoko\solver.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\satoko\solver_api.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\satoko\utils\sort.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\satoko\types.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\satoko\utils\vec\vec_char.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\satoko\utils\vec\vec_flt.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\satoko\utils\vec\vec_int.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\satoko\utils\vec\vec_uint.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\satoko\watch_list.h +# End Source File +# End Group +# Begin Group "xsat" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\xsat\xsat.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\xsat\xsatBQueue.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\xsat\xsatClause.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\xsat\xsatCnfReader.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\xsat\xsatHeap.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\xsat\xsatMemory.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\xsat\xsatSolver.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\xsat\xsatSolver.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\xsat\xsatSolverAPI.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\xsat\xsatUtils.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\xsat\xsatWatchList.h +# End Source File +# End Group +# Begin Group "glucose" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\glucose\AbcGlucose.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\AbcGlucose.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\AbcGlucoseCmd.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\Alg.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\Alloc.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\BoundedQueue.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\Constants.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\Dimacs.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\Glucose.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\Heap.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\IntTypes.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\Map.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\Options.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\Options.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\ParseUtils.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\pstdint.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\Queue.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\SimpSolver.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\SimpSolver.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\Solver.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\SolverTypes.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\Sort.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\System.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\System.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\Vec.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose\XAlloc.h +# End Source File +# End Group +# Begin Group "glucose2" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\glucose2\AbcGlucose2.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\AbcGlucose2.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\AbcGlucoseCmd2.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Alg.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Alloc.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\BoundedQueue.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\CGlucose.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\CGlucoseCore.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Constants.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Dimacs.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Glucose2.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Heap.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\IntTypes.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Map.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Options.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Options2.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\ParseUtils.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\pstdint.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Queue.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\SimpSolver.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\SimpSolver2.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Solver.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\SolverTypes.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Sort.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\System.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\System2.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\Vec.h +# End Source File +# Begin Source File + +SOURCE=.\src\sat\glucose2\XAlloc.h +# End Source File +# End Group +# Begin Group "kissat" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\kissat\allocate.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\analyze.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\ands.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\arena.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\assign.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\averages.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\backbone.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\backtrack.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\build.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\bump.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\check.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\classify.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\clause.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\collect.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\colors.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\compact.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\config.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\congruence.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\decide.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\deduce.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\definition.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\dense.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\dump.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\eliminate.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\equivalences.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\error.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\extend.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\factor.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\fastel.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\file.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\flags.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\format.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\forward.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\gates.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\heap.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\ifthenelse.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\import.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\internal.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\kimits.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\kissatSolver.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\kissatTest.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\kitten.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\kptions.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\krite.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\kucky.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\learn.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\logging.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\minimize.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\mode.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\phases.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\preprocess.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\print.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\probe.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\profile.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\promote.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\proof.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\propbeyond.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\propdense.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\propinitially.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\proprobe.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\propsearch.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\queue.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\reduce.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\reluctant.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\reorder.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\rephase.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\report.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\resize.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\resolve.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\resources.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\restart.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\search.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\shrink.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\smooth.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\sort.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\stack.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\statistics.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\strengthen.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\substitute.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\sweep.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\terminate.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\tiers.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\trail.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\transitive.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\utilities.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\vector.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\vivify.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\walk.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\warmup.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\watch.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\kissat\weaken.c +# End Source File +# End Group +# Begin Group "cadical" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_kitten.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_analyze.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_arena.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_assume.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_averages.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_backtrack.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_backward.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_bins.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_block.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_ccadical.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_checker.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_clause.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_collect.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_compact.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_condition.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_config.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_congruence.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_constrain.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_contract.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_cover.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_decide.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_decompose.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_deduplicate.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_definition.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_drattracer.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_elim.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_elimfast.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_ema.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_extend.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_external.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_external_propagate.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_factor.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_file.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_flags.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_flip.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_format.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_frattracer.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_gates.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_idruptracer.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_instantiate.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_internal.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_ipasir.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_lidruptracer.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_limit.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_logging.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_lookahead.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_lratchecker.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_lrattracer.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_lucky.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_message.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_minimize.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_occs.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_options.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_parse.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_phases.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_probe.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_profile.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_proof.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_propagate.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_queue.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_random.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_reap.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_reduce.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_rephase.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_report.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_resources.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_restart.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_restore.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_score.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_shrink.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_signal.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_solution.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_solver.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_stable.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_stats.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_subsume.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_sweep.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_terminal.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_ternary.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_tier.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_transred.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_unstable.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_util.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_var.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_veripbtracer.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_version.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_vivify.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_walk.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadical_watch.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadicalSolver.c +# End Source File +# Begin Source File + +SOURCE=.\src\sat\cadical\cadicalTest.c +# End Source File +# End Group +# End Group +# Begin Group "opt" + +# PROP Default_Filter "" +# Begin Group "fxu" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\fxu\fxu.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxu.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuCreate.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuHeapD.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuHeapS.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuList.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuMatrix.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuPair.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuPrint.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuReduce.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuSelect.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuSingle.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxu\fxuUpdate.c +# End Source File +# End Group +# Begin Group "rar" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\rar\rewire_map.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rar\rewire_miaig.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rar\rewire_rar.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rar\rewire_rng.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rar\rewire_time.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rar\rewire_tt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rar\rewire_vec.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rar\rewire_map.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rar\rewire_miaig.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rar\rewire_rar.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rar\rewire_rng.c +# End Source File +# End Group +# Begin Group "rwr" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\rwr\rwr.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwr\rwrDec.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwr\rwrEva.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwr\rwrExp.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwr\rwrLib.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwr\rwrMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwr\rwrPrint.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwr\rwrTemp.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwr\rwrUtil.c +# End Source File +# End Group +# Begin Group "cut" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\cut\cut.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutExpand.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutList.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutMerge.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutNode.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutOracle.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutPre22.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutSeq.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cut\cutTruth.c +# End Source File +# End Group +# Begin Group "sim" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\sim\sim.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simSeq.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simSupp.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simSwitch.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simSym.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simSymSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simSymSim.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simSymStr.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sim\simUtils.c +# End Source File +# End Group +# Begin Group "ret" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\ret\retArea.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\ret\retCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\ret\retDelay.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\ret\retFlow.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\ret\retIncrem.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\ret\retInit.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\ret\retInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\ret\retLvalue.c +# End Source File +# End Group +# Begin Group "res" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\res\res.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\res\resCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\res\resDivs.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\res\resFilter.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\res\resInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\res\resSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\res\resSim.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\res\resStrash.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\res\resWin.c +# End Source File +# End Group +# Begin Group "lpk" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\lpk\lpk.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkAbcDec.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkAbcDsd.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkAbcMux.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkAbcUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkMap.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkMulti.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkMux.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\lpk\lpkSets.c +# End Source File +# End Group +# Begin Group "mfs" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\mfs\mfs.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\mfs\mfsCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\mfs\mfsDiv.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\mfs\mfsInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\mfs\mfsInter.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\mfs\mfsMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\mfs\mfsResub.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\mfs\mfsSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\mfs\mfsStrash.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\mfs\mfsWin.c +# End Source File +# End Group +# Begin Group "cgt" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\cgt\cgt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cgt\cgtAig.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cgt\cgtCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cgt\cgtDecide.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cgt\cgtInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cgt\cgtMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\cgt\cgtSat.c +# End Source File +# End Group +# Begin Group "csw" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\csw\csw.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\csw\cswCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\csw\cswCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\csw\cswInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\csw\cswMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\csw\cswTable.c +# End Source File +# End Group +# Begin Group "dar" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\dar\dar.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dar\darBalance.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dar\darCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dar\darCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dar\darData.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dar\darInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dar\darLib.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dar\darMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dar\darPrec.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dar\darRefact.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dar\darResub.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dar\darScript.c +# End Source File +# End Group +# Begin Group "rwt" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\rwt\rwt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwt\rwtDec.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwt\rwtMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\rwt\rwtUtil.c +# End Source File +# End Group +# Begin Group "nwk" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\nwk\ntlnwk.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwk.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkAig.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkBidec.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkCheck.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkDfs.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkFanio.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkFlow.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkMap.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkMerge.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkMerge.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkObj.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkSpeedup.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkStrash.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkTiming.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\nwk\nwkUtil.c +# End Source File +# End Group +# Begin Group "dau" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\dau\dau.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dau\dau.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dau\dauCanon.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dau\dauCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dau\dauCount.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dau\dauDivs.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dau\dauDsd.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dau\dauEnum.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dau\dauGia.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dau\dauInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dau\dauMerge.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dau\dauNonDsd.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dau\dauNpn.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dau\dauNpn2.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dau\dauTree.c +# End Source File +# End Group +# Begin Group "sfm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\sfm\sfm.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sfm\sfmArea.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sfm\sfmCnf.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sfm\sfmCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sfm\sfmDec.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sfm\sfmInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sfm\sfmLib.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sfm\sfmMit.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sfm\sfmNtk.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sfm\sfmSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sfm\sfmTim.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sfm\sfmWin.c +# End Source File +# End Group +# Begin Group "fret" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\fret\fretFlow.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fret\fretime.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fret\fretInit.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fret\fretMain.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fret\fretTime.c +# End Source File +# End Group +# Begin Group "fxch" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\fxch\Fxch.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxch\Fxch.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxch\FxchDiv.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxch\FxchMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\fxch\FxchSCHashTable.c +# End Source File +# End Group +# Begin Group "dsc" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\dsc\dsc.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\dsc\dsc.h +# End Source File +# End Group +# Begin Group "sbd" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\sbd\sbd.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sbd\sbd.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sbd\sbdCnf.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sbd\sbdCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sbd\sbdCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sbd\sbdCut2.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sbd\sbdInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sbd\sbdLut.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sbd\sbdPath.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sbd\sbdSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\opt\sbd\sbdWin.c +# End Source File +# End Group +# Begin Group "eslim" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\opt\eslim\eSLIM.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\opt\eslim\eSLIM.h +# End Source File +# Begin Source File + +SOURCE=.\src\opt\eslim\eSLIMMan.hpp +# End Source File +# Begin Source File + +SOURCE=.\src\opt\eslim\relationGeneration.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\opt\eslim\relationGeneration.hpp +# End Source File +# Begin Source File + +SOURCE=.\src\opt\eslim\satInterfaces.hpp +# End Source File +# Begin Source File + +SOURCE=.\src\opt\eslim\selectionStrategy.hpp +# End Source File +# Begin Source File + +SOURCE=.\src\opt\eslim\utils.hpp +# End Source File +# Begin Source File + +SOURCE=.\src\opt\eslim\synthesisEngine.hpp +# End Source File +# End Group +# End Group +# Begin Group "map" + +# PROP Default_Filter "" +# Begin Group "mapper" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\map\mapper\mapper.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapper.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperCanon.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperCreate.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperCutUtils.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperFanout.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperLib.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperMatch.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperRefs.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperSuper.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperSwitch.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperTable.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperTime.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperTree.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperTruth.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperUtils.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mapper\mapperVec.c +# End Source File +# End Group +# Begin Group "mio" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\map\mio\exp.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\mio\mio.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mio\mio.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\mio\mioApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mio\mioFunc.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mio\mioInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\mio\mioParse.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mio\mioRead.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mio\mioSop.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mio\mioUtils.c +# End Source File +# End Group +# Begin Group "super" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\map\super\super.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\super\super.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\super\superAnd.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\super\superGate.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\super\superInt.h +# End Source File +# End Group +# Begin Group "if" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\map\if\if.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifCache.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifCom.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifCount.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifData2.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifDec07.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifDec08.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifDec10.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifDec16.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifDec66.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifDec75.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifDelay.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifDsd.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifLibBox.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifLibLut.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifMap.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifMatch2.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifReduce.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifSelect.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifSeq.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifTest.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifTime.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifTruth.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifTune.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\acd\ac_wrapper.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\map\if\ifUtil.c +# End Source File +# End Group +# Begin Group "amap" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\map\amap\amap.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\amap\amapCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\amap\amapGraph.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\amap\amapInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\amap\amapLib.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\amap\amapLiberty.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\amap\amapMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\amap\amapMatch.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\amap\amapMerge.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\amap\amapOutput.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\amap\amapParse.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\amap\amapPerm.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\amap\amapRead.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\amap\amapRule.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\amap\amapUniq.c +# End Source File +# End Group +# Begin Group "cov" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\map\cov\cov.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\cov\covBuild.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\cov\covCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\cov\covInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\cov\covMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\cov\covMinEsop.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\cov\covMinMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\cov\covMinSop.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\cov\covMinUtil.c +# End Source File +# End Group +# Begin Group "scl" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\map\scl\scl.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\scl\scl.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\scl\sclBuffer.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\scl\sclBufSize.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\scl\sclCon.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\scl\sclDnsize.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\scl\sclLib.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\scl\sclLiberty.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\scl\sclLibScl.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\scl\sclLibUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\scl\sclLoad.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\scl\sclSize.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\scl\sclSize.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\scl\sclTime.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\scl\sclUpsize.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\scl\sclUtil.c +# End Source File +# End Group +# Begin Group "mpm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\map\mpm\mpm.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mpm\mpm.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\mpm\mpmAbc.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mpm\mpmCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mpm\mpmDsd.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mpm\mpmGates.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mpm\mpmInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\mpm\mpmLib.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mpm\mpmMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mpm\mpmMap.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mpm\mpmMig.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mpm\mpmMig.h +# End Source File +# Begin Source File + +SOURCE=.\src\map\mpm\mpmPre.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mpm\mpmTruth.c +# End Source File +# Begin Source File + +SOURCE=.\src\map\mpm\mpmUtil.c +# End Source File +# End Group +# End Group +# Begin Group "misc" + +# PROP Default_Filter "" +# Begin Group "extra" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\extra\extra.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilBitMatrix.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilCanon.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilCfs.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilCube.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilDsd.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilEnum.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilFile.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilGen.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilMacc.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilMaj.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilMemory.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilMisc.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilMult.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilPath.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilPerm.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilPrime.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilProgress.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilReader.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilSupp.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilTruth.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\extra\extraUtilUtil.c +# End Source File +# End Group +# Begin Group "st" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\st\st.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\st\st.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\st\stmm.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\st\stmm.h +# End Source File +# End Group +# Begin Group "mvc" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\mvc\mvc.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvc.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcCompare.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcContain.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcCover.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcCube.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcDivide.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcDivisor.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcList.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcLits.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcOpAlg.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcOpBool.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcPrint.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcSort.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mvc\mvcUtils.c +# End Source File +# End Group +# Begin Group "vec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\vec\vec.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecAtt.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecBit.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecFlt.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecHash.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecHsh.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecMem.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecPtr.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecQue.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecSet.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecStr.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecVec.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecWec.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\vec\vecWrd.h +# End Source File +# End Group +# Begin Group "util" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\util\abc_global.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\util\util_hack.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\util\utilBridge.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\util\utilBSet.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\util\utilCex.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\util\utilCex.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\util\utilColor.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\util\utilDouble.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\util\utilFile.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\util\utilFloat.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\util\utilIsop.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\util\utilMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\util\utilMem.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\util\utilNam.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\util\utilNam.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\util\utilPth.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\util\utilSignal.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\util\utilSignal.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\util\utilSort.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\util\utilTruth.h +# End Source File +# End Group +# Begin Group "nm" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\nm\nm.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\nm\nmApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\nm\nmInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\nm\nmTable.c +# End Source File +# End Group +# Begin Group "hash" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\hash\hash.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\hash\hashFlt.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\hash\hashInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\hash\hashPtr.h +# End Source File +# End Group +# Begin Group "bzlib" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\bzlib\blocksort.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\bzlib\bzlib.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\bzlib\bzlib.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\bzlib\bzlib_private.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\bzlib\compress.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\bzlib\crctable.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\bzlib\decompress.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\bzlib\huffman.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\bzlib\randtable.c +# End Source File +# End Group +# Begin Group "zlib" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\zlib\adler32.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\compress_.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\crc32.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\crc32.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\deflate.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\deflate.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\gzclose.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\gzguts.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\gzlib.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\gzread.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\gzwrite.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\infback.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\inffast.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\inffast.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\inffixed.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\inflate.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\inflate.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\inftrees.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\inftrees.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\trees.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\trees.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\uncompr.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\zconf.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\zlib.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\zutil.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\zlib\zutil.h +# End Source File +# End Group +# Begin Group "bar" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\bar\bar.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\bar\bar.h +# End Source File +# End Group +# Begin Group "bbl" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\bbl\bblif.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\bbl\bblif.h +# End Source File +# End Group +# Begin Group "mem" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\mem\mem.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mem\mem.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\mem\mem2.h +# End Source File +# End Group +# Begin Group "tim" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\tim\tim.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\tim\tim.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\tim\timBox.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\tim\timDump.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\tim\timInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\tim\timMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\tim\timTime.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\tim\timTrav.c +# End Source File +# End Group +# Begin Group "parse" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\misc\parse\parseEqn.c +# End Source File +# Begin Source File + +SOURCE=.\src\misc\parse\parseInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\misc\parse\parseStack.c +# End Source File +# End Group +# End Group +# Begin Group "ai" + +# PROP Default_Filter "" +# Begin Group "hop" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\hop\hop.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopBalance.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopCheck.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopDfs.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopObj.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopOper.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopTable.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopTruth.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\hop\hopUtil.c +# End Source File +# End Group +# Begin Group "ivy" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\ivy\ivy.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyBalance.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyCanon.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyCheck.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyCutTrav.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyDfs.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyDsd.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyFanout.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyFastMap.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyFraig.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyHaig.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyMulti.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyObj.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyOper.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyResyn.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyRwr.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivySeq.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyShow.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyTable.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ivy\ivyUtil.c +# End Source File +# End Group +# Begin Group "ioa" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\ioa\ioa.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ioa\ioaReadAig.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ioa\ioaUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\ioa\ioaWriteAig.c +# End Source File +# End Group +# Begin Group "aig" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\aig\aig.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigCanon.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigCheck.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigCuts.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigDfs.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigDoms.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigDup.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigFact.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigFanout.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigFrames.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigInter.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigJust.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigMffc.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigObj.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigOper.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigOrder.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigPack.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigPart.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigPartReg.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigPartSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigRepr.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigRet.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigRetF.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigScl.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigShow.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigSplit.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigTable.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigTiming.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigTruth.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigTsim.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\aig\aigWin.c +# End Source File +# End Group +# Begin Group "saig" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\saig\saig.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigCone.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigConstr.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigConstr2.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigDual.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigDup.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigInd.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigIoa.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigIso.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigIsoFast.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigIsoSlow.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigMiter.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigOutDec.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigPhase.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigRetFwd.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigRetMin.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigRetStep.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigScl.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigSimFast.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigSimMv.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigSimSeq.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigStrSim.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigSwitch.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigSynch.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigTempor.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigTrans.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\saig\saigWnd.c +# End Source File +# End Group +# Begin Group "gia" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\gia\gia.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\gia.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaAig.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaAig.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaAiger.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaAigerExt.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaBalAig.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaBalLut.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaBalMap.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaBidec.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaBound.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaCCof.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaCex.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaClp.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaCof.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaCone.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaCSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaCSat2.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaCSat3.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaCSatOld.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaCSatP.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaCSatP.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaCTas.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaCut.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaDecs.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaDeep.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaDfs.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaDup.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaEdge.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaEmbed.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaEnable.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaEquiv.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaEra.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaEra2.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaEsop.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaExist.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaFalse.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaFanout.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaForce.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaFrames.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaFront.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaFx.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaGen.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaGig.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaGlitch.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaHash.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaIf.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaIff.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaIiff.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaIiff.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaIso.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaIso2.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaIso3.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaJf.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaKf.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaLf.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaMf.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaMfs.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaMini.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaMinLut.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaMinLut2.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaMulFind.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaMuxes.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaNewBdd.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaNewTt.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaNf.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaOf.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaPack.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaPat.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaPat2.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaPf.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaQbf.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaReshape1.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaReshape2.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaResub.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaResub2.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaResub3.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaResub6.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaRetime.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaRex.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaRrr.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaSat3.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaSatEdge.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaSatLE.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaSatLut.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaSatMap.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaSatoko.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaSatSyn.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaScl.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaScript.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaShow.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaShrink.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaShrink6.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaShrink7.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaSif.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaSim.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaSim2.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaSimBase.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaSort.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaSpeedup.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaSplit.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaStg.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaStoch.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaStr.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaSupMin.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaSupp.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaSupps.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaSweep.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaSweeper.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaSwitch.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaTim.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaTis.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaTruth.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaTsim.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaTtopt.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaTransduction.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaTransduction.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaTranStoch.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaUnate.c +# End Source File +# Begin Source File + +SOURCE=.\src\aig\gia\giaUtil.c +# End Source File +# End Group +# Begin Group "miniaig" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\aig\miniaig\abcOper.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\miniaig\miniaig.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\miniaig\minilut.h +# End Source File +# Begin Source File + +SOURCE=.\src\aig\miniaig\ndr.h +# End Source File +# End Group +# End Group +# Begin Group "bool" + +# PROP Default_Filter "" +# Begin Group "bdc" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bool\bdc\bdc.h +# End Source File +# Begin Source File + +SOURCE=.\src\bool\bdc\bdcCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\bdc\bdcDec.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\bdc\bdcInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\bool\bdc\bdcSpfd.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\bdc\bdcTable.c +# End Source File +# End Group +# Begin Group "dec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bool\dec\dec.h +# End Source File +# Begin Source File + +SOURCE=.\src\bool\dec\decAbc.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\dec\decFactor.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\dec\decMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\dec\decPrint.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\dec\decUtil.c +# End Source File +# End Group +# Begin Group "deco" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bool\deco\deco.h +# End Source File +# End Group +# Begin Group "kit" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bool\kit\cloud.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\kit\cloud.h +# End Source File +# Begin Source File + +SOURCE=.\src\bool\kit\kit.h +# End Source File +# Begin Source File + +SOURCE=.\src\bool\kit\kitAig.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\kit\kitBdd.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\kit\kitCloud.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\kit\kitDec.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\kit\kitDsd.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\kit\kitFactor.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\kit\kitGraph.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\kit\kitHop.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\kit\kitIsop.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\kit\kitPerm.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\kit\kitPla.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\kit\kitSop.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\kit\kitTruth.c +# End Source File +# End Group +# Begin Group "lucky" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bool\lucky\lucky.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\lucky\lucky.h +# End Source File +# Begin Source File + +SOURCE=.\src\bool\lucky\luckyFast16.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\lucky\luckyFast6.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\lucky\luckyInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\bool\lucky\luckyRead.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\lucky\luckySimple.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\lucky\luckySwap.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\lucky\luckySwapIJ.c +# End Source File +# End Group +# Begin Group "rsb" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bool\rsb\rsb.h +# End Source File +# Begin Source File + +SOURCE=.\src\bool\rsb\rsbDec6.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\rsb\rsbInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\bool\rsb\rsbMan.c +# End Source File +# End Group +# Begin Group "rpo" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\bool\rpo\literal.h +# End Source File +# Begin Source File + +SOURCE=.\src\bool\rpo\rpo.c +# End Source File +# Begin Source File + +SOURCE=.\src\bool\rpo\rpo.h +# End Source File +# End Group +# End Group +# Begin Group "prove" + +# PROP Default_Filter "" +# Begin Group "cec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\proof\cec\cec.h +# End Source File +# Begin Source File + +SOURCE=.\src\proof\cec\cecCec.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\cec\cecChoice.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\cec\cecClass.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\cec\cecCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\cec\cecCorr.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\cec\cecInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\proof\cec\cecIso.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\cec\cecMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\cec\cecPat.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\cec\cecProve.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\cec\cecSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\cec\cecSatG.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\cec\cecSatG2.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\cec\cecSatG3.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\cec\cecSeq.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\cec\cecSim.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\cec\cecSolve.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\cec\cecSolveG.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\cec\cecSplit.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\cec\cecSweep.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\cec\cecSynth.c +# End Source File +# End Group +# Begin Group "dch" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\proof\dch\dch.h +# End Source File +# Begin Source File + +SOURCE=.\src\proof\dch\dchAig.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\dch\dchChoice.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\dch\dchClass.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\dch\dchCnf.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\dch\dchCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\dch\dchInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\proof\dch\dchMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\dch\dchSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\dch\dchSim.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\dch\dchSimSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\dch\dchSweep.c +# End Source File +# End Group +# Begin Group "fra" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\proof\fra\fra.h +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fra\fraBmc.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fra\fraCec.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fra\fraClass.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fra\fraClau.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fra\fraClaus.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fra\fraCnf.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fra\fraCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fra\fraHot.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fra\fraImp.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fra\fraInd.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fra\fraIndVer.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fra\fraLcr.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fra\fraMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fra\fraPart.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fra\fraSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fra\fraSec.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fra\fraSim.c +# End Source File +# End Group +# Begin Group "fraig" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\proof\fraig\fraig.h +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fraig\fraigApi.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fraig\fraigCanon.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fraig\fraigChoice.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fraig\fraigFanout.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fraig\fraigFeed.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fraig\fraigInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fraig\fraigMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fraig\fraigMem.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fraig\fraigNode.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fraig\fraigPrime.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fraig\fraigSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fraig\fraigTable.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fraig\fraigUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\fraig\fraigVec.c +# End Source File +# End Group +# Begin Group "int" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\proof\int\int.h +# End Source File +# Begin Source File + +SOURCE=.\src\proof\int\intCheck.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\int\intContain.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\int\intCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\int\intCtrex.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\int\intDup.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\int\intFrames.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\int\intInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\proof\int\intInter.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\int\intM114.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\int\intMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\int\intUtil.c +# End Source File +# End Group +# Begin Group "live" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\proof\live\arenaViolation.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\live\combination.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\live\disjunctiveMonotone.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\live\kLiveConstraints.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\live\kliveness.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\live\liveness.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\live\liveness_sim.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\live\ltl_parser.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\live\monotone.c +# End Source File +# End Group +# Begin Group "pdr" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\proof\pdr\pdr.h +# End Source File +# Begin Source File + +SOURCE=.\src\proof\pdr\pdrClass.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\pdr\pdrCnf.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\pdr\pdrCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\pdr\pdrIncr.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\pdr\pdrInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\proof\pdr\pdrInv.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\pdr\pdrMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\pdr\pdrSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\pdr\pdrTsim.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\pdr\pdrTsim2.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\pdr\pdrTsim3.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\pdr\pdrUtil.c +# End Source File +# End Group +# Begin Group "ssw" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\proof\ssw\ssw.h +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssw\sswAig.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssw\sswBmc.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssw\sswClass.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssw\sswCnf.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssw\sswConstr.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssw\sswCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssw\sswDyn.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssw\sswFilter.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssw\sswInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssw\sswIslands.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssw\sswLcorr.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssw\sswMan.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssw\sswPairs.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssw\sswPart.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssw\sswRarity.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssw\sswRarity2.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssw\sswSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssw\sswSemi.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssw\sswSim.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssw\sswSimSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssw\sswSweep.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssw\sswUnique.c +# End Source File +# End Group +# Begin Group "abs" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\proof\abs\abs.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\abs\abs.h +# End Source File +# Begin Source File + +SOURCE=.\src\proof\abs\absDup.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\abs\absGla.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\abs\absGlaOld.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\abs\absIter.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\abs\absOldCex.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\abs\absOldRef.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\abs\absOldSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\abs\absOldSim.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\abs\absOut.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\abs\absPth.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\abs\absRef.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\abs\absRef.h +# End Source File +# Begin Source File + +SOURCE=.\src\proof\abs\absRefSelect.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\abs\absRpm.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\abs\absRpmOld.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\abs\absUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\abs\absVta.c +# End Source File +# End Group +# Begin Group "ssc" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\proof\ssc\ssc.h +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssc\sscClass.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssc\sscCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssc\sscInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssc\sscSat.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssc\sscSim.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\ssc\sscUtil.c +# End Source File +# End Group +# Begin Group "int2" + +# PROP Default_Filter "" +# End Group +# Begin Group "acec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\src\proof\acec\acec.h +# End Source File +# Begin Source File + +SOURCE=.\src\proof\acec\acec2Mult.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\acec\acecBo.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\acec\acecCl.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\acec\acecCo.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\acec\acecCore.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\acec\acecCover.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\acec\acecFadds.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\acec\acecInt.h +# End Source File +# Begin Source File + +SOURCE=.\src\proof\acec\acecMult.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\acec\acecNorm.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\acec\acecOrder.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\acec\acecPa.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\acec\acecPo.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\acec\acecPolyn.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\acec\acecPool.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\acec\acecRe.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\acec\acecSt.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\acec\acecStruct.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\acec\acecTree.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\acec\acecUtil.c +# End Source File +# Begin Source File + +SOURCE=.\src\proof\acec\acecXor.c +# End Source File +# End Group +# End Group +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# End Target +# End Project diff --git a/yosys/abc/abcspace.dsw b/yosys/abc/abcspace.dsw new file mode 100644 index 00000000000..0f69c0dfc46 --- /dev/null +++ b/yosys/abc/abcspace.dsw @@ -0,0 +1,44 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "abcexe"=.\abcexe.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name abclib + End Project Dependency +}}} + +############################################################################### + +Project: "abclib"=.\abclib.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/yosys/abc/arch_flags.c b/yosys/abc/arch_flags.c new file mode 100644 index 00000000000..a2945ae0a18 --- /dev/null +++ b/yosys/abc/arch_flags.c @@ -0,0 +1,17 @@ +#include + +int main() +{ + if (sizeof(void*) == 8) // Assume 64-bit Linux if pointers are 8 bytes. + printf("-DLIN64 "); + else + printf("-DLIN "); + + printf("-DSIZEOF_VOID_P=%d -DSIZEOF_LONG=%d -DSIZEOF_INT=%d\n", + (int)sizeof(void*), + (int)sizeof(long), + (int)sizeof(int) ); + + + return 0; +} diff --git a/yosys/abc/copyright.txt b/yosys/abc/copyright.txt new file mode 100644 index 00000000000..f99ef9adad3 --- /dev/null +++ b/yosys/abc/copyright.txt @@ -0,0 +1,23 @@ +ABC: System for Sequential Synthesis and Verification + +http://www.eecs.berkeley.edu/~alanmi/abc/ + + +Copyright (c) The Regents of the University of California. All rights reserved. + +Permission is hereby granted, without written agreement and without license or +royalty fees, to use, copy, modify, and distribute this software and its +documentation for any purpose, provided that the above copyright notice and +the following two paragraphs appear in all copies of this software. + +IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR +DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF +THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF +CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, +BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, +AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, +SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + diff --git a/yosys/abc/depends.sh b/yosys/abc/depends.sh new file mode 100755 index 00000000000..d302cd04c78 --- /dev/null +++ b/yosys/abc/depends.sh @@ -0,0 +1,13 @@ +#!/bin/sh +#echo "## Got: $*" +CC="$1" +DIR="$2" +shift 2 +case "$DIR" in + "" | ".") + $CC -MM -MG "$@" | sed -e 's@^\(.*\)\.o:@\1.d \1.o:@' + ;; + *) + $CC -MM -MG "$@" | sed -e "s@^\(.*\)\.o:@$DIR/\1.d $DIR/\1.o:@" + ;; +esac diff --git a/yosys/abc/i10.aig b/yosys/abc/i10.aig new file mode 100644 index 00000000000..203a607e13c --- /dev/null +++ b/yosys/abc/i10.aig @@ -0,0 +1,752 @@ +aig 2932 257 0 224 2675 +886 +1864 +2106 +2108 +2155 +2164 +2389 +2491 +2509 +2461 +2754 +2787 +2789 +2817 +2821 +2834 +2864 +2866 +2868 +2870 +2872 +2912 +2958 +3004 +3056 +3108 +3160 +3214 +3262 +3303 +3325 +3349 +3417 +3487 +3557 +3651 +3745 +3841 +3873 +67 +3876 +3887 +3897 +3907 +3917 +3940 +3948 +2784 +3962 +3955 +93 +766 +578 +4068 +2126 +4072 +2124 +4082 +4084 +4086 +4088 +2128 +2116 +4233 +4234 +555 +4243 +4255 +4276 +4298 +3261 +3213 +3159 +3107 +3055 +3003 +2957 +2911 +979 +1367 +1199 +1319 +2355 +2279 +2317 +3393 +3461 +3531 +3639 +3733 +3829 +887 +4300 +4330 +2136 +2120 +4332 +4334 +4336 +2118 +4338 +4340 +4342 +4344 +4381 +4437 +4449 +4461 +4473 +4485 +4497 +4512 +317 +4516 +4546 +4554 +4564 +4574 +2122 +4595 +2132 +4596 +4598 +4600 +2134 +4604 +4611 +4613 +4635 +4651 +4667 +4672 +4683 +45 +4699 +353 +4755 +4779 +4799 +4735 +4802 +4808 +4823 +4841 +5120 +5266 +5279 +5295 +5301 +5311 +5364 +383 +5367 +5399 +5411 +5423 +5435 +5447 +5459 +5477 +2178 +5487 +5492 +4209 +5499 +2505 +5503 +5517 +413 +5527 +5537 +5547 +5557 +5567 +5577 +5587 +5597 +5607 +5617 +5627 +5637 +5647 +5653 +5662 +385 +423 +81 +5671 +5677 +5683 +5689 +5693 +5697 +4895 +4933 +4983 +5021 +5065 +5103 +4846 +5161 +5175 +5201 +5215 +5235 +5249 +4861 +5131 +5141 +5717 +5735 +5755 +5773 +5785 +5795 +5805 +5813 +5821 +5827 +5833 +5843 +5851 +5859 +5865 +—1––•›Ÿ£Ú¡Üâ䫿ì + !·Uœ»¹ ©ËÑÄXÄʰÐÎØÎÚØÜÂâÞãìâîçü€ƒj礥َ‘r—0––• + ì˨/‘æ)2:7!-•2€M=! +X*©‹ÈÃ^Žj™©ñÔ¬²àëý6¸ðïïóûÃþý +ÄÌÃÐýŠþô  £à>üæ¤ žÃË8¾„ƒÓ9Æ‹,E%À‹Õí˜Ù rˆÄ½†è¿ÅÖ—æ÷æûæÿô + +ƒù')³Çˆ¸®‹û*ÖÇ[`bäc·ý·ÅR[c Yg\êøôü82 4þ€‹  !#229;ÃÄ¥ªVXWXVV¾ ¾ÉÌÍ$¹ÔËÚÛÖ†‡D‘Ãæ–ªéݲ£Ý·¼¾è¿’––šš•²™  ™3Î4  ßàÁÆ ‚ ‚„„ÔÕttþÿ ‰ÁÞŽ¨áÕª›Õ¯´¶ê·Ñר­Ö¬®¯¹Å޾¬‘…ÚË…ßäææç½øˆU¬6Ñâ”A”—B—í﫩ǵüËc®dÐЗdýÄÅ©#ÌÿÒÓ<²³8“‘óÍÀ÷ûò?¼B¼88€((Þß ÇÅ÷uìE<Dòó«©åüˆÿD мI¼¿J¿•—ÕÓý§¤UÖÈ\††Ï\­ìíáô¯úû<ÚÛ8½»­»è±éš?öBö88¨©((†‡ ñï¯e”E<Dš›ÕÓ +€ˆ©DìOšìŸñÔš¤ú¸ ¸ ‚@ƒ@ aÙd×¥ë¨éÕ +Ф:¥:éåìã­¯°­ñAô?÷ +þÆ4Ç4ðIñKþ3ÿ5ÔíÕï™ +¬Ñå§wmM- ø#ù%¢7£9°'±)†Ñ‡ÓË +À õ¥ø£Í÷Ðõ—»š¹Ë]Î[í +ä íÏðÍšȟå’ãÇƅ +ˆÝP‚ŒÞ Œ«”å몪ô?õAž}Ÿ¬a­c‚çƒéÇ +–9—;ÀqÁsÎQÏS¤Ù¥Ûé +ð¸3¹5âeãgðAñCÆùÇû‹  +žÁÿ ŸwmM- ¬Ò ”­×¬°,œÂ„ܼ&À$æ*„½ê,®À +ênõöÞß°®®ƒúï › +ߺÃÛÑ»çÉýü…§‹…« “‹ »ý¹ïÍ }£ óÑ¿‰ Í—   ¿ ¥” Ä — ° à Ñ ‹  ˆ ¼’ ” ð +ô +ö +Ô÷ +å £º ê Ž½ Ö † ÷ ± ³ ® º¸ º – š œ Ò ‹ §à ’ã ü ¬  × Ù Ô ¾Þ à ¼ À  Öà s¦M)¸ÊÆÄÂÆÌÒØ±Ì´¯ 䬫 6¯ßÙœ»œ Œð ðØ ‰Ä Á ŒÅ ëª âË ª ÒÅ Û ³ šéä Š¡Å5Ú œè¤ý ¤²¦Q¬   aw ¯Må7ç0ª¬Ä¨ó +Öö +Öñ â ô â “ Ä– ÄÚÆ Ö¢ „ è ¸œ”«ÄØ“zØÁˆUîùêåÔøÛØ× ‘,¢£•˜ Ÿ¢Îγ¶µ¸úûñô€€0’…øÐÖ}¨‹©n£ð¾Ú«ùºÙƒäÕ —‘‘éÿ•·Øâ™™¼ÒØÃÛÙ§‚ ðΊ¶ý¸ŽG¾lôéäôåï ΠЗší‡ï´Ú®âœàϯ Š…ø­ƒ‹ ³… »ß ãåßÍ…½¢½É’°•ÝͱŒçìîÞïëõéåÊå˺경…õÙ´µ¯ º–šœà™£‹“ø“Í蘴볣‡âãÞ +èÄÈÊâËÇщÁ¦Áϖƶ™áѵ‘‹Í‹Ž›œ +øüþäÿû…õÚõÑÊú¸Í•…éÄſ˿ÂÏÐ +¬°²æ³¯¹‡©Ž©Óþ®ºÉ¹øùóÉóöƒ„ +à俨çãíÝÂÝղ⼵ýíѬ­¨Ì©Ç©¹º –šœÚ™×â’¾å­àÜÝØÊÙÁÙéê ÆÊÌÜÍÉÇO‘øÊÙ½ïÒâæâG£ˆâêI ä ¼ ôþÿ # ñâ Š.-”“‘8;1“¡è˜Œë„´¥ßáÜÈÝ¿Ýíî ÊÎÐÐÑ–ÎrqŒÌÕÓ|uן¬ÜŠ¯Èøé£¥ Æ¡½¡±² Ž’”Εڒ¶µÐÈœ™—ÂÅ»ò¢ˆõ޾¯éëæÄç»ç÷ø ÔØÚÌÛ Øüû” ÊâÝÛˆ‹»õô–‹® Æøþ÷õ¤§ý›Ò‚†ÕñÚ— ¨ü +Ö×ÒÂÓÉÓãä ÀÄÆÊÇŒÄèçA™óÒôéŠ +ÈÖÜÓÑ‚…ûÛ™°à„³ûë϶õþ†Ú +´µ°À±Ç±Á ž¢¤È¥ê¢ÆÅA÷ñ°ÒÇè +ݶ¼±¯âåÛ»—À‚“Û˯”ÕÞæº +”•Ƒő¡¢ þ‚„Æ…Ê‚¦¥A×ï²§½ ËÀ ɺ½³ŸÌ¢ÆÅ ó„Þàã¹ ¯ ¾ ­Á ¯Æ ­É ¯!Î ­%¡¼ +Ñ ¯ ¦à©ñº¯ ß ìÅíÇœ•½ÀœÁ¢þ ßü· ÉÖ–©Žþ +Ó‰è ðì¥î ô´ ôø £‘ ù£á€ +œ ‡£¼¤Ž‹Åùõ –Ú²œÜïÔ )³ [®óÜ´ÕÖÁŸÇàÝà¦âäT‡<¾êÄÇ òòÉÏŽÆŠüžŠ ÏÝ̰²µ´·º³·ážá¬ ÕÏÌçç–.ÞÜ±Ì Ã¨     Ë Æ öÅ ½ Ì—æàÄ£À© Ò¾ šë® è EæÌ Q‡Ð®³ìÒ ëô Ð ëæà¸ùµsŠ“ Õ„ÉÏœ’ dß1Ó ¡!ëšæ¼º Ç‚!Ûê‹ °ñ"ñ¶˜½! Õ!À˜Í!ŠÐÜ æ à Ζž®ÌÞ!• öò ™â §æƒ‹ãƒ“ºêÖ¾  ¯ü8˜–ü¡ˆ ¯³õ Ž ÖÚñŽ Å!­!Í!Ë!¨ Œ "º!"$Š ').¼!.0ˆ 35:¾!:<† ?AFÀ!FH„ KMR¢!R˜å ‡“ª•Ì€#õ‚®â š°N€äÿ 軌®õ â Í«îæ‡#âÍõ¼­#ìí Þ·#ìš#öæ¸ã"Ê"é"è"À#òç Ð"ÅŽ¨â"Væ"Tž¶Ì!‰¥Ð!È‹ËÈ!Æ!Æ!Æ!î 4â!è"ã!ë"B¯"ä"Ì!ô!Ì!ø!Ç!Ê!Ú!„"Ú!ˆ"½Ñàæ!ùžÂýȤî!±ó!²§$ó!¦"Ф Ùùö!±Ý€"É$Ó$&°×ÌФööÀ$ ©×"›¿³“óÓ©ïÀ³í᫹ë)Â.‘£ŸÍÿ=ä‚’#Û" é˜# !Íì‡ò´žŽù#ü#³!€ ›ê °î£ß¶ì©å»‰¯ìÀ¾»ËýÇ“ÄÓ…Ï‘ËÜ Ü¼×ç™ã‘àï¡ëçø©ó•ïÿ²%'GIŽº‰™Ë•’¡Ó™ªÛ¥—¡±ä´¸¯¿ñ»¸ÇùË¿ÐË™Ç׊%'à¶Ûëç‹äó¥ï‰ëü­÷›óƒ¶†À‘Ã•Š™Ë•‡‘¢Ó™©Ü%'QS©«¼êŠ¿çÆè”Éå—  âúÕ‘çëÜ—ðøãŸõéê¥ !#Šöý¹ç„¿˜ô‹Çå’Í ¬òŸÛ±ã¦áºð­é¿á´ï !#IK–ܨ&Á µÚ$¬&Ö°&Ò‘•œ¿½ +¨Ò€‹Ê$ß™)åÀ&(ë&´é&˜(Ä&TÆ&á$… » › Ë)éþÍ„ Ó Ž +é +Ê•Â%Ü-ß$´ º ç%ýÞ(üÜÑÝ%Ë'†' º „' þ( ‚'%',€),&€'138‚)82þ&=?D„)D>ü&IKPæ(Pö$»×ú +Ê'÷'…ü ¶&Ô'dº%¦•설Æ&Ó)Ï&‘ê*í&á'¸ò&î&ø +‚ é'Ø(¢%å¢%¥%„¥%¬%ç¬%¯%‚¯%æÏµ%º%ûº% Ÿ¿%Ä%ýÄ%„„ˆ+Ä$Ç‹+Ú¸’+ˆ•+¾Þœ+ÂÝŸ+”’¦+‚§©+ÚÖ°+Àó³+žœº+þ¿½+¼ˆÄ+¼‹Ç+èæÎ+ôÝÑ+’ÆØ+¬¯Û+º!¨ +â+VÍÇ&½™)Œï)– € ù(‚݈¬ ÷(” õ(š Œó(ñ(ö¹Ó'Âþ“¦)€ ¼ ß(œ*Й'è(Â(³ Ú µ º» Û —á½ ý(€)Ê ¦«ßÑ ž,œ,œ,œ,œ,œ,ƒ++š,¨,¨,±,¯,˜,²,¹,·,(–,¼,Ç,Å,2”,É,Ç,Î, Ù,×,Ö, ×, · ï º í Ä Ä!†++‹+Î Â!“+‘+˜+Ÿ++ +¡+ i0 V32(0) +i1 V32(1) +i2 V32(2) +i3 V32(3) +i4 V56(0) +i5 V289(0) +i6 V10(0) +i7 V13(0) +i8 V35(0) +i9 V203(0) +i10 V288(6) +i11 V288(7) +i12 V248(0) +i13 V249(0) +i14 V62(0) +i15 V59(0) +i16 V174(0) +i17 V215(0) +i18 V66(0) +i19 V70(0) +i20 V43(0) +i21 V214(0) +i22 V37(0) +i23 V271(0) +i24 V40(0) +i25 V45(0) +i26 V149(7) +i27 V149(6) +i28 V149(5) +i29 V149(4) +i30 V1(0) +i31 V7(0) +i32 V34(0) +i33 V243(0) +i34 V244(0) +i35 V245(0) +i36 V246(0) +i37 V247(0) +i38 V293(0) +i39 V302(0) +i40 V270(0) +i41 V269(0) +i42 V274(0) +i43 V202(0) +i44 V275(0) +i45 V257(7) +i46 V257(5) +i47 V257(3) +i48 V257(1) +i49 V257(2) +i50 V257(4) +i51 V257(6) +i52 V9(0) +i53 V149(0) +i54 V149(1) +i55 V149(2) +i56 V149(3) +i57 V169(1) +i58 V165(0) +i59 V165(2) +i60 V165(4) +i61 V165(5) +i62 V165(6) +i63 V165(7) +i64 V165(1) +i65 V88(2) +i66 V88(3) +i67 V55(0) +i68 V169(0) +i69 V52(0) +i70 V5(0) +i71 V6(0) +i72 V12(0) +i73 V11(0) +i74 V4(0) +i75 V165(3) +i76 V51(0) +i77 V65(0) +i78 V290(0) +i79 V279(0) +i80 V280(0) +i81 V288(4) +i82 V288(2) +i83 V288(0) +i84 V258(0) +i85 V229(5) +i86 V229(4) +i87 V229(3) +i88 V229(2) +i89 V229(1) +i90 V229(0) +i91 V223(5) +i92 V223(4) +i93 V223(3) +i94 V223(2) +i95 V223(1) +i96 V223(0) +i97 V189(5) +i98 V189(4) +i99 V189(3) +i100 V189(2) +i101 V189(1) +i102 V189(0) +i103 V183(5) +i104 V183(4) +i105 V183(3) +i106 V183(2) +i107 V183(1) +i108 V183(0) +i109 V239(4) +i110 V239(3) +i111 V239(2) +i112 V239(1) +i113 V239(0) +i114 V234(4) +i115 V234(3) +i116 V234(2) +i117 V234(1) +i118 V234(0) +i119 V199(4) +i120 V199(3) +i121 V199(2) +i122 V199(1) +i123 V199(0) +i124 V194(4) +i125 V194(3) +i126 V194(2) +i127 V194(1) +i128 V194(0) +i129 V257(0) +i130 V32(8) +i131 V32(7) +i132 V32(6) +i133 V32(5) +i134 V32(4) +i135 V32(11) +i136 V32(10) +i137 V32(9) +i138 V88(1) +i139 V88(0) +i140 V84(5) +i141 V84(4) +i142 V84(3) +i143 V84(2) +i144 V84(1) +i145 V84(0) +i146 V78(5) +i147 V78(4) +i148 V2(0) +i149 V3(0) +i150 V14(0) +i151 V213(0) +i152 V213(5) +i153 V213(4) +i154 V213(3) +i155 V213(2) +i156 V213(1) +i157 V268(5) +i158 V268(3) +i159 V268(1) +i160 V268(2) +i161 V268(4) +i162 V8(0) +i163 V60(0) +i164 V53(0) +i165 V57(0) +i166 V109(0) +i167 V277(0) +i168 V278(0) +i169 V259(0) +i170 V260(0) +i171 V67(0) +i172 V68(0) +i173 V69(0) +i174 V216(0) +i175 V175(0) +i176 V177(0) +i177 V172(0) +i178 V171(0) +i179 V50(0) +i180 V63(0) +i181 V71(0) +i182 V292(0) +i183 V291(0) +i184 V91(0) +i185 V91(1) +i186 V294(0) +i187 V207(0) +i188 V295(0) +i189 V204(0) +i190 V205(0) +i191 V261(0) +i192 V262(0) +i193 V100(0) +i194 V100(5) +i195 V100(4) +i196 V100(3) +i197 V100(2) +i198 V100(1) +i199 V240(0) +i200 V242(0) +i201 V241(0) +i202 V33(0) +i203 V16(0) +i204 V15(0) +i205 V101(0) +i206 V268(0) +i207 V288(1) +i208 V288(3) +i209 V288(5) +i210 V301(0) +i211 V108(0) +i212 V108(1) +i213 V108(2) +i214 V108(3) +i215 V108(4) +i216 V108(5) +i217 V124(5) +i218 V124(4) +i219 V124(3) +i220 V124(2) +i221 V124(1) +i222 V124(0) +i223 V132(7) +i224 V132(6) +i225 V132(5) +i226 V132(4) +i227 V132(3) +i228 V132(2) +i229 V132(1) +i230 V132(0) +i231 V118(5) +i232 V118(4) +i233 V118(3) +i234 V118(2) +i235 V118(1) +i236 V118(0) +i237 V118(7) +i238 V118(6) +i239 V46(0) +i240 V48(0) +i241 V102(0) +i242 V110(0) +i243 V134(1) +i244 V134(0) +i245 V272(0) +i246 V78(2) +i247 V78(3) +i248 V39(0) +i249 V38(0) +i250 V42(0) +i251 V44(0) +i252 V41(0) +i253 V78(1) +i254 V78(0) +i255 V94(0) +i256 V94(1) +o0 V321(2) +o1 V356 +o2 V357 +o3 V373 +o4 V375(0) +o5 V377 +o6 V393(0) +o7 V398(0) +o8 V410(0) +o9 V423(0) +o10 V432 +o11 V435(0) +o12 V500(0) +o13 V508(0) +o14 V511(0) +o15 V512 +o16 V527 +o17 V537 +o18 V538 +o19 V539 +o20 V540 +o21 V541 +o22 V542 +o23 V543 +o24 V544 +o25 V545 +o26 V546 +o27 V547 +o28 V548 +o29 V572(9) +o30 V572(8) +o31 V572(7) +o32 V572(6) +o33 V572(5) +o34 V572(4) +o35 V572(3) +o36 V572(2) +o37 V572(1) +o38 V572(0) +o39 V585(0) +o40 V587 +o41 V591(0) +o42 V597(0) +o43 V603(0) +o44 V609(0) +o45 V620 +o46 V621 +o47 V630 +o48 V634(0) +o49 V640(0) +o50 V657 +o51 V707 +o52 V763 +o53 V775 +o54 V778 +o55 V779 +o56 V780 +o57 V781 +o58 V782 +o59 V783 +o60 V784 +o61 V787 +o62 V789 +o63 V798(0) +o64 V801 +o65 V802(0) +o66 V821(0) +o67 V826(0) +o68 V966 +o69 V986 +o70 V1213(11) +o71 V1213(10) +o72 V1213(9) +o73 V1213(8) +o74 V1213(7) +o75 V1213(6) +o76 V1213(5) +o77 V1213(4) +o78 V1213(3) +o79 V1213(2) +o80 V1213(1) +o81 V1213(0) +o82 V1243(9) +o83 V1243(8) +o84 V1243(7) +o85 V1243(6) +o86 V1243(5) +o87 V1243(4) +o88 V1243(3) +o89 V1243(2) +o90 V1243(1) +o91 V1243(0) +o92 V1256 +o93 V1257 +o94 V1258 +o95 V1259 +o96 V1260 +o97 V1261 +o98 V1262 +o99 V1263 +o100 V1264 +o101 V1265 +o102 V1266 +o103 V1267 +o104 V1274(0) +o105 V1281(0) +o106 V1297(4) +o107 V1297(3) +o108 V1297(2) +o109 V1297(1) +o110 V1297(0) +o111 V1365 +o112 V1375 +o113 V1378 +o114 V1380 +o115 V1382 +o116 V1384 +o117 V1386 +o118 V1387 +o119 V1392(0) +o120 V1423 +o121 V1426 +o122 V1428 +o123 V1429 +o124 V1431 +o125 V1432 +o126 V1439(0) +o127 V1440(0) +o128 V1451(0) +o129 V1459(0) +o130 V1467(0) +o131 V1470 +o132 V1480(0) +o133 V1481(0) +o134 V1492(0) +o135 V1495(0) +o136 V1512(3) +o137 V1512(2) +o138 V1512(1) +o139 V1536(0) +o140 V1537 +o141 V1539 +o142 V1552(1) +o143 V1552(0) +o144 V1613(0) +o145 V1613(1) +o146 V1620(0) +o147 V1629(0) +o148 V1645(0) +o149 V1652(0) +o150 V1669 +o151 V1671(0) +o152 V1679(0) +o153 V1693(0) +o154 V1709(4) +o155 V1709(3) +o156 V1709(2) +o157 V1709(1) +o158 V1709(0) +o159 V1717(0) +o160 V1719 +o161 V1726(0) +o162 V1736 +o163 V1741(0) +o164 V1745(0) +o165 V1757(0) +o166 V1758(0) +o167 V1759(0) +o168 V1760(0) +o169 V1771(1) +o170 V1771(0) +o171 V1781(1) +o172 V1781(0) +o173 V1829(9) +o174 V1829(8) +o175 V1829(7) +o176 V1829(6) +o177 V1829(5) +o178 V1829(4) +o179 V1829(3) +o180 V1829(2) +o181 V1829(1) +o182 V1829(0) +o183 V1832 +o184 V1833(0) +o185 V1863(0) +o186 V1864(0) +o187 V1896(0) +o188 V1897(0) +o189 V1898(0) +o190 V1899(0) +o191 V1900(0) +o192 V1901(0) +o193 V1921(5) +o194 V1921(4) +o195 V1921(3) +o196 V1921(2) +o197 V1921(1) +o198 V1921(0) +o199 V1953(1) +o200 V1953(7) +o201 V1953(6) +o202 V1953(5) +o203 V1953(4) +o204 V1953(3) +o205 V1953(2) +o206 V1953(0) +o207 V1960(1) +o208 V1960(0) +o209 V1968(0) +o210 V1992(1) +o211 V1992(0) +o212 V650 +o213 V651 +o214 V652 +o215 V653 +o216 V654 +o217 V655 +o218 V656 +o219 V1370 +o220 V1371 +o221 V1372 +o222 V1373 +o223 V1374 +c +i10 +This file was written by ABC on Sat Mar 12 12:08:09 2011 +For information about AIGER format, refer to http://fmv.jku.at/aiger diff --git a/yosys/abc/lib/pthread.h b/yosys/abc/lib/pthread.h new file mode 100644 index 00000000000..5039a5d72b3 --- /dev/null +++ b/yosys/abc/lib/pthread.h @@ -0,0 +1,1369 @@ +/* This is an implementation of the threads API of POSIX 1003.1-2001. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#if !defined( PTHREAD_H ) +#define PTHREAD_H + +/* + * See the README file for an explanation of the pthreads-win32 version + * numbering scheme and how the DLL is named etc. + */ +#define PTW32_VERSION 2,8,0,0 +#define PTW32_VERSION_STRING "2, 8, 0, 0\0" + +/* There are three implementations of cancel cleanup. + * Note that pthread.h is included in both application + * compilation units and also internally for the library. + * The code here and within the library aims to work + * for all reasonable combinations of environments. + * + * The three implementations are: + * + * WIN32 SEH + * C + * C++ + * + * Please note that exiting a push/pop block via + * "return", "exit", "break", or "continue" will + * lead to different behaviour amongst applications + * depending upon whether the library was built + * using SEH, C++, or C. For example, a library built + * with SEH will call the cleanup routine, while both + * C++ and C built versions will not. + */ + +/* + * Define defaults for cleanup code. + * Note: Unless the build explicitly defines one of the following, then + * we default to standard C style cleanup. This style uses setjmp/longjmp + * in the cancelation and thread exit implementations and therefore won't + * do stack unwinding if linked to applications that have it (e.g. + * C++ apps). This is currently consistent with most/all commercial Unix + * POSIX threads implementations. + */ +#if !defined( __CLEANUP_SEH ) && !defined( __CLEANUP_CXX ) && !defined( __CLEANUP_C ) +# define __CLEANUP_C +#endif + +#if defined( __CLEANUP_SEH ) && ( !defined( _MSC_VER ) && !defined(PTW32_RC_MSC)) +#error ERROR [__FILE__, line __LINE__]: SEH is not supported for this compiler. +#endif + +/* + * Stop here if we are being included by the resource compiler. + */ +#ifndef RC_INVOKED + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + +#ifdef _UWIN +# define HAVE_STRUCT_TIMESPEC 1 +# define HAVE_SIGNAL_H 1 +# undef HAVE_CONFIG_H +# pragma comment(lib, "pthread") +#endif + +/* + * ------------------------------------------------------------- + * + * + * Module: pthread.h + * + * Purpose: + * Provides an implementation of PThreads based upon the + * standard: + * + * POSIX 1003.1-2001 + * and + * The Single Unix Specification version 3 + * + * (these two are equivalent) + * + * in order to enhance code portability between Windows, + * various commercial Unix implementations, and Linux. + * + * See the ANNOUNCE file for a full list of conforming + * routines and defined constants, and a list of missing + * routines and constants not defined in this implementation. + * + * Authors: + * There have been many contributors to this library. + * The initial implementation was contributed by + * John Bossom, and several others have provided major + * sections or revisions of parts of the implementation. + * Often significant effort has been contributed to + * find and fix important bugs and other problems to + * improve the reliability of the library, which sometimes + * is not reflected in the amount of code which changed as + * result. + * As much as possible, the contributors are acknowledged + * in the ChangeLog file in the source code distribution + * where their changes are noted in detail. + * + * Contributors are listed in the CONTRIBUTORS file. + * + * As usual, all bouquets go to the contributors, and all + * brickbats go to the project maintainer. + * + * Maintainer: + * The code base for this project is coordinated and + * eventually pre-tested, packaged, and made available by + * + * Ross Johnson + * + * QA Testers: + * Ultimately, the library is tested in the real world by + * a host of competent and demanding scientists and + * engineers who report bugs and/or provide solutions + * which are then fixed or incorporated into subsequent + * versions of the library. Each time a bug is fixed, a + * test case is written to prove the fix and ensure + * that later changes to the code don't reintroduce the + * same error. The number of test cases is slowly growing + * and therefore so is the code reliability. + * + * Compliance: + * See the file ANNOUNCE for the list of implemented + * and not-implemented routines and defined options. + * Of course, these are all defined is this file as well. + * + * Web site: + * The source code and other information about this library + * are available from + * + * http://sources.redhat.com/pthreads-win32/ + * + * ------------------------------------------------------------- + */ + +/* Try to avoid including windows.h */ +#if defined(__MINGW32__) && defined(__cplusplus) +#define PTW32_INCLUDE_WINDOWS_H +#endif + +#ifdef PTW32_INCLUDE_WINDOWS_H +#include +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1300 || defined(__DMC__) +/* + * VC++6.0 or early compiler's header has no DWORD_PTR type. + */ +typedef unsigned long DWORD_PTR; +#endif +/* + * ----------------- + * autoconf switches + * ----------------- + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + +#ifndef NEED_FTIME +#include +#else /* NEED_FTIME */ +/* use native WIN32 time API */ +#endif /* NEED_FTIME */ + +#if HAVE_SIGNAL_H +#include +#endif /* HAVE_SIGNAL_H */ + +#include +#include + +/* + * Boolean values to make us independent of system includes. + */ +enum { + PTW32_FALSE = 0, + PTW32_TRUE = (! PTW32_FALSE) +}; + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Several systems don't define some error numbers. + */ +#ifndef ENOTSUP +# define ENOTSUP 48 /* This is the value in Solaris. */ +#endif + +#ifndef ETIMEDOUT +# define ETIMEDOUT 10060 /* This is the value in winsock.h. */ +#endif + +#ifndef ENOSYS +# define ENOSYS 140 /* Semi-arbitrary value */ +#endif + +#ifndef EDEADLK +# ifdef EDEADLOCK +# define EDEADLK EDEADLOCK +# else +# define EDEADLK 36 /* This is the value in MSVC. */ +# endif +#endif + +//#include -- changed by alanmi +#include "sched.h" + +/* + * To avoid including windows.h we define only those things that we + * actually need from it. + */ +#ifndef PTW32_INCLUDE_WINDOWS_H +#ifndef HANDLE +# define PTW32__HANDLE_DEF +# define HANDLE void * +#endif +#ifndef DWORD +# define PTW32__DWORD_DEF +# define DWORD unsigned long +#endif +#endif + +#ifndef HAVE_STRUCT_TIMESPEC +#define HAVE_STRUCT_TIMESPEC 1 +struct timespec { + long tv_sec; + long tv_nsec; +}; +#endif /* HAVE_STRUCT_TIMESPEC */ + +#ifndef SIG_BLOCK +#define SIG_BLOCK 0 +#endif /* SIG_BLOCK */ + +#ifndef SIG_UNBLOCK +#define SIG_UNBLOCK 1 +#endif /* SIG_UNBLOCK */ + +#ifndef SIG_SETMASK +#define SIG_SETMASK 2 +#endif /* SIG_SETMASK */ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * ------------------------------------------------------------- + * + * POSIX 1003.1-2001 Options + * ========================= + * + * Options are normally set in , which is not provided + * with pthreads-win32. + * + * For conformance with the Single Unix Specification (version 3), all of the + * options below are defined, and have a value of either -1 (not supported) + * or 200112L (supported). + * + * These options can neither be left undefined nor have a value of 0, because + * either indicates that sysconf(), which is not implemented, may be used at + * runtime to check the status of the option. + * + * _POSIX_THREADS (== 200112L) + * If == 200112L, you can use threads + * + * _POSIX_THREAD_ATTR_STACKSIZE (== 200112L) + * If == 200112L, you can control the size of a thread's + * stack + * pthread_attr_getstacksize + * pthread_attr_setstacksize + * + * _POSIX_THREAD_ATTR_STACKADDR (== -1) + * If == 200112L, you can allocate and control a thread's + * stack. If not supported, the following functions + * will return ENOSYS, indicating they are not + * supported: + * pthread_attr_getstackaddr + * pthread_attr_setstackaddr + * + * _POSIX_THREAD_PRIORITY_SCHEDULING (== -1) + * If == 200112L, you can use realtime scheduling. + * This option indicates that the behaviour of some + * implemented functions conforms to the additional TPS + * requirements in the standard. E.g. rwlocks favour + * writers over readers when threads have equal priority. + * + * _POSIX_THREAD_PRIO_INHERIT (== -1) + * If == 200112L, you can create priority inheritance + * mutexes. + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PRIO_PROTECT (== -1) + * If == 200112L, you can create priority ceiling mutexes + * Indicates the availability of: + * pthread_mutex_getprioceiling + * pthread_mutex_setprioceiling + * pthread_mutexattr_getprioceiling + * pthread_mutexattr_getprotocol + + * pthread_mutexattr_setprioceiling + * pthread_mutexattr_setprotocol + + * + * _POSIX_THREAD_PROCESS_SHARED (== -1) + * If set, you can create mutexes and condition + * variables that can be shared with another + * process.If set, indicates the availability + * of: + * pthread_mutexattr_getpshared + * pthread_mutexattr_setpshared + * pthread_condattr_getpshared + * pthread_condattr_setpshared + * + * _POSIX_THREAD_SAFE_FUNCTIONS (== 200112L) + * If == 200112L you can use the special *_r library + * functions that provide thread-safe behaviour + * + * _POSIX_READER_WRITER_LOCKS (== 200112L) + * If == 200112L, you can use read/write locks + * + * _POSIX_SPIN_LOCKS (== 200112L) + * If == 200112L, you can use spin locks + * + * _POSIX_BARRIERS (== 200112L) + * If == 200112L, you can use barriers + * + * + These functions provide both 'inherit' and/or + * 'protect' protocol, based upon these macro + * settings. + * + * ------------------------------------------------------------- + */ + +/* + * POSIX Options + */ +#undef _POSIX_THREADS +#define _POSIX_THREADS 200112L + +#undef _POSIX_READER_WRITER_LOCKS +#define _POSIX_READER_WRITER_LOCKS 200112L + +#undef _POSIX_SPIN_LOCKS +#define _POSIX_SPIN_LOCKS 200112L + +#undef _POSIX_BARRIERS +#define _POSIX_BARRIERS 200112L + +#undef _POSIX_THREAD_SAFE_FUNCTIONS +#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L + +#undef _POSIX_THREAD_ATTR_STACKSIZE +#define _POSIX_THREAD_ATTR_STACKSIZE 200112L + +/* + * The following options are not supported + */ +#undef _POSIX_THREAD_ATTR_STACKADDR +#define _POSIX_THREAD_ATTR_STACKADDR -1 + +#undef _POSIX_THREAD_PRIO_INHERIT +#define _POSIX_THREAD_PRIO_INHERIT -1 + +#undef _POSIX_THREAD_PRIO_PROTECT +#define _POSIX_THREAD_PRIO_PROTECT -1 + +/* TPS is not fully supported. */ +#undef _POSIX_THREAD_PRIORITY_SCHEDULING +#define _POSIX_THREAD_PRIORITY_SCHEDULING -1 + +#undef _POSIX_THREAD_PROCESS_SHARED +#define _POSIX_THREAD_PROCESS_SHARED -1 + + +/* + * POSIX 1003.1-2001 Limits + * =========================== + * + * These limits are normally set in , which is not provided with + * pthreads-win32. + * + * PTHREAD_DESTRUCTOR_ITERATIONS + * Maximum number of attempts to destroy + * a thread's thread-specific data on + * termination (must be at least 4) + * + * PTHREAD_KEYS_MAX + * Maximum number of thread-specific data keys + * available per process (must be at least 128) + * + * PTHREAD_STACK_MIN + * Minimum supported stack size for a thread + * + * PTHREAD_THREADS_MAX + * Maximum number of threads supported per + * process (must be at least 64). + * + * SEM_NSEMS_MAX + * The maximum number of semaphores a process can have. + * (must be at least 256) + * + * SEM_VALUE_MAX + * The maximum value a semaphore can have. + * (must be at least 32767) + * + */ +#undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 + +#undef PTHREAD_DESTRUCTOR_ITERATIONS +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +#undef _POSIX_THREAD_KEYS_MAX +#define _POSIX_THREAD_KEYS_MAX 128 + +#undef PTHREAD_KEYS_MAX +#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX + +#undef PTHREAD_STACK_MIN +#define PTHREAD_STACK_MIN 0 + +#undef _POSIX_THREAD_THREADS_MAX +#define _POSIX_THREAD_THREADS_MAX 64 + + /* Arbitrary value */ +#undef PTHREAD_THREADS_MAX +#define PTHREAD_THREADS_MAX 2019 + +#undef _POSIX_SEM_NSEMS_MAX +#define _POSIX_SEM_NSEMS_MAX 256 + + /* Arbitrary value */ +#undef SEM_NSEMS_MAX +#define SEM_NSEMS_MAX 1024 + +#undef _POSIX_SEM_VALUE_MAX +#define _POSIX_SEM_VALUE_MAX 32767 + +#undef SEM_VALUE_MAX +#define SEM_VALUE_MAX INT_MAX + + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * The Open Watcom C/C++ compiler uses a non-standard calling convention + * that passes function args in registers unless __cdecl is explicitly specified + * in exposed function prototypes. + * + * We force all calls to cdecl even though this could slow Watcom code down + * slightly. If you know that the Watcom compiler will be used to build both + * the DLL and application, then you can probably define this as a null string. + * Remember that pthread.h (this file) is used for both the DLL and application builds. + */ +#define PTW32_CDECL __cdecl + +#if defined(_UWIN) && PTW32_LEVEL >= PTW32_LEVEL_MAX +# include +#else +/* + * Generic handle type - intended to extend uniqueness beyond + * that available with a simple pointer. It should scale for either + * IA-32 or IA-64. + */ +typedef struct { + void * p; /* Pointer to actual object */ + unsigned int x; /* Extra information - reuse count etc */ +} ptw32_handle_t; + +typedef ptw32_handle_t pthread_t; +typedef struct pthread_attr_t_ * pthread_attr_t; +typedef struct pthread_once_t_ pthread_once_t; +typedef struct pthread_key_t_ * pthread_key_t; +typedef struct pthread_mutex_t_ * pthread_mutex_t; +typedef struct pthread_mutexattr_t_ * pthread_mutexattr_t; +typedef struct pthread_cond_t_ * pthread_cond_t; +typedef struct pthread_condattr_t_ * pthread_condattr_t; +#endif +typedef struct pthread_rwlock_t_ * pthread_rwlock_t; +typedef struct pthread_rwlockattr_t_ * pthread_rwlockattr_t; +typedef struct pthread_spinlock_t_ * pthread_spinlock_t; +typedef struct pthread_barrier_t_ * pthread_barrier_t; +typedef struct pthread_barrierattr_t_ * pthread_barrierattr_t; + +/* + * ==================== + * ==================== + * POSIX Threads + * ==================== + * ==================== + */ + +enum { +/* + * pthread_attr_{get,set}detachstate + */ + PTHREAD_CREATE_JOINABLE = 0, /* Default */ + PTHREAD_CREATE_DETACHED = 1, + +/* + * pthread_attr_{get,set}inheritsched + */ + PTHREAD_INHERIT_SCHED = 0, + PTHREAD_EXPLICIT_SCHED = 1, /* Default */ + +/* + * pthread_{get,set}scope + */ + PTHREAD_SCOPE_PROCESS = 0, + PTHREAD_SCOPE_SYSTEM = 1, /* Default */ + +/* + * pthread_setcancelstate paramters + */ + PTHREAD_CANCEL_ENABLE = 0, /* Default */ + PTHREAD_CANCEL_DISABLE = 1, + +/* + * pthread_setcanceltype parameters + */ + PTHREAD_CANCEL_ASYNCHRONOUS = 0, + PTHREAD_CANCEL_DEFERRED = 1, /* Default */ + +/* + * pthread_mutexattr_{get,set}pshared + * pthread_condattr_{get,set}pshared + */ + PTHREAD_PROCESS_PRIVATE = 0, + PTHREAD_PROCESS_SHARED = 1, + +/* + * pthread_barrier_wait + */ + PTHREAD_BARRIER_SERIAL_THREAD = -1 +}; + +/* + * ==================== + * ==================== + * Cancelation + * ==================== + * ==================== + */ +#define PTHREAD_CANCELED ((void *) -1) + + +/* + * ==================== + * ==================== + * Once Key + * ==================== + * ==================== + */ +#define PTHREAD_ONCE_INIT { PTW32_FALSE, 0, 0, 0} + +struct pthread_once_t_ +{ + int done; /* indicates if user function has been executed */ + void * lock; + int reserved1; + int reserved2; +}; + + +/* + * ==================== + * ==================== + * Object initialisers + * ==================== + * ==================== + */ +#define PTHREAD_MUTEX_INITIALIZER ((pthread_mutex_t) -1) +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER ((pthread_mutex_t) -2) +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER ((pthread_mutex_t) -3) + +/* + * Compatibility with LinuxThreads + */ +#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER +#define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP PTHREAD_ERRORCHECK_MUTEX_INITIALIZER + +#define PTHREAD_COND_INITIALIZER ((pthread_cond_t) -1) + +#define PTHREAD_RWLOCK_INITIALIZER ((pthread_rwlock_t) -1) + +#define PTHREAD_SPINLOCK_INITIALIZER ((pthread_spinlock_t) -1) + + +/* + * Mutex types. + */ +enum +{ + /* Compatibility with LinuxThreads */ + PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_TIMED_NP = PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_ADAPTIVE_NP = PTHREAD_MUTEX_FAST_NP, + /* For compatibility with POSIX */ + PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_FAST_NP, + PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL +}; + + +typedef struct ptw32_cleanup_t ptw32_cleanup_t; + +#if defined(_MSC_VER) +/* Disable MSVC 'anachronism used' warning */ +#pragma warning( disable : 4229 ) +#endif + +typedef void (* PTW32_CDECL ptw32_cleanup_callback_t)(void *); + +#if defined(_MSC_VER) +#pragma warning( default : 4229 ) +#endif + +struct ptw32_cleanup_t +{ + ptw32_cleanup_callback_t routine; + void *arg; + struct ptw32_cleanup_t *prev; +}; + +#ifdef __CLEANUP_SEH + /* + * WIN32 SEH version of cancel cleanup. + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + _cleanup.routine = (ptw32_cleanup_callback_t)(_rout); \ + _cleanup.arg = (_arg); \ + __try \ + { \ + +#define pthread_cleanup_pop( _execute ) \ + } \ + __finally \ + { \ + if( _execute || AbnormalTermination()) \ + { \ + (*(_cleanup.routine))( _cleanup.arg ); \ + } \ + } \ + } + +#else /* __CLEANUP_SEH */ + +#ifdef __CLEANUP_C + + /* + * C implementation of PThreads cancel cleanup + */ + +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + ptw32_cleanup_t _cleanup; \ + \ + ptw32_push_cleanup( &_cleanup, (ptw32_cleanup_callback_t) (_rout), (_arg) ); \ + +#define pthread_cleanup_pop( _execute ) \ + (void) ptw32_pop_cleanup( _execute ); \ + } + +#else /* __CLEANUP_C */ + +#ifdef __CLEANUP_CXX + + /* + * C++ version of cancel cleanup. + * - John E. Bossom. + */ + + class PThreadCleanup { + /* + * PThreadCleanup + * + * Purpose + * This class is a C++ helper class that is + * used to implement pthread_cleanup_push/ + * pthread_cleanup_pop. + * The destructor of this class automatically + * pops the pushed cleanup routine regardless + * of how the code exits the scope + * (i.e. such as by an exception) + */ + ptw32_cleanup_callback_t cleanUpRout; + void * obj; + int executeIt; + + public: + PThreadCleanup() : + cleanUpRout( 0 ), + obj( 0 ), + executeIt( 0 ) + /* + * No cleanup performed + */ + { + } + + PThreadCleanup( + ptw32_cleanup_callback_t routine, + void * arg ) : + cleanUpRout( routine ), + obj( arg ), + executeIt( 1 ) + /* + * Registers a cleanup routine for 'arg' + */ + { + } + + ~PThreadCleanup() + { + if ( executeIt && ((void *) cleanUpRout != (void *) 0) ) + { + (void) (*cleanUpRout)( obj ); + } + } + + void execute( int exec ) + { + executeIt = exec; + } + }; + + /* + * C++ implementation of PThreads cancel cleanup; + * This implementation takes advantage of a helper + * class who's destructor automatically calls the + * cleanup routine if we exit our scope weirdly + */ +#define pthread_cleanup_push( _rout, _arg ) \ + { \ + PThreadCleanup cleanup((ptw32_cleanup_callback_t)(_rout), \ + (void *) (_arg) ); + +#define pthread_cleanup_pop( _execute ) \ + cleanup.execute( _execute ); \ + } + +#else + +#error ERROR [__FILE__, line __LINE__]: Cleanup type undefined. + +#endif /* __CLEANUP_CXX */ + +#endif /* __CLEANUP_C */ + +#endif /* __CLEANUP_SEH */ + +/* + * =============== + * =============== + * Methods + * =============== + * =============== + */ + +/* + * PThread Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_attr_init (pthread_attr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_destroy (pthread_attr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getdetachstate (const pthread_attr_t * attr, + int *detachstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstackaddr (const pthread_attr_t * attr, + void **stackaddr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getstacksize (const pthread_attr_t * attr, + size_t * stacksize); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setdetachstate (pthread_attr_t * attr, + int detachstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstackaddr (pthread_attr_t * attr, + void *stackaddr); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setstacksize (pthread_attr_t * attr, + size_t stacksize); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedparam (const pthread_attr_t *attr, + struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedparam (pthread_attr_t *attr, + const struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setschedpolicy (pthread_attr_t *, + int); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getschedpolicy (pthread_attr_t *, + int *); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setinheritsched(pthread_attr_t * attr, + int inheritsched); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getinheritsched(pthread_attr_t * attr, + int * inheritsched); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_setscope (pthread_attr_t *, + int); + +PTW32_DLLPORT int PTW32_CDECL pthread_attr_getscope (const pthread_attr_t *, + int *); + +/* + * PThread Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_create (pthread_t * tid, + const pthread_attr_t * attr, + void *(*start) (void *), + void *arg); + +PTW32_DLLPORT int PTW32_CDECL pthread_detach (pthread_t tid); + +PTW32_DLLPORT int PTW32_CDECL pthread_equal (pthread_t t1, + pthread_t t2); + +PTW32_DLLPORT void PTW32_CDECL pthread_exit (void *value_ptr); + +PTW32_DLLPORT int PTW32_CDECL pthread_join (pthread_t thread, + void **value_ptr); + +PTW32_DLLPORT pthread_t PTW32_CDECL pthread_self (void); + +PTW32_DLLPORT int PTW32_CDECL pthread_cancel (pthread_t thread); + +PTW32_DLLPORT int PTW32_CDECL pthread_setcancelstate (int state, + int *oldstate); + +PTW32_DLLPORT int PTW32_CDECL pthread_setcanceltype (int type, + int *oldtype); + +PTW32_DLLPORT void PTW32_CDECL pthread_testcancel (void); + +PTW32_DLLPORT int PTW32_CDECL pthread_once (pthread_once_t * once_control, + void (*init_routine) (void)); + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +PTW32_DLLPORT ptw32_cleanup_t * PTW32_CDECL ptw32_pop_cleanup (int execute); + +PTW32_DLLPORT void PTW32_CDECL ptw32_push_cleanup (ptw32_cleanup_t * cleanup, + void (*routine) (void *), + void *arg); +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Thread Specific Data Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_key_create (pthread_key_t * key, + void (*destructor) (void *)); + +PTW32_DLLPORT int PTW32_CDECL pthread_key_delete (pthread_key_t key); + +PTW32_DLLPORT int PTW32_CDECL pthread_setspecific (pthread_key_t key, + const void *value); + +PTW32_DLLPORT void * PTW32_CDECL pthread_getspecific (pthread_key_t key); + + +/* + * Mutex Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_init (pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_destroy (pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getpshared (const pthread_mutexattr_t + * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setpshared (pthread_mutexattr_t * attr, + int pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_settype (pthread_mutexattr_t * attr, int kind); +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_gettype (pthread_mutexattr_t * attr, int *kind); + +/* + * Barrier Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_init (pthread_barrierattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_destroy (pthread_barrierattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_getpshared (const pthread_barrierattr_t + * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrierattr_setpshared (pthread_barrierattr_t * attr, + int pshared); + +/* + * Mutex Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_init (pthread_mutex_t * mutex, + const pthread_mutexattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_destroy (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_lock (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_timedlock(pthread_mutex_t *mutex, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_trylock (pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_mutex_unlock (pthread_mutex_t * mutex); + +/* + * Spinlock Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_spin_init (pthread_spinlock_t * lock, int pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_destroy (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_lock (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_trylock (pthread_spinlock_t * lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_spin_unlock (pthread_spinlock_t * lock); + +/* + * Barrier Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_init (pthread_barrier_t * barrier, + const pthread_barrierattr_t * attr, + unsigned int count); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_destroy (pthread_barrier_t * barrier); + +PTW32_DLLPORT int PTW32_CDECL pthread_barrier_wait (pthread_barrier_t * barrier); + +/* + * Condition Variable Attribute Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_init (pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_destroy (pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_getpshared (const pthread_condattr_t * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_condattr_setpshared (pthread_condattr_t * attr, + int pshared); + +/* + * Condition Variable Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_cond_init (pthread_cond_t * cond, + const pthread_condattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_destroy (pthread_cond_t * cond); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_wait (pthread_cond_t * cond, + pthread_mutex_t * mutex); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_timedwait (pthread_cond_t * cond, + pthread_mutex_t * mutex, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_signal (pthread_cond_t * cond); + +PTW32_DLLPORT int PTW32_CDECL pthread_cond_broadcast (pthread_cond_t * cond); + +/* + * Scheduling + */ +PTW32_DLLPORT int PTW32_CDECL pthread_setschedparam (pthread_t thread, + int policy, + const struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_getschedparam (pthread_t thread, + int *policy, + struct sched_param *param); + +PTW32_DLLPORT int PTW32_CDECL pthread_setconcurrency (int); + +PTW32_DLLPORT int PTW32_CDECL pthread_getconcurrency (void); + +/* + * Read-Write Lock Functions + */ +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_init(pthread_rwlock_t *lock, + const pthread_rwlockattr_t *attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_destroy(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_tryrdlock(pthread_rwlock_t *); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_trywrlock(pthread_rwlock_t *); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_rdlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedrdlock(pthread_rwlock_t *lock, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_wrlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_timedwrlock(pthread_rwlock_t *lock, + const struct timespec *abstime); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlock_unlock(pthread_rwlock_t *lock); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_init (pthread_rwlockattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_destroy (pthread_rwlockattr_t * attr); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * attr, + int *pshared); + +PTW32_DLLPORT int PTW32_CDECL pthread_rwlockattr_setpshared (pthread_rwlockattr_t * attr, + int pshared); + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 + +/* + * Signal Functions. Should be defined in but MSVC and MinGW32 + * already have signal.h that don't define these. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_kill(pthread_t thread, int sig); + +/* + * Non-portable functions + */ + +/* + * Compatibility with Linux. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_setkind_np(pthread_mutexattr_t * attr, + int kind); +PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * attr, + int *kind); + +/* + * Possibly supported by other POSIX threads implementations + */ +PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval); +PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void); + +/* + * Useful if an application wants to statically link + * the lib rather than load the DLL at run-time. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_attach_np(void); +PTW32_DLLPORT int PTW32_CDECL pthread_win32_thread_detach_np(void); + +/* + * Features that are auto-detected at load/run time. + */ +PTW32_DLLPORT int PTW32_CDECL pthread_win32_test_features_np(int); +enum ptw32_features { + PTW32_SYSTEM_INTERLOCKED_COMPARE_EXCHANGE = 0x0001, /* System provides it. */ + PTW32_ALERTABLE_ASYNC_CANCEL = 0x0002 /* Can cancel blocked threads. */ +}; + +/* + * Register a system time change with the library. + * Causes the library to perform various functions + * in response to the change. Should be called whenever + * the application's top level window receives a + * WM_TIMECHANGE message. It can be passed directly to + * pthread_create() as a new thread if desired. + */ +PTW32_DLLPORT void * PTW32_CDECL pthread_timechange_handler_np(void *); + +#endif /*PTW32_LEVEL >= PTW32_LEVEL_MAX - 1 */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX + +/* + * Returns the Win32 HANDLE for the POSIX thread. + */ +PTW32_DLLPORT HANDLE PTW32_CDECL pthread_getw32threadhandle_np(pthread_t thread); + + +/* + * Protected Methods + * + * This function blocks until the given WIN32 handle + * is signaled or pthread_cancel had been called. + * This function allows the caller to hook into the + * PThreads cancel mechanism. It is implemented using + * + * WaitForMultipleObjects + * + * on 'waitHandle' and a manually reset WIN32 Event + * used to implement pthread_cancel. The 'timeout' + * argument to TimedWait is simply passed to + * WaitForMultipleObjects. + */ +PTW32_DLLPORT int PTW32_CDECL pthreadCancelableWait (HANDLE waitHandle); +PTW32_DLLPORT int PTW32_CDECL pthreadCancelableTimedWait (HANDLE waitHandle, + DWORD timeout); + +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +/* + * Thread-Safe C Runtime Library Mappings. + */ +#ifndef _UWIN +# if defined(NEED_ERRNO) + PTW32_DLLPORT int * PTW32_CDECL _errno( void ); +# else +# ifndef errno +# if (defined(_MT) || defined(_DLL)) + __declspec(dllimport) extern int * __cdecl _errno(void); +# define errno (*_errno()) +# endif +# endif +# endif +#endif + +/* + * WIN32 C runtime library had been made thread-safe + * without affecting the user interface. Provide + * mappings from the UNIX thread-safe versions to + * the standard C runtime library calls. + * Only provide function mappings for functions that + * actually exist on WIN32. + */ + +#if !defined(__MINGW32__) +#define strtok_r( _s, _sep, _lasts ) \ + ( *(_lasts) = strtok( (_s), (_sep) ) ) +#endif /* !__MINGW32__ */ + +#define asctime_r( _tm, _buf ) \ + ( strcpy( (_buf), asctime( (_tm) ) ), \ + (_buf) ) + +#define ctime_r( _clock, _buf ) \ + ( strcpy( (_buf), ctime( (_clock) ) ), \ + (_buf) ) + +#define gmtime_r( _clock, _result ) \ + ( *(_result) = *gmtime( (_clock) ), \ + (_result) ) + +#define localtime_r( _clock, _result ) \ + ( *(_result) = *localtime( (_clock) ), \ + (_result) ) + +#define rand_r( _seed ) \ + ( _seed == _seed? rand() : rand() ) + + +/* + * Some compiler environments don't define some things. + */ +#if defined(__BORLANDC__) +# define _ftime ftime +# define _timeb timeb +#endif + +#ifdef __cplusplus + +/* + * Internal exceptions + */ +class ptw32_exception {}; +class ptw32_exception_cancel : public ptw32_exception {}; +class ptw32_exception_exit : public ptw32_exception {}; + +#endif + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX + +/* FIXME: This is only required if the library was built using SEH */ +/* + * Get internal SEH tag + */ +PTW32_DLLPORT DWORD PTW32_CDECL ptw32_get_exception_services_code(void); + +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#ifndef PTW32_BUILD + +#ifdef __CLEANUP_SEH + +/* + * Redefine the SEH __except keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#define __except( E ) \ + __except( ( GetExceptionCode() == ptw32_get_exception_services_code() ) \ + ? EXCEPTION_CONTINUE_SEARCH : ( E ) ) + +#endif /* __CLEANUP_SEH */ + +#ifdef __CLEANUP_CXX + +/* + * Redefine the C++ catch keyword to ensure that applications + * propagate our internal exceptions up to the library's internal handlers. + */ +#ifdef _MSC_VER + /* + * WARNING: Replace any 'catch( ... )' with 'PtW32CatchAll' + * if you want Pthread-Win32 cancelation and pthread_exit to work. + */ + +#ifndef PtW32NoCatchWarn + +#pragma message("Specify \"/DPtW32NoCatchWarn\" compiler flag to skip this message.") +#pragma message("------------------------------------------------------------------") +#pragma message("When compiling applications with MSVC++ and C++ exception handling:") +#pragma message(" Replace any 'catch( ... )' in routines called from POSIX threads") +#pragma message(" with 'PtW32CatchAll' or 'CATCHALL' if you want POSIX thread") +#pragma message(" cancelation and pthread_exit to work. For example:") +#pragma message("") +#pragma message(" #ifdef PtW32CatchAll") +#pragma message(" PtW32CatchAll") +#pragma message(" #else") +#pragma message(" catch(...)") +#pragma message(" #endif") +#pragma message(" {") +#pragma message(" /* Catchall block processing */") +#pragma message(" }") +#pragma message("------------------------------------------------------------------") + +#endif + +#define PtW32CatchAll \ + catch( ptw32_exception & ) { throw; } \ + catch( ... ) + +#else /* _MSC_VER */ + +#define catch( E ) \ + catch( ptw32_exception & ) { throw; } \ + catch( E ) + +#endif /* _MSC_VER */ + +#endif /* __CLEANUP_CXX */ + +#endif /* ! PTW32_BUILD */ + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#ifdef PTW32__HANDLE_DEF +# undef HANDLE +#endif +#ifdef PTW32__DWORD_DEF +# undef DWORD +#endif + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* ! RC_INVOKED */ + +#endif /* PTHREAD_H */ diff --git a/yosys/abc/lib/sched.h b/yosys/abc/lib/sched.h new file mode 100644 index 00000000000..dfb8e934af4 --- /dev/null +++ b/yosys/abc/lib/sched.h @@ -0,0 +1,178 @@ +/* + * Module: sched.h + * + * Purpose: + * Provides an implementation of POSIX realtime extensions + * as defined in + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#ifndef _SCHED_H +#define _SCHED_H + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#if defined(__MINGW32__) || defined(_UWIN) +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +/* For pid_t */ +# include +/* Required by Unix 98 */ +# include +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ +#else +typedef int pid_t; +#endif + +/* Thread scheduling policies */ + +enum { + SCHED_OTHER = 0, + SCHED_FIFO, + SCHED_RR, + SCHED_MIN = SCHED_OTHER, + SCHED_MAX = SCHED_RR +}; + +struct sched_param { + int sched_priority; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +PTW32_DLLPORT int __cdecl sched_yield (void); + +PTW32_DLLPORT int __cdecl sched_get_priority_min (int policy); + +PTW32_DLLPORT int __cdecl sched_get_priority_max (int policy); + +PTW32_DLLPORT int __cdecl sched_setscheduler (pid_t pid, int policy); + +PTW32_DLLPORT int __cdecl sched_getscheduler (pid_t pid); + +/* + * Note that this macro returns ENOTSUP rather than + * ENOSYS as might be expected. However, returning ENOSYS + * should mean that sched_get_priority_{min,max} are + * not implemented as well as sched_rr_get_interval. + * This is not the case, since we just don't support + * round-robin scheduling. Therefore I have chosen to + * return the same value as sched_setscheduler when + * SCHED_RR is passed to it. + */ +#define sched_rr_get_interval(_pid, _interval) \ + ( errno = ENOTSUP, (int) -1 ) + + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* !_SCHED_H */ + diff --git a/yosys/abc/lib/semaphore.h b/yosys/abc/lib/semaphore.h new file mode 100644 index 00000000000..bdcc2c7ea7d --- /dev/null +++ b/yosys/abc/lib/semaphore.h @@ -0,0 +1,166 @@ +/* + * Module: semaphore.h + * + * Purpose: + * Semaphores aren't actually part of the PThreads standard. + * They are defined by the POSIX Standard: + * + * POSIX 1003.1b-1993 (POSIX.1b) + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#if !defined( SEMAPHORE_H ) +#define SEMAPHORE_H + +#undef PTW32_LEVEL + +#if defined(_POSIX_SOURCE) +#define PTW32_LEVEL 0 +/* Early POSIX */ +#endif + +#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309 +#undef PTW32_LEVEL +#define PTW32_LEVEL 1 +/* Include 1b, 1c and 1d */ +#endif + +#if defined(INCLUDE_NP) +#undef PTW32_LEVEL +#define PTW32_LEVEL 2 +/* Include Non-Portable extensions */ +#endif + +#define PTW32_LEVEL_MAX 3 + +#if !defined(PTW32_LEVEL) +#define PTW32_LEVEL PTW32_LEVEL_MAX +/* Include everything */ +#endif + +#if __GNUC__ && ! defined (__declspec) +# error Please upgrade your GNU compiler to one that supports __declspec. +#endif + +/* + * When building the DLL code, you should define PTW32_BUILD so that + * the variables/functions are exported correctly. When using the DLL, + * do NOT define PTW32_BUILD, and then the variables/functions will + * be imported correctly. + */ +#ifndef PTW32_STATIC_LIB +# ifdef PTW32_BUILD +# define PTW32_DLLPORT __declspec (dllexport) +# else +# define PTW32_DLLPORT __declspec (dllimport) +# endif +#else +# define PTW32_DLLPORT +#endif + +/* + * This is a duplicate of what is in the autoconf config.h, + * which is only used when building the pthread-win32 libraries. + */ + +#ifndef PTW32_CONFIG_H +# if defined(WINCE) +# define NEED_ERRNO +# define NEED_SEM +# endif +# if defined(_UWIN) || defined(__MINGW32__) +# define HAVE_MODE_T +# endif +#endif + +/* + * + */ + +#if PTW32_LEVEL >= PTW32_LEVEL_MAX +#ifdef NEED_ERRNO +#include "need_errno.h" +#else +#include +#endif +#endif /* PTW32_LEVEL >= PTW32_LEVEL_MAX */ + +#define _POSIX_SEMAPHORES + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#ifndef HAVE_MODE_T +typedef unsigned int mode_t; +#endif + + +typedef struct sem_t_ * sem_t; + +PTW32_DLLPORT int __cdecl sem_init (sem_t * sem, + int pshared, + unsigned int value); + +PTW32_DLLPORT int __cdecl sem_destroy (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_trywait (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_wait (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_timedwait (sem_t * sem, + const struct timespec * abstime); + +PTW32_DLLPORT int __cdecl sem_post (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_post_multiple (sem_t * sem, + int count); + +PTW32_DLLPORT int __cdecl sem_open (const char * name, + int oflag, + mode_t mode, + unsigned int value); + +PTW32_DLLPORT int __cdecl sem_close (sem_t * sem); + +PTW32_DLLPORT int __cdecl sem_unlink (const char * name); + +PTW32_DLLPORT int __cdecl sem_getvalue (sem_t * sem, + int * sval); + +#ifdef __cplusplus +} /* End of extern "C" */ +#endif /* __cplusplus */ + +#undef PTW32_LEVEL +#undef PTW32_LEVEL_MAX + +#endif /* !SEMAPHORE_H */ diff --git a/yosys/abc/lib/x64/pthreadVC2.dll b/yosys/abc/lib/x64/pthreadVC2.dll new file mode 100644 index 00000000000..165b4d26ec4 Binary files /dev/null and b/yosys/abc/lib/x64/pthreadVC2.dll differ diff --git a/yosys/abc/lib/x64/pthreadVC2.lib b/yosys/abc/lib/x64/pthreadVC2.lib new file mode 100644 index 00000000000..1b07e0e9aa4 Binary files /dev/null and b/yosys/abc/lib/x64/pthreadVC2.lib differ diff --git a/yosys/abc/lib/x86/pthreadVC2.dll b/yosys/abc/lib/x86/pthreadVC2.dll new file mode 100644 index 00000000000..93f562baa91 Binary files /dev/null and b/yosys/abc/lib/x86/pthreadVC2.dll differ diff --git a/yosys/abc/lib/x86/pthreadVC2.lib b/yosys/abc/lib/x86/pthreadVC2.lib new file mode 100644 index 00000000000..58733254175 Binary files /dev/null and b/yosys/abc/lib/x86/pthreadVC2.lib differ diff --git a/yosys/abc/readmeaig b/yosys/abc/readmeaig new file mode 100644 index 00000000000..7615b8fcc70 --- /dev/null +++ b/yosys/abc/readmeaig @@ -0,0 +1,71 @@ +Using AIG Package in ABC + +- Download the latest snapshot of ABC +- Compile the code found in "abc\src\aig\aig", "abc\src\aig\saig", and "abc\src\misc\vec" as a static library. +- Link the library to the project. +- Add #include "saig.h". +- Start the AIG package using Aig_ManStart(). +- Assign primary inputs using Aig_ObjCreateCi(). +- Assign register outputs using Aig_ObjCreateCi(). +(it is important to create all PIs first, before creating register outputs). +- Construct AIG in the topological order using Aig_And(), Aig_Or(), Aig_Not(), etc. +- If constant-0/1 AIG nodes are needed, use Aig_ManConst0() or Aig_ManConst1() +- Create primary outputs using Aig_ObjCreateCo(). +- Create register inputs using Aig_ObjCreateCo(). +(it is important to create all POs first, before creating register inputs). +- Set the number of registers by calling Aig_ManSetRegNum(). +- Remove dangling AIG nodes (produced by structural hashing) using Aig_ManCleanup(). +- Call the consistency checking procedure Aig_ManCheck(). +- Dump AIG into a file using the new BLIF dumper Saig_ManDumpBlif(). +- For each object in the design annotated with the constructed AIG node (pNode), remember its AIG node ID by calling Aig_ObjId( Aig_Regular(pNode) ). To check whether the corresponding AIG node is complemented use Aig_IsComplement(pNode). +- Quit the AIG package using Aig_ManStop(). +The above process should not produce memory leaks. + + + +Using GIA Package in ABC + +- Add #include "gia.h". +- Start the AIG package using Gia_ManStart( int nObjMax ). +(Parameter 'nNodeMax' should approximately reflect the expected number of objects, including PIs, POs, flop inputs, and flop outputs. If the number of objects is more, memory will be automatically reallocated.) +- If structural hashing is to be used, start hash table by calling Gia_ManHashStart(). +- Similarly, whenever structural hashingn is no longer needed, deallocate hash table by calling Gia_ManHashStop(). +- Assign primary inputs using Gia_ManAppendCi(). +- Assign flop outputs using Gia_ManAppendCi(). +(It is important to create all PIs first, before creating flop outputs). +(Flop control logic, if present, should be elaborated into AND gates. For example, to represent a flop enable, create the driver of enable signal, which can be a PI or an internal node, and then add logic for = MUX( , , ). The output of this logic feeds into the flop. +- Construct AIG in the topological order using Gia_ManHashAnd(), Gia_ManHashOr(), Gia_Not(), etc. +- If constant-0/1 AIG nodes are needed, use Gia_ManConst0() or Gia_ManConst1() +- Create primary outputs using Gia_ManAppendCo(). +- Create flop inputs using Gia_ManAppendCo(). +(it is important to create all POs first, before creating register inputs). +- Set the number of flops by calling Gia_ManSetRegNum(). +- Remove dangling AIG nodes (produced by structural hashing) by running Gia_ManCleanup(), which will return a new AIG. If object mapping is defined for the original AIG, it should be remapped into the new AIG. +- Dump AIG into an AIGER file use Gia_DumpAiger(). +- For each object in the design annotated with the constructed AIG node (pNode), remember its AIG node ID by calling Gia_ObjId(pMan,pNode). +- Quit the AIG package using Gia_ManStop(). +The above process should not produce memory leaks. + + + + +Using MiniAIG Package + +- Add #include "miniaig.h". +- Start the AIG package using Mini_AigStart(). +- Assign primary inputs using Mini_AigCreatePi(). +- Assign flop outputs using Mini_AigCreatePi(). +(It is important to create all PIs first, before creating flop outputs.) +(Flop control logic, if present, should be elaborated into AND gates. For example, to represent a flop enable, create the driver of enable signal, which can be a PI or an internal node, and then add logic for = MUX( , , ). The output of this logic feeds into the flop. +- Construct AIG in a topological order using Mini_AigAnd(), Mini_AigOr(), etc. +- If constant-0 or constant-1 functions are needed, use 0 or 1. +- Create primary outputs using Mini_AigCreatePo(). +- Create flop inputs using Mini_AigCreatePo(). +(It is important to create all POs first, before creating register inputs.) +- Set the number of flops by calling Mini_AigSetRegNum(). +- The AIG may contain internal nodes without fanout and/or internal nodes fed by constants. +- Dump AIG in internal MiniAIG binary format using Mini_AigDump() and read it into ABC using "&read -m file.mini" +- Dump AIG in standard AIGER format (https://fmv.jku.at/aiger/index.html) using Mini_AigerWrite() and read it into ABC using "&read file.aig" +- For each object in the design represented using MiniAIG, it may be helpful to save the MiniAIG literal returned by Mini_AigAnd(), Mini_AigOr(), etc when constructing that object. +- Quit the AIG package using Mini_AigStop(). +The above process should not produce memory leaks. diff --git a/yosys/abc/src/aig/aig/aig.h b/yosys/abc/src/aig/aig/aig.h new file mode 100644 index 00000000000..5285ae72bbd --- /dev/null +++ b/yosys/abc/src/aig/aig/aig.h @@ -0,0 +1,713 @@ +/**CFile**************************************************************** + + FileName [aig.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aig.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__aig__aig_h +#define ABC__aig__aig__aig_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#include "misc/vec/vec.h" +#include "misc/util/utilCex.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Aig_Man_t_ Aig_Man_t; +typedef struct Aig_Obj_t_ Aig_Obj_t; +typedef struct Aig_MmFixed_t_ Aig_MmFixed_t; +typedef struct Aig_MmFlex_t_ Aig_MmFlex_t; +typedef struct Aig_MmStep_t_ Aig_MmStep_t; + +// object types +typedef enum { + AIG_OBJ_NONE, // 0: non-existent object + AIG_OBJ_CONST1, // 1: constant 1 + AIG_OBJ_CI, // 2: combinational input + AIG_OBJ_CO, // 3: combinational output + AIG_OBJ_BUF, // 4: buffer node + AIG_OBJ_AND, // 5: AND node + AIG_OBJ_EXOR, // 6: EXOR node + AIG_OBJ_VOID // 7: unused object +} Aig_Type_t; + +// the AIG node +struct Aig_Obj_t_ // 8 words +{ + union { + Aig_Obj_t * pNext; // strashing table + int CioId; // 0-based number of CI/CO + }; + Aig_Obj_t * pFanin0; // fanin + Aig_Obj_t * pFanin1; // fanin + unsigned int Type : 3; // object type + unsigned int fPhase : 1; // value under 000...0 pattern + unsigned int fMarkA : 1; // multipurpose mask + unsigned int fMarkB : 1; // multipurpose mask + unsigned int nRefs : 26; // reference count + unsigned Level : 24; // the level of this node + unsigned nCuts : 8; // the number of cuts + int TravId; // unique ID of last traversal involving the node + int Id; // unique ID of the node + union { // temporary store for user's data + void * pData; + int iData; + float dData; + }; +}; + +// the AIG manager +struct Aig_Man_t_ +{ + char * pName; // the design name + char * pSpec; // the input file name + // AIG nodes + Vec_Ptr_t * vCis; // the array of PIs + Vec_Ptr_t * vCos; // the array of POs + Vec_Ptr_t * vObjs; // the array of all nodes (optional) + Vec_Ptr_t * vBufs; // the array of buffers + Aig_Obj_t * pConst1; // the constant 1 node + Aig_Obj_t Ghost; // the ghost node + int nRegs; // the number of registers (registers are last POs) + int nTruePis; // the number of true primary inputs + int nTruePos; // the number of true primary outputs + int nAsserts; // the number of asserts among POs (asserts are first POs) + int nConstrs; // the number of constraints (model checking only) + int nBarBufs; // the number of barrier buffers + // AIG node counters + int nObjs[AIG_OBJ_VOID];// the number of objects by type + int nDeleted; // the number of deleted objects + // structural hash table + Aig_Obj_t ** pTable; // structural hash table + int nTableSize; // structural hash table size + // representation of fanouts + int * pFanData; // the database to store fanout information + int nFansAlloc; // the size of fanout representation + Vec_Vec_t * vLevels; // used to update timing information + int nBufReplaces; // the number of times replacement led to a buffer + int nBufFixes; // the number of times buffers were propagated + int nBufMax; // the maximum number of buffers during computation + // topological order + unsigned * pOrderData; + int nOrderAlloc; + int iPrev; + int iNext; + int nAndTotal; + int nAndPrev; + // representatives + Aig_Obj_t ** pEquivs; // linked list of equivalent nodes (when choices are used) + Aig_Obj_t ** pReprs; // representatives of each node + int nReprsAlloc; // the number of allocated representatives + // various data members + Aig_MmFixed_t * pMemObjs; // memory manager for objects + Vec_Int_t * vLevelR; // the reverse level of the nodes + int nLevelMax; // maximum number of levels + void * pData; // the temporary data + void * pData2; // the temporary data + int nTravIds; // the current traversal ID + int fCatchExor; // enables EXOR nodes + int fAddStrash; // performs additional strashing + Aig_Obj_t ** pObjCopies; // mapping of AIG nodes into FRAIG nodes + void (*pImpFunc) (void*, void*); // implication checking precedure + void * pImpData; // implication checking data + void * pManTime; // the timing manager + void * pManCuts; + int * pFastSim; + unsigned * pTerSimData; // ternary simulation data + Vec_Ptr_t * vMapped; + Vec_Int_t * vFlopNums; + Vec_Int_t * vFlopReprs; + Abc_Cex_t * pSeqModel; + Vec_Ptr_t * vSeqModelVec; // vector of counter-examples (for sequential miters) + Aig_Man_t * pManExdc; + Vec_Ptr_t * vOnehots; + int fCreatePios; + Vec_Int_t * vEquPairs; + Vec_Vec_t * vClockDoms; + Vec_Int_t * vProbs; // probability of node being 1 + Vec_Int_t * vCiNumsOrig; // original CI names + int nComplEdges; // complemented edges + abctime Time2Quit; + // timing statistics + abctime time1; + abctime time2; + //-- jlong -- begin + Vec_Ptr_t * unfold2_type_I; + Vec_Ptr_t * unfold2_type_II; + //-- jlong -- end +}; + +// cut computation +typedef struct Aig_ManCut_t_ Aig_ManCut_t; +typedef struct Aig_Cut_t_ Aig_Cut_t; + +// the cut used to represent node in the AIG +struct Aig_Cut_t_ +{ + Aig_Cut_t * pNext; // the next cut in the table + int Cost; // the cost of the cut + unsigned uSign; // cut signature + int iNode; // the node, for which it is the cut + short nCutSize; // the number of bytes in the cut + char nLeafMax; // the maximum number of fanins + char nFanins; // the current number of fanins + int pFanins[0]; // the fanins (followed by the truth table) +}; + +// the CNF computation manager +struct Aig_ManCut_t_ +{ + // AIG manager + Aig_Man_t * pAig; // the input AIG manager + Aig_Cut_t ** pCuts; // the cuts for each node in the output manager + // parameters + int nCutsMax; // the max number of cuts at the node + int nLeafMax; // the max number of leaves of a cut + int fTruth; // enables truth table computation + int fVerbose; // enables verbose output + // internal variables + int nCutSize; // the number of bytes needed to store one cut + int nTruthWords; // the number of truth table words + Aig_MmFixed_t * pMemCuts; // memory manager for cuts + unsigned * puTemp[4]; // used for the truth table computation +}; + +static inline Aig_Cut_t * Aig_ObjCuts( Aig_ManCut_t * p, Aig_Obj_t * pObj ) { return p->pCuts[pObj->Id]; } +static inline void Aig_ObjSetCuts( Aig_ManCut_t * p, Aig_Obj_t * pObj, Aig_Cut_t * pCuts ) { p->pCuts[pObj->Id] = pCuts; } + +static inline int Aig_CutLeaveNum( Aig_Cut_t * pCut ) { return pCut->nFanins; } +static inline int * Aig_CutLeaves( Aig_Cut_t * pCut ) { return pCut->pFanins; } +static inline unsigned * Aig_CutTruth( Aig_Cut_t * pCut ) { return (unsigned *)(pCut->pFanins + pCut->nLeafMax); } +static inline Aig_Cut_t * Aig_CutNext( Aig_Cut_t * pCut ) { return (Aig_Cut_t *)(((char *)pCut) + pCut->nCutSize); } + +// iterator over cuts of the node +#define Aig_ObjForEachCut( p, pObj, pCut, i ) \ + for ( i = 0, pCut = Aig_ObjCuts(p, pObj); i < p->nCutsMax; i++, pCut = Aig_CutNext(pCut) ) +// iterator over leaves of the cut +#define Aig_CutForEachLeaf( p, pCut, pLeaf, i ) \ + for ( i = 0; (i < (int)(pCut)->nFanins) && ((pLeaf) = Aig_ManObj(p, (pCut)->pFanins[i])); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline unsigned Aig_ObjCutSign( unsigned ObjId ) { return (1U << (ObjId & 31)); } +static inline int Aig_WordCountOnes( unsigned uWord ) +{ + uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555); + uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333); + uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F); + uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF); + return (uWord & 0x0000FFFF) + (uWord>>16); +} +static inline int Aig_WordFindFirstBit( unsigned uWord ) +{ + int i; + for ( i = 0; i < 32; i++ ) + if ( uWord & (1 << i) ) + return i; + return -1; +} + +static inline Aig_Obj_t * Aig_Regular( Aig_Obj_t * p ) { return (Aig_Obj_t *)((ABC_PTRUINT_T)(p) & ~01); } +static inline Aig_Obj_t * Aig_Not( Aig_Obj_t * p ) { return (Aig_Obj_t *)((ABC_PTRUINT_T)(p) ^ 01); } +static inline Aig_Obj_t * Aig_NotCond( Aig_Obj_t * p, int c ) { return (Aig_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c)); } +static inline int Aig_IsComplement( Aig_Obj_t * p ) { return (int)((ABC_PTRUINT_T)(p) & 01); } + +static inline int Aig_ManCiNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_CI]; } +static inline int Aig_ManCoNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_CO]; } +static inline int Aig_ManBufNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_BUF]; } +static inline int Aig_ManAndNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_AND]; } +static inline int Aig_ManExorNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_EXOR]; } +static inline int Aig_ManNodeNum( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_AND]+p->nObjs[AIG_OBJ_EXOR]; } +static inline int Aig_ManGetCost( Aig_Man_t * p ) { return p->nObjs[AIG_OBJ_AND]+3*p->nObjs[AIG_OBJ_EXOR]; } +static inline int Aig_ManObjNum( Aig_Man_t * p ) { return Vec_PtrSize(p->vObjs) - p->nDeleted; } +static inline int Aig_ManObjNumMax( Aig_Man_t * p ) { return Vec_PtrSize(p->vObjs); } +static inline int Aig_ManRegNum( Aig_Man_t * p ) { return p->nRegs; } +static inline int Aig_ManConstrNum( Aig_Man_t * p ) { return p->nConstrs; } + +static inline Aig_Obj_t * Aig_ManConst0( Aig_Man_t * p ) { return Aig_Not(p->pConst1); } +static inline Aig_Obj_t * Aig_ManConst1( Aig_Man_t * p ) { return p->pConst1; } +static inline Aig_Obj_t * Aig_ManGhost( Aig_Man_t * p ) { return &p->Ghost; } +static inline Aig_Obj_t * Aig_ManCi( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vCis, i); } +static inline Aig_Obj_t * Aig_ManCo( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vCos, i); } +static inline Aig_Obj_t * Aig_ManLo( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vCis, Aig_ManCiNum(p)-Aig_ManRegNum(p)+i); } +static inline Aig_Obj_t * Aig_ManLi( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vCos, Aig_ManCoNum(p)-Aig_ManRegNum(p)+i); } +static inline Aig_Obj_t * Aig_ManObj( Aig_Man_t * p, int i ) { return p->vObjs ? (Aig_Obj_t *)Vec_PtrEntry(p->vObjs, i) : NULL; } + +static inline Aig_Type_t Aig_ObjType( Aig_Obj_t * pObj ) { return (Aig_Type_t)pObj->Type; } +static inline int Aig_ObjIsNone( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_NONE; } +static inline int Aig_ObjIsConst1( Aig_Obj_t * pObj ) { assert(!Aig_IsComplement(pObj)); return pObj->Type == AIG_OBJ_CONST1; } +static inline int Aig_ObjIsCi( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_CI; } +static inline int Aig_ObjIsCo( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_CO; } +static inline int Aig_ObjIsBuf( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_BUF; } +static inline int Aig_ObjIsAnd( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_AND; } +static inline int Aig_ObjIsExor( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_EXOR; } +static inline int Aig_ObjIsNode( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_AND || pObj->Type == AIG_OBJ_EXOR; } +static inline int Aig_ObjIsTerm( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_CI || pObj->Type == AIG_OBJ_CO || pObj->Type == AIG_OBJ_CONST1; } +static inline int Aig_ObjIsHash( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_AND || pObj->Type == AIG_OBJ_EXOR; } +static inline int Aig_ObjIsChoice( Aig_Man_t * p, Aig_Obj_t * pObj ) { return p->pEquivs && p->pEquivs[pObj->Id] && pObj->nRefs > 0; } +static inline int Aig_ObjIsCand( Aig_Obj_t * pObj ) { return pObj->Type == AIG_OBJ_CI || pObj->Type == AIG_OBJ_AND || pObj->Type == AIG_OBJ_EXOR; } +static inline int Aig_ObjCioId( Aig_Obj_t * pObj ) { assert( !Aig_ObjIsNode(pObj) ); return pObj->CioId; } +static inline int Aig_ObjId( Aig_Obj_t * pObj ) { return pObj->Id; } + +static inline int Aig_ObjIsMarkA( Aig_Obj_t * pObj ) { return pObj->fMarkA; } +static inline void Aig_ObjSetMarkA( Aig_Obj_t * pObj ) { pObj->fMarkA = 1; } +static inline void Aig_ObjClearMarkA( Aig_Obj_t * pObj ) { pObj->fMarkA = 0; } + +static inline void Aig_ObjSetTravId( Aig_Obj_t * pObj, int TravId ) { pObj->TravId = TravId; } +static inline void Aig_ObjSetTravIdCurrent( Aig_Man_t * p, Aig_Obj_t * pObj ) { pObj->TravId = p->nTravIds; } +static inline void Aig_ObjSetTravIdPrevious( Aig_Man_t * p, Aig_Obj_t * pObj ) { pObj->TravId = p->nTravIds - 1; } +static inline int Aig_ObjIsTravIdCurrent( Aig_Man_t * p, Aig_Obj_t * pObj ) { return (int)(pObj->TravId == p->nTravIds); } +static inline int Aig_ObjIsTravIdPrevious( Aig_Man_t * p, Aig_Obj_t * pObj ) { return (int)(pObj->TravId == p->nTravIds - 1); } + +static inline int Aig_ObjPhase( Aig_Obj_t * pObj ) { return pObj->fPhase; } +static inline int Aig_ObjPhaseReal( Aig_Obj_t * pObj ) { return pObj? Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) : 1; } +static inline int Aig_ObjRefs( Aig_Obj_t * pObj ) { return pObj->nRefs; } +static inline void Aig_ObjRef( Aig_Obj_t * pObj ) { pObj->nRefs++; } +static inline void Aig_ObjDeref( Aig_Obj_t * pObj ) { assert( pObj->nRefs > 0 ); pObj->nRefs--; } +static inline void Aig_ObjClearRef( Aig_Obj_t * pObj ) { pObj->nRefs = 0; } +static inline int Aig_ObjFaninId0( Aig_Obj_t * pObj ) { return pObj->pFanin0? Aig_Regular(pObj->pFanin0)->Id : -1; } +static inline int Aig_ObjFaninId1( Aig_Obj_t * pObj ) { return pObj->pFanin1? Aig_Regular(pObj->pFanin1)->Id : -1; } +static inline int Aig_ObjFaninC0( Aig_Obj_t * pObj ) { return Aig_IsComplement(pObj->pFanin0); } +static inline int Aig_ObjFaninC1( Aig_Obj_t * pObj ) { return Aig_IsComplement(pObj->pFanin1); } +static inline Aig_Obj_t * Aig_ObjFanin0( Aig_Obj_t * pObj ) { return Aig_Regular(pObj->pFanin0); } +static inline Aig_Obj_t * Aig_ObjFanin1( Aig_Obj_t * pObj ) { return Aig_Regular(pObj->pFanin1); } +static inline Aig_Obj_t * Aig_ObjChild0( Aig_Obj_t * pObj ) { return pObj->pFanin0; } +static inline Aig_Obj_t * Aig_ObjChild1( Aig_Obj_t * pObj ) { return pObj->pFanin1; } +static inline Aig_Obj_t * Aig_ObjChild0Copy( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj)) : NULL; } +static inline Aig_Obj_t * Aig_ObjChild1Copy( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj)) : NULL; } +static inline Aig_Obj_t * Aig_ObjChild0Next( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin0(pObj)? Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj)->pNext, Aig_ObjFaninC0(pObj)) : NULL; } +static inline Aig_Obj_t * Aig_ObjChild1Next( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin1(pObj)->pNext, Aig_ObjFaninC1(pObj)) : NULL; } +static inline void Aig_ObjChild0Flip( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); pObj->pFanin0 = Aig_Not(pObj->pFanin0); } +static inline void Aig_ObjChild1Flip( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); pObj->pFanin1 = Aig_Not(pObj->pFanin1); } +static inline Aig_Obj_t * Aig_ObjCopy( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return (Aig_Obj_t *)pObj->pData; } +static inline void Aig_ObjSetCopy( Aig_Obj_t * pObj, Aig_Obj_t * pCopy ) { assert( !Aig_IsComplement(pObj) ); pObj->pData = pCopy; } +static inline Aig_Obj_t * Aig_ObjRealCopy( Aig_Obj_t * pObj ) { return Aig_NotCond((Aig_Obj_t *)Aig_Regular(pObj)->pData, Aig_IsComplement(pObj));} +static inline int Aig_ObjToLit( Aig_Obj_t * pObj ) { return Abc_Var2Lit( Aig_ObjId(Aig_Regular(pObj)), Aig_IsComplement(pObj) ); } +static inline Aig_Obj_t * Aig_ObjFromLit( Aig_Man_t * p,int iLit){ return Aig_NotCond( Aig_ManObj(p, Abc_Lit2Var(iLit)), Abc_LitIsCompl(iLit) ); } +static inline int Aig_ObjLevel( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return pObj->Level; } +static inline int Aig_ObjLevelNew( Aig_Obj_t * pObj ) { assert( !Aig_IsComplement(pObj) ); return Aig_ObjFanin1(pObj)? 1 + Aig_ObjIsExor(pObj) + Abc_MaxInt(Aig_ObjFanin0(pObj)->Level, Aig_ObjFanin1(pObj)->Level) : Aig_ObjFanin0(pObj)->Level; } +static inline int Aig_ObjSetLevel( Aig_Obj_t * pObj, int i ) { assert( !Aig_IsComplement(pObj) ); return pObj->Level = i; } +static inline void Aig_ObjClean( Aig_Obj_t * pObj ) { memset( pObj, 0, sizeof(Aig_Obj_t) ); } +static inline Aig_Obj_t * Aig_ObjFanout0( Aig_Man_t * p, Aig_Obj_t * pObj ) { assert(p->pFanData && pObj->Id < p->nFansAlloc); return Aig_ManObj(p, p->pFanData[5*pObj->Id] >> 1); } +static inline Aig_Obj_t * Aig_ObjEquiv( Aig_Man_t * p, Aig_Obj_t * pObj ) { return p->pEquivs? p->pEquivs[pObj->Id] : NULL; } +static inline void Aig_ObjSetEquiv( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pEqu ) { assert(p->pEquivs); p->pEquivs[pObj->Id] = pEqu; } +static inline Aig_Obj_t * Aig_ObjRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return p->pReprs? p->pReprs[pObj->Id] : NULL; } +static inline void Aig_ObjSetRepr( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr ) { assert(p->pReprs); p->pReprs[pObj->Id] = pRepr; } +static inline int Aig_ObjWhatFanin( Aig_Obj_t * pObj, Aig_Obj_t * pFanin ) +{ + if ( Aig_ObjFanin0(pObj) == pFanin ) return 0; + if ( Aig_ObjFanin1(pObj) == pFanin ) return 1; + assert(0); return -1; +} +static inline int Aig_ObjFanoutC( Aig_Obj_t * pObj, Aig_Obj_t * pFanout ) +{ + if ( Aig_ObjFanin0(pFanout) == pObj ) return Aig_ObjFaninC0(pObj); + if ( Aig_ObjFanin1(pFanout) == pObj ) return Aig_ObjFaninC1(pObj); + assert(0); return -1; +} + +// create the ghost of the new node +static inline Aig_Obj_t * Aig_ObjCreateGhost( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Type_t Type ) +{ + Aig_Obj_t * pGhost; + assert( Type != AIG_OBJ_AND || !Aig_ObjIsConst1(Aig_Regular(p0)) ); + assert( p1 == NULL || !Aig_ObjIsConst1(Aig_Regular(p1)) ); + assert( Type == AIG_OBJ_CI || Aig_Regular(p0) != Aig_Regular(p1) ); + pGhost = Aig_ManGhost(p); + pGhost->Type = Type; + if ( p1 == NULL || Aig_Regular(p0)->Id < Aig_Regular(p1)->Id ) + { + pGhost->pFanin0 = p0; + pGhost->pFanin1 = p1; + } + else + { + pGhost->pFanin0 = p1; + pGhost->pFanin1 = p0; + } + return pGhost; +} + +// internal memory manager +static inline Aig_Obj_t * Aig_ManFetchMemory( Aig_Man_t * p ) +{ + extern char * Aig_MmFixedEntryFetch( Aig_MmFixed_t * p ); + Aig_Obj_t * pTemp; + pTemp = (Aig_Obj_t *)Aig_MmFixedEntryFetch( p->pMemObjs ); + memset( pTemp, 0, sizeof(Aig_Obj_t) ); + pTemp->Id = Vec_PtrSize(p->vObjs); + Vec_PtrPush( p->vObjs, pTemp ); + return pTemp; +} +static inline void Aig_ManRecycleMemory( Aig_Man_t * p, Aig_Obj_t * pEntry ) +{ + extern void Aig_MmFixedEntryRecycle( Aig_MmFixed_t * p, char * pEntry ); + assert( pEntry->nRefs == 0 ); + pEntry->Type = AIG_OBJ_NONE; // distinquishes a dead node from a live node + Aig_MmFixedEntryRecycle( p->pMemObjs, (char *)pEntry ); + p->nDeleted++; +} + + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +// iterator over the combinational inputs +#define Aig_ManForEachCi( p, pObj, i ) \ + Vec_PtrForEachEntry( Aig_Obj_t *, p->vCis, pObj, i ) +#define Aig_ManForEachCiReverse( p, pObj, i ) \ + Vec_PtrForEachEntryReverse( Aig_Obj_t *, p->vCis, pObj, i ) +// iterator over the combinational outputs +#define Aig_ManForEachCo( p, pObj, i ) \ + Vec_PtrForEachEntry( Aig_Obj_t *, p->vCos, pObj, i ) +#define Aig_ManForEachCoReverse( p, pObj, i ) \ + Vec_PtrForEachEntryReverse( Aig_Obj_t *, p->vCos, pObj, i ) +// iterators over all objects, including those currently not used +#define Aig_ManForEachObj( p, pObj, i ) \ + Vec_PtrForEachEntry( Aig_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL ) {} else +#define Aig_ManForEachObjReverse( p, pObj, i ) \ + Vec_PtrForEachEntryReverse( Aig_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL ) {} else +// iterators over the objects whose IDs are stored in an array +#define Aig_ManForEachObjVec( vIds, p, pObj, i ) \ + for ( i = 0; i < Vec_IntSize(vIds) && (((pObj) = Aig_ManObj(p, Vec_IntEntry(vIds,i))), 1); i++ ) +#define Aig_ManForEachObjVecReverse( vIds, p, pObj, i ) \ + for ( i = Vec_IntSize(vIds) - 1; i >= 0 && (((pObj) = Aig_ManObj(p, Vec_IntEntry(vIds,i))), 1); i-- ) +// iterators over all nodes +#define Aig_ManForEachNode( p, pObj, i ) \ + Vec_PtrForEachEntry( Aig_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL || !Aig_ObjIsNode(pObj) ) {} else +#define Aig_ManForEachNodeReverse( p, pObj, i ) \ + Vec_PtrForEachEntryReverse( Aig_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL || !Aig_ObjIsNode(pObj) ) {} else +// iterator over all nodes +#define Aig_ManForEachExor( p, pObj, i ) \ + Vec_PtrForEachEntry( Aig_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL || !Aig_ObjIsExor(pObj) ) {} else +#define Aig_ManForEachExorReverse( p, pObj, i ) \ + Vec_PtrForEachEntryReverse( Aig_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL || !Aig_ObjIsExor(pObj) ) {} else + +// these two procedures are only here for the use inside the iterator +static inline int Aig_ObjFanout0Int( Aig_Man_t * p, int ObjId ) { assert(ObjId < p->nFansAlloc); return p->pFanData[5*ObjId]; } +static inline int Aig_ObjFanoutNext( Aig_Man_t * p, int iFan ) { assert(iFan/2 < p->nFansAlloc); return p->pFanData[5*(iFan >> 1) + 3 + (iFan & 1)]; } +// iterator over the fanouts +#define Aig_ObjForEachFanout( p, pObj, pFanout, iFan, i ) \ + for ( assert(p->pFanData), i = 0; (i < (int)(pObj)->nRefs) && \ + (((iFan) = i? Aig_ObjFanoutNext(p, iFan) : Aig_ObjFanout0Int(p, pObj->Id)), 1) && \ + (((pFanout) = Aig_ManObj(p, iFan>>1)), 1); i++ ) + + +//////////////////////////////////////////////////////////////////////// +/// SEQUENTIAL ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +// iterator over the primary inputs +#define Aig_ManForEachPiSeq( p, pObj, i ) \ + Vec_PtrForEachEntryStop( Aig_Obj_t *, p->vCis, pObj, i, Aig_ManCiNum(p)-Aig_ManRegNum(p) ) +// iterator over the latch outputs +#define Aig_ManForEachLoSeq( p, pObj, i ) \ + Vec_PtrForEachEntryStart( Aig_Obj_t *, p->vCis, pObj, i, Aig_ManCiNum(p)-Aig_ManRegNum(p) ) +// iterator over the primary outputs +#define Aig_ManForEachPoSeq( p, pObj, i ) \ + Vec_PtrForEachEntryStop( Aig_Obj_t *, p->vCos, pObj, i, Aig_ManCoNum(p)-Aig_ManRegNum(p) ) +// iterator over the latch inputs +#define Aig_ManForEachLiSeq( p, pObj, i ) \ + Vec_PtrForEachEntryStart( Aig_Obj_t *, p->vCos, pObj, i, Aig_ManCoNum(p)-Aig_ManRegNum(p) ) +// iterator over the latch input and outputs +#define Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, k ) \ + for ( k = 0; (k < Aig_ManRegNum(p)) && (((pObjLi) = Aig_ManLi(p, k)), 1) \ + && (((pObjLo)=Aig_ManLo(p, k)), 1); k++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== aigCheck.c ========================================================*/ +extern ABC_DLL int Aig_ManCheck( Aig_Man_t * p ); +extern void Aig_ManCheckMarkA( Aig_Man_t * p ); +extern void Aig_ManCheckPhase( Aig_Man_t * p ); +/*=== aigCuts.c ========================================================*/ +extern Aig_ManCut_t * Aig_ComputeCuts( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fTruth, int fVerbose ); +extern void Aig_ManCutStop( Aig_ManCut_t * p ); +/*=== aigDfs.c ==========================================================*/ +extern int Aig_ManVerifyTopoOrder( Aig_Man_t * p ); +extern Vec_Ptr_t * Aig_ManDfs( Aig_Man_t * p, int fNodesOnly ); +extern Vec_Ptr_t * Aig_ManDfsAll( Aig_Man_t * p ); +extern Vec_Ptr_t * Aig_ManDfsPreorder( Aig_Man_t * p, int fNodesOnly ); +extern Vec_Vec_t * Aig_ManLevelize( Aig_Man_t * p ); +extern Vec_Ptr_t * Aig_ManDfsNodes( Aig_Man_t * p, Aig_Obj_t ** ppNodes, int nNodes ); +extern Vec_Ptr_t * Aig_ManDfsChoices( Aig_Man_t * p ); +extern Vec_Ptr_t * Aig_ManDfsReverse( Aig_Man_t * p ); +extern int Aig_ManLevelNum( Aig_Man_t * p ); +extern int Aig_ManChoiceLevel( Aig_Man_t * p ); +extern int Aig_DagSize( Aig_Obj_t * pObj ); +extern int Aig_SupportSize( Aig_Man_t * p, Aig_Obj_t * pObj ); +extern Vec_Ptr_t * Aig_Support( Aig_Man_t * p, Aig_Obj_t * pObj ); +extern void Aig_SupportNodes( Aig_Man_t * p, Aig_Obj_t ** ppObjs, int nObjs, Vec_Ptr_t * vSupp ); +extern void Aig_ConeUnmark_rec( Aig_Obj_t * pObj ); +extern Aig_Obj_t * Aig_Transfer( Aig_Man_t * pSour, Aig_Man_t * pDest, Aig_Obj_t * pObj, int nVars ); +extern Aig_Obj_t * Aig_Compose( Aig_Man_t * p, Aig_Obj_t * pRoot, Aig_Obj_t * pFunc, int iVar ); +extern void Aig_ObjCollectCut( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes ); +extern int Aig_ObjCollectSuper( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ); +/*=== aigDup.c ==========================================================*/ +extern Aig_Obj_t * Aig_ManDupSimpleDfs_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ); +extern Aig_Man_t * Aig_ManDupSimple( Aig_Man_t * p ); +extern Aig_Man_t * Aig_ManDupSimpleWithHints( Aig_Man_t * p, Vec_Int_t * vHints ); +extern Aig_Man_t * Aig_ManDupSimpleDfs( Aig_Man_t * p ); +extern Aig_Man_t * Aig_ManDupSimpleDfsPart( Aig_Man_t * p, Vec_Ptr_t * vPis, Vec_Ptr_t * vCos ); +extern Aig_Man_t * Aig_ManDupOrdered( Aig_Man_t * p ); +extern Aig_Man_t * Aig_ManDupCof( Aig_Man_t * p, int iInput, int Value ); +extern Aig_Man_t * Aig_ManDupTrim( Aig_Man_t * p ); +extern Aig_Man_t * Aig_ManDupExor( Aig_Man_t * p ); +extern Aig_Man_t * Aig_ManDupDfs( Aig_Man_t * p ); +extern Vec_Ptr_t * Aig_ManOrderPios( Aig_Man_t * p, Aig_Man_t * pOrder ); +extern Aig_Man_t * Aig_ManDupDfsGuided( Aig_Man_t * p, Vec_Ptr_t * vPios ); +extern Aig_Man_t * Aig_ManDupLevelized( Aig_Man_t * p ); +extern Aig_Man_t * Aig_ManDupWithoutPos( Aig_Man_t * p ); +extern Aig_Man_t * Aig_ManDupFlopsOnly( Aig_Man_t * p ); +extern Aig_Man_t * Aig_ManDupRepres( Aig_Man_t * p ); +extern Aig_Man_t * Aig_ManDupRepresDfs( Aig_Man_t * p ); +extern Aig_Man_t * Aig_ManCreateMiter( Aig_Man_t * p1, Aig_Man_t * p2, int fImpl ); +extern Aig_Man_t * Aig_ManDupOrpos( Aig_Man_t * p, int fAddRegs ); +extern Aig_Man_t * Aig_ManDupOneOutput( Aig_Man_t * p, int iPoNum, int fAddRegs ); +extern Aig_Man_t * Aig_ManDupUnsolvedOutputs( Aig_Man_t * p, int fAddRegs ); +extern Aig_Man_t * Aig_ManDupArray( Vec_Ptr_t * vArray ); +extern Aig_Man_t * Aig_ManDupNodes( Aig_Man_t * pMan, Vec_Ptr_t * vArray ); +/*=== aigFanout.c ==========================================================*/ +extern void Aig_ObjAddFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout ); +extern void Aig_ObjRemoveFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout ); +extern void Aig_ManFanoutStart( Aig_Man_t * p ); +extern void Aig_ManFanoutStop( Aig_Man_t * p ); +/*=== aigFrames.c ==========================================================*/ +extern Aig_Man_t * Aig_ManFrames( Aig_Man_t * pAig, int nFs, int fInit, int fOuts, int fRegs, int fEnlarge, Aig_Obj_t *** ppObjMap ); +/*=== aigMan.c ==========================================================*/ +extern Aig_Man_t * Aig_ManStart( int nNodesMax ); +extern Aig_Man_t * Aig_ManStartFrom( Aig_Man_t * p ); +extern Aig_Man_t * Aig_ManExtractMiter( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 ); +extern void Aig_ManStop( Aig_Man_t * p ); +extern void Aig_ManStopP( Aig_Man_t ** p ); +extern int Aig_ManCleanup( Aig_Man_t * p ); +extern int Aig_ManAntiCleanup( Aig_Man_t * p ); +extern int Aig_ManCiCleanup( Aig_Man_t * p ); +extern int Aig_ManCoCleanup( Aig_Man_t * p ); +extern void Aig_ManPrintStats( Aig_Man_t * p ); +extern void Aig_ManReportImprovement( Aig_Man_t * p, Aig_Man_t * pNew ); +extern void Aig_ManSetRegNum( Aig_Man_t * p, int nRegs ); +extern void Aig_ManFlipFirstPo( Aig_Man_t * p ); +extern void * Aig_ManReleaseData( Aig_Man_t * p ); +/*=== aigMem.c ==========================================================*/ +extern void Aig_ManStartMemory( Aig_Man_t * p ); +extern void Aig_ManStopMemory( Aig_Man_t * p ); +/*=== aigMffc.c ==========================================================*/ +extern int Aig_NodeRef_rec( Aig_Obj_t * pNode, unsigned LevelMin ); +extern int Aig_NodeDeref_rec( Aig_Obj_t * pNode, unsigned LevelMin, float * pPower, float * pProbs ); +extern int Aig_NodeMffcSupp( Aig_Man_t * p, Aig_Obj_t * pNode, int LevelMin, Vec_Ptr_t * vSupp ); +extern int Aig_NodeMffcLabel( Aig_Man_t * p, Aig_Obj_t * pNode, float * pPower ); +extern int Aig_NodeMffcLabelCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves ); +extern int Aig_NodeMffcExtendCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vResult ); +/*=== aigObj.c ==========================================================*/ +extern Aig_Obj_t * Aig_ObjCreateCi( Aig_Man_t * p ); +extern Aig_Obj_t * Aig_ObjCreateCo( Aig_Man_t * p, Aig_Obj_t * pDriver ); +extern Aig_Obj_t * Aig_ObjCreate( Aig_Man_t * p, Aig_Obj_t * pGhost ); +extern void Aig_ObjConnect( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFan0, Aig_Obj_t * pFan1 ); +extern void Aig_ObjDisconnect( Aig_Man_t * p, Aig_Obj_t * pObj ); +extern void Aig_ObjDelete( Aig_Man_t * p, Aig_Obj_t * pObj ); +extern void Aig_ObjDelete_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int fFreeTop ); +extern void Aig_ObjDeletePo( Aig_Man_t * p, Aig_Obj_t * pObj ); +extern void Aig_ObjPrint( Aig_Man_t * p, Aig_Obj_t * pObj ); +extern void Aig_ObjPatchFanin0( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFaninNew ); +extern void Aig_ObjReplace( Aig_Man_t * p, Aig_Obj_t * pObjOld, Aig_Obj_t * pObjNew, int fUpdateLevel ); +/*=== aigOper.c =========================================================*/ +extern Aig_Obj_t * Aig_IthVar( Aig_Man_t * p, int i ); +extern Aig_Obj_t * Aig_Oper( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Type_t Type ); +extern Aig_Obj_t * Aig_And( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ); +extern Aig_Obj_t * Aig_Or( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ); +extern Aig_Obj_t * Aig_Exor( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ); +extern Aig_Obj_t * Aig_Mux( Aig_Man_t * p, Aig_Obj_t * pC, Aig_Obj_t * p1, Aig_Obj_t * p0 ); +extern Aig_Obj_t * Aig_Maj( Aig_Man_t * p, Aig_Obj_t * pA, Aig_Obj_t * pB, Aig_Obj_t * pC ); +extern Aig_Obj_t * Aig_Multi( Aig_Man_t * p, Aig_Obj_t ** pArgs, int nArgs, Aig_Type_t Type ); +extern Aig_Obj_t * Aig_Miter( Aig_Man_t * p, Vec_Ptr_t * vPairs ); +extern Aig_Obj_t * Aig_MiterTwo( Aig_Man_t * p, Vec_Ptr_t * vNodes1, Vec_Ptr_t * vNodes2 ); +extern Aig_Obj_t * Aig_CreateAnd( Aig_Man_t * p, int nVars ); +extern Aig_Obj_t * Aig_CreateOr( Aig_Man_t * p, int nVars ); +extern Aig_Obj_t * Aig_CreateExor( Aig_Man_t * p, int nVars ); +/*=== aigOrder.c =========================================================*/ +extern void Aig_ManOrderStart( Aig_Man_t * p ); +extern void Aig_ManOrderStop( Aig_Man_t * p ); +extern void Aig_ObjOrderInsert( Aig_Man_t * p, int ObjId ); +extern void Aig_ObjOrderRemove( Aig_Man_t * p, int ObjId ); +extern void Aig_ObjOrderAdvance( Aig_Man_t * p ); +/*=== aigPart.c =========================================================*/ +extern Vec_Ptr_t * Aig_ManSupports( Aig_Man_t * p ); +extern Vec_Ptr_t * Aig_ManSupportsInverse( Aig_Man_t * p ); +extern Vec_Ptr_t * Aig_ManSupportsRegisters( Aig_Man_t * p ); +extern Vec_Ptr_t * Aig_ManPartitionSmart( Aig_Man_t * p, int nPartSizeLimit, int fVerbose, Vec_Ptr_t ** pvPartSupps ); +extern Vec_Ptr_t * Aig_ManPartitionSmartRegisters( Aig_Man_t * pAig, int nSuppSizeLimit, int fVerbose ); +extern Vec_Ptr_t * Aig_ManPartitionNaive( Aig_Man_t * p, int nPartSize ); +extern Vec_Ptr_t * Aig_ManMiterPartitioned( Aig_Man_t * p1, Aig_Man_t * p2, int nPartSize, int fSmart ); +extern Aig_Man_t * Aig_ManChoicePartitioned( Vec_Ptr_t * vAigs, int nPartSize, int nConfMax, int nLevelMax, int fVerbose ); +extern Aig_Man_t * Aig_ManFraigPartitioned( Aig_Man_t * pAig, int nPartSize, int nConfMax, int nLevelMax, int fVerbose ); +extern Aig_Man_t * Aig_ManChoiceConstructive( Vec_Ptr_t * vAigs, int fVerbose ); +/*=== aigPartReg.c =========================================================*/ +extern Vec_Ptr_t * Aig_ManRegPartitionSimple( Aig_Man_t * pAig, int nPartSize, int nOverSize ); +extern void Aig_ManPartDivide( Vec_Ptr_t * vResult, Vec_Int_t * vDomain, int nPartSize, int nOverSize ); +extern Vec_Ptr_t * Aig_ManRegPartitionSmart( Aig_Man_t * pAig, int nPartSize ); +extern Aig_Man_t * Aig_ManRegCreatePart( Aig_Man_t * pAig, Vec_Int_t * vPart, int * pnCountPis, int * pnCountRegs, int ** ppMapBack ); +extern Vec_Ptr_t * Aig_ManRegProjectOnehots( Aig_Man_t * pAig, Aig_Man_t * pPart, Vec_Ptr_t * vOnehots, int fVerbose ); +/*=== aigRepr.c =========================================================*/ +extern void Aig_ManReprStart( Aig_Man_t * p, int nIdMax ); +extern void Aig_ManReprStop( Aig_Man_t * p ); +extern void Aig_ObjCreateRepr( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 ); +extern void Aig_ManTransferRepr( Aig_Man_t * pNew, Aig_Man_t * p ); +extern Aig_Man_t * Aig_ManDupRepr( Aig_Man_t * p, int fOrdered ); +extern Aig_Man_t * Aig_ManDupReprBasic( Aig_Man_t * p ); +extern int Aig_ManCountReprs( Aig_Man_t * p ); +extern Aig_Man_t * Aig_ManRehash( Aig_Man_t * p ); +extern int Aig_ObjCheckTfi( Aig_Man_t * p, Aig_Obj_t * pNew, Aig_Obj_t * pOld ); +extern void Aig_ManMarkValidChoices( Aig_Man_t * p ); +extern int Aig_TransferMappedClasses( Aig_Man_t * pAig, Aig_Man_t * pPart, int * pMapBack ); +/*=== aigRet.c ========================================================*/ +extern Aig_Man_t * Rtm_ManRetime( Aig_Man_t * p, int fForward, int nStepsMax, int fVerbose ); +/*=== aigRetF.c ========================================================*/ +extern Aig_Man_t * Aig_ManRetimeFrontier( Aig_Man_t * p, int nStepsMax ); +/*=== aigScl.c ==========================================================*/ +extern Aig_Man_t * Aig_ManRemap( Aig_Man_t * p, Vec_Ptr_t * vMap ); +extern int Aig_ManSeqCleanup( Aig_Man_t * p ); +extern int Aig_ManSeqCleanupBasic( Aig_Man_t * p ); +extern int Aig_ManCountMergeRegs( Aig_Man_t * p ); +extern Aig_Man_t * Aig_ManReduceLaches( Aig_Man_t * p, int fVerbose ); +extern void Aig_ManComputeSccs( Aig_Man_t * p ); +extern Aig_Man_t * Aig_ManScl( Aig_Man_t * pAig, int fLatchConst, int fLatchEqual, int fUseMvSweep, int nFramesSymb, int nFramesSatur, int fVerbose, int fVeryVerbose ); +/*=== aigShow.c ========================================================*/ +extern void Aig_ManShow( Aig_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ); +/*=== aigTable.c ========================================================*/ +extern Aig_Obj_t * Aig_TableLookup( Aig_Man_t * p, Aig_Obj_t * pGhost ); +extern Aig_Obj_t * Aig_TableLookupTwo( Aig_Man_t * p, Aig_Obj_t * pFanin0, Aig_Obj_t * pFanin1 ); +extern void Aig_TableInsert( Aig_Man_t * p, Aig_Obj_t * pObj ); +extern void Aig_TableDelete( Aig_Man_t * p, Aig_Obj_t * pObj ); +extern int Aig_TableCountEntries( Aig_Man_t * p ); +extern void Aig_TableProfile( Aig_Man_t * p ); +extern void Aig_TableClear( Aig_Man_t * p ); +/*=== aigTiming.c ========================================================*/ +extern void Aig_ObjClearReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObj ); +extern int Aig_ObjRequiredLevel( Aig_Man_t * p, Aig_Obj_t * pObj ); +extern void Aig_ManStartReverseLevels( Aig_Man_t * p, int nMaxLevelIncrease ); +extern void Aig_ManStopReverseLevels( Aig_Man_t * p ); +extern void Aig_ManUpdateLevel( Aig_Man_t * p, Aig_Obj_t * pObjNew ); +extern void Aig_ManUpdateReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObjNew ); +extern void Aig_ManVerifyLevel( Aig_Man_t * p ); +extern void Aig_ManVerifyReverseLevel( Aig_Man_t * p ); +/*=== aigTruth.c ========================================================*/ +extern unsigned * Aig_ManCutTruth( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes, Vec_Ptr_t * vTruthElem, Vec_Ptr_t * vTruthStore ); +/*=== aigTsim.c ========================================================*/ +extern Aig_Man_t * Aig_ManConstReduce( Aig_Man_t * p, int fUseMvSweep, int nFramesSymb, int nFramesSatur, int fVerbose, int fVeryVerbose ); +/*=== aigUtil.c =========================================================*/ +extern void Aig_ManIncrementTravId( Aig_Man_t * p ); +extern char * Aig_TimeStamp(); +extern int Aig_ManHasNoGaps( Aig_Man_t * p ); +extern int Aig_ManLevels( Aig_Man_t * p ); +extern void Aig_ManResetRefs( Aig_Man_t * p ); +extern void Aig_ManCleanMarkA( Aig_Man_t * p ); +extern void Aig_ManCleanMarkB( Aig_Man_t * p ); +extern void Aig_ManCleanMarkAB( Aig_Man_t * p ); +extern void Aig_ManCleanData( Aig_Man_t * p ); +extern void Aig_ObjCleanData_rec( Aig_Obj_t * pObj ); +extern void Aig_ManCleanNext( Aig_Man_t * p ); +extern void Aig_ObjCollectMulti( Aig_Obj_t * pFunc, Vec_Ptr_t * vSuper ); +extern int Aig_ObjIsMuxType( Aig_Obj_t * pObj ); +extern int Aig_ObjRecognizeExor( Aig_Obj_t * pObj, Aig_Obj_t ** ppFan0, Aig_Obj_t ** ppFan1 ); +extern Aig_Obj_t * Aig_ObjRecognizeMux( Aig_Obj_t * pObj, Aig_Obj_t ** ppObjT, Aig_Obj_t ** ppObjE ); +extern Aig_Obj_t * Aig_ObjReal_rec( Aig_Obj_t * pObj ); +extern int Aig_ObjCompareIdIncrease( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 ); +extern void Aig_ObjPrintEqn( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ); +extern void Aig_ObjPrintVerilog( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ); +extern void Aig_ObjPrintVerbose( Aig_Obj_t * pObj, int fHaig ); +extern void Aig_ManPrintVerbose( Aig_Man_t * p, int fHaig ); +extern void Aig_ManDump( Aig_Man_t * p ); +extern void Aig_ManDumpBlif( Aig_Man_t * p, char * pFileName, Vec_Ptr_t * vPiNames, Vec_Ptr_t * vPoNames ); +extern void Aig_ManDumpVerilog( Aig_Man_t * p, char * pFileName ); +extern void Aig_ManSetCioIds( Aig_Man_t * p ); +extern void Aig_ManCleanCioIds( Aig_Man_t * p ); +extern int Aig_ManChoiceNum( Aig_Man_t * p ); +extern char * Aig_FileNameGenericAppend( char * pBase, char * pSuffix ); +extern unsigned Aig_ManRandom( int fReset ); +extern word Aig_ManRandom64( int fReset ); +extern void Aig_ManRandomInfo( Vec_Ptr_t * vInfo, int iInputStart, int iWordStart, int iWordStop ); +extern void Aig_NodeUnionLists( Vec_Ptr_t * vArr1, Vec_Ptr_t * vArr2, Vec_Ptr_t * vArr ); +extern void Aig_NodeIntersectLists( Vec_Ptr_t * vArr1, Vec_Ptr_t * vArr2, Vec_Ptr_t * vArr ); +extern void Aig_ManSetPhase( Aig_Man_t * pAig ); +extern Vec_Ptr_t * Aig_ManMuxesCollect( Aig_Man_t * pAig ); +extern void Aig_ManMuxesDeref( Aig_Man_t * pAig, Vec_Ptr_t * vMuxes ); +extern void Aig_ManMuxesRef( Aig_Man_t * pAig, Vec_Ptr_t * vMuxes ); +extern void Aig_ManInvertConstraints( Aig_Man_t * pAig ); + +/*=== aigWin.c =========================================================*/ +extern void Aig_ManFindCut( Aig_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited, int nSizeLimit, int nFanoutLimit ); + +/*=== aigMem.c ===========================================================*/ +// fixed-size-block memory manager +extern Aig_MmFixed_t * Aig_MmFixedStart( int nEntrySize, int nEntriesMax ); +extern void Aig_MmFixedStop( Aig_MmFixed_t * p, int fVerbose ); +extern char * Aig_MmFixedEntryFetch( Aig_MmFixed_t * p ); +extern void Aig_MmFixedEntryRecycle( Aig_MmFixed_t * p, char * pEntry ); +extern void Aig_MmFixedRestart( Aig_MmFixed_t * p ); +extern int Aig_MmFixedReadMemUsage( Aig_MmFixed_t * p ); +extern int Aig_MmFixedReadMaxEntriesUsed( Aig_MmFixed_t * p ); +// flexible-size-block memory manager +extern Aig_MmFlex_t * Aig_MmFlexStart(); +extern void Aig_MmFlexStop( Aig_MmFlex_t * p, int fVerbose ); +extern char * Aig_MmFlexEntryFetch( Aig_MmFlex_t * p, int nBytes ); +extern void Aig_MmFlexRestart( Aig_MmFlex_t * p ); +extern int Aig_MmFlexReadMemUsage( Aig_MmFlex_t * p ); +// hierarchical memory manager +extern Aig_MmStep_t * Aig_MmStepStart( int nSteps ); +extern void Aig_MmStepStop( Aig_MmStep_t * p, int fVerbose ); +extern char * Aig_MmStepEntryFetch( Aig_MmStep_t * p, int nBytes ); +extern void Aig_MmStepEntryRecycle( Aig_MmStep_t * p, char * pEntry, int nBytes ); +extern int Aig_MmStepReadMemUsage( Aig_MmStep_t * p ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/yosys/abc/src/aig/aig/aigCanon.c b/yosys/abc/src/aig/aig/aigCanon.c new file mode 100644 index 00000000000..02c9ab8f9df --- /dev/null +++ b/yosys/abc/src/aig/aig/aigCanon.c @@ -0,0 +1,701 @@ +/**CFile**************************************************************** + + FileName [aigCanon.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Processing the library of semi-canonical AIGs.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigCanon.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" +#include "bool/kit/kit.h" +#include "bool/bdc/bdc.h" +#include "aig/ioa/ioa.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define RMAN_MAXVARS 12 +#define RMAX_MAXWORD (RMAN_MAXVARS <= 5 ? 1 : (1 << (RMAN_MAXVARS - 5))) + +typedef struct Aig_VSig_t_ Aig_VSig_t; +struct Aig_VSig_t_ +{ + int nOnes; + int nCofOnes[RMAN_MAXVARS]; +}; + +typedef struct Aig_Tru_t_ Aig_Tru_t; +struct Aig_Tru_t_ +{ + Aig_Tru_t * pNext; + int Id; + unsigned nVisits : 27; + unsigned nVars : 5; + unsigned pTruth[0]; +}; + +typedef struct Aig_RMan_t_ Aig_RMan_t; +struct Aig_RMan_t_ +{ + int nVars; // the largest variable number + Aig_Man_t * pAig; // recorded subgraphs + // hash table + int nBins; + Aig_Tru_t ** pBins; + int nEntries; + Aig_MmFlex_t* pMemTrus; + // bidecomposion + Bdc_Man_t * pBidec; + // temporaries + unsigned pTruthInit[RMAX_MAXWORD]; // canonical truth table + unsigned pTruth[RMAX_MAXWORD]; // current truth table + unsigned pTruthC[RMAX_MAXWORD]; // canonical truth table + unsigned pTruthTemp[RMAX_MAXWORD]; // temporary truth table + Aig_VSig_t pMints[2*RMAN_MAXVARS]; // minterm count + char pPerm[RMAN_MAXVARS]; // permutation + char pPermR[RMAN_MAXVARS]; // reverse permutation + // statistics + int nVarFuncs[RMAN_MAXVARS+1]; + int nTotal; + int nTtDsd; + int nTtDsdPart; + int nTtDsdNot; + int nUniqueVars; +}; + +static Aig_RMan_t * s_pRMan = NULL; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates recording manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_RMan_t * Aig_RManStart() +{ + static Bdc_Par_t Pars = {0}, * pPars = &Pars; + Aig_RMan_t * p; + p = ABC_ALLOC( Aig_RMan_t, 1 ); + memset( p, 0, sizeof(Aig_RMan_t) ); + p->nVars = RMAN_MAXVARS; + p->pAig = Aig_ManStart( 1000000 ); + Aig_IthVar( p->pAig, p->nVars-1 ); + // create hash table + p->nBins = Abc_PrimeCudd(5000); + p->pBins = ABC_CALLOC( Aig_Tru_t *, p->nBins ); + p->pMemTrus = Aig_MmFlexStart(); + // bi-decomposition manager + pPars->nVarsMax = p->nVars; + pPars->fVerbose = 0; + p->pBidec = Bdc_ManAlloc( pPars ); + return p; +} + +/**Function************************************************************* + + Synopsis [Returns the hash key.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_RManTableHash( unsigned * pTruth, int nVars, int nBins, int * pPrimes ) +{ + int i, nWords = Kit_TruthWordNum( nVars ); + unsigned uHash = 0; + for ( i = 0; i < nWords; i++ ) + uHash ^= pTruth[i] * pPrimes[i & 0xf]; + return (int)(uHash % nBins); +} + +/**Function************************************************************* + + Synopsis [Returns the given record.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Tru_t ** Aig_RManTableLookup( Aig_RMan_t * p, unsigned * pTruth, int nVars ) +{ + static int s_Primes[16] = { + 1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177, + 4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 }; + Aig_Tru_t ** ppSpot, * pEntry; + ppSpot = p->pBins + Aig_RManTableHash( pTruth, nVars, p->nBins, s_Primes ); + for ( pEntry = *ppSpot; pEntry; ppSpot = &pEntry->pNext, pEntry = pEntry->pNext ) + if ( Kit_TruthIsEqual( pEntry->pTruth, pTruth, nVars ) ) + return ppSpot; + return ppSpot; +} + +/**Function************************************************************* + + Synopsis [Find or add new entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_RManTableResize( Aig_RMan_t * p ) +{ + Aig_Tru_t * pEntry, * pNext; + Aig_Tru_t ** pBinsOld, ** ppPlace; + int nBinsOld, Counter, i; + abctime clk; + assert( p->pBins != NULL ); +clk = Abc_Clock(); + // save the old Bins + pBinsOld = p->pBins; + nBinsOld = p->nBins; + // get the new Bins + p->nBins = Abc_PrimeCudd( 3 * nBinsOld ); + p->pBins = ABC_CALLOC( Aig_Tru_t *, p->nBins ); + // rehash the entries from the old table + Counter = 0; + for ( i = 0; i < nBinsOld; i++ ) + for ( pEntry = pBinsOld[i], pNext = pEntry? pEntry->pNext : NULL; + pEntry; pEntry = pNext, pNext = pEntry? pEntry->pNext : NULL ) + { + // get the place where this entry goes in the Bins + ppPlace = Aig_RManTableLookup( p, pEntry->pTruth, pEntry->nVars ); + assert( *ppPlace == NULL ); // should not be there + // add the entry to the list + *ppPlace = pEntry; + pEntry->pNext = NULL; + Counter++; + } + assert( Counter == p->nEntries ); +// ABC_PRT( "Time", Abc_Clock() - clk ); + ABC_FREE( pBinsOld ); +} + +/**Function************************************************************* + + Synopsis [Find or add new entry.] + + Description [Returns 1 if this is a new entry.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_RManTableFindOrAdd( Aig_RMan_t * p, unsigned * pTruth, int nVars ) +{ + Aig_Tru_t ** ppSpot, * pEntry; + int nBytes; + ppSpot = Aig_RManTableLookup( p, pTruth, nVars ); + if ( *ppSpot ) + { + (*ppSpot)->nVisits++; + return 0; + } + nBytes = sizeof(Aig_Tru_t) + sizeof(unsigned) * Kit_TruthWordNum(nVars); + if ( p->nEntries == 3*p->nBins ) + Aig_RManTableResize( p ); + pEntry = (Aig_Tru_t *)Aig_MmFlexEntryFetch( p->pMemTrus, nBytes ); + pEntry->Id = p->nEntries++; + pEntry->nVars = nVars; + pEntry->nVisits = 1; + pEntry->pNext = NULL; + memcpy( pEntry->pTruth, pTruth, sizeof(unsigned) * Kit_TruthWordNum(nVars) ); + *ppSpot = pEntry; + return 1; +} + +/**Function************************************************************* + + Synopsis [Deallocates recording manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_RManStop( Aig_RMan_t * p ) +{ + int i; + printf( "Total funcs = %10d\n", p->nTotal ); + printf( "Full DSD funcs = %10d\n", p->nTtDsd ); + printf( "Part DSD funcs = %10d\n", p->nTtDsdPart ); + printf( "Non- DSD funcs = %10d\n", p->nTtDsdNot ); + printf( "Uniq-var funcs = %10d\n", p->nUniqueVars ); + printf( "Unique funcs = %10d\n", p->nEntries ); + printf( "Distribution of functions:\n" ); + for ( i = 5; i <= p->nVars; i++ ) + printf( "%2d = %8d\n", i, p->nVarFuncs[i] ); + Aig_MmFlexStop( p->pMemTrus, 0 ); + Aig_ManStop( p->pAig ); + Bdc_ManFree( p->pBidec ); + ABC_FREE( p->pBins ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [Stops recording.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_RManQuit() +{ +// extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact ); + char Buffer[20]; + if ( s_pRMan == NULL ) + return; + // dump the library file + sprintf( Buffer, "aiglib%02d.aig", s_pRMan->nVars ); + Ioa_WriteAiger( s_pRMan->pAig, Buffer, 0, 1 ); + // quit the manager + Aig_RManStop( s_pRMan ); + s_pRMan = NULL; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if all variables are unique.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_RManPrintVarProfile( unsigned * pTruth, int nVars, unsigned * pTruthAux ) +{ + int pStore2[32]; + int i; + Kit_TruthCountOnesInCofsSlow( pTruth, nVars, pStore2, pTruthAux ); + for ( i = 0; i < nVars; i++ ) + printf( "%2d/%2d ", pStore2[2*i], pStore2[2*i+1] ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Sorts numbers in the increasing order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_RManSortNums( int * pArray, int nVars ) +{ + int i, j, best_i, tmp; + for ( i = 0; i < nVars-1; i++ ) + { + best_i = i; + for ( j = i+1; j < nVars; j++ ) + if ( pArray[j] > pArray[best_i] ) + best_i = j; + tmp = pArray[i]; pArray[i] = pArray[best_i]; pArray[best_i] = tmp; + } +} + +/**Function************************************************************* + + Synopsis [Prints signatures for all variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_RManPrintSigs( Aig_VSig_t * pSigs, int nVars ) +{ + int v, i, k; + for ( v = 0; v < nVars; v++ ) + { + printf( "%2d : ", v ); + for ( k = 0; k < 2; k++ ) + { + printf( "%5d ", pSigs[2*v+k].nOnes ); + printf( "(" ); + for ( i = 0; i < nVars; i++ ) + printf( "%4d ", pSigs[2*v+k].nCofOnes[i] ); + printf( ") " ); + } + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Computes signatures for all variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_RManComputeVSigs( unsigned * pTruth, int nVars, Aig_VSig_t * pSigs, unsigned * pAux ) +{ + int v; + for ( v = 0; v < nVars; v++ ) + { + Kit_TruthCofactor0New( pAux, pTruth, nVars, v ); + pSigs[2*v+0].nOnes = Kit_TruthCountOnes( pAux, nVars ); + Kit_TruthCountOnesInCofs0( pAux, nVars, pSigs[2*v+0].nCofOnes ); + Aig_RManSortNums( pSigs[2*v+0].nCofOnes, nVars ); + + Kit_TruthCofactor1New( pAux, pTruth, nVars, v ); + pSigs[2*v+1].nOnes = Kit_TruthCountOnes( pAux, nVars ); + Kit_TruthCountOnesInCofs0( pAux, nVars, pSigs[2*v+1].nCofOnes ); + Aig_RManSortNums( pSigs[2*v+1].nCofOnes, nVars ); + } +} + +/**Function************************************************************* + + Synopsis [Computs signatures for all variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_RManCompareSigs( Aig_VSig_t * p0, Aig_VSig_t * p1, int nVars ) +{ +// return memcmp( p0, p1, sizeof(int) + sizeof(int) * nVars ); + return memcmp( p0, p1, sizeof(int) ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if all variables are unique.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_RManVarsAreUnique( Aig_VSig_t * pMints, int nVars ) +{ + int i; + for ( i = 0; i < nVars - 1; i++ ) + if ( Aig_RManCompareSigs( &pMints[2*i], &pMints[2*(i+1)], nVars ) == 0 ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if all variables are unique.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_RManPrintUniqueVars( Aig_VSig_t * pMints, int nVars ) +{ + int i; + for ( i = 0; i < nVars; i++ ) + if ( Aig_RManCompareSigs( &pMints[2*i], &pMints[2*i+1], nVars ) == 0 ) + printf( "=" ); + else + printf( "x" ); + printf( "\n" ); + + printf( "0" ); + for ( i = 1; i < nVars; i++ ) + if ( Aig_RManCompareSigs( &pMints[2*(i-1)], &pMints[2*i], nVars ) == 0 ) + printf( "-" ); + else if ( i < 10 ) + printf( "%c", '0' + i ); + else + printf( "%c", 'A' + i-10 ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Canonicize the truth table.] + + Description [Returns the phase. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Aig_RManSemiCanonicize( unsigned * pOut, unsigned * pIn, int nVars, char * pCanonPerm, Aig_VSig_t * pSigs, int fReturnIn ) +{ + Aig_VSig_t TempSig; + int i, Temp, fChange, Counter; + unsigned * pTemp, uCanonPhase = 0; + // collect signatures + Aig_RManComputeVSigs( pIn, nVars, pSigs, pOut ); + // canonicize phase + for ( i = 0; i < nVars; i++ ) + { +// if ( pStore[2*i+0] <= pStore[2*i+1] ) + if ( Aig_RManCompareSigs( &pSigs[2*i+0], &pSigs[2*i+1], nVars ) <= 0 ) + continue; + uCanonPhase |= (1 << i); + TempSig = pSigs[2*i+0]; + pSigs[2*i+0] = pSigs[2*i+1]; + pSigs[2*i+1] = TempSig; + Kit_TruthChangePhase( pIn, nVars, i ); + } + // permute + Counter = 0; + do { + fChange = 0; + for ( i = 0; i < nVars-1; i++ ) + { +// if ( pStore[2*i] <= pStore[2*(i+1)] ) + if ( Aig_RManCompareSigs( &pSigs[2*i], &pSigs[2*(i+1)], nVars ) <= 0 ) + continue; + Counter++; + fChange = 1; + + Temp = pCanonPerm[i]; + pCanonPerm[i] = pCanonPerm[i+1]; + pCanonPerm[i+1] = Temp; + + TempSig = pSigs[2*i]; + pSigs[2*i] = pSigs[2*(i+1)]; + pSigs[2*(i+1)] = TempSig; + + TempSig = pSigs[2*i+1]; + pSigs[2*i+1] = pSigs[2*(i+1)+1]; + pSigs[2*(i+1)+1] = TempSig; + + Kit_TruthSwapAdjacentVars( pOut, pIn, nVars, i ); + pTemp = pIn; pIn = pOut; pOut = pTemp; + } + } while ( fChange ); + + // swap if it was moved an even number of times + if ( fReturnIn ^ !(Counter & 1) ) + Kit_TruthCopy( pOut, pIn, nVars ); + return uCanonPhase; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Aig_Obj_t * Bdc_FunCopyHop( Bdc_Fun_t * pObj ) +{ return Aig_NotCond( (Aig_Obj_t *)Bdc_FuncCopy(Bdc_Regular(pObj)), Bdc_IsComplement(pObj) ); } + +/**Function************************************************************* + + Synopsis [Records one function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_RManSaveOne( Aig_RMan_t * p, unsigned * pTruth, int nVars ) +{ + int i, nNodes, RetValue; + Bdc_Fun_t * pFunc; + Aig_Obj_t * pTerm; + // perform decomposition + RetValue = Bdc_ManDecompose( p->pBidec, pTruth, NULL, nVars, NULL, 1000 ); + if ( RetValue < 0 ) + { + printf( "Decomposition failed.\n" ); + return; + } + // convert back into HOP + Bdc_FuncSetCopy( Bdc_ManFunc( p->pBidec, 0 ), Aig_ManConst1(p->pAig) ); + for ( i = 0; i < nVars; i++ ) + Bdc_FuncSetCopy( Bdc_ManFunc( p->pBidec, i+1 ), Aig_IthVar(p->pAig, i) ); + nNodes = Bdc_ManNodeNum(p->pBidec); + for ( i = nVars + 1; i < nNodes; i++ ) + { + pFunc = Bdc_ManFunc( p->pBidec, i ); + Bdc_FuncSetCopy( pFunc, Aig_And( p->pAig, + Bdc_FunCopyHop(Bdc_FuncFanin0(pFunc)), + Bdc_FunCopyHop(Bdc_FuncFanin1(pFunc)) ) ); + } + pTerm = Bdc_FunCopyHop( Bdc_ManRoot(p->pBidec) ); + pTerm = Aig_ObjCreateCo( p->pAig, pTerm ); +// assert( pTerm->fPhase == 0 ); +} + +/**Function************************************************************* + + Synopsis [Records one function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_RManRecord( unsigned * pTruth, int nVarsInit ) +{ + int fVerify = 1; + Kit_DsdNtk_t * pNtk; + Kit_DsdObj_t * pObj; + unsigned uPhaseC; + int i, nVars, nWords; + int fUniqueVars; + + if ( nVarsInit > RMAN_MAXVARS ) + { + printf( "The number of variables in too large.\n" ); + return; + } + + if ( s_pRMan == NULL ) + s_pRMan = Aig_RManStart(); + s_pRMan->nTotal++; + // canonicize the function + pNtk = Kit_DsdDecompose( pTruth, nVarsInit ); + pObj = Kit_DsdNonDsdPrimeMax( pNtk ); + if ( pObj == NULL || pObj->nFans == 3 ) + { + s_pRMan->nTtDsd++; + Kit_DsdNtkFree( pNtk ); + return; + } + nVars = pObj->nFans; + s_pRMan->nVarFuncs[nVars]++; + if ( nVars < nVarsInit ) + s_pRMan->nTtDsdPart++; + else + s_pRMan->nTtDsdNot++; + // compute the number of words + nWords = Abc_TruthWordNum( nVars ); + // copy the function + memcpy( s_pRMan->pTruthInit, Kit_DsdObjTruth(pObj), (size_t)(4*nWords) ); + Kit_DsdNtkFree( pNtk ); + // canonicize the output + if ( s_pRMan->pTruthInit[0] & 1 ) + Kit_TruthNot( s_pRMan->pTruthInit, s_pRMan->pTruthInit, nVars ); + memcpy( s_pRMan->pTruth, s_pRMan->pTruthInit, 4*nWords ); + + // canonize the function + for ( i = 0; i < nVars; i++ ) + s_pRMan->pPerm[i] = i; + uPhaseC = Aig_RManSemiCanonicize( s_pRMan->pTruthTemp, s_pRMan->pTruth, nVars, s_pRMan->pPerm, s_pRMan->pMints, 1 ); + // check unique variables + fUniqueVars = Aig_RManVarsAreUnique( s_pRMan->pMints, nVars ); + s_pRMan->nUniqueVars += fUniqueVars; + +/* + printf( "%4d : ", s_pRMan->nTotal ); + printf( "%2d %2d ", nVarsInit, nVars ); + Extra_PrintBinary( stdout, &uPhaseC, nVars ); + printf( " " ); + for ( i = 0; i < nVars; i++ ) + printf( "%2d/%2d ", s_pRMan->pMints[2*i], s_pRMan->pMints[2*i+1] ); + printf( "\n" ); + Aig_RManPrintUniqueVars( s_pRMan->pMints, nVars ); +Extra_PrintBinary( stdout, s_pRMan->pTruth, 1<nTotal ); + printf( "%2d %2d ", nVarsInit, nVars ); + printf( " " ); + printf( "\n" ); + Aig_RManPrintUniqueVars( s_pRMan->pMints, nVars ); +// Aig_RManPrintSigs( s_pRMan->pMints, nVars ); +*/ + +//Extra_PrintBinary( stdout, s_pRMan->pTruth, 1<pTruth, nVars ) ) + Aig_RManSaveOne( s_pRMan, s_pRMan->pTruth, nVars ); + + if ( fVerify ) + { + // derive reverse permutation + for ( i = 0; i < nVars; i++ ) + s_pRMan->pPermR[i] = s_pRMan->pPerm[i]; + // implement permutation + Kit_TruthPermute( s_pRMan->pTruthTemp, s_pRMan->pTruth, nVars, s_pRMan->pPermR, 1 ); + // implement polarity + for ( i = 0; i < nVars; i++ ) + if ( uPhaseC & (1 << i) ) + Kit_TruthChangePhase( s_pRMan->pTruth, nVars, i ); + + // perform verification + if ( fUniqueVars && !Kit_TruthIsEqual( s_pRMan->pTruth, s_pRMan->pTruthInit, nVars ) ) + printf( "Verification failed.\n" ); + } +//Aig_RManPrintVarProfile( s_pRMan->pTruth, nVars, s_pRMan->pTruthTemp ); +//Extra_PrintBinary( stdout, s_pRMan->pTruth, 1<Id >= Aig_ObjFanin1(pObj)->Id ) + { + printf( "Aig_ManCheck: The AIG has node \"%p\" with a wrong ordering of fanins.\n", pObj ); + return 0; + } + pObj2 = Aig_TableLookup( p, pObj ); + if ( pObj2 != pObj ) + { + printf( "Aig_ManCheck: Node \"%p\" is not in the structural hashing table.\n", pObj ); + return 0; + } + } + // count the total number of nodes + if ( Aig_ManObjNum(p) != 1 + Aig_ManCiNum(p) + Aig_ManCoNum(p) + + Aig_ManBufNum(p) + Aig_ManAndNum(p) + Aig_ManExorNum(p) ) + { + printf( "Aig_ManCheck: The number of created nodes is wrong.\n" ); + printf( "C1 = %d. Pi = %d. Po = %d. Buf = %d. And = %d. Xor = %d. Total = %d.\n", + 1, Aig_ManCiNum(p), Aig_ManCoNum(p), Aig_ManBufNum(p), Aig_ManAndNum(p), Aig_ManExorNum(p), + 1 + Aig_ManCiNum(p) + Aig_ManCoNum(p) + Aig_ManBufNum(p) + Aig_ManAndNum(p) + Aig_ManExorNum(p) ); + printf( "Created = %d. Deleted = %d. Existing = %d.\n", + Aig_ManObjNumMax(p), p->nDeleted, Aig_ManObjNum(p) ); + return 0; + } + // count the number of nodes in the table + if ( Aig_TableCountEntries(p) != Aig_ManAndNum(p) + Aig_ManExorNum(p) ) + { + printf( "Aig_ManCheck: The number of nodes in the structural hashing table is wrong.\n" ); + printf( "Entries = %d. And = %d. Xor = %d. Total = %d.\n", + Aig_TableCountEntries(p), Aig_ManAndNum(p), Aig_ManExorNum(p), + Aig_ManAndNum(p) + Aig_ManExorNum(p) ); + + return 0; + } +// if ( !Aig_ManIsAcyclic(p) ) +// return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks if the markA is reset.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManCheckMarkA( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachObj( p, pObj, i ) + assert( pObj->fMarkA == 0 ); +} + +/**Function************************************************************* + + Synopsis [Checks the consistency of phase assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManCheckPhase( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachObj( p, pObj, i ) + if ( Aig_ObjIsCi(pObj) ) + assert( (int)pObj->fPhase == 0 ); + else + assert( (int)pObj->fPhase == (Aig_ObjPhaseReal(Aig_ObjChild0(pObj)) & Aig_ObjPhaseReal(Aig_ObjChild1(pObj))) ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigCuts.c b/yosys/abc/src/aig/aig/aigCuts.c new file mode 100644 index 00000000000..af4edcbb936 --- /dev/null +++ b/yosys/abc/src/aig/aig/aigCuts.c @@ -0,0 +1,673 @@ +/**CFile**************************************************************** + + FileName [aigCuts.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Computation of K-feasible priority cuts.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigCuts.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" +#include "bool/kit/kit.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the cut sweeping manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_ManCut_t * Aig_ManCutStart( Aig_Man_t * pMan, int nCutsMax, int nLeafMax, int fTruth, int fVerbose ) +{ + Aig_ManCut_t * p; + assert( nCutsMax >= 2 ); + assert( nLeafMax <= 16 ); + // allocate the fraiging manager + p = ABC_ALLOC( Aig_ManCut_t, 1 ); + memset( p, 0, sizeof(Aig_ManCut_t) ); + p->nCutsMax = nCutsMax; + p->nLeafMax = nLeafMax; + p->fTruth = fTruth; + p->fVerbose = fVerbose; + p->pAig = pMan; + p->pCuts = ABC_CALLOC( Aig_Cut_t *, Aig_ManObjNumMax(pMan) ); + // allocate memory manager + p->nTruthWords = Abc_TruthWordNum(nLeafMax); + p->nCutSize = sizeof(Aig_Cut_t) + sizeof(int) * nLeafMax + fTruth * sizeof(unsigned) * p->nTruthWords; + p->pMemCuts = Aig_MmFixedStart( p->nCutSize * p->nCutsMax, 512 ); + // room for temporary truth tables + if ( fTruth ) + { + p->puTemp[0] = ABC_ALLOC( unsigned, 4 * p->nTruthWords ); + p->puTemp[1] = p->puTemp[0] + p->nTruthWords; + p->puTemp[2] = p->puTemp[1] + p->nTruthWords; + p->puTemp[3] = p->puTemp[2] + p->nTruthWords; + } + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the fraiging manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManCutStop( Aig_ManCut_t * p ) +{ + Aig_MmFixedStop( p->pMemCuts, 0 ); + ABC_FREE( p->puTemp[0] ); + ABC_FREE( p->pCuts ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Prints one cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_CutPrint( Aig_Cut_t * pCut ) +{ + int i; + printf( "{" ); + for ( i = 0; i < pCut->nFanins; i++ ) + printf( " %d", pCut->pFanins[i] ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints one cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjCutPrint( Aig_ManCut_t * p, Aig_Obj_t * pObj ) +{ + Aig_Cut_t * pCut; + int i; + printf( "Cuts for node %d:\n", pObj->Id ); + Aig_ObjForEachCut( p, pObj, pCut, i ) + if ( pCut->nFanins ) + Aig_CutPrint( pCut ); +// printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Computes the total number of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManCutCount( Aig_ManCut_t * p, int * pnCutsK ) +{ + Aig_Cut_t * pCut; + Aig_Obj_t * pObj; + int i, k, nCuts = 0, nCutsK = 0; + Aig_ManForEachNode( p->pAig, pObj, i ) + Aig_ObjForEachCut( p, pObj, pCut, k ) + { + if ( pCut->nFanins == 0 ) + continue; + nCuts++; + if ( pCut->nFanins == p->nLeafMax ) + nCutsK++; + } + if ( pnCutsK ) + *pnCutsK = nCutsK; + return nCuts; +} + +/**Function************************************************************* + + Synopsis [Compute the cost of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_CutFindCost( Aig_ManCut_t * p, Aig_Cut_t * pCut ) +{ + Aig_Obj_t * pLeaf; + int i, Cost = 0; + assert( pCut->nFanins > 0 ); + Aig_CutForEachLeaf( p->pAig, pCut, pLeaf, i ) + Cost += pLeaf->nRefs; + return Cost * 1000 / pCut->nFanins; +} + +/**Function************************************************************* + + Synopsis [Compute the cost of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline float Aig_CutFindCost2( Aig_ManCut_t * p, Aig_Cut_t * pCut ) +{ + Aig_Obj_t * pLeaf; + float Cost = 0.0; + int i; + assert( pCut->nFanins > 0 ); + Aig_CutForEachLeaf( p->pAig, pCut, pLeaf, i ) + Cost += (float)1.0/pLeaf->nRefs; + return 1/Cost; +} + +/**Function************************************************************* + + Synopsis [Returns the next free cut to use.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Aig_Cut_t * Aig_CutFindFree( Aig_ManCut_t * p, Aig_Obj_t * pObj ) +{ + Aig_Cut_t * pCut, * pCutMax; + int i; + pCutMax = NULL; + Aig_ObjForEachCut( p, pObj, pCut, i ) + { + if ( pCut->nFanins == 0 ) + return pCut; + if ( pCutMax == NULL || pCutMax->Cost < pCut->Cost ) + pCutMax = pCut; + } + assert( pCutMax != NULL ); + pCutMax->nFanins = 0; + return pCutMax; +} + +/**Function************************************************************* + + Synopsis [Computes the stretching phase of the cut w.r.t. the merged cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Aig_CutTruthPhase( Aig_Cut_t * pCut, Aig_Cut_t * pCut1 ) +{ + unsigned uPhase = 0; + int i, k; + for ( i = k = 0; i < pCut->nFanins; i++ ) + { + if ( k == pCut1->nFanins ) + break; + if ( pCut->pFanins[i] < pCut1->pFanins[k] ) + continue; + assert( pCut->pFanins[i] == pCut1->pFanins[k] ); + uPhase |= (1 << i); + k++; + } + return uPhase; +} + +/**Function************************************************************* + + Synopsis [Performs truth table computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Aig_CutComputeTruth( Aig_ManCut_t * p, Aig_Cut_t * pCut, Aig_Cut_t * pCut0, Aig_Cut_t * pCut1, int fCompl0, int fCompl1 ) +{ + // permute the first table + if ( fCompl0 ) + Kit_TruthNot( p->puTemp[0], Aig_CutTruth(pCut0), p->nLeafMax ); + else + Kit_TruthCopy( p->puTemp[0], Aig_CutTruth(pCut0), p->nLeafMax ); + Kit_TruthStretch( p->puTemp[2], p->puTemp[0], pCut0->nFanins, p->nLeafMax, Aig_CutTruthPhase(pCut, pCut0), 0 ); + // permute the second table + if ( fCompl1 ) + Kit_TruthNot( p->puTemp[1], Aig_CutTruth(pCut1), p->nLeafMax ); + else + Kit_TruthCopy( p->puTemp[1], Aig_CutTruth(pCut1), p->nLeafMax ); + Kit_TruthStretch( p->puTemp[3], p->puTemp[1], pCut1->nFanins, p->nLeafMax, Aig_CutTruthPhase(pCut, pCut1), 0 ); + // produce the resulting table + Kit_TruthAnd( Aig_CutTruth(pCut), p->puTemp[2], p->puTemp[3], p->nLeafMax ); +// assert( pCut->nFanins >= Kit_TruthSupportSize( Aig_CutTruth(pCut), p->nLeafMax ) ); + return Aig_CutTruth(pCut); +} + +/**Function************************************************************* + + Synopsis [Performs support minimization for the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_CutSupportMinimize( Aig_ManCut_t * p, Aig_Cut_t * pCut ) +{ + unsigned * pTruth; + int uSupp, nFansNew, i, k; + // get truth table + pTruth = Aig_CutTruth( pCut ); + // get support + uSupp = Kit_TruthSupport( pTruth, p->nLeafMax ); + // get the new support size + nFansNew = Kit_WordCountOnes( uSupp ); + // check if there are redundant variables + if ( nFansNew == pCut->nFanins ) + return nFansNew; + assert( nFansNew < pCut->nFanins ); + // minimize support + Kit_TruthShrink( p->puTemp[0], pTruth, nFansNew, p->nLeafMax, uSupp, 1 ); + for ( i = k = 0; i < pCut->nFanins; i++ ) + if ( uSupp & (1 << i) ) + pCut->pFanins[k++] = pCut->pFanins[i]; + assert( k == nFansNew ); + pCut->nFanins = nFansNew; +// assert( nFansNew == Kit_TruthSupportSize( pTruth, p->nLeafMax ) ); +//Extra_PrintBinary( stdout, pTruth, (1<nLeafMax) ); printf( "\n" ); + return nFansNew; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pDom is contained in pCut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_CutCheckDominance( Aig_Cut_t * pDom, Aig_Cut_t * pCut ) +{ + int i, k; + for ( i = 0; i < (int)pDom->nFanins; i++ ) + { + for ( k = 0; k < (int)pCut->nFanins; k++ ) + if ( pDom->pFanins[i] == pCut->pFanins[k] ) + break; + if ( k == (int)pCut->nFanins ) // node i in pDom is not contained in pCut + return 0; + } + // every node in pDom is contained in pCut + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the cut is contained.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_CutFilter( Aig_ManCut_t * p, Aig_Obj_t * pObj, Aig_Cut_t * pCut ) +{ + Aig_Cut_t * pTemp; + int i; + // go through the cuts of the node + Aig_ObjForEachCut( p, pObj, pTemp, i ) + { + if ( pTemp->nFanins < 2 ) + continue; + if ( pTemp == pCut ) + continue; + if ( pTemp->nFanins > pCut->nFanins ) + { + // skip the non-contained cuts + if ( (pTemp->uSign & pCut->uSign) != pCut->uSign ) + continue; + // check containment seriously + if ( Aig_CutCheckDominance( pCut, pTemp ) ) + { + // remove contained cut + pTemp->nFanins = 0; + } + } + else + { + // skip the non-contained cuts + if ( (pTemp->uSign & pCut->uSign) != pTemp->uSign ) + continue; + // check containment seriously + if ( Aig_CutCheckDominance( pTemp, pCut ) ) + { + // remove the given + pCut->nFanins = 0; + return 1; + } + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Merges two cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_CutMergeOrdered( Aig_ManCut_t * p, Aig_Cut_t * pC0, Aig_Cut_t * pC1, Aig_Cut_t * pC ) +{ + int i, k, c; + assert( pC0->nFanins >= pC1->nFanins ); + // the case of the largest cut sizes + if ( pC0->nFanins == p->nLeafMax && pC1->nFanins == p->nLeafMax ) + { + for ( i = 0; i < pC0->nFanins; i++ ) + if ( pC0->pFanins[i] != pC1->pFanins[i] ) + return 0; + for ( i = 0; i < pC0->nFanins; i++ ) + pC->pFanins[i] = pC0->pFanins[i]; + pC->nFanins = pC0->nFanins; + return 1; + } + // the case when one of the cuts is the largest + if ( pC0->nFanins == p->nLeafMax ) + { + for ( i = 0; i < pC1->nFanins; i++ ) + { + for ( k = pC0->nFanins - 1; k >= 0; k-- ) + if ( pC0->pFanins[k] == pC1->pFanins[i] ) + break; + if ( k == -1 ) // did not find + return 0; + } + for ( i = 0; i < pC0->nFanins; i++ ) + pC->pFanins[i] = pC0->pFanins[i]; + pC->nFanins = pC0->nFanins; + return 1; + } + + // compare two cuts with different numbers + i = k = 0; + for ( c = 0; c < p->nLeafMax; c++ ) + { + if ( k == pC1->nFanins ) + { + if ( i == pC0->nFanins ) + { + pC->nFanins = c; + return 1; + } + pC->pFanins[c] = pC0->pFanins[i++]; + continue; + } + if ( i == pC0->nFanins ) + { + if ( k == pC1->nFanins ) + { + pC->nFanins = c; + return 1; + } + pC->pFanins[c] = pC1->pFanins[k++]; + continue; + } + if ( pC0->pFanins[i] < pC1->pFanins[k] ) + { + pC->pFanins[c] = pC0->pFanins[i++]; + continue; + } + if ( pC0->pFanins[i] > pC1->pFanins[k] ) + { + pC->pFanins[c] = pC1->pFanins[k++]; + continue; + } + pC->pFanins[c] = pC0->pFanins[i++]; + k++; + } + if ( i < pC0->nFanins || k < pC1->nFanins ) + return 0; + pC->nFanins = c; + return 1; +} + +/**Function************************************************************* + + Synopsis [Prepares the object for FPGA mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_CutMerge( Aig_ManCut_t * p, Aig_Cut_t * pCut0, Aig_Cut_t * pCut1, Aig_Cut_t * pCut ) +{ + assert( p->nLeafMax > 0 ); + // merge the nodes + if ( pCut0->nFanins < pCut1->nFanins ) + { + if ( !Aig_CutMergeOrdered( p, pCut1, pCut0, pCut ) ) + return 0; + } + else + { + if ( !Aig_CutMergeOrdered( p, pCut0, pCut1, pCut ) ) + return 0; + } + pCut->uSign = pCut0->uSign | pCut1->uSign; + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Cut_t * Aig_ObjPrepareCuts( Aig_ManCut_t * p, Aig_Obj_t * pObj, int fTriv ) +{ + Aig_Cut_t * pCutSet, * pCut; + int i; + // create the cutset of the node + pCutSet = (Aig_Cut_t *)Aig_MmFixedEntryFetch( p->pMemCuts ); + Aig_ObjSetCuts( p, pObj, pCutSet ); + Aig_ObjForEachCut( p, pObj, pCut, i ) + { + pCut->nFanins = 0; + pCut->iNode = pObj->Id; + pCut->nCutSize = p->nCutSize; + pCut->nLeafMax = p->nLeafMax; + } + // add unit cut if needed + if ( fTriv ) + { + pCut = pCutSet; + pCut->Cost = 0; + pCut->iNode = pObj->Id; + pCut->nFanins = 1; + pCut->pFanins[0] = pObj->Id; + pCut->uSign = Aig_ObjCutSign( pObj->Id ); + if ( p->fTruth ) + memset( Aig_CutTruth(pCut), 0xAA, sizeof(unsigned) * p->nTruthWords ); + } + return pCutSet; +} + +/**Function************************************************************* + + Synopsis [Derives cuts for one node and sweeps this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjComputeCuts( Aig_ManCut_t * p, Aig_Obj_t * pObj, int fTriv ) +{ + Aig_Cut_t * pCut0, * pCut1, * pCut, * pCutSet; + Aig_Obj_t * pFanin0 = Aig_ObjFanin0(pObj); + Aig_Obj_t * pFanin1 = Aig_ObjFanin1(pObj); + int i, k; + // the node is not processed yet + assert( Aig_ObjIsNode(pObj) ); + assert( Aig_ObjCuts(p, pObj) == NULL ); + // set up the first cut + pCutSet = Aig_ObjPrepareCuts( p, pObj, fTriv ); + // compute pair-wise cut combinations while checking table + Aig_ObjForEachCut( p, pFanin0, pCut0, i ) + if ( pCut0->nFanins > 0 ) + Aig_ObjForEachCut( p, pFanin1, pCut1, k ) + if ( pCut1->nFanins > 0 ) + { + // make sure K-feasible cut exists + if ( Kit_WordCountOnes(pCut0->uSign | pCut1->uSign) > p->nLeafMax ) + continue; + // get the next cut of this node + pCut = Aig_CutFindFree( p, pObj ); + // assemble the new cut + if ( !Aig_CutMerge( p, pCut0, pCut1, pCut ) ) + { + assert( pCut->nFanins == 0 ); + continue; + } + // check containment + if ( Aig_CutFilter( p, pObj, pCut ) ) + { + assert( pCut->nFanins == 0 ); + continue; + } + // create its truth table + if ( p->fTruth ) + Aig_CutComputeTruth( p, pCut, pCut0, pCut1, Aig_ObjFaninC0(pObj), Aig_ObjFaninC1(pObj) ); + // assign the cost + pCut->Cost = Aig_CutFindCost( p, pCut ); + assert( pCut->nFanins > 0 ); + assert( pCut->Cost > 0 ); + } +} + +/**Function************************************************************* + + Synopsis [Computes the cuts for all nodes in the static AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_ManCut_t * Aig_ComputeCuts( Aig_Man_t * pAig, int nCutsMax, int nLeafMax, int fTruth, int fVerbose ) +{ + Aig_ManCut_t * p; + Aig_Obj_t * pObj; + int i; + abctime clk = Abc_Clock(); + assert( pAig->pManCuts == NULL ); + // start the manager + p = Aig_ManCutStart( pAig, nCutsMax, nLeafMax, fTruth, fVerbose ); + // set elementary cuts at the PIs + Aig_ManForEachCi( pAig, pObj, i ) + Aig_ObjPrepareCuts( p, pObj, 1 ); + // process the nodes + Aig_ManForEachNode( pAig, pObj, i ) + Aig_ObjComputeCuts( p, pObj, 1 ); + // print stats + if ( fVerbose ) + { + int nCuts, nCutsK; + nCuts = Aig_ManCutCount( p, &nCutsK ); + printf( "Nodes = %6d. Total cuts = %6d. %d-input cuts = %6d.\n", + Aig_ManObjNum(pAig), nCuts, nLeafMax, nCutsK ); + printf( "Cut size = %2d. Truth size = %2d. Total mem = %5.2f MB ", + p->nCutSize, 4*p->nTruthWords, 1.0*Aig_MmFixedReadMemUsage(p->pMemCuts)/(1<<20) ); + ABC_PRT( "Runtime", Abc_Clock() - clk ); +/* + Aig_ManForEachNode( pAig, pObj, i ) + if ( i % 300 == 0 ) + Aig_ObjCutPrint( p, pObj ); +*/ + } + // remember the cut manager + pAig->pManCuts = p; + return p; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigDfs.c b/yosys/abc/src/aig/aig/aigDfs.c new file mode 100644 index 00000000000..d560fc29151 --- /dev/null +++ b/yosys/abc/src/aig/aig/aigDfs.c @@ -0,0 +1,1136 @@ +/**CFile**************************************************************** + + FileName [aigDfs.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [DFS traversal procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigDfs.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" +#include "misc/tim/tim.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Verifies that the objects are in a topo order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManVerifyTopoOrder( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj, * pNext; + int i, k, iBox, iTerm1, nTerms; + Aig_ManSetCioIds( p ); + Aig_ManIncrementTravId( p ); + Aig_ManForEachObj( p, pObj, i ) + { + if ( Aig_ObjIsNode(pObj) ) + { + pNext = Aig_ObjFanin0(pObj); + if ( !Aig_ObjIsTravIdCurrent(p,pNext) ) + { + printf( "Node %d has fanin %d that is not in a topological order.\n", pObj->Id, pNext->Id ); + return 0; + } + pNext = Aig_ObjFanin1(pObj); + if ( !Aig_ObjIsTravIdCurrent(p,pNext) ) + { + printf( "Node %d has fanin %d that is not in a topological order.\n", pObj->Id, pNext->Id ); + return 0; + } + } + else if ( Aig_ObjIsCo(pObj) || Aig_ObjIsBuf(pObj) ) + { + pNext = Aig_ObjFanin0(pObj); + if ( !Aig_ObjIsTravIdCurrent(p,pNext) ) + { + printf( "Node %d has fanin %d that is not in a topological order.\n", pObj->Id, pNext->Id ); + return 0; + } + } + else if ( Aig_ObjIsCi(pObj) ) + { + if ( p->pManTime ) + { + iBox = Tim_ManBoxForCi( (Tim_Man_t *)p->pManTime, Aig_ObjCioId(pObj) ); + if ( iBox >= 0 ) // this is not a true PI + { + iTerm1 = Tim_ManBoxInputFirst( (Tim_Man_t *)p->pManTime, iBox ); + nTerms = Tim_ManBoxInputNum( (Tim_Man_t *)p->pManTime, iBox ); + for ( k = 0; k < nTerms; k++ ) + { + pNext = Aig_ManCo( p, iTerm1 + k ); + assert( Tim_ManBoxForCo( (Tim_Man_t *)p->pManTime, Aig_ObjCioId(pNext) ) == iBox ); + if ( !Aig_ObjIsTravIdCurrent(p,pNext) ) + { + printf( "Box %d has input %d that is not in a topological order.\n", iBox, pNext->Id ); + return 0; + } + } + } + } + } + else if ( !Aig_ObjIsConst1(pObj) ) + assert( 0 ); + Aig_ObjSetTravIdCurrent( p, pObj ); + } + Aig_ManCleanCioIds( p ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManDfs_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( pObj == NULL ) + return; + assert( !Aig_IsComplement(pObj) ); + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( p->pEquivs && Aig_ObjEquiv(p, pObj) ) + Aig_ManDfs_rec( p, Aig_ObjEquiv(p, pObj), vNodes ); + Aig_ManDfs_rec( p, Aig_ObjFanin0(pObj), vNodes ); + Aig_ManDfs_rec( p, Aig_ObjFanin1(pObj), vNodes ); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Collects objects of the AIG in the DFS order.] + + Description [Works with choice nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManDfs( Aig_Man_t * p, int fNodesOnly ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + Aig_ManIncrementTravId( p ); + Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); + // start the array of nodes + vNodes = Vec_PtrAlloc( Aig_ManObjNumMax(p) ); + // mark PIs if they should not be collected + if ( fNodesOnly ) + Aig_ManForEachCi( p, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + else + Vec_PtrPush( vNodes, Aig_ManConst1(p) ); + // collect nodes reachable in the DFS order + Aig_ManForEachCo( p, pObj, i ) + Aig_ManDfs_rec( p, fNodesOnly? Aig_ObjFanin0(pObj): pObj, vNodes ); + if ( fNodesOnly ) + assert( Vec_PtrSize(vNodes) == Aig_ManNodeNum(p) ); + else + assert( Vec_PtrSize(vNodes) == Aig_ManObjNum(p) ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManDfsAll_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Aig_ObjIsCi(pObj) ) + { + Vec_PtrPush( vNodes, pObj ); + return; + } + if ( Aig_ObjIsCo(pObj) ) + { + Aig_ManDfsAll_rec( p, Aig_ObjFanin0(pObj), vNodes ); + Vec_PtrPush( vNodes, pObj ); + return; + } + assert( Aig_ObjIsNode(pObj) ); + Aig_ManDfsAll_rec( p, Aig_ObjFanin0(pObj), vNodes ); + Aig_ManDfsAll_rec( p, Aig_ObjFanin1(pObj), vNodes ); + Vec_PtrPush( vNodes, pObj ); +} +Vec_Ptr_t * Aig_ManDfsArray( Aig_Man_t * p, Aig_Obj_t ** pNodes, int nNodes ) +{ + Vec_Ptr_t * vNodes; + int i; + Aig_ManIncrementTravId( p ); + vNodes = Vec_PtrAlloc( Aig_ManObjNumMax(p) ); + // add constant + Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); + Vec_PtrPush( vNodes, Aig_ManConst1(p) ); + // collect nodes reachable in the DFS order + for ( i = 0; i < nNodes; i++ ) + Aig_ManDfsAll_rec( p, pNodes[i], vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Collects objects of the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManDfsAll( Aig_Man_t * p ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + Aig_ManIncrementTravId( p ); + vNodes = Vec_PtrAlloc( Aig_ManObjNumMax(p) ); + // add constant + Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); + Vec_PtrPush( vNodes, Aig_ManConst1(p) ); + // collect nodes reachable in the DFS order + Aig_ManForEachCo( p, pObj, i ) + Aig_ManDfsAll_rec( p, pObj, vNodes ); + Aig_ManForEachCi( p, pObj, i ) + if ( !Aig_ObjIsTravIdCurrent(p, pObj) ) + Vec_PtrPush( vNodes, pObj ); + assert( Vec_PtrSize(vNodes) == Aig_ManObjNum(p) ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManDfsPreorder_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( pObj == NULL ) + return; + assert( !Aig_IsComplement(pObj) ); + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + Vec_PtrPush( vNodes, pObj ); + if ( p->pEquivs && Aig_ObjEquiv(p, pObj) ) + Aig_ManDfs_rec( p, Aig_ObjEquiv(p, pObj), vNodes ); + Aig_ManDfsPreorder_rec( p, Aig_ObjFanin0(pObj), vNodes ); + Aig_ManDfsPreorder_rec( p, Aig_ObjFanin1(pObj), vNodes ); +} + +/**Function************************************************************* + + Synopsis [Collects objects of the AIG in the DFS order.] + + Description [Works with choice nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManDfsPreorder( Aig_Man_t * p, int fNodesOnly ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + Aig_ManIncrementTravId( p ); + Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); + // start the array of nodes + vNodes = Vec_PtrAlloc( Aig_ManObjNumMax(p) ); + // mark PIs if they should not be collected + if ( fNodesOnly ) + Aig_ManForEachCi( p, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + else + Vec_PtrPush( vNodes, Aig_ManConst1(p) ); + // collect nodes reachable in the DFS order + Aig_ManForEachCo( p, pObj, i ) + Aig_ManDfsPreorder_rec( p, fNodesOnly? Aig_ObjFanin0(pObj): pObj, vNodes ); + if ( fNodesOnly ) + assert( Vec_PtrSize(vNodes) == Aig_ManNodeNum(p) ); + else + assert( Vec_PtrSize(vNodes) == Aig_ManObjNum(p) ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Levelizes the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Vec_t * Aig_ManLevelize( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + Vec_Vec_t * vLevels; + int nLevels, i; + nLevels = Aig_ManLevelNum( p ); + vLevels = Vec_VecStart( nLevels + 1 ); + Aig_ManForEachObj( p, pObj, i ) + { + assert( (int)pObj->Level <= nLevels ); + Vec_VecPush( vLevels, pObj->Level, pObj ); + } + return vLevels; +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes and PIs in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManDfsNodes( Aig_Man_t * p, Aig_Obj_t ** ppNodes, int nNodes ) +{ + Vec_Ptr_t * vNodes; +// Aig_Obj_t * pObj; + int i; + Aig_ManIncrementTravId( p ); + // mark constant and PIs + Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); +// Aig_ManForEachCi( p, pObj, i ) +// Aig_ObjSetTravIdCurrent( p, pObj ); + // go through the nodes + vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) ); + for ( i = 0; i < nNodes; i++ ) + if ( Aig_ObjIsCo(ppNodes[i]) ) + Aig_ManDfs_rec( p, Aig_ObjFanin0(ppNodes[i]), vNodes ); + else + Aig_ManDfs_rec( p, ppNodes[i], vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManDfsChoices_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( pObj == NULL ) + return; + assert( !Aig_IsComplement(pObj) ); + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + assert( Aig_ObjIsNode(pObj) ); + Aig_ManDfsChoices_rec( p, Aig_ObjFanin0(pObj), vNodes ); + Aig_ManDfsChoices_rec( p, Aig_ObjFanin1(pObj), vNodes ); + Aig_ManDfsChoices_rec( p, Aig_ObjEquiv(p, pObj), vNodes ); + assert( !Aig_ObjIsTravIdCurrent(p, pObj) ); // loop detection + Aig_ObjSetTravIdCurrent(p, pObj); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManDfsChoices( Aig_Man_t * p ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i, Counter = 0; + + Aig_ManForEachNode( p, pObj, i ) + { + if ( Aig_ObjEquiv(p, pObj) == NULL ) + continue; + Counter = 0; + for ( pObj = Aig_ObjEquiv(p, pObj) ; pObj; pObj = Aig_ObjEquiv(p, pObj) ) + Counter++; +// printf( "%d ", Counter ); + } +// printf( "\n" ); + + assert( p->pEquivs != NULL ); + Aig_ManIncrementTravId( p ); + // mark constant and PIs + Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); + Aig_ManForEachCi( p, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // go through the nodes + vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) ); + Aig_ManForEachCo( p, pObj, i ) + Aig_ManDfsChoices_rec( p, Aig_ObjFanin0(pObj), vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the reverse DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManDfsReverse_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + Aig_Obj_t * pFanout; + int iFanout = -1, i; + assert( !Aig_IsComplement(pObj) ); + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + assert( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) ); + Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) + Aig_ManDfsReverse_rec( p, pFanout, vNodes ); + assert( !Aig_ObjIsTravIdCurrent(p, pObj) ); // loop detection + Aig_ObjSetTravIdCurrent(p, pObj); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the reverse DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManDfsReverse( Aig_Man_t * p ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + Aig_ManIncrementTravId( p ); + // mark POs + Aig_ManForEachCo( p, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + // go through the nodes + vNodes = Vec_PtrAlloc( Aig_ManNodeNum(p) ); + Aig_ManForEachObj( p, pObj, i ) + if ( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) ) + Aig_ManDfsReverse_rec( p, pObj, vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Computes the max number of levels in the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManLevelNum( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, LevelsMax; + LevelsMax = 0; + Aig_ManForEachCo( p, pObj, i ) + LevelsMax = Abc_MaxInt( LevelsMax, (int)Aig_ObjFanin0(pObj)->Level ); + return LevelsMax; +} + +//#if 0 + +/**Function************************************************************* + + Synopsis [Computes levels for AIG with choices and white boxes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManChoiceLevel_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pNext; + int i, iBox, iTerm1, nTerms, LevelMax = 0; + if ( Aig_ObjIsTravIdCurrent( p, pObj ) ) + return; + Aig_ObjSetTravIdCurrent( p, pObj ); + if ( Aig_ObjIsCi(pObj) ) + { + if ( p->pManTime ) + { + iBox = Tim_ManBoxForCi( (Tim_Man_t *)p->pManTime, Aig_ObjCioId(pObj) ); + if ( iBox >= 0 ) // this is not a true PI + { + iTerm1 = Tim_ManBoxInputFirst( (Tim_Man_t *)p->pManTime, iBox ); + nTerms = Tim_ManBoxInputNum( (Tim_Man_t *)p->pManTime, iBox ); + for ( i = 0; i < nTerms; i++ ) + { + pNext = Aig_ManCo(p, iTerm1 + i); + Aig_ManChoiceLevel_rec( p, pNext ); + if ( LevelMax < Aig_ObjLevel(pNext) ) + LevelMax = Aig_ObjLevel(pNext); + } + LevelMax++; + } + } +// printf( "%d ", pObj->Level ); + } + else if ( Aig_ObjIsCo(pObj) ) + { + pNext = Aig_ObjFanin0(pObj); + Aig_ManChoiceLevel_rec( p, pNext ); + if ( LevelMax < Aig_ObjLevel(pNext) ) + LevelMax = Aig_ObjLevel(pNext); + } + else if ( Aig_ObjIsNode(pObj) ) + { + // get the maximum level of the two fanins + pNext = Aig_ObjFanin0(pObj); + Aig_ManChoiceLevel_rec( p, pNext ); + if ( LevelMax < Aig_ObjLevel(pNext) ) + LevelMax = Aig_ObjLevel(pNext); + pNext = Aig_ObjFanin1(pObj); + Aig_ManChoiceLevel_rec( p, pNext ); + if ( LevelMax < Aig_ObjLevel(pNext) ) + LevelMax = Aig_ObjLevel(pNext); + LevelMax++; + + // get the level of the nodes in the choice node + if ( p->pEquivs && (pNext = Aig_ObjEquiv(p, pObj)) ) + { + Aig_ManChoiceLevel_rec( p, pNext ); + if ( LevelMax < Aig_ObjLevel(pNext) ) + LevelMax = Aig_ObjLevel(pNext); + } + } + else if ( !Aig_ObjIsConst1(pObj) ) + assert( 0 ); + Aig_ObjSetLevel( pObj, LevelMax ); +} + +/**Function************************************************************* + + Synopsis [Computes levels for AIG with choices and white boxes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManChoiceLevel( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, LevelMax = 0; + Aig_ManForEachObj( p, pObj, i ) + Aig_ObjSetLevel( pObj, 0 ); + Aig_ManSetCioIds( p ); + Aig_ManIncrementTravId( p ); + Aig_ManForEachCo( p, pObj, i ) + { + Aig_ManChoiceLevel_rec( p, pObj ); + if ( LevelMax < Aig_ObjLevel(pObj) ) + LevelMax = Aig_ObjLevel(pObj); + } + // account for dangling boxes + Aig_ManForEachCi( p, pObj, i ) + { + Aig_ManChoiceLevel_rec( p, pObj ); + if ( LevelMax < Aig_ObjLevel(pObj) ) + LevelMax = Aig_ObjLevel(pObj); + } + Aig_ManCleanCioIds( p ); +// Aig_ManForEachNode( p, pObj, i ) +// assert( Aig_ObjLevel(pObj) > 0 ); + return LevelMax; +} + +//#endif + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ConeMark_rec( Aig_Obj_t * pObj ) +{ + assert( !Aig_IsComplement(pObj) ); + if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) + return; + Aig_ConeMark_rec( Aig_ObjFanin0(pObj) ); + Aig_ConeMark_rec( Aig_ObjFanin1(pObj) ); + assert( !Aig_ObjIsMarkA(pObj) ); // loop detection + Aig_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ConeCleanAndMark_rec( Aig_Obj_t * pObj ) +{ + assert( !Aig_IsComplement(pObj) ); + if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) + return; + Aig_ConeCleanAndMark_rec( Aig_ObjFanin0(pObj) ); + Aig_ConeCleanAndMark_rec( Aig_ObjFanin1(pObj) ); + assert( !Aig_ObjIsMarkA(pObj) ); // loop detection + Aig_ObjSetMarkA( pObj ); + pObj->pData = NULL; +} + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ConeCountAndMark_rec( Aig_Obj_t * pObj ) +{ + int Counter; + assert( !Aig_IsComplement(pObj) ); + if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) + return 0; + Counter = 1 + Aig_ConeCountAndMark_rec( Aig_ObjFanin0(pObj) ) + + Aig_ConeCountAndMark_rec( Aig_ObjFanin1(pObj) ); + assert( !Aig_ObjIsMarkA(pObj) ); // loop detection + Aig_ObjSetMarkA( pObj ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ConeUnmark_rec( Aig_Obj_t * pObj ) +{ + assert( !Aig_IsComplement(pObj) ); + if ( !Aig_ObjIsNode(pObj) || !Aig_ObjIsMarkA(pObj) ) + return; + Aig_ConeUnmark_rec( Aig_ObjFanin0(pObj) ); + Aig_ConeUnmark_rec( Aig_ObjFanin1(pObj) ); + assert( Aig_ObjIsMarkA(pObj) ); // loop detection + Aig_ObjClearMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_DagSize( Aig_Obj_t * pObj ) +{ + int Counter; + Counter = Aig_ConeCountAndMark_rec( Aig_Regular(pObj) ); + Aig_ConeUnmark_rec( Aig_Regular(pObj) ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the support size of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_SupportSize_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int * pCounter ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Aig_ObjIsCi(pObj) ) + { + (*pCounter)++; + return; + } + assert( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) ); + Aig_SupportSize_rec( p, Aig_ObjFanin0(pObj), pCounter ); + if ( Aig_ObjFanin1(pObj) ) + Aig_SupportSize_rec( p, Aig_ObjFanin1(pObj), pCounter ); +} + +/**Function************************************************************* + + Synopsis [Counts the support size of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_SupportSize( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + int Counter = 0; + assert( !Aig_IsComplement(pObj) ); + assert( !Aig_ObjIsCo(pObj) ); + Aig_ManIncrementTravId( p ); + Aig_SupportSize_rec( p, pObj, &Counter ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the support size of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_SupportSizeTest( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + abctime clk = Abc_Clock(); + Aig_ManForEachObj( p, pObj, i ) + if ( Aig_ObjIsNode(pObj) ) + Counter += (Aig_SupportSize(p, pObj) <= 16); + printf( "Nodes with small support %d (out of %d)\n", Counter, Aig_ManNodeNum(p) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the support size of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_Support_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vSupp ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Aig_ObjIsConst1(pObj) ) + return; + if ( Aig_ObjIsCi(pObj) ) + { + Vec_PtrPush( vSupp, pObj ); + return; + } + assert( Aig_ObjIsNode(pObj) || Aig_ObjIsBuf(pObj) ); + Aig_Support_rec( p, Aig_ObjFanin0(pObj), vSupp ); + if ( Aig_ObjFanin1(pObj) ) + Aig_Support_rec( p, Aig_ObjFanin1(pObj), vSupp ); +} + +/**Function************************************************************* + + Synopsis [Counts the support size of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_Support( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Vec_Ptr_t * vSupp; + assert( !Aig_IsComplement(pObj) ); + assert( !Aig_ObjIsCo(pObj) ); + Aig_ManIncrementTravId( p ); + vSupp = Vec_PtrAlloc( 100 ); + Aig_Support_rec( p, pObj, vSupp ); + return vSupp; +} + +/**Function************************************************************* + + Synopsis [Counts the support size of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_SupportNodes( Aig_Man_t * p, Aig_Obj_t ** ppObjs, int nObjs, Vec_Ptr_t * vSupp ) +{ + int i; + Vec_PtrClear( vSupp ); + Aig_ManIncrementTravId( p ); + Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); + for ( i = 0; i < nObjs; i++ ) + { + assert( !Aig_IsComplement(ppObjs[i]) ); + if ( Aig_ObjIsCo(ppObjs[i]) ) + Aig_Support_rec( p, Aig_ObjFanin0(ppObjs[i]), vSupp ); + else + Aig_Support_rec( p, ppObjs[i], vSupp ); + } +} + +/**Function************************************************************* + + Synopsis [Transfers the AIG from one manager into another.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_Transfer_rec( Aig_Man_t * pDest, Aig_Obj_t * pObj ) +{ + assert( !Aig_IsComplement(pObj) ); + if ( !Aig_ObjIsNode(pObj) || Aig_ObjIsMarkA(pObj) ) + return; + Aig_Transfer_rec( pDest, Aig_ObjFanin0(pObj) ); + Aig_Transfer_rec( pDest, Aig_ObjFanin1(pObj) ); + pObj->pData = Aig_And( pDest, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + assert( !Aig_ObjIsMarkA(pObj) ); // loop detection + Aig_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Transfers the AIG from one manager into another.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_Transfer( Aig_Man_t * pSour, Aig_Man_t * pDest, Aig_Obj_t * pRoot, int nVars ) +{ + Aig_Obj_t * pObj; + int i; + // solve simple cases + if ( pSour == pDest ) + return pRoot; + if ( Aig_ObjIsConst1( Aig_Regular(pRoot) ) ) + return Aig_NotCond( Aig_ManConst1(pDest), Aig_IsComplement(pRoot) ); + // set the PI mapping + Aig_ManForEachCi( pSour, pObj, i ) + { + if ( i == nVars ) + break; + pObj->pData = Aig_IthVar(pDest, i); + } + // transfer and set markings + Aig_Transfer_rec( pDest, Aig_Regular(pRoot) ); + // clear the markings + Aig_ConeUnmark_rec( Aig_Regular(pRoot) ); + return Aig_NotCond( (Aig_Obj_t *)Aig_Regular(pRoot)->pData, Aig_IsComplement(pRoot) ); +} + +/**Function************************************************************* + + Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_Compose_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFunc, Aig_Obj_t * pVar ) +{ + assert( !Aig_IsComplement(pObj) ); + if ( Aig_ObjIsMarkA(pObj) ) + return; + if ( Aig_ObjIsConst1(pObj) || Aig_ObjIsCi(pObj) ) + { + pObj->pData = pObj == pVar ? pFunc : pObj; + return; + } + Aig_Compose_rec( p, Aig_ObjFanin0(pObj), pFunc, pVar ); + Aig_Compose_rec( p, Aig_ObjFanin1(pObj), pFunc, pVar ); + pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + assert( !Aig_ObjIsMarkA(pObj) ); // loop detection + Aig_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_Compose( Aig_Man_t * p, Aig_Obj_t * pRoot, Aig_Obj_t * pFunc, int iVar ) +{ + // quit if the PI variable is not defined + if ( iVar >= Aig_ManCiNum(p) ) + { + printf( "Aig_Compose(): The PI variable %d is not defined.\n", iVar ); + return NULL; + } + // recursively perform composition + Aig_Compose_rec( p, Aig_Regular(pRoot), pFunc, Aig_ManCi(p, iVar) ); + // clear the markings + Aig_ConeUnmark_rec( Aig_Regular(pRoot) ); + return Aig_NotCond( (Aig_Obj_t *)Aig_Regular(pRoot)->pData, Aig_IsComplement(pRoot) ); +} + +/**Function************************************************************* + + Synopsis [Computes the internal nodes of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjCollectCut_rec( Aig_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ +// Aig_Obj_t * pFan0 = Aig_ObjFanin0(pNode); +// Aig_Obj_t * pFan1 = Aig_ObjFanin1(pNode); + if ( pNode->fMarkA ) + return; + pNode->fMarkA = 1; + assert( Aig_ObjIsNode(pNode) ); + Aig_ObjCollectCut_rec( Aig_ObjFanin0(pNode), vNodes ); + Aig_ObjCollectCut_rec( Aig_ObjFanin1(pNode), vNodes ); + Vec_PtrPush( vNodes, pNode ); +//printf( "added %d ", pNode->Id ); +} + +/**Function************************************************************* + + Synopsis [Computes the internal nodes of the cut.] + + Description [Does not include the leaves of the cut.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjCollectCut( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes ) +{ + Aig_Obj_t * pObj; + int i; + // collect and mark the leaves + Vec_PtrClear( vNodes ); + Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i ) + { + assert( pObj->fMarkA == 0 ); + pObj->fMarkA = 1; +// printf( "%d " , pObj->Id ); + } +//printf( "\n" ); + // collect and mark the nodes + Aig_ObjCollectCut_rec( pRoot, vNodes ); + // clean the nodes + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + pObj->fMarkA = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i ) + pObj->fMarkA = 0; +} + + +/**Function************************************************************* + + Synopsis [Collects the nodes of the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjCollectSuper_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) +{ + int RetValue1, RetValue2, i; + // check if the node is visited + if ( Aig_Regular(pObj)->fMarkA ) + { + // check if the node occurs in the same polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == pObj ) + return 1; + // check if the node is present in the opposite polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == Aig_Not(pObj) ) + return -1; + assert( 0 ); + return 0; + } + // if the new node is complemented or a PI, another gate begins + if ( pObj != pRoot && (Aig_IsComplement(pObj) || Aig_ObjType(pObj) != Aig_ObjType(pRoot) || Aig_ObjRefs(pObj) > 1) ) + { + Vec_PtrPush( vSuper, pObj ); + Aig_Regular(pObj)->fMarkA = 1; + return 0; + } + assert( !Aig_IsComplement(pObj) ); + assert( Aig_ObjIsNode(pObj) ); + // go through the branches + RetValue1 = Aig_ObjCollectSuper_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild0(pObj) ), vSuper ); + RetValue2 = Aig_ObjCollectSuper_rec( pRoot, Aig_ObjReal_rec( Aig_ObjChild1(pObj) ), vSuper ); + if ( RetValue1 == -1 || RetValue2 == -1 ) + return -1; + // return 1 if at least one branch has a duplicate + return RetValue1 || RetValue2; +} + +/**Function************************************************************* + + Synopsis [Collects the nodes of the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjCollectSuper( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) +{ + int RetValue, i; + assert( !Aig_IsComplement(pObj) ); + assert( Aig_ObjIsNode(pObj) ); + // collect the nodes in the implication supergate + Vec_PtrClear( vSuper ); + RetValue = Aig_ObjCollectSuper_rec( pObj, pObj, vSuper ); + assert( Vec_PtrSize(vSuper) > 1 ); + // unmark the visited nodes + Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pObj, i ) + Aig_Regular(pObj)->fMarkA = 0; + // if we found the node and its complement in the same implication supergate, + // return empty set of nodes (meaning that we should use constant-0 node) + if ( RetValue == -1 ) + vSuper->nSize = 0; + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigDoms.c b/yosys/abc/src/aig/aig/aigDoms.c new file mode 100644 index 00000000000..7e3bc504012 --- /dev/null +++ b/yosys/abc/src/aig/aig/aigDoms.c @@ -0,0 +1,1154 @@ +/**CFile**************************************************************** + + FileName [aigDoms.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Computing multi-output dominators.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigDoms.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" +#include "aig/saig/saig.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Aig_Sto_t_ Aig_Sto_t; +typedef struct Aig_Dom_t_ Aig_Dom_t; + +struct Aig_Dom_t_ +{ + int uSign; // signature + int nNodes; // the number of nodes + int pNodes[0]; // the nodes +}; + +struct Aig_Sto_t_ +{ + int Limit; + Aig_Man_t * pAig; // user's AIG + Aig_MmFixed_t * pMem; // memory manager for dominators + Vec_Ptr_t * vDoms; // dominators + Vec_Int_t * vFans; // temporary fanouts + Vec_Int_t * vTimes; // the number of times each appears + int nDomNodes; // nodes with dominators + int nDomsTotal; // total dominators + int nDomsFilter1; // filtered dominators + int nDomsFilter2; // filtered dominators +}; + +#define Aig_DomForEachNode( pAig, pDom, pNode, i ) \ + for ( i = 0; (i < pDom->nNodes) && ((pNode) = Aig_ManObj(pAig, (pDom)->pNodes[i])); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates dominator manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Sto_t * Aig_ManDomStart( Aig_Man_t * pAig, int Limit ) +{ + Aig_Sto_t * pSto; + pSto = ABC_CALLOC( Aig_Sto_t, 1 ); + pSto->pAig = pAig; + pSto->Limit = Limit; + pSto->pMem = Aig_MmFixedStart( sizeof(Aig_Dom_t) + sizeof(int) * Limit, 10000 ); + pSto->vDoms = Vec_PtrStart( Aig_ManObjNumMax(pAig) ); + pSto->vFans = Vec_IntAlloc( 100 ); + pSto->vTimes = Vec_IntStart( Aig_ManObjNumMax(pAig) ); + return pSto; +} + +/**Function************************************************************* + + Synopsis [Adds trivial dominator.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjAddTriv( Aig_Sto_t * pSto, int Id, Vec_Ptr_t * vDoms ) +{ + Aig_Dom_t * pDom; + pDom = (Aig_Dom_t *)Aig_MmFixedEntryFetch( pSto->pMem ); + pDom->uSign = (1 << (Id % 63)); + pDom->nNodes = 1; + pDom->pNodes[0] = Id; + Vec_PtrPushFirst( vDoms, pDom ); + assert( Vec_PtrEntry( pSto->vDoms, Id ) == NULL ); + Vec_PtrWriteEntry( pSto->vDoms, Id, vDoms ); +} + +/**Function************************************************************* + + Synopsis [Duplicates vector of doms.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ObjDomVecDup( Aig_Sto_t * pSto, Vec_Ptr_t * vDoms, int fSkip1 ) +{ + Vec_Ptr_t * vDoms2; + Aig_Dom_t * pDom, * pDom2; + int i; + vDoms2 = Vec_PtrAlloc( 0 ); + Vec_PtrForEachEntryStart( Aig_Dom_t *, vDoms, pDom, i, fSkip1 ) + { + pDom2 = (Aig_Dom_t *)Aig_MmFixedEntryFetch( pSto->pMem ); + memcpy( pDom2, pDom, sizeof(Aig_Dom_t) + sizeof(int) * pSto->Limit ); + Vec_PtrPush( vDoms2, pDom2 ); + } + return vDoms2; +} + +/**Function************************************************************* + + Synopsis [Recycles vector of doms.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjDomVecRecycle( Aig_Sto_t * pSto, Vec_Ptr_t * vDoms ) +{ + Aig_Dom_t * pDom; + int i; + Vec_PtrForEachEntry( Aig_Dom_t *, vDoms, pDom, i ) + Aig_MmFixedEntryRecycle( pSto->pMem, (char *)pDom ); + Vec_PtrFree( vDoms ); +} + +/**Function************************************************************* + + Synopsis [Duplicates the vector of doms.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjDomPrint( Aig_Sto_t * pSto, Aig_Dom_t * pDom, int Num ) +{ + int k; + printf( "%4d : {", Num ); + for ( k = 0; k < pDom->nNodes; k++ ) + printf( " %4d", pDom->pNodes[k] ); + for ( ; k < pSto->Limit; k++ ) + printf( " " ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [Duplicates the vector of doms.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjDomVecPrint( Aig_Sto_t * pSto, Vec_Ptr_t * vDoms ) +{ + Aig_Dom_t * pDom; + int i; + Vec_PtrForEachEntry( Aig_Dom_t *, vDoms, pDom, i ) + Aig_ObjDomPrint( pSto, pDom, i ); +} + +/**Function************************************************************* + + Synopsis [Computes multi-node dominators.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManDomPrint( Aig_Sto_t * pSto ) +{ + Aig_Obj_t * pObj; + int i; + Saig_ManForEachPi( pSto->pAig, pObj, i ) + { + printf( "*** PI %4d %4d :\n", i, pObj->Id ); + Aig_ObjDomVecPrint( pSto, (Vec_Ptr_t *)Vec_PtrEntry(pSto->vDoms, pObj->Id) ); + } +} + +/**Function************************************************************* + + Synopsis [Divides the circuit into well-balanced parts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManDomStop( Aig_Sto_t * pSto ) +{ + Vec_Ptr_t * vDoms; + int i; + Vec_PtrForEachEntry( Vec_Ptr_t *, pSto->vDoms, vDoms, i ) + if ( vDoms ) + Aig_ObjDomVecRecycle( pSto, vDoms ); + Vec_PtrFree( pSto->vDoms ); + Vec_IntFree( pSto->vFans ); + Vec_IntFree( pSto->vTimes ); + Aig_MmFixedStop( pSto->pMem, 0 ); + ABC_FREE( pSto ); +} + + +/**Function************************************************************* + + Synopsis [Checks correctness of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjDomCheck( Aig_Dom_t * pDom ) +{ + int i; + for ( i = 1; i < pDom->nNodes; i++ ) + { + if ( pDom->pNodes[i-1] >= pDom->pNodes[i] ) + { + Abc_Print( -1, "Aig_ObjDomCheck(): Cut has wrong ordering of inputs.\n" ); + return 0; + } + assert( pDom->pNodes[i-1] < pDom->pNodes[i] ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pDom is contained in pCut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_ObjDomCheckDominance( Aig_Dom_t * pDom, Aig_Dom_t * pCut ) +{ + int i, k; + for ( i = 0; i < pDom->nNodes; i++ ) + { + for ( k = 0; k < (int)pCut->nNodes; k++ ) + if ( pDom->pNodes[i] == pCut->pNodes[k] ) + break; + if ( k == (int)pCut->nNodes ) // node i in pDom is not contained in pCut + return 0; + } + // every node in pDom is contained in pCut + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the cut is contained.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjDomFilter( Aig_Sto_t * pSto, Vec_Ptr_t * vDoms, Aig_Dom_t * pDom ) +{ + Aig_Dom_t * pTemp; + int i; + Vec_PtrForEachEntry( Aig_Dom_t *, vDoms, pTemp, i ) + { + if ( pTemp->nNodes > pDom->nNodes ) + { + // do not fiter the first cut + if ( i == 0 ) + continue; + // skip the non-contained cuts + if ( (pTemp->uSign & pDom->uSign) != pDom->uSign ) + continue; + // check containment seriously + if ( Aig_ObjDomCheckDominance( pDom, pTemp ) ) + { + Vec_PtrRemove( vDoms, pTemp ); + Aig_MmFixedEntryRecycle( pSto->pMem, (char *)pTemp ); + i--; + pSto->nDomsFilter1++; + } + } + else + { + // skip the non-contained cuts + if ( (pTemp->uSign & pDom->uSign) != pTemp->uSign ) + continue; + // check containment seriously + if ( Aig_ObjDomCheckDominance( pTemp, pDom ) ) + { + pSto->nDomsFilter2++; + return 1; + } + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Merges two cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_ObjDomMergeOrdered( Aig_Dom_t * pD0, Aig_Dom_t * pD1, Aig_Dom_t * pD, int Limit ) +{ + int i, k, c; + assert( pD0->nNodes >= pD1->nNodes ); + // the case of the largest cut sizes + if ( pD0->nNodes == Limit && pD1->nNodes == Limit ) + { + for ( i = 0; i < pD0->nNodes; i++ ) + if ( pD0->pNodes[i] != pD1->pNodes[i] ) + return 0; + for ( i = 0; i < pD0->nNodes; i++ ) + pD->pNodes[i] = pD0->pNodes[i]; + pD->nNodes = pD0->nNodes; + return 1; + } + // the case when one of the cuts is the largest + if ( pD0->nNodes == Limit ) + { + for ( i = 0; i < pD1->nNodes; i++ ) + { + for ( k = pD0->nNodes - 1; k >= 0; k-- ) + if ( pD0->pNodes[k] == pD1->pNodes[i] ) + break; + if ( k == -1 ) // did not find + return 0; + } + for ( i = 0; i < pD0->nNodes; i++ ) + pD->pNodes[i] = pD0->pNodes[i]; + pD->nNodes = pD0->nNodes; + return 1; + } + + // compare two cuts with different numbers + i = k = 0; + for ( c = 0; c < (int)Limit; c++ ) + { + if ( k == pD1->nNodes ) + { + if ( i == pD0->nNodes ) + { + pD->nNodes = c; + return 1; + } + pD->pNodes[c] = pD0->pNodes[i++]; + continue; + } + if ( i == pD0->nNodes ) + { + if ( k == pD1->nNodes ) + { + pD->nNodes = c; + return 1; + } + pD->pNodes[c] = pD1->pNodes[k++]; + continue; + } + if ( pD0->pNodes[i] < pD1->pNodes[k] ) + { + pD->pNodes[c] = pD0->pNodes[i++]; + continue; + } + if ( pD0->pNodes[i] > pD1->pNodes[k] ) + { + pD->pNodes[c] = pD1->pNodes[k++]; + continue; + } + pD->pNodes[c] = pD0->pNodes[i++]; + k++; + } + if ( i < pD0->nNodes || k < pD1->nNodes ) + return 0; + pD->nNodes = c; + return 1; +} + +/**Function************************************************************* + + Synopsis [Prepares the object for FPGA mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjDomMergeTwo( Aig_Dom_t * pDom0, Aig_Dom_t * pDom1, Aig_Dom_t * pDom, int Limit ) +{ + assert( Limit > 0 ); + if ( pDom0->nNodes < pDom1->nNodes ) + { + if ( !Aig_ObjDomMergeOrdered( pDom1, pDom0, pDom, Limit ) ) + return 0; + } + else + { + if ( !Aig_ObjDomMergeOrdered( pDom0, pDom1, pDom, Limit ) ) + return 0; + } + pDom->uSign = pDom0->uSign | pDom1->uSign; + assert( pDom->nNodes <= Limit ); + assert( Aig_ObjDomCheck( pDom ) ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Merge two arrays of dominators.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ObjDomMerge( Aig_Sto_t * pSto, Vec_Ptr_t * vDoms0, Vec_Ptr_t * vDoms1 ) +{ + Vec_Ptr_t * vDoms; + Aig_Dom_t * pDom0, * pDom1, * pDom; + int i, k; + vDoms = Vec_PtrAlloc( 16 ); + Vec_PtrForEachEntry( Aig_Dom_t *, vDoms0, pDom0, i ) + Vec_PtrForEachEntry( Aig_Dom_t *, vDoms1, pDom1, k ) + { + if ( Aig_WordCountOnes( pDom0->uSign | pDom1->uSign ) > pSto->Limit ) + continue; + // check if the cut exists + pDom = (Aig_Dom_t *)Aig_MmFixedEntryFetch( pSto->pMem ); + if ( !Aig_ObjDomMergeTwo( pDom0, pDom1, pDom, pSto->Limit ) ) + { + Aig_MmFixedEntryRecycle( pSto->pMem, (char *)pDom ); + continue; + } + // check if this cut is contained in any of the available cuts + if ( Aig_ObjDomFilter( pSto, vDoms, pDom ) ) + { + Aig_MmFixedEntryRecycle( pSto->pMem, (char *)pDom ); + continue; + } + Vec_PtrPush( vDoms, pDom ); + } + return vDoms; +} + +/**Function************************************************************* + + Synopsis [Union two arrays of dominators.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjDomUnion( Aig_Sto_t * pSto, Vec_Ptr_t * vDoms2, Vec_Ptr_t * vDoms1 ) +{ + Aig_Dom_t * pDom1, * pDom2; + int i; + Vec_PtrForEachEntry( Aig_Dom_t *, vDoms1, pDom1, i ) + { + if ( i == 0 ) + continue; + if ( Aig_ObjDomFilter( pSto, vDoms2, pDom1 ) ) + continue; + pDom2 = (Aig_Dom_t *)Aig_MmFixedEntryFetch( pSto->pMem ); + memcpy( pDom2, pDom1, sizeof(Aig_Dom_t) + sizeof(int) * pSto->Limit ); + Vec_PtrPush( vDoms2, pDom2 ); + } +} + + +/**Function************************************************************* + + Synopsis [Computes multi-node dominators.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjDomCompute( Aig_Sto_t * pSto, Aig_Obj_t * pObj ) +{ + Vec_Ptr_t * vDoms0, * vDoms1, * vDoms2, * vDomsT; + Aig_Obj_t * pFanout; + int i, iFanout; + pSto->nDomNodes += Aig_ObjIsNode(pObj); + Vec_IntClear( pSto->vFans ); + Aig_ObjForEachFanout( pSto->pAig, pObj, pFanout, iFanout, i ) + if ( Aig_ObjIsTravIdCurrent(pSto->pAig, pFanout) ) + Vec_IntPush( pSto->vFans, iFanout>>1 ); + if ( Vec_IntSize(pSto->vFans) == 0 ) + return; + vDoms0 = (Vec_Ptr_t *)Vec_PtrEntry( pSto->vDoms, Vec_IntEntry(pSto->vFans, 0) ); + vDoms2 = Aig_ObjDomVecDup( pSto, vDoms0, 0 ); + Vec_IntForEachEntryStart( pSto->vFans, iFanout, i, 1 ) + { + vDoms1 = (Vec_Ptr_t *)Vec_PtrEntry( pSto->vDoms, iFanout ); + vDoms2 = Aig_ObjDomMerge( pSto, vDomsT = vDoms2, vDoms1 ); + Aig_ObjDomVecRecycle( pSto, vDomsT ); + } + Aig_ObjAddTriv( pSto, pObj->Id, vDoms2 ); + pSto->nDomsTotal += Vec_PtrSize(vDoms2); +} + +/**Function************************************************************* + + Synopsis [Marks the flop TFI with the current traversal ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManMarkFlopTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + int Count; + assert( !Aig_IsComplement(pObj) ); + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return 0; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) ) + return 1; + Count = Aig_ManMarkFlopTfi_rec( p, Aig_ObjFanin0(pObj) ); + if ( Aig_ObjIsNode(pObj) ) + Count += Aig_ManMarkFlopTfi_rec( p, Aig_ObjFanin1(pObj) ); + return Count; +} + +/**Function************************************************************* + + Synopsis [Marks the flop TFI with the current traversal ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManMarkFlopTfi( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManIncrementTravId( p ); + Saig_ManForEachLi( p, pObj, i ) + Aig_ManMarkFlopTfi_rec( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Computes multi-node dominators.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Sto_t * Aig_ManComputeDomsFlops( Aig_Man_t * pAig, int Limit ) +{ + Aig_Sto_t * pSto; + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + abctime clk = Abc_Clock(); + pSto = Aig_ManDomStart( pAig, Limit ); + // initialize flop inputs + Saig_ManForEachLi( pAig, pObj, i ) + Aig_ObjAddTriv( pSto, pObj->Id, Vec_PtrAlloc(1) ); + // compute internal nodes + vNodes = Aig_ManDfsReverse( pAig ); + Aig_ManMarkFlopTfi( pAig ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + if ( Aig_ObjIsTravIdCurrent(pSto->pAig, pObj) ) + Aig_ObjDomCompute( pSto, pObj ); + Vec_PtrFree( vNodes ); + // compute combinational inputs + Aig_ManForEachCi( pAig, pObj, i ) + Aig_ObjDomCompute( pSto, pObj ); + // print statistics + printf( "Nodes =%4d. Flops =%4d. Doms =%9d. Ave =%8.2f. ", + pSto->nDomNodes, Aig_ManRegNum(pSto->pAig), pSto->nDomsTotal, +// pSto->nDomsFilter1, pSto->nDomsFilter2, + 1.0 * pSto->nDomsTotal / (pSto->nDomNodes + Aig_ManRegNum(pSto->pAig)) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return pSto; +} + +/**Function************************************************************* + + Synopsis [Computes multi-node dominators.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Sto_t * Aig_ManComputeDomsPis( Aig_Man_t * pAig, int Limit ) +{ + Aig_Sto_t * pSto; + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + abctime clk = Abc_Clock(); + pSto = Aig_ManDomStart( pAig, Limit ); + // initialize flop inputs + Aig_ManForEachCo( pAig, pObj, i ) + Aig_ObjAddTriv( pSto, pObj->Id, Vec_PtrAlloc(1) ); + // compute internal nodes + vNodes = Aig_ManDfsReverse( pAig ); + Aig_ManMarkFlopTfi( pAig ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + if ( Aig_ObjIsTravIdCurrent(pSto->pAig, pObj) ) + Aig_ObjDomCompute( pSto, pObj ); + Vec_PtrFree( vNodes ); + // compute combinational inputs + Saig_ManForEachPi( pAig, pObj, i ) + Aig_ObjDomCompute( pSto, pObj ); + // print statistics + printf( "Nodes =%4d. PIs =%4d. Doms =%9d. Ave =%8.2f. ", + pSto->nDomNodes, Saig_ManPiNum(pSto->pAig), pSto->nDomsTotal, +// pSto->nDomsFilter1, pSto->nDomsFilter2, + 1.0 * pSto->nDomsTotal / (pSto->nDomNodes + Saig_ManPiNum(pSto->pAig)) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return pSto; +} + +/**Function************************************************************* + + Synopsis [Computes multi-node dominators.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Sto_t * Aig_ManComputeDomsNodes( Aig_Man_t * pAig, int Limit ) +{ + Aig_Sto_t * pSto; + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + abctime clk = Abc_Clock(); + pSto = Aig_ManDomStart( pAig, Limit ); + // initialize flop inputs + Aig_ManForEachCo( pAig, pObj, i ) + Aig_ObjAddTriv( pSto, pObj->Id, Vec_PtrAlloc(1) ); + // compute internal nodes + vNodes = Aig_ManDfsReverse( pAig ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + Aig_ObjDomCompute( pSto, pObj ); + Vec_PtrFree( vNodes ); + // compute combinational inputs + Aig_ManForEachCi( pAig, pObj, i ) + Aig_ObjDomCompute( pSto, pObj ); + // print statistics + printf( "Nodes =%6d. Doms =%9d. Ave =%8.2f. ", + pSto->nDomNodes, pSto->nDomsTotal, +// pSto->nDomsFilter1, pSto->nDomsFilter2, + 1.0 * pSto->nDomsTotal / pSto->nDomNodes ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return pSto; +} + +/**Function************************************************************* + + Synopsis [Collects dominators from the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ObjDomCollect( Aig_Sto_t * pSto, Vec_Int_t * vCut ) +{ + Vec_Ptr_t * vDoms0, * vDoms1, * vDoms2; + int i, ObjId; + vDoms0 = (Vec_Ptr_t *)Vec_PtrEntry( pSto->vDoms, Vec_IntEntry(vCut, 0) ); + vDoms2 = Aig_ObjDomVecDup( pSto, vDoms0, 1 ); + Vec_IntForEachEntryStart( vCut, ObjId, i, 1 ) + { + vDoms1 = (Vec_Ptr_t *)Vec_PtrEntry( pSto->vDoms, ObjId ); + if ( vDoms1 == NULL ) + continue; + Aig_ObjDomUnion( pSto, vDoms2, vDoms1 ); + } + return vDoms2; +} + + +/**Function************************************************************* + + Synopsis [Marks the flop TFI with the current traversal ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjDomVolume_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + int Count; + assert( !Aig_IsComplement(pObj) ); + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return 0; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( pObj->fMarkA ) + return 1; +// assert( !Aig_ObjIsCi(pObj) && !Aig_ObjIsConst1(pObj) ); + if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) ) + return 1; + Count = Aig_ObjDomVolume_rec( p, Aig_ObjFanin0(pObj) ); + if ( Aig_ObjIsNode(pObj) ) + Count += Aig_ObjDomVolume_rec( p, Aig_ObjFanin1(pObj) ); + return Count; +} + +/**Function************************************************************* + + Synopsis [Count the number of nodes in the dominator.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjDomVolume( Aig_Sto_t * pSto, Aig_Dom_t * pDom ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + Aig_ManIncrementTravId( pSto->pAig ); + Aig_DomForEachNode( pSto->pAig, pDom, pObj, i ) + Counter += Aig_ObjDomVolume_rec( pSto->pAig, pObj ); + return Counter; +} + + + + +/**Function************************************************************* + + Synopsis [Dereferences the node's MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjDomDeref_rec( Aig_Obj_t * pNode ) +{ + int Counter = 0; + assert( pNode->nRefs > 0 ); + if ( --pNode->nRefs > 0 ) + return 0; + assert( pNode->nRefs == 0 ); + if ( pNode->fMarkA ) + return 1; + if ( Aig_ObjIsCi(pNode) ) + return 0; + Counter += Aig_ObjDomDeref_rec( Aig_ObjFanin0(pNode) ); + if ( Aig_ObjIsNode(pNode) ) + Counter += Aig_ObjDomDeref_rec( Aig_ObjFanin1(pNode) ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [References the node's MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjDomRef_rec( Aig_Obj_t * pNode ) +{ + int Counter = 0; + assert( pNode->nRefs >= 0 ); + if ( pNode->nRefs++ > 0 ) + return 0; + assert( pNode->nRefs == 1 ); + if ( pNode->fMarkA ) + return 1; + if ( Aig_ObjIsCi(pNode) ) + return 0; + Counter += Aig_ObjDomRef_rec( Aig_ObjFanin0(pNode) ); + if ( Aig_ObjIsNode(pNode) ) + Counter += Aig_ObjDomRef_rec( Aig_ObjFanin1(pNode) ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Count the number of nodes in the dominator.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjDomDomed( Aig_Sto_t * pSto, Aig_Dom_t * pDom ) +{ + Aig_Obj_t * pObj; + int i, Counter0, Counter1; + Counter0 = 0; + Aig_DomForEachNode( pSto->pAig, pDom, pObj, i ) + { + assert( !Aig_ObjIsCi(pObj) ); + Counter0 += Aig_ObjDomDeref_rec( Aig_ObjFanin0(pObj) ); + if ( Aig_ObjIsNode(pObj) ) + Counter0 += Aig_ObjDomDeref_rec( Aig_ObjFanin1(pObj) ); + } + Counter1 = 0; + Aig_DomForEachNode( pSto->pAig, pDom, pObj, i ) + { + assert( !Aig_ObjIsCi(pObj) ); + Counter1 += Aig_ObjDomRef_rec( Aig_ObjFanin0(pObj) ); + if ( Aig_ObjIsNode(pObj) ) + Counter1 += Aig_ObjDomRef_rec( Aig_ObjFanin1(pObj) ); + } + assert( Counter0 == Counter1 ); + return Counter0; +} + + +/**Function************************************************************* + + Synopsis [Collects dominators from the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Aig_ObjDomCollectLos( Aig_Sto_t * pSto ) +{ + Vec_Int_t * vCut; + Aig_Obj_t * pObj; + int i; + vCut = Vec_IntAlloc( Aig_ManRegNum(pSto->pAig) ); + Saig_ManForEachLo( pSto->pAig, pObj, i ) + { + Vec_IntPush( vCut, pObj->Id ); + pObj->fMarkA = 1; + } + return vCut; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjPoLogicDeref( Aig_Sto_t * pSto ) +{ + Aig_Obj_t * pObj; + int i; + Saig_ManForEachPo( pSto->pAig, pObj, i ) + Aig_ObjDomDeref_rec( Aig_ObjFanin0(pObj) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjPoLogicRef( Aig_Sto_t * pSto ) +{ + Aig_Obj_t * pObj; + int i; + Saig_ManForEachPo( pSto->pAig, pObj, i ) + Aig_ObjDomRef_rec( Aig_ObjFanin0(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Collects dominators from the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjDomFindGood( Aig_Sto_t * pSto ) +{ + Aig_Dom_t * pDom; + Vec_Int_t * vCut; + Vec_Ptr_t * vDoms; + int i; + vCut = Aig_ObjDomCollectLos( pSto ); + vDoms = Aig_ObjDomCollect( pSto, vCut ); + Vec_IntFree( vCut ); + printf( "The cut has %d non-trivial %d-dominators.\n", Vec_PtrSize(vDoms), pSto->Limit ); + + Aig_ObjPoLogicDeref( pSto ); + Vec_PtrForEachEntry( Aig_Dom_t *, vDoms, pDom, i ) + { +// if ( Aig_ObjDomDomed(pSto, pDom) <= 1 ) +// continue; + printf( "Vol =%3d. ", Aig_ObjDomVolume(pSto, pDom) ); + printf( "Dom =%3d. ", Aig_ObjDomDomed(pSto, pDom) ); + Aig_ObjDomPrint( pSto, pDom, i ); + } + Aig_ObjPoLogicRef( pSto ); + + Aig_ObjDomVecRecycle( pSto, vDoms ); + Aig_ManCleanMarkA( pSto->pAig ); +} + + +/**Function************************************************************* + + Synopsis [Computes multi-node dominators.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManComputeDomsTest2( Aig_Man_t * pAig, int Num ) +{ + Aig_Sto_t * pSto; +// int i; +//Aig_ManShow( pAig, 0, NULL ); + Aig_ManFanoutStart( pAig ); +// for ( i = 1; i < 9; i++ ) + { + printf( "ITERATION %d:\n", Num ); + pSto = Aig_ManComputeDomsFlops( pAig, Num ); + Aig_ObjDomFindGood( pSto ); +// Aig_ManDomPrint( pSto ); + Aig_ManDomStop( pSto ); + } + Aig_ManFanoutStop( pAig ); +} + +/**Function************************************************************* + + Synopsis [Computes multi-node dominators.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManComputeDomsTest( Aig_Man_t * pAig ) +{ + Aig_Sto_t * pSto; + Aig_ManFanoutStart( pAig ); + pSto = Aig_ManComputeDomsPis( pAig, 1 ); + Aig_ManDomPrint( pSto ); + Aig_ManDomStop( pSto ); + Aig_ManFanoutStop( pAig ); +} + + + + + +/**Function************************************************************* + + Synopsis [Collects dominators from the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjDomCount( Aig_Sto_t * pSto, Aig_Obj_t * pObj ) +{ + Aig_Dom_t * pDom; + Aig_Obj_t * pFanout; + Vec_Int_t * vSingles; + Vec_Ptr_t * vDoms; + int i, k, Entry, iFanout, fPrint = 0; + vSingles = Vec_IntAlloc( 100 ); + // for each dominator of a fanout, count how many fanouts have it as a dominator + Aig_ObjForEachFanout( pSto->pAig, pObj, pFanout, iFanout, i ) + { + vDoms = (Vec_Ptr_t *)Vec_PtrEntry( pSto->vDoms, Aig_ObjId(pFanout) ); + Vec_PtrForEachEntryStart( Aig_Dom_t *, vDoms, pDom, k, 1 ) + { +// printf( "Fanout %d Dominator %d\n", Aig_ObjId(pFanout), pDom->pNodes[0] ); + Vec_IntAddToEntry( pSto->vTimes, pDom->pNodes[0], 1 ); + Vec_IntPushUnique( vSingles, pDom->pNodes[0] ); + } + } + // clear storage + Vec_IntForEachEntry( vSingles, Entry, i ) + { + if ( Vec_IntEntry(pSto->vTimes, Entry) > 5 ) + { + if ( fPrint == 0 ) + { + printf( "%6d : Level =%4d. Fanout =%6d.\n", + Aig_ObjId(pObj), Aig_ObjLevel(pObj), Aig_ObjRefs(pObj) ); + } + fPrint = 1; + printf( "%d(%d) ", Entry, Vec_IntEntry(pSto->vTimes, Entry) ); + } + Vec_IntWriteEntry( pSto->vTimes, Entry, 0); + } + if ( fPrint ) + printf( "\n" ); + Vec_IntFree( vSingles ); +} + + +/**Function************************************************************* + + Synopsis [Computes multi-node dominators.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManComputeDomsForCofactoring( Aig_Man_t * pAig ) +{ + Vec_Ptr_t * vDoms; + Aig_Sto_t * pSto; + Aig_Obj_t * pObj; + int i; + Aig_ManFanoutStart( pAig ); + pSto = Aig_ManComputeDomsNodes( pAig, 1 ); + Aig_ManForEachObj( pAig, pObj, i ) + { + if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) ) + continue; + if ( Aig_ObjRefs(pObj) < 10 ) + continue; + vDoms = (Vec_Ptr_t *)Vec_PtrEntry( pSto->vDoms, Aig_ObjId(pObj) ); +// printf( "%6d : Level =%4d. Fanout =%6d.\n", +// Aig_ObjId(pObj), Aig_ObjLevel(pObj), Aig_ObjRefs(pObj) ); + + Aig_ObjDomCount( pSto, pObj ); + } + Aig_ManDomStop( pSto ); + Aig_ManFanoutStop( pAig ); +} + + + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigDup.c b/yosys/abc/src/aig/aig/aigDup.c new file mode 100644 index 00000000000..234192cb85f --- /dev/null +++ b/yosys/abc/src/aig/aig/aigDup.c @@ -0,0 +1,1335 @@ +/**CFile**************************************************************** + + FileName [aigDup.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [AIG duplication (re-strashing).] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigDup.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig/saig/saig.h" +#include "misc/tim/tim.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager.] + + Description [Orders nodes as follows: PIs, ANDs, POs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupSimple( Aig_Man_t * p ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pObjNew = NULL; + int i; + assert( p->pManTime == NULL ); + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nAsserts = p->nAsserts; + pNew->nConstrs = p->nConstrs; + pNew->nBarBufs = p->nBarBufs; + if ( p->vFlopNums ) + pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); + // create the PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachCi( p, pObj, i ) + { + pObjNew = Aig_ObjCreateCi( pNew ); + pObjNew->Level = pObj->Level; + pObj->pData = pObjNew; + } + // duplicate internal nodes + Aig_ManForEachObj( p, pObj, i ) + if ( Aig_ObjIsBuf(pObj) ) + { + pObjNew = Aig_ObjChild0Copy(pObj); + pObj->pData = pObjNew; + } + else if ( Aig_ObjIsNode(pObj) ) + { + pObjNew = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + pObj->pData = pObjNew; + } + // add the POs + Aig_ManForEachCo( p, pObj, i ) + { + pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + pObj->pData = pObjNew; + } + assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) ); + Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); + // check the resulting network + if ( !Aig_ManCheck(pNew) ) + printf( "Aig_ManDupSimple(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Derives AIG with hints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupSimpleWithHints( Aig_Man_t * p, Vec_Int_t * vHints ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj = NULL; + int i, Entry; + assert( p->nAsserts == 0 || p->nConstrs == 0 ); + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + // create the PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachCi( p, pObj, i ) + { + pObj->pData = Aig_ObjCreateCi( pNew ); + Entry = Vec_IntEntry( vHints, Aig_ObjId(pObj) ); + if ( Entry == 0 || Entry == 1 ) + pObj->pData = Aig_NotCond( Aig_ManConst1(pNew), Entry ); // restrict to the complement of constraint!!! + } + // duplicate internal nodes + Aig_ManForEachNode( p, pObj, i ) + { + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + Entry = Vec_IntEntry( vHints, Aig_ObjId(pObj) ); + if ( Entry == 0 || Entry == 1 ) + pObj->pData = Aig_NotCond( Aig_ManConst1(pNew), Entry ); // restrict to the complement of constraint!!! + } + // add the POs + Aig_ManForEachCo( p, pObj, i ) + pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + Aig_ManCleanup( pNew ); + Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); + // check the resulting network + if ( !Aig_ManCheck(pNew) ) + printf( "Llb_ManDeriveAigWithHints(): The check has failed.\n" ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager recursively.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ManDupSimpleDfs_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( pObj->pData ) + return (Aig_Obj_t *)pObj->pData; + Aig_ManDupSimpleDfs_rec( pNew, p, Aig_ObjFanin0(pObj) ); + if ( Aig_ObjIsBuf(pObj) ) + return (Aig_Obj_t *)(pObj->pData = Aig_ObjChild0Copy(pObj)); + Aig_ManDupSimpleDfs_rec( pNew, p, Aig_ObjFanin1(pObj) ); + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + return (Aig_Obj_t *)pObj->pData; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager.] + + Description [Orders nodes as follows: PIs, ANDs, POs.] + + SideEffects [This procedure assumes that buffers are not used during + HAIG recording. This way, each HAIG node is in one-to-one correspondence + with old HAIG node. There is no need to create new nodes, just reassign + the pointers. If it were not the case, we would need to create HAIG nodes + for each new node duplicated. ] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupSimpleDfs( Aig_Man_t * p ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pObjNew = NULL; + int i; + assert( p->pManTime == NULL ); + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nAsserts = p->nAsserts; + pNew->nConstrs = p->nConstrs; + pNew->nBarBufs = p->nBarBufs; + if ( p->vFlopNums ) + pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); + // create the PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachCi( p, pObj, i ) + { + pObjNew = Aig_ObjCreateCi( pNew ); + pObjNew->Level = pObj->Level; + pObj->pData = pObjNew; + } + // duplicate internal nodes + Aig_ManForEachObj( p, pObj, i ) + if ( !Aig_ObjIsCo(pObj) ) + { + Aig_ManDupSimpleDfs_rec( pNew, p, pObj ); + assert( pObj->Level == ((Aig_Obj_t*)pObj->pData)->Level ); + } + // add the POs + Aig_ManForEachCo( p, pObj, i ) + { + pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + pObj->pData = pObjNew; + } + assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) ); + Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); + // check the resulting network + if ( !Aig_ManCheck(pNew) ) + printf( "Aig_ManDupSimple(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates part of the AIG manager.] + + Description [Orders nodes as follows: PIs, ANDs, POs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupSimpleDfsPart( Aig_Man_t * p, Vec_Ptr_t * vPis, Vec_Ptr_t * vPos ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pObjNew = NULL; + int i; + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + // create the PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1( pNew ); + Vec_PtrForEachEntry( Aig_Obj_t *, vPis, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pNew ); + // duplicate internal nodes + Vec_PtrForEachEntry( Aig_Obj_t *, vPos, pObj, i ) + { + pObjNew = Aig_ManDupSimpleDfs_rec( pNew, p, Aig_ObjFanin0(pObj) ); + pObjNew = Aig_NotCond( pObjNew, Aig_ObjFaninC0(pObj) ); + Aig_ObjCreateCo( pNew, pObjNew ); + } + Aig_ManSetRegNum( pNew, 0 ); + // check the resulting network + if ( !Aig_ManCheck(pNew) ) + printf( "Aig_ManDupSimple(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager.] + + Description [Assumes topological ordering of the nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupOrdered( Aig_Man_t * p ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pObjNew = NULL; + int i, nNodes; + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nAsserts = p->nAsserts; + pNew->nConstrs = p->nConstrs; + pNew->nBarBufs = p->nBarBufs; + if ( p->vFlopNums ) + pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); + // create the PIs + Aig_ManCleanData( p ); + // duplicate internal nodes + Aig_ManForEachObj( p, pObj, i ) + { + if ( Aig_ObjIsBuf(pObj) ) + { + pObjNew = Aig_ObjChild0Copy(pObj); + } + else if ( Aig_ObjIsNode(pObj) ) + { + pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) ); + } + else if ( Aig_ObjIsCi(pObj) ) + { + pObjNew = Aig_ObjCreateCi( pNew ); + pObjNew->Level = pObj->Level; + } + else if ( Aig_ObjIsCo(pObj) ) + { + pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + } + else if ( Aig_ObjIsConst1(pObj) ) + { + pObjNew = Aig_ManConst1(pNew); + } + else + assert( 0 ); + pObj->pData = pObjNew; + } + assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) ); + if ( (nNodes = Aig_ManCleanup( pNew )) ) + printf( "Aig_ManDupOrdered(): Cleanup after AIG duplication removed %d nodes.\n", nNodes ); + Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); + // duplicate the timing manager + if ( p->pManTime ) + pNew->pManTime = Tim_ManDup( (Tim_Man_t *)p->pManTime, 0 ); + // check the resulting network + if ( !Aig_ManCheck(pNew) ) + printf( "Aig_ManDupOrdered(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager.] + + Description [Orders nodes as follows: PIs, ANDs, POs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupCof( Aig_Man_t * p, int iInput, int Value ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pObjNew = NULL; + int i; + assert( p->pManTime == NULL ); + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nAsserts = p->nAsserts; + pNew->nConstrs = p->nConstrs; + pNew->nBarBufs = p->nBarBufs; + if ( p->vFlopNums ) + pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); + // create the PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachCi( p, pObj, i ) + { + if ( i == iInput ) + pObjNew = Value ? Aig_ManConst1(pNew) : Aig_ManConst0(pNew); + else + { + pObjNew = Aig_ObjCreateCi( pNew ); + pObjNew->Level = pObj->Level; + } + pObj->pData = pObjNew; + } + // duplicate internal nodes + Aig_ManForEachObj( p, pObj, i ) + if ( Aig_ObjIsBuf(pObj) ) + { + pObjNew = Aig_ObjChild0Copy(pObj); + pObj->pData = pObjNew; + } + else if ( Aig_ObjIsNode(pObj) ) + { + pObjNew = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + pObj->pData = pObjNew; + } + // add the POs + Aig_ManForEachCo( p, pObj, i ) + { + pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + pObj->pData = pObjNew; + } +// assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) ); + Aig_ManCleanup( pNew ); + Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); + // check the resulting network + if ( !Aig_ManCheck(pNew) ) + printf( "Aig_ManDupSimple(): The check has failed.\n" ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager.] + + Description [Assumes topological ordering of the nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupTrim( Aig_Man_t * p ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pObjNew = NULL; + int i, nNodes; + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nConstrs = p->nConstrs; + pNew->nBarBufs = p->nBarBufs; + // create the PIs + Aig_ManCleanData( p ); + // duplicate internal nodes + Aig_ManForEachObj( p, pObj, i ) + { + if ( Aig_ObjIsNode(pObj) ) + pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) ); + else if ( Aig_ObjIsCi(pObj) ) + pObjNew = (Aig_ObjRefs(pObj) > 0 || Saig_ObjIsLo(p, pObj)) ? Aig_ObjCreateCi(pNew) : NULL; + else if ( Aig_ObjIsCo(pObj) ) + pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + else if ( Aig_ObjIsConst1(pObj) ) + pObjNew = Aig_ManConst1(pNew); + else + assert( 0 ); + pObj->pData = pObjNew; + } + assert( Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) ); + if ( (nNodes = Aig_ManCleanup( pNew )) ) + printf( "Aig_ManDupTrim(): Cleanup after AIG duplication removed %d nodes.\n", nNodes ); + Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); + // check the resulting network + if ( !Aig_ManCheck(pNew) ) + printf( "Aig_ManDupTrim(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager to have EXOR gates.] + + Description [Assumes topological ordering of the nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupExor( Aig_Man_t * p ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pObjNew = NULL; + int i; + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->fCatchExor = 1; + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nAsserts = p->nAsserts; + pNew->nConstrs = p->nConstrs; + pNew->nBarBufs = p->nBarBufs; + if ( p->vFlopNums ) + pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); + // create the PIs + Aig_ManCleanData( p ); + // duplicate internal nodes + Aig_ManForEachObj( p, pObj, i ) + { + if ( Aig_ObjIsBuf(pObj) ) + { + pObjNew = Aig_ObjChild0Copy(pObj); + } + else if ( Aig_ObjIsNode(pObj) ) + { + pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) ); + } + else if ( Aig_ObjIsCi(pObj) ) + { + pObjNew = Aig_ObjCreateCi( pNew ); + pObjNew->Level = pObj->Level; + } + else if ( Aig_ObjIsCo(pObj) ) + { + pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + } + else if ( Aig_ObjIsConst1(pObj) ) + { + pObjNew = Aig_ManConst1(pNew); + } + else + assert( 0 ); + pObj->pData = pObjNew; + } + Aig_ManCleanup( pNew ); + Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); + // duplicate the timing manager + if ( p->pManTime ) + pNew->pManTime = Tim_ManDup( (Tim_Man_t *)p->pManTime, 0 ); + // check the resulting network + if ( !Aig_ManCheck(pNew) ) + printf( "Aig_ManDupExor(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager recursively.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ManDupDfs_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pObjNew, * pEquivNew = NULL; + if ( pObj->pData ) + return (Aig_Obj_t *)pObj->pData; + if ( p->pEquivs && Aig_ObjEquiv(p, pObj) ) + pEquivNew = Aig_ManDupDfs_rec( pNew, p, Aig_ObjEquiv(p, pObj) ); + Aig_ManDupDfs_rec( pNew, p, Aig_ObjFanin0(pObj) ); + if ( Aig_ObjIsBuf(pObj) ) + return (Aig_Obj_t *)(pObj->pData = Aig_ObjChild0Copy(pObj)); + Aig_ManDupDfs_rec( pNew, p, Aig_ObjFanin1(pObj) ); + pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) ); + if ( pEquivNew ) + { + assert( Aig_Regular(pEquivNew)->Id < Aig_Regular(pObjNew)->Id ); + if ( pNew->pEquivs ) + pNew->pEquivs[Aig_Regular(pObjNew)->Id] = Aig_Regular(pEquivNew); + if ( pNew->pReprs ) + pNew->pReprs[Aig_Regular(pEquivNew)->Id] = Aig_Regular(pObjNew); + } + return (Aig_Obj_t *)(pObj->pData = pObjNew); +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager.] + + Description [This duplicator works for AIGs with choices.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupDfs( Aig_Man_t * p ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pObjNew = NULL; + int i, nNodes; + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nAsserts = p->nAsserts; + pNew->nConstrs = p->nConstrs; + pNew->nBarBufs = p->nBarBufs; + if ( p->vFlopNums ) + pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); + // duplicate representation of choice nodes + if ( p->pEquivs ) + pNew->pEquivs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p) ); + if ( p->pReprs ) + pNew->pReprs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p) ); + // create the PIs + Aig_ManCleanData( p ); + // duplicate internal nodes + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachObj( p, pObj, i ) + { + if ( Aig_ObjIsCi(pObj) ) + { + pObjNew = Aig_ObjCreateCi( pNew ); + pObjNew->Level = pObj->Level; + pObj->pData = pObjNew; + } + else if ( Aig_ObjIsCo(pObj) ) + { + Aig_ManDupDfs_rec( pNew, p, Aig_ObjFanin0(pObj) ); +// assert( pObj->Level == ((Aig_Obj_t*)pObj->pData)->Level ); + pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + pObj->pData = pObjNew; + } + } + assert( p->pEquivs != NULL || Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) ); + if ( p->pEquivs == NULL && p->pReprs == NULL && (nNodes = Aig_ManCleanup( pNew )) ) + printf( "Aig_ManDupDfs(): Cleanup after AIG duplication removed %d nodes.\n", nNodes ); + Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); + // duplicate the timing manager + if ( p->pManTime ) + pNew->pManTime = Tim_ManDup( (Tim_Man_t *)p->pManTime, 0 ); + // check the resulting network + if ( !Aig_ManCheck(pNew) ) + printf( "Aig_ManDupDfs(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager.] + + Description [This duplicator works for AIGs with choices.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManOrderPios( Aig_Man_t * p, Aig_Man_t * pOrder ) +{ + Vec_Ptr_t * vPios; + Aig_Obj_t * pObj = NULL; + int i; + assert( Aig_ManCiNum(p) == Aig_ManCiNum(pOrder) ); + assert( Aig_ManCoNum(p) == Aig_ManCoNum(pOrder) ); + Aig_ManSetCioIds( pOrder ); + vPios = Vec_PtrAlloc( Aig_ManCiNum(p) + Aig_ManCoNum(p) ); + Aig_ManForEachObj( pOrder, pObj, i ) + { + if ( Aig_ObjIsCi(pObj) ) + Vec_PtrPush( vPios, Aig_ManCi(p, Aig_ObjCioId(pObj)) ); + else if ( Aig_ObjIsCo(pObj) ) + Vec_PtrPush( vPios, Aig_ManCo(p, Aig_ObjCioId(pObj)) ); + } + Aig_ManCleanCioIds( pOrder ); + return vPios; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager recursively.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ManDupDfsGuided_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pObjNew, * pEquivNew = NULL; + if ( pObj->pData ) + return (Aig_Obj_t *)pObj->pData; + if ( Aig_ObjIsCi(pObj) ) + return NULL; + if ( p->pEquivs && Aig_ObjEquiv(p, pObj) ) + pEquivNew = Aig_ManDupDfsGuided_rec( pNew, p, Aig_ObjEquiv(p, pObj) ); + if ( !Aig_ManDupDfsGuided_rec( pNew, p, Aig_ObjFanin0(pObj) ) ) + return NULL; + if ( Aig_ObjIsBuf(pObj) ) + return (Aig_Obj_t *)(pObj->pData = Aig_ObjChild0Copy(pObj)); + if ( !Aig_ManDupDfsGuided_rec( pNew, p, Aig_ObjFanin1(pObj) ) ) + return NULL; + pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) ); + if ( pEquivNew ) + { + if ( pNew->pEquivs ) + pNew->pEquivs[Aig_Regular(pObjNew)->Id] = Aig_Regular(pEquivNew); + if ( pNew->pReprs ) + pNew->pReprs[Aig_Regular(pEquivNew)->Id] = Aig_Regular(pObjNew); + } + return (Aig_Obj_t *)(pObj->pData = pObjNew); +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager.] + + Description [This duplicator works for AIGs with choices.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupDfsGuided( Aig_Man_t * p, Vec_Ptr_t * vPios ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pObjNew = NULL; + int i, nNodes; + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nAsserts = p->nAsserts; + pNew->nConstrs = p->nConstrs; + pNew->nBarBufs = p->nBarBufs; + if ( p->vFlopNums ) + pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); + // duplicate representation of choice nodes + if ( p->pEquivs ) + { + pNew->pEquivs = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p) ); + memset( pNew->pEquivs, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p) ); + } + if ( p->pReprs ) + { + pNew->pReprs = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p) ); + memset( pNew->pReprs, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p) ); + } + // create the PIs + Aig_ManCleanData( p ); + // duplicate internal nodes + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Vec_PtrForEachEntry( Aig_Obj_t *, vPios, pObj, i ) + { + if ( Aig_ObjIsCi(pObj) ) + { + pObjNew = Aig_ObjCreateCi( pNew ); + pObjNew->Level = pObj->Level; + pObj->pData = pObjNew; + } + else if ( Aig_ObjIsCo(pObj) ) + { + Aig_ManDupDfsGuided_rec( pNew, p, Aig_ObjFanin0(pObj) ); +// assert( pObj->Level == ((Aig_Obj_t*)pObj->pData)->Level ); + pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + pObj->pData = pObjNew; + } + } +// assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) ); + if ( p->pEquivs == NULL && p->pReprs == NULL && (nNodes = Aig_ManCleanup( pNew )) ) + printf( "Aig_ManDupDfs(): Cleanup after AIG duplication removed %d nodes.\n", nNodes ); + Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); + // duplicate the timing manager + if ( p->pManTime ) + pNew->pManTime = Tim_ManDup( (Tim_Man_t *)p->pManTime, 0 ); + // check the resulting network + if ( !Aig_ManCheck(pNew) ) + printf( "Aig_ManDupDfs(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager.] + + Description [This duplicator works for AIGs with choices.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupLevelized( Aig_Man_t * p ) +{ + Vec_Vec_t * vLevels; + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pObjNew = NULL; + int i, k; + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nAsserts = p->nAsserts; + pNew->nConstrs = p->nConstrs; + pNew->nBarBufs = p->nBarBufs; + if ( p->vFlopNums ) + pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); + // duplicate representation of choice nodes + if ( p->pEquivs ) + { + pNew->pEquivs = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p) ); + memset( pNew->pEquivs, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p) ); + } + if ( p->pReprs ) + { + pNew->pReprs = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p) ); + memset( pNew->pReprs, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p) ); + } + // create the PIs + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachCi( p, pObj, i ) + { + pObjNew = Aig_ObjCreateCi( pNew ); + pObjNew->Level = pObj->Level; + pObj->pData = pObjNew; + } + // duplicate internal nodes + vLevels = Aig_ManLevelize( p ); + Vec_VecForEachEntry( Aig_Obj_t *, vLevels, pObj, i, k ) + { + pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) ); + pObj->pData = pObjNew; + } + Vec_VecFree( vLevels ); + // duplicate POs + Aig_ManForEachCo( p, pObj, i ) + { + pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + pObj->pData = pObjNew; + } + assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) ); +// if ( (nNodes = Aig_ManCleanup( pNew )) ) +// printf( "Aig_ManDupLevelized(): Cleanup after AIG duplication removed %d nodes.\n", nNodes ); + Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); + // duplicate the timing manager + if ( p->pManTime ) + pNew->pManTime = Tim_ManDup( (Tim_Man_t *)p->pManTime, 0 ); + // check the resulting network + if ( !Aig_ManCheck(pNew) ) + printf( "Aig_ManDupLevelized(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager.] + + Description [Assumes topological ordering of nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupWithoutPos( Aig_Man_t * p ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj = NULL; + int i; + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + // create the PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachCi( p, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pNew ); + // duplicate internal nodes + Aig_ManForEachObj( p, pObj, i ) + { + assert( !Aig_ObjIsBuf(pObj) ); + if ( Aig_ObjIsNode(pObj) ) + pObj->pData = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) ); + } + assert( Aig_ManBufNum(p) != 0 || Aig_ManNodeNum(p) == Aig_ManNodeNum(pNew) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager.] + + Description [Assumes topological ordering of nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupFlopsOnly( Aig_Man_t * p ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj = NULL; + int i; + pNew = Aig_ManDupWithoutPos( p ); + Saig_ManForEachLi( p, pObj, i ) + pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + Aig_ManCleanup( pNew ); + Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); + if ( !Aig_ManCheck(pNew) ) + printf( "Aig_ManDupFlopsOnly(): The check has failed.\n" ); + return pNew; + +} + + +/**Function************************************************************* + + Synopsis [Returns representatives of fanin in approapriate polarity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Aig_Obj_t * Aig_ObjGetRepres( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pRepr; + if ( (pRepr = Aig_ObjRepr(p, pObj)) ) + return Aig_NotCond( (Aig_Obj_t *)pRepr->pData, pObj->fPhase ^ pRepr->fPhase ); + return (Aig_Obj_t *)pObj->pData; +} +static inline Aig_Obj_t * Aig_ObjChild0Repres( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_NotCond( Aig_ObjGetRepres(p, Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj) ); } +static inline Aig_Obj_t * Aig_ObjChild1Repres( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_NotCond( Aig_ObjGetRepres(p, Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj) ); } + +/**Function************************************************************* + + Synopsis [Duplicates AIG while substituting representatives.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupRepres( Aig_Man_t * p ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj = NULL; + int i; + // start the HOP package + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nConstrs = p->nConstrs; + pNew->nBarBufs = p->nBarBufs; + if ( p->vFlopNums ) + pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); + // map the const and primary inputs + Aig_ManCleanData( p ); + Aig_ManForEachObj( p, pObj, i ) + { + if ( Aig_ObjIsNode(pObj) ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Repres(p, pObj), Aig_ObjChild1Repres(p, pObj) ); + else if ( Aig_ObjIsCi(pObj) ) + { + pObj->pData = Aig_ObjCreateCi(pNew); + pObj->pData = Aig_ObjGetRepres( p, pObj ); + } + else if ( Aig_ObjIsCo(pObj) ) + pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Repres(p, pObj) ); + else if ( Aig_ObjIsConst1(pObj) ) + pObj->pData = Aig_ManConst1(pNew); + else + assert( 0 ); + } + Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); + // check the new manager + if ( !Aig_ManCheck(pNew) ) + printf( "Aig_ManDupRepres: Check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager recursively.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ManDupRepres_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pRepr; + if ( pObj->pData ) + return (Aig_Obj_t *)pObj->pData; + if ( (pRepr = Aig_ObjRepr(p, pObj)) ) + { + Aig_ManDupRepres_rec( pNew, p, pRepr ); + return (Aig_Obj_t *)(pObj->pData = Aig_NotCond( (Aig_Obj_t *)pRepr->pData, pRepr->fPhase ^ pObj->fPhase )); + } + Aig_ManDupRepres_rec( pNew, p, Aig_ObjFanin0(pObj) ); + Aig_ManDupRepres_rec( pNew, p, Aig_ObjFanin1(pObj) ); + return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, Aig_ObjChild0Repres(p, pObj), Aig_ObjChild1Repres(p, pObj) )); +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG while substituting representatives.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupRepresDfs( Aig_Man_t * p ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj = NULL; + int i; + // start the HOP package + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nConstrs = p->nConstrs; + pNew->nBarBufs = p->nBarBufs; + if ( p->vFlopNums ) + pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); + // map the const and primary inputs + Aig_ManCleanData( p ); + Aig_ManForEachObj( p, pObj, i ) + { + if ( Aig_ObjIsNode(pObj) ) + continue; + if ( Aig_ObjIsCi(pObj) ) + pObj->pData = Aig_ObjCreateCi(pNew); + else if ( Aig_ObjIsCo(pObj) ) + { + Aig_ManDupRepres_rec( pNew, p, Aig_ObjFanin0(pObj) ); + pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Repres(p, pObj) ); + } + else if ( Aig_ObjIsConst1(pObj) ) + pObj->pData = Aig_ManConst1(pNew); + else + assert( 0 ); + } + Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); + // check the new manager + if ( !Aig_ManCheck(pNew) ) + printf( "Aig_ManDupRepresDfs: Check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Creates the miter of the two AIG managers.] + + Description [Oper is the operation to perform on the outputs of the miter. + Oper == 0 is XOR + Oper == 1 is complemented implication (p1 => p2) + Oper == 2 is OR + Oper == 3 is AND + ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManCreateMiter( Aig_Man_t * p1, Aig_Man_t * p2, int Oper ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj = NULL; + int i; + assert( Aig_ManRegNum(p1) == 0 ); + assert( Aig_ManRegNum(p2) == 0 ); + assert( Aig_ManCoNum(p1) == 1 ); + assert( Aig_ManCoNum(p2) == 1 ); + assert( Aig_ManCiNum(p1) == Aig_ManCiNum(p2) ); + pNew = Aig_ManStart( Aig_ManObjNumMax(p1) + Aig_ManObjNumMax(p2) ); + // add first AIG + Aig_ManConst1(p1)->pData = Aig_ManConst1(pNew); + Aig_ManForEachCi( p1, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pNew ); + Aig_ManForEachNode( p1, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // add second AIG + Aig_ManConst1(p2)->pData = Aig_ManConst1(pNew); + Aig_ManForEachCi( p2, pObj, i ) + pObj->pData = Aig_ManCi( pNew, i ); + Aig_ManForEachNode( p2, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // add the output + if ( Oper == 0 ) // XOR + pObj = Aig_Exor( pNew, Aig_ObjChild0Copy(Aig_ManCo(p1,0)), Aig_ObjChild0Copy(Aig_ManCo(p2,0)) ); + else if ( Oper == 1 ) // implication is PO(p1) -> PO(p2) ... complement is PO(p1) & !PO(p2) + pObj = Aig_And( pNew, Aig_ObjChild0Copy(Aig_ManCo(p1,0)), Aig_Not(Aig_ObjChild0Copy(Aig_ManCo(p2,0))) ); + else if ( Oper == 2 ) // OR + pObj = Aig_Or( pNew, Aig_ObjChild0Copy(Aig_ManCo(p1,0)), Aig_ObjChild0Copy(Aig_ManCo(p2,0)) ); + else if ( Oper == 3 ) // AND + pObj = Aig_And( pNew, Aig_ObjChild0Copy(Aig_ManCo(p1,0)), Aig_ObjChild0Copy(Aig_ManCo(p2,0)) ); + else + assert( 0 ); + Aig_ObjCreateCo( pNew, pObj ); + Aig_ManCleanup( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG with only one primary output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupOrpos( Aig_Man_t * p, int fAddRegs ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pMiter; + int i; + assert( Aig_ManRegNum(p) > 0 ); + if ( p->nConstrs > 0 ) + { + printf( "The AIG manager should have no constraints.\n" ); + return NULL; + } + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + // create the PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachCi( p, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pNew ); + // set registers + pNew->nRegs = fAddRegs? p->nRegs : 0; + pNew->nTruePis = fAddRegs? p->nTruePis : p->nTruePis + p->nRegs; + pNew->nTruePos = 1; + // duplicate internal nodes + Aig_ManForEachNode( p, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // create the PO + pMiter = Aig_ManConst0(pNew); + Aig_ManForEachPoSeq( p, pObj, i ) + pMiter = Aig_Or( pNew, pMiter, Aig_ObjChild0Copy(pObj) ); + Aig_ObjCreateCo( pNew, pMiter ); + // create register inputs with MUXes + if ( fAddRegs ) + { + Aig_ManForEachLiSeq( p, pObj, i ) + Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + } + Aig_ManCleanup( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG with only one primary output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupOneOutput( Aig_Man_t * p, int iPoNum, int fAddRegs ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj = NULL; + int i; + //assert( Aig_ManRegNum(p) > 0 ); + assert( iPoNum < Aig_ManCoNum(p)-Aig_ManRegNum(p) ); + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + // create the PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachCi( p, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pNew ); + // set registers + pNew->nRegs = fAddRegs? p->nRegs : 0; + pNew->nTruePis = fAddRegs? p->nTruePis : p->nTruePis + p->nRegs; + pNew->nTruePos = 1; + // duplicate internal nodes + Aig_ManForEachNode( p, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // create the PO + pObj = Aig_ManCo( p, iPoNum ); + Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + // create register inputs with MUXes + if ( fAddRegs ) + { + Aig_ManForEachLiSeq( p, pObj, i ) + Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + } + Aig_ManCleanup( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG with only one primary output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupUnsolvedOutputs( Aig_Man_t * p, int fAddRegs ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj = NULL; + int i, nOuts = 0; + assert( Aig_ManRegNum(p) > 0 ); + if ( p->nConstrs > 0 ) + { + printf( "The AIG manager should have no constraints.\n" ); + return NULL; + } + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + // create the PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachCi( p, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pNew ); + // create the POs + nOuts = 0; + Aig_ManForEachPoSeq( p, pObj, i ) + nOuts += ( Aig_ObjFanin0(pObj) != Aig_ManConst1(p) ); + // set registers + pNew->nRegs = fAddRegs? p->nRegs : 0; + pNew->nTruePis = fAddRegs? p->nTruePis : p->nTruePis + p->nRegs; + pNew->nTruePos = nOuts; + // duplicate internal nodes + Aig_ManForEachNode( p, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // create the PO + Aig_ManForEachPoSeq( p, pObj, i ) + if ( Aig_ObjFanin0(pObj) != Aig_ManConst1(p) ) + Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + // create register inputs with MUXes + if ( fAddRegs ) + { + Aig_ManForEachLiSeq( p, pObj, i ) + Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + } + Aig_ManCleanup( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG with only one primary output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupArray( Vec_Ptr_t * vArray ) +{ + Aig_Man_t * p, * pNew; + Aig_Obj_t * pObj = NULL; + int i, k; + if ( Vec_PtrSize(vArray) == 0 ) + return NULL; + p = (Aig_Man_t *)Vec_PtrEntry( vArray, 0 ); + Vec_PtrForEachEntry( Aig_Man_t *, vArray, pNew, k ) + { + assert( Aig_ManRegNum(pNew) == 0 ); + assert( Aig_ManCiNum(pNew) == Aig_ManCiNum(p) ); + } + // create the new manager + pNew = Aig_ManStart( 10000 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Aig_ManForEachCi( p, pObj, i ) + Aig_ObjCreateCi(pNew); + // create the PIs + Vec_PtrForEachEntry( Aig_Man_t *, vArray, p, k ) + { + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachCi( p, pObj, i ) + pObj->pData = Aig_ManCi( pNew, i ); + Aig_ManForEachNode( p, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + Aig_ManForEachCo( p, pObj, i ) + Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + } + Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); + // check the resulting network + if ( !Aig_ManCheck(pNew) ) + printf( "Aig_ManDupSimple(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG with only one primary output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupNodes( Aig_Man_t * pMan, Vec_Ptr_t * vArray ) +{ + Aig_Man_t * pNew; + Vec_Ptr_t * vObjs; + Aig_Obj_t * pObj = NULL; + int i; + if ( Vec_PtrSize(vArray) == 0 ) + return NULL; + vObjs = Aig_ManDfsNodes( pMan, (Aig_Obj_t **)Vec_PtrArray(vArray), Vec_PtrSize(vArray) ); + // create the new manager + pNew = Aig_ManStart( 10000 ); + pNew->pName = Abc_UtilStrsav( pMan->pName ); + Aig_ManConst1(pMan)->pData = Aig_ManConst1(pNew); + Vec_PtrForEachEntry( Aig_Obj_t *, vObjs, pObj, i ) + if ( Aig_ObjIsCi(pObj) ) + pObj->pData = Aig_ObjCreateCi(pNew); + Vec_PtrForEachEntry( Aig_Obj_t *, vObjs, pObj, i ) + if ( Aig_ObjIsNode(pObj) ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + Vec_PtrForEachEntry( Aig_Obj_t *, vArray, pObj, i ) + Aig_ObjCreateCo( pNew, (Aig_Obj_t *)pObj->pData ); + Aig_ManSetRegNum( pNew, 0 ); + Vec_PtrFree( vObjs ); + return pNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigFact.c b/yosys/abc/src/aig/aig/aigFact.c new file mode 100644 index 00000000000..6354a981476 --- /dev/null +++ b/yosys/abc/src/aig/aig/aigFact.c @@ -0,0 +1,734 @@ +/**CFile**************************************************************** + + FileName [aigFactor.c] + + SystemName [] + + PackageName [] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [] + + Date [Ver. 1.0. Started - April 17, 2009.] + + Revision [$Id: aigFactor.c,v 1.00 2009/04/17 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" +#include "bool/kit/kit.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Detects multi-input AND gate rooted at this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManFindImplications_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vImplics ) +{ + if ( Aig_IsComplement(pObj) || Aig_ObjIsCi(pObj) ) + { + Vec_PtrPushUnique( vImplics, pObj ); + return; + } + Aig_ManFindImplications_rec( Aig_ObjChild0(pObj), vImplics ); + Aig_ManFindImplications_rec( Aig_ObjChild1(pObj), vImplics ); +} + +/**Function************************************************************* + + Synopsis [Returns the nodes whose values are implied by pNode.] + + Description [Attention! Both pNode and results can be complemented! + Also important: Currently, this procedure only does backward propagation. + In general, it may find more implications if forward propagation is enabled.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManFindImplications( Aig_Man_t * p, Aig_Obj_t * pNode ) +{ + Vec_Ptr_t * vImplics; + vImplics = Vec_PtrAlloc( 100 ); + Aig_ManFindImplications_rec( pNode, vImplics ); + return vImplics; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the cone of the node overlaps with the vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManFindConeOverlap_rec( Aig_Man_t * p, Aig_Obj_t * pNode ) +{ + if ( Aig_ObjIsTravIdPrevious( p, pNode ) ) + return 1; + if ( Aig_ObjIsTravIdCurrent( p, pNode ) ) + return 0; + Aig_ObjSetTravIdCurrent( p, pNode ); + if ( Aig_ObjIsCi(pNode) ) + return 0; + if ( Aig_ManFindConeOverlap_rec( p, Aig_ObjFanin0(pNode) ) ) + return 1; + if ( Aig_ManFindConeOverlap_rec( p, Aig_ObjFanin1(pNode) ) ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the cone of the node overlaps with the vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManFindConeOverlap( Aig_Man_t * p, Vec_Ptr_t * vImplics, Aig_Obj_t * pNode ) +{ + Aig_Obj_t * pTemp; + int i; + assert( !Aig_IsComplement(pNode) ); + assert( !Aig_ObjIsConst1(pNode) ); + Aig_ManIncrementTravId( p ); + Vec_PtrForEachEntry( Aig_Obj_t *, vImplics, pTemp, i ) + Aig_ObjSetTravIdCurrent( p, Aig_Regular(pTemp) ); + Aig_ManIncrementTravId( p ); + return Aig_ManFindConeOverlap_rec( p, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the cone of the node overlaps with the vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ManDeriveNewCone_rec( Aig_Man_t * p, Aig_Obj_t * pNode ) +{ + if ( Aig_ObjIsTravIdCurrent( p, pNode ) ) + return (Aig_Obj_t *)pNode->pData; + Aig_ObjSetTravIdCurrent( p, pNode ); + if ( Aig_ObjIsCi(pNode) ) + return (Aig_Obj_t *)(pNode->pData = pNode); + Aig_ManDeriveNewCone_rec( p, Aig_ObjFanin0(pNode) ); + Aig_ManDeriveNewCone_rec( p, Aig_ObjFanin1(pNode) ); + return (Aig_Obj_t *)(pNode->pData = Aig_And( p, Aig_ObjChild0Copy(pNode), Aig_ObjChild1Copy(pNode) )); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the cone of the node overlaps with the vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ManDeriveNewCone( Aig_Man_t * p, Vec_Ptr_t * vImplics, Aig_Obj_t * pNode ) +{ + Aig_Obj_t * pTemp; + int i; + assert( !Aig_IsComplement(pNode) ); + assert( !Aig_ObjIsConst1(pNode) ); + Aig_ManIncrementTravId( p ); + Vec_PtrForEachEntry( Aig_Obj_t *, vImplics, pTemp, i ) + { + Aig_ObjSetTravIdCurrent( p, Aig_Regular(pTemp) ); + Aig_Regular(pTemp)->pData = Aig_NotCond( Aig_ManConst1(p), Aig_IsComplement(pTemp) ); + } + return Aig_ManDeriveNewCone_rec( p, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns algebraic factoring of B in terms of A.] + + Description [Returns internal node C (an AND gate) that is equal to B + under assignment A = 'Value', or NULL if there is no such node C. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ManFactorAlgebraic_int( Aig_Man_t * p, Aig_Obj_t * pPoA, Aig_Obj_t * pPoB, int Value ) +{ + Aig_Obj_t * pNodeA, * pNodeC; + Vec_Ptr_t * vImplics; + int RetValue; + if ( Aig_ObjIsConst1(Aig_ObjFanin0(pPoA)) || Aig_ObjIsConst1(Aig_ObjFanin0(pPoB)) ) + return NULL; + if ( Aig_ObjIsCi(Aig_ObjFanin0(pPoB)) ) + return NULL; + // get the internal node representing function of A under assignment A = 'Value' + pNodeA = Aig_ObjChild0( pPoA ); + pNodeA = Aig_NotCond( pNodeA, Value==0 ); + // find implications of this signal (nodes whose value is fixed under assignment A = 'Value') + vImplics = Aig_ManFindImplications( p, pNodeA ); + // check if the TFI cone of B overlaps with the implied nodes + RetValue = Aig_ManFindConeOverlap( p, vImplics, Aig_ObjFanin0(pPoB) ); + if ( RetValue == 0 ) // no overlap + { + Vec_PtrFree( vImplics ); + return NULL; + } + // there is overlap - derive node representing value of B under assignment A = 'Value' + pNodeC = Aig_ManDeriveNewCone( p, vImplics, Aig_ObjFanin0(pPoB) ); + pNodeC = Aig_NotCond( pNodeC, Aig_ObjFaninC0(pPoB) ); + Vec_PtrFree( vImplics ); + return pNodeC; +} + +/**Function************************************************************* + + Synopsis [Returns algebraic factoring of B in terms of A.] + + Description [Returns internal node C (an AND gate) that is equal to B + under assignment A = 'Value', or NULL if there is no such node C. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ManFactorAlgebraic( Aig_Man_t * p, int iPoA, int iPoB, int Value ) +{ + assert( iPoA >= 0 && iPoA < Aig_ManCoNum(p) ); + assert( iPoB >= 0 && iPoB < Aig_ManCoNum(p) ); + assert( Value == 0 || Value == 1 ); + return Aig_ManFactorAlgebraic_int( p, Aig_ManCo(p, iPoA), Aig_ManCo(p, iPoB), Value ); +} + +/**Function************************************************************* + + Synopsis [Testing procedure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManFactorAlgebraicTest( Aig_Man_t * p ) +{ + int iPoA = 0; + int iPoB = 1; + int Value = 0; + Aig_Obj_t * pRes; +// Aig_Obj_t * pObj; +// int i; + pRes = Aig_ManFactorAlgebraic( p, iPoA, iPoB, Value ); + Aig_ManShow( p, 0, NULL ); + Aig_ObjPrint( p, pRes ); + printf( "\n" ); +/* + printf( "Results:\n" ); + Aig_ManForEachObj( p, pObj, i ) + { + printf( "Object = %d.\n", i ); + Aig_ObjPrint( p, pObj ); + printf( "\n" ); + Aig_ObjPrint( p, pObj->pData ); + printf( "\n" ); + } +*/ +} + + + +/**Function************************************************************* + + Synopsis [Determines what support variables can be cofactored.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_SuppMinPerform( Aig_Man_t * p, Vec_Ptr_t * vOrGate, Vec_Ptr_t * vNodes, Vec_Ptr_t * vSupp ) +{ + Aig_Obj_t * pObj; + Vec_Ptr_t * vTrSupp, * vTrNode, * vCofs; + unsigned * uFunc = NULL, * uCare, * uFunc0, * uFunc1; + unsigned * uCof0, * uCof1, * uCare0, * uCare1; + int i, nWords = Abc_TruthWordNum( Vec_PtrSize(vSupp) ); + // assign support nodes + vTrSupp = Vec_PtrAllocTruthTables( Vec_PtrSize(vSupp) ); + Vec_PtrForEachEntry( Aig_Obj_t *, vSupp, pObj, i ) + pObj->pData = Vec_PtrEntry( vTrSupp, i ); + // compute internal nodes + vTrNode = Vec_PtrAllocSimInfo( Vec_PtrSize(vNodes) + 5, nWords ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + pObj->pData = uFunc = (unsigned *)Vec_PtrEntry( vTrNode, i ); + uFunc0 = (unsigned *)Aig_ObjFanin0(pObj)->pData; + uFunc1 = (unsigned *)Aig_ObjFanin1(pObj)->pData; + Kit_TruthAndPhase( uFunc, uFunc0, uFunc1, Vec_PtrSize(vSupp), Aig_ObjFaninC0(pObj), Aig_ObjFaninC1(pObj) ); + } + // uFunc contains the result of computation + // compute care set + uCare = (unsigned *)Vec_PtrEntry( vTrNode, Vec_PtrSize(vNodes) ); + Kit_TruthClear( uCare, Vec_PtrSize(vSupp) ); + Vec_PtrForEachEntry( Aig_Obj_t *, vOrGate, pObj, i ) + Kit_TruthOrPhase( uCare, uCare, (unsigned *)Aig_Regular(pObj)->pData, Vec_PtrSize(vSupp), 0, Aig_IsComplement(pObj) ); + // try cofactoring each variable in both polarities + vCofs = Vec_PtrAlloc( 10 ); + uCof0 = (unsigned *)Vec_PtrEntry( vTrNode, Vec_PtrSize(vNodes)+1 ); + uCof1 = (unsigned *)Vec_PtrEntry( vTrNode, Vec_PtrSize(vNodes)+2 ); + uCare0 = (unsigned *)Vec_PtrEntry( vTrNode, Vec_PtrSize(vNodes)+3 ); + uCare1 = (unsigned *)Vec_PtrEntry( vTrNode, Vec_PtrSize(vNodes)+4 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vSupp, pObj, i ) + { + Kit_TruthCofactor0New( uCof0, uFunc, Vec_PtrSize(vSupp), i ); + Kit_TruthCofactor1New( uCof1, uFunc, Vec_PtrSize(vSupp), i ); + Kit_TruthCofactor0New( uCare0, uCare, Vec_PtrSize(vSupp), i ); + Kit_TruthCofactor1New( uCare1, uCare, Vec_PtrSize(vSupp), i ); + if ( Kit_TruthIsEqualWithCare( uCof0, uCof1, uCare1, Vec_PtrSize(vSupp) ) ) + Vec_PtrPush( vCofs, Aig_Not(pObj) ); + else if ( Kit_TruthIsEqualWithCare( uCof0, uCof1, uCare0, Vec_PtrSize(vSupp) ) ) + Vec_PtrPush( vCofs, pObj ); + } + Vec_PtrFree( vTrNode ); + Vec_PtrFree( vTrSupp ); + return vCofs; +} + + + +/**Function************************************************************* + + Synopsis [Returns the new node after cofactoring.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_SuppMinReconstruct( Aig_Man_t * p, Vec_Ptr_t * vCofs, Vec_Ptr_t * vNodes, Vec_Ptr_t * vSupp ) +{ + Aig_Obj_t * pObj = NULL; + int i; + // set the value of the support variables + Vec_PtrForEachEntry( Aig_Obj_t *, vSupp, pObj, i ) + assert( !Aig_IsComplement(pObj) ); + Vec_PtrForEachEntry( Aig_Obj_t *, vSupp, pObj, i ) + pObj->pData = pObj; + // set the value of the cofactoring variables + Vec_PtrForEachEntry( Aig_Obj_t *, vCofs, pObj, i ) + Aig_Regular(pObj)->pData = Aig_NotCond( Aig_ManConst1(p), Aig_IsComplement(pObj) ); + // reconstruct the node + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + return (Aig_Obj_t *)pObj->pData; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if all nodes of vOrGate are in vSupp.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_SuppMinGateIsInSupport( Aig_Man_t * p, Vec_Ptr_t * vOrGate, Vec_Ptr_t * vSupp ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManIncrementTravId( p ); + Vec_PtrForEachEntry( Aig_Obj_t *, vSupp, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + Vec_PtrForEachEntry( Aig_Obj_t *, vOrGate, pObj, i ) + if ( !Aig_ObjIsTravIdCurrent( p, Aig_Regular(pObj) ) ) + return 0; + return 1; +} + + +/**Function************************************************************* + + Synopsis [Collects fanins of the marked nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_SuppMinCollectSupport( Aig_Man_t * p, Vec_Ptr_t * vNodes ) +{ + Vec_Ptr_t * vSupp; + Aig_Obj_t * pObj, * pFanin; + int i; + vSupp = Vec_PtrAlloc( 4 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + assert( Aig_ObjIsTravIdCurrent(p, pObj) ); + assert( Aig_ObjIsNode(pObj) ); + pFanin = Aig_ObjFanin0( pObj ); + if ( !Aig_ObjIsTravIdCurrent(p, pFanin) ) + { + Aig_ObjSetTravIdCurrent( p, pFanin ); + Vec_PtrPush( vSupp, pFanin ); + } + pFanin = Aig_ObjFanin1( pObj ); + if ( !Aig_ObjIsTravIdCurrent(p, pFanin) ) + { + Aig_ObjSetTravIdCurrent( p, pFanin ); + Vec_PtrPush( vSupp, pFanin ); + } + } + return vSupp; +} + +/**Function************************************************************* + + Synopsis [Marks the nodes in the cone with current trav ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_SuppMinCollectCone_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( Aig_ObjIsTravIdCurrent( p, pObj ) ) // visited + return; + if ( !Aig_ObjIsTravIdPrevious( p, pObj ) ) // not visited, but outside + return; + assert( Aig_ObjIsTravIdPrevious(p, pObj) ); // not visited, inside + assert( Aig_ObjIsNode(pObj) ); + Aig_ObjSetTravIdCurrent( p, pObj ); + Aig_SuppMinCollectCone_rec( p, Aig_ObjFanin0(pObj), vNodes ); + Aig_SuppMinCollectCone_rec( p, Aig_ObjFanin1(pObj), vNodes ); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Collects nodes with the current trav ID rooted in the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_SuppMinCollectCone( Aig_Man_t * p, Aig_Obj_t * pRoot ) +{ + Vec_Ptr_t * vNodes; + assert( !Aig_IsComplement(pRoot) ); +// assert( Aig_ObjIsTravIdCurrent( p, pRoot ) ); + vNodes = Vec_PtrAlloc( 4 ); + Aig_ManIncrementTravId( p ); + Aig_SuppMinCollectCone_rec( p, Aig_Regular(pRoot), vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Marks the nodes in the cone with current trav ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_SuppMinHighlightCone_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + int RetValue; + if ( Aig_ObjIsTravIdCurrent( p, pObj ) ) // visited, marks there + return 1; + if ( Aig_ObjIsTravIdPrevious( p, pObj ) ) // visited, no marks there + return 0; + Aig_ObjSetTravIdPrevious( p, pObj ); + if ( Aig_ObjIsCi(pObj) ) + return 0; + RetValue = Aig_SuppMinHighlightCone_rec( p, Aig_ObjFanin0(pObj) ) | + Aig_SuppMinHighlightCone_rec( p, Aig_ObjFanin1(pObj) ); +// printf( "%d %d\n", Aig_ObjId(pObj), RetValue ); + if ( RetValue ) + Aig_ObjSetTravIdCurrent( p, pObj ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Marks the nodes in the cone with current trav ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_SuppMinHighlightCone( Aig_Man_t * p, Aig_Obj_t * pRoot, Vec_Ptr_t * vOrGate ) +{ + Aig_Obj_t * pLeaf; + int i, RetValue; + assert( !Aig_IsComplement(pRoot) ); + Aig_ManIncrementTravId( p ); + Aig_ManIncrementTravId( p ); + Vec_PtrForEachEntry( Aig_Obj_t *, vOrGate, pLeaf, i ) + Aig_ObjSetTravIdCurrent( p, Aig_Regular(pLeaf) ); + RetValue = Aig_SuppMinHighlightCone_rec( p, pRoot ); + Vec_PtrForEachEntry( Aig_Obj_t *, vOrGate, pLeaf, i ) + Aig_ObjSetTravIdPrevious( p, Aig_Regular(pLeaf) ); + return RetValue; +} + + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_SuppMinCollectSuper_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) +{ + // if the new node is complemented or a PI, another gate begins + if ( Aig_IsComplement(pObj) || Aig_ObjIsCi(pObj) ) // || (Aig_ObjRefs(pObj) > 1) ) + { + Vec_PtrPushUnique( vSuper, Aig_Not(pObj) ); + return; + } + // go through the branches + Aig_SuppMinCollectSuper_rec( Aig_ObjChild0(pObj), vSuper ); + Aig_SuppMinCollectSuper_rec( Aig_ObjChild1(pObj), vSuper ); +} + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_SuppMinCollectSuper( Aig_Obj_t * pObj ) +{ + Vec_Ptr_t * vSuper; + assert( !Aig_IsComplement(pObj) ); + assert( !Aig_ObjIsCi(pObj) ); + vSuper = Vec_PtrAlloc( 4 ); + Aig_SuppMinCollectSuper_rec( Aig_ObjChild0(pObj), vSuper ); + Aig_SuppMinCollectSuper_rec( Aig_ObjChild1(pObj), vSuper ); + return vSuper; +} + +/**Function************************************************************* + + Synopsis [Returns the result of support minimization.] + + Description [Returns internal AIG node that is equal to pFunc under + assignment pCond == 1, or NULL if there is no such node. status is + -1 if condition is not OR; + -2 if cone is too large or no cone; + -3 if no support reduction is possible.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ManSupportMinimization( Aig_Man_t * p, Aig_Obj_t * pCond, Aig_Obj_t * pFunc, int * pStatus ) +{ + int nSuppMax = 16; + Vec_Ptr_t * vOrGate, * vNodes, * vSupp, * vCofs; + Aig_Obj_t * pResult; + int RetValue; + *pStatus = 0; + // if pCond is not OR + if ( !Aig_IsComplement(pCond) || Aig_ObjIsCi(Aig_Regular(pCond)) || Aig_ObjIsConst1(Aig_Regular(pCond)) ) + { + *pStatus = -1; + return NULL; + } + // if pFunc is not a node + if ( !Aig_ObjIsNode(Aig_Regular(pFunc)) ) + { + *pStatus = -2; + return NULL; + } + // collect the multi-input OR gate rooted in the condition + vOrGate = Aig_SuppMinCollectSuper( Aig_Regular(pCond) ); + if ( Vec_PtrSize(vOrGate) > nSuppMax ) + { + Vec_PtrFree( vOrGate ); + *pStatus = -2; + return NULL; + } + // highlight the cone limited by these gates + RetValue = Aig_SuppMinHighlightCone( p, Aig_Regular(pFunc), vOrGate ); + if ( RetValue == 0 ) // no overlap + { + Vec_PtrFree( vOrGate ); + *pStatus = -2; + return NULL; + } + // collect the cone rooted in pFunc limited by vOrGate + vNodes = Aig_SuppMinCollectCone( p, Aig_Regular(pFunc) ); + // collect the support nodes reachable from the cone + vSupp = Aig_SuppMinCollectSupport( p, vNodes ); + if ( Vec_PtrSize(vSupp) > nSuppMax ) + { + Vec_PtrFree( vOrGate ); + Vec_PtrFree( vNodes ); + Vec_PtrFree( vSupp ); + *pStatus = -2; + return NULL; + } + // check if all nodes belonging to OR gate are included in the support + // (if this is not the case, don't-care minimization is not possible) + if ( !Aig_SuppMinGateIsInSupport( p, vOrGate, vSupp ) ) + { + Vec_PtrFree( vOrGate ); + Vec_PtrFree( vNodes ); + Vec_PtrFree( vSupp ); + *pStatus = -3; + return NULL; + } + // create truth tables of all nodes and find the maximal number + // of support varialbles that can be replaced by constants + vCofs = Aig_SuppMinPerform( p, vOrGate, vNodes, vSupp ); + if ( Vec_PtrSize(vCofs) == 0 ) + { + Vec_PtrFree( vCofs ); + Vec_PtrFree( vOrGate ); + Vec_PtrFree( vNodes ); + Vec_PtrFree( vSupp ); + *pStatus = -3; + return NULL; + } + // reconstruct the cone + pResult = Aig_SuppMinReconstruct( p, vCofs, vNodes, vSupp ); + pResult = Aig_NotCond( pResult, Aig_IsComplement(pFunc) ); + Vec_PtrFree( vCofs ); + Vec_PtrFree( vOrGate ); + Vec_PtrFree( vNodes ); + Vec_PtrFree( vSupp ); + return pResult; +} +/**Function************************************************************* + + Synopsis [Testing procedure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManSupportMinimizationTest() +{ + Aig_Man_t * p; + Aig_Obj_t * pFunc, * pCond, * pRes; + int i, Status; + p = Aig_ManStart( 100 ); + for ( i = 0; i < 5; i++ ) + Aig_IthVar(p,i); + pFunc = Aig_Mux( p, Aig_IthVar(p,3), Aig_IthVar(p,1), Aig_IthVar(p,0) ); + pFunc = Aig_Mux( p, Aig_IthVar(p,4), Aig_IthVar(p,2), pFunc ); + pCond = Aig_Or( p, Aig_IthVar(p,3), Aig_IthVar(p,4) ); + pRes = Aig_ManSupportMinimization( p, pCond, pFunc, &Status ); + assert( Status == 0 ); + + Aig_ObjPrint( p, Aig_Regular(pRes) ); printf( "\n" ); + Aig_ObjPrint( p, Aig_ObjFanin0(Aig_Regular(pRes)) ); printf( "\n" ); + Aig_ObjPrint( p, Aig_ObjFanin1(Aig_Regular(pRes)) ); printf( "\n" ); + + Aig_ManStop( p ); +} +void Aig_ManSupportMinimizationTest2() +{ + Aig_Man_t * p; + Aig_Obj_t * node09, * node10, * node11, * node12, * node13, * pRes; + int i, Status; + p = Aig_ManStart( 100 ); + for ( i = 0; i < 3; i++ ) + Aig_IthVar(p,i); + + node09 = Aig_And( p, Aig_IthVar(p,0), Aig_Not(Aig_IthVar(p,1)) ); + node10 = Aig_And( p, Aig_Not(node09), Aig_Not(Aig_IthVar(p,2)) ); + node11 = Aig_And( p, node10, Aig_IthVar(p,1) ); + + node12 = Aig_Or( p, Aig_IthVar(p,1), Aig_IthVar(p,2) ); + node13 = Aig_Or( p, node12, Aig_IthVar(p,0) ); + + pRes = Aig_ManSupportMinimization( p, node13, node11, &Status ); + assert( Status == 0 ); + + printf( "Compl = %d ", Aig_IsComplement(pRes) ); + Aig_ObjPrint( p, Aig_Regular(pRes) ); printf( "\n" ); + if ( Aig_ObjIsNode(Aig_Regular(pRes)) ) + { + Aig_ObjPrint( p, Aig_ObjFanin0(Aig_Regular(pRes)) ); printf( "\n" ); + Aig_ObjPrint( p, Aig_ObjFanin1(Aig_Regular(pRes)) ); printf( "\n" ); + } + + Aig_ManStop( p ); +} +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigFanout.c b/yosys/abc/src/aig/aig/aigFanout.c new file mode 100644 index 00000000000..d2fc1fe3635 --- /dev/null +++ b/yosys/abc/src/aig/aig/aigFanout.c @@ -0,0 +1,194 @@ +/**CFile**************************************************************** + + FileName [aigFanout.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Fanout manipulation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigFanout.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +ABC_NAMESPACE_IMPL_START + + +// 0: first iFan +// 1: prev iFan0 +// 2: prev iFan1 +// 3: next iFan0 +// 4: next iFan1 + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Aig_FanoutCreate( int FanId, int Num ) { assert( Num < 2 ); return (FanId << 1) | Num; } +static inline int * Aig_FanoutObj( int * pData, int ObjId ) { return pData + 5*ObjId; } +static inline int * Aig_FanoutPrev( int * pData, int iFan ) { return pData + 5*(iFan >> 1) + 1 + (iFan & 1); } +static inline int * Aig_FanoutNext( int * pData, int iFan ) { return pData + 5*(iFan >> 1) + 3 + (iFan & 1); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Create fanout for all objects in the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManFanoutStart( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + assert( Aig_ManBufNum(p) == 0 ); + // allocate fanout datastructure + assert( p->pFanData == NULL ); + p->nFansAlloc = 2 * Aig_ManObjNumMax(p); + if ( p->nFansAlloc < (1<<12) ) + p->nFansAlloc = (1<<12); + p->pFanData = ABC_ALLOC( int, 5 * p->nFansAlloc ); + memset( p->pFanData, 0, sizeof(int) * 5 * p->nFansAlloc ); + // add fanouts for all objects + Aig_ManForEachObj( p, pObj, i ) + { + if ( Aig_ObjChild0(pObj) ) + Aig_ObjAddFanout( p, Aig_ObjFanin0(pObj), pObj ); + if ( Aig_ObjChild1(pObj) ) + Aig_ObjAddFanout( p, Aig_ObjFanin1(pObj), pObj ); + } +} + +/**Function************************************************************* + + Synopsis [Deletes fanout for all objects in the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManFanoutStop( Aig_Man_t * p ) +{ + assert( p->pFanData != NULL ); + ABC_FREE( p->pFanData ); + p->nFansAlloc = 0; +} + +/**Function************************************************************* + + Synopsis [Adds fanout (pFanout) of node (pObj).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjAddFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout ) +{ + int iFan, * pFirst, * pPrevC, * pNextC, * pPrev, * pNext; + assert( p->pFanData ); + assert( !Aig_IsComplement(pObj) && !Aig_IsComplement(pFanout) ); + assert( pFanout->Id > 0 ); + if ( pObj->Id >= p->nFansAlloc || pFanout->Id >= p->nFansAlloc ) + { + int nFansAlloc = 2 * Abc_MaxInt( pObj->Id, pFanout->Id ); + p->pFanData = ABC_REALLOC( int, p->pFanData, 5 * nFansAlloc ); + memset( p->pFanData + 5 * p->nFansAlloc, 0, sizeof(int) * 5 * (nFansAlloc - p->nFansAlloc) ); + p->nFansAlloc = nFansAlloc; + } + assert( pObj->Id < p->nFansAlloc && pFanout->Id < p->nFansAlloc ); + iFan = Aig_FanoutCreate( pFanout->Id, Aig_ObjWhatFanin(pFanout, pObj) ); + pPrevC = Aig_FanoutPrev( p->pFanData, iFan ); + pNextC = Aig_FanoutNext( p->pFanData, iFan ); + pFirst = Aig_FanoutObj( p->pFanData, pObj->Id ); + if ( *pFirst == 0 ) + { + *pFirst = iFan; + *pPrevC = iFan; + *pNextC = iFan; + } + else + { + pPrev = Aig_FanoutPrev( p->pFanData, *pFirst ); + pNext = Aig_FanoutNext( p->pFanData, *pPrev ); + assert( *pNext == *pFirst ); + *pPrevC = *pPrev; + *pNextC = *pFirst; + *pPrev = iFan; + *pNext = iFan; + } +} + +/**Function************************************************************* + + Synopsis [Removes fanout (pFanout) of node (pObj).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjRemoveFanout( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFanout ) +{ + int iFan, * pFirst, * pPrevC, * pNextC, * pPrev, * pNext; + assert( p->pFanData && pObj->Id < p->nFansAlloc && pFanout->Id < p->nFansAlloc ); + assert( !Aig_IsComplement(pObj) && !Aig_IsComplement(pFanout) ); + assert( pFanout->Id > 0 ); + iFan = Aig_FanoutCreate( pFanout->Id, Aig_ObjWhatFanin(pFanout, pObj) ); + pPrevC = Aig_FanoutPrev( p->pFanData, iFan ); + pNextC = Aig_FanoutNext( p->pFanData, iFan ); + pPrev = Aig_FanoutPrev( p->pFanData, *pNextC ); + pNext = Aig_FanoutNext( p->pFanData, *pPrevC ); + assert( *pPrev == iFan ); + assert( *pNext == iFan ); + pFirst = Aig_FanoutObj( p->pFanData, pObj->Id ); + assert( *pFirst > 0 ); + if ( *pFirst == iFan ) + { + if ( *pNextC == iFan ) + { + *pFirst = 0; + *pPrev = 0; + *pNext = 0; + *pPrevC = 0; + *pNextC = 0; + return; + } + *pFirst = *pNextC; + } + *pPrev = *pPrevC; + *pNext = *pNextC; + *pPrevC = 0; + *pNextC = 0; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigFrames.c b/yosys/abc/src/aig/aig/aigFrames.c new file mode 100644 index 00000000000..2d11104453d --- /dev/null +++ b/yosys/abc/src/aig/aig/aigFrames.c @@ -0,0 +1,140 @@ +/**CFile**************************************************************** + + FileName [aigFrames.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Performs timeframe expansion of the AIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigFrames.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline Aig_Obj_t * Aig_ObjFrames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return pObjMap[nFs*pObj->Id + i]; } +static inline void Aig_ObjSetFrames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { pObjMap[nFs*pObj->Id + i] = pNode; } + +static inline Aig_Obj_t * Aig_ObjChild0Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin0(pObj)? Aig_NotCond(Aig_ObjFrames(pObjMap,nFs,Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL; } +static inline Aig_Obj_t * Aig_ObjChild1Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin1(pObj)? Aig_NotCond(Aig_ObjFrames(pObjMap,nFs,Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs timeframe expansion of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManFrames( Aig_Man_t * pAig, int nFs, int fInit, int fOuts, int fRegs, int fEnlarge, Aig_Obj_t *** ppObjMap ) +{ + Aig_Man_t * pFrames; + Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew; + Aig_Obj_t ** pObjMap; + int i, f; + + // create mapping for the frames nodes + pObjMap = ABC_ALLOC( Aig_Obj_t *, nFs * Aig_ManObjNumMax(pAig) ); + memset( pObjMap, 0, sizeof(Aig_Obj_t *) * nFs * Aig_ManObjNumMax(pAig) ); + + // start the fraig package + pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFs ); + pFrames->pName = Abc_UtilStrsav( pAig->pName ); + pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); + // map constant nodes + for ( f = 0; f < nFs; f++ ) + Aig_ObjSetFrames( pObjMap, nFs, Aig_ManConst1(pAig), f, Aig_ManConst1(pFrames) ); + // create PI nodes for the frames + for ( f = 0; f < nFs; f++ ) + Aig_ManForEachPiSeq( pAig, pObj, i ) + Aig_ObjSetFrames( pObjMap, nFs, pObj, f, Aig_ObjCreateCi(pFrames) ); + // set initial state for the latches + if ( fInit ) + { + Aig_ManForEachLoSeq( pAig, pObj, i ) + Aig_ObjSetFrames( pObjMap, nFs, pObj, 0, Aig_ManConst0(pFrames) ); + } + else + { + Aig_ManForEachLoSeq( pAig, pObj, i ) + Aig_ObjSetFrames( pObjMap, nFs, pObj, 0, Aig_ObjCreateCi(pFrames) ); + } + + // add timeframes + for ( f = 0; f < nFs; f++ ) + { +// printf( "Frame = %d.\n", f ); + // add internal nodes of this frame + Aig_ManForEachNode( pAig, pObj, i ) + { +// Aig_Obj_t * pFanin0 = Aig_ObjChild0Frames(pObjMap,nFs,pObj,f); +// Aig_Obj_t * pFanin1 = Aig_ObjChild1Frames(pObjMap,nFs,pObj,f); +// printf( "Node = %3d. Fanin0 = %3d. Fanin1 = %3d.\n", pObj->Id, Aig_Regular(pFanin0)->Id, Aig_Regular(pFanin1)->Id ); + pObjNew = Aig_And( pFrames, Aig_ObjChild0Frames(pObjMap,nFs,pObj,f), Aig_ObjChild1Frames(pObjMap,nFs,pObj,f) ); + Aig_ObjSetFrames( pObjMap, nFs, pObj, f, pObjNew ); + } + // set the latch inputs and copy them into the latch outputs of the next frame + Aig_ManForEachLiLoSeq( pAig, pObjLi, pObjLo, i ) + { + pObjNew = Aig_ObjChild0Frames(pObjMap,nFs,pObjLi,f); + if ( f < nFs - 1 ) + Aig_ObjSetFrames( pObjMap, nFs, pObjLo, f+1, pObjNew ); + } + } + if ( fOuts ) + { + for ( f = fEnlarge?nFs-1:0; f < nFs; f++ ) + Aig_ManForEachPoSeq( pAig, pObj, i ) + { + pObjNew = Aig_ObjCreateCo( pFrames, Aig_ObjChild0Frames(pObjMap,nFs,pObj,f) ); + Aig_ObjSetFrames( pObjMap, nFs, pObj, f, pObjNew ); + } + } + if ( fRegs ) + { + pFrames->nRegs = pAig->nRegs; + Aig_ManForEachLiSeq( pAig, pObj, i ) + { + pObjNew = Aig_ObjCreateCo( pFrames, Aig_ObjChild0Frames(pObjMap,nFs,pObj,fEnlarge?0:nFs-1) ); + Aig_ObjSetFrames( pObjMap, nFs, pObj, nFs-1, pObjNew ); + } + Aig_ManSetRegNum( pFrames, Aig_ManRegNum(pAig) ); + } + Aig_ManCleanup( pFrames ); + // return the new manager + if ( ppObjMap ) + *ppObjMap = pObjMap; + else + ABC_FREE( pObjMap ); + return pFrames; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigInter.c b/yosys/abc/src/aig/aig/aigInter.c new file mode 100644 index 00000000000..f09a41f8e09 --- /dev/null +++ b/yosys/abc/src/aig/aig/aigInter.c @@ -0,0 +1,301 @@ +/**CFile**************************************************************** + + FileName [aigInter.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Interpolate two AIGs.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigInter.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" +#include "sat/cnf/cnf.h" +#include "sat/bsat/satStore.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern abctime timeCnf; +extern abctime timeSat; +extern abctime timeInt; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManInterFast( Aig_Man_t * pManOn, Aig_Man_t * pManOff, int fVerbose ) +{ + sat_solver * pSat; + Cnf_Dat_t * pCnfOn, * pCnfOff; + Aig_Obj_t * pObj, * pObj2; + int Lits[3], status, i; +// abctime clk = Abc_Clock(); + + assert( Aig_ManCiNum(pManOn) == Aig_ManCiNum(pManOff) ); + assert( Aig_ManCoNum(pManOn) == Aig_ManCoNum(pManOff) ); + + // derive CNFs + pManOn->nRegs = Aig_ManCoNum(pManOn); + pCnfOn = Cnf_Derive( pManOn, Aig_ManCoNum(pManOn) ); + pManOn->nRegs = 0; + + pManOff->nRegs = Aig_ManCoNum(pManOn); + pCnfOff = Cnf_Derive( pManOff, Aig_ManCoNum(pManOff) ); + pManOff->nRegs = 0; + +// pCnfOn = Cnf_DeriveSimple( pManOn, Aig_ManCoNum(pManOn) ); +// pCnfOff = Cnf_DeriveSimple( pManOff, Aig_ManCoNum(pManOn) ); + Cnf_DataLift( pCnfOff, pCnfOn->nVars ); + + // start the solver + pSat = sat_solver_new(); + sat_solver_setnvars( pSat, pCnfOn->nVars + pCnfOff->nVars ); + + // add clauses of A + for ( i = 0; i < pCnfOn->nClauses; i++ ) + { + if ( !sat_solver_addclause( pSat, pCnfOn->pClauses[i], pCnfOn->pClauses[i+1] ) ) + { + Cnf_DataFree( pCnfOn ); + Cnf_DataFree( pCnfOff ); + sat_solver_delete( pSat ); + return; + } + } + + // add clauses of B + for ( i = 0; i < pCnfOff->nClauses; i++ ) + { + if ( !sat_solver_addclause( pSat, pCnfOff->pClauses[i], pCnfOff->pClauses[i+1] ) ) + { + Cnf_DataFree( pCnfOn ); + Cnf_DataFree( pCnfOff ); + sat_solver_delete( pSat ); + return; + } + } + + // add PI clauses + // collect the common variables + Aig_ManForEachCi( pManOn, pObj, i ) + { + pObj2 = Aig_ManCi( pManOff, i ); + + Lits[0] = toLitCond( pCnfOn->pVarNums[pObj->Id], 0 ); + Lits[1] = toLitCond( pCnfOff->pVarNums[pObj2->Id], 1 ); + if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) + assert( 0 ); + Lits[0] = toLitCond( pCnfOn->pVarNums[pObj->Id], 1 ); + Lits[1] = toLitCond( pCnfOff->pVarNums[pObj2->Id], 0 ); + if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) + assert( 0 ); + } + status = sat_solver_simplify( pSat ); + assert( status != 0 ); + + // solve incremental SAT problems + Aig_ManForEachCo( pManOn, pObj, i ) + { + pObj2 = Aig_ManCo( pManOff, i ); + + Lits[0] = toLitCond( pCnfOn->pVarNums[pObj->Id], 0 ); + Lits[1] = toLitCond( pCnfOff->pVarNums[pObj2->Id], 0 ); + status = sat_solver_solve( pSat, Lits, Lits+2, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + if ( status != l_False ) + printf( "The incremental SAT problem is not UNSAT.\n" ); + } + Cnf_DataFree( pCnfOn ); + Cnf_DataFree( pCnfOff ); + sat_solver_delete( pSat ); +// ABC_PRT( "Fast interpolation time", Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManInter( Aig_Man_t * pManOn, Aig_Man_t * pManOff, int fRelation, int fVerbose ) +{ + void * pSatCnf = NULL; + Inta_Man_t * pManInter; + Aig_Man_t * pRes; + sat_solver * pSat; + Cnf_Dat_t * pCnfOn, * pCnfOff; + Vec_Int_t * vVarsAB; + Aig_Obj_t * pObj, * pObj2; + int Lits[3], status, i; + abctime clk; + int iLast = -1; // Suppress "might be used uninitialized" + + assert( Aig_ManCiNum(pManOn) == Aig_ManCiNum(pManOff) ); + +clk = Abc_Clock(); + // derive CNFs +// pCnfOn = Cnf_Derive( pManOn, 0 ); +// pCnfOff = Cnf_Derive( pManOff, 0 ); + pCnfOn = Cnf_DeriveSimple( pManOn, 0 ); + pCnfOff = Cnf_DeriveSimple( pManOff, 0 ); + Cnf_DataLift( pCnfOff, pCnfOn->nVars ); +timeCnf += Abc_Clock() - clk; + +clk = Abc_Clock(); + // start the solver + pSat = sat_solver_new(); + sat_solver_store_alloc( pSat ); + sat_solver_setnvars( pSat, pCnfOn->nVars + pCnfOff->nVars ); + + // add clauses of A + for ( i = 0; i < pCnfOn->nClauses; i++ ) + { + if ( !sat_solver_addclause( pSat, pCnfOn->pClauses[i], pCnfOn->pClauses[i+1] ) ) + { + Cnf_DataFree( pCnfOn ); + Cnf_DataFree( pCnfOff ); + sat_solver_delete( pSat ); + return NULL; + } + } + sat_solver_store_mark_clauses_a( pSat ); + + // update the last clause + if ( fRelation ) + { + extern int sat_solver_store_change_last( sat_solver * pSat ); + iLast = sat_solver_store_change_last( pSat ); + } + + // add clauses of B + for ( i = 0; i < pCnfOff->nClauses; i++ ) + { + if ( !sat_solver_addclause( pSat, pCnfOff->pClauses[i], pCnfOff->pClauses[i+1] ) ) + { + Cnf_DataFree( pCnfOn ); + Cnf_DataFree( pCnfOff ); + sat_solver_delete( pSat ); + return NULL; + } + } + + // add PI clauses + // collect the common variables + vVarsAB = Vec_IntAlloc( Aig_ManCiNum(pManOn) ); + if ( fRelation ) + Vec_IntPush( vVarsAB, iLast ); + + Aig_ManForEachCi( pManOn, pObj, i ) + { + Vec_IntPush( vVarsAB, pCnfOn->pVarNums[pObj->Id] ); + pObj2 = Aig_ManCi( pManOff, i ); + + Lits[0] = toLitCond( pCnfOn->pVarNums[pObj->Id], 0 ); + Lits[1] = toLitCond( pCnfOff->pVarNums[pObj2->Id], 1 ); + if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) + assert( 0 ); + Lits[0] = toLitCond( pCnfOn->pVarNums[pObj->Id], 1 ); + Lits[1] = toLitCond( pCnfOff->pVarNums[pObj2->Id], 0 ); + if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) + assert( 0 ); + } + Cnf_DataFree( pCnfOn ); + Cnf_DataFree( pCnfOff ); + sat_solver_store_mark_roots( pSat ); + +/* + status = sat_solver_simplify(pSat); + if ( status == 0 ) + { + Vec_IntFree( vVarsAB ); + Cnf_DataFree( pCnfOn ); + Cnf_DataFree( pCnfOff ); + sat_solver_delete( pSat ); + return NULL; + } +*/ + + // solve the problem + status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); +timeSat += Abc_Clock() - clk; + if ( status == l_False ) + { + pSatCnf = sat_solver_store_release( pSat ); +// printf( "unsat\n" ); + } + else if ( status == l_True ) + { +// printf( "sat\n" ); + } + else + { +// printf( "undef\n" ); + } + sat_solver_delete( pSat ); + if ( pSatCnf == NULL ) + { + printf( "The SAT problem is not unsat.\n" ); + Vec_IntFree( vVarsAB ); + return NULL; + } + + // create the resulting manager +clk = Abc_Clock(); + pManInter = Inta_ManAlloc(); + pRes = (Aig_Man_t *)Inta_ManInterpolate( pManInter, (Sto_Man_t *)pSatCnf, 0, vVarsAB, fVerbose ); + Inta_ManFree( pManInter ); +timeInt += Abc_Clock() - clk; +/* + // test UNSAT core computation + { + Intp_Man_t * pManProof; + Vec_Int_t * vCore; + pManProof = Intp_ManAlloc(); + vCore = Intp_ManUnsatCore( pManProof, pSatCnf, 0 ); + Intp_ManFree( pManProof ); + Vec_IntFree( vCore ); + } +*/ + Vec_IntFree( vVarsAB ); + Sto_ManFree( (Sto_Man_t *)pSatCnf ); + +// Ioa_WriteAiger( pRes, "inter2.aig", 0, 0 ); + return pRes; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigJust.c b/yosys/abc/src/aig/aig/aigJust.c new file mode 100644 index 00000000000..c420b2d9c8e --- /dev/null +++ b/yosys/abc/src/aig/aig/aigJust.c @@ -0,0 +1,316 @@ +/**CFile**************************************************************** + + FileName [aigJust.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Justification of node values.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigJust.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define AIG_VAL0 1 +#define AIG_VAL1 2 +#define AIG_VALX 3 + +// storing ternary values +static inline int Aig_ObjSetTerValue( Aig_Obj_t * pNode, int Value ) +{ + assert( Value ); + pNode->fMarkA = (Value & 1); + pNode->fMarkB = ((Value >> 1) & 1); + return Value; +} +static inline int Aig_ObjGetTerValue( Aig_Obj_t * pNode ) +{ + return (pNode->fMarkB << 1) | pNode->fMarkA; +} + +// working with ternary values +static inline int Aig_ObjNotTerValue( int Value ) +{ + if ( Value == AIG_VAL1 ) + return AIG_VAL0; + if ( Value == AIG_VAL0 ) + return AIG_VAL1; + return AIG_VALX; +} +static inline int Aig_ObjAndTerValue( int Value0, int Value1 ) +{ + if ( Value0 == AIG_VAL0 || Value1 == AIG_VAL0 ) + return AIG_VAL0; + if ( Value0 == AIG_VAL1 && Value1 == AIG_VAL1 ) + return AIG_VAL1; + return AIG_VALX; +} +static inline int Aig_ObjNotCondTerValue( int Value, int Cond ) +{ + return Cond ? Aig_ObjNotTerValue( Value ) : Value; +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns value (0 or 1) or X if unassigned.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_ObjSatValue( Aig_Man_t * pAig, Aig_Obj_t * pNode, int fCompl ) +{ + if ( Aig_ObjIsTravIdCurrent(pAig, pNode) ) + return (pNode->fMarkA ^ fCompl) ? AIG_VAL1 : AIG_VAL0; + return AIG_VALX; +} + +/**Function************************************************************* + + Synopsis [Recursively searched for a satisfying assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_NtkFindSatAssign_rec( Aig_Man_t * pAig, Aig_Obj_t * pNode, int Value, Vec_Int_t * vSuppLits, int Heur ) +{ + int Value0, Value1; +// ++Heur; + if ( Aig_ObjIsConst1(pNode) ) + return 1; + if ( Aig_ObjIsTravIdCurrent(pAig, pNode) ) + return ((int)pNode->fMarkA == Value); + Aig_ObjSetTravIdCurrent(pAig, pNode); + pNode->fMarkA = Value; + if ( Aig_ObjIsCi(pNode) ) + { +// if ( Aig_ObjId(pNode) % 1000 == 0 ) +// Value ^= 1; + if ( vSuppLits ) + Vec_IntPush( vSuppLits, Abc_Var2Lit( Aig_ObjCioId(pNode), !Value ) ); + return 1; + } + assert( Aig_ObjIsNode(pNode) ); + // propagation + if ( Value ) + { + if ( !Aig_NtkFindSatAssign_rec(pAig, Aig_ObjFanin0(pNode), !Aig_ObjFaninC0(pNode), vSuppLits, Heur) ) + return 0; + return Aig_NtkFindSatAssign_rec(pAig, Aig_ObjFanin1(pNode), !Aig_ObjFaninC1(pNode), vSuppLits, Heur); + } + // justification + Value0 = Aig_ObjSatValue( pAig, Aig_ObjFanin0(pNode), Aig_ObjFaninC0(pNode) ); + if ( Value0 == AIG_VAL0 ) + return 1; + Value1 = Aig_ObjSatValue( pAig, Aig_ObjFanin1(pNode), Aig_ObjFaninC1(pNode) ); + if ( Value1 == AIG_VAL0 ) + return 1; + if ( Value0 == AIG_VAL1 && Value1 == AIG_VAL1 ) + return 0; + if ( Value0 == AIG_VAL1 ) + return Aig_NtkFindSatAssign_rec(pAig, Aig_ObjFanin1(pNode), Aig_ObjFaninC1(pNode), vSuppLits, Heur); + if ( Value1 == AIG_VAL1 ) + return Aig_NtkFindSatAssign_rec(pAig, Aig_ObjFanin0(pNode), Aig_ObjFaninC0(pNode), vSuppLits, Heur); + assert( Value0 == AIG_VALX && Value1 == AIG_VALX ); + // decision making +// if ( rand() % 10 == Heur ) +// if ( Aig_ObjId(pNode) % 8 == Heur ) + if ( ++Heur % 8 == 0 ) + return Aig_NtkFindSatAssign_rec(pAig, Aig_ObjFanin1(pNode), Aig_ObjFaninC1(pNode), vSuppLits, Heur); + else + return Aig_NtkFindSatAssign_rec(pAig, Aig_ObjFanin0(pNode), Aig_ObjFaninC0(pNode), vSuppLits, Heur); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if SAT assignment is found; 0 otherwise.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjFindSatAssign( Aig_Man_t * pAig, Aig_Obj_t * pNode, int Value, Vec_Int_t * vSuppLits ) +{ + int i; + if ( Aig_ObjIsCo(pNode) ) + return Aig_ObjFindSatAssign( pAig, Aig_ObjFanin0(pNode), Value ^ Aig_ObjFaninC0(pNode), vSuppLits ); + for ( i = 0; i < 8; i++ ) + { + Vec_IntClear( vSuppLits ); + Aig_ManIncrementTravId( pAig ); + if ( Aig_NtkFindSatAssign_rec( pAig, pNode, Value, vSuppLits, i ) ) + return 1; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjTerSimulate_rec( Aig_Man_t * pAig, Aig_Obj_t * pNode ) +{ + int Value0, Value1; + if ( Aig_ObjIsConst1(pNode) ) + return AIG_VAL1; + if ( Aig_ObjIsTravIdCurrent(pAig, pNode) ) + return Aig_ObjGetTerValue( pNode ); + Aig_ObjSetTravIdCurrent( pAig, pNode ); + if ( Aig_ObjIsCi(pNode) ) + return Aig_ObjSetTerValue( pNode, AIG_VALX ); + Value0 = Aig_ObjNotCondTerValue( Aig_ObjTerSimulate_rec(pAig, Aig_ObjFanin0(pNode)), Aig_ObjFaninC0(pNode) ); + if ( Aig_ObjIsCo(pNode) || Value0 == AIG_VAL0 ) + return Aig_ObjSetTerValue( pNode, Value0 ); + assert( Aig_ObjIsNode(pNode) ); + Value1 = Aig_ObjNotCondTerValue( Aig_ObjTerSimulate_rec(pAig, Aig_ObjFanin1(pNode)), Aig_ObjFaninC1(pNode) ); + return Aig_ObjSetTerValue( pNode, Aig_ObjAndTerValue(Value0, Value1) ); +} + +/**Function************************************************************* + + Synopsis [Returns value of the object under input assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjTerSimulate( Aig_Man_t * pAig, Aig_Obj_t * pNode, Vec_Int_t * vSuppLits ) +{ + Aig_Obj_t * pObj; + int i, Entry; + Aig_ManIncrementTravId( pAig ); + Vec_IntForEachEntry( vSuppLits, Entry, i ) + { + pObj = Aig_ManCi( pAig, Abc_Lit2Var(Entry) ); + Aig_ObjSetTerValue( pObj, Abc_LitIsCompl(Entry) ? AIG_VAL0 : AIG_VAL1 ); + Aig_ObjSetTravIdCurrent( pAig, pObj ); +//printf( "%d ", Entry ); + } +//printf( "\n" ); + return Aig_ObjTerSimulate_rec( pAig, pNode ); +} + + +typedef struct Aig_ManPack_t_ Aig_ManPack_t; +extern Aig_ManPack_t * Aig_ManPackStart( Aig_Man_t * pAig ); +extern void Aig_ManPackStop( Aig_ManPack_t * p ); +extern void Aig_ManPackAddPattern( Aig_ManPack_t * p, Vec_Int_t * vLits ); +extern Vec_Int_t * Aig_ManPackConstNodes( Aig_ManPack_t * p ); + +/**Function************************************************************* + + Synopsis [Testing of the framework.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManJustExperiment( Aig_Man_t * pAig ) +{ + Aig_ManPack_t * pPack; + Vec_Int_t * vSuppLits, * vNodes; + Aig_Obj_t * pObj; + int i; + abctime clk = Abc_Clock(); + int Count0 = 0, Count0f = 0, Count1 = 0, Count1f = 0; + int nTotalLits = 0; + vSuppLits = Vec_IntAlloc( 100 ); + pPack = Aig_ManPackStart( pAig ); + vNodes = Aig_ManPackConstNodes( pPack ); +// Aig_ManForEachCo( pAig, pObj, i ) + Aig_ManForEachObjVec( vNodes, pAig, pObj, i ) + { + if ( pObj->fPhase ) // const 1 + { + if ( Aig_ObjFindSatAssign(pAig, pObj, 0, vSuppLits) ) + { +// assert( Aig_ObjTerSimulate(pAig, pObj, vSuppLits) == AIG_VAL0 ); +// if ( Aig_ObjTerSimulate(pAig, pObj, vSuppLits) != AIG_VAL0 ) +// printf( "Justification error!\n" ); + Count0++; + nTotalLits += Vec_IntSize(vSuppLits); + Aig_ManPackAddPattern( pPack, vSuppLits ); + } + else + Count0f++; + } + else + { + if ( Aig_ObjFindSatAssign(pAig, pObj, 1, vSuppLits) ) + { +// assert( Aig_ObjTerSimulate(pAig, pObj, vSuppLits) == AIG_VAL1 ); +// if ( Aig_ObjTerSimulate(pAig, pObj, vSuppLits) != AIG_VAL1 ) +// printf( "Justification error!\n" ); + Count1++; + nTotalLits += Vec_IntSize(vSuppLits); + Aig_ManPackAddPattern( pPack, vSuppLits ); + } + else + Count1f++; + } + } + Vec_IntFree( vSuppLits ); + printf( "PO =%6d. C0 =%6d. C0f =%6d. C1 =%6d. C1f =%6d. (%6.2f %%) Ave =%4.1f ", + Aig_ManCoNum(pAig), Count0, Count0f, Count1, Count1f, 100.0*(Count0+Count1)/Aig_ManCoNum(pAig), 1.0*nTotalLits/(Count0+Count1) ); + Abc_PrintTime( 1, "T", Abc_Clock() - clk ); + Aig_ManCleanMarkAB( pAig ); + Aig_ManPackStop( pPack ); + Vec_IntFree( vNodes ); +} + + + + + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigMan.c b/yosys/abc/src/aig/aig/aigMan.c new file mode 100644 index 00000000000..246e050190c --- /dev/null +++ b/yosys/abc/src/aig/aig/aigMan.c @@ -0,0 +1,486 @@ +/**CFile**************************************************************** + + FileName [aigMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [AIG manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigMan.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" +#include "misc/tim/tim.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the AIG manager.] + + Description [The argument of this procedure is a soft limit on the + the number of nodes, or 0 if the limit is unknown.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManStart( int nNodesMax ) +{ + Aig_Man_t * p; + if ( nNodesMax <= 0 ) + nNodesMax = 10007; + // start the manager + p = ABC_ALLOC( Aig_Man_t, 1 ); + memset( p, 0, sizeof(Aig_Man_t) ); + // perform initializations + p->nTravIds = 1; + p->fCatchExor = 0; + // allocate arrays for nodes + p->vCis = Vec_PtrAlloc( 100 ); + p->vCos = Vec_PtrAlloc( 100 ); + p->vObjs = Vec_PtrAlloc( 1000 ); + p->vBufs = Vec_PtrAlloc( 100 ); + //--jlong -- begin + p->unfold2_type_I = Vec_PtrAlloc( 4); + p->unfold2_type_II = Vec_PtrAlloc( 4); + //--jlong -- end + // prepare the internal memory manager + p->pMemObjs = Aig_MmFixedStart( sizeof(Aig_Obj_t), nNodesMax ); + // create the constant node + p->pConst1 = Aig_ManFetchMemory( p ); + p->pConst1->Type = AIG_OBJ_CONST1; + p->pConst1->fPhase = 1; + p->nObjs[AIG_OBJ_CONST1]++; + // start the table + p->nTableSize = Abc_PrimeCudd( nNodesMax ); + p->pTable = ABC_ALLOC( Aig_Obj_t *, p->nTableSize ); + memset( p->pTable, 0, sizeof(Aig_Obj_t *) * p->nTableSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManStartFrom( Aig_Man_t * p ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pObjNew; + int i; + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + // create the PIs + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachCi( p, pObj, i ) + { + pObjNew = Aig_ObjCreateCi( pNew ); + pObjNew->Level = pObj->Level; + pObj->pData = pObjNew; + } + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager recursively.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ManDup_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pObjNew; + if ( pObj->pData ) + return (Aig_Obj_t *)pObj->pData; + Aig_ManDup_rec( pNew, p, Aig_ObjFanin0(pObj) ); + if ( Aig_ObjIsBuf(pObj) ) + return (Aig_Obj_t *)(pObj->pData = Aig_ObjChild0Copy(pObj)); + Aig_ManDup_rec( pNew, p, Aig_ObjFanin1(pObj) ); + pObjNew = Aig_Oper( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj), Aig_ObjType(pObj) ); + return (Aig_Obj_t *)(pObj->pData = pObjNew); +} + +/**Function************************************************************* + + Synopsis [Extracts the miter composed of XOR of the two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManExtractMiter( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj; + int i; + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + // create the PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachCi( p, pObj, i ) + pObj->pData = Aig_ObjCreateCi(pNew); + // dump the nodes + Aig_ManDup_rec( pNew, p, pNode1 ); + Aig_ManDup_rec( pNew, p, pNode2 ); + // construct the EXOR + pObj = Aig_Exor( pNew, (Aig_Obj_t *)pNode1->pData, (Aig_Obj_t *)pNode2->pData ); + pObj = Aig_NotCond( pObj, Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) ); + // add the PO + Aig_ObjCreateCo( pNew, pObj ); + // check the resulting network + if ( !Aig_ManCheck(pNew) ) + printf( "Aig_ManExtractMiter(): The check has failed.\n" ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Stops the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManStop( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + if ( p->time1 ) { ABC_PRT( "time1", p->time1 ); } + if ( p->time2 ) { ABC_PRT( "time2", p->time2 ); } + // make sure the nodes have clean marks + Aig_ManForEachObj( p, pObj, i ) + assert( !pObj->fMarkA && !pObj->fMarkB ); + Tim_ManStopP( (Tim_Man_t **)&p->pManTime ); + if ( p->pFanData ) + Aig_ManFanoutStop( p ); + if ( p->pManExdc ) + Aig_ManStop( p->pManExdc ); +// Aig_TableProfile( p ); + Aig_MmFixedStop( p->pMemObjs, 0 ); + Vec_PtrFreeP( &p->vCis ); + Vec_PtrFreeP( &p->vCos ); + Vec_PtrFreeP( &p->vObjs ); + Vec_PtrFreeP( &p->vBufs ); + //--jlong -- begin + Vec_PtrFreeP( &p->unfold2_type_I ); + Vec_PtrFreeP( &p->unfold2_type_II ); + //--jlong -- end + Vec_IntFreeP( &p->vLevelR ); + Vec_VecFreeP( &p->vLevels ); + Vec_IntFreeP( &p->vFlopNums ); + Vec_IntFreeP( &p->vFlopReprs ); + Vec_VecFreeP( (Vec_Vec_t **)&p->vOnehots ); + Vec_VecFreeP( &p->vClockDoms ); + Vec_IntFreeP( &p->vProbs ); + Vec_IntFreeP( &p->vCiNumsOrig ); + Vec_PtrFreeP( &p->vMapped ); + if ( p->vSeqModelVec ) + Vec_PtrFreeFree( p->vSeqModelVec ); + ABC_FREE( p->pTerSimData ); + ABC_FREE( p->pFastSim ); + ABC_FREE( p->pData ); + ABC_FREE( p->pSeqModel ); + ABC_FREE( p->pName ); + ABC_FREE( p->pSpec ); + ABC_FREE( p->pObjCopies ); + ABC_FREE( p->pReprs ); + ABC_FREE( p->pEquivs ); + ABC_FREE( p->pTable ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Stops the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManStopP( Aig_Man_t ** p ) +{ + if ( *p == NULL ) + return; + Aig_ManStop( *p ); + *p = NULL; +} + +/**Function************************************************************* + + Synopsis [Removes combinational logic that does not feed into POs.] + + Description [Returns the number of dangling nodes removed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManCleanup( Aig_Man_t * p ) +{ + Vec_Ptr_t * vObjs; + Aig_Obj_t * pNode; + int i, nNodesOld = Aig_ManNodeNum(p); + // collect roots of dangling nodes + vObjs = Vec_PtrAlloc( 100 ); + Aig_ManForEachObj( p, pNode, i ) + if ( Aig_ObjIsNode(pNode) && Aig_ObjRefs(pNode) == 0 ) + Vec_PtrPush( vObjs, pNode ); + // recursively remove dangling nodes + Vec_PtrForEachEntry( Aig_Obj_t *, vObjs, pNode, i ) + Aig_ObjDelete_rec( p, pNode, 1 ); + Vec_PtrFree( vObjs ); + return nNodesOld - Aig_ManNodeNum(p); +} + +/**Function************************************************************* + + Synopsis [Adds POs for the nodes that otherwise would be dangling.] + + Description [Returns the number of POs added.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManAntiCleanup( Aig_Man_t * p ) +{ + Aig_Obj_t * pNode; + int i, nNodesOld = Aig_ManCoNum(p); + Aig_ManForEachObj( p, pNode, i ) + if ( Aig_ObjIsNode(pNode) && Aig_ObjRefs(pNode) == 0 ) + Aig_ObjCreateCo( p, pNode ); + return nNodesOld - Aig_ManCoNum(p); +} + +/**Function************************************************************* + + Synopsis [Removes PIs without fanouts.] + + Description [Returns the number of PIs removed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManCiCleanup( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, k = 0, nPisOld = Aig_ManCiNum(p); + Vec_PtrForEachEntry( Aig_Obj_t *, p->vCis, pObj, i ) + { + if ( i >= Aig_ManCiNum(p) - Aig_ManRegNum(p) ) + Vec_PtrWriteEntry( p->vCis, k++, pObj ); + else if ( Aig_ObjRefs(pObj) > 0 ) + Vec_PtrWriteEntry( p->vCis, k++, pObj ); + else + Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); + } + Vec_PtrShrink( p->vCis, k ); + p->nObjs[AIG_OBJ_CI] = Vec_PtrSize( p->vCis ); + if ( Aig_ManRegNum(p) ) + p->nTruePis = Aig_ManCiNum(p) - Aig_ManRegNum(p); + return nPisOld - Aig_ManCiNum(p); +} + +/**Function************************************************************* + + Synopsis [Removes POs with constant input.] + + Description [Returns the number of POs removed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManCoCleanup( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, k = 0, nPosOld = Aig_ManCoNum(p); + Vec_PtrForEachEntry( Aig_Obj_t *, p->vCos, pObj, i ) + { + if ( i >= Aig_ManCoNum(p) - Aig_ManRegNum(p) ) + Vec_PtrWriteEntry( p->vCos, k++, pObj ); + else if ( !Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) || !Aig_ObjFaninC0(pObj) ) // non-const or const1 + Vec_PtrWriteEntry( p->vCos, k++, pObj ); + else + { + Aig_ObjDisconnect( p, pObj ); + Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); + } + } + Vec_PtrShrink( p->vCos, k ); + p->nObjs[AIG_OBJ_CO] = Vec_PtrSize( p->vCos ); + if ( Aig_ManRegNum(p) ) + p->nTruePos = Aig_ManCoNum(p) - Aig_ManRegNum(p); + return nPosOld - Aig_ManCoNum(p); +} + +/**Function************************************************************* + + Synopsis [Stops the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManPrintStats( Aig_Man_t * p ) +{ + int nChoices = Aig_ManChoiceNum(p); + printf( "%-15s : ", p->pName ); + printf( "pi = %5d ", Aig_ManCiNum(p)-Aig_ManRegNum(p) ); + printf( "po = %5d ", Aig_ManCoNum(p)-Aig_ManRegNum(p) ); + if ( Aig_ManRegNum(p) ) + printf( "lat = %5d ", Aig_ManRegNum(p) ); + printf( "and = %7d ", Aig_ManAndNum(p) ); +// printf( "Eq = %7d ", Aig_ManHaigCounter(p) ); + if ( Aig_ManExorNum(p) ) + printf( "xor = %5d ", Aig_ManExorNum(p) ); + if ( nChoices ) + printf( "ch = %5d ", nChoices ); + if ( Aig_ManBufNum(p) ) + printf( "buf = %5d ", Aig_ManBufNum(p) ); +// printf( "Cre = %6d ", p->nCreated ); +// printf( "Del = %6d ", p->nDeleted ); +// printf( "Lev = %3d ", Aig_ManLevelNum(p) ); +// printf( "Max = %7d ", Aig_ManObjNumMax(p) ); + printf( "lev = %3d", Aig_ManLevels(p) ); + printf( "\n" ); + fflush( stdout ); +} + +/**Function************************************************************* + + Synopsis [Reports the reduction of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManReportImprovement( Aig_Man_t * p, Aig_Man_t * pNew ) +{ + printf( "REG: Beg = %5d. End = %5d. (R =%5.1f %%) ", + Aig_ManRegNum(p), Aig_ManRegNum(pNew), + Aig_ManRegNum(p)? 100.0*(Aig_ManRegNum(p)-Aig_ManRegNum(pNew))/Aig_ManRegNum(p) : 0.0 ); + printf( "AND: Beg = %6d. End = %6d. (R =%5.1f %%)", + Aig_ManNodeNum(p), Aig_ManNodeNum(pNew), + Aig_ManNodeNum(p)? 100.0*(Aig_ManNodeNum(p)-Aig_ManNodeNum(pNew))/Aig_ManNodeNum(p) : 0.0 ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Sets the number of registers in the AIG manager.] + + Description [This procedure should be called after the manager is + fully constructed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManSetRegNum( Aig_Man_t * p, int nRegs ) +{ + p->nRegs = nRegs; + p->nTruePis = Aig_ManCiNum(p) - nRegs; + p->nTruePos = Aig_ManCoNum(p) - nRegs; + Aig_ManSetCioIds( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManFlipFirstPo( Aig_Man_t * p ) +{ + Aig_ObjChild0Flip( Aig_ManCo(p, 0) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Aig_ManReleaseData( Aig_Man_t * p ) +{ + void * pD = p->pData; + p->pData = NULL; + return pD; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigMem.c b/yosys/abc/src/aig/aig/aigMem.c new file mode 100644 index 00000000000..7626b5fb8e6 --- /dev/null +++ b/yosys/abc/src/aig/aig/aigMem.c @@ -0,0 +1,610 @@ +/**CFile**************************************************************** + + FileName [aigMem.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Memory managers.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigMem.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct Aig_MmFixed_t_ +{ + // information about individual entries + int nEntrySize; // the size of one entry + int nEntriesAlloc; // the total number of entries allocated + int nEntriesUsed; // the number of entries in use + int nEntriesMax; // the max number of entries in use + char * pEntriesFree; // the linked list of free entries + + // this is where the memory is stored + int nChunkSize; // the size of one chunk + int nChunksAlloc; // the maximum number of memory chunks + int nChunks; // the current number of memory chunks + char ** pChunks; // the allocated memory + + // statistics + int nMemoryUsed; // memory used in the allocated entries + int nMemoryAlloc; // memory allocated +}; + +struct Aig_MmFlex_t_ +{ + // information about individual entries + int nEntriesUsed; // the number of entries allocated + char * pCurrent; // the current pointer to free memory + char * pEnd; // the first entry outside the free memory + + // this is where the memory is stored + int nChunkSize; // the size of one chunk + int nChunksAlloc; // the maximum number of memory chunks + int nChunks; // the current number of memory chunks + char ** pChunks; // the allocated memory + + // statistics + int nMemoryUsed; // memory used in the allocated entries + int nMemoryAlloc; // memory allocated +}; + +struct Aig_MmStep_t_ +{ + int nMems; // the number of fixed memory managers employed + Aig_MmFixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc + int nMapSize; // the size of the memory array + Aig_MmFixed_t ** pMap; // maps the number of bytes into its memory manager + // additional memory chunks + int nChunksAlloc; // the maximum number of memory chunks + int nChunks; // the current number of memory chunks + char ** pChunks; // the allocated memory +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates memory pieces of fixed size.] + + Description [The size of the chunk is computed as the minimum of + 1024 entries and 64K. Can only work with entry size at least 4 byte long.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_MmFixed_t * Aig_MmFixedStart( int nEntrySize, int nEntriesMax ) +{ + Aig_MmFixed_t * p; + + p = ABC_ALLOC( Aig_MmFixed_t, 1 ); + memset( p, 0, sizeof(Aig_MmFixed_t) ); + + p->nEntrySize = nEntrySize; + p->nEntriesAlloc = 0; + p->nEntriesUsed = 0; + p->pEntriesFree = NULL; + + p->nChunkSize = nEntriesMax / 8; + if ( p->nChunkSize < 8 ) + p->nChunkSize = 8; + + p->nChunksAlloc = 64; + p->nChunks = 0; + p->pChunks = ABC_ALLOC( char *, p->nChunksAlloc ); + + p->nMemoryUsed = 0; + p->nMemoryAlloc = 0; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_MmFixedStop( Aig_MmFixed_t * p, int fVerbose ) +{ + int i; + if ( p == NULL ) + return; + if ( fVerbose ) + { + printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n", + p->nEntrySize, p->nChunkSize, p->nChunks ); + printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n", + p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc ); + } + for ( i = 0; i < p->nChunks; i++ ) + ABC_FREE( p->pChunks[i] ); + ABC_FREE( p->pChunks ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Aig_MmFixedEntryFetch( Aig_MmFixed_t * p ) +{ + char * pTemp; + int i; + + // check if there are still free entries + if ( p->nEntriesUsed == p->nEntriesAlloc ) + { // need to allocate more entries + assert( p->pEntriesFree == NULL ); + if ( p->nChunks == p->nChunksAlloc ) + { + p->nChunksAlloc *= 2; + p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); + } + p->pEntriesFree = ABC_ALLOC( char, p->nEntrySize * p->nChunkSize ); + p->nMemoryAlloc += p->nEntrySize * p->nChunkSize; + // transform these entries into a linked list + pTemp = p->pEntriesFree; + for ( i = 1; i < p->nChunkSize; i++ ) + { + *((char **)pTemp) = pTemp + p->nEntrySize; + pTemp += p->nEntrySize; + } + // set the last link + *((char **)pTemp) = NULL; + // add the chunk to the chunk storage + p->pChunks[ p->nChunks++ ] = p->pEntriesFree; + // add to the number of entries allocated + p->nEntriesAlloc += p->nChunkSize; + } + // incrememt the counter of used entries + p->nEntriesUsed++; + if ( p->nEntriesMax < p->nEntriesUsed ) + p->nEntriesMax = p->nEntriesUsed; + // return the first entry in the free entry list + pTemp = p->pEntriesFree; + p->pEntriesFree = *((char **)pTemp); + return pTemp; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_MmFixedEntryRecycle( Aig_MmFixed_t * p, char * pEntry ) +{ + // decrement the counter of used entries + p->nEntriesUsed--; + // add the entry to the linked list of free entries + *((char **)pEntry) = p->pEntriesFree; + p->pEntriesFree = pEntry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [Relocates all the memory except the first chunk.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_MmFixedRestart( Aig_MmFixed_t * p ) +{ + int i; + char * pTemp; + if ( p->nChunks == 0 ) + return; + // deallocate all chunks except the first one + for ( i = 1; i < p->nChunks; i++ ) + ABC_FREE( p->pChunks[i] ); + p->nChunks = 1; + // transform these entries into a linked list + pTemp = p->pChunks[0]; + for ( i = 1; i < p->nChunkSize; i++ ) + { + *((char **)pTemp) = pTemp + p->nEntrySize; + pTemp += p->nEntrySize; + } + // set the last link + *((char **)pTemp) = NULL; + // set the free entry list + p->pEntriesFree = p->pChunks[0]; + // set the correct statistics + p->nMemoryAlloc = p->nEntrySize * p->nChunkSize; + p->nMemoryUsed = 0; + p->nEntriesAlloc = p->nChunkSize; + p->nEntriesUsed = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_MmFixedReadMemUsage( Aig_MmFixed_t * p ) +{ + return p->nMemoryAlloc; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_MmFixedReadMaxEntriesUsed( Aig_MmFixed_t * p ) +{ + return p->nEntriesMax; +} + + + +/**Function************************************************************* + + Synopsis [Allocates entries of flexible size.] + + Description [Can only work with entry size at least 4 byte long.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_MmFlex_t * Aig_MmFlexStart() +{ + Aig_MmFlex_t * p; + + p = ABC_ALLOC( Aig_MmFlex_t, 1 ); + memset( p, 0, sizeof(Aig_MmFlex_t) ); + + p->nEntriesUsed = 0; + p->pCurrent = NULL; + p->pEnd = NULL; + + p->nChunkSize = (1 << 18); + p->nChunksAlloc = 64; + p->nChunks = 0; + p->pChunks = ABC_ALLOC( char *, p->nChunksAlloc ); + + p->nMemoryUsed = 0; + p->nMemoryAlloc = 0; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_MmFlexStop( Aig_MmFlex_t * p, int fVerbose ) +{ + int i; + if ( p == NULL ) + return; + if ( fVerbose ) + { + printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n", + p->nChunkSize, p->nChunks ); + printf( " Entries used = %d. Memory used = %d. Memory alloc = %d.\n", + p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc ); + } + for ( i = 0; i < p->nChunks; i++ ) + ABC_FREE( p->pChunks[i] ); + ABC_FREE( p->pChunks ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Aig_MmFlexEntryFetch( Aig_MmFlex_t * p, int nBytes ) +{ + char * pTemp; +#ifdef ABC_MEMALIGN + // extend size to max alignment + nBytes += (ABC_MEMALIGN - nBytes % ABC_MEMALIGN) % ABC_MEMALIGN; +#endif + // check if there are still free entries + if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd ) + { // need to allocate more entries + if ( p->nChunks == p->nChunksAlloc ) + { + p->nChunksAlloc *= 2; + p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); + } + if ( nBytes > p->nChunkSize ) + { + // resize the chunk size if more memory is requested than it can give + // (ideally, this should never happen) + p->nChunkSize = 2 * nBytes; + } + p->pCurrent = ABC_ALLOC( char, p->nChunkSize ); + p->pEnd = p->pCurrent + p->nChunkSize; + p->nMemoryAlloc += p->nChunkSize; + // add the chunk to the chunk storage + p->pChunks[ p->nChunks++ ] = p->pCurrent; + } + assert( p->pCurrent + nBytes <= p->pEnd ); + // increment the counter of used entries + p->nEntriesUsed++; + // keep track of the memory used + p->nMemoryUsed += nBytes; + // return the next entry + pTemp = p->pCurrent; + p->pCurrent += nBytes; + return pTemp; +} + +/**Function************************************************************* + + Synopsis [] + + Description [Relocates all the memory except the first chunk.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_MmFlexRestart( Aig_MmFlex_t * p ) +{ + int i; + if ( p->nChunks == 0 ) + return; + // deallocate all chunks except the first one + for ( i = 1; i < p->nChunks; i++ ) + ABC_FREE( p->pChunks[i] ); + p->nChunks = 1; + p->nMemoryAlloc = p->nChunkSize; + // transform these entries into a linked list + p->pCurrent = p->pChunks[0]; + p->pEnd = p->pCurrent + p->nChunkSize; + p->nEntriesUsed = 0; + p->nMemoryUsed = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_MmFlexReadMemUsage( Aig_MmFlex_t * p ) +{ + return p->nMemoryUsed; +} + + + + + +/**Function************************************************************* + + Synopsis [Starts the hierarchical memory manager.] + + Description [This manager can allocate entries of any size. + Iternally they are mapped into the entries with the number of bytes + equal to the power of 2. The smallest entry size is 8 bytes. The + next one is 16 bytes etc. So, if the user requests 6 bytes, he gets + 8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc. + The input parameters "nSteps" says how many fixed memory managers + are employed internally. Calling this procedure with nSteps equal + to 10 results in 10 hierarchically arranged internal memory managers, + which can allocate up to 4096 (1Kb) entries. Requests for larger + entries are handed over to malloc() and then ABC_FREE()ed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_MmStep_t * Aig_MmStepStart( int nSteps ) +{ + Aig_MmStep_t * p; + int i, k; + p = ABC_ALLOC( Aig_MmStep_t, 1 ); + memset( p, 0, sizeof(Aig_MmStep_t) ); + p->nMems = nSteps; + // start the fixed memory managers + p->pMems = ABC_ALLOC( Aig_MmFixed_t *, p->nMems ); + for ( i = 0; i < p->nMems; i++ ) + p->pMems[i] = Aig_MmFixedStart( (8<nMapSize = (4<nMems); + p->pMap = ABC_ALLOC( Aig_MmFixed_t *, p->nMapSize+1 ); + p->pMap[0] = NULL; + for ( k = 1; k <= 4; k++ ) + p->pMap[k] = p->pMems[0]; + for ( i = 0; i < p->nMems; i++ ) + for ( k = (4<pMap[k] = p->pMems[i]; +//for ( i = 1; i < 100; i ++ ) +//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize ); + p->nChunksAlloc = 64; + p->nChunks = 0; + p->pChunks = ABC_ALLOC( char *, p->nChunksAlloc ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_MmStepStop( Aig_MmStep_t * p, int fVerbose ) +{ + int i; + for ( i = 0; i < p->nMems; i++ ) + Aig_MmFixedStop( p->pMems[i], fVerbose ); + if ( p->nChunksAlloc ) + { + for ( i = 0; i < p->nChunks; i++ ) + ABC_FREE( p->pChunks[i] ); + ABC_FREE( p->pChunks ); + } + ABC_FREE( p->pMems ); + ABC_FREE( p->pMap ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Creates the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Aig_MmStepEntryFetch( Aig_MmStep_t * p, int nBytes ) +{ + if ( nBytes == 0 ) + return NULL; +#ifdef ABC_MEMALIGN + // extend size to max alignment + nBytes += (ABC_MEMALIGN - nBytes % ABC_MEMALIGN) % ABC_MEMALIGN; +#endif + if ( nBytes > p->nMapSize ) + { + if ( p->nChunks == p->nChunksAlloc ) + { + p->nChunksAlloc *= 2; + p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); + } + p->pChunks[ p->nChunks++ ] = ABC_ALLOC( char, nBytes ); + return p->pChunks[p->nChunks-1]; + } + return Aig_MmFixedEntryFetch( p->pMap[nBytes] ); +} + + +/**Function************************************************************* + + Synopsis [Recycles the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_MmStepEntryRecycle( Aig_MmStep_t * p, char * pEntry, int nBytes ) +{ + if ( nBytes == 0 ) + return; +#ifdef ABC_MEMALIGN + // extend size to max alignment + nBytes += (ABC_MEMALIGN - nBytes % ABC_MEMALIGN) % ABC_MEMALIGN; +#endif + if ( nBytes > p->nMapSize ) + { +// ABC_FREE( pEntry ); + return; + } + Aig_MmFixedEntryRecycle( p->pMap[nBytes], pEntry ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_MmStepReadMemUsage( Aig_MmStep_t * p ) +{ + int i, nMemTotal = 0; + for ( i = 0; i < p->nMems; i++ ) + nMemTotal += p->pMems[i]->nMemoryAlloc; + return nMemTotal; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigMffc.c b/yosys/abc/src/aig/aig/aigMffc.c new file mode 100644 index 00000000000..e577124a23f --- /dev/null +++ b/yosys/abc/src/aig/aig/aigMffc.c @@ -0,0 +1,316 @@ +/**CFile**************************************************************** + + FileName [aigMffc.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Computation of MFFCs.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigMffc.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Dereferences the node's MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_NodeDeref_rec( Aig_Obj_t * pNode, unsigned LevelMin, float * pPower, float * pProbs ) +{ + float Power0 = 0.0, Power1 = 0.0; + Aig_Obj_t * pFanin; + int Counter = 0; + if ( pProbs ) + *pPower = 0.0; + if ( Aig_ObjIsCi(pNode) ) + return 0; + // consider the first fanin + pFanin = Aig_ObjFanin0(pNode); + assert( pFanin->nRefs > 0 ); + if ( --pFanin->nRefs == 0 && (!LevelMin || pFanin->Level > LevelMin) ) + Counter += Aig_NodeDeref_rec( pFanin, LevelMin, &Power0, pProbs ); + if ( pProbs ) + *pPower += Power0 + 2.0 * pProbs[pFanin->Id] * (1.0 - pProbs[pFanin->Id]); + // skip the buffer + if ( Aig_ObjIsBuf(pNode) ) + return Counter; + assert( Aig_ObjIsNode(pNode) ); + // consider the second fanin + pFanin = Aig_ObjFanin1(pNode); + assert( pFanin->nRefs > 0 ); + if ( --pFanin->nRefs == 0 && (!LevelMin || pFanin->Level > LevelMin) ) + Counter += Aig_NodeDeref_rec( pFanin, LevelMin, &Power1, pProbs ); + if ( pProbs ) + *pPower += Power1 + 2.0 * pProbs[pFanin->Id] * (1.0 - pProbs[pFanin->Id]); + return Counter + 1; +} + +/**Function************************************************************* + + Synopsis [References the node's MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_NodeRef_rec( Aig_Obj_t * pNode, unsigned LevelMin ) +{ + Aig_Obj_t * pFanin; + int Counter = 0; + if ( Aig_ObjIsCi(pNode) ) + return 0; + // consider the first fanin + pFanin = Aig_ObjFanin0(pNode); + if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) ) + Counter += Aig_NodeRef_rec( pFanin, LevelMin ); + // skip the buffer + if ( Aig_ObjIsBuf(pNode) ) + return Counter; + assert( Aig_ObjIsNode(pNode) ); + // consider the second fanin + pFanin = Aig_ObjFanin1(pNode); + if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) ) + Counter += Aig_NodeRef_rec( pFanin, LevelMin ); + return Counter + 1; +} + +/**Function************************************************************* + + Synopsis [References the node's MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_NodeRefLabel_rec( Aig_Man_t * p, Aig_Obj_t * pNode, unsigned LevelMin ) +{ + Aig_Obj_t * pFanin; + int Counter = 0; + if ( Aig_ObjIsCi(pNode) ) + return 0; + Aig_ObjSetTravIdCurrent( p, pNode ); + // consider the first fanin + pFanin = Aig_ObjFanin0(pNode); + if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) ) + Counter += Aig_NodeRefLabel_rec( p, pFanin, LevelMin ); + if ( Aig_ObjIsBuf(pNode) ) + return Counter; + assert( Aig_ObjIsNode(pNode) ); + // consider the second fanin + pFanin = Aig_ObjFanin1(pNode); + if ( pFanin->nRefs++ == 0 && (!LevelMin || pFanin->Level > LevelMin) ) + Counter += Aig_NodeRefLabel_rec( p, pFanin, LevelMin ); + return Counter + 1; +} + +/**Function************************************************************* + + Synopsis [Collects the internal and boundary nodes in the derefed MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_NodeMffcSupp_rec( Aig_Man_t * p, Aig_Obj_t * pNode, unsigned LevelMin, Vec_Ptr_t * vSupp, int fTopmost, Aig_Obj_t * pObjSkip ) +{ + // skip visited nodes + if ( Aig_ObjIsTravIdCurrent(p, pNode) ) + return; + Aig_ObjSetTravIdCurrent(p, pNode); + // add to the new support nodes + if ( !fTopmost && pNode != pObjSkip && (Aig_ObjIsCi(pNode) || pNode->nRefs > 0 || pNode->Level <= LevelMin) ) + { + if ( vSupp ) Vec_PtrPush( vSupp, pNode ); + return; + } + assert( Aig_ObjIsNode(pNode) ); + // recur on the children + Aig_NodeMffcSupp_rec( p, Aig_ObjFanin0(pNode), LevelMin, vSupp, 0, pObjSkip ); + Aig_NodeMffcSupp_rec( p, Aig_ObjFanin1(pNode), LevelMin, vSupp, 0, pObjSkip ); +} + +/**Function************************************************************* + + Synopsis [Collects the support of depth-limited MFFC.] + + Description [Returns the number of internal nodes in the MFFC.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_NodeMffcSupp( Aig_Man_t * p, Aig_Obj_t * pNode, int LevelMin, Vec_Ptr_t * vSupp ) +{ + int ConeSize1, ConeSize2; + if ( vSupp ) Vec_PtrClear( vSupp ); + if ( !Aig_ObjIsNode(pNode) ) + { + if ( Aig_ObjIsCi(pNode) && vSupp ) + Vec_PtrPush( vSupp, pNode ); + return 0; + } + assert( !Aig_IsComplement(pNode) ); + assert( Aig_ObjIsNode(pNode) ); + Aig_ManIncrementTravId( p ); + ConeSize1 = Aig_NodeDeref_rec( pNode, LevelMin, NULL, NULL ); + Aig_NodeMffcSupp_rec( p, pNode, LevelMin, vSupp, 1, NULL ); + ConeSize2 = Aig_NodeRef_rec( pNode, LevelMin ); + assert( ConeSize1 == ConeSize2 ); + assert( ConeSize1 > 0 ); + return ConeSize1; +} + +/**Function************************************************************* + + Synopsis [Labels the nodes in the MFFC.] + + Description [Returns the number of internal nodes in the MFFC.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_NodeMffcLabel( Aig_Man_t * p, Aig_Obj_t * pNode, float * pPower ) +{ + int ConeSize1, ConeSize2; + assert( (pPower != NULL) == (p->vProbs != NULL) ); + assert( !Aig_IsComplement(pNode) ); + assert( Aig_ObjIsNode(pNode) ); + Aig_ManIncrementTravId( p ); + ConeSize1 = Aig_NodeDeref_rec( pNode, 0, pPower, p->vProbs? (float *)p->vProbs->pArray : NULL ); + ConeSize2 = Aig_NodeRefLabel_rec( p, pNode, 0 ); + assert( ConeSize1 == ConeSize2 ); + assert( ConeSize1 > 0 ); + return ConeSize1; +} + +/**Function************************************************************* + + Synopsis [Labels the nodes in the MFFC.] + + Description [Returns the number of internal nodes in the MFFC.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_NodeMffcLabelCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves ) +{ + Aig_Obj_t * pObj; + int i, ConeSize1, ConeSize2; + assert( !Aig_IsComplement(pNode) ); + assert( Aig_ObjIsNode(pNode) ); + Aig_ManIncrementTravId( p ); + Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i ) + pObj->nRefs++; + ConeSize1 = Aig_NodeDeref_rec( pNode, 0, NULL, NULL ); + ConeSize2 = Aig_NodeRefLabel_rec( p, pNode, 0 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i ) + pObj->nRefs--; + assert( ConeSize1 == ConeSize2 ); + assert( ConeSize1 > 0 ); + return ConeSize1; +} + +/**Function************************************************************* + + Synopsis [Expands the cut by adding the most closely related node.] + + Description [Returns 1 if the cut exists.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_NodeMffcExtendCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vResult ) +{ + Aig_Obj_t * pObj, * pLeafBest; + int i, LevelMax, ConeSize1, ConeSize2, ConeCur1, ConeCur2, ConeBest; + // dereference the current cut + LevelMax = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i ) + LevelMax = Abc_MaxInt( LevelMax, (int)pObj->Level ); + if ( LevelMax == 0 ) + return 0; + // dereference the cut + ConeSize1 = Aig_NodeDeref_rec( pNode, 0, NULL, NULL ); + // try expanding each node in the boundary + ConeBest = ABC_INFINITY; + pLeafBest = NULL; + Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i ) + { + if ( (int)pObj->Level != LevelMax ) + continue; + ConeCur1 = Aig_NodeDeref_rec( pObj, 0, NULL, NULL ); + if ( ConeBest > ConeCur1 ) + { + ConeBest = ConeCur1; + pLeafBest = pObj; + } + ConeCur2 = Aig_NodeRef_rec( pObj, 0 ); + assert( ConeCur1 == ConeCur2 ); + } + assert( pLeafBest != NULL ); + assert( Aig_ObjIsNode(pLeafBest) ); + // deref the best leaf + ConeCur1 = Aig_NodeDeref_rec( pLeafBest, 0, NULL, NULL ); + // collect the cut nodes + Vec_PtrClear( vResult ); + Aig_ManIncrementTravId( p ); + Aig_NodeMffcSupp_rec( p, pNode, 0, vResult, 1, pLeafBest ); + // ref the nodes + ConeCur2 = Aig_NodeRef_rec( pLeafBest, 0 ); + assert( ConeCur1 == ConeCur2 ); + // ref the original node + ConeSize2 = Aig_NodeRef_rec( pNode, 0 ); + assert( ConeSize1 == ConeSize2 ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigObj.c b/yosys/abc/src/aig/aig/aigObj.c new file mode 100644 index 00000000000..4de2e191865 --- /dev/null +++ b/yosys/abc/src/aig/aig/aigObj.c @@ -0,0 +1,536 @@ +/**CFile**************************************************************** + + FileName [aigObj.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Adding/removing objects.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigObj.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates primary input.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ObjCreateCi( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + pObj = Aig_ManFetchMemory( p ); + pObj->Type = AIG_OBJ_CI; + Vec_PtrPush( p->vCis, pObj ); + p->nObjs[AIG_OBJ_CI]++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Creates primary output with the given driver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ObjCreateCo( Aig_Man_t * p, Aig_Obj_t * pDriver ) +{ + Aig_Obj_t * pObj; + pObj = Aig_ManFetchMemory( p ); + pObj->Type = AIG_OBJ_CO; + Vec_PtrPush( p->vCos, pObj ); + Aig_ObjConnect( p, pObj, pDriver, NULL ); + p->nObjs[AIG_OBJ_CO]++; + return pObj; +} + + +/**Function************************************************************* + + Synopsis [Create the new node assuming it does not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ObjCreate( Aig_Man_t * p, Aig_Obj_t * pGhost ) +{ + Aig_Obj_t * pObj; + assert( !Aig_IsComplement(pGhost) ); + assert( Aig_ObjIsHash(pGhost) ); +// assert( pGhost == &p->Ghost ); + // get memory for the new object + pObj = Aig_ManFetchMemory( p ); + pObj->Type = pGhost->Type; + // add connections + Aig_ObjConnect( p, pObj, pGhost->pFanin0, pGhost->pFanin1 ); + // update node counters of the manager + p->nObjs[Aig_ObjType(pObj)]++; + assert( pObj->pData == NULL ); + // create the power counter + if ( p->vProbs ) + { + float Prob0 = Abc_Int2Float( Vec_IntEntry( p->vProbs, Aig_ObjFaninId0(pObj) ) ); + float Prob1 = Abc_Int2Float( Vec_IntEntry( p->vProbs, Aig_ObjFaninId1(pObj) ) ); + Prob0 = Aig_ObjFaninC0(pObj)? 1.0 - Prob0 : Prob0; + Prob1 = Aig_ObjFaninC1(pObj)? 1.0 - Prob1 : Prob1; + Vec_IntSetEntry( p->vProbs, pObj->Id, Abc_Float2Int(Prob0 * Prob1) ); + } + return pObj; +} + +/**Function************************************************************* + + Synopsis [Connect the object to the fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjConnect( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFan0, Aig_Obj_t * pFan1 ) +{ + assert( !Aig_IsComplement(pObj) ); + assert( !Aig_ObjIsCi(pObj) ); + // add the first fanin + pObj->pFanin0 = pFan0; + pObj->pFanin1 = pFan1; + // increment references of the fanins and add their fanouts + if ( pFan0 != NULL ) + { + assert( Aig_ObjFanin0(pObj)->Type > 0 ); + Aig_ObjRef( Aig_ObjFanin0(pObj) ); + if ( p->pFanData ) + Aig_ObjAddFanout( p, Aig_ObjFanin0(pObj), pObj ); + } + if ( pFan1 != NULL ) + { + assert( Aig_ObjFanin1(pObj)->Type > 0 ); + Aig_ObjRef( Aig_ObjFanin1(pObj) ); + if ( p->pFanData ) + Aig_ObjAddFanout( p, Aig_ObjFanin1(pObj), pObj ); + } + // set level and phase + pObj->Level = Aig_ObjLevelNew( pObj ); + pObj->fPhase = Aig_ObjPhaseReal(pFan0) & Aig_ObjPhaseReal(pFan1); + // add the node to the structural hash table + if ( p->pTable && Aig_ObjIsHash(pObj) ) + Aig_TableInsert( p, pObj ); + // add the node to the dynamically updated topological order +// if ( p->pOrderData && Aig_ObjIsNode(pObj) ) +// Aig_ObjOrderInsert( p, pObj->Id ); + assert( !Aig_ObjIsNode(pObj) || pObj->Level > 0 ); +} + +/**Function************************************************************* + + Synopsis [Disconnects the object from the fanins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjDisconnect( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + assert( !Aig_IsComplement(pObj) ); + // remove connections + if ( pObj->pFanin0 != NULL ) + { + if ( p->pFanData ) + Aig_ObjRemoveFanout( p, Aig_ObjFanin0(pObj), pObj ); + Aig_ObjDeref(Aig_ObjFanin0(pObj)); + } + if ( pObj->pFanin1 != NULL ) + { + if ( p->pFanData ) + Aig_ObjRemoveFanout( p, Aig_ObjFanin1(pObj), pObj ); + Aig_ObjDeref(Aig_ObjFanin1(pObj)); + } + // remove the node from the structural hash table + if ( p->pTable && Aig_ObjIsHash(pObj) ) + Aig_TableDelete( p, pObj ); + // add the first fanin + pObj->pFanin0 = NULL; + pObj->pFanin1 = NULL; + // remove the node from the dynamically updated topological order +// if ( p->pOrderData && Aig_ObjIsNode(pObj) ) +// Aig_ObjOrderRemove( p, pObj->Id ); +} + +/**Function************************************************************* + + Synopsis [Deletes the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjDelete( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + assert( !Aig_IsComplement(pObj) ); + assert( !Aig_ObjIsTerm(pObj) ); + assert( Aig_ObjRefs(pObj) == 0 ); + if ( p->pFanData && Aig_ObjIsBuf(pObj) ) + Vec_PtrRemove( p->vBufs, pObj ); + p->nObjs[pObj->Type]--; + Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); + Aig_ManRecycleMemory( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Deletes the MFFC of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjDelete_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int fFreeTop ) +{ + Aig_Obj_t * pFanin0, * pFanin1; + assert( !Aig_IsComplement(pObj) ); + if ( Aig_ObjIsConst1(pObj) || Aig_ObjIsCi(pObj) ) + return; + assert( !Aig_ObjIsCo(pObj) ); + pFanin0 = Aig_ObjFanin0(pObj); + pFanin1 = Aig_ObjFanin1(pObj); + Aig_ObjDisconnect( p, pObj ); + if ( fFreeTop ) + Aig_ObjDelete( p, pObj ); + if ( pFanin0 && !Aig_ObjIsNone(pFanin0) && Aig_ObjRefs(pFanin0) == 0 ) + Aig_ObjDelete_rec( p, pFanin0, 1 ); + if ( pFanin1 && !Aig_ObjIsNone(pFanin1) && Aig_ObjRefs(pFanin1) == 0 ) + Aig_ObjDelete_rec( p, pFanin1, 1 ); +} + +/**Function************************************************************* + + Synopsis [Deletes the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjDeletePo( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + assert( Aig_ObjIsCo(pObj) ); + Aig_ObjDeref(Aig_ObjFanin0(pObj)); + pObj->pFanin0 = NULL; + p->nObjs[pObj->Type]--; + Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); + Aig_ManRecycleMemory( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Replaces the first fanin of the node by the new fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjPatchFanin0( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFaninNew ) +{ + Aig_Obj_t * pFaninOld; + assert( !Aig_IsComplement(pObj) ); + assert( Aig_ObjIsCo(pObj) ); + pFaninOld = Aig_ObjFanin0(pObj); + // decrement ref and remove fanout + if ( p->pFanData ) + Aig_ObjRemoveFanout( p, pFaninOld, pObj ); + Aig_ObjDeref( pFaninOld ); + // update the fanin + pObj->pFanin0 = pFaninNew; + pObj->Level = Aig_ObjLevelNew( pObj ); + pObj->fPhase = Aig_ObjPhaseReal(pObj->pFanin0); + // increment ref and add fanout + if ( p->pFanData ) + Aig_ObjAddFanout( p, Aig_ObjFanin0(pObj), pObj ); + Aig_ObjRef( Aig_ObjFanin0(pObj) ); + // get rid of old fanin + if ( !Aig_ObjIsCi(pFaninOld) && !Aig_ObjIsConst1(pFaninOld) && Aig_ObjRefs(pFaninOld) == 0 ) + Aig_ObjDelete_rec( p, pFaninOld, 1 ); +} + +/**Function************************************************************* + + Synopsis [Verbose printing of the AIG node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjPrint( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + int fShowFanouts = 0; + Aig_Obj_t * pTemp; + if ( pObj == NULL ) + { + printf( "Object is NULL." ); + return; + } + if ( Aig_IsComplement(pObj) ) + { + printf( "Compl " ); + pObj = Aig_Not(pObj); + } + assert( !Aig_IsComplement(pObj) ); + printf( "Node %4d : ", Aig_ObjId(pObj) ); + if ( Aig_ObjIsConst1(pObj) ) + printf( "constant 1" ); + else if ( Aig_ObjIsCi(pObj) ) + printf( "PI" ); + else if ( Aig_ObjIsCo(pObj) ) + printf( "PO( %4d%s )", Aig_ObjFanin0(pObj)->Id, (Aig_ObjFaninC0(pObj)? "\'" : " ") ); + else if ( Aig_ObjIsBuf(pObj) ) + printf( "BUF( %d%s )", Aig_ObjFanin0(pObj)->Id, (Aig_ObjFaninC0(pObj)? "\'" : " ") ); + else + printf( "AND( %4d%s, %4d%s )", + Aig_ObjFanin0(pObj)->Id, (Aig_ObjFaninC0(pObj)? "\'" : " "), + Aig_ObjFanin1(pObj)->Id, (Aig_ObjFaninC1(pObj)? "\'" : " ") ); + printf( " (refs = %3d)", Aig_ObjRefs(pObj) ); + if ( fShowFanouts && p->pFanData ) + { + Aig_Obj_t * pFanout; + int i; + int iFan = -1; // Suppress "might be used uninitialized" + printf( "\nFanouts:\n" ); + Aig_ObjForEachFanout( p, pObj, pFanout, iFan, i ) + { + printf( " " ); + printf( "Node %4d : ", Aig_ObjId(pFanout) ); + if ( Aig_ObjIsCo(pFanout) ) + printf( "PO( %4d%s )", Aig_ObjFanin0(pFanout)->Id, (Aig_ObjFaninC0(pFanout)? "\'" : " ") ); + else if ( Aig_ObjIsBuf(pFanout) ) + printf( "BUF( %d%s )", Aig_ObjFanin0(pFanout)->Id, (Aig_ObjFaninC0(pFanout)? "\'" : " ") ); + else + printf( "AND( %4d%s, %4d%s )", + Aig_ObjFanin0(pFanout)->Id, (Aig_ObjFaninC0(pFanout)? "\'" : " "), + Aig_ObjFanin1(pFanout)->Id, (Aig_ObjFaninC1(pFanout)? "\'" : " ") ); + printf( "\n" ); + } + return; + } + // there are choices + if ( p->pEquivs && p->pEquivs[pObj->Id] ) + { + // print equivalence class + printf( " { %4d ", pObj->Id ); + for ( pTemp = p->pEquivs[pObj->Id]; pTemp; pTemp = p->pEquivs[pTemp->Id] ) + printf( " %4d%s", pTemp->Id, (pTemp->fPhase != pObj->fPhase)? "\'" : " " ); + printf( " }" ); + return; + } + // this is a secondary node + if ( p->pReprs && p->pReprs[pObj->Id] ) + printf( " class of %d", pObj->Id ); +} + +/**Function************************************************************* + + Synopsis [Replaces node with a buffer fanin by a node without them.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_NodeFixBufferFanins( Aig_Man_t * p, Aig_Obj_t * pObj, int fUpdateLevel ) +{ + Aig_Obj_t * pFanReal0, * pFanReal1, * pResult = NULL; + p->nBufFixes++; + if ( Aig_ObjIsCo(pObj) ) + { + assert( Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) ); + pFanReal0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); + assert( Aig_ObjPhaseReal(Aig_ObjChild0(pObj)) == Aig_ObjPhaseReal(pFanReal0) ); + Aig_ObjPatchFanin0( p, pObj, pFanReal0 ); + return; + } + assert( Aig_ObjIsNode(pObj) ); + assert( Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) || Aig_ObjIsBuf(Aig_ObjFanin1(pObj)) ); + // get the real fanins + pFanReal0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); + pFanReal1 = Aig_ObjReal_rec( Aig_ObjChild1(pObj) ); + // get the new node + if ( Aig_ObjIsNode(pObj) ) + pResult = Aig_Oper( p, pFanReal0, pFanReal1, Aig_ObjType(pObj) ); +// else if ( Aig_ObjIsLatch(pObj) ) +// pResult = Aig_Latch( p, pFanReal0, Aig_ObjInit(pObj) ); + else + assert( 0 ); + // replace the node with buffer by the node without buffer + Aig_ObjReplace( p, pObj, pResult, fUpdateLevel ); +} + +/**Function************************************************************* + + Synopsis [Returns the number of dangling nodes removed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManPropagateBuffers( Aig_Man_t * p, int fUpdateLevel ) +{ + Aig_Obj_t * pObj; + int nSteps; + assert( p->pFanData ); + for ( nSteps = 0; Vec_PtrSize(p->vBufs) > 0; nSteps++ ) + { + // get the node with a buffer fanin + for ( pObj = (Aig_Obj_t *)Vec_PtrEntryLast(p->vBufs); Aig_ObjIsBuf(pObj); pObj = Aig_ObjFanout0(p, pObj) ); + // replace this node by a node without buffer + Aig_NodeFixBufferFanins( p, pObj, fUpdateLevel ); + // stop if a cycle occured + if ( nSteps > 1000000 ) + { + printf( "Error: A cycle is encountered while propagating buffers.\n" ); + break; + } + } + return nSteps; +} + +/**Function************************************************************* + + Synopsis [Replaces one object by another.] + + Description [The new object (pObjNew) should be used instead of the old + object (pObjOld). If the new object is complemented or used, the buffer + is added and the new object remains in the manager; otherwise, the new + object is deleted.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjReplace( Aig_Man_t * p, Aig_Obj_t * pObjOld, Aig_Obj_t * pObjNew, int fUpdateLevel ) +{ + Aig_Obj_t * pObjNewR = Aig_Regular(pObjNew); + // the object to be replaced cannot be complemented + assert( !Aig_IsComplement(pObjOld) ); + // the object to be replaced cannot be a terminal + assert( !Aig_ObjIsCi(pObjOld) && !Aig_ObjIsCo(pObjOld) ); + // the object to be used cannot be a buffer or a PO + assert( !Aig_ObjIsBuf(pObjNewR) && !Aig_ObjIsCo(pObjNewR) ); + // the object cannot be the same + assert( pObjOld != pObjNewR ); + // make sure object is not pointing to itself + assert( pObjOld != Aig_ObjFanin0(pObjNewR) ); + assert( pObjOld != Aig_ObjFanin1(pObjNewR) ); + if ( pObjOld == Aig_ObjFanin0(pObjNewR) || pObjOld == Aig_ObjFanin1(pObjNewR) ) + { + printf( "Aig_ObjReplace(): Internal error!\n" ); + exit(1); + } + // recursively delete the old node - but leave the object there + pObjNewR->nRefs++; + Aig_ObjDelete_rec( p, pObjOld, 0 ); + pObjNewR->nRefs--; + // if the new object is complemented or already used, create a buffer + p->nObjs[pObjOld->Type]--; + if ( Aig_IsComplement(pObjNew) || Aig_ObjRefs(pObjNew) > 0 || !Aig_ObjIsNode(pObjNew) ) + { + pObjOld->Type = AIG_OBJ_BUF; + Aig_ObjConnect( p, pObjOld, pObjNew, NULL ); + p->nBufReplaces++; + } + else + { + Aig_Obj_t * pFanin0 = pObjNew->pFanin0; + Aig_Obj_t * pFanin1 = pObjNew->pFanin1; + int LevelOld = pObjOld->Level; + pObjOld->Type = pObjNew->Type; + Aig_ObjDisconnect( p, pObjNew ); + Aig_ObjConnect( p, pObjOld, pFanin0, pFanin1 ); + // delete the new object + Aig_ObjDelete( p, pObjNew ); + // update levels + if ( p->pFanData ) + { + pObjOld->Level = LevelOld; + Aig_ManUpdateLevel( p, pObjOld ); + } + if ( fUpdateLevel ) + { + Aig_ObjClearReverseLevel( p, pObjOld ); + Aig_ManUpdateReverseLevel( p, pObjOld ); + } + } + p->nObjs[pObjOld->Type]++; + // store buffers if fanout is allocated + if ( p->pFanData && Aig_ObjIsBuf(pObjOld) ) + { + Vec_PtrPush( p->vBufs, pObjOld ); + p->nBufMax = Abc_MaxInt( p->nBufMax, Vec_PtrSize(p->vBufs) ); + Aig_ManPropagateBuffers( p, fUpdateLevel ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigOper.c b/yosys/abc/src/aig/aig/aigOper.c new file mode 100644 index 00000000000..d6f02a6e0bb --- /dev/null +++ b/yosys/abc/src/aig/aig/aigOper.c @@ -0,0 +1,606 @@ +/**CFile**************************************************************** + + FileName [aigOper.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [AIG operations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigOper.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// procedure to detect an EXOR gate +static inline int Aig_ObjIsExorType( Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Obj_t ** ppFan0, Aig_Obj_t ** ppFan1 ) +{ + if ( !Aig_IsComplement(p0) || !Aig_IsComplement(p1) ) + return 0; + p0 = Aig_Regular(p0); + p1 = Aig_Regular(p1); + if ( !Aig_ObjIsAnd(p0) || !Aig_ObjIsAnd(p1) ) + return 0; + if ( Aig_ObjFanin0(p0) != Aig_ObjFanin0(p1) || Aig_ObjFanin1(p0) != Aig_ObjFanin1(p1) ) + return 0; + if ( Aig_ObjFaninC0(p0) == Aig_ObjFaninC0(p1) || Aig_ObjFaninC1(p0) == Aig_ObjFaninC1(p1) ) + return 0; + *ppFan0 = Aig_ObjChild0(p0); + *ppFan1 = Aig_ObjChild1(p0); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns i-th elementary variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_IthVar( Aig_Man_t * p, int i ) +{ + int v; + for ( v = Aig_ManCiNum(p); v <= i; v++ ) + Aig_ObjCreateCi( p ); + assert( i < Vec_PtrSize(p->vCis) ); + return Aig_ManCi( p, i ); +} + +/**Function************************************************************* + + Synopsis [Perform one operation.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_Oper( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1, Aig_Type_t Type ) +{ + if ( Type == AIG_OBJ_AND ) + return Aig_And( p, p0, p1 ); + if ( Type == AIG_OBJ_EXOR ) + return Aig_Exor( p, p0, p1 ); + assert( 0 ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_And( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ) +{ + Aig_Obj_t * pGhost, * pResult; + Aig_Obj_t * pFan0, * pFan1; + // check trivial cases + if ( p0 == p1 ) + return p0; + if ( p0 == Aig_Not(p1) ) + return Aig_Not(p->pConst1); + if ( Aig_Regular(p0) == p->pConst1 ) + return p0 == p->pConst1 ? p1 : Aig_Not(p->pConst1); + if ( Aig_Regular(p1) == p->pConst1 ) + return p1 == p->pConst1 ? p0 : Aig_Not(p->pConst1); + // check not so trivial cases + if ( p->fAddStrash && (Aig_ObjIsNode(Aig_Regular(p0)) || Aig_ObjIsNode(Aig_Regular(p1))) ) + { // http://fmv.jku.at/papers/BrummayerBiere-MEMICS06.pdf + Aig_Obj_t * pFanA, * pFanB, * pFanC, * pFanD; + pFanA = Aig_ObjChild0(Aig_Regular(p0)); + pFanB = Aig_ObjChild1(Aig_Regular(p0)); + pFanC = Aig_ObjChild0(Aig_Regular(p1)); + pFanD = Aig_ObjChild1(Aig_Regular(p1)); + if ( Aig_IsComplement(p0) ) + { + if ( pFanA == Aig_Not(p1) || pFanB == Aig_Not(p1) ) + return p1; + if ( pFanB == p1 ) + return Aig_And( p, Aig_Not(pFanA), pFanB ); + if ( pFanA == p1 ) + return Aig_And( p, Aig_Not(pFanB), pFanA ); + } + else + { + if ( pFanA == Aig_Not(p1) || pFanB == Aig_Not(p1) ) + return Aig_Not(p->pConst1); + if ( pFanA == p1 || pFanB == p1 ) + return p0; + } + if ( Aig_IsComplement(p1) ) + { + if ( pFanC == Aig_Not(p0) || pFanD == Aig_Not(p0) ) + return p0; + if ( pFanD == p0 ) + return Aig_And( p, Aig_Not(pFanC), pFanD ); + if ( pFanC == p0 ) + return Aig_And( p, Aig_Not(pFanD), pFanC ); + } + else + { + if ( pFanC == Aig_Not(p0) || pFanD == Aig_Not(p0) ) + return Aig_Not(p->pConst1); + if ( pFanC == p0 || pFanD == p0 ) + return p1; + } + if ( !Aig_IsComplement(p0) && !Aig_IsComplement(p1) ) + { + if ( pFanA == Aig_Not(pFanC) || pFanA == Aig_Not(pFanD) || pFanB == Aig_Not(pFanC) || pFanB == Aig_Not(pFanD) ) + return Aig_Not(p->pConst1); + if ( pFanA == pFanC || pFanB == pFanC ) + return Aig_And( p, p0, pFanD ); + if ( pFanB == pFanC || pFanB == pFanD ) + return Aig_And( p, pFanA, p1 ); + if ( pFanA == pFanD || pFanB == pFanD ) + return Aig_And( p, p0, pFanC ); + if ( pFanA == pFanC || pFanA == pFanD ) + return Aig_And( p, pFanB, p1 ); + } + else if ( Aig_IsComplement(p0) && !Aig_IsComplement(p1) ) + { + if ( pFanA == Aig_Not(pFanC) || pFanA == Aig_Not(pFanD) || pFanB == Aig_Not(pFanC) || pFanB == Aig_Not(pFanD) ) + return p1; + if ( pFanB == pFanC || pFanB == pFanD ) + return Aig_And( p, Aig_Not(pFanA), p1 ); + if ( pFanA == pFanC || pFanA == pFanD ) + return Aig_And( p, Aig_Not(pFanB), p1 ); + } + else if ( !Aig_IsComplement(p0) && Aig_IsComplement(p1) ) + { + if ( pFanC == Aig_Not(pFanA) || pFanC == Aig_Not(pFanB) || pFanD == Aig_Not(pFanA) || pFanD == Aig_Not(pFanB) ) + return p0; + if ( pFanD == pFanA || pFanD == pFanB ) + return Aig_And( p, Aig_Not(pFanC), p0 ); + if ( pFanC == pFanA || pFanC == pFanB ) + return Aig_And( p, Aig_Not(pFanD), p0 ); + } + else // if ( Aig_IsComplement(p0) && Aig_IsComplement(p1) ) + { + if ( pFanA == pFanD && pFanB == Aig_Not(pFanC) ) + return Aig_Not(pFanA); + if ( pFanB == pFanC && pFanA == Aig_Not(pFanD) ) + return Aig_Not(pFanB); + if ( pFanA == pFanC && pFanB == Aig_Not(pFanD) ) + return Aig_Not(pFanA); + if ( pFanB == pFanD && pFanA == Aig_Not(pFanC) ) + return Aig_Not(pFanB); + } + } + // check if it can be an EXOR gate + if ( p->fCatchExor && Aig_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) ) + return Aig_Exor( p, pFan0, pFan1 ); + pGhost = Aig_ObjCreateGhost( p, p0, p1, AIG_OBJ_AND ); + if ( (pResult = Aig_TableLookup( p, pGhost )) ) + return pResult; + return Aig_ObjCreate( p, pGhost ); +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_Exor( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ) +{ + Aig_Obj_t * pGhost, * pResult; + int fCompl; + // check trivial cases + if ( p0 == p1 ) + return Aig_Not(p->pConst1); + if ( p0 == Aig_Not(p1) ) + return p->pConst1; + if ( Aig_Regular(p0) == p->pConst1 ) + return Aig_NotCond( p1, p0 == p->pConst1 ); + if ( Aig_Regular(p1) == p->pConst1 ) + return Aig_NotCond( p0, p1 == p->pConst1 ); + // when there is no special XOR gates + if ( !p->fCatchExor ) + return Aig_Or( p, Aig_And(p, p0, Aig_Not(p1)), Aig_And(p, Aig_Not(p0), p1) ); + // canonicize + fCompl = Aig_IsComplement(p0) ^ Aig_IsComplement(p1); + p0 = Aig_Regular(p0); + p1 = Aig_Regular(p1); + pGhost = Aig_ObjCreateGhost( p, p0, p1, AIG_OBJ_EXOR ); + // check the table + if ( (pResult = Aig_TableLookup( p, pGhost )) ) + return Aig_NotCond( pResult, fCompl ); + pResult = Aig_ObjCreate( p, pGhost ); + return Aig_NotCond( pResult, fCompl ); +} + +/**Function************************************************************* + + Synopsis [Implements Boolean OR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_Or( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ) +{ + return Aig_Not( Aig_And( p, Aig_Not(p0), Aig_Not(p1) ) ); +} + +/**Function************************************************************* + + Synopsis [Implements ITE operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_TableLookupInt( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 ) +{ + if ( p0 == p1 ) + return p0; + if ( p0 == Aig_ManConst0(p) || p1 == Aig_ManConst0(p) || p0 == Aig_Not(p1) ) + return Aig_ManConst0(p); + if ( p0 == Aig_ManConst1(p) ) + return p1; + if ( p1 == Aig_ManConst1(p) ) + return p0; + if ( Aig_Regular(p0)->Id < Aig_Regular(p1)->Id ) + return Aig_TableLookup( p, Aig_ObjCreateGhost(p, p0, p1, AIG_OBJ_AND) ); + return Aig_TableLookup( p, Aig_ObjCreateGhost(p, p1, p0, AIG_OBJ_AND) ); +} + +/**Function************************************************************* + + Synopsis [Implements ITE operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_Mux2( Aig_Man_t * p, Aig_Obj_t * pC, Aig_Obj_t * p1, Aig_Obj_t * p0 ) +{ + return Aig_Or( p, Aig_And(p, pC, p1), Aig_And(p, Aig_Not(pC), p0) ); +} + +/**Function************************************************************* + + Synopsis [Implements ITE operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_Mux( Aig_Man_t * p, Aig_Obj_t * pC, Aig_Obj_t * p1, Aig_Obj_t * p0 ) +{ + int fUseMuxCanon = 0; + Aig_Obj_t * pTempA1, * pTempA2, * pTempB1, * pTempB2, * pTemp; + int Count0, Count1; + if ( !fUseMuxCanon ) + return Aig_Mux2( p, pC, p1, p0 ); + if ( p0 == p1 ) + return p0; + if ( p1 == Aig_Not(p0) ) + return Aig_Exor( p, pC, p0 ); + if ( pC == Aig_ManConst0(p) ) + return p0; + if ( pC == Aig_ManConst1(p) ) + return p1; + if ( p0 == Aig_ManConst0(p) ) + return Aig_And( p, pC, p1 ); + if ( p0 == Aig_ManConst1(p) ) + return Aig_Or( p, Aig_Not(pC), p1 ); + if ( p1 == Aig_ManConst0(p) ) + return Aig_And( p, Aig_Not(pC), p0 ); + if ( p1 == Aig_ManConst1(p) ) + return Aig_Or( p, pC, p0 ); + // implement the first MUX (F = C * x1 + C' * x0) + pTempA1 = Aig_TableLookupInt( p, pC, p1 ); + pTempA2 = Aig_TableLookupInt( p, Aig_Not(pC), p0 ); + if ( pTempA1 && pTempA2 ) + { + pTemp = Aig_TableLookupInt( p, Aig_Not(pTempA1), Aig_Not(pTempA2) ); + if ( pTemp ) return Aig_Not(pTemp); + } + Count0 = (pTempA1 != NULL) + (pTempA2 != NULL); + // implement the second MUX (F' = C * x1' + C' * x0') + pTempB1 = Aig_TableLookupInt( p, pC, Aig_Not(p1) ); + pTempB2 = Aig_TableLookupInt( p, Aig_Not(pC), Aig_Not(p0) ); + if ( pTempB1 && pTempB2 ) + { + pTemp = Aig_TableLookupInt( p, Aig_Not(pTempB1), Aig_Not(pTempB2) ); + if ( pTemp ) return pTemp; + } + Count1 = (pTempB1 != NULL) + (pTempB2 != NULL); + // compare and decide which one to implement + if ( Count0 >= Count1 ) + return Aig_Or( p, Aig_And(p, pC, p1), Aig_And(p, Aig_Not(pC), p0) ); + return Aig_Not( Aig_Or( p, Aig_And(p, pC, Aig_Not(p1)), Aig_And(p, Aig_Not(pC), Aig_Not(p0)) ) ); +// return Aig_Or( p, Aig_And(p, pC, p1), Aig_And(p, Aig_Not(pC), p0) ); +} + +/**Function************************************************************* + + Synopsis [Implements ITE operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_Maj( Aig_Man_t * p, Aig_Obj_t * pA, Aig_Obj_t * pB, Aig_Obj_t * pC ) +{ + return Aig_Or( p, Aig_Or(p, Aig_And(p, pA, pB), Aig_And(p, pA, pC)), Aig_And(p, pB, pC) ); +} + +/**Function************************************************************* + + Synopsis [Constructs the well-balanced tree of gates.] + + Description [Disregards levels and possible logic sharing.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_Multi_rec( Aig_Man_t * p, Aig_Obj_t ** ppObjs, int nObjs, Aig_Type_t Type ) +{ + Aig_Obj_t * pObj1, * pObj2; + if ( nObjs == 1 ) + return ppObjs[0]; + pObj1 = Aig_Multi_rec( p, ppObjs, nObjs/2, Type ); + pObj2 = Aig_Multi_rec( p, ppObjs + nObjs/2, nObjs - nObjs/2, Type ); + return Aig_Oper( p, pObj1, pObj2, Type ); +} + +/**Function************************************************************* + + Synopsis [Old code.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_Multi( Aig_Man_t * p, Aig_Obj_t ** pArgs, int nArgs, Aig_Type_t Type ) +{ + assert( Type == AIG_OBJ_AND || Type == AIG_OBJ_EXOR ); + assert( nArgs > 0 ); + return Aig_Multi_rec( p, pArgs, nArgs, Type ); +} + +/**Function************************************************************* + + Synopsis [Implements the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_Miter( Aig_Man_t * p, Vec_Ptr_t * vPairs ) +{ + int i; + assert( vPairs->nSize > 0 ); + assert( vPairs->nSize % 2 == 0 ); + for ( i = 0; i < vPairs->nSize; i += 2 ) + vPairs->pArray[i/2] = Aig_Not( Aig_Exor( p, (Aig_Obj_t *)vPairs->pArray[i], (Aig_Obj_t *)vPairs->pArray[i+1] ) ); + vPairs->nSize = vPairs->nSize/2; + return Aig_Not( Aig_Multi_rec( p, (Aig_Obj_t **)vPairs->pArray, vPairs->nSize, AIG_OBJ_AND ) ); +} + +/**Function************************************************************* + + Synopsis [Implements the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_MiterTwo( Aig_Man_t * p, Vec_Ptr_t * vNodes1, Vec_Ptr_t * vNodes2 ) +{ + int i; + assert( vNodes1->nSize > 0 && vNodes2->nSize > 0 ); + assert( vNodes1->nSize == vNodes2->nSize ); + for ( i = 0; i < vNodes1->nSize; i++ ) + vNodes1->pArray[i] = Aig_Not( Aig_Exor( p, (Aig_Obj_t *)vNodes1->pArray[i], (Aig_Obj_t *)vNodes2->pArray[i] ) ); + return Aig_Not( Aig_Multi_rec( p, (Aig_Obj_t **)vNodes1->pArray, vNodes1->nSize, AIG_OBJ_AND ) ); +} + +/**Function************************************************************* + + Synopsis [Creates AND function with nVars inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_CreateAnd( Aig_Man_t * p, int nVars ) +{ + Aig_Obj_t * pFunc; + int i; + pFunc = Aig_ManConst1( p ); + for ( i = 0; i < nVars; i++ ) + pFunc = Aig_And( p, pFunc, Aig_IthVar(p, i) ); + return pFunc; +} + +/**Function************************************************************* + + Synopsis [Creates AND function with nVars inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_CreateOr( Aig_Man_t * p, int nVars ) +{ + Aig_Obj_t * pFunc; + int i; + pFunc = Aig_ManConst0( p ); + for ( i = 0; i < nVars; i++ ) + pFunc = Aig_Or( p, pFunc, Aig_IthVar(p, i) ); + return pFunc; +} + +/**Function************************************************************* + + Synopsis [Creates AND function with nVars inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_CreateExor( Aig_Man_t * p, int nVars ) +{ + Aig_Obj_t * pFunc; + int i; + pFunc = Aig_ManConst0( p ); + for ( i = 0; i < nVars; i++ ) + pFunc = Aig_Exor( p, pFunc, Aig_IthVar(p, i) ); + return pFunc; +} + +/**Function************************************************************* + + Synopsis [Implements ITE operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_MuxTest() +{ + Vec_Ptr_t * vNodes; + Aig_Man_t * p; + Aig_Obj_t * pObj, * pFanin0, * pFanin1, * pCtrl; + int nNodes = 2000; + int i,nPIs = 20; +// srand( time(NULL) ); + srand( 321 ); + vNodes = Vec_PtrAlloc( 100 ); + // create a bunch of random MUXes + p = Aig_ManStart( 10000 ); + for ( i = 0; i < nPIs; i++ ) + Aig_IthVar(p,i); + for ( i = 0; i < nNodes; i++ ) + { + if ( rand() % 10 == 0 ) + pCtrl = Aig_ManConst0(p); + else if ( rand() % 10 == 0 ) + pCtrl = Aig_ManConst1(p); + else if ( rand() % 3 == 0 || i < nPIs ) + pCtrl = Aig_IthVar( p, rand() % nPIs ); + else + pCtrl = (Aig_Obj_t *)Vec_PtrEntry(vNodes, rand() % i); + if ( rand() % 2 == 0 ) + pCtrl = Aig_Not( pCtrl ); + + if ( rand() % 10 == 0 ) + pFanin1 = Aig_ManConst0(p); + else if ( rand() % 10 == 0 ) + pFanin1 = Aig_ManConst1(p); + else if ( rand() % 3 == 0 || i < nPIs ) + pFanin1 = Aig_IthVar( p, rand() % nPIs ); + else + pFanin1 = (Aig_Obj_t *)Vec_PtrEntry(vNodes, rand() % i); + if ( rand() % 2 == 0 ) + pFanin1 = Aig_Not( pFanin1 ); + + if ( rand() % 10 == 0 ) + pFanin0 = Aig_ManConst0(p); + else if ( rand() % 10 == 0 ) + pFanin0 = Aig_ManConst1(p); + else if ( rand() % 3 == 0 || i < nPIs ) + pFanin0 = Aig_IthVar( p, rand() % nPIs ); + else + pFanin0 = (Aig_Obj_t *)Vec_PtrEntry(vNodes, rand() % i); + if ( rand() % 2 == 0 ) + pFanin0 = Aig_Not( pFanin0 ); + + pObj = Aig_Mux( p, pCtrl, pFanin1, pFanin0 ); + Vec_PtrPush( vNodes, pObj ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + Aig_ObjCreateCo( p, pObj ); + Vec_PtrFree( vNodes ); + + printf( "Number of nodes = %6d.\n", Aig_ManObjNum(p) ); + Aig_ManCleanup( p ); + printf( "Number of nodes = %6d.\n", Aig_ManObjNum(p) ); + Aig_ManDumpBlif( p, "test1.blif", NULL, NULL ); + Aig_ManStop( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigOrder.c b/yosys/abc/src/aig/aig/aigOrder.c new file mode 100644 index 00000000000..21bf8b8ee81 --- /dev/null +++ b/yosys/abc/src/aig/aig/aigOrder.c @@ -0,0 +1,176 @@ +/**CFile**************************************************************** + + FileName [aigOrder.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Dynamically updated topological order.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigOrder.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Initializes the order datastructure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManOrderStart( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + assert( Aig_ManBufNum(p) == 0 ); + // allocate order datastructure + assert( p->pOrderData == NULL ); + p->nOrderAlloc = 2 * Aig_ManObjNumMax(p); + if ( p->nOrderAlloc < (1<<12) ) + p->nOrderAlloc = (1<<12); + p->pOrderData = ABC_ALLOC( unsigned, 2 * p->nOrderAlloc ); + memset( p->pOrderData, 0xFF, sizeof(unsigned) * 2 * p->nOrderAlloc ); + // add the constant node + p->pOrderData[0] = p->pOrderData[1] = 0; + p->iPrev = p->iNext = 0; + // add the internal nodes + Aig_ManForEachNode( p, pObj, i ) + Aig_ObjOrderInsert( p, pObj->Id ); +} + +/**Function************************************************************* + + Synopsis [Deletes the order datastructure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManOrderStop( Aig_Man_t * p ) +{ + assert( p->pOrderData ); + ABC_FREE( p->pOrderData ); + p->nOrderAlloc = 0; + p->iPrev = p->iNext = 0; +} + +/**Function************************************************************* + + Synopsis [Inserts an entry before iNext.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjOrderInsert( Aig_Man_t * p, int ObjId ) +{ + int iPrev; + assert( ObjId != 0 ); + assert( Aig_ObjIsNode( Aig_ManObj(p, ObjId) ) ); + if ( ObjId >= p->nOrderAlloc ) + { + int nOrderAlloc = 2 * ObjId; + p->pOrderData = ABC_REALLOC( unsigned, p->pOrderData, 2 * nOrderAlloc ); + memset( p->pOrderData + 2 * p->nOrderAlloc, 0xFF, sizeof(unsigned) * 2 * (nOrderAlloc - p->nOrderAlloc) ); + p->nOrderAlloc = nOrderAlloc; + } + assert( p->pOrderData[2*ObjId] == 0xFFFFFFFF ); // prev + assert( p->pOrderData[2*ObjId+1] == 0xFFFFFFFF ); // next + iPrev = p->pOrderData[2*p->iNext]; + assert( p->pOrderData[2*iPrev+1] == (unsigned)p->iNext ); + p->pOrderData[2*ObjId] = iPrev; + p->pOrderData[2*iPrev+1] = ObjId; + p->pOrderData[2*p->iNext] = ObjId; + p->pOrderData[2*ObjId+1] = p->iNext; + p->nAndTotal++; +} + +/**Function************************************************************* + + Synopsis [Removes the entry.] + + Description [If iPrev is removed, it slides backward. + If iNext is removed, it slides forward.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjOrderRemove( Aig_Man_t * p, int ObjId ) +{ + int iPrev, iNext; + assert( ObjId != 0 ); + assert( Aig_ObjIsNode( Aig_ManObj(p, ObjId) ) ); + iPrev = p->pOrderData[2*ObjId]; + iNext = p->pOrderData[2*ObjId+1]; + p->pOrderData[2*ObjId] = 0xFFFFFFFF; + p->pOrderData[2*ObjId+1] = 0xFFFFFFFF; + p->pOrderData[2*iNext] = iPrev; + p->pOrderData[2*iPrev+1] = iNext; + if ( p->iPrev == ObjId ) + { + p->nAndPrev--; + p->iPrev = iPrev; + } + if ( p->iNext == ObjId ) + p->iNext = iNext; + p->nAndTotal--; +} + +/**Function************************************************************* + + Synopsis [Advances the order forward.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjOrderAdvance( Aig_Man_t * p ) +{ + assert( p->pOrderData ); + assert( p->pOrderData[2*p->iPrev+1] == (unsigned)p->iNext ); + p->iPrev = p->iNext; + p->nAndPrev++; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigPack.c b/yosys/abc/src/aig/aig/aigPack.c new file mode 100644 index 00000000000..0f0ad72f8f9 --- /dev/null +++ b/yosys/abc/src/aig/aig/aigPack.c @@ -0,0 +1,404 @@ +/**CFile**************************************************************** + + FileName [aigPack.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Bit-packing code.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigPack.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// resubstitution manager +typedef struct Aig_ManPack_t_ Aig_ManPack_t; +struct Aig_ManPack_t_ +{ + Aig_Man_t * pAig; // working manager + Vec_Wrd_t * vSigns; // object signatures + Vec_Wrd_t * vPiPats; // PI assignments + Vec_Wrd_t * vPiCare; // PI care set + int iPatCur; // current pattern + int fVerbose; // verbosiness flag + // statistics + int nPatTotal; // number of all patterns + int nPatSkip; // number of skipped patterns + int nPatRepeat; // number of repeated patterns +}; + +static inline int Aig_Word6CountOnes( word t ) { return Aig_WordCountOnes( (unsigned)(t >> 32) ) + Aig_WordCountOnes( (unsigned)(t & 0xFFFFFFFF) ); } +static inline int Aig_Word6HasOneBit( word t ) { return (t & (t-1)) == 0; } + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_ManPack_t * Aig_ManPackAlloc( Aig_Man_t * pAig ) +{ + Aig_ManPack_t * p; + p = ABC_CALLOC( Aig_ManPack_t, 1 ); + p->pAig = pAig; + p->vSigns = Vec_WrdStart( Aig_ManObjNumMax(pAig) ); + p->vPiPats = Vec_WrdStart( Aig_ManCiNum(pAig) ); + p->vPiCare = Vec_WrdStart( Aig_ManCiNum(pAig) ); + p->iPatCur = 1; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManPackCountCares( Aig_ManPack_t * p ) +{ + Aig_Obj_t * pObj; + int i, Total = 0; + Aig_ManForEachCi( p->pAig, pObj, i ) + Total += Aig_Word6CountOnes( Vec_WrdEntry(p->vPiCare, i) ); + return Total; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManPackPrintCare( Aig_ManPack_t * p ) +{ + Aig_Obj_t * pObj; + word Sign; + int i; + Aig_ManForEachCi( p->pAig, pObj, i ) + { + Sign = Vec_WrdEntry( p->vPiCare, i ); +// Extra_PrintBinary( stdout, (unsigned *)&Sign, 64 ); +// printf( "\n" ); + } +// printf( "\n" ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManPackFree( Aig_ManPack_t * p ) +{ +// Aig_ManPackPrintCare( p ); + printf( "Patterns: " ); + printf( "Total = %6d. ", p->nPatTotal ); + printf( "Skipped = %6d. ", p->nPatSkip ); + printf( "Cares = %6.2f %% ", 100.0*Aig_ManPackCountCares(p)/Aig_ManCiNum(p->pAig)/64 ); + printf( "\n" ); + Vec_WrdFree( p->vSigns ); + Vec_WrdFree( p->vPiPats ); + Vec_WrdFree( p->vPiCare ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManPackSetRandom( Aig_ManPack_t * p ) +{ + Aig_Obj_t * pObj; + word Sign; + int i; + Aig_ManForEachCi( p->pAig, pObj, i ) + { + Sign = (((word)Aig_ManRandom(0)) << 32) | ((word)Aig_ManRandom(0)); + Vec_WrdWriteEntry( p->vPiPats, i, Sign << 1 ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManPackSimulate( Aig_ManPack_t * p ) +{ + Aig_Obj_t * pObj; + word Sign, Sign0, Sign1; + int i; + // set the constant + Vec_WrdWriteEntry( p->vSigns, 0, ~(word)0 ); + // transfer into the array + Aig_ManForEachCi( p->pAig, pObj, i ) + Vec_WrdWriteEntry( p->vSigns, Aig_ObjId(pObj), Vec_WrdEntry(p->vPiPats, i) ); + // simulate internal nodes + Aig_ManForEachNode( p->pAig, pObj, i ) + { + Sign0 = Vec_WrdEntry( p->vSigns, Aig_ObjFaninId0(pObj) ); + Sign1 = Vec_WrdEntry( p->vSigns, Aig_ObjFaninId1(pObj) ); + if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) + Sign = ~(Sign0 | Sign1); + else if ( Aig_ObjFaninC0(pObj) ) + Sign = ~Sign0 & Sign1; + else if ( Aig_ObjFaninC1(pObj) ) + Sign = Sign0 & ~Sign1; + else + Sign = Sign0 & Sign1; + Vec_WrdWriteEntry( p->vSigns, Aig_ObjId(pObj), Sign ); + } + // set the outputs + Aig_ManForEachCo( p->pAig, pObj, i ) + { + Sign0 = Vec_WrdEntry( p->vSigns, Aig_ObjFaninId0(pObj) ); + Sign = Aig_ObjFaninC0(pObj) ? ~Sign0 : Sign0; + Vec_WrdWriteEntry( p->vSigns, Aig_ObjId(pObj), Sign ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManPackPrintStats( Aig_ManPack_t * p ) +{ + word Sign; + Aig_Obj_t * pObj; + int i, Total, Count, Counts[33] = {0}; // the number of nodes having that many patterns + Aig_ManForEachNode( p->pAig, pObj, i ) + { + Sign = Vec_WrdEntry( p->vSigns, Aig_ObjId(pObj) ); + Count = Aig_Word6CountOnes( Sign ); + if ( Count > 32 ) + Count = 64 - Count; + Counts[Count]++; + } + // print statistics + Total = 0; + for ( i = 0; i <= 32; i++ ) + { + Total += Counts[i]; + printf( "%2d : ", i ); + printf( "%6d ", Counts[i] ); + printf( "%6.1f %%", 100.0*Counts[i]/Aig_ManNodeNum(p->pAig) ); + printf( "%6.1f %%", 100.0*Total/Aig_ManNodeNum(p->pAig) ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Aig_ManPackConstNodes( Aig_ManPack_t * p ) +{ + Vec_Int_t * vNodes; + Aig_Obj_t * pObj; + word Sign; + int i; + vNodes = Vec_IntAlloc( 1000 ); + Aig_ManForEachNode( p->pAig, pObj, i ) + { + Sign = Vec_WrdEntry( p->vSigns, Aig_ObjId(pObj) ); + if ( Sign == 0 || ~Sign == 0 || Aig_Word6HasOneBit(Sign) || Aig_Word6HasOneBit(~Sign) ) + Vec_IntPush( vNodes, Aig_ObjId(pObj) ); + } + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Packs patterns into array of simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +*************************************`**********************************/ +int Aig_ManPackAddPatternTry( Aig_ManPack_t * p, int iBit, Vec_Int_t * vLits ) +{ + word * pInfo, * pPres; + int i, Lit; + Vec_IntForEachEntry( vLits, Lit, i ) + { + pInfo = Vec_WrdEntryP( p->vPiPats, Abc_Lit2Var(Lit) ); + pPres = Vec_WrdEntryP( p->vPiCare, Abc_Lit2Var(Lit) ); + if ( Abc_InfoHasBit( (unsigned *)pPres, iBit ) && + Abc_InfoHasBit( (unsigned *)pInfo, iBit ) == Abc_LitIsCompl(Lit) ) + return 0; + } + Vec_IntForEachEntry( vLits, Lit, i ) + { + pInfo = Vec_WrdEntryP( p->vPiPats, Abc_Lit2Var(Lit) ); + pPres = Vec_WrdEntryP( p->vPiCare, Abc_Lit2Var(Lit) ); + Abc_InfoSetBit( (unsigned *)pPres, iBit ); + if ( Abc_InfoHasBit( (unsigned *)pInfo, iBit ) == Abc_LitIsCompl(Lit) ) + Abc_InfoXorBit( (unsigned *)pInfo, iBit ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManPackAddPattern( Aig_ManPack_t * p, Vec_Int_t * vLits ) +{ + int k; + for ( k = 1; k < 64; k++ ) + if ( Aig_ManPackAddPatternTry( p, k, vLits ) ) + break; + if ( k == 64 ) + { +/* + word * pInfo, * pPres; + int i, Lit; + Vec_IntForEachEntry( vLits, Lit, i ) + printf( "%d", Abc_LitIsCompl(Lit) ); + printf( "\n\n" ); + for ( k = 1; k < 64; k++ ) + { + Vec_IntForEachEntry( vLits, Lit, i ) + { + pInfo = Vec_WrdEntryP( p->vPiPats, Abc_Lit2Var(Lit) ); + pPres = Vec_WrdEntryP( p->vPiCare, Abc_Lit2Var(Lit) ); + if ( Abc_InfoHasBit( (unsigned *)pPres, k ) ) + printf( "%d", Abc_InfoHasBit( (unsigned *)pInfo, k ) ); + else + printf( "-" ); + } + printf( "\n" ); + } +*/ + p->nPatSkip++; + } + p->nPatTotal++; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_ManPack_t * Aig_ManPackStart( Aig_Man_t * pAig ) +{ + Aig_ManPack_t * p; + p = Aig_ManPackAlloc( pAig ); + Aig_ManPackSetRandom( p ); + Aig_ManPackSimulate( p ); + Aig_ManPackPrintStats( p ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManPackStop( Aig_ManPack_t * p ) +{ + Aig_ManPackSimulate( p ); + Aig_ManPackPrintStats( p ); + Aig_ManPackFree( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigPart.c b/yosys/abc/src/aig/aig/aigPart.c new file mode 100644 index 00000000000..9b978e3b47b --- /dev/null +++ b/yosys/abc/src/aig/aig/aigPart.c @@ -0,0 +1,1613 @@ +/**CFile**************************************************************** + + FileName [aigPart.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [AIG partitioning package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigPart.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" +#include "misc/tim/tim.h" +#include "proof/fra/fra.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Part_Man_t_ Part_Man_t; +struct Part_Man_t_ +{ + int nChunkSize; // the size of one chunk of memory (~1 MB) + int nStepSize; // the step size in saving memory (~64 bytes) + char * pFreeBuf; // the pointer to free memory + int nFreeSize; // the size of remaining free memory + Vec_Ptr_t * vMemory; // the memory allocated + Vec_Ptr_t * vFree; // the vector of free pieces of memory +}; + +typedef struct Part_One_t_ Part_One_t; +struct Part_One_t_ +{ + int nRefs; // the number of references + int nOuts; // the number of outputs + int nOutsAlloc; // the array size + int pOuts[0]; // the array of outputs +}; + +static inline int Part_SizeType( int nSize, int nStepSize ) { return nSize / nStepSize + ((nSize % nStepSize) > 0); } +static inline char * Part_OneNext( char * pPart ) { return *((char **)pPart); } +static inline void Part_OneSetNext( char * pPart, char * pNext ) { *((char **)pPart) = pNext; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Start the memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Part_Man_t * Part_ManStart( int nChunkSize, int nStepSize ) +{ + Part_Man_t * p; + p = ABC_ALLOC( Part_Man_t, 1 ); + memset( p, 0, sizeof(Part_Man_t) ); + p->nChunkSize = nChunkSize; + p->nStepSize = nStepSize; + p->vMemory = Vec_PtrAlloc( 1000 ); + p->vFree = Vec_PtrAlloc( 1000 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Part_ManStop( Part_Man_t * p ) +{ + void * pMemory; + int i; + Vec_PtrForEachEntry( void *, p->vMemory, pMemory, i ) + ABC_FREE( pMemory ); + Vec_PtrFree( p->vMemory ); + Vec_PtrFree( p->vFree ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Fetches the memory entry of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Part_ManFetch( Part_Man_t * p, int nSize ) +{ + int Type, nSizeReal; + char * pMemory; + assert( nSize > 0 ); + Type = Part_SizeType( nSize, p->nStepSize ); + Vec_PtrFillExtra( p->vFree, Type + 1, NULL ); + if ( (pMemory = (char *)Vec_PtrEntry( p->vFree, Type )) ) + { + Vec_PtrWriteEntry( p->vFree, Type, Part_OneNext(pMemory) ); + return pMemory; + } + nSizeReal = p->nStepSize * Type; + if ( p->nFreeSize < nSizeReal ) + { + p->pFreeBuf = ABC_ALLOC( char, p->nChunkSize ); + p->nFreeSize = p->nChunkSize; + Vec_PtrPush( p->vMemory, p->pFreeBuf ); + } + assert( p->nFreeSize >= nSizeReal ); + pMemory = p->pFreeBuf; + p->pFreeBuf += nSizeReal; + p->nFreeSize -= nSizeReal; + return pMemory; +} + +/**Function************************************************************* + + Synopsis [Recycles the memory entry of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Part_ManRecycle( Part_Man_t * p, char * pMemory, int nSize ) +{ + int Type; + Type = Part_SizeType( nSize, p->nStepSize ); + Vec_PtrFillExtra( p->vFree, Type + 1, NULL ); + Part_OneSetNext( pMemory, (char *)Vec_PtrEntry(p->vFree, Type) ); + Vec_PtrWriteEntry( p->vFree, Type, pMemory ); +} + +/**Function************************************************************* + + Synopsis [Fetches the memory entry of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Part_One_t * Part_ManFetchEntry( Part_Man_t * p, int nWords, int nRefs ) +{ + Part_One_t * pPart; + pPart = (Part_One_t *)Part_ManFetch( p, sizeof(Part_One_t) + sizeof(int) * nWords ); + pPart->nRefs = nRefs; + pPart->nOuts = 0; + pPart->nOutsAlloc = nWords; + return pPart; +} + +/**Function************************************************************* + + Synopsis [Recycles the memory entry of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Part_ManRecycleEntry( Part_Man_t * p, Part_One_t * pEntry ) +{ + assert( pEntry->nOuts <= pEntry->nOutsAlloc ); + assert( pEntry->nOuts >= pEntry->nOutsAlloc/2 ); + Part_ManRecycle( p, (char *)pEntry, sizeof(Part_One_t) + sizeof(int) * pEntry->nOutsAlloc ); +} + +/**Function************************************************************* + + Synopsis [Merges two entries.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Part_One_t * Part_ManMergeEntry( Part_Man_t * pMan, Part_One_t * p1, Part_One_t * p2, int nRefs ) +{ + Part_One_t * p = Part_ManFetchEntry( pMan, p1->nOuts + p2->nOuts, nRefs ); + int * pBeg1 = p1->pOuts; + int * pBeg2 = p2->pOuts; + int * pBeg = p->pOuts; + int * pEnd1 = p1->pOuts + p1->nOuts; + int * pEnd2 = p2->pOuts + p2->nOuts; + while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) + { + if ( *pBeg1 == *pBeg2 ) + *pBeg++ = *pBeg1++, pBeg2++; + else if ( *pBeg1 < *pBeg2 ) + *pBeg++ = *pBeg1++; + else + *pBeg++ = *pBeg2++; + } + while ( pBeg1 < pEnd1 ) + *pBeg++ = *pBeg1++; + while ( pBeg2 < pEnd2 ) + *pBeg++ = *pBeg2++; + p->nOuts = pBeg - p->pOuts; + assert( p->nOuts <= p->nOutsAlloc ); + assert( p->nOuts >= p1->nOuts ); + assert( p->nOuts >= p2->nOuts ); + return p; +} + +/**Function************************************************************* + + Synopsis [Tranfers the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Part_ManTransferEntry( Part_One_t * p ) +{ + Vec_Int_t * vSupp; + int i; + vSupp = Vec_IntAlloc( p->nOuts ); + for ( i = 0; i < p->nOuts; i++ ) + Vec_IntPush( vSupp, p->pOuts[i] ); + return vSupp; +} + +/**Function************************************************************* + + Synopsis [Computes supports of the POs in the multi-output AIG.] + + Description [Returns the array of integer arrays containing indices + of the primary inputs for each primary output.] + + SideEffects [Adds the integer PO number at end of each array.] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManSupports( Aig_Man_t * pMan ) +{ + Vec_Ptr_t * vSupports; + Vec_Int_t * vSupp; + Part_Man_t * p; + Part_One_t * pPart0, * pPart1; + Aig_Obj_t * pObj; + int i, Counter = 0; + // set the number of PIs/POs + Aig_ManForEachCi( pMan, pObj, i ) + pObj->pNext = (Aig_Obj_t *)(long)i; + Aig_ManForEachCo( pMan, pObj, i ) + pObj->pNext = (Aig_Obj_t *)(long)i; + // start the support computation manager + p = Part_ManStart( 1 << 20, 1 << 6 ); + // consider objects in the topological order + vSupports = Vec_PtrAlloc( Aig_ManCoNum(pMan) ); + Aig_ManCleanData(pMan); + Aig_ManForEachObj( pMan, pObj, i ) + { + if ( Aig_ObjIsNode(pObj) ) + { + pPart0 = (Part_One_t *)Aig_ObjFanin0(pObj)->pData; + pPart1 = (Part_One_t *)Aig_ObjFanin1(pObj)->pData; + pObj->pData = Part_ManMergeEntry( p, pPart0, pPart1, pObj->nRefs ); + assert( pPart0->nRefs > 0 ); + if ( --pPart0->nRefs == 0 ) + Part_ManRecycleEntry( p, pPart0 ); + assert( pPart1->nRefs > 0 ); + if ( --pPart1->nRefs == 0 ) + Part_ManRecycleEntry( p, pPart1 ); + if ( ((Part_One_t *)pObj->pData)->nOuts <= 16 ) + Counter++; + continue; + } + if ( Aig_ObjIsCo(pObj) ) + { + pPart0 = (Part_One_t *)Aig_ObjFanin0(pObj)->pData; + vSupp = Part_ManTransferEntry(pPart0); + Vec_IntPush( vSupp, (int)(long)pObj->pNext ); + Vec_PtrPush( vSupports, vSupp ); + assert( pPart0->nRefs > 0 ); + if ( --pPart0->nRefs == 0 ) + Part_ManRecycleEntry( p, pPart0 ); + continue; + } + if ( Aig_ObjIsCi(pObj) ) + { + if ( pObj->nRefs ) + { + pPart0 = Part_ManFetchEntry( p, 1, pObj->nRefs ); + pPart0->pOuts[ pPart0->nOuts++ ] = (int)(long)pObj->pNext; + pObj->pData = pPart0; + } + continue; + } + if ( Aig_ObjIsConst1(pObj) ) + { + if ( pObj->nRefs ) + pObj->pData = Part_ManFetchEntry( p, 0, pObj->nRefs ); + continue; + } + assert( 0 ); + } +//printf( "Memory usage = %d MB.\n", Vec_PtrSize(p->vMemory) * p->nChunkSize / (1<<20) ); + Part_ManStop( p ); + // sort supports by size + Vec_VecSort( (Vec_Vec_t *)vSupports, 1 ); + // clear the number of PIs/POs + Aig_ManForEachCi( pMan, pObj, i ) + pObj->pNext = NULL; + Aig_ManForEachCo( pMan, pObj, i ) + pObj->pNext = NULL; +/* + Aig_ManForEachCo( pMan, pObj, i ) + printf( "%d ", Vec_IntSize( Vec_VecEntryInt(vSupports, i) ) ); + printf( "\n" ); +*/ +// printf( "%d \n", Counter ); + return vSupports; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManSupportsTest( Aig_Man_t * pMan ) +{ + Vec_Ptr_t * vSupps; + vSupps = Aig_ManSupports( pMan ); + Vec_VecFree( (Vec_Vec_t *)vSupps ); +} + +/**Function************************************************************* + + Synopsis [Computes the set of outputs for each input.] + + Description [Returns the array of integer arrays containing indices + of the primary outputsf for each primary input.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManSupportsInverse( Aig_Man_t * p ) +{ + Vec_Ptr_t * vSupps, * vSuppsInv; + Vec_Int_t * vSupp; + int i, k, iIn, iOut; + // get structural supports for each output + vSupps = Aig_ManSupports( p ); + // start the inverse supports + vSuppsInv = Vec_PtrAlloc( Aig_ManCiNum(p) ); + for ( i = 0; i < Aig_ManCiNum(p); i++ ) + Vec_PtrPush( vSuppsInv, Vec_IntAlloc(8) ); + // transforms the supports into the inverse supports + Vec_PtrForEachEntry( Vec_Int_t *, vSupps, vSupp, i ) + { + iOut = Vec_IntPop( vSupp ); + Vec_IntForEachEntry( vSupp, iIn, k ) + Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(vSuppsInv, iIn), iOut ); + } + Vec_VecFree( (Vec_Vec_t *)vSupps ); + return vSuppsInv; +} + +/**Function************************************************************* + + Synopsis [Returns the register dependency matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManSupportsRegisters( Aig_Man_t * p ) +{ + Vec_Ptr_t * vSupports, * vMatrix; + Vec_Int_t * vSupp; + int iOut, iIn, k, m, i; + // get structural supports for each output + vSupports = Aig_ManSupports( p ); + // transforms the supports into the latch dependency matrix + vMatrix = Vec_PtrStart( Aig_ManRegNum(p) ); + Vec_PtrForEachEntry( Vec_Int_t *, vSupports, vSupp, i ) + { + // skip true POs + iOut = Vec_IntPop( vSupp ); + iOut -= Aig_ManCoNum(p) - Aig_ManRegNum(p); + if ( iOut < 0 ) + { + Vec_IntFree( vSupp ); + continue; + } + // remove PIs + m = 0; + Vec_IntForEachEntry( vSupp, iIn, k ) + { + iIn -= Aig_ManCiNum(p) - Aig_ManRegNum(p); + if ( iIn < 0 ) + continue; + assert( iIn < Aig_ManRegNum(p) ); + Vec_IntWriteEntry( vSupp, m++, iIn ); + } + Vec_IntShrink( vSupp, m ); + // store support in the matrix + assert( iOut < Aig_ManRegNum(p) ); + Vec_PtrWriteEntry( vMatrix, iOut, vSupp ); + } + Vec_PtrFree( vSupports ); + // check that all supports are used + Vec_PtrForEachEntry( Vec_Int_t *, vMatrix, vSupp, i ) + assert( vSupp != NULL ); + return vMatrix; +} + +/**Function************************************************************* + + Synopsis [Start char-bases support representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Aig_ManSuppCharStart( Vec_Int_t * vOne, int nPis ) +{ + unsigned * pBuffer; + int i, Entry; + int nWords = Abc_BitWordNum(nPis); + pBuffer = ABC_ALLOC( unsigned, nWords ); + memset( pBuffer, 0, sizeof(unsigned) * nWords ); + Vec_IntForEachEntry( vOne, Entry, i ) + { + assert( Entry < nPis ); + Abc_InfoSetBit( pBuffer, Entry ); + } + return pBuffer; +} + +/**Function************************************************************* + + Synopsis [Add to char-bases support representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManSuppCharAdd( unsigned * pBuffer, Vec_Int_t * vOne, int nPis ) +{ + int i, Entry; + Vec_IntForEachEntry( vOne, Entry, i ) + { + assert( Entry < nPis ); + Abc_InfoSetBit( pBuffer, Entry ); + } +} + +/**Function************************************************************* + + Synopsis [Find the common variables using char-bases support representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManSuppCharCommon( unsigned * pBuffer, Vec_Int_t * vOne ) +{ + int i, Entry, nCommon = 0; + Vec_IntForEachEntry( vOne, Entry, i ) + nCommon += Abc_InfoHasBit(pBuffer, Entry); + return nCommon; +} + +/**Function************************************************************* + + Synopsis [Find the best partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManPartitionSmartFindPart( Vec_Ptr_t * vPartSuppsAll, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsBit, int nSuppSizeLimit, Vec_Int_t * vOne ) +{ + Vec_Int_t * vPartSupp;//, * vPart; + int Attract, Repulse, Value, ValueBest; + int i, nCommon, iBest; + iBest = -1; + ValueBest = 0; + Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vPartSupp, i ) + { +// vPart = Vec_PtrEntry( vPartsAll, i ); +// if ( nSuppSizeLimit > 0 && Vec_IntSize(vPart) >= nSuppSizeLimit ) +// continue; +// nCommon = Vec_IntTwoCountCommon( vPartSupp, vOne ); + nCommon = Aig_ManSuppCharCommon( (unsigned *)Vec_PtrEntry(vPartSuppsBit, i), vOne ); + if ( nCommon == 0 ) + continue; + if ( nCommon == Vec_IntSize(vOne) ) + return i; + // skip partitions whose size exceeds the limit + if ( nSuppSizeLimit > 0 && Vec_IntSize(vPartSupp) >= 2 * nSuppSizeLimit ) + continue; + Attract = 1000 * nCommon / Vec_IntSize(vOne); + if ( Vec_IntSize(vPartSupp) < 100 ) + Repulse = 1; + else + Repulse = 1+Abc_Base2Log(Vec_IntSize(vPartSupp)-100); + Value = Attract/Repulse; + if ( ValueBest < Value ) + { + ValueBest = Value; + iBest = i; + } + } + if ( ValueBest < 75 ) + return -1; + return iBest; +} + +/**Function************************************************************* + + Synopsis [Perform the smart partitioning.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManPartitionPrint( Aig_Man_t * p, Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll ) +{ + Vec_Int_t * vOne; + int i, nOutputs, Counter; + + Counter = 0; + Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vOne, i ) + { + nOutputs = Vec_IntSize((Vec_Int_t *)Vec_PtrEntry(vPartsAll, i)); + printf( "%d=(%d,%d) ", i, Vec_IntSize(vOne), nOutputs ); + Counter += nOutputs; + if ( i == Vec_PtrSize(vPartsAll) - 1 ) + break; + } + assert( Counter == Aig_ManCoNum(p) ); +// printf( "\nTotal = %d. Outputs = %d.\n", Counter, Aig_ManCoNum(p) ); +} + +/**Function************************************************************* + + Synopsis [Perform the smart partitioning.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManPartitionCompact( Vec_Ptr_t * vPartsAll, Vec_Ptr_t * vPartSuppsAll, int nSuppSizeLimit ) +{ + Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp; + int i, iPart; + + if ( nSuppSizeLimit == 0 ) + nSuppSizeLimit = 200; + + // pack smaller partitions into larger blocks + iPart = 0; + vPart = vPartSupp = NULL; + Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vOne, i ) + { + if ( Vec_IntSize(vOne) < nSuppSizeLimit ) + { + if ( vPartSupp == NULL ) + { + assert( vPart == NULL ); + vPartSupp = Vec_IntDup(vOne); + vPart = (Vec_Int_t *)Vec_PtrEntry(vPartsAll, i); + } + else + { + vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne ); + Vec_IntFree( vTemp ); + vPart = Vec_IntTwoMerge( vTemp = vPart, (Vec_Int_t *)Vec_PtrEntry(vPartsAll, i) ); + Vec_IntFree( vTemp ); + Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(vPartsAll, i) ); + } + if ( Vec_IntSize(vPartSupp) < nSuppSizeLimit ) + continue; + } + else + vPart = (Vec_Int_t *)Vec_PtrEntry(vPartsAll, i); + // add the partition + Vec_PtrWriteEntry( vPartsAll, iPart, vPart ); + vPart = NULL; + if ( vPartSupp ) + { + Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(vPartSuppsAll, iPart) ); + Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp ); + vPartSupp = NULL; + } + iPart++; + } + // add the last one + if ( vPart ) + { + Vec_PtrWriteEntry( vPartsAll, iPart, vPart ); + vPart = NULL; + + assert( vPartSupp != NULL ); + Vec_IntFree( (Vec_Int_t *)Vec_PtrEntry(vPartSuppsAll, iPart) ); + Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp ); + vPartSupp = NULL; + iPart++; + } + Vec_PtrShrink( vPartsAll, iPart ); + Vec_PtrShrink( vPartsAll, iPart ); +} + +/**Function************************************************************* + + Synopsis [Perform the smart partitioning.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManPartitionSmart( Aig_Man_t * p, int nSuppSizeLimit, int fVerbose, Vec_Ptr_t ** pvPartSupps ) +{ + Vec_Ptr_t * vPartSuppsBit; + Vec_Ptr_t * vSupports, * vPartsAll, * vPartsAll2, * vPartSuppsAll;//, * vPartPtr; + Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp; + int i, iPart, iOut; + abctime clk; + + // compute the supports for all outputs +clk = Abc_Clock(); + vSupports = Aig_ManSupports( p ); +if ( fVerbose ) +{ +ABC_PRT( "Supps", Abc_Clock() - clk ); +} + // start char-based support representation + vPartSuppsBit = Vec_PtrAlloc( 1000 ); + + // create partitions +clk = Abc_Clock(); + vPartsAll = Vec_PtrAlloc( 256 ); + vPartSuppsAll = Vec_PtrAlloc( 256 ); + Vec_PtrForEachEntry( Vec_Int_t *, vSupports, vOne, i ) + { + // get the output number + iOut = Vec_IntPop(vOne); + // find closely matching part + iPart = Aig_ManPartitionSmartFindPart( vPartSuppsAll, vPartsAll, vPartSuppsBit, nSuppSizeLimit, vOne ); + if ( iPart == -1 ) + { + // create new partition + vPart = Vec_IntAlloc( 32 ); + Vec_IntPush( vPart, iOut ); + // create new partition support + vPartSupp = Vec_IntDup( vOne ); + // add this partition and its support + Vec_PtrPush( vPartsAll, vPart ); + Vec_PtrPush( vPartSuppsAll, vPartSupp ); + + Vec_PtrPush( vPartSuppsBit, Aig_ManSuppCharStart(vOne, Aig_ManCiNum(p)) ); + } + else + { + // add output to this partition + vPart = (Vec_Int_t *)Vec_PtrEntry( vPartsAll, iPart ); + Vec_IntPush( vPart, iOut ); + // merge supports + vPartSupp = (Vec_Int_t *)Vec_PtrEntry( vPartSuppsAll, iPart ); + vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne ); + Vec_IntFree( vTemp ); + // reinsert new support + Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp ); + + Aig_ManSuppCharAdd( (unsigned *)Vec_PtrEntry(vPartSuppsBit, iPart), vOne, Aig_ManCiNum(p) ); + } + } + + // stop char-based support representation + Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsBit, vTemp, i ) + ABC_FREE( vTemp ); + Vec_PtrFree( vPartSuppsBit ); + +//printf( "\n" ); +if ( fVerbose ) +{ +ABC_PRT( "Parts", Abc_Clock() - clk ); +} + +clk = Abc_Clock(); + // reorder partitions in the decreasing order of support sizes + // remember partition number in each partition support + Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vOne, i ) + Vec_IntPush( vOne, i ); + // sort the supports in the decreasing order + Vec_VecSort( (Vec_Vec_t *)vPartSuppsAll, 1 ); + // reproduce partitions + vPartsAll2 = Vec_PtrAlloc( 256 ); + Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vOne, i ) + Vec_PtrPush( vPartsAll2, Vec_PtrEntry(vPartsAll, Vec_IntPop(vOne)) ); + Vec_PtrFree( vPartsAll ); + vPartsAll = vPartsAll2; + + // compact small partitions +// Aig_ManPartitionPrint( p, vPartsAll, vPartSuppsAll ); + Aig_ManPartitionCompact( vPartsAll, vPartSuppsAll, nSuppSizeLimit ); + if ( fVerbose ) +// Aig_ManPartitionPrint( p, vPartsAll, vPartSuppsAll ); + printf( "Created %d partitions.\n", Vec_PtrSize(vPartsAll) ); + +if ( fVerbose ) +{ +//ABC_PRT( "Comps", Abc_Clock() - clk ); +} + + // cleanup + Vec_VecFree( (Vec_Vec_t *)vSupports ); + if ( pvPartSupps == NULL ) + Vec_VecFree( (Vec_Vec_t *)vPartSuppsAll ); + else + *pvPartSupps = vPartSuppsAll; +/* + // converts from intergers to nodes + Vec_PtrForEachEntry( Vec_Int_t *, vPartsAll, vPart, iPart ) + { + vPartPtr = Vec_PtrAlloc( Vec_IntSize(vPart) ); + Vec_IntForEachEntry( vPart, iOut, i ) + Vec_PtrPush( vPartPtr, Aig_ManCo(p, iOut) ); + Vec_IntFree( vPart ); + Vec_PtrWriteEntry( vPartsAll, iPart, vPartPtr ); + } +*/ + return vPartsAll; +} + +/**Function************************************************************* + + Synopsis [Perform the smart partitioning.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManPartitionSmartRegisters( Aig_Man_t * pAig, int nSuppSizeLimit, int fVerbose ) +{ + Vec_Ptr_t * vPartSuppsBit; + Vec_Ptr_t * vSupports, * vPartsAll, * vPartsAll2, * vPartSuppsAll; + Vec_Int_t * vOne, * vPart, * vPartSupp, * vTemp; + int i, iPart, iOut; + abctime clk; + + // add output number to each +clk = Abc_Clock(); + vSupports = Aig_ManSupportsRegisters( pAig ); + assert( Vec_PtrSize(vSupports) == Aig_ManRegNum(pAig) ); + Vec_PtrForEachEntry( Vec_Int_t *, vSupports, vOne, i ) + Vec_IntPush( vOne, i ); +if ( fVerbose ) +{ +ABC_PRT( "Supps", Abc_Clock() - clk ); +} + + // start char-based support representation + vPartSuppsBit = Vec_PtrAlloc( 1000 ); + + // create partitions +clk = Abc_Clock(); + vPartsAll = Vec_PtrAlloc( 256 ); + vPartSuppsAll = Vec_PtrAlloc( 256 ); + Vec_PtrForEachEntry( Vec_Int_t *, vSupports, vOne, i ) + { + // get the output number + iOut = Vec_IntPop(vOne); + // find closely matching part + iPart = Aig_ManPartitionSmartFindPart( vPartSuppsAll, vPartsAll, vPartSuppsBit, nSuppSizeLimit, vOne ); + if ( iPart == -1 ) + { + // create new partition + vPart = Vec_IntAlloc( 32 ); + Vec_IntPush( vPart, iOut ); + // create new partition support + vPartSupp = Vec_IntDup( vOne ); + // add this partition and its support + Vec_PtrPush( vPartsAll, vPart ); + Vec_PtrPush( vPartSuppsAll, vPartSupp ); + + Vec_PtrPush( vPartSuppsBit, Aig_ManSuppCharStart(vOne, Vec_PtrSize(vSupports)) ); + } + else + { + // add output to this partition + vPart = (Vec_Int_t *)Vec_PtrEntry( vPartsAll, iPart ); + Vec_IntPush( vPart, iOut ); + // merge supports + vPartSupp = (Vec_Int_t *)Vec_PtrEntry( vPartSuppsAll, iPart ); + vPartSupp = Vec_IntTwoMerge( vTemp = vPartSupp, vOne ); + Vec_IntFree( vTemp ); + // reinsert new support + Vec_PtrWriteEntry( vPartSuppsAll, iPart, vPartSupp ); + + Aig_ManSuppCharAdd( (unsigned *)Vec_PtrEntry(vPartSuppsBit, iPart), vOne, Vec_PtrSize(vSupports) ); + } + } + + // stop char-based support representation + Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsBit, vTemp, i ) + ABC_FREE( vTemp ); + Vec_PtrFree( vPartSuppsBit ); + +//printf( "\n" ); +if ( fVerbose ) +{ +ABC_PRT( "Parts", Abc_Clock() - clk ); +} + +clk = Abc_Clock(); + // reorder partitions in the decreasing order of support sizes + // remember partition number in each partition support + Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vOne, i ) + Vec_IntPush( vOne, i ); + // sort the supports in the decreasing order + Vec_VecSort( (Vec_Vec_t *)vPartSuppsAll, 1 ); + // reproduce partitions + vPartsAll2 = Vec_PtrAlloc( 256 ); + Vec_PtrForEachEntry( Vec_Int_t *, vPartSuppsAll, vOne, i ) + Vec_PtrPush( vPartsAll2, Vec_PtrEntry(vPartsAll, Vec_IntPop(vOne)) ); + Vec_PtrFree( vPartsAll ); + vPartsAll = vPartsAll2; + + // compact small partitions +// Aig_ManPartitionPrint( p, vPartsAll, vPartSuppsAll ); + Aig_ManPartitionCompact( vPartsAll, vPartSuppsAll, nSuppSizeLimit ); + if ( fVerbose ) +// Aig_ManPartitionPrint( p, vPartsAll, vPartSuppsAll ); + printf( "Created %d partitions.\n", Vec_PtrSize(vPartsAll) ); + +if ( fVerbose ) +{ +//ABC_PRT( "Comps", Abc_Clock() - clk ); +} + + // cleanup + Vec_VecFree( (Vec_Vec_t *)vSupports ); +// if ( pvPartSupps == NULL ) + Vec_VecFree( (Vec_Vec_t *)vPartSuppsAll ); +// else +// *pvPartSupps = vPartSuppsAll; + +/* + // converts from intergers to nodes + Vec_PtrForEachEntry( Vec_Int_t *, vPartsAll, vPart, iPart ) + { + vPartPtr = Vec_PtrAlloc( Vec_IntSize(vPart) ); + Vec_IntForEachEntry( vPart, iOut, i ) + Vec_PtrPush( vPartPtr, Aig_ManCo(p, iOut) ); + Vec_IntFree( vPart ); + Vec_PtrWriteEntry( vPartsAll, iPart, vPartPtr ); + } +*/ + return vPartsAll; +} + +/**Function************************************************************* + + Synopsis [Perform the naive partitioning.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManPartitionNaive( Aig_Man_t * p, int nPartSize ) +{ + Vec_Ptr_t * vParts; + Aig_Obj_t * pObj; + int nParts, i; + nParts = (Aig_ManCoNum(p) / nPartSize) + ((Aig_ManCoNum(p) % nPartSize) > 0); + vParts = (Vec_Ptr_t *)Vec_VecStart( nParts ); + Aig_ManForEachCo( p, pObj, i ) + Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry(vParts, i / nPartSize), i ); + return vParts; +} + + + +/**Function************************************************************* + + Synopsis [Adds internal nodes in the topological order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ManDupPart_rec( Aig_Man_t * pNew, Aig_Man_t * pOld, Aig_Obj_t * pObj, Vec_Int_t * vSuppMap ) +{ + assert( !Aig_IsComplement(pObj) ); + if ( Aig_ObjIsTravIdCurrent(pOld, pObj) ) + return (Aig_Obj_t *)pObj->pData; + Aig_ObjSetTravIdCurrent(pOld, pObj); + if ( Aig_ObjIsCi(pObj) ) + { + assert( Vec_IntSize(vSuppMap) == Aig_ManCiNum(pNew) ); + Vec_IntPush( vSuppMap, (int)(long)pObj->pNext ); + return (Aig_Obj_t *)(pObj->pData = Aig_ObjCreateCi(pNew)); + } + assert( Aig_ObjIsNode(pObj) ); + Aig_ManDupPart_rec( pNew, pOld, Aig_ObjFanin0(pObj), vSuppMap ); + Aig_ManDupPart_rec( pNew, pOld, Aig_ObjFanin1(pObj), vSuppMap ); + return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) )); +} + +/**Function************************************************************* + + Synopsis [Adds internal nodes in the topological order.] + + Description [Returns the array of new outputs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManDupPart( Aig_Man_t * pNew, Aig_Man_t * pOld, Vec_Int_t * vPart, Vec_Int_t * vSuppMap, int fInverse ) +{ + Vec_Ptr_t * vOutsTotal; + Aig_Obj_t * pObj; + int Entry, i; + // create the PIs + Aig_ManIncrementTravId( pOld ); + Aig_ManConst1(pOld)->pData = Aig_ManConst1(pNew); + Aig_ObjSetTravIdCurrent( pOld, Aig_ManConst1(pOld) ); + if ( !fInverse ) + { + Vec_IntForEachEntry( vSuppMap, Entry, i ) + { + pObj = Aig_ManCi( pOld, Entry ); + pObj->pData = Aig_ManCi( pNew, i ); + Aig_ObjSetTravIdCurrent( pOld, pObj ); + } + } + else + { + Vec_IntForEachEntry( vSuppMap, Entry, i ) + { + pObj = Aig_ManCi( pOld, i ); + pObj->pData = Aig_ManCi( pNew, Entry ); + Aig_ObjSetTravIdCurrent( pOld, pObj ); + } + vSuppMap = NULL; // should not be useful + } + // create the internal nodes + vOutsTotal = Vec_PtrAlloc( Vec_IntSize(vPart) ); + if ( !fInverse ) + { + Vec_IntForEachEntry( vPart, Entry, i ) + { + pObj = Aig_ManCo( pOld, Entry ); + Aig_ManDupPart_rec( pNew, pOld, Aig_ObjFanin0(pObj), vSuppMap ); + Vec_PtrPush( vOutsTotal, Aig_ObjChild0Copy(pObj) ); + } + } + else + { + Aig_ManForEachObj( pOld, pObj, i ) + { + if ( Aig_ObjIsCo(pObj) ) + { + Aig_ManDupPart_rec( pNew, pOld, Aig_ObjFanin0(pObj), vSuppMap ); + Vec_PtrPush( vOutsTotal, Aig_ObjChild0Copy(pObj) ); + } + else if ( Aig_ObjIsNode(pObj) && pObj->nRefs == 0 ) + Aig_ManDupPart_rec( pNew, pOld, pObj, vSuppMap ); + + } + } + return vOutsTotal; +} + +/**Function************************************************************* + + Synopsis [Adds internal nodes in the topological order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManDupPartAll_rec( Aig_Man_t * pNew, Aig_Man_t * pOld, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pObjNew; + assert( !Aig_IsComplement(pObj) ); + if ( Aig_ObjIsTravIdCurrent(pOld, pObj) ) + return; + Aig_ObjSetTravIdCurrent(pOld, pObj); + if ( Aig_ObjIsCi(pObj) ) + pObjNew = Aig_ObjCreateCi(pNew); + else if ( Aig_ObjIsCo(pObj) ) + { + Aig_ManDupPartAll_rec( pNew, pOld, Aig_ObjFanin0(pObj) ); + pObjNew = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + } + else + { + assert( Aig_ObjIsNode(pObj) ); + Aig_ManDupPartAll_rec( pNew, pOld, Aig_ObjFanin0(pObj) ); + Aig_ManDupPartAll_rec( pNew, pOld, Aig_ObjFanin1(pObj) ); + pObjNew = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + } + pObj->pData = pObjNew; + pObjNew->pData = pObj; +} + +/**Function************************************************************* + + Synopsis [Adds internal nodes in the topological order.] + + Description [Returns the array of new outputs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupPartAll( Aig_Man_t * pOld, Vec_Int_t * vPart ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pObjNew; + int i, Entry; + Aig_ManIncrementTravId( pOld ); + pNew = Aig_ManStart( 5000 ); + // map constant nodes + pObj = Aig_ManConst1(pOld); + pObjNew = Aig_ManConst1(pNew); + pObj->pData = pObjNew; + pObjNew->pData = pObj; + Aig_ObjSetTravIdCurrent(pOld, pObj); + // map all other nodes + Vec_IntForEachEntry( vPart, Entry, i ) + { + pObj = Aig_ManCo( pOld, Entry ); + Aig_ManDupPartAll_rec( pNew, pOld, pObj ); + } + return pNew; +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManSupportNodes_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Int_t * vSupport ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Aig_ObjIsCi(pObj) ) + { + Vec_IntPush( vSupport, Aig_ObjCioId(pObj) ); + return; + } + Aig_ManSupportNodes_rec( p, Aig_ObjFanin0(pObj), vSupport ); + Aig_ManSupportNodes_rec( p, Aig_ObjFanin1(pObj), vSupport ); +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes and PIs in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManSupportNodes( Aig_Man_t * p, Vec_Ptr_t * vParts ) +{ + Vec_Ptr_t * vPartSupps; + Vec_Int_t * vPart, * vSupport; + int i, k, iOut; + Aig_ManSetCioIds( p ); + vPartSupps = Vec_PtrAlloc( Vec_PtrSize(vParts) ); + Vec_PtrForEachEntry( Vec_Int_t *, vParts, vPart, i ) + { + vSupport = Vec_IntAlloc( 100 ); + Aig_ManIncrementTravId( p ); + Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); + Vec_IntForEachEntry( vPart, iOut, k ) + Aig_ManSupportNodes_rec( p, Aig_ObjFanin0(Aig_ManCo(p, iOut)), vSupport ); +// Vec_IntSort( vSupport, 0 ); + Vec_PtrPush( vPartSupps, vSupport ); + } + Aig_ManCleanCioIds( p ); + return vPartSupps; +} + +/**Function************************************************************* + + Synopsis [Create partitioned miter of the two AIGs.] + + Description [Assumes that each output in the second AIG cannot have + more supp vars than the same output in the first AIG.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManMiterPartitioned( Aig_Man_t * p1, Aig_Man_t * p2, int nPartSize, int fSmart ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pMiter; + Vec_Ptr_t * vMiters, * vNodes1, * vNodes2; + Vec_Ptr_t * vParts, * vPartSupps; + Vec_Int_t * vPart, * vPartSupp; + int i, k; + // partition the first manager + if ( fSmart ) + vParts = Aig_ManPartitionSmart( p1, nPartSize, 0, &vPartSupps ); + else + { + vParts = Aig_ManPartitionNaive( p1, nPartSize ); + vPartSupps = Aig_ManSupportNodes( p1, vParts ); + } + // derive miters + vMiters = Vec_PtrAlloc( Vec_PtrSize(vParts) ); + for ( i = 0; i < Vec_PtrSize(vParts); i++ ) + { + // get partition and its support + vPart = (Vec_Int_t *)Vec_PtrEntry( vParts, i ); + vPartSupp = (Vec_Int_t *)Vec_PtrEntry( vPartSupps, i ); + // create the new miter + pNew = Aig_ManStart( 1000 ); + // create the PIs + for ( k = 0; k < Vec_IntSize(vPartSupp); k++ ) + Aig_ObjCreateCi( pNew ); + // copy the components + vNodes1 = Aig_ManDupPart( pNew, p1, vPart, vPartSupp, 0 ); + vNodes2 = Aig_ManDupPart( pNew, p2, vPart, vPartSupp, 0 ); + // create the miter + pMiter = Aig_MiterTwo( pNew, vNodes1, vNodes2 ); + Vec_PtrFree( vNodes1 ); + Vec_PtrFree( vNodes2 ); + // create the output + Aig_ObjCreateCo( pNew, pMiter ); + // clean up + Aig_ManCleanup( pNew ); + Vec_PtrPush( vMiters, pNew ); + } + Vec_VecFree( (Vec_Vec_t *)vParts ); + Vec_VecFree( (Vec_Vec_t *)vPartSupps ); + return vMiters; +} + +/**Function************************************************************* + + Synopsis [Performs partitioned choice computation.] + + Description [Assumes that each output in the second AIG cannot have + more supp vars than the same output in the first AIG.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManChoicePartitioned( Vec_Ptr_t * vAigs, int nPartSize, int nConfMax, int nLevelMax, int fVerbose ) +{ +// extern int Cmd_CommandExecute( void * pAbc, char * sCommand ); +// extern void * Abc_FrameGetGlobalFrame(); +// extern Aig_Man_t * Fra_FraigChoice( Aig_Man_t * pManAig, int nConfMax, int nLevelMax ); + + Vec_Ptr_t * vPios; + Vec_Ptr_t * vOutsTotal, * vOuts; + Aig_Man_t * pAigTotal, * pAigPart, * pAig, * pTemp; + Vec_Int_t * vPart, * vPartSupp; + Vec_Ptr_t * vParts; + Aig_Obj_t * pObj; + void ** ppData; + int i, k, m, nIdMax; + assert( Vec_PtrSize(vAigs) > 1 ); + + // compute the total number of IDs + nIdMax = 0; + Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig, i ) + nIdMax += Aig_ManObjNumMax(pAig); + + // partition the first AIG in the array + pAig = (Aig_Man_t *)Vec_PtrEntry( vAigs, 0 ); + vParts = Aig_ManPartitionSmart( pAig, nPartSize, 0, NULL ); + + // start the total fraiged AIG + pAigTotal = Aig_ManStartFrom( pAig ); + Aig_ManReprStart( pAigTotal, nIdMax ); + vOutsTotal = Vec_PtrStart( Aig_ManCoNum(pAig) ); + + // set the PI numbers + Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig, i ) + Aig_ManForEachCi( pAig, pObj, k ) + pObj->pNext = (Aig_Obj_t *)(long)k; + +// Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" ); + + // create the total fraiged AIG + vPartSupp = Vec_IntAlloc( 100 ); // maps part PI num into total PI num + Vec_PtrForEachEntry( Vec_Int_t *, vParts, vPart, i ) + { + // derive the partition AIG + pAigPart = Aig_ManStart( 5000 ); +// pAigPart->pName = Extra_UtilStrsav( pAigPart->pName ); + Vec_IntClear( vPartSupp ); + Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig, k ) + { + vOuts = Aig_ManDupPart( pAigPart, pAig, vPart, vPartSupp, 0 ); + if ( k == 0 ) + { + Vec_PtrForEachEntry( Aig_Obj_t *, vOuts, pObj, m ) + Aig_ObjCreateCo( pAigPart, pObj ); + } + Vec_PtrFree( vOuts ); + } + // derive the total AIG from the partitioned AIG + vOuts = Aig_ManDupPart( pAigTotal, pAigPart, vPart, vPartSupp, 1 ); + // add to the outputs + Vec_PtrForEachEntry( Aig_Obj_t *, vOuts, pObj, k ) + { + assert( Vec_PtrEntry( vOutsTotal, Vec_IntEntry(vPart,k) ) == NULL ); + Vec_PtrWriteEntry( vOutsTotal, Vec_IntEntry(vPart,k), pObj ); + } + Vec_PtrFree( vOuts ); + // store contents of pData pointers + ppData = ABC_ALLOC( void *, Aig_ManObjNumMax(pAigPart) ); + Aig_ManForEachObj( pAigPart, pObj, k ) + ppData[k] = pObj->pData; + // report the process + if ( fVerbose ) + printf( "Part %4d (out of %4d) PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r", + i+1, Vec_PtrSize(vParts), Aig_ManCiNum(pAigPart), Aig_ManCoNum(pAigPart), + Aig_ManNodeNum(pAigPart), Aig_ManLevelNum(pAigPart) ); + // compute equivalence classes (to be stored in pNew->pReprs) + pAig = Fra_FraigChoice( pAigPart, nConfMax, nLevelMax ); + Aig_ManStop( pAig ); + // reset the pData pointers + Aig_ManForEachObj( pAigPart, pObj, k ) + pObj->pData = ppData[k]; + ABC_FREE( ppData ); + // transfer representatives to the total AIG + if ( pAigPart->pReprs ) + Aig_ManTransferRepr( pAigTotal, pAigPart ); + Aig_ManStop( pAigPart ); + } + if ( fVerbose ) + printf( " \r" ); + Vec_VecFree( (Vec_Vec_t *)vParts ); + Vec_IntFree( vPartSupp ); + +// Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" ); + + // clear the PI numbers + Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig, i ) + Aig_ManForEachCi( pAig, pObj, k ) + pObj->pNext = NULL; + + // add the outputs in the same order + Vec_PtrForEachEntry( Aig_Obj_t *, vOutsTotal, pObj, i ) + Aig_ObjCreateCo( pAigTotal, pObj ); + Vec_PtrFree( vOutsTotal ); + + // derive the result of choicing + pAig = Aig_ManRehash( pAigTotal ); + // create the equivalent nodes lists + Aig_ManMarkValidChoices( pAig ); + // reconstruct the network + vPios = Aig_ManOrderPios( pAig, (Aig_Man_t *)Vec_PtrEntry(vAigs,0) ); + pAig = Aig_ManDupDfsGuided( pTemp = pAig, vPios ); + Aig_ManStop( pTemp ); + Vec_PtrFree( vPios ); + // duplicate the timing manager + pTemp = (Aig_Man_t *)Vec_PtrEntry( vAigs, 0 ); + if ( pTemp->pManTime ) + pAig->pManTime = Tim_ManDup( (Tim_Man_t *)pTemp->pManTime, 0 ); + // reset levels + Aig_ManChoiceLevel( pAig ); + return pAig; +} + +/**Function************************************************************* + + Synopsis [Performs partitioned choice computation.] + + Description [Assumes that each output in the second AIG cannot have + more supp vars than the same output in the first AIG.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManFraigPartitioned( Aig_Man_t * pAig, int nPartSize, int nConfMax, int nLevelMax, int fVerbose ) +{ +// extern Aig_Man_t * Fra_FraigChoice( Aig_Man_t * pManAig, int nConfMax, int nLevelMax ); + + Aig_Man_t * pAigPart, * pAigTemp; + Vec_Int_t * vPart; + Vec_Ptr_t * vParts; + Aig_Obj_t * pObj; + void ** ppData; + int i, k; + + // partition the outputs of the AIG + vParts = Aig_ManPartitionNaive( pAig, nPartSize ); + + // start the equivalence classes + Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) ); + + // set the PI numbers + Aig_ManSetCioIds( pAig ); + + // create the total fraiged AIG + Vec_PtrForEachEntry( Vec_Int_t *, vParts, vPart, i ) + { + // derive the partition AIG + pAigPart = Aig_ManDupPartAll( pAig, vPart ); + // store contents of pData pointers + ppData = ABC_ALLOC( void *, Aig_ManObjNumMax(pAigPart) ); + Aig_ManForEachObj( pAigPart, pObj, k ) + ppData[k] = pObj->pData; + // report the process + if ( fVerbose ) + printf( "Part %4d (out of %4d) PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r", + i+1, Vec_PtrSize(vParts), Aig_ManCiNum(pAigPart), Aig_ManCoNum(pAigPart), + Aig_ManNodeNum(pAigPart), Aig_ManLevelNum(pAigPart) ); + // compute equivalence classes (to be stored in pNew->pReprs) + pAigTemp = Fra_FraigChoice( pAigPart, nConfMax, nLevelMax ); + Aig_ManStop( pAigTemp ); + // reset the pData pointers + Aig_ManForEachObj( pAigPart, pObj, k ) + pObj->pData = ppData[k]; + ABC_FREE( ppData ); + // transfer representatives to the total AIG + if ( pAigPart->pReprs ) + Aig_ManTransferRepr( pAig, pAigPart ); + Aig_ManStop( pAigPart ); + } + if ( fVerbose ) + printf( " \r" ); + Vec_VecFree( (Vec_Vec_t *)vParts ); + + // clear the PI numbers + Aig_ManCleanCioIds( pAig ); + + // derive the result of choicing + return Aig_ManDupRepr( pAig, 0 ); +} + + + + +/**Function************************************************************* + + Synopsis [Set the representative.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Aig_ObjSetRepr_( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 ) +{ + assert( p->pReprs != NULL ); + assert( !Aig_IsComplement(pNode1) ); + assert( !Aig_IsComplement(pNode2) ); + assert( pNode1->Id < p->nReprsAlloc ); + assert( pNode2->Id < p->nReprsAlloc ); + if ( pNode1 == pNode2 ) + return; + if ( pNode1->Id < pNode2->Id ) + p->pReprs[pNode2->Id] = pNode1; + else + p->pReprs[pNode1->Id] = pNode2; +} + +/**Function************************************************************* + + Synopsis [Constructively accumulates choices.] + + Description [pNew is a new AIG with choices under construction. + pPrev is the AIG preceding pThis in the order of deriving choices. + pThis is the current AIG to be added to pNew while creating choices.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManChoiceConstructiveOne( Aig_Man_t * pNew, Aig_Man_t * pPrev, Aig_Man_t * pThis ) +{ + Aig_Obj_t * pObj, * pObjNew; + int i; + assert( Aig_ManCiNum(pNew) == Aig_ManCiNum(pPrev) ); + assert( Aig_ManCiNum(pNew) == Aig_ManCiNum(pThis) ); + assert( Aig_ManCoNum(pNew) == Aig_ManCoNum(pPrev) ); + assert( Aig_ManCoNum(pNew) == Aig_ManCoNum(pThis) ); + // make sure the nodes of pPrev point to pNew + Aig_ManForEachObj( pNew, pObj, i ) + pObj->fMarkB = 1; + Aig_ManForEachObj( pPrev, pObj, i ) + assert( Aig_Regular((Aig_Obj_t *)pObj->pData)->fMarkB ); + Aig_ManForEachObj( pNew, pObj, i ) + pObj->fMarkB = 0; + // make sure the nodes of pThis point to pPrev + Aig_ManForEachObj( pPrev, pObj, i ) + pObj->fMarkB = 1; + Aig_ManForEachObj( pPrev, pObj, i ) + pObj->fMarkB = 0; + // remap nodes of pThis on top of pNew using pPrev + pObj = Aig_ManConst1(pThis); + pObj->pData = Aig_ManConst1(pNew); + Aig_ManForEachCi( pThis, pObj, i ) + pObj->pData = Aig_ManCi(pNew, i); + Aig_ManForEachCo( pThis, pObj, i ) + pObj->pData = Aig_ManCo(pNew, i); + // go through the nodes in the topological order + Aig_ManForEachNode( pThis, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // set the inputs of POs as equivalent + Aig_ManForEachCo( pThis, pObj, i ) + { + pObjNew = Aig_ObjFanin0( Aig_ManCo(pNew,i) ); + // pObjNew and Aig_ObjFanin0(pObj)->pData are equivalent + Aig_ObjSetRepr_( pNew, pObjNew, Aig_Regular((Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData) ); + } +} + +/**Function************************************************************* + + Synopsis [Constructively accumulates choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManChoiceEval( Aig_Man_t * p ) +{ + Vec_Ptr_t * vSupp; + Aig_Obj_t * pNode, * pTemp; + int i, Counter; + + vSupp = Vec_PtrAlloc( 100 ); + Aig_ManForEachNode( p, pNode, i ) + { + if ( !Aig_ObjIsChoice(p, pNode) ) + continue; + Counter = 0; + for ( pTemp = pNode; pTemp; pTemp = Aig_ObjEquiv(p, pTemp) ) + Counter++; + printf( "Choice node = %5d. Level = %2d. Choices = %d. { ", pNode->Id, pNode->Level, Counter ); + for ( pTemp = pNode; pTemp; pTemp = Aig_ObjEquiv(p, pTemp) ) + { + Counter = Aig_NodeMffcSupp( p, pTemp, 0, vSupp ); + printf( "S=%d N=%d L=%d ", Vec_PtrSize(vSupp), Counter, pTemp->Level ); + } + printf( "}\n" ); + } + Vec_PtrFree( vSupp ); +} + +/**Function************************************************************* + + Synopsis [Constructively accumulates choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManChoiceConstructive( Vec_Ptr_t * vAigs, int fVerbose ) +{ + Vec_Ptr_t * vPios; + Aig_Man_t * pNew, * pThis, * pPrev, * pTemp; + int i; + // start AIG with choices + pPrev = (Aig_Man_t *)Vec_PtrEntry( vAigs, 0 ); + pNew = Aig_ManDupOrdered( pPrev ); + // create room for equivalent nodes and representatives + assert( pNew->pReprs == NULL ); + pNew->nReprsAlloc = Vec_PtrSize(vAigs) * Aig_ManObjNumMax(pNew); + pNew->pReprs = ABC_ALLOC( Aig_Obj_t *, pNew->nReprsAlloc ); + memset( pNew->pReprs, 0, sizeof(Aig_Obj_t *) * pNew->nReprsAlloc ); + // add other AIGs one by one + Vec_PtrForEachEntryStart( Aig_Man_t *, vAigs, pThis, i, 1 ) + { + Aig_ManChoiceConstructiveOne( pNew, pPrev, pThis ); + pPrev = pThis; + } + // derive the result of choicing + pNew = Aig_ManRehash( pNew ); + // create the equivalent nodes lists + Aig_ManMarkValidChoices( pNew ); + // reconstruct the network + vPios = Aig_ManOrderPios( pNew, (Aig_Man_t *)Vec_PtrEntry( vAigs, 0 ) ); + pNew = Aig_ManDupDfsGuided( pTemp = pNew, vPios ); + Aig_ManStop( pTemp ); + Vec_PtrFree( vPios ); + // duplicate the timing manager + pTemp = (Aig_Man_t *)Vec_PtrEntry( vAigs, 0 ); + if ( pTemp->pManTime ) + pNew->pManTime = Tim_ManDup( (Tim_Man_t *)pTemp->pManTime, 0 ); + // reset levels + Aig_ManChoiceLevel( pNew ); + return pNew; +} + +/* + Vec_Ptr_t * vPios; + vPios = Aig_ManOrderPios( pMan, pAig ); + Vec_PtrFree( vPios ); +*/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigPartReg.c b/yosys/abc/src/aig/aig/aigPartReg.c new file mode 100644 index 00000000000..b506490039b --- /dev/null +++ b/yosys/abc/src/aig/aig/aigPartReg.c @@ -0,0 +1,629 @@ +/**CFile**************************************************************** + + FileName [aigPartReg.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Register partitioning algorithm.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigPartReg.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" +//#include "fra.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Aig_ManPre_t_ Aig_ManPre_t; + +struct Aig_ManPre_t_ +{ + // input data + Aig_Man_t * pAig; // seq AIG manager + Vec_Ptr_t * vMatrix; // register dependency + int nRegsMax; // the max number of registers in the cluster + // information about partitions + Vec_Ptr_t * vParts; // the partitions + char * pfUsedRegs; // the registers already included in the partitions + // info about the current partition + Vec_Int_t * vRegs; // registers of this partition + Vec_Int_t * vUniques; // unique registers of this partition + Vec_Int_t * vFreeVars; // free variables of this partition + Vec_Flt_t * vPartCost; // costs of adding each variable + char * pfPartVars; // input/output registers of the partition +}; + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes partitioning of registers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_ManPre_t * Aig_ManRegManStart( Aig_Man_t * pAig, int nPartSize ) +{ + Aig_ManPre_t * p; + p = ABC_ALLOC( Aig_ManPre_t, 1 ); + memset( p, 0, sizeof(Aig_ManPre_t) ); + p->pAig = pAig; + p->vMatrix = Aig_ManSupportsRegisters( pAig ); + p->nRegsMax = nPartSize; + p->vParts = Vec_PtrAlloc(256); + p->vRegs = Vec_IntAlloc(256); + p->vUniques = Vec_IntAlloc(256); + p->vFreeVars = Vec_IntAlloc(256); + p->vPartCost = Vec_FltAlloc(256); + p->pfUsedRegs = ABC_ALLOC( char, Aig_ManRegNum(p->pAig) ); + memset( p->pfUsedRegs, 0, sizeof(char) * Aig_ManRegNum(p->pAig) ); + p->pfPartVars = ABC_ALLOC( char, Aig_ManRegNum(p->pAig) ); + return p; +} + +/**Function************************************************************* + + Synopsis [Computes partitioning of registers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManRegManStop( Aig_ManPre_t * p ) +{ + Vec_VecFree( (Vec_Vec_t *)p->vMatrix ); + if ( p->vParts ) + Vec_VecFree( (Vec_Vec_t *)p->vParts ); + Vec_IntFree( p->vRegs ); + Vec_IntFree( p->vUniques ); + Vec_IntFree( p->vFreeVars ); + Vec_FltFree( p->vPartCost ); + ABC_FREE( p->pfUsedRegs ); + ABC_FREE( p->pfPartVars ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Determines what register to use as the seed.] + + Description [The register is selected as the one having the largest + number of non-taken registers in its support.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManRegFindSeed( Aig_ManPre_t * p ) +{ + Vec_Int_t * vRegs; + int i, k, iReg; + int iMax = -1; // Suppress "might be used uninitialized" + int nRegsCur, nRegsMax = -1; + for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ ) + { + if ( p->pfUsedRegs[i] ) + continue; + nRegsCur = 0; + vRegs = (Vec_Int_t *)Vec_PtrEntry( p->vMatrix, i ); + Vec_IntForEachEntry( vRegs, iReg, k ) + nRegsCur += !p->pfUsedRegs[iReg]; + if ( nRegsMax < nRegsCur ) + { + nRegsMax = nRegsCur; + iMax = i; + } + } + return iMax; +} + +/**Function************************************************************* + + Synopsis [Computes the next register to be added to the set.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManRegFindBestVar( Aig_ManPre_t * p ) +{ + Vec_Int_t * vSupp; + int nNewVars, nNewVarsBest = ABC_INFINITY; + int iVarFree, iVarSupp, iVarBest = -1, i, k; + // go through the free variables + Vec_IntForEachEntry( p->vFreeVars, iVarFree, i ) + { +// if ( p->pfUsedRegs[iVarFree] ) +// continue; + // get support of this variable + vSupp = (Vec_Int_t *)Vec_PtrEntry( p->vMatrix, iVarFree ); + // count the number of new vars + nNewVars = 0; + Vec_IntForEachEntry( vSupp, iVarSupp, k ) + { + if ( p->pfPartVars[iVarSupp] ) + continue; + nNewVars += 1 + 3 * p->pfUsedRegs[iVarSupp]; + } + // quit if there is no new variables + if ( nNewVars == 0 ) + return iVarFree; + // compare the cost of this + if ( nNewVarsBest > nNewVars ) + { + nNewVarsBest = nNewVars; + iVarBest = iVarFree; + } + } + return iVarBest; +} + +/**Function************************************************************* + + Synopsis [Computes partitioning of registers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManRegPartitionAdd( Aig_ManPre_t * p, int iReg ) +{ + Vec_Int_t * vSupp; + int RetValue, iVar, i; + // make sure this is a new variable +// assert( !p->pfUsedRegs[iReg] ); + if ( !p->pfUsedRegs[iReg] ) + { + p->pfUsedRegs[iReg] = 1; + Vec_IntPush( p->vUniques, iReg ); + } + // remove it from the free variables + if ( Vec_IntSize(p->vFreeVars) > 0 ) + { + assert( p->pfPartVars[iReg] ); + RetValue = Vec_IntRemove( p->vFreeVars, iReg ); + assert( RetValue ); + } + else + assert( !p->pfPartVars[iReg] ); + // add it to the partition + p->pfPartVars[iReg] = 1; + Vec_IntPush( p->vRegs, iReg ); + // add new variables + vSupp = (Vec_Int_t *)Vec_PtrEntry( p->vMatrix, iReg ); + Vec_IntForEachEntry( vSupp, iVar, i ) + { + if ( p->pfPartVars[iVar] ) + continue; + p->pfPartVars[iVar] = 1; + Vec_IntPush( p->vFreeVars, iVar ); + } + // add it to the cost + Vec_FltPush( p->vPartCost, 1.0*Vec_IntSize(p->vFreeVars)/Vec_IntSize(p->vRegs) ); +} + +/**Function************************************************************* + + Synopsis [Creates projection of 1-hot registers onto the given partition.] + + Description [Assumes that the relevant register outputs are labeled with + the current traversal ID.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManRegProjectOnehots( Aig_Man_t * pAig, Aig_Man_t * pPart, Vec_Ptr_t * vOnehots, int fVerbose ) +{ + Vec_Ptr_t * vOnehotsPart = NULL; + Vec_Int_t * vGroup, * vGroupNew; + Aig_Obj_t * pObj, * pObjNew; + int nOffset, iReg, i, k; + // set the PI numbers + Aig_ManForEachCi( pPart, pObj, i ) + pObj->iData = i; + // go through each group and check if registers are involved in this one + nOffset = Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig); + Vec_PtrForEachEntry( Vec_Int_t *, vOnehots, vGroup, i ) + { + vGroupNew = NULL; + Vec_IntForEachEntry( vGroup, iReg, k ) + { + pObj = Aig_ManCi( pAig, nOffset+iReg ); + if ( !Aig_ObjIsTravIdCurrent(pAig, pObj) ) + continue; + if ( vGroupNew == NULL ) + vGroupNew = Vec_IntAlloc( Vec_IntSize(vGroup) ); + pObjNew = (Aig_Obj_t *)pObj->pData; + Vec_IntPush( vGroupNew, pObjNew->iData ); + } + if ( vGroupNew == NULL ) + continue; + if ( Vec_IntSize(vGroupNew) > 1 ) + { + if ( vOnehotsPart == NULL ) + vOnehotsPart = Vec_PtrAlloc( 100 ); + Vec_PtrPush( vOnehotsPart, vGroupNew ); + } + else + Vec_IntFree( vGroupNew ); + } + // clear the PI numbers + Aig_ManForEachCi( pPart, pObj, i ) + pObj->iData = 0; + // print out + if ( vOnehotsPart && fVerbose ) + { + printf( "Partition contains %d groups of 1-hot registers: { ", Vec_PtrSize(vOnehotsPart) ); + Vec_PtrForEachEntry( Vec_Int_t *, vOnehotsPart, vGroup, k ) + printf( "%d ", Vec_IntSize(vGroup) ); + printf( "}\n" ); + } + return vOnehotsPart; +} + +/**Function************************************************************* + + Synopsis [Computes partitioning of registers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManRegCreatePart( Aig_Man_t * pAig, Vec_Int_t * vPart, int * pnCountPis, int * pnCountRegs, int ** ppMapBack ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pObjNew; + Vec_Ptr_t * vNodes; + Vec_Ptr_t * vRoots; + int nOffset, iOut, i; + int nCountPis, nCountRegs; + int * pMapBack; + // collect roots + vRoots = Vec_PtrAlloc( Vec_IntSize(vPart) ); + nOffset = Aig_ManCoNum(pAig)-Aig_ManRegNum(pAig); + Vec_IntForEachEntry( vPart, iOut, i ) + { + pObj = Aig_ManCo(pAig, nOffset+iOut); + Vec_PtrPush( vRoots, Aig_ObjFanin0(pObj) ); + } + // collect/mark nodes/PIs in the DFS order + vNodes = Aig_ManDfsNodes( pAig, (Aig_Obj_t **)Vec_PtrArray(vRoots), Vec_PtrSize(vRoots) ); + Vec_PtrFree( vRoots ); + // unmark register outputs + nOffset = Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig); + Vec_IntForEachEntry( vPart, iOut, i ) + { + pObj = Aig_ManCi(pAig, nOffset+iOut); + Aig_ObjSetTravIdPrevious( pAig, pObj ); + } + // count pure PIs + nCountPis = nCountRegs = 0; + Aig_ManForEachPiSeq( pAig, pObj, i ) + nCountPis += Aig_ObjIsTravIdCurrent(pAig, pObj); + // count outputs of other registers + Aig_ManForEachLoSeq( pAig, pObj, i ) + nCountRegs += Aig_ObjIsTravIdCurrent(pAig, pObj); + if ( pnCountPis ) + *pnCountPis = nCountPis; + if ( pnCountRegs ) + *pnCountRegs = nCountRegs; + // create the new manager + pNew = Aig_ManStart( Vec_PtrSize(vNodes) ); + Aig_ManConst1(pAig)->pData = Aig_ManConst1(pNew); + // create the PIs + Aig_ManForEachCi( pAig, pObj, i ) + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + pObj->pData = Aig_ObjCreateCi(pNew); + // add variables for the register outputs + // create fake POs to hold the register outputs + nOffset = Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig); + Vec_IntForEachEntry( vPart, iOut, i ) + { + pObj = Aig_ManCi(pAig, nOffset+iOut); + pObj->pData = Aig_ObjCreateCi(pNew); + Aig_ObjCreateCo( pNew, (Aig_Obj_t *)pObj->pData ); + Aig_ObjSetTravIdCurrent( pAig, pObj ); // added + } + // create the nodes + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + if ( Aig_ObjIsNode(pObj) ) + pObj->pData = Aig_And(pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // add real POs for the registers + nOffset = Aig_ManCoNum(pAig)-Aig_ManRegNum(pAig); + Vec_IntForEachEntry( vPart, iOut, i ) + { + pObj = Aig_ManCo( pAig, nOffset+iOut ); + Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + } + pNew->nRegs = Vec_IntSize(vPart); + // create map + if ( ppMapBack ) + { + pMapBack = ABC_ALLOC( int, Aig_ManObjNumMax(pNew) ); + memset( pMapBack, 0xff, sizeof(int) * Aig_ManObjNumMax(pNew) ); + // map constant nodes + pMapBack[0] = 0; + // logic cones of register outputs + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + pObjNew = Aig_Regular((Aig_Obj_t *)pObj->pData); + pMapBack[pObjNew->Id] = pObj->Id; + } + // map register outputs + nOffset = Aig_ManCiNum(pAig)-Aig_ManRegNum(pAig); + Vec_IntForEachEntry( vPart, iOut, i ) + { + pObj = Aig_ManCi(pAig, nOffset+iOut); + pObjNew = (Aig_Obj_t *)pObj->pData; + pMapBack[pObjNew->Id] = pObj->Id; + } + *ppMapBack = pMapBack; + } + Vec_PtrFree( vNodes ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Computes partitioning of registers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManRegPartitionSmart( Aig_Man_t * pAig, int nPartSize ) +{ + extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact ); + + Aig_ManPre_t * p; + Vec_Ptr_t * vResult; + int iSeed, iNext, i, k; + // create the manager + p = Aig_ManRegManStart( pAig, nPartSize ); + // add partitions as long as registers remain + for ( i = 0; (iSeed = Aig_ManRegFindSeed(p)) >= 0; i++ ) + { +//printf( "Seed variable = %d.\n", iSeed ); + // clean the current partition information + Vec_IntClear( p->vRegs ); + Vec_IntClear( p->vUniques ); + Vec_IntClear( p->vFreeVars ); + Vec_FltClear( p->vPartCost ); + memset( p->pfPartVars, 0, sizeof(char) * Aig_ManRegNum(p->pAig) ); + // add the register and its partition support + Aig_ManRegPartitionAdd( p, iSeed ); + // select the best var to add + for ( k = 0; Vec_IntSize(p->vRegs) < p->nRegsMax; k++ ) + { + // get the next best variable + iNext = Aig_ManRegFindBestVar( p ); + if ( iNext == -1 ) + break; + // add the register to the support of the partition + Aig_ManRegPartitionAdd( p, iNext ); + // report the result +//printf( "Part %3d Reg %3d : Free = %4d. Total = %4d. Ratio = %6.2f. Unique = %4d.\n", i, k, +// Vec_IntSize(p->vFreeVars), Vec_IntSize(p->vRegs), +// 1.0*Vec_IntSize(p->vFreeVars)/Vec_IntSize(p->vRegs), Vec_IntSize(p->vUniques) ); + // quit if there are not free variables + if ( Vec_IntSize(p->vFreeVars) == 0 ) + break; + } + // add this partition to the set + Vec_PtrPush( p->vParts, Vec_IntDup(p->vRegs) ); +printf( "Part %3d SUMMARY: Free = %4d. Total = %4d. Ratio = %6.2f. Unique = %4d.\n", i, + Vec_IntSize(p->vFreeVars), Vec_IntSize(p->vRegs), + 1.0*Vec_IntSize(p->vFreeVars)/Vec_IntSize(p->vRegs), Vec_IntSize(p->vUniques) ); +//printf( "\n" ); + } + vResult = p->vParts; p->vParts = NULL; + Aig_ManRegManStop( p ); + return vResult; +} + +/**Function************************************************************* + + Synopsis [Computes partitioning of registers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManRegPartitionSimple( Aig_Man_t * pAig, int nPartSize, int nOverSize ) +{ + Vec_Ptr_t * vResult; + Vec_Int_t * vPart; + int i, Counter; + if ( nOverSize >= nPartSize ) + { + printf( "Overlap size (%d) is more or equal than the partition size (%d).\n", nOverSize, nPartSize ); + printf( "Adjusting it to be equal to half of the partition size.\n" ); + nOverSize = nPartSize/2; + } + assert( nOverSize < nPartSize ); + vResult = Vec_PtrAlloc( 100 ); + for ( Counter = 0; Counter < Aig_ManRegNum(pAig); Counter -= nOverSize ) + { + vPart = Vec_IntAlloc( nPartSize ); + for ( i = 0; i < nPartSize; i++, Counter++ ) + if ( Counter < Aig_ManRegNum(pAig) ) + Vec_IntPush( vPart, Counter ); + if ( Vec_IntSize(vPart) <= nOverSize ) + Vec_IntFree(vPart); + else + Vec_PtrPush( vResult, vPart ); + } + return vResult; +} + + +/**Function************************************************************* + + Synopsis [Divides a large partition into several ones.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManPartDivide( Vec_Ptr_t * vResult, Vec_Int_t * vDomain, int nPartSize, int nOverSize ) +{ + Vec_Int_t * vPart; + int i, Counter; + assert( nPartSize && Vec_IntSize(vDomain) > nPartSize ); + if ( nOverSize >= nPartSize ) + { + printf( "Overlap size (%d) is more or equal than the partition size (%d).\n", nOverSize, nPartSize ); + printf( "Adjusting it to be equal to half of the partition size.\n" ); + nOverSize = nPartSize/2; + } + assert( nOverSize < nPartSize ); + for ( Counter = 0; Counter < Vec_IntSize(vDomain); Counter -= nOverSize ) + { + vPart = Vec_IntAlloc( nPartSize ); + for ( i = 0; i < nPartSize; i++, Counter++ ) + if ( Counter < Vec_IntSize(vDomain) ) + Vec_IntPush( vPart, Vec_IntEntry(vDomain, Counter) ); + if ( Vec_IntSize(vPart) <= nOverSize ) + Vec_IntFree(vPart); + else + Vec_PtrPush( vResult, vPart ); + } +} + +/**Function************************************************************* + + Synopsis [Computes partitioning of registers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManRegPartitionTraverse_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vLos ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent( p, pObj ); + if ( Aig_ObjIsCi(pObj) ) + { + if ( pObj->iData >= Aig_ManCiNum(p) - Aig_ManRegNum(p) ) + { + Vec_PtrPush( vLos, pObj ); + printf( "%d ", pObj->iData - (Aig_ManCiNum(p) - Aig_ManRegNum(p)) ); + } + return; + } + Aig_ManRegPartitionTraverse_rec( p, Aig_ObjFanin0(pObj), vLos ); + Aig_ManRegPartitionTraverse_rec( p, Aig_ObjFanin1(pObj), vLos ); +} + +/**Function************************************************************* + + Synopsis [Computes partitioning of registers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManRegPartitionTraverse( Aig_Man_t * p ) +{ + Vec_Ptr_t * vLos; + Aig_Obj_t * pObj; + int i, nPrev, Counter; + // mark the registers + Aig_ManForEachCi( p, pObj, i ) + pObj->iData = i; + // collect registers + vLos = Vec_PtrAlloc( Aig_ManRegNum(p) ); + nPrev = 0; + Counter = 0; + Aig_ManIncrementTravId( p ); + Aig_ManForEachLiSeq( p, pObj, i ) + { + ++Counter; + printf( "Latch %d: ", Counter ); + Aig_ManRegPartitionTraverse_rec( p, Aig_ObjFanin0(pObj), vLos ); +printf( "%d=%d \n", Counter, Vec_PtrSize(vLos)-nPrev ); + nPrev = Vec_PtrSize(vLos); + } + printf( "Total collected = %d. Total regs = %d.\n", Vec_PtrSize(vLos), Aig_ManRegNum(p) ); + return vLos; +} + +/**Function************************************************************* + + Synopsis [Computes partitioning of registers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManRegPartitionLinear( Aig_Man_t * pAig, int nPartSize ) +{ + Vec_Ptr_t * vLos; + vLos = Aig_ManRegPartitionTraverse( pAig ); + Vec_PtrFree( vLos ); + return NULL; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigPartSat.c b/yosys/abc/src/aig/aig/aigPartSat.c new file mode 100644 index 00000000000..2794e886004 --- /dev/null +++ b/yosys/abc/src/aig/aig/aigPartSat.c @@ -0,0 +1,618 @@ +/**CFile**************************************************************** + + FileName [aigPartSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Partitioning for SAT solving.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigPartSat.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" +#include "sat/bsat/satSolver.h" +#include "sat/cnf/cnf.h" + +ABC_NAMESPACE_IMPL_START + + +/* + +The node partitioners defined in this file return array of intergers +mapping each AND node's ID into the 0-based number of its partition. +The mapping of PIs/POs will be derived automatically in Aig_ManPartSplit(). + +The partitions can be ordered in any way, but the recommended ordering +is to first include partitions whose nodes are closer to the outputs. + +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern Aig_Man_t * Dar_ManRwsat( Aig_Man_t * pAig, int fBalance, int fVerbose ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [No partitioning.] + + Description [The partitioner ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Aig_ManPartitionMonolithic( Aig_Man_t * p ) +{ + Vec_Int_t * vId2Part; + vId2Part = Vec_IntStart( Aig_ManObjNumMax(p) ); + return vId2Part; +} + +/**Function************************************************************* + + Synopsis [Partitioning using levelized order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Aig_ManPartitionLevelized( Aig_Man_t * p, int nPartSize ) +{ + Vec_Int_t * vId2Part; + Vec_Vec_t * vNodes; + Aig_Obj_t * pObj; + int i, k, Counter = 0; + vNodes = Aig_ManLevelize( p ); + vId2Part = Vec_IntStart( Aig_ManObjNumMax(p) ); + Vec_VecForEachEntryReverseReverse( Aig_Obj_t *, vNodes, pObj, i, k ) + Vec_IntWriteEntry( vId2Part, Aig_ObjId(pObj), Counter++/nPartSize ); + Vec_VecFree( vNodes ); + return vId2Part; +} + +/**Function************************************************************* + + Synopsis [Partitioning using DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Aig_ManPartitionDfs( Aig_Man_t * p, int nPartSize, int fPreorder ) +{ + Vec_Int_t * vId2Part; + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i, Counter = 0; + vId2Part = Vec_IntStart( Aig_ManObjNumMax(p) ); + if ( fPreorder ) + { + vNodes = Aig_ManDfsPreorder( p, 1 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + Vec_IntWriteEntry( vId2Part, Aig_ObjId(pObj), Counter++/nPartSize ); + } + else + { + vNodes = Aig_ManDfs( p, 1 ); + Vec_PtrForEachEntryReverse( Aig_Obj_t *, vNodes, pObj, i ) + Vec_IntWriteEntry( vId2Part, Aig_ObjId(pObj), Counter++/nPartSize ); + } + Vec_PtrFree( vNodes ); + return vId2Part; +} + +/**Function************************************************************* + + Synopsis [Recursively constructs the partition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManPartSplitOne_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Int_t * vPio2Id ) +{ + if ( !Aig_ObjIsTravIdCurrent( p, pObj ) ) + { // new PI + Aig_ObjSetTravIdCurrent( p, pObj ); +/* + if ( pObj->fMarkA ) // const0 + pObj->pData = Aig_ManConst0( pNew ); + else if ( pObj->fMarkB ) // const1 + pObj->pData = Aig_ManConst1( pNew ); + else +*/ + { + pObj->pData = Aig_ObjCreateCi( pNew ); + if ( pObj->fMarkA ) // const0 + ((Aig_Obj_t *)pObj->pData)->fMarkA = 1; + else if ( pObj->fMarkB ) // const1 + ((Aig_Obj_t *)pObj->pData)->fMarkB = 1; + Vec_IntPush( vPio2Id, Aig_ObjId(pObj) ); + } + return; + } + if ( pObj->pData ) + return; + Aig_ManPartSplitOne_rec( pNew, p, Aig_ObjFanin0(pObj), vPio2Id ); + Aig_ManPartSplitOne_rec( pNew, p, Aig_ObjFanin1(pObj), vPio2Id ); + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Carves out one partition of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManPartSplitOne( Aig_Man_t * p, Vec_Ptr_t * vNodes, Vec_Int_t ** pvPio2Id ) +{ + Vec_Int_t * vPio2Id; + Aig_Man_t * pNew; + Aig_Obj_t * pObj; + int i; + // mark these nodes + Aig_ManIncrementTravId( p ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + Aig_ObjSetTravIdCurrent( p, pObj ); + pObj->pData = NULL; + } + // add these nodes in a DFS order + pNew = Aig_ManStart( Vec_PtrSize(vNodes) ); + vPio2Id = Vec_IntAlloc( 100 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + Aig_ManPartSplitOne_rec( pNew, p, pObj, vPio2Id ); + // add the POs + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + if ( Aig_ObjRefs((Aig_Obj_t *)pObj->pData) != Aig_ObjRefs(pObj) ) + { + assert( Aig_ObjRefs((Aig_Obj_t *)pObj->pData) < Aig_ObjRefs(pObj) ); + Aig_ObjCreateCo( pNew, (Aig_Obj_t *)pObj->pData ); + Vec_IntPush( vPio2Id, Aig_ObjId(pObj) ); + } + assert( Aig_ManNodeNum(pNew) == Vec_PtrSize(vNodes) ); + *pvPio2Id = vPio2Id; + return pNew; +} + +/**Function************************************************************* + + Synopsis [Derives AIGs for each partition.] + + Description [The first argument is a original AIG. The second argument + is the array mapping each AND-node's ID into the 0-based number of its + partition. The last argument is the array of arrays (one for each new AIG) + mapping the index of each terminal in the new AIG (the index of each + terminal is derived by ordering PIs followed by POs in their natural order) + into the ID of the corresponding node in the original AIG. The returned + value is the array of AIGs representing the partitions.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManPartSplit( Aig_Man_t * p, Vec_Int_t * vNode2Part, Vec_Ptr_t ** pvPio2Id, Vec_Ptr_t ** pvPart2Pos ) +{ + Vec_Vec_t * vGroups, * vPart2Pos; + Vec_Ptr_t * vAigs, * vPio2Id, * vNodes; + Vec_Int_t * vPio2IdOne; + Aig_Man_t * pAig; + Aig_Obj_t * pObj, * pDriver; + int i, nodePart, nParts; + vAigs = Vec_PtrAlloc( 100 ); + vPio2Id = Vec_PtrAlloc( 100 ); + // put all nodes into levels according to their partition + nParts = Vec_IntFindMax(vNode2Part) + 1; + assert( nParts > 0 ); + vGroups = Vec_VecAlloc( nParts ); + Vec_IntForEachEntry( vNode2Part, nodePart, i ) + { + pObj = Aig_ManObj( p, i ); + if ( Aig_ObjIsNode(pObj) ) + Vec_VecPush( vGroups, nodePart, pObj ); + } + + // label PIs that should be restricted to some values + Aig_ManForEachCo( p, pObj, i ) + { + pDriver = Aig_ObjFanin0(pObj); + if ( Aig_ObjIsCi(pDriver) ) + { + if ( Aig_ObjFaninC0(pObj) ) + pDriver->fMarkA = 1; // const0 PI + else + pDriver->fMarkB = 1; // const1 PI + } + } + + // create partitions + Vec_VecForEachLevel( vGroups, vNodes, i ) + { + if ( Vec_PtrSize(vNodes) == 0 ) + { + printf( "Aig_ManPartSplit(): Skipping partition # %d without nodes (warning).\n", i ); + continue; + } + pAig = Aig_ManPartSplitOne( p, vNodes, &vPio2IdOne ); + Vec_PtrPush( vPio2Id, vPio2IdOne ); + Vec_PtrPush( vAigs, pAig ); + } + Vec_VecFree( vGroups ); + + // divide POs according to their partitions + vPart2Pos = Vec_VecStart( Vec_PtrSize(vAigs) ); + Aig_ManForEachCo( p, pObj, i ) + { + pDriver = Aig_ObjFanin0(pObj); + if ( Aig_ObjIsCi(pDriver) ) + pDriver->fMarkA = pDriver->fMarkB = 0; + else + Vec_VecPush( vPart2Pos, Vec_IntEntry(vNode2Part, Aig_ObjFaninId0(pObj)), pObj ); + } + + *pvPio2Id = vPio2Id; + *pvPart2Pos = (Vec_Ptr_t *)vPart2Pos; + return vAigs; +} + +/**Function************************************************************* + + Synopsis [Resets node polarity to unbias the polarity of CNF variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManPartResetNodePolarity( Aig_Man_t * pPart ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachObj( pPart, pObj, i ) + pObj->fPhase = 0; +} + +/**Function************************************************************* + + Synopsis [Sets polarity according to the original nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManPartSetNodePolarity( Aig_Man_t * p, Aig_Man_t * pPart, Vec_Int_t * vPio2Id ) +{ + Aig_Obj_t * pObj, * pObjInit; + int i; + Aig_ManConst1(pPart)->fPhase = 1; + Aig_ManForEachCi( pPart, pObj, i ) + { + pObjInit = Aig_ManObj( p, Vec_IntEntry(vPio2Id, i) ); + pObj->fPhase = pObjInit->fPhase; + } + Aig_ManForEachNode( pPart, pObj, i ) + pObj->fPhase = (Aig_ObjFanin0(pObj)->fPhase ^ Aig_ObjFaninC0(pObj)) & (Aig_ObjFanin1(pObj)->fPhase ^ Aig_ObjFaninC1(pObj)); + Aig_ManForEachCo( pPart, pObj, i ) + { + pObjInit = Aig_ManObj( p, Vec_IntEntry(vPio2Id, Aig_ManCiNum(pPart) + i) ); + pObj->fPhase = (Aig_ObjFanin0(pObj)->fPhase ^ Aig_ObjFaninC0(pObj)); + assert( pObj->fPhase == pObjInit->fPhase ); + } +} + +/**Function************************************************************* + + Synopsis [Sets polarity according to the original nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManDeriveCounterExample( Aig_Man_t * p, Vec_Int_t * vNode2Var, sat_solver * pSat ) +{ + Vec_Int_t * vPisIds; + Aig_Obj_t * pObj; + int i; + // collect IDs of PI variables + // (fanoutless PIs have SAT var 0, which is an unused in the SAT solver -> has value 0) + vPisIds = Vec_IntAlloc( Aig_ManCiNum(p) ); + Aig_ManForEachCi( p, pObj, i ) + Vec_IntPush( vPisIds, Vec_IntEntry(vNode2Var, Aig_ObjId(pObj)) ); + // derive the SAT assignment + p->pData = Sat_SolverGetModel( pSat, vPisIds->pArray, vPisIds->nSize ); + Vec_IntFree( vPisIds ); +} + +/**Function************************************************************* + + Synopsis [Derives CNF for the partition (pAig) and adds it to solver.] + + Description [Array vPio2Id contains mapping of the PI/PO terminal of pAig + into the IDs of the corresponding original nodes. Array vNode2Var contains + mapping of the original nodes into their SAT variable numbers.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManAddNewCnfToSolver( sat_solver * pSat, Aig_Man_t * pAig, Vec_Int_t * vNode2Var, + Vec_Int_t * vPioIds, Vec_Ptr_t * vPartPos, int fAlignPol ) +{ + Cnf_Dat_t * pCnf; + Aig_Obj_t * pObj; + int * pBeg, * pEnd; + int i, Lits[2], iSatVarOld, iNodeIdOld; + // derive CNF and express it using new SAT variables + pCnf = Cnf_Derive( pAig, Aig_ManCoNum(pAig) ); + Cnf_DataTranformPolarity( pCnf, 1 ); + Cnf_DataLift( pCnf, sat_solver_nvars(pSat) ); + // create new variables in the SAT solver + sat_solver_setnvars( pSat, sat_solver_nvars(pSat) + pCnf->nVars ); + // add clauses for this CNF + Cnf_CnfForClause( pCnf, pBeg, pEnd, i ) + if ( !sat_solver_addclause( pSat, pBeg, pEnd ) ) + { + assert( 0 ); // if it happens, can return 1 (unsatisfiable) + return 1; + } + // derive the connector clauses + Aig_ManForEachCi( pAig, pObj, i ) + { + iNodeIdOld = Vec_IntEntry( vPioIds, i ); + iSatVarOld = Vec_IntEntry( vNode2Var, iNodeIdOld ); + if ( iSatVarOld == 0 ) // iNodeIdOld in the original AIG has no SAT var + { + // map the corresponding original AIG node into this SAT var + Vec_IntWriteEntry( vNode2Var, iNodeIdOld, pCnf->pVarNums[Aig_ObjId(pObj)] ); + continue; + } + // add connector clauses + Lits[0] = toLitCond( iSatVarOld, 0 ); + Lits[1] = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 1 ); + if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) + assert( 0 ); + Lits[0] = toLitCond( iSatVarOld, 1 ); + Lits[1] = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ); + if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) + assert( 0 ); + } + // derive the connector clauses + Aig_ManForEachCo( pAig, pObj, i ) + { + iNodeIdOld = Vec_IntEntry( vPioIds, Aig_ManCiNum(pAig) + i ); + iSatVarOld = Vec_IntEntry( vNode2Var, iNodeIdOld ); + if ( iSatVarOld == 0 ) // iNodeIdOld in the original AIG has no SAT var + { + // map the corresponding original AIG node into this SAT var + Vec_IntWriteEntry( vNode2Var, iNodeIdOld, pCnf->pVarNums[Aig_ObjId(pObj)] ); + continue; + } + // add connector clauses + Lits[0] = toLitCond( iSatVarOld, 0 ); + Lits[1] = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 1 ); + if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) + assert( 0 ); + Lits[0] = toLitCond( iSatVarOld, 1 ); + Lits[1] = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ); + if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) + assert( 0 ); + } + // transfer the ID of constant 1 node + if ( Vec_IntEntry( vNode2Var, 0 ) == 0 ) + Vec_IntWriteEntry( vNode2Var, 0, pCnf->pVarNums[0] ); + // remove the CNF + Cnf_DataFree( pCnf ); + // constrain the solver with the literals corresponding to the original POs + Vec_PtrForEachEntry( Aig_Obj_t *, vPartPos, pObj, i ) + { + iNodeIdOld = Aig_ObjFaninId0( pObj ); + iSatVarOld = Vec_IntEntry( vNode2Var, iNodeIdOld ); + assert( iSatVarOld != 0 ); + // assert the original PO to be 1 + Lits[0] = toLitCond( iSatVarOld, Aig_ObjFaninC0(pObj) ); + // correct the polarity if polarity alignment is enabled + if ( fAlignPol && Aig_ObjFanin0(pObj)->fPhase ) + Lits[0] = lit_neg( Lits[0] ); + if ( !sat_solver_addclause( pSat, Lits, Lits+1 ) ) + { + assert( 0 ); // if it happens, can return 1 (unsatisfiable) + return 1; + } + } + // constrain some the primary inputs to constant values + Aig_ManForEachCi( pAig, pObj, i ) + { + if ( !pObj->fMarkA && !pObj->fMarkB ) + continue; + iNodeIdOld = Vec_IntEntry( vPioIds, i ); + iSatVarOld = Vec_IntEntry( vNode2Var, iNodeIdOld ); + Lits[0] = toLitCond( iSatVarOld, pObj->fMarkA ); + if ( !sat_solver_addclause( pSat, Lits, Lits+1 ) ) + { + assert( 0 ); // if it happens, can return 1 (unsatisfiable) + return 1; + } + pObj->fMarkA = pObj->fMarkB = 0; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Performs partitioned SAT solving.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManPartitionedSat( Aig_Man_t * p, int nAlgo, int nPartSize, + int nConfPart, int nConfTotal, int fAlignPol, int fSynthesize, int fVerbose ) +{ + sat_solver * pSat; + Vec_Ptr_t * vAigs; + Vec_Vec_t * vPio2Id, * vPart2Pos; + Aig_Man_t * pAig, * pTemp; + Vec_Int_t * vNode2Part, * vNode2Var; + int nConfRemaining = nConfTotal, nNodes = 0; + int i, status, RetValue = -1; + abctime clk; + + // perform partitioning according to the selected algorithm + clk = Abc_Clock(); + switch ( nAlgo ) + { + case 0: + vNode2Part = Aig_ManPartitionMonolithic( p ); + break; + case 1: + vNode2Part = Aig_ManPartitionLevelized( p, nPartSize ); + break; + case 2: + vNode2Part = Aig_ManPartitionDfs( p, nPartSize, 0 ); + break; + case 3: + vNode2Part = Aig_ManPartitionDfs( p, nPartSize, 1 ); + break; + default: + printf( "Unknown partitioning algorithm.\n" ); + return -1; + } + + if ( fVerbose ) + { + printf( "Partitioning derived %d partitions. ", Vec_IntFindMax(vNode2Part) + 1 ); + ABC_PRT( "Time", Abc_Clock() - clk ); + } + + // split the original AIG into partition AIGs (vAigs) + // also, derives mapping of PIs/POs of partition AIGs into original nodes + // also, derives mapping of POs of the original AIG into partitions + vAigs = Aig_ManPartSplit( p, vNode2Part, (Vec_Ptr_t **)&vPio2Id, (Vec_Ptr_t **)&vPart2Pos ); + Vec_IntFree( vNode2Part ); + + if ( fVerbose ) + { + printf( "Partions were transformed into AIGs. " ); + ABC_PRT( "Time", Abc_Clock() - clk ); + } + + // synthesize partitions + if ( fSynthesize ) + Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig, i ) + { + pAig = Dar_ManRwsat( pTemp = pAig, 0, 0 ); + Vec_PtrWriteEntry( vAigs, i, pAig ); + Aig_ManStop( pTemp ); + } + + // start the SAT solver + pSat = sat_solver_new(); +// pSat->verbosity = fVerbose; + // start mapping of the original AIG IDs into their SAT variable numbers + vNode2Var = Vec_IntStart( Aig_ManObjNumMax(p) ); + + // add partitions, one at a time, and run the SAT solver + Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pAig, i ) + { +clk = Abc_Clock(); + // transform polarity of the AIG + if ( fAlignPol ) + Aig_ManPartSetNodePolarity( p, pAig, Vec_VecEntryInt(vPio2Id,i) ); + else + Aig_ManPartResetNodePolarity( pAig ); + // add CNF of this partition to the SAT solver + if ( Aig_ManAddNewCnfToSolver( pSat, pAig, vNode2Var, + Vec_VecEntryInt(vPio2Id,i), Vec_VecEntry(vPart2Pos,i), fAlignPol ) ) + { + RetValue = 1; + break; + } + // call the SAT solver + status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfRemaining, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + if ( fVerbose ) + { + printf( "%4d : Aig = %6d. Vs = %7d. RootCs = %7d. LearnCs = %6d. ", + i, nNodes += Aig_ManNodeNum(pAig), sat_solver_nvars(pSat), + (int)pSat->stats.clauses, (int)pSat->stats.learnts ); +ABC_PRT( "Time", Abc_Clock() - clk ); + } + // analize the result + if ( status == l_False ) + { + RetValue = 1; + break; + } + else if ( status == l_True ) + RetValue = 0; + else + RetValue = -1; + nConfRemaining -= pSat->stats.conflicts; + if ( nConfRemaining <= 0 ) + { + printf( "Exceeded the limit on the total number of conflicts (%d).\n", nConfTotal ); + break; + } + } + if ( RetValue == 0 ) + Aig_ManDeriveCounterExample( p, vNode2Var, pSat ); + // cleanup + sat_solver_delete( pSat ); + Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pTemp, i ) + Aig_ManStop( pTemp ); + Vec_PtrFree( vAigs ); + Vec_VecFree( vPio2Id ); + Vec_VecFree( vPart2Pos ); + Vec_IntFree( vNode2Var ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigRepar.c b/yosys/abc/src/aig/aig/aigRepar.c new file mode 100644 index 00000000000..e85f5d21742 --- /dev/null +++ b/yosys/abc/src/aig/aig/aigRepar.c @@ -0,0 +1,403 @@ +/**CFile**************************************************************** + + FileName [aigRepar.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Interpolation-based reparametrization.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigRepar.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" +#include "sat/cnf/cnf.h" +#include "sat/bsat/satSolver2.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Adds buffer to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Aig_ManInterAddBuffer( sat_solver2 * pSat, int iVarA, int iVarB, int fCompl, int fMark ) +{ + lit Lits[2]; + int Cid; + assert( iVarA >= 0 && iVarB >= 0 ); + + Lits[0] = toLitCond( iVarA, 0 ); + Lits[1] = toLitCond( iVarB, !fCompl ); + Cid = sat_solver2_addclause( pSat, Lits, Lits + 2, 0 ); + if ( fMark ) + clause2_set_partA( pSat, Cid, 1 ); + + Lits[0] = toLitCond( iVarA, 1 ); + Lits[1] = toLitCond( iVarB, fCompl ); + Cid = sat_solver2_addclause( pSat, Lits, Lits + 2, 0 ); + if ( fMark ) + clause2_set_partA( pSat, Cid, 1 ); +} + +/**Function************************************************************* + + Synopsis [Adds constraints for the two-input AND-gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Aig_ManInterAddXor( sat_solver2 * pSat, int iVarA, int iVarB, int iVarC, int fCompl, int fMark ) +{ + lit Lits[3]; + int Cid; + assert( iVarA >= 0 && iVarB >= 0 && iVarC >= 0 ); + + Lits[0] = toLitCond( iVarA, !fCompl ); + Lits[1] = toLitCond( iVarB, 1 ); + Lits[2] = toLitCond( iVarC, 1 ); + Cid = sat_solver2_addclause( pSat, Lits, Lits + 3, 0 ); + if ( fMark ) + clause2_set_partA( pSat, Cid, 1 ); + + Lits[0] = toLitCond( iVarA, !fCompl ); + Lits[1] = toLitCond( iVarB, 0 ); + Lits[2] = toLitCond( iVarC, 0 ); + Cid = sat_solver2_addclause( pSat, Lits, Lits + 3, 0 ); + if ( fMark ) + clause2_set_partA( pSat, Cid, 1 ); + + Lits[0] = toLitCond( iVarA, fCompl ); + Lits[1] = toLitCond( iVarB, 1 ); + Lits[2] = toLitCond( iVarC, 0 ); + Cid = sat_solver2_addclause( pSat, Lits, Lits + 3, 0 ); + if ( fMark ) + clause2_set_partA( pSat, Cid, 1 ); + + Lits[0] = toLitCond( iVarA, fCompl ); + Lits[1] = toLitCond( iVarB, 0 ); + Lits[2] = toLitCond( iVarC, 1 ); + Cid = sat_solver2_addclause( pSat, Lits, Lits + 3, 0 ); + if ( fMark ) + clause2_set_partA( pSat, Cid, 1 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManInterTest( Aig_Man_t * pMan, int fVerbose ) +{ + sat_solver2 * pSat; +// Aig_Man_t * pInter; + word * pInter; + Vec_Int_t * vVars; + Cnf_Dat_t * pCnf; + Aig_Obj_t * pObj; + int Lit, Cid, Var, status, i; + clock_t clk = clock(); + assert( Aig_ManRegNum(pMan) == 0 ); + assert( Aig_ManCoNum(pMan) == 1 ); + + // derive CNFs + pCnf = Cnf_Derive( pMan, 1 ); + + // start the solver + pSat = sat_solver2_new(); + sat_solver2_setnvars( pSat, 2*pCnf->nVars+1 ); + // set A-variables (all used except PI/PO) + Aig_ManForEachObj( pMan, pObj, i ) + { + if ( pCnf->pVarNums[pObj->Id] < 0 ) + continue; + if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsCo(pObj) ) + var_set_partA( pSat, pCnf->pVarNums[pObj->Id], 1 ); + } + + // add clauses of A + for ( i = 0; i < pCnf->nClauses; i++ ) + { + Cid = sat_solver2_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1], 0 ); + clause2_set_partA( pSat, Cid, 1 ); + } + + // add clauses of B + Cnf_DataLift( pCnf, pCnf->nVars ); + for ( i = 0; i < pCnf->nClauses; i++ ) + sat_solver2_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1], 0 ); + Cnf_DataLift( pCnf, -pCnf->nVars ); + + // add PI equality clauses + vVars = Vec_IntAlloc( Aig_ManCoNum(pMan)+1 ); + Aig_ManForEachCi( pMan, pObj, i ) + { + if ( Aig_ObjRefs(pObj) == 0 ) + continue; + Var = pCnf->pVarNums[pObj->Id]; + Aig_ManInterAddBuffer( pSat, Var, pCnf->nVars + Var, 0, 0 ); + Vec_IntPush( vVars, Var ); + } + + // add an XOR clause in the end + Var = pCnf->pVarNums[Aig_ManCo(pMan,0)->Id]; + Aig_ManInterAddXor( pSat, Var, pCnf->nVars + Var, 2*pCnf->nVars, 0, 0 ); + Vec_IntPush( vVars, Var ); + + // solve the problem + Lit = toLitCond( 2*pCnf->nVars, 0 ); + status = sat_solver2_solve( pSat, &Lit, &Lit + 1, 0, 0, 0, 0 ); + assert( status == l_False ); + Sat_Solver2PrintStats( stdout, pSat ); + + // derive interpolant +// pInter = Sat_ProofInterpolant( pSat, vVars ); +// Aig_ManPrintStats( pInter ); +// Aig_ManDumpBlif( pInter, "int.blif", NULL, NULL ); +//pInter = Sat_ProofInterpolantTruth( pSat, vVars ); + pInter = NULL; +// Extra_PrintHex( stdout, pInter, Vec_IntSize(vVars) ); printf( "\n" ); + + // clean up +// Aig_ManStop( pInter ); + ABC_FREE( pInter ); + + Vec_IntFree( vVars ); + Cnf_DataFree( pCnf ); + sat_solver2_delete( pSat ); + ABC_PRT( "Total interpolation time", clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG while mapping PIs into the given array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManAppend( Aig_Man_t * pBase, Aig_Man_t * pNew ) +{ + Aig_Obj_t * pObj; + int i; + assert( Aig_ManCoNum(pNew) == 1 ); + assert( Aig_ManCiNum(pNew) == Aig_ManCiNum(pBase) ); + // create the PIs + Aig_ManCleanData( pNew ); + Aig_ManConst1(pNew)->pData = Aig_ManConst1(pBase); + Aig_ManForEachCi( pNew, pObj, i ) + pObj->pData = Aig_IthVar(pBase, i); + // duplicate internal nodes + Aig_ManForEachNode( pNew, pObj, i ) + pObj->pData = Aig_And( pBase, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // add one PO to base + pObj = Aig_ManCo( pNew, 0 ); + Aig_ObjCreateCo( pBase, Aig_ObjChild0Copy(pObj) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManInterRepar( Aig_Man_t * pMan, int fVerbose ) +{ + Aig_Man_t * pAigTemp, * pInter, * pBase = NULL; + sat_solver2 * pSat; + Vec_Int_t * vVars; + Cnf_Dat_t * pCnf, * pCnfInter; + Aig_Obj_t * pObj; + int nOuts = Aig_ManCoNum(pMan); + int ShiftP[2], ShiftCnf[2], ShiftOr[2], ShiftAssume; + int Cid, Lit, status, i, k, c; + clock_t clk = clock(); + assert( Aig_ManRegNum(pMan) == 0 ); + + // derive CNFs + pCnf = Cnf_Derive( pMan, nOuts ); + + // start the solver + pSat = sat_solver2_new(); + sat_solver2_setnvars( pSat, 4*pCnf->nVars + 6*nOuts ); + // vars: pGlobal + (p0 + A1 + A2 + or0) + (p1 + B1 + B2 + or1) + pAssume; + ShiftP[0] = nOuts; + ShiftP[1] = 2*pCnf->nVars + 3*nOuts; + ShiftCnf[0] = ShiftP[0] + nOuts; + ShiftCnf[1] = ShiftP[1] + nOuts; + ShiftOr[0] = ShiftCnf[0] + 2*pCnf->nVars; + ShiftOr[1] = ShiftCnf[1] + 2*pCnf->nVars; + ShiftAssume = ShiftOr[1] + nOuts; + assert( ShiftAssume + nOuts == pSat->size ); + + // mark variables of A + for ( i = ShiftCnf[0]; i < ShiftP[1]; i++ ) + var_set_partA( pSat, i, 1 ); + + // add clauses of A, then B + vVars = Vec_IntAlloc( 2*nOuts ); + for ( k = 0; k < 2; k++ ) + { + // copy A1 + Cnf_DataLift( pCnf, ShiftCnf[k] ); + for ( i = 0; i < pCnf->nClauses; i++ ) + { + Cid = sat_solver2_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1], 0 ); + clause2_set_partA( pSat, Cid, k==0 ); + } + // add equality p[k] == A1/B1 + Aig_ManForEachCo( pMan, pObj, i ) + Aig_ManInterAddBuffer( pSat, ShiftP[k] + i, pCnf->pVarNums[pObj->Id], k==1, k==0 ); + // copy A2 + Cnf_DataLift( pCnf, pCnf->nVars ); + for ( i = 0; i < pCnf->nClauses; i++ ) + { + Cid = sat_solver2_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1], 0 ); + clause2_set_partA( pSat, Cid, k==0 ); + } + // add comparator (!p[k] ^ A2/B2) == or[k] + Vec_IntClear( vVars ); + Aig_ManForEachCo( pMan, pObj, i ) + { + Aig_ManInterAddXor( pSat, ShiftP[k] + i, pCnf->pVarNums[pObj->Id], ShiftOr[k] + i, k==1, k==0 ); + Vec_IntPush( vVars, toLitCond(ShiftOr[k] + i, 1) ); + } + Cid = sat_solver2_addclause( pSat, Vec_IntArray(vVars), Vec_IntArray(vVars) + Vec_IntSize(vVars), 0 ); + clause2_set_partA( pSat, Cid, k==0 ); + // return to normal + Cnf_DataLift( pCnf, -ShiftCnf[k]-pCnf->nVars ); + } + // add clauses to constrain p[0] and p[1] + for ( k = 0; k < nOuts; k++ ) + Aig_ManInterAddXor( pSat, ShiftP[0] + k, ShiftP[1] + k, ShiftAssume + k, 0, 0 ); + + // start the interpolant + pBase = Aig_ManStart( 1000 ); + pBase->pName = Abc_UtilStrsav( "repar" ); + for ( k = 0; k < 2*nOuts; k++ ) + Aig_IthVar(pBase, i); + + // start global variables (pGlobal and p[0]) + Vec_IntClear( vVars ); + for ( k = 0; k < 2*nOuts; k++ ) + Vec_IntPush( vVars, k ); + + // perform iterative solving + // vars: pGlobal + (p0 + A1 + A2 + or0) + (p1 + B1 + B2 + or1) + pAssume; + for ( k = 0; k < nOuts; k++ ) + { + // swap k-th variables + int Temp = Vec_IntEntry( vVars, k ); + Vec_IntWriteEntry( vVars, k, Vec_IntEntry(vVars, nOuts+k) ); + Vec_IntWriteEntry( vVars, nOuts+k, Temp ); + + // solve incrementally + Lit = toLitCond( ShiftAssume + k, 1 ); // XOR output is 0 ==> p1 == p2 + status = sat_solver2_solve( pSat, &Lit, &Lit + 1, 0, 0, 0, 0 ); + assert( status == l_False ); + Sat_Solver2PrintStats( stdout, pSat ); + + // derive interpolant + pInter = (Aig_Man_t *)Sat_ProofInterpolant( pSat, vVars ); + Aig_ManPrintStats( pInter ); + // make sure interpolant does not depend on useless vars + Aig_ManForEachCi( pInter, pObj, i ) + assert( i <= k || Aig_ObjRefs(pObj) == 0 ); + + // simplify + pInter = Dar_ManRwsat( pAigTemp = pInter, 1, 0 ); + Aig_ManStop( pAigTemp ); + + // add interpolant to the solver + pCnfInter = Cnf_Derive( pInter, 1 ); + Cnf_DataLift( pCnfInter, pSat->size ); + sat_solver2_setnvars( pSat, pSat->size + 2*pCnfInter->nVars ); + for ( i = 0; i < pCnfInter->nVars; i++ ) + var_set_partA( pSat, pSat->size-2*pCnfInter->nVars + i, 1 ); + for ( c = 0; c < 2; c++ ) + { + if ( c == 1 ) + Cnf_DataLift( pCnfInter, pCnfInter->nVars ); + // add to A + for ( i = 0; i < pCnfInter->nClauses; i++ ) + { + Cid = sat_solver2_addclause( pSat, pCnfInter->pClauses[i], pCnfInter->pClauses[i+1], 0 ); + clause2_set_partA( pSat, Cid, c==0 ); + } + // connect to the inputs + Aig_ManForEachCi( pInter, pObj, i ) + if ( i <= k ) + Aig_ManInterAddBuffer( pSat, i, pCnf->pVarNums[pObj->Id], 0, c==0 ); + // connect to the outputs + pObj = Aig_ManCo(pInter, 0); + Aig_ManInterAddBuffer( pSat, ShiftP[c] + k, pCnf->pVarNums[pObj->Id], 0, c==0 ); + if ( c == 1 ) + Cnf_DataLift( pCnfInter, -pCnfInter->nVars ); + } + Cnf_DataFree( pCnfInter ); + + // accumulate + Aig_ManAppend( pBase, pInter ); + Aig_ManStop( pInter ); + + // update global variables + Temp = Vec_IntEntry( vVars, k ); + Vec_IntWriteEntry( vVars, k, Vec_IntEntry(vVars, nOuts+k) ); + Vec_IntWriteEntry( vVars, nOuts+k, Temp ); + } + + Vec_IntFree( vVars ); + Cnf_DataFree( pCnf ); + sat_solver2_delete( pSat ); + ABC_PRT( "Reparameterization time", clock() - clk ); + return pBase; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigRepr.c b/yosys/abc/src/aig/aig/aigRepr.c new file mode 100644 index 00000000000..0a9ebd4cd11 --- /dev/null +++ b/yosys/abc/src/aig/aig/aigRepr.c @@ -0,0 +1,559 @@ +/**CFile**************************************************************** + + FileName [aigRepr.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Handing node representatives.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigRepr.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the array of representatives.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManReprStart( Aig_Man_t * p, int nIdMax ) +{ + assert( Aig_ManBufNum(p) == 0 ); + assert( p->pReprs == NULL ); + p->nReprsAlloc = nIdMax; + p->pReprs = ABC_ALLOC( Aig_Obj_t *, p->nReprsAlloc ); + memset( p->pReprs, 0, sizeof(Aig_Obj_t *) * p->nReprsAlloc ); +} + +/**Function************************************************************* + + Synopsis [Stop the array of representatives.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManReprStop( Aig_Man_t * p ) +{ + assert( p->pReprs != NULL ); + ABC_FREE( p->pReprs ); + p->nReprsAlloc = 0; +} + +/**Function************************************************************* + + Synopsis [Set the representative.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjCreateRepr( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 ) +{ + assert( p->pReprs != NULL ); + assert( !Aig_IsComplement(pNode1) ); + assert( !Aig_IsComplement(pNode2) ); + assert( pNode1->Id < p->nReprsAlloc ); + assert( pNode2->Id < p->nReprsAlloc ); + assert( pNode1->Id < pNode2->Id ); + p->pReprs[pNode2->Id] = pNode1; +} + +/**Function************************************************************* + + Synopsis [Set the representative.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Aig_ObjSetRepr_( Aig_Man_t * p, Aig_Obj_t * pNode1, Aig_Obj_t * pNode2 ) +{ + assert( p->pReprs != NULL ); + assert( !Aig_IsComplement(pNode1) ); + assert( !Aig_IsComplement(pNode2) ); + assert( pNode1->Id < p->nReprsAlloc ); + assert( pNode2->Id < p->nReprsAlloc ); + if ( pNode1 == pNode2 ) + return; + if ( pNode1->Id < pNode2->Id ) + p->pReprs[pNode2->Id] = pNode1; + else + p->pReprs[pNode1->Id] = pNode2; +} + +/**Function************************************************************* + + Synopsis [Find representative.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Aig_Obj_t * Aig_ObjFindRepr( Aig_Man_t * p, Aig_Obj_t * pNode ) +{ + assert( p->pReprs != NULL ); + assert( !Aig_IsComplement(pNode) ); + assert( pNode->Id < p->nReprsAlloc ); +// assert( !p->pReprs[pNode->Id] || p->pReprs[pNode->Id]->Id < pNode->Id ); + return p->pReprs[pNode->Id]; +} + +/**Function************************************************************* + + Synopsis [Clears the representative.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Aig_ObjClearRepr( Aig_Man_t * p, Aig_Obj_t * pNode ) +{ + assert( p->pReprs != NULL ); + assert( !Aig_IsComplement(pNode) ); + assert( pNode->Id < p->nReprsAlloc ); + p->pReprs[pNode->Id] = NULL; +} + +/**Function************************************************************* + + Synopsis [Find representative transitively.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Aig_Obj_t * Aig_ObjFindReprTransitive( Aig_Man_t * p, Aig_Obj_t * pNode ) +{ + Aig_Obj_t * pNext, * pRepr; + if ( (pRepr = Aig_ObjFindRepr(p, pNode)) ) + while ( (pNext = Aig_ObjFindRepr(p, pRepr)) ) + pRepr = pNext; + return pRepr; +} + +/**Function************************************************************* + + Synopsis [Returns representatives of fanin in approapriate polarity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Aig_Obj_t * Aig_ObjGetRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pRepr; + if ( (pRepr = Aig_ObjFindRepr(p, pObj)) ) + return Aig_NotCond( (Aig_Obj_t *)pRepr->pData, pObj->fPhase ^ pRepr->fPhase ); + return (Aig_Obj_t *)pObj->pData; +} +static inline Aig_Obj_t * Aig_ObjChild0Repr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_NotCond( Aig_ObjGetRepr(p, Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj) ); } +static inline Aig_Obj_t * Aig_ObjChild1Repr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_NotCond( Aig_ObjGetRepr(p, Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj) ); } + +/**Function************************************************************* + + Synopsis [Duplicates AIG while substituting representatives.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManTransferRepr( Aig_Man_t * pNew, Aig_Man_t * pOld ) +{ + Aig_Obj_t * pObj, * pRepr; + int k; + assert( pNew->pReprs != NULL ); + // extend storage to fix pNew + if ( pNew->nReprsAlloc < Aig_ManObjNumMax(pNew) ) + { + int nReprsAllocNew = 2 * Aig_ManObjNumMax(pNew); + pNew->pReprs = ABC_REALLOC( Aig_Obj_t *, pNew->pReprs, nReprsAllocNew ); + memset( pNew->pReprs + pNew->nReprsAlloc, 0, sizeof(Aig_Obj_t *) * (nReprsAllocNew-pNew->nReprsAlloc) ); + pNew->nReprsAlloc = nReprsAllocNew; + } + // go through the nodes which have representatives + Aig_ManForEachObj( pOld, pObj, k ) + if ( (pRepr = Aig_ObjFindRepr(pOld, pObj)) ) + Aig_ObjSetRepr_( pNew, Aig_Regular((Aig_Obj_t *)pRepr->pData), Aig_Regular((Aig_Obj_t *)pObj->pData) ); +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager recursively.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ManDupRepr_rec( Aig_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pRepr; + if ( pObj->pData ) + return (Aig_Obj_t *)pObj->pData; + if ( (pRepr = Aig_ObjFindRepr(p, pObj)) ) + { + Aig_ManDupRepr_rec( pNew, p, pRepr ); + return (Aig_Obj_t *)(pObj->pData = Aig_NotCond( (Aig_Obj_t *)pRepr->pData, pRepr->fPhase ^ pObj->fPhase )); + } + Aig_ManDupRepr_rec( pNew, p, Aig_ObjFanin0(pObj) ); + Aig_ManDupRepr_rec( pNew, p, Aig_ObjFanin1(pObj) ); + return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, Aig_ObjChild0Repr(p, pObj), Aig_ObjChild1Repr(p, pObj) )); +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG while substituting representatives.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupRepr( Aig_Man_t * p, int fOrdered ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj; + int i; + // start the HOP package + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nConstrs = p->nConstrs; + pNew->nBarBufs = p->nBarBufs; + if ( p->vFlopNums ) + pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); + // map the const and primary inputs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachCi( p, pObj, i ) + pObj->pData = Aig_ObjCreateCi(pNew); +// Aig_ManForEachCi( p, pObj, i ) +// pObj->pData = Aig_ObjGetRepr( p, pObj ); + // map the internal nodes + if ( fOrdered ) + { + Aig_ManForEachNode( p, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Repr(p, pObj), Aig_ObjChild1Repr(p, pObj) ); + } + else + { +// Aig_ManForEachObj( p, pObj, i ) +// if ( p->pReprs[i] ) +// printf( "Substituting %d for %d.\n", p->pReprs[i]->Id, pObj->Id ); + + Aig_ManForEachCo( p, pObj, i ) + Aig_ManDupRepr_rec( pNew, p, Aig_ObjFanin0(pObj) ); + } + // transfer the POs + Aig_ManForEachCo( p, pObj, i ) + Aig_ObjCreateCo( pNew, Aig_ObjChild0Repr(p, pObj) ); + Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); + // check the new manager + if ( !Aig_ManCheck(pNew) ) + printf( "Aig_ManDupRepr: Check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG with representatives without removing registers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupReprBasic( Aig_Man_t * p ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj; + int i; + assert( p->pReprs != NULL ); + // reconstruct AIG with representatives + pNew = Aig_ManDupRepr( p, 0 ); + // perfrom sequential cleanup but do not remove registers + Aig_ManSeqCleanupBasic( pNew ); + // remove pointers to the dead nodes + Aig_ManForEachObj( p, pObj, i ) + if ( pObj->pData && Aig_ObjIsNone((Aig_Obj_t *)pObj->pData) ) + pObj->pData = NULL; + return pNew; +} + +/**Function************************************************************* + + Synopsis [Transfer representatives and return the number of critical fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManRemapRepr( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj, * pRepr; + int i, nFanouts = 0; + Aig_ManForEachNode( p, pObj, i ) + { + pRepr = Aig_ObjFindReprTransitive( p, pObj ); + if ( pRepr == NULL ) + continue; + assert( pRepr->Id < pObj->Id ); + Aig_ObjSetRepr_( p, pObj, pRepr ); + nFanouts += (pObj->nRefs > 0); + } + return nFanouts; +} + +/**Function************************************************************* + + Synopsis [Transfer representatives and return the number of critical fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManCountReprs( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + if ( p->pReprs == NULL ) + return 0; + Aig_ManForEachObj( p, pObj, i ) + Counter += (p->pReprs[i] != NULL); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pOld is in the TFI of pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjCheckTfi_rec( Aig_Man_t * p, Aig_Obj_t * pNode, Aig_Obj_t * pOld ) +{ + // check the trivial cases + if ( pNode == NULL ) + return 0; + if ( Aig_ObjIsCi(pNode) ) + return 0; +// if ( pNode->Id < pOld->Id ) // cannot use because of choices of pNode +// return 0; + if ( pNode == pOld ) + return 1; + // skip the visited node + if ( Aig_ObjIsTravIdCurrent( p, pNode ) ) + return 0; + Aig_ObjSetTravIdCurrent( p, pNode ); + // check the children + if ( Aig_ObjCheckTfi_rec( p, Aig_ObjFanin0(pNode), pOld ) ) + return 1; + if ( Aig_ObjCheckTfi_rec( p, Aig_ObjFanin1(pNode), pOld ) ) + return 1; + // check equivalent nodes + return Aig_ObjCheckTfi_rec( p, Aig_ObjEquiv(p, pNode), pOld ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pOld is in the TFI of pNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjCheckTfi( Aig_Man_t * p, Aig_Obj_t * pNew, Aig_Obj_t * pOld ) +{ + assert( !Aig_IsComplement(pNew) ); + assert( !Aig_IsComplement(pOld) ); + Aig_ManIncrementTravId( p ); + return Aig_ObjCheckTfi_rec( p, pNew, pOld ); +} + +/**Function************************************************************* + + Synopsis [Iteratively rehashes the AIG.] + + Description [The input AIG is assumed to have representatives assigned.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManRehash( Aig_Man_t * p ) +{ + Aig_Man_t * pTemp; + int i, nFanouts; + assert( p->pReprs != NULL ); + for ( i = 0; (nFanouts = Aig_ManRemapRepr( p )); i++ ) + { +// printf( "Iter = %3d. Fanouts = %6d. Nodes = %7d.\n", i+1, nFanouts, Aig_ManNodeNum(p) ); + p = Aig_ManDupRepr( pTemp = p, 1 ); + Aig_ManReprStart( p, Aig_ManObjNumMax(p) ); + Aig_ManTransferRepr( p, pTemp ); + Aig_ManStop( pTemp ); + } + return p; +} + +/**Function************************************************************* + + Synopsis [Marks the nodes that are Creates choices.] + + Description [The input AIG is assumed to have representatives assigned.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManMarkValidChoices( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj, * pRepr; + int i; + assert( p->pReprs != NULL ); + // create equivalent nodes in the manager + assert( p->pEquivs == NULL ); + p->pEquivs = ABC_ALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p) ); + memset( p->pEquivs, 0, sizeof(Aig_Obj_t *) * Aig_ManObjNumMax(p) ); + // make the choice nodes + Aig_ManForEachNode( p, pObj, i ) + { + pRepr = Aig_ObjFindRepr( p, pObj ); + if ( pRepr == NULL ) + continue; + // skip constant and PI classes + if ( !Aig_ObjIsNode(pRepr) ) + { + Aig_ObjClearRepr( p, pObj ); + continue; + } + // skip choices with combinatinal loops + if ( Aig_ObjCheckTfi( p, pObj, pRepr ) ) + { + Aig_ObjClearRepr( p, pObj ); + continue; + } +//printf( "Node %d is represented by node %d.\n", pObj->Id, pRepr->Id ); + // add choice to the choice node + if ( pObj->nRefs > 0 ) + { + Aig_ObjClearRepr( p, pObj ); + continue; + } + assert( pObj->nRefs == 0 ); + p->pEquivs[pObj->Id] = p->pEquivs[pRepr->Id]; + p->pEquivs[pRepr->Id] = pObj; + } +} + + +/**Function************************************************************* + + Synopsis [Transfers the classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_TransferMappedClasses( Aig_Man_t * pAig, Aig_Man_t * pPart, int * pMapBack ) +{ + Aig_Obj_t * pObj; + int nClasses, k; + nClasses = 0; + if ( pPart->pReprs ) { + Aig_ManForEachObj( pPart, pObj, k ) + { + if ( pPart->pReprs[pObj->Id] == NULL ) + continue; + nClasses++; + Aig_ObjSetRepr_( pAig, + Aig_ManObj(pAig, pMapBack[pObj->Id]), + Aig_ManObj(pAig, pMapBack[pPart->pReprs[pObj->Id]->Id]) ); + } + } + return nClasses; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigRet.c b/yosys/abc/src/aig/aig/aigRet.c new file mode 100644 index 00000000000..7712e8679dc --- /dev/null +++ b/yosys/abc/src/aig/aig/aigRet.c @@ -0,0 +1,975 @@ +/**CFile**************************************************************** + + FileName [aigRet.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Retiming of AIGs.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigRet.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// init values +typedef enum { + RTM_VAL_NONE, // 0: non-existent value + RTM_VAL_ZERO, // 1: initial value 0 + RTM_VAL_ONE, // 2: initial value 1 + RTM_VAL_VOID // 3: unused value +} Rtm_Init_t; + +typedef struct Rtm_Man_t_ Rtm_Man_t; +struct Rtm_Man_t_ +{ + // network representation + Vec_Ptr_t * vObjs; // retiming objects + Vec_Ptr_t * vPis; // PIs only + Vec_Ptr_t * vPos; // POs only + Aig_MmFlex_t * pMem; // the memory manager + // autonomous components after cutting off + // storage for overflow latches + unsigned * pExtra; + int nExtraCur; + int nExtraAlloc; +}; + +typedef struct Rtm_Edg_t_ Rtm_Edg_t; +struct Rtm_Edg_t_ +{ + unsigned long nLats : 12; // the number of latches + unsigned long LData : 20; // the latches themselves +}; + +typedef struct Rtm_Obj_t_ Rtm_Obj_t; +struct Rtm_Obj_t_ +{ + void * pCopy; // the copy of this object + unsigned long Type : 3; // object type + unsigned long fMark : 1; // multipurpose mark + unsigned long fAuto : 1; // this object belongs to an autonomous component + unsigned long fCompl0 : 1; // complemented attribute of the first edge + unsigned long fCompl1 : 1; // complemented attribute of the second edge + unsigned long nFanins : 8; // the number of fanins + unsigned Num : 17; // the retiming number of this node + int Id; // ID of this object + int Temp; // temporary usage + int nFanouts; // the number of fanouts + void * pFanio[0]; // fanins and their edges (followed by fanouts and pointers to their edges) +}; + +static inline Rtm_Obj_t * Rtm_ObjFanin( Rtm_Obj_t * pObj, int i ) { return (Rtm_Obj_t *)pObj->pFanio[2*i]; } +static inline Rtm_Obj_t * Rtm_ObjFanout( Rtm_Obj_t * pObj, int i ) { return (Rtm_Obj_t *)pObj->pFanio[2*(pObj->nFanins+i)]; } +static inline Rtm_Edg_t * Rtm_ObjEdge( Rtm_Obj_t * pObj, int i ) { return (Rtm_Edg_t *)(pObj->pFanio + 2*i + 1); } +static inline Rtm_Edg_t * Rtm_ObjFanoutEdge( Rtm_Obj_t * pObj, int i ) { return (Rtm_Edg_t *)pObj->pFanio[2*(pObj->nFanins+i) + 1]; } + +static inline Rtm_Init_t Rtm_InitNot( Rtm_Init_t Val ) { if ( Val == RTM_VAL_ZERO ) return (Rtm_Init_t)RTM_VAL_ONE; if ( Val == RTM_VAL_ONE ) return (Rtm_Init_t)RTM_VAL_ZERO; assert( 0 ); return (Rtm_Init_t)-1; } +static inline Rtm_Init_t Rtm_InitNotCond( Rtm_Init_t Val, int c ) { return c ? Rtm_InitNot(Val) : Val; } +static inline Rtm_Init_t Rtm_InitAnd(Rtm_Init_t ValA, Rtm_Init_t ValB ) { if ( ValA == RTM_VAL_ONE && ValB == RTM_VAL_ONE ) return (Rtm_Init_t)RTM_VAL_ONE; if ( ValA == RTM_VAL_ZERO || ValB == RTM_VAL_ZERO ) return (Rtm_Init_t)RTM_VAL_ZERO; assert( 0 ); return (Rtm_Init_t)-1; } + +static inline int Rtm_InitWordsNum( int nLats ) { return (nLats >> 4) + ((nLats & 15) > 0); } +static inline int Rtm_InitGetTwo( unsigned * p, int i ) { return (p[i>>4] >> ((i & 15)<<1)) & 3; } +static inline void Rtm_InitSetTwo( unsigned * p, int i, int val ) { p[i>>4] |= (val << ((i & 15)<<1)); } +static inline void Rtm_InitXorTwo( unsigned * p, int i, int val ) { p[i>>4] ^= (val << ((i & 15)<<1)); } + +static inline Rtm_Init_t Rtm_ObjGetFirst1( Rtm_Edg_t * pEdge ) { return (Rtm_Init_t)(pEdge->LData & 3); } +static inline Rtm_Init_t Rtm_ObjGetLast1( Rtm_Edg_t * pEdge ) { return (Rtm_Init_t)((pEdge->LData >> ((pEdge->nLats-1)<<1)) & 3); } +static inline Rtm_Init_t Rtm_ObjGetOne1( Rtm_Edg_t * pEdge, int i ) { assert( i < (int)pEdge->nLats ); return (Rtm_Init_t)((pEdge->LData >> (i << 1)) & 3); } +static inline Rtm_Init_t Rtm_ObjRemFirst1( Rtm_Edg_t * pEdge ) { int Val = pEdge->LData & 3; pEdge->LData >>= 2; assert(pEdge->nLats > 0); pEdge->nLats--; return (Rtm_Init_t)Val; } +static inline Rtm_Init_t Rtm_ObjRemLast1( Rtm_Edg_t * pEdge ) { int Val = (pEdge->LData >> ((pEdge->nLats-1)<<1)) & 3; pEdge->LData ^= Val << ((pEdge->nLats-1)<<1); assert(pEdge->nLats > 0); pEdge->nLats--; return (Rtm_Init_t)Val; } +static inline void Rtm_ObjAddFirst1( Rtm_Edg_t * pEdge, Rtm_Init_t Val ) { assert( Val > 0 ); pEdge->LData = (pEdge->LData << 2) | Val; pEdge->nLats++; } +static inline void Rtm_ObjAddLast1( Rtm_Edg_t * pEdge, Rtm_Init_t Val ) { assert( Val > 0 ); pEdge->LData |= Val << (pEdge->nLats<<1); pEdge->nLats++; } + +static inline Rtm_Init_t Rtm_ObjGetFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { return (Rtm_Init_t)Rtm_InitGetTwo( p->pExtra + pEdge->LData, 0 ); } +static inline Rtm_Init_t Rtm_ObjGetLast2( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { return (Rtm_Init_t)Rtm_InitGetTwo( p->pExtra + pEdge->LData, pEdge->nLats - 1 ); } +static inline Rtm_Init_t Rtm_ObjGetOne2( Rtm_Man_t * p, Rtm_Edg_t * pEdge, int i ) { return (Rtm_Init_t)Rtm_InitGetTwo( p->pExtra + pEdge->LData, i ); } +static Rtm_Init_t Rtm_ObjRemFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge ); +static inline Rtm_Init_t Rtm_ObjRemLast2( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { Rtm_Init_t Val = Rtm_ObjGetLast2( p, pEdge ); Rtm_InitXorTwo( p->pExtra + pEdge->LData, pEdge->nLats - 1, Val ); pEdge->nLats--; return (Rtm_Init_t)Val; } +static void Rtm_ObjAddFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val ); +static inline void Rtm_ObjAddLast2( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val ) { Rtm_InitSetTwo( p->pExtra + pEdge->LData, pEdge->nLats, Val ); pEdge->nLats++; } + +static void Rtm_ObjTransferToSmall( Rtm_Man_t * p, Rtm_Edg_t * pEdge ); +static void Rtm_ObjTransferToBig( Rtm_Man_t * p, Rtm_Edg_t * pEdge ); +static void Rtm_ObjTransferToBigger( Rtm_Man_t * p, Rtm_Edg_t * pEdge ); + +static inline Rtm_Init_t Rtm_ObjGetFirst( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { return pEdge->nLats > 10? Rtm_ObjGetFirst2(p, pEdge) : Rtm_ObjGetFirst1(pEdge); } +static inline Rtm_Init_t Rtm_ObjGetLast( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { return pEdge->nLats > 10? Rtm_ObjGetLast2(p, pEdge) : Rtm_ObjGetLast1(pEdge); } +static inline Rtm_Init_t Rtm_ObjGetOne( Rtm_Man_t * p, Rtm_Edg_t * pEdge, int i ) { return pEdge->nLats > 10? Rtm_ObjGetOne2(p, pEdge, i) : Rtm_ObjGetOne1(pEdge, i); } +static Rtm_Init_t Rtm_ObjRemFirst( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { Rtm_Init_t Res = pEdge->nLats > 10 ? Rtm_ObjRemFirst2(p, pEdge) : Rtm_ObjRemFirst1(pEdge); if ( pEdge->nLats == 10 ) Rtm_ObjTransferToSmall(p, pEdge); return Res; } +static Rtm_Init_t Rtm_ObjRemLast( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) { Rtm_Init_t Res = pEdge->nLats > 10 ? Rtm_ObjRemLast2(p, pEdge) : Rtm_ObjRemLast1(pEdge); if ( pEdge->nLats == 10 ) Rtm_ObjTransferToSmall(p, pEdge); return Res; } +static void Rtm_ObjAddFirst( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val ) { if ( pEdge->nLats == 10 ) Rtm_ObjTransferToBig(p, pEdge); else if ( (pEdge->nLats & 15) == 15 ) Rtm_ObjTransferToBigger(p, pEdge); if ( pEdge->nLats >= 10 ) Rtm_ObjAddFirst2(p, pEdge, Val); else Rtm_ObjAddFirst1(pEdge, Val); } +static void Rtm_ObjAddLast( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val ) { if ( pEdge->nLats == 10 ) Rtm_ObjTransferToBig(p, pEdge); else if ( (pEdge->nLats & 15) == 15 ) Rtm_ObjTransferToBigger(p, pEdge); if ( pEdge->nLats >= 10 ) Rtm_ObjAddLast2(p, pEdge, Val); else Rtm_ObjAddLast1(pEdge, Val); } + + +// iterator over the primary inputs +#define Rtm_ManForEachPi( p, pObj, i ) \ + Vec_PtrForEachEntry( Rtm_Obj_t *, p->vPis, pObj, i ) +// iterator over the primary outputs +#define Rtm_ManForEachPo( p, pObj, i ) \ + Vec_PtrForEachEntry( Rtm_Obj_t *, p->vPos, pObj, i ) +// iterator over all objects, including those currently not used +#define Rtm_ManForEachObj( p, pObj, i ) \ + Vec_PtrForEachEntry( Rtm_Obj_t *, p->vObjs, pObj, i ) +// iterate through the fanins +#define Rtm_ObjForEachFanin( pObj, pFanin, i ) \ + for ( i = 0; i < (int)(pObj)->nFanins && ((pFanin = Rtm_ObjFanin(pObj, i)), 1); i++ ) +// iterate through the fanouts +#define Rtm_ObjForEachFanout( pObj, pFanout, i ) \ + for ( i = 0; i < (int)(pObj)->nFanouts && ((pFanout = Rtm_ObjFanout(pObj, i)), 1); i++ ) +// iterate through the fanin edges +#define Rtm_ObjForEachFaninEdge( pObj, pEdge, i ) \ + for ( i = 0; i < (int)(pObj)->nFanins && ((pEdge = Rtm_ObjEdge(pObj, i)), 1); i++ ) +// iterate through the fanout edges +#define Rtm_ObjForEachFanoutEdge( pObj, pEdge, i ) \ + for ( i = 0; i < (int)(pObj)->nFanouts && ((pEdge = Rtm_ObjFanoutEdge(pObj, i)), 1); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Transfers from big to small storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rtm_ObjTransferToSmall( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) +{ + assert( pEdge->nLats == 10 ); + pEdge->LData = p->pExtra[pEdge->LData]; +} + +/**Function************************************************************* + + Synopsis [Transfers from small to big storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rtm_ObjTransferToBig( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) +{ + assert( pEdge->nLats == 10 ); + if ( p->nExtraCur + 1 > p->nExtraAlloc ) + { + int nExtraAllocNew = Abc_MaxInt( 2 * p->nExtraAlloc, 1024 ); + p->pExtra = ABC_REALLOC( unsigned, p->pExtra, nExtraAllocNew ); + p->nExtraAlloc = nExtraAllocNew; + } + p->pExtra[p->nExtraCur] = pEdge->LData; + pEdge->LData = p->nExtraCur++; +} + +/**Function************************************************************* + + Synopsis [Transfers to bigger storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rtm_ObjTransferToBigger( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) +{ + int nWords; + assert( (pEdge->nLats & 15) == 15 ); + nWords = (pEdge->nLats + 1) >> 4; + if ( p->nExtraCur + nWords + 1 > p->nExtraAlloc ) + { + int nExtraAllocNew = Abc_MaxInt( 2 * p->nExtraAlloc, 1024 ); + p->pExtra = ABC_REALLOC( unsigned, p->pExtra, nExtraAllocNew ); + p->nExtraAlloc = nExtraAllocNew; + } + memcpy( p->pExtra + p->nExtraCur, p->pExtra + pEdge->LData, sizeof(unsigned) * nWords ); + p->pExtra[p->nExtraCur + nWords] = 0; + pEdge->LData = p->nExtraCur; + p->nExtraCur += nWords + 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Rtm_Init_t Rtm_ObjRemFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) +{ + Rtm_Init_t Val = (Rtm_Init_t)0, Temp; + unsigned * pB = p->pExtra + pEdge->LData, * pE = pB + Rtm_InitWordsNum( pEdge->nLats-- ) - 1; + while ( pE >= pB ) + { + Temp = (Rtm_Init_t)(*pE & 3); + *pE = (*pE >> 2) | (Val << 30); + Val = Temp; + pE--; + } + assert( Val != 0 ); + return Val; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rtm_ObjAddFirst2( Rtm_Man_t * p, Rtm_Edg_t * pEdge, Rtm_Init_t Val ) +{ + unsigned * pB = p->pExtra + pEdge->LData, * pE = pB + Rtm_InitWordsNum( ++pEdge->nLats ); + Rtm_Init_t Temp; + assert( Val != 0 ); + while ( pB < pE ) + { + Temp = (Rtm_Init_t)(*pB >> 30); + *pB = (*pB << 2) | Val; + Val = Temp; + pB++; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rtm_PrintEdge( Rtm_Man_t * p, Rtm_Edg_t * pEdge ) +{ +// unsigned LData = pEdge->LData; + printf( "%d : ", (int)pEdge->nLats ); +/* + if ( pEdge->nLats > 10 ) + Extra_PrintBinary( stdout, p->pExtra + pEdge->LData, 2*(pEdge->nLats+1) ); + else + Extra_PrintBinary( stdout, &LData, 2*(pEdge->nLats+1) ); +*/ + printf( "\n" ); +} + + +/**Function************************************************************* + + Synopsis [Allocates the retiming manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Rtm_Man_t * Rtm_ManAlloc( Aig_Man_t * p ) +{ + Rtm_Man_t * pRtm; + // start the manager + pRtm = ABC_ALLOC( Rtm_Man_t, 1 ); + memset( pRtm, 0, sizeof(Rtm_Man_t) ); + // perform initializations + pRtm->vObjs = Vec_PtrAlloc( Aig_ManObjNum(p) ); + pRtm->vPis = Vec_PtrAlloc( Aig_ManCiNum(p) ); + pRtm->vPos = Vec_PtrAlloc( Aig_ManCoNum(p) ); + pRtm->pMem = Aig_MmFlexStart(); + return pRtm; +} + +/**Function************************************************************* + + Synopsis [Allocates the retiming manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rtm_ManFree( Rtm_Man_t * p ) +{ + Vec_PtrFree( p->vObjs ); + Vec_PtrFree( p->vPis ); + Vec_PtrFree( p->vPos ); + Aig_MmFlexStop( p->pMem, 0 ); + ABC_FREE( p->pExtra ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Counts the maximum number of latches on an edge.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rtm_ManLatchMax( Rtm_Man_t * p ) +{ + Rtm_Obj_t * pObj; + Rtm_Edg_t * pEdge; + int nLatchMax = 0, i, k;//, c, Val; + Rtm_ManForEachObj( p, pObj, i ) + Rtm_ObjForEachFaninEdge( pObj, pEdge, k ) + { +/* + for ( c = 0; c < (int)pEdge->nLats; c++ ) + { + Val = Rtm_ObjGetOne( p, pEdge, c ); + assert( Val == 1 || Val == 2 ); + } +*/ + nLatchMax = Abc_MaxInt( nLatchMax, (int)pEdge->nLats ); + } + return nLatchMax; +} + +/**Function************************************************************* + + Synopsis [Allocates the retiming object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Rtm_Obj_t * Rtm_ObjAlloc( Rtm_Man_t * pRtm, int nFanins, int nFanouts ) +{ + Rtm_Obj_t * pObj; + int Size = sizeof(Rtm_Obj_t) + sizeof(Rtm_Obj_t *) * (nFanins + nFanouts) * 2; + pObj = (Rtm_Obj_t *)Aig_MmFlexEntryFetch( pRtm->pMem, Size ); + memset( pObj, 0, sizeof(Rtm_Obj_t) ); + pObj->Type = (int)(nFanins == 1 && nFanouts == 0); // mark PO + pObj->Num = nFanins; // temporary + pObj->Temp = nFanouts; + pObj->Id = Vec_PtrSize(pRtm->vObjs); + Vec_PtrPush( pRtm->vObjs, pObj ); + return pObj; +} + +/**Function************************************************************* + + Synopsis [Allocates the retiming object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rtm_ObjAddFanin( Rtm_Obj_t * pObj, Rtm_Obj_t * pFanin, int fCompl ) +{ + pObj->pFanio[ 2*pObj->nFanins ] = pFanin; + pObj->pFanio[ 2*pObj->nFanins + 1 ] = NULL; + pFanin->pFanio[ 2*(pFanin->Num + pFanin->nFanouts) ] = pObj; + pFanin->pFanio[ 2*(pFanin->Num + pFanin->nFanouts) + 1 ] = pObj->pFanio + 2*pObj->nFanins + 1; + if ( pObj->nFanins == 0 ) + pObj->fCompl0 = fCompl; + else if ( pObj->nFanins == 1 ) + pObj->fCompl1 = fCompl; + else + assert( 0 ); + pObj->nFanins++; + pFanin->nFanouts++; + assert( pObj->nFanins <= pObj->Num ); + assert( pFanin->nFanouts <= pFanin->Temp ); +} + +/**Function************************************************************* + + Synopsis [Check the possibility of forward retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rtm_ObjCheckRetimeFwd( Rtm_Obj_t * pObj ) +{ + Rtm_Edg_t * pEdge; + int i; + Rtm_ObjForEachFaninEdge( pObj, pEdge, i ) + if ( pEdge->nLats == 0 ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Check the possibility of forward retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rtm_ObjCheckRetimeBwd( Rtm_Obj_t * pObj ) +{ + Rtm_Edg_t * pEdge; + int i; + Rtm_ObjForEachFanoutEdge( pObj, pEdge, i ) + if ( pEdge->nLats == 0 ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Check the possibility of forward retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rtm_ObjGetDegreeFwd( Rtm_Obj_t * pObj ) +{ + Rtm_Obj_t * pFanin; + int i, Degree = 0; + Rtm_ObjForEachFanin( pObj, pFanin, i ) + Degree = Abc_MaxInt( Degree, (int)pFanin->Num ); + return Degree + 1; +} + +/**Function************************************************************* + + Synopsis [Check the possibility of forward retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rtm_ObjGetDegreeBwd( Rtm_Obj_t * pObj ) +{ + Rtm_Obj_t * pFanout; + int i, Degree = 0; + Rtm_ObjForEachFanout( pObj, pFanout, i ) + Degree = Abc_MaxInt( Degree, (int)pFanout->Num ); + return Degree + 1; +} + +/**Function************************************************************* + + Synopsis [Performs forward retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rtm_ObjRetimeFwd( Rtm_Man_t * pRtm, Rtm_Obj_t * pObj ) +{ + Rtm_Init_t ValTotal, ValCur; + Rtm_Edg_t * pEdge; + int i; + assert( Rtm_ObjCheckRetimeFwd(pObj) ); + // extract values and compute the result + ValTotal = RTM_VAL_ONE; + Rtm_ObjForEachFaninEdge( pObj, pEdge, i ) + { + ValCur = Rtm_ObjRemFirst( pRtm, pEdge ); + ValCur = Rtm_InitNotCond( ValCur, i? pObj->fCompl1 : pObj->fCompl0 ); + ValTotal = Rtm_InitAnd( ValTotal, ValCur ); + } + // insert the result in the fanout values + Rtm_ObjForEachFanoutEdge( pObj, pEdge, i ) + Rtm_ObjAddLast( pRtm, pEdge, ValTotal ); +} + +/**Function************************************************************* + + Synopsis [Performs forward retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rtm_ObjRetimeBwd( Rtm_Man_t * pRtm, Rtm_Obj_t * pObj ) +{ + Rtm_Edg_t * pEdge; + int i; + assert( Rtm_ObjCheckRetimeBwd(pObj) ); + // extract values and compute the result + Rtm_ObjForEachFanoutEdge( pObj, pEdge, i ) + Rtm_ObjRemLast( pRtm, pEdge ); + // insert the result in the fanout values + Rtm_ObjForEachFaninEdge( pObj, pEdge, i ) + Rtm_ObjAddFirst( pRtm, pEdge, RTM_VAL_VOID ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rtm_ObjMarkAutoFwd_rec( Rtm_Obj_t * pObj ) +{ + Rtm_Obj_t * pFanout; + int i; + if ( pObj->fAuto ) + return; + pObj->fAuto = 1; + Rtm_ObjForEachFanout( pObj, pFanout, i ) + Rtm_ObjMarkAutoFwd_rec( pFanout ); +} + +/**Function************************************************************* + + Synopsis [Marks the nodes unreachable from the PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rtm_ManMarkAutoFwd( Rtm_Man_t * pRtm ) +{ + Rtm_Obj_t * pObjRtm; + int i, Counter = 0; + // mark nodes reachable from the PIs + pObjRtm = (Rtm_Obj_t *)Vec_PtrEntry( pRtm->vObjs, 0 ); + Rtm_ObjMarkAutoFwd_rec( pObjRtm ); + Rtm_ManForEachPi( pRtm, pObjRtm, i ) + Rtm_ObjMarkAutoFwd_rec( pObjRtm ); + // count the number of autonomous nodes + Rtm_ManForEachObj( pRtm, pObjRtm, i ) + { + pObjRtm->fAuto = !pObjRtm->fAuto; + Counter += pObjRtm->fAuto; + } + // mark the fanins of the autonomous nodes + return Counter; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Rtm_ObjMarkAutoBwd_rec( Rtm_Obj_t * pObj ) +{ + Rtm_Obj_t * pFanin; + int i; + if ( pObj->fAuto ) + return; + pObj->fAuto = 1; + Rtm_ObjForEachFanin( pObj, pFanin, i ) + Rtm_ObjMarkAutoBwd_rec( pFanin ); +} + +/**Function************************************************************* + + Synopsis [Marks the nodes unreachable from the POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Rtm_ManMarkAutoBwd( Rtm_Man_t * pRtm ) +{ + Rtm_Obj_t * pObjRtm; + int i, Counter = 0; + // mark nodes reachable from the PIs + pObjRtm = (Rtm_Obj_t *)Vec_PtrEntry( pRtm->vObjs, 0 ); + pObjRtm->fAuto = 1; + Rtm_ManForEachPi( pRtm, pObjRtm, i ) + pObjRtm->fAuto = 1; + Rtm_ManForEachPo( pRtm, pObjRtm, i ) + Rtm_ObjMarkAutoBwd_rec( pObjRtm ); + // count the number of autonomous nodes + Rtm_ManForEachObj( pRtm, pObjRtm, i ) + { + pObjRtm->fAuto = !pObjRtm->fAuto; + Counter += pObjRtm->fAuto; + } + // mark the fanins of the autonomous nodes + return Counter; +} + +/**Function************************************************************* + + Synopsis [Derive retiming manager from the given AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Rtm_Man_t * Rtm_ManFromAig( Aig_Man_t * p ) +{ + Rtm_Man_t * pRtm; + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int i; + assert( Aig_ManRegNum(p) > 0 ); + assert( Aig_ManBufNum(p) == 0 ); + // allocate the manager + pRtm = Rtm_ManAlloc( p ); + // allocate objects + pObj = Aig_ManConst1(p); + pObj->pData = Rtm_ObjAlloc( pRtm, 0, pObj->nRefs ); + Aig_ManForEachPiSeq( p, pObj, i ) + { + pObj->pData = Rtm_ObjAlloc( pRtm, 0, pObj->nRefs ); + Vec_PtrPush( pRtm->vPis, pObj->pData ); + } + Aig_ManForEachPoSeq( p, pObj, i ) + { + pObj->pData = Rtm_ObjAlloc( pRtm, 1, 0 ); + Vec_PtrPush( pRtm->vPos, pObj->pData ); + } + Aig_ManForEachLoSeq( p, pObj, i ) + pObj->pData = Rtm_ObjAlloc( pRtm, 1, pObj->nRefs ); + Aig_ManForEachLiSeq( p, pObj, i ) + pObj->pData = Rtm_ObjAlloc( pRtm, 1, 1 ); + Aig_ManForEachNode( p, pObj, i ) + pObj->pData = Rtm_ObjAlloc( pRtm, 2, pObj->nRefs ); + // connect objects + Aig_ManForEachPoSeq( p, pObj, i ) + Rtm_ObjAddFanin( (Rtm_Obj_t *)pObj->pData, (Rtm_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + Aig_ManForEachLiSeq( p, pObj, i ) + Rtm_ObjAddFanin( (Rtm_Obj_t *)pObj->pData, (Rtm_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + Rtm_ObjAddFanin( (Rtm_Obj_t *)pObjLo->pData, (Rtm_Obj_t *)pObjLi->pData, 0 ); + Aig_ManForEachNode( p, pObj, i ) + { + Rtm_ObjAddFanin( (Rtm_Obj_t *)pObj->pData, (Rtm_Obj_t *)Aig_ObjFanin0(pObj)->pData, Aig_ObjFaninC0(pObj) ); + Rtm_ObjAddFanin( (Rtm_Obj_t *)pObj->pData, (Rtm_Obj_t *)Aig_ObjFanin1(pObj)->pData, Aig_ObjFaninC1(pObj) ); + } + return pRtm; +} + +/**Function************************************************************* + + Synopsis [Derive AIG manager after retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Rtm_ManToAig_rec( Aig_Man_t * pNew, Rtm_Man_t * pRtm, Rtm_Obj_t * pObjRtm, int * pLatches ) +{ + Rtm_Edg_t * pEdge; + Aig_Obj_t * pRes, * pFanin; + int k, Val; + if ( pObjRtm->pCopy ) + return (Aig_Obj_t *)pObjRtm->pCopy; + // get the inputs + pRes = Aig_ManConst1( pNew ); + Rtm_ObjForEachFaninEdge( pObjRtm, pEdge, k ) + { + if ( pEdge->nLats == 0 ) + pFanin = Rtm_ManToAig_rec( pNew, pRtm, Rtm_ObjFanin(pObjRtm, k), pLatches ); + else + { + Val = Rtm_ObjGetFirst( pRtm, pEdge ); + pFanin = Aig_ManCi( pNew, pLatches[2*pObjRtm->Id + k] + pEdge->nLats - 1 ); + pFanin = Aig_NotCond( pFanin, Val == RTM_VAL_ONE ); + } + pFanin = Aig_NotCond( pFanin, k ? pObjRtm->fCompl1 : pObjRtm->fCompl0 ); + pRes = Aig_And( pNew, pRes, pFanin ); + } + return (Aig_Obj_t *)(pObjRtm->pCopy = pRes); +} + +/**Function************************************************************* + + Synopsis [Derive AIG manager after retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Rtm_ManToAig( Rtm_Man_t * pRtm ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObjNew; + Rtm_Obj_t * pObjRtm; + Rtm_Edg_t * pEdge; + int i, k, m, Val, nLatches, * pLatches; + // count latches and mark the first latch on each edge + pLatches = ABC_ALLOC( int, 2 * Vec_PtrSize(pRtm->vObjs) ); + nLatches = 0; + Rtm_ManForEachObj( pRtm, pObjRtm, i ) + Rtm_ObjForEachFaninEdge( pObjRtm, pEdge, k ) + { + pLatches[2*pObjRtm->Id + k] = Vec_PtrSize(pRtm->vPis) + nLatches; + nLatches += pEdge->nLats; + } + // create the new manager + pNew = Aig_ManStart( Vec_PtrSize(pRtm->vObjs) + nLatches ); + // create PIs/POs and latches + pObjRtm = (Rtm_Obj_t *)Vec_PtrEntry( pRtm->vObjs, 0 ); + pObjRtm->pCopy = Aig_ManConst1(pNew); + Rtm_ManForEachPi( pRtm, pObjRtm, i ) + pObjRtm->pCopy = Aig_ObjCreateCi(pNew); + for ( i = 0; i < nLatches; i++ ) + Aig_ObjCreateCi(pNew); + // create internal nodes + Rtm_ManForEachObj( pRtm, pObjRtm, i ) + Rtm_ManToAig_rec( pNew, pRtm, pObjRtm, pLatches ); + // create POs + Rtm_ManForEachPo( pRtm, pObjRtm, i ) + Aig_ObjCreateCo( pNew, (Aig_Obj_t *)pObjRtm->pCopy ); + // connect latches + Rtm_ManForEachObj( pRtm, pObjRtm, i ) + Rtm_ObjForEachFaninEdge( pObjRtm, pEdge, k ) + { + if ( pEdge->nLats == 0 ) + continue; + pObjNew = (Aig_Obj_t *)Rtm_ObjFanin( pObjRtm, k )->pCopy; + for ( m = 0; m < (int)pEdge->nLats; m++ ) + { + Val = Rtm_ObjGetOne( pRtm, pEdge, pEdge->nLats - 1 - m ); + assert( Val == RTM_VAL_ZERO || Val == RTM_VAL_ONE || Val == RTM_VAL_VOID ); + pObjNew = Aig_NotCond( pObjNew, Val == RTM_VAL_ONE ); + Aig_ObjCreateCo( pNew, pObjNew ); + pObjNew = Aig_ManCi( pNew, pLatches[2*pObjRtm->Id + k] + m ); + pObjNew = Aig_NotCond( pObjNew, Val == RTM_VAL_ONE ); + } +// assert( Aig_Regular(pObjNew)->nRefs > 0 ); + } + ABC_FREE( pLatches ); + Aig_ManSetRegNum( pNew, nLatches ); + // remove useless nodes + Aig_ManCleanup( pNew ); + if ( !Aig_ManCheck( pNew ) ) + printf( "Rtm_ManToAig: The network check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Performs forward retiming with the given limit on depth.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Rtm_ManRetime( Aig_Man_t * p, int fForward, int nStepsMax, int fVerbose ) +{ + Vec_Ptr_t * vQueue; + Aig_Man_t * pNew; + Rtm_Man_t * pRtm; + Rtm_Obj_t * pObj, * pNext; + Aig_Obj_t * pObjAig; + int i, k, nAutos, Degree, DegreeMax = 0; + abctime clk; + + // create the retiming manager +clk = Abc_Clock(); + pRtm = Rtm_ManFromAig( p ); + // set registers + Aig_ManForEachLoSeq( p, pObjAig, i ) + Rtm_ObjAddFirst( pRtm, Rtm_ObjEdge((Rtm_Obj_t *)pObjAig->pData, 0), fForward? RTM_VAL_ZERO : RTM_VAL_VOID ); + // detect and mark the autonomous components + if ( fForward ) + nAutos = Rtm_ManMarkAutoFwd( pRtm ); + else + nAutos = Rtm_ManMarkAutoBwd( pRtm ); + if ( fVerbose ) + { + printf( "Detected %d autonomous objects. ", nAutos ); + ABC_PRT( "Time", Abc_Clock() - clk ); + } + + // set the current retiming number + Rtm_ManForEachObj( pRtm, pObj, i ) + { + assert( pObj->nFanins == pObj->Num ); + assert( pObj->nFanouts == pObj->Temp ); + pObj->Num = 0; + } + +clk = Abc_Clock(); + // put the LOs on the queue + vQueue = Vec_PtrAlloc( 1000 ); + if ( fForward ) + { + Aig_ManForEachLoSeq( p, pObjAig, i ) + { + pObj = (Rtm_Obj_t *)pObjAig->pData; + if ( pObj->fAuto ) + continue; + pObj->fMark = 1; + Vec_PtrPush( vQueue, pObj ); + } + } + else + { + Aig_ManForEachLiSeq( p, pObjAig, i ) + { + pObj = (Rtm_Obj_t *)pObjAig->pData; + if ( pObj->fAuto ) + continue; + pObj->fMark = 1; + Vec_PtrPush( vQueue, pObj ); + } + } + // perform retiming + DegreeMax = 0; + Vec_PtrForEachEntry( Rtm_Obj_t *, vQueue, pObj, i ) + { + pObj->fMark = 0; + // retime the node + if ( fForward ) + { + Rtm_ObjRetimeFwd( pRtm, pObj ); + // check if its fanouts should be retimed + Rtm_ObjForEachFanout( pObj, pNext, k ) + { + if ( pNext->fMark ) // skip aleady scheduled + continue; + if ( pNext->Type ) // skip POs + continue; + if ( !Rtm_ObjCheckRetimeFwd( pNext ) ) // skip non-retimable + continue; + Degree = Rtm_ObjGetDegreeFwd( pNext ); + DegreeMax = Abc_MaxInt( DegreeMax, Degree ); + if ( Degree > nStepsMax ) // skip nodes with high degree + continue; + pNext->fMark = 1; + pNext->Num = Degree; + Vec_PtrPush( vQueue, pNext ); + } + } + else + { + Rtm_ObjRetimeBwd( pRtm, pObj ); + // check if its fanouts should be retimed + Rtm_ObjForEachFanin( pObj, pNext, k ) + { + if ( pNext->fMark ) // skip aleady scheduled + continue; + if ( pNext->nFanins == 0 ) // skip PIs + continue; + if ( !Rtm_ObjCheckRetimeBwd( pNext ) ) // skip non-retimable + continue; + Degree = Rtm_ObjGetDegreeBwd( pNext ); + DegreeMax = Abc_MaxInt( DegreeMax, Degree ); + if ( Degree > nStepsMax ) // skip nodes with high degree + continue; + pNext->fMark = 1; + pNext->Num = Degree; + Vec_PtrPush( vQueue, pNext ); + } + } + } + + if ( fVerbose ) + { + printf( "Performed %d %s latch moves of max depth %d and max latch count %d.\n", + Vec_PtrSize(vQueue), fForward? "fwd":"bwd", DegreeMax, Rtm_ManLatchMax(pRtm) ); + printf( "Memory usage = %d. ", pRtm->nExtraCur ); + ABC_PRT( "Time", Abc_Clock() - clk ); + } + Vec_PtrFree( vQueue ); + + // get the new manager + pNew = Rtm_ManToAig( pRtm ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Rtm_ManFree( pRtm ); + // group the registers +clk = Abc_Clock(); + pNew = Aig_ManReduceLaches( pNew, fVerbose ); + if ( fVerbose ) + { + ABC_PRT( "Register sharing time", Abc_Clock() - clk ); + } + return pNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigRetF.c b/yosys/abc/src/aig/aig/aigRetF.c new file mode 100644 index 00000000000..05fba120eb0 --- /dev/null +++ b/yosys/abc/src/aig/aig/aigRetF.c @@ -0,0 +1,214 @@ +/**CFile**************************************************************** + + FileName [aigRetF.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Retiming frontier.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigRetF.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Mark the nodes reachable from the PIs in the reverse order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManRetimeMark_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( pObj->fMarkB ) + return 1; + if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) ) + return 0; + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return pObj->fMarkB; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Aig_ManRetimeMark_rec( p, Aig_ObjFanin0(pObj) ) ) + return pObj->fMarkB = 1; + if ( Aig_ObjIsNode(pObj) && Aig_ManRetimeMark_rec( p, Aig_ObjFanin1(pObj) ) ) + return pObj->fMarkB = 1; + assert( pObj->fMarkB == 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Mark the nodes reachable from the true PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManRetimeMark( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int fChange, i; + // mark the PIs + Aig_ManForEachObj( p, pObj, i ) + assert( pObj->fMarkB == 0 ); + Aig_ManForEachPiSeq( p, pObj, i ) + pObj->fMarkB = 1; + // map registers into each other + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + { + assert( pObjLo->pNext == NULL ); + assert( pObjLi->pNext == NULL ); + pObjLo->pNext = pObjLi; + pObjLi->pNext = pObjLo; + } + // iterativively mark the logic reachable from PIs + fChange = 1; + while ( fChange ) + { + fChange = 0; + Aig_ManIncrementTravId( p ); + Aig_ManForEachCo( p, pObj, i ) + { + if ( pObj->fMarkB ) + continue; + if ( Aig_ManRetimeMark_rec( p, pObj ) ) + { + if ( pObj->pNext ) + pObj->pNext->fMarkB = 1; + fChange = 1; + } + } + } + // clean register mapping + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + pObjLo->pNext = pObjLi->pNext = NULL; +} + + +/**Function************************************************************* + + Synopsis [Performs forward retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManRetimeFrontier( Aig_Man_t * p, int nStepsMax ) +{ + Aig_Obj_t * pObj, * pObjNew, * pObjLo, * pObjLo0, * pObjLo1, * pObjLi, * pObjLi0, * pObjLi1;//, * pObjLi0_, * pObjLi1_, * pObjLi0__, * pObjLi1__; + int i, Counter, fCompl, fChange; + assert( Aig_ManRegNum(p) > 0 ); + // remove structural hashing table + Aig_TableClear( p ); + // mark the retimable nodes + Aig_ManRetimeMark( p ); + // mark the register outputs + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + { + pObjLo->fMarkA = 1; + pObjLo->pNext = pObjLi; + pObjLi->pNext = pObjLo; + } + // go through the nodes and find retimable ones + Counter = 0; + fChange = 1; + while ( fChange ) + { + fChange = 0; + Aig_ManForEachNode( p, pObj, i ) + { + if ( !pObj->fMarkB ) + continue; + if ( Aig_ObjIsBuf(pObj) ) + continue; + // get the real inputs of the node (skipping the buffers) + pObjLo0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); + pObjLo1 = Aig_ObjReal_rec( Aig_ObjChild1(pObj) ); + if ( !Aig_Regular(pObjLo0)->fMarkA || !Aig_Regular(pObjLo1)->fMarkA ) + continue; + // remember complemented attribute + fCompl = Aig_IsComplement(pObjLo0) & Aig_IsComplement(pObjLo1); + // get the register inputs +// pObjLi0_ = Aig_Regular(pObjLo0)->pNext; +// pObjLi1_ = Aig_Regular(pObjLo1)->pNext; +// pObjLi0__ = Aig_ObjChild0(Aig_Regular(pObjLo0)->pNext); +// pObjLi1__ = Aig_ObjChild0(Aig_Regular(pObjLo1)->pNext); + pObjLi0 = Aig_NotCond( Aig_ObjChild0(Aig_Regular(pObjLo0)->pNext), Aig_IsComplement(pObjLo0) ); + pObjLi1 = Aig_NotCond( Aig_ObjChild0(Aig_Regular(pObjLo1)->pNext), Aig_IsComplement(pObjLo1) ); + // create new node + pObjNew = Aig_And( p, pObjLi0, pObjLi1 ); + pObjNew->fMarkB = 1; + // create new register + pObjLo = Aig_ObjCreateCi(p); + pObjLo->fMarkA = 1; + pObjLi = Aig_ObjCreateCo( p, Aig_NotCond(pObjNew, fCompl) ); + p->nRegs++; + pObjLo->pNext = pObjLi; + pObjLi->pNext = pObjLo; + // add the buffer + Aig_ObjDisconnect( p, pObj ); + pObj->Type = AIG_OBJ_BUF; + p->nObjs[AIG_OBJ_AND]--; + p->nObjs[AIG_OBJ_BUF]++; + Aig_ObjConnect( p, pObj, Aig_NotCond(pObjLo, fCompl), NULL ); + // create HAIG if defined + // mark the change + fChange = 1; + // check the limit + if ( ++Counter >= nStepsMax ) + { + fChange = 0; + break; + } + } + } + // clean the markings + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + { + pObjLo->fMarkA = 0; + pObjLo->pNext = pObjLi->pNext = NULL; + } + Aig_ManForEachObj( p, pObj, i ) + pObj->fMarkB = 0; + // remove useless registers + Aig_ManSeqCleanup( p ); + // rehash the nodes + return Aig_ManDupOrdered( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigScl.c b/yosys/abc/src/aig/aig/aigScl.c new file mode 100644 index 00000000000..731fa333c65 --- /dev/null +++ b/yosys/abc/src/aig/aig/aigScl.c @@ -0,0 +1,708 @@ +/**CFile**************************************************************** + + FileName [aigScl.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Sequential cleanup.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigScl.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Remaps the manager.] + + Description [Map in the array specifies for each CI node the node that + should be used after remapping.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManRemap( Aig_Man_t * p, Vec_Ptr_t * vMap ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pObjMapped; + int i, nTruePis; + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nAsserts = p->nAsserts; + pNew->nConstrs = p->nConstrs; + pNew->nBarBufs = p->nBarBufs; + assert( p->vFlopNums == NULL || Vec_IntSize(p->vFlopNums) == p->nRegs ); + if ( p->vFlopNums ) + pNew->vFlopNums = Vec_IntDup( p->vFlopNums ); + if ( p->vFlopReprs ) + pNew->vFlopReprs = Vec_IntDup( p->vFlopReprs ); + // create the PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachCi( p, pObj, i ) + pObj->pData = Aig_ObjCreateCi(pNew); + // implement the mapping + nTruePis = Aig_ManCiNum(p)-Aig_ManRegNum(p); + if ( p->vFlopReprs ) + { + Aig_ManForEachLoSeq( p, pObj, i ) + pObj->pNext = (Aig_Obj_t *)(long)Vec_IntEntry( p->vFlopNums, i-nTruePis ); + } + Aig_ManForEachCi( p, pObj, i ) + { + pObjMapped = (Aig_Obj_t *)Vec_PtrEntry( vMap, i ); + pObj->pData = Aig_NotCond( (Aig_Obj_t *)Aig_Regular(pObjMapped)->pData, Aig_IsComplement(pObjMapped) ); + if ( pNew->vFlopReprs && i >= nTruePis && pObj != pObjMapped ) + { + Vec_IntPush( pNew->vFlopReprs, Aig_ObjCioId(pObj) ); + if ( Aig_ObjIsConst1( Aig_Regular(pObjMapped) ) ) + Vec_IntPush( pNew->vFlopReprs, -1 ); + else + { + assert( !Aig_IsComplement(pObjMapped) ); + assert( Aig_ObjIsCi(pObjMapped) ); + assert( Aig_ObjCioId(pObj) != Aig_ObjCioId(pObjMapped) ); + Vec_IntPush( pNew->vFlopReprs, Aig_ObjCioId(pObjMapped) ); + } + } + } + if ( p->vFlopReprs ) + { + Aig_ManForEachLoSeq( p, pObj, i ) + pObj->pNext = NULL; + } + // duplicate internal nodes + Aig_ManForEachObj( p, pObj, i ) + if ( Aig_ObjIsBuf(pObj) ) + pObj->pData = Aig_ObjChild0Copy(pObj); + else if ( Aig_ObjIsNode(pObj) ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // add the POs + Aig_ManForEachCo( p, pObj, i ) + Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + assert( Aig_ManNodeNum(p) >= Aig_ManNodeNum(pNew) ); + Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); + // check the resulting network + if ( !Aig_ManCheck(pNew) ) + printf( "Aig_ManRemap(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Returns the number of dangling nodes removed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManSeqCleanup_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + // collect latch input corresponding to unmarked PI (latch output) + if ( Aig_ObjIsCi(pObj) ) + { + Vec_PtrPush( vNodes, pObj->pNext ); + return; + } + if ( Aig_ObjIsCo(pObj) || Aig_ObjIsBuf(pObj) ) + { + Aig_ManSeqCleanup_rec( p, Aig_ObjFanin0(pObj), vNodes ); + return; + } + assert( Aig_ObjIsNode(pObj) ); + Aig_ManSeqCleanup_rec( p, Aig_ObjFanin0(pObj), vNodes ); + Aig_ManSeqCleanup_rec( p, Aig_ObjFanin1(pObj), vNodes ); +} + +/**Function************************************************************* + + Synopsis [Returns the number of dangling nodes removed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManSeqCleanup( Aig_Man_t * p ) +{ + Vec_Ptr_t * vNodes, * vCis, * vCos; + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int i, nTruePis, nTruePos; +// assert( Aig_ManBufNum(p) == 0 ); + + // mark the PIs + Aig_ManIncrementTravId( p ); + Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); + Aig_ManForEachPiSeq( p, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + + // prepare to collect nodes reachable from POs + vNodes = Vec_PtrAlloc( 100 ); + Aig_ManForEachPoSeq( p, pObj, i ) + Vec_PtrPush( vNodes, pObj ); + + // remember latch inputs in latch outputs + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + pObjLo->pNext = pObjLi; + // mark the nodes reachable from these nodes + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + Aig_ManSeqCleanup_rec( p, pObj, vNodes ); + assert( Vec_PtrSize(vNodes) <= Aig_ManCoNum(p) ); + // clean latch output pointers + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + pObjLo->pNext = NULL; + + // if some latches are removed, update PIs/POs + if ( Vec_PtrSize(vNodes) < Aig_ManCoNum(p) ) + { + if ( p->vFlopNums ) + { + int nTruePos = Aig_ManCoNum(p)-Aig_ManRegNum(p); + int iNum, k = 0; + Aig_ManForEachCo( p, pObj, i ) + if ( i >= nTruePos && Aig_ObjIsTravIdCurrent(p, pObj) ) + { + iNum = Vec_IntEntry( p->vFlopNums, i - nTruePos ); + Vec_IntWriteEntry( p->vFlopNums, k++, iNum ); + } + assert( k == Vec_PtrSize(vNodes) - nTruePos ); + Vec_IntShrink( p->vFlopNums, k ); + } + // collect new CIs/COs + vCis = Vec_PtrAlloc( Aig_ManCiNum(p) ); + Aig_ManForEachCi( p, pObj, i ) + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + Vec_PtrPush( vCis, pObj ); + else + { + Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); +// Aig_ManRecycleMemory( p, pObj ); + } + vCos = Vec_PtrAlloc( Aig_ManCoNum(p) ); + Aig_ManForEachCo( p, pObj, i ) + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + Vec_PtrPush( vCos, pObj ); + else + { + Aig_ObjDisconnect( p, pObj ); + Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); +// Aig_ManRecycleMemory( p, pObj ); + } + // remember the number of true PIs/POs + nTruePis = Aig_ManCiNum(p) - Aig_ManRegNum(p); + nTruePos = Aig_ManCoNum(p) - Aig_ManRegNum(p); + // set the new number of registers + p->nRegs -= Aig_ManCoNum(p) - Vec_PtrSize(vNodes); + // create new PIs/POs + assert( Vec_PtrSize(vCis) == nTruePis + p->nRegs ); + assert( Vec_PtrSize(vCos) == nTruePos + p->nRegs ); + Vec_PtrFree( p->vCis ); p->vCis = vCis; + Vec_PtrFree( p->vCos ); p->vCos = vCos; + p->nObjs[AIG_OBJ_CI] = Vec_PtrSize( p->vCis ); + p->nObjs[AIG_OBJ_CO] = Vec_PtrSize( p->vCos ); + + } + Vec_PtrFree( vNodes ); + p->nTruePis = Aig_ManCiNum(p) - Aig_ManRegNum(p); + p->nTruePos = Aig_ManCoNum(p) - Aig_ManRegNum(p); + Aig_ManSetCioIds( p ); + // remove dangling nodes + return Aig_ManCleanup( p ); +} + +/**Function************************************************************* + + Synopsis [Returns the number of dangling nodes removed.] + + Description [This cleanup procedure is different in that + it removes logic but does not remove the dangling latches.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManSeqCleanupBasic( Aig_Man_t * p ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int i; +// assert( Aig_ManBufNum(p) == 0 ); + + // mark the PIs + Aig_ManIncrementTravId( p ); + Aig_ObjSetTravIdCurrent( p, Aig_ManConst1(p) ); + Aig_ManForEachPiSeq( p, pObj, i ) + Aig_ObjSetTravIdCurrent( p, pObj ); + + // prepare to collect nodes reachable from POs + vNodes = Vec_PtrAlloc( 100 ); + Aig_ManForEachPoSeq( p, pObj, i ) + Vec_PtrPush( vNodes, pObj ); + + // remember latch inputs in latch outputs + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + pObjLo->pNext = pObjLi; + // mark the nodes reachable from these nodes + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + Aig_ManSeqCleanup_rec( p, pObj, vNodes ); + assert( Vec_PtrSize(vNodes) <= Aig_ManCoNum(p) ); + // clean latch output pointers + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + pObjLo->pNext = NULL; + + // if some latches are removed, update PIs/POs + if ( Vec_PtrSize(vNodes) < Aig_ManCoNum(p) ) + { + // add constant drivers to the dangling latches + Aig_ManForEachCo( p, pObj, i ) + if ( !Aig_ObjIsTravIdCurrent(p, pObj) ) + Aig_ObjPatchFanin0( p, pObj, Aig_ManConst0(p) ); + } + Vec_PtrFree( vNodes ); + // remove dangling nodes + return Aig_ManCleanup( p ); +} + +/**Function************************************************************* + + Synopsis [Returns the number of dangling nodes removed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManCountMergeRegs( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj, * pFanin; + int i, Counter = 0, Const0 = 0, Const1 = 0; + Aig_ManIncrementTravId( p ); + Aig_ManForEachLiSeq( p, pObj, i ) + { + pFanin = Aig_ObjFanin0(pObj); + if ( Aig_ObjIsConst1(pFanin) ) + { + if ( Aig_ObjFaninC0(pObj) ) + Const0++; + else + Const1++; + } + if ( Aig_ObjIsTravIdCurrent(p, pFanin) ) + continue; + Aig_ObjSetTravIdCurrent(p, pFanin); + Counter++; + } + printf( "Regs = %d. Fanins = %d. Const0 = %d. Const1 = %d.\n", + Aig_ManRegNum(p), Counter, Const0, Const1 ); + return 0; +} + + +/**Function************************************************************* + + Synopsis [Checks how many latches can be reduced.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManReduceLachesCount( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj, * pFanin; + int i, Counter = 0, Diffs = 0; + assert( Aig_ManRegNum(p) > 0 ); + Aig_ManForEachObj( p, pObj, i ) + assert( !pObj->fMarkA && !pObj->fMarkB ); + Aig_ManForEachLiSeq( p, pObj, i ) + { + pFanin = Aig_ObjFanin0(pObj); + if ( Aig_ObjFaninC0(pObj) ) + { + if ( pFanin->fMarkB ) + Counter++; + else + pFanin->fMarkB = 1; + } + else + { + if ( pFanin->fMarkA ) + Counter++; + else + pFanin->fMarkA = 1; + } + } + // count fanins that have both attributes + Aig_ManForEachLiSeq( p, pObj, i ) + { + pFanin = Aig_ObjFanin0(pObj); + Diffs += pFanin->fMarkA && pFanin->fMarkB; + pFanin->fMarkA = pFanin->fMarkB = 0; + } +// printf( "Diffs = %d.\n", Diffs ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Reduces the latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManReduceLachesOnce( Aig_Man_t * p ) +{ + Vec_Ptr_t * vMap; + Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pFanin; + int * pMapping, i; + // start mapping by adding the true PIs + vMap = Vec_PtrAlloc( Aig_ManCiNum(p) ); + Aig_ManForEachPiSeq( p, pObj, i ) + Vec_PtrPush( vMap, pObj ); + // create mapping of fanin nodes into the corresponding latch outputs + pMapping = ABC_FALLOC( int, 2 * Aig_ManObjNumMax(p) ); + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + { + pFanin = Aig_ObjFanin0(pObjLi); + if ( Aig_ObjFaninC0(pObjLi) ) + { + if ( pFanin->fMarkB ) + { + Vec_PtrPush( vMap, Aig_ManLo(p, pMapping[2*pFanin->Id + 1]) ); + } + else + { + pFanin->fMarkB = 1; + pMapping[2*pFanin->Id + 1] = i; + Vec_PtrPush( vMap, pObjLo ); + } + } + else + { + if ( pFanin->fMarkA ) + { + Vec_PtrPush( vMap, Aig_ManLo(p, pMapping[2*pFanin->Id]) ); + } + else + { + pFanin->fMarkA = 1; + pMapping[2*pFanin->Id] = i; + Vec_PtrPush( vMap, pObjLo ); + } + } + } + ABC_FREE( pMapping ); + Aig_ManForEachLiSeq( p, pObj, i ) + { + pFanin = Aig_ObjFanin0(pObj); + pFanin->fMarkA = pFanin->fMarkB = 0; + } + return vMap; +} + +/**Function************************************************************* + + Synopsis [Reduces the latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManReduceLaches( Aig_Man_t * p, int fVerbose ) +{ + Aig_Man_t * pTemp; + Vec_Ptr_t * vMap; + int nSaved, nCur; + if ( fVerbose ) + printf( "Performing combinational register sweep:\n" ); + for ( nSaved = 0; (nCur = Aig_ManReduceLachesCount(p)); nSaved += nCur ) + { +// printf( "Reducible = %d\n", nCur ); + vMap = Aig_ManReduceLachesOnce( p ); + p = Aig_ManRemap( pTemp = p, vMap ); + Vec_PtrFree( vMap ); + Aig_ManSeqCleanup( p ); + if ( fVerbose ) + Aig_ManReportImprovement( pTemp, p ); + Aig_ManStop( pTemp ); + if ( p->nRegs == 0 ) + break; + } + return p; +} + +/**Function************************************************************* + + Synopsis [Computes strongly connected components of registers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManComputeSccs( Aig_Man_t * p ) +{ + Vec_Ptr_t * vSupports, * vMatrix, * vMatrix2; + Vec_Int_t * vSupp, * vSupp2, * vComp; + char * pVarsTot; + int i, k, m, iOut, iIn, nComps; + if ( Aig_ManRegNum(p) == 0 ) + { + printf( "The network is combinational.\n" ); + return; + } + // get structural supports for each output + vSupports = Aig_ManSupports( p ); + // transforms the supports into the latch dependency matrix + vMatrix = Vec_PtrStart( Aig_ManRegNum(p) ); + Vec_PtrForEachEntry( Vec_Int_t *, vSupports, vSupp, i ) + { + // skip true POs + iOut = Vec_IntPop( vSupp ); + iOut -= Aig_ManCoNum(p) - Aig_ManRegNum(p); + if ( iOut < 0 ) + continue; + // remove PIs + m = 0; + Vec_IntForEachEntry( vSupp, iIn, k ) + { + iIn -= Aig_ManCiNum(p) - Aig_ManRegNum(p); + if ( iIn < 0 ) + continue; + assert( iIn < Aig_ManRegNum(p) ); + Vec_IntWriteEntry( vSupp, m++, iIn ); + } + Vec_IntShrink( vSupp, m ); + // store support in the matrix + assert( iOut < Aig_ManRegNum(p) ); + Vec_PtrWriteEntry( vMatrix, iOut, vSupp ); + } + // create the reverse matrix + vMatrix2 = Vec_PtrAlloc( Aig_ManRegNum(p) ); + for ( i = 0; i < Aig_ManRegNum(p); i++ ) + Vec_PtrPush( vMatrix2, Vec_IntAlloc(8) ); + Vec_PtrForEachEntry( Vec_Int_t *, vMatrix, vSupp, i ) + { + Vec_IntForEachEntry( vSupp, iIn, k ) + { + vSupp2 = (Vec_Int_t *)Vec_PtrEntry( vMatrix2, iIn ); + Vec_IntPush( vSupp2, i ); + } + } + + // detect strongly connected components + vComp = Vec_IntAlloc( Aig_ManRegNum(p) ); + pVarsTot = ABC_ALLOC( char, Aig_ManRegNum(p) ); + memset( pVarsTot, 0, Aig_ManRegNum(p) * sizeof(char) ); + for ( nComps = 0; ; nComps++ ) + { + Vec_IntClear( vComp ); + // get the first support + for ( iOut = 0; iOut < Aig_ManRegNum(p); iOut++ ) + if ( pVarsTot[iOut] == 0 ) + break; + if ( iOut == Aig_ManRegNum(p) ) + break; + pVarsTot[iOut] = 1; + Vec_IntPush( vComp, iOut ); + Vec_IntForEachEntry( vComp, iOut, i ) + { + vSupp = (Vec_Int_t *)Vec_PtrEntry( vMatrix, iOut ); + Vec_IntForEachEntry( vSupp, iIn, k ) + { + if ( pVarsTot[iIn] ) + continue; + pVarsTot[iIn] = 1; + Vec_IntPush( vComp, iIn ); + } + vSupp2 = (Vec_Int_t *)Vec_PtrEntry( vMatrix2, iOut ); + Vec_IntForEachEntry( vSupp2, iIn, k ) + { + if ( pVarsTot[iIn] ) + continue; + pVarsTot[iIn] = 1; + Vec_IntPush( vComp, iIn ); + } + } + if ( Vec_IntSize(vComp) == Aig_ManRegNum(p) ) + { + printf( "There is only one SCC of registers in this network.\n" ); + break; + } + printf( "SCC #%d contains %5d registers.\n", nComps+1, Vec_IntSize(vComp) ); + } + ABC_FREE( pVarsTot ); + Vec_IntFree( vComp ); + Vec_PtrFree( vMatrix ); + Vec_VecFree( (Vec_Vec_t *)vMatrix2 ); + Vec_VecFree( (Vec_Vec_t *)vSupports ); +} + +/**Function************************************************************* + + Synopsis [Performs partitioned register sweep.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManSclPart( Aig_Man_t * pAig, int fLatchConst, int fLatchEqual, int fVerbose ) +{ + Vec_Ptr_t * vResult; + Vec_Int_t * vPart; + int i, nCountPis, nCountRegs; + int * pMapBack; + Aig_Man_t * pTemp, * pNew; + int nClasses; + + if ( pAig->vClockDoms ) + { + vResult = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Vec_Int_t *, (Vec_Ptr_t *)pAig->vClockDoms, vPart, i ) + Vec_PtrPush( vResult, Vec_IntDup(vPart) ); + } + else + vResult = Aig_ManRegPartitionSimple( pAig, 0, 0 ); + + Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) ); + Vec_PtrForEachEntry( Vec_Int_t *, vResult, vPart, i ) + { + pTemp = Aig_ManRegCreatePart( pAig, vPart, &nCountPis, &nCountRegs, &pMapBack ); + Aig_ManSetRegNum( pTemp, pTemp->nRegs ); + if (nCountPis>0) + { + pNew = Aig_ManScl( pTemp, fLatchConst, fLatchEqual, 0, -1, -1, fVerbose, 0 ); + nClasses = Aig_TransferMappedClasses( pAig, pTemp, pMapBack ); + if ( fVerbose ) + printf( "%3d : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d. It = %3d. Cl = %5d\n", + i, Vec_IntSize(vPart), Aig_ManCiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Aig_ManNodeNum(pTemp), 0, nClasses ); + Aig_ManStop( pNew ); + } + Aig_ManStop( pTemp ); + ABC_FREE( pMapBack ); + } + pNew = Aig_ManDupRepr( pAig, 0 ); + Aig_ManSeqCleanup( pNew ); + Vec_VecFree( (Vec_Vec_t*)vResult ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Gives the current ABC network to AIG manager for processing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManScl( Aig_Man_t * pAig, int fLatchConst, int fLatchEqual, int fUseMvSweep, int nFramesSymb, int nFramesSatur, int fVerbose, int fVeryVerbose ) +{ + extern void Saig_ManReportUselessRegisters( Aig_Man_t * pAig ); + extern int Saig_ManReportComplements( Aig_Man_t * p ); + + Aig_Man_t * pAigInit, * pAigNew; + Aig_Obj_t * pFlop1, * pFlop2; + int i, Entry1, Entry2, nTruePis;//, nRegs; + + if ( pAig->vClockDoms && Vec_VecSize(pAig->vClockDoms) > 0 ) + return Aig_ManSclPart( pAig, fLatchConst, fLatchEqual, fVerbose); + + // store the original AIG + assert( pAig->vFlopNums == NULL ); + pAigInit = pAig; + pAig = Aig_ManDupSimple( pAig ); + // create storage for latch numbers + pAig->vFlopNums = Vec_IntStartNatural( pAig->nRegs ); + pAig->vFlopReprs = Vec_IntAlloc( 100 ); + Aig_ManSeqCleanup( pAig ); + if ( fLatchConst && pAig->nRegs ) + pAig = Aig_ManConstReduce( pAig, fUseMvSweep, nFramesSymb, nFramesSatur, fVerbose, fVeryVerbose ); + if ( fLatchEqual && pAig->nRegs ) + pAig = Aig_ManReduceLaches( pAig, fVerbose ); + // translate pairs into reprs + nTruePis = Aig_ManCiNum(pAigInit)-Aig_ManRegNum(pAigInit); + Aig_ManReprStart( pAigInit, Aig_ManObjNumMax(pAigInit) ); + Vec_IntForEachEntry( pAig->vFlopReprs, Entry1, i ) + { + Entry2 = Vec_IntEntry( pAig->vFlopReprs, ++i ); + pFlop1 = Aig_ManCi( pAigInit, nTruePis + Entry1 ); + pFlop2 = (Entry2 == -1)? Aig_ManConst1(pAigInit) : Aig_ManCi( pAigInit, nTruePis + Entry2 ); + assert( pFlop1 != pFlop2 ); + if ( pFlop1->Id > pFlop2->Id ) + pAigInit->pReprs[pFlop1->Id] = pFlop2; + else + pAigInit->pReprs[pFlop2->Id] = pFlop1; + } + Aig_ManStop( pAig ); +// Aig_ManSeqCleanup( pAigInit ); + pAigNew = Aig_ManDupRepr( pAigInit, 0 ); + Aig_ManSeqCleanup( pAigNew ); + +// Saig_ManReportUselessRegisters( pAigNew ); + if ( Aig_ManRegNum(pAigNew) == 0 ) + return pAigNew; +// nRegs = Saig_ManReportComplements( pAigNew ); +// if ( nRegs ) +// printf( "The number of complemented registers = %d.\n", nRegs ); + return pAigNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigShow.c b/yosys/abc/src/aig/aig/aigShow.c new file mode 100644 index 00000000000..7612d02b1f4 --- /dev/null +++ b/yosys/abc/src/aig/aig/aigShow.c @@ -0,0 +1,368 @@ +/**CFile**************************************************************** + + FileName [ivyShow.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Visualization of HAIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyShow.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" +#include "misc/extra/extra.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the graph structure of AIG for DOT.] + + Description [Useful for graph visualization using tools such as GraphViz: + http://www.graphviz.org/] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_WriteDotAig( Aig_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold ) +{ + FILE * pFile; + Aig_Obj_t * pNode;//, * pTemp, * pPrev; + int LevelMax, Prev, Level, i; + + if ( Aig_ManNodeNum(pMan) > 200 ) + { + fprintf( stdout, "Cannot visualize AIG with more than 200 nodes.\n" ); + return; + } + if ( (pFile = fopen( pFileName, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); + return; + } + + // mark the nodes + if ( vBold ) + Vec_PtrForEachEntry( Aig_Obj_t *, vBold, pNode, i ) + pNode->fMarkB = 1; + + // compute levels +// LevelMax = 1 + Aig_ManSetLevels( pMan, fHaig ); + LevelMax = 1 + Aig_ManLevels( pMan ); + Aig_ManForEachCo( pMan, pNode, i ) + pNode->Level = LevelMax; + + // write the DOT header + fprintf( pFile, "# %s\n", "AIG structure generated by IVY package" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "digraph AIG {\n" ); + fprintf( pFile, "size = \"7.5,10\";\n" ); +// fprintf( pFile, "ranksep = 0.5;\n" ); +// fprintf( pFile, "nodesep = 0.5;\n" ); + fprintf( pFile, "center = true;\n" ); +// fprintf( pFile, "orientation = landscape;\n" ); +// fprintf( pFile, "edge [fontsize = 10];\n" ); +// fprintf( pFile, "edge [dir = none];\n" ); + fprintf( pFile, "edge [dir = back];\n" ); + fprintf( pFile, "\n" ); + + // labels on the left of the picture + fprintf( pFile, "{\n" ); + fprintf( pFile, " node [shape = plaintext];\n" ); + fprintf( pFile, " edge [style = invis];\n" ); + fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); + fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); + // generate node names with labels + for ( Level = LevelMax; Level >= 0; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + fprintf( pFile, " [label = " ); + // label name + fprintf( pFile, "\"" ); + fprintf( pFile, "\"" ); + fprintf( pFile, "];\n" ); + } + + // genetate the sequence of visible/invisible nodes to mark levels + fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); + for ( Level = LevelMax; Level >= 0; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + // the connector + if ( Level != 0 ) + fprintf( pFile, " ->" ); + else + fprintf( pFile, ";" ); + } + fprintf( pFile, "\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate title box on top + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle1;\n" ); + fprintf( pFile, " title1 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=20,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + fprintf( pFile, "%s", "AIG structure visualized by ABC" ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "Benchmark \\\"%s\\\". ", "aig" ); +// fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate statistics box + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle2;\n" ); + fprintf( pFile, " title2 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=18,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Aig_ManNodeNum(pMan), LevelMax ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate the COs + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", LevelMax ); + // generate the CO nodes + Aig_ManForEachCo( pMan, pNode, i ) + { +/* + if ( fHaig || pNode->pEquiv == NULL ) + fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id, + (Aig_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Aig_ObjIsLatch(pNode)? "_in":"") ); + else + fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, + (Aig_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Aig_ObjIsLatch(pNode)? "_in":""), + Aig_Regular(pNode->pEquiv)->Id, Aig_IsComplement(pNode->pEquiv)? "\'":"" ); +*/ + fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); + + fprintf( pFile, ", shape = %s", "invtriangle" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate nodes of each rank + for ( Level = LevelMax - 1; Level > 0; Level-- ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", Level ); + Aig_ManForEachObj( pMan, pNode, i ) + { + if ( (int)pNode->Level != Level ) + continue; +/* + if ( fHaig || pNode->pEquiv == NULL ) + fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); + else + fprintf( pFile, " Node%d [label = \"%d(%d%s)\"", pNode->Id, pNode->Id, + Aig_Regular(pNode->pEquiv)->Id, Aig_IsComplement(pNode->pEquiv)? "\'":"" ); +*/ + fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); + + fprintf( pFile, ", shape = ellipse" ); + if ( vBold && pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate the CI nodes + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", 0 ); + // generate constant node + if ( Aig_ObjRefs(Aig_ManConst1(pMan)) > 0 ) + { + pNode = Aig_ManConst1(pMan); + // check if the costant node is present + fprintf( pFile, " Node%d [label = \"Const1\"", pNode->Id ); + fprintf( pFile, ", shape = ellipse" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + // generate the CI nodes + Aig_ManForEachCi( pMan, pNode, i ) + { +/* + if ( fHaig || pNode->pEquiv == NULL ) + fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id, + (Aig_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Aig_ObjIsLatch(pNode)? "_out":"") ); + else + fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, + (Aig_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Aig_ObjIsLatch(pNode)? "_out":""), + Aig_Regular(pNode->pEquiv)->Id, Aig_IsComplement(pNode->pEquiv)? "\'":"" ); +*/ + fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); + + fprintf( pFile, ", shape = %s", "triangle" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate invisible edges from the square down + fprintf( pFile, "title1 -> title2 [style = invis];\n" ); + Aig_ManForEachCo( pMan, pNode, i ) + fprintf( pFile, "title2 -> Node%d [style = invis];\n", pNode->Id ); + // generate invisible edges among the COs + Prev = -1; + Aig_ManForEachCo( pMan, pNode, i ) + { + if ( i > 0 ) + fprintf( pFile, "Node%d -> Node%d [style = invis];\n", Prev, pNode->Id ); + Prev = pNode->Id; + } + + // generate edges + Aig_ManForEachObj( pMan, pNode, i ) + { + if ( !Aig_ObjIsNode(pNode) && !Aig_ObjIsCo(pNode) && !Aig_ObjIsBuf(pNode) ) + continue; + // generate the edge from this node to the next + fprintf( pFile, "Node%d", pNode->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", Aig_ObjFaninId0(pNode) ); + fprintf( pFile, " [" ); + fprintf( pFile, "style = %s", Aig_ObjFaninC0(pNode)? "dotted" : "bold" ); +// if ( Aig_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL0(pNode) > 0 ) +// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,0) ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + if ( !Aig_ObjIsNode(pNode) ) + continue; + // generate the edge from this node to the next + fprintf( pFile, "Node%d", pNode->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", Aig_ObjFaninId1(pNode) ); + fprintf( pFile, " [" ); + fprintf( pFile, "style = %s", Aig_ObjFaninC1(pNode)? "dotted" : "bold" ); +// if ( Aig_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL1(pNode) > 0 ) +// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,1) ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); +/* + // generate the edges between the equivalent nodes + if ( fHaig && pNode->pEquiv && Aig_ObjRefs(pNode) > 0 ) + { + pPrev = pNode; + for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Aig_Regular(pTemp->pEquiv) ) + { + fprintf( pFile, "Node%d", pPrev->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", pTemp->Id ); + fprintf( pFile, " [style = %s]", Aig_IsComplement(pTemp->pEquiv)? "dotted" : "bold" ); + fprintf( pFile, ";\n" ); + pPrev = pTemp; + } + // connect the last node with the first + fprintf( pFile, "Node%d", pPrev->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", pNode->Id ); + fprintf( pFile, " [style = %s]", Aig_IsComplement(pPrev->pEquiv)? "dotted" : "bold" ); + fprintf( pFile, ";\n" ); + } +*/ + } + + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + fclose( pFile ); + + // unmark nodes + if ( vBold ) + Vec_PtrForEachEntry( Aig_Obj_t *, vBold, pNode, i ) + pNode->fMarkB = 0; + + Aig_ManForEachCo( pMan, pNode, i ) + pNode->Level = Aig_ObjFanin0(pNode)->Level; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManShow( Aig_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ) +{ + extern void Abc_ShowFile( char * FileNameDot, int fKeepDot ); + char FileNameDot[200]; + FILE * pFile; + // create the file name + sprintf( FileNameDot, "%s", Extra_FileNameGenericAppend(pMan->pName ? pMan->pName : (char *)"unknown", ".dot") ); + // check that the file can be opened + if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); + return; + } + fclose( pFile ); + // generate the file + Aig_WriteDotAig( pMan, FileNameDot, fHaig, vBold ); + // visualize the file + Abc_ShowFile( FileNameDot, 0 ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigSplit.c b/yosys/abc/src/aig/aig/aigSplit.c new file mode 100644 index 00000000000..9e74d1be709 --- /dev/null +++ b/yosys/abc/src/aig/aig/aigSplit.c @@ -0,0 +1,330 @@ +/**CFile**************************************************************** + + FileName [aigSplit.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Splits the property output cone into a set of cofactor properties.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigSplit.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" +#include "aig/saig/saig.h" + +#ifdef ABC_USE_CUDD +#include "bdd/extrab/extraBdd.h" +#endif + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#ifdef ABC_USE_CUDD + +/**Function************************************************************* + + Synopsis [Converts the node to MUXes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_NodeBddToMuxes_rec( DdManager * dd, DdNode * bFunc, Aig_Man_t * pNew, st__table * tBdd2Node ) +{ + Aig_Obj_t * pNode, * pNode0, * pNode1, * pNodeC; + assert( !Cudd_IsComplement(bFunc) ); + if ( st__lookup( tBdd2Node, (char *)bFunc, (char **)&pNode ) ) + return pNode; + // solve for the children nodes + pNode0 = Aig_NodeBddToMuxes_rec( dd, Cudd_Regular(cuddE(bFunc)), pNew, tBdd2Node ); + pNode0 = Aig_NotCond( pNode0, Cudd_IsComplement(cuddE(bFunc)) ); + pNode1 = Aig_NodeBddToMuxes_rec( dd, cuddT(bFunc), pNew, tBdd2Node ); + if ( ! st__lookup( tBdd2Node, (char *)Cudd_bddIthVar(dd, bFunc->index), (char **)&pNodeC ) ) + assert( 0 ); + // create the MUX node + pNode = Aig_Mux( pNew, pNodeC, pNode1, pNode0 ); + st__insert( tBdd2Node, (char *)bFunc, (char *)pNode ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Derives AIG for the BDDs of the cofactors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManConvertBddsToAigs( Aig_Man_t * p, DdManager * dd, Vec_Ptr_t * vCofs ) +{ + DdNode * bFunc; + st__table * tBdd2Node; + Aig_Man_t * pNew; + Aig_Obj_t * pObj; + int i; + Aig_ManCleanData( p ); + // generate AIG for BDD + pNew = Aig_ManStart( Aig_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachCi( p, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pNew ); + // create the table mapping BDD nodes into the ABC nodes + tBdd2Node = st__init_table( st__ptrcmp, st__ptrhash ); + // add the constant and the elementary vars + st__insert( tBdd2Node, (char *)Cudd_ReadOne(dd), (char *)Aig_ManConst1(pNew) ); + Aig_ManForEachCi( p, pObj, i ) + st__insert( tBdd2Node, (char *)Cudd_bddIthVar(dd, i), (char *)pObj->pData ); + // build primary outputs for the cofactors + Vec_PtrForEachEntry( DdNode *, vCofs, bFunc, i ) + { + if ( bFunc == Cudd_ReadLogicZero(dd) ) + continue; + pObj = Aig_NodeBddToMuxes_rec( dd, Cudd_Regular(bFunc), pNew, tBdd2Node ); + pObj = Aig_NotCond( pObj, Cudd_IsComplement(bFunc) ); + Aig_ObjCreateCo( pNew, pObj ); + } + st__free_table( tBdd2Node ); + + // duplicate the rest of the AIG + // add the POs + Aig_ManForEachCo( p, pObj, i ) + { + if ( i == 0 ) + continue; + Aig_ManDupSimpleDfs_rec( pNew, p, Aig_ObjFanin0(pObj) ); + pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + } + Aig_ManCleanup( pNew ); + Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); + // check the resulting network + if ( !Aig_ManCheck(pNew) ) + printf( "Aig_ManConvertBddsToAigs(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Returns the array of constraint candidates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Aig_ManBuildPoBdd_rec( Aig_Man_t * p, Aig_Obj_t * pObj, DdManager * dd ) +{ + DdNode * bBdd0, * bBdd1; + if ( pObj->pData != NULL ) + return (DdNode *)pObj->pData; + assert( Aig_ObjIsNode(pObj) ); + bBdd0 = Aig_ManBuildPoBdd_rec( p, Aig_ObjFanin0(pObj), dd ); + bBdd1 = Aig_ManBuildPoBdd_rec( p, Aig_ObjFanin1(pObj), dd ); + bBdd0 = Cudd_NotCond( bBdd0, Aig_ObjFaninC0(pObj) ); + bBdd1 = Cudd_NotCond( bBdd1, Aig_ObjFaninC1(pObj) ); + pObj->pData = Cudd_bddAnd( dd, bBdd0, bBdd1 ); Cudd_Ref( (DdNode *)pObj->pData ); + return (DdNode *)pObj->pData; +} + +/**Function************************************************************* + + Synopsis [Derive BDDs for the cofactors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManCofactorBdds( Aig_Man_t * p, Vec_Ptr_t * vSubset, DdManager * dd, DdNode * bFunc ) +{ + Vec_Ptr_t * vCofs; + DdNode * bCube, * bTemp, * bCof, ** pbVars; + int i; + vCofs = Vec_PtrAlloc( 100 ); + pbVars = (DdNode **)Vec_PtrArray(vSubset); + for ( i = 0; i < (1 << Vec_PtrSize(vSubset)); i++ ) + { + bCube = Extra_bddBitsToCube( dd, i, Vec_PtrSize(vSubset), pbVars, 1 ); Cudd_Ref( bCube ); + bCof = Cudd_Cofactor( dd, bFunc, bCube ); Cudd_Ref( bCof ); + bCof = Cudd_bddAnd( dd, bTemp = bCof, bCube ); Cudd_Ref( bCof ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + Vec_PtrPush( vCofs, bCof ); + } + return vCofs; +} + +/**Function************************************************************* + + Synopsis [Construct BDDs for the primary output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdManager * Aig_ManBuildPoBdd( Aig_Man_t * p, DdNode ** pbFunc ) +{ + DdManager * dd; + Aig_Obj_t * pObj; + int i; + assert( Saig_ManPoNum(p) == 1 ); + Aig_ManCleanData( p ); + dd = Cudd_Init( Aig_ManCiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + pObj = Aig_ManConst1(p); + pObj->pData = Cudd_ReadOne(dd); Cudd_Ref( (DdNode *)pObj->pData ); + Aig_ManForEachCi( p, pObj, i ) + { + pObj->pData = Cudd_bddIthVar(dd, i); Cudd_Ref( (DdNode *)pObj->pData ); + } + pObj = Aig_ManCo( p, 0 ); + *pbFunc = Aig_ManBuildPoBdd_rec( p, Aig_ObjFanin0(pObj), dd ); Cudd_Ref( *pbFunc ); + *pbFunc = Cudd_NotCond( *pbFunc, Aig_ObjFaninC0(pObj) ); + Aig_ManForEachObj( p, pObj, i ) + { + if ( pObj->pData ) + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + } + Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); + return dd; +} + +/**Function************************************************************* + + Synopsis [Randomly selects a random subset of inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManVecRandSubset( Vec_Ptr_t * vVec, int nVars ) +{ + Vec_Ptr_t * vRes; + void * pEntry; + unsigned Rand; + vRes = Vec_PtrDup(vVec); + while ( Vec_PtrSize(vRes) > nVars ) + { + Rand = Aig_ManRandom( 0 ); + pEntry = Vec_PtrEntry( vRes, Rand % Vec_PtrSize(vRes) ); + Vec_PtrRemove( vRes, pEntry ); + } + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManSplit( Aig_Man_t * p, int nVars, int fVerbose ) +{ + Aig_Man_t * pRes; + Aig_Obj_t * pNode; + DdNode * bFunc; + DdManager * dd; + Vec_Ptr_t * vSupp, * vSubs, * vCofs; + int i; + abctime clk = Abc_Clock(); + if ( Saig_ManPoNum(p) != 1 ) + { + printf( "Currently works only for one primary output.\n" ); + return NULL; + } + if ( nVars < 1 ) + { + printf( "The number of cofactoring variables should be a positive number.\n" ); + return NULL; + } + if ( nVars > 16 ) + { + printf( "The number of cofactoring variables should be less than 17.\n" ); + return NULL; + } + vSupp = Aig_Support( p, Aig_ObjFanin0(Aig_ManCo(p,0)) ); + if ( Vec_PtrSize(vSupp) == 0 ) + { + printf( "Property output function is a constant.\n" ); + Vec_PtrFree( vSupp ); + return NULL; + } + dd = Aig_ManBuildPoBdd( p, &bFunc ); // bFunc is referenced + if ( fVerbose ) + printf( "Support =%5d. BDD size =%6d. ", Vec_PtrSize(vSupp), Cudd_DagSize(bFunc) ); + vSubs = Aig_ManVecRandSubset( vSupp, nVars ); + // replace nodes by their BDD variables + Vec_PtrForEachEntry( Aig_Obj_t *, vSubs, pNode, i ) + Vec_PtrWriteEntry( vSubs, i, pNode->pData ); + // derive cofactors and functions + vCofs = Aig_ManCofactorBdds( p, vSubs, dd, bFunc ); + pRes = Aig_ManConvertBddsToAigs( p, dd, vCofs ); + Vec_PtrFree( vSupp ); + Vec_PtrFree( vSubs ); + if ( fVerbose ) + printf( "Created %d cofactors (out of %d). ", Saig_ManPoNum(pRes), Vec_PtrSize(vCofs) ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + // dereference + Cudd_RecursiveDeref( dd, bFunc ); + Vec_PtrForEachEntry( DdNode *, vCofs, bFunc, i ) + Cudd_RecursiveDeref( dd, bFunc ); + Vec_PtrFree( vCofs ); + Extra_StopManager( dd ); + return pRes; +} + +#else + +Aig_Man_t * Aig_ManSplit( Aig_Man_t * p, int nVars, int fVerbose ) +{ + return NULL; +} + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigTable.c b/yosys/abc/src/aig/aig/aigTable.c new file mode 100644 index 00000000000..2c7adee7137 --- /dev/null +++ b/yosys/abc/src/aig/aig/aigTable.c @@ -0,0 +1,277 @@ +/**CFile**************************************************************** + + FileName [aigTable.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Structural hashing table.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigTable.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// hashing the node +static unsigned long Aig_Hash( Aig_Obj_t * pObj, int TableSize ) +{ + unsigned long Key = Aig_ObjIsExor(pObj) * 1699; + Key ^= Aig_ObjFanin0(pObj)->Id * 7937; + Key ^= Aig_ObjFanin1(pObj)->Id * 2971; + Key ^= Aig_ObjFaninC0(pObj) * 911; + Key ^= Aig_ObjFaninC1(pObj) * 353; + return Key % TableSize; +} + +// returns the place where this node is stored (or should be stored) +static Aig_Obj_t ** Aig_TableFind( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t ** ppEntry; + assert( Aig_ObjChild0(pObj) && Aig_ObjChild1(pObj) ); + assert( Aig_ObjFanin0(pObj)->Id < Aig_ObjFanin1(pObj)->Id ); + for ( ppEntry = p->pTable + Aig_Hash(pObj, p->nTableSize); *ppEntry; ppEntry = &(*ppEntry)->pNext ) + if ( *ppEntry == pObj ) + return ppEntry; + assert( *ppEntry == NULL ); + return ppEntry; +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Resizes the table.] + + Description [Typically this procedure should not be called.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_TableResize( Aig_Man_t * p ) +{ + Aig_Obj_t * pEntry, * pNext; + Aig_Obj_t ** pTableOld, ** ppPlace; + int nTableSizeOld, Counter, i; + abctime clk; + assert( p->pTable != NULL ); +clk = Abc_Clock(); + // save the old table + pTableOld = p->pTable; + nTableSizeOld = p->nTableSize; + // get the new table + p->nTableSize = Abc_PrimeCudd( 2 * Aig_ManNodeNum(p) ); + p->pTable = ABC_ALLOC( Aig_Obj_t *, p->nTableSize ); + memset( p->pTable, 0, sizeof(Aig_Obj_t *) * p->nTableSize ); + // rehash the entries from the old table + Counter = 0; + for ( i = 0; i < nTableSizeOld; i++ ) + for ( pEntry = pTableOld[i], pNext = pEntry? pEntry->pNext : NULL; + pEntry; pEntry = pNext, pNext = pEntry? pEntry->pNext : NULL ) + { + // get the place where this entry goes in the table + ppPlace = Aig_TableFind( p, pEntry ); + assert( *ppPlace == NULL ); // should not be there + // add the entry to the list + *ppPlace = pEntry; + pEntry->pNext = NULL; + Counter++; + } + assert( Counter == Aig_ManNodeNum(p) ); +// printf( "Increasing the structural table size from %6d to %6d. ", nTableSizeOld, p->nTableSize ); +// ABC_PRT( "Time", Abc_Clock() - clk ); + // replace the table and the parameters + ABC_FREE( pTableOld ); +} + +/**Function************************************************************* + + Synopsis [Checks if node with the given attributes is in the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_TableLookup( Aig_Man_t * p, Aig_Obj_t * pGhost ) +{ + Aig_Obj_t * pEntry; + assert( !Aig_IsComplement(pGhost) ); + assert( Aig_ObjIsNode(pGhost) ); + assert( Aig_ObjChild0(pGhost) && Aig_ObjChild1(pGhost) ); + assert( Aig_ObjFanin0(pGhost)->Id < Aig_ObjFanin1(pGhost)->Id ); + if ( p->pTable == NULL || !Aig_ObjRefs(Aig_ObjFanin0(pGhost)) || !Aig_ObjRefs(Aig_ObjFanin1(pGhost)) ) + return NULL; + for ( pEntry = p->pTable[Aig_Hash(pGhost, p->nTableSize)]; pEntry; pEntry = pEntry->pNext ) + { + if ( Aig_ObjChild0(pEntry) == Aig_ObjChild0(pGhost) && + Aig_ObjChild1(pEntry) == Aig_ObjChild1(pGhost) && + Aig_ObjType(pEntry) == Aig_ObjType(pGhost) ) + return pEntry; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Checks if node with the given attributes is in the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_TableLookupTwo( Aig_Man_t * p, Aig_Obj_t * pFanin0, Aig_Obj_t * pFanin1 ) +{ + Aig_Obj_t * pGhost; + // consider simple cases + if ( pFanin0 == pFanin1 ) + return pFanin0; + if ( pFanin0 == Aig_Not(pFanin1) ) + return Aig_ManConst0(p); + if ( Aig_Regular(pFanin0) == Aig_ManConst1(p) ) + return pFanin0 == Aig_ManConst1(p) ? pFanin1 : Aig_ManConst0(p); + if ( Aig_Regular(pFanin1) == Aig_ManConst1(p) ) + return pFanin1 == Aig_ManConst1(p) ? pFanin0 : Aig_ManConst0(p); + pGhost = Aig_ObjCreateGhost( p, pFanin0, pFanin1, AIG_OBJ_AND ); + return Aig_TableLookup( p, pGhost ); +} + +/**Function************************************************************* + + Synopsis [Adds the new node to the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_TableInsert( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t ** ppPlace; + assert( !Aig_IsComplement(pObj) ); + assert( Aig_TableLookup(p, pObj) == NULL ); + if ( (pObj->Id & 0xFF) == 0 && 2 * p->nTableSize < Aig_ManNodeNum(p) ) + Aig_TableResize( p ); + ppPlace = Aig_TableFind( p, pObj ); + assert( *ppPlace == NULL ); + *ppPlace = pObj; +} + +/**Function************************************************************* + + Synopsis [Deletes the node from the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_TableDelete( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t ** ppPlace; + assert( !Aig_IsComplement(pObj) ); + ppPlace = Aig_TableFind( p, pObj ); + assert( *ppPlace == pObj ); // node should be in the table + // remove the node + *ppPlace = pObj->pNext; + pObj->pNext = NULL; +} + +/**Function************************************************************* + + Synopsis [Count the number of nodes in the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_TableCountEntries( Aig_Man_t * p ) +{ + Aig_Obj_t * pEntry; + int i, Counter = 0; + for ( i = 0; i < p->nTableSize; i++ ) + for ( pEntry = p->pTable[i]; pEntry; pEntry = pEntry->pNext ) + Counter++; + return Counter; +} + +/**Function******************************************************************** + + Synopsis [Profiles the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Aig_TableProfile( Aig_Man_t * p ) +{ + Aig_Obj_t * pEntry; + int i, Counter; + printf( "Table size = %d. Entries = %d.\n", p->nTableSize, Aig_ManNodeNum(p) ); + for ( i = 0; i < p->nTableSize; i++ ) + { + Counter = 0; + for ( pEntry = p->pTable[i]; pEntry; pEntry = pEntry->pNext ) + Counter++; + if ( Counter ) + printf( "%d ", Counter ); + } +} + +/**Function******************************************************************** + + Synopsis [Profiles the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Aig_TableClear( Aig_Man_t * p ) +{ + ABC_FREE( p->pTable ); + p->nTableSize = 0; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigTest.c b/yosys/abc/src/aig/aig/aigTest.c new file mode 100644 index 00000000000..42c81c3fab3 --- /dev/null +++ b/yosys/abc/src/aig/aig/aigTest.c @@ -0,0 +1,39 @@ + + +#include "aig.h" + +ABC_NAMESPACE_IMPL_START + + +void Aig_ProcedureTest() +{ + Aig_Man_t * p; + Aig_Obj_t * pA, * pB, * pC; + Aig_Obj_t * pFunc; + Aig_Obj_t * pFunc2; + + p = Aig_ManStart( 1000 ); + + pA = Aig_IthVar( p, 0 ); + pB = Aig_IthVar( p, 1 ); + pC = Aig_IthVar( p, 2 ); + + pFunc = Aig_Mux( p, pA, pB, pC ); + pFunc2 = Aig_And( p, pA, pB ); + + Aig_ObjCreatePo( p, pFunc ); + Aig_ObjCreatePo( p, pFunc2 ); + + Aig_ManSetRegNum( p, 1 ); + + Aig_ManCleanup( p ); + + if ( !Aig_ManCheck( p ) ) + { + printf( "Check has failed\n" ); + } + + Aig_ManDumpBlif( p, "aig_test_file.blif", NULL, NULL ); + Aig_ManStop( p ); +}ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigTiming.c b/yosys/abc/src/aig/aig/aigTiming.c new file mode 100644 index 00000000000..e855e012bc6 --- /dev/null +++ b/yosys/abc/src/aig/aig/aigTiming.c @@ -0,0 +1,356 @@ +/**CFile**************************************************************** + + FileName [aigTiming.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Incremental updating of direct/reverse AIG levels.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigTiming.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the reverse level of the node.] + + Description [The reverse level is the level of the node in reverse + topological order, starting from the COs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_ObjReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + assert( p->vLevelR ); + Vec_IntFillExtra( p->vLevelR, pObj->Id + 1, 0 ); + return Vec_IntEntry(p->vLevelR, pObj->Id); +} + +/**Function************************************************************* + + Synopsis [Sets the reverse level of the node.] + + Description [The reverse level is the level of the node in reverse + topological order, starting from the COs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Aig_ObjSetReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObj, int LevelR ) +{ + assert( p->vLevelR ); + Vec_IntFillExtra( p->vLevelR, pObj->Id + 1, 0 ); + Vec_IntWriteEntry( p->vLevelR, pObj->Id, LevelR ); +} + +/**Function************************************************************* + + Synopsis [Resets reverse level of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjClearReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_ObjSetReverseLevel( p, pObj, 0 ); +} + +/**Function************************************************************* + + Synopsis [Returns required level of the node.] + + Description [Converts the reverse levels of the node into its required + level as follows: ReqLevel(Node) = MaxLevels(Ntk) + 1 - LevelR(Node).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjRequiredLevel( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + assert( p->vLevelR ); + return p->nLevelMax + 1 - Aig_ObjReverseLevel(p, pObj); +} + +/**Function************************************************************* + + Synopsis [Computes the reverse level of the node using its fanout levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjReverseLevelNew( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pFanout; + int i, iFanout = -1, LevelCur, Level = 0; + Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) + { + LevelCur = Aig_ObjReverseLevel( p, pFanout ); + Level = Abc_MaxInt( Level, LevelCur ); + } + return Level + 1; +} + +/**Function************************************************************* + + Synopsis [Prepares for the computation of required levels.] + + Description [This procedure should be called before the required times + are used. It starts internal data structures, which records the level + from the COs of the network nodes in reverse topologogical order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManStartReverseLevels( Aig_Man_t * p, int nMaxLevelIncrease ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + assert( p->pFanData != NULL ); + assert( p->vLevelR == NULL ); + // remember the maximum number of direct levels + p->nLevelMax = Aig_ManLevels(p) + nMaxLevelIncrease; + // start the reverse levels + p->vLevelR = Vec_IntAlloc( 0 ); + Vec_IntFill( p->vLevelR, Aig_ManObjNumMax(p), 0 ); + // compute levels in reverse topological order + vNodes = Aig_ManDfsReverse( p ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + assert( pObj->fMarkA == 0 ); + Aig_ObjSetReverseLevel( p, pObj, Aig_ObjReverseLevelNew(p, pObj) ); + } + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Cleans the data structures used to compute required levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManStopReverseLevels( Aig_Man_t * p ) +{ + assert( p->vLevelR != NULL ); + Vec_IntFree( p->vLevelR ); + p->vLevelR = NULL; + p->nLevelMax = 0; + +} + +/**Function************************************************************* + + Synopsis [Incrementally updates level of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManUpdateLevel( Aig_Man_t * p, Aig_Obj_t * pObjNew ) +{ + Aig_Obj_t * pFanout, * pTemp; + int iFanout = -1, LevelOld, Lev, k, m; + assert( p->pFanData != NULL ); + assert( Aig_ObjIsNode(pObjNew) ); + // allocate level if needed + if ( p->vLevels == NULL ) + p->vLevels = Vec_VecAlloc( Aig_ManLevels(p) + 8 ); + // check if level has changed + LevelOld = Aig_ObjLevel(pObjNew); + if ( LevelOld == Aig_ObjLevelNew(pObjNew) ) + return; + // start the data structure for level update + // we cannot fail to visit a node when using this structure because the + // nodes are stored by their _old_ levels, which are assumed to be correct + Vec_VecClear( p->vLevels ); + Vec_VecPush( p->vLevels, LevelOld, pObjNew ); + pObjNew->fMarkA = 1; + // recursively update level + Vec_VecForEachEntryStart( Aig_Obj_t *, p->vLevels, pTemp, Lev, k, LevelOld ) + { + pTemp->fMarkA = 0; + assert( Aig_ObjLevel(pTemp) == Lev ); + pTemp->Level = Aig_ObjLevelNew(pTemp); + // if the level did not change, no need to check the fanout levels + if ( Aig_ObjLevel(pTemp) == Lev ) + continue; + // schedule fanout for level update + Aig_ObjForEachFanout( p, pTemp, pFanout, iFanout, m ) + { + if ( Aig_ObjIsNode(pFanout) && !pFanout->fMarkA ) + { + assert( Aig_ObjLevel(pFanout) >= Lev ); + Vec_VecPush( p->vLevels, Aig_ObjLevel(pFanout), pFanout ); + pFanout->fMarkA = 1; + } + } + } +} + +/**Function************************************************************* + + Synopsis [Incrementally updates level of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManUpdateReverseLevel( Aig_Man_t * p, Aig_Obj_t * pObjNew ) +{ + Aig_Obj_t * pFanin, * pTemp; + int LevelOld, LevFanin, Lev, k; + assert( p->vLevelR != NULL ); + assert( Aig_ObjIsNode(pObjNew) ); + // allocate level if needed + if ( p->vLevels == NULL ) + p->vLevels = Vec_VecAlloc( Aig_ManLevels(p) + 8 ); + // check if level has changed + LevelOld = Aig_ObjReverseLevel(p, pObjNew); + if ( LevelOld == Aig_ObjReverseLevelNew(p, pObjNew) ) + return; + // start the data structure for level update + // we cannot fail to visit a node when using this structure because the + // nodes are stored by their _old_ levels, which are assumed to be correct + Vec_VecClear( p->vLevels ); + Vec_VecPush( p->vLevels, LevelOld, pObjNew ); + pObjNew->fMarkA = 1; + // recursively update level + Vec_VecForEachEntryStart( Aig_Obj_t *, p->vLevels, pTemp, Lev, k, LevelOld ) + { + pTemp->fMarkA = 0; + LevelOld = Aig_ObjReverseLevel(p, pTemp); + assert( LevelOld == Lev ); + Aig_ObjSetReverseLevel( p, pTemp, Aig_ObjReverseLevelNew(p, pTemp) ); + // if the level did not change, to need to check the fanout levels + if ( Aig_ObjReverseLevel(p, pTemp) == Lev ) + continue; + // schedule fanins for level update + pFanin = Aig_ObjFanin0(pTemp); + if ( Aig_ObjIsNode(pFanin) && !pFanin->fMarkA ) + { + LevFanin = Aig_ObjReverseLevel( p, pFanin ); + assert( LevFanin >= Lev ); + Vec_VecPush( p->vLevels, LevFanin, pFanin ); + pFanin->fMarkA = 1; + } + pFanin = Aig_ObjFanin1(pTemp); + if ( Aig_ObjIsNode(pFanin) && !pFanin->fMarkA ) + { + LevFanin = Aig_ObjReverseLevel( p, pFanin ); + assert( LevFanin >= Lev ); + Vec_VecPush( p->vLevels, LevFanin, pFanin ); + pFanin->fMarkA = 1; + } + } +} + +/**Function************************************************************* + + Synopsis [Verifies direct level of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManVerifyLevel( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + assert( p->pFanData ); + Aig_ManForEachNode( p, pObj, i ) + if ( Aig_ObjLevel(pObj) != Aig_ObjLevelNew(pObj) ) + { + printf( "Level of node %6d should be %4d instead of %4d.\n", + pObj->Id, Aig_ObjLevelNew(pObj), Aig_ObjLevel(pObj) ); + Counter++; + } + if ( Counter ) + printf( "Levels of %d nodes are incorrect.\n", Counter ); +} + +/**Function************************************************************* + + Synopsis [Verifies reverse level of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManVerifyReverseLevel( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + assert( p->vLevelR ); + Aig_ManForEachNode( p, pObj, i ) + if ( Aig_ObjLevel(pObj) != Aig_ObjLevelNew(pObj) ) + { + printf( "Reverse level of node %6d should be %4d instead of %4d.\n", + pObj->Id, Aig_ObjReverseLevelNew(p, pObj), Aig_ObjReverseLevel(p, pObj) ); + Counter++; + } + if ( Counter ) + printf( "Reverse levels of %d nodes are incorrect.\n", Counter ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigTruth.c b/yosys/abc/src/aig/aig/aigTruth.c new file mode 100644 index 00000000000..5115c4f49d3 --- /dev/null +++ b/yosys/abc/src/aig/aig/aigTruth.c @@ -0,0 +1,103 @@ +/**CFile**************************************************************** + + FileName [aigTruth.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Computes truth table for the cut.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigTruth.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes truth table of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Aig_ManCutTruthOne( Aig_Obj_t * pNode, unsigned * pTruth, int nWords ) +{ + unsigned * pTruth0, * pTruth1; + int i; + pTruth0 = (unsigned *)Aig_ObjFanin0(pNode)->pData; + pTruth1 = (unsigned *)Aig_ObjFanin1(pNode)->pData; + if ( Aig_ObjIsExor(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] ^ pTruth1[i]; + else if ( !Aig_ObjFaninC0(pNode) && !Aig_ObjFaninC1(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] & pTruth1[i]; + else if ( !Aig_ObjFaninC0(pNode) && Aig_ObjFaninC1(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] & ~pTruth1[i]; + else if ( Aig_ObjFaninC0(pNode) && !Aig_ObjFaninC1(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ~pTruth0[i] & pTruth1[i]; + else // if ( Aig_ObjFaninC0(pNode) && Aig_ObjFaninC1(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ~pTruth0[i] & ~pTruth1[i]; + return pTruth; +} + +/**Function************************************************************* + + Synopsis [Computes truth table of the cut.] + + Description [The returned pointer should be used immediately.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Aig_ManCutTruth( Aig_Obj_t * pRoot, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes, Vec_Ptr_t * vTruthElem, Vec_Ptr_t * vTruthStore ) +{ + Aig_Obj_t * pObj; + int i, nWords; + assert( Vec_PtrSize(vLeaves) <= Vec_PtrSize(vTruthElem) ); + assert( Vec_PtrSize(vNodes) <= Vec_PtrSize(vTruthStore) ); + assert( Vec_PtrSize(vNodes) == 0 || pRoot == Vec_PtrEntryLast(vNodes) ); + // assign elementary truth tables + Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i ) + pObj->pData = Vec_PtrEntry( vTruthElem, i ); + // compute truths for other nodes + nWords = Abc_TruthWordNum( Vec_PtrSize(vLeaves) ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + pObj->pData = Aig_ManCutTruthOne( pObj, (unsigned *)Vec_PtrEntry(vTruthStore, i), nWords ); + return (unsigned *)pRoot->pData; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigTsim.c b/yosys/abc/src/aig/aig/aigTsim.c new file mode 100644 index 00000000000..dd9eb6e7264 --- /dev/null +++ b/yosys/abc/src/aig/aig/aigTsim.c @@ -0,0 +1,526 @@ +/**CFile**************************************************************** + + FileName [aigTsim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Ternary simulation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigTsim.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" +#include "aig/saig/saig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define TSI_MAX_ROUNDS 1000 +#define TSI_ONE_SERIES 300 + +#define AIG_XVS0 1 +#define AIG_XVS1 2 +#define AIG_XVSX 3 + +static inline void Aig_ObjSetXsim( Aig_Obj_t * pObj, int Value ) { pObj->nCuts = Value; } +static inline int Aig_ObjGetXsim( Aig_Obj_t * pObj ) { return pObj->nCuts; } +static inline int Aig_XsimInv( int Value ) +{ + if ( Value == AIG_XVS0 ) + return AIG_XVS1; + if ( Value == AIG_XVS1 ) + return AIG_XVS0; + assert( Value == AIG_XVSX ); + return AIG_XVSX; +} +static inline int Aig_XsimAnd( int Value0, int Value1 ) +{ + if ( Value0 == AIG_XVS0 || Value1 == AIG_XVS0 ) + return AIG_XVS0; + if ( Value0 == AIG_XVSX || Value1 == AIG_XVSX ) + return AIG_XVSX; + assert( Value0 == AIG_XVS1 && Value1 == AIG_XVS1 ); + return AIG_XVS1; +} +static inline int Aig_XsimRand2() +{ + return (Aig_ManRandom(0) & 1) ? AIG_XVS1 : AIG_XVS0; +} +static inline int Aig_XsimRand3() +{ + int RetValue; + do { + RetValue = Aig_ManRandom(0) & 3; + } while ( RetValue == 0 ); + return RetValue; +} +static inline int Aig_ObjGetXsimFanin0( Aig_Obj_t * pObj ) +{ + int RetValue; + RetValue = Aig_ObjGetXsim(Aig_ObjFanin0(pObj)); + return Aig_ObjFaninC0(pObj)? Aig_XsimInv(RetValue) : RetValue; +} +static inline int Aig_ObjGetXsimFanin1( Aig_Obj_t * pObj ) +{ + int RetValue; + RetValue = Aig_ObjGetXsim(Aig_ObjFanin1(pObj)); + return Aig_ObjFaninC1(pObj)? Aig_XsimInv(RetValue) : RetValue; +} +static inline void Aig_XsimPrint( FILE * pFile, int Value ) +{ + if ( Value == AIG_XVS0 ) + { + fprintf( pFile, "0" ); + return; + } + if ( Value == AIG_XVS1 ) + { + fprintf( pFile, "1" ); + return; + } + assert( Value == AIG_XVSX ); + fprintf( pFile, "x" ); +} + +// simulation manager +typedef struct Aig_Tsi_t_ Aig_Tsi_t; +struct Aig_Tsi_t_ +{ + Aig_Man_t * pAig; // the original AIG manager + // ternary state representation + int nWords; // the number of words in the states + Vec_Ptr_t * vStates; // the collection of ternary states + Aig_MmFixed_t * pMem; // memory for ternary states + // hash table for terminary states + unsigned ** pBins; + int nBins; +}; + +static inline unsigned * Aig_TsiNext( unsigned * pState, int nWords ) { return *((unsigned **)(pState + nWords)); } +static inline void Aig_TsiSetNext( unsigned * pState, int nWords, unsigned * pNext ) { *((unsigned **)(pState + nWords)) = pNext; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Tsi_t * Aig_TsiStart( Aig_Man_t * pAig ) +{ + Aig_Tsi_t * p; + p = ABC_ALLOC( Aig_Tsi_t, 1 ); + memset( p, 0, sizeof(Aig_Tsi_t) ); + p->pAig = pAig; + p->nWords = Abc_BitWordNum( 2*Aig_ManRegNum(pAig) ); + p->vStates = Vec_PtrAlloc( 1000 ); + p->pMem = Aig_MmFixedStart( sizeof(unsigned) * p->nWords + sizeof(unsigned *), 10000 ); + p->nBins = Abc_PrimeCudd(TSI_MAX_ROUNDS/2); + p->pBins = ABC_ALLOC( unsigned *, p->nBins ); + memset( p->pBins, 0, sizeof(unsigned *) * p->nBins ); + return p; +} + +/**Function************************************************************* + + Synopsis [Deallocates simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_TsiStop( Aig_Tsi_t * p ) +{ + Aig_MmFixedStop( p->pMem, 0 ); + Vec_PtrFree( p->vStates ); + ABC_FREE( p->pBins ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Computes hash value of the node using its simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_TsiStateHash( unsigned * pState, int nWords, int nTableSize ) +{ + static int s_FPrimes[128] = { + 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, + 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, + 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, + 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, + 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, + 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, + 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, + 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, + 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, + 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, + 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, + 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, + 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 + }; + unsigned uHash; + int i; + uHash = 0; + for ( i = 0; i < nWords; i++ ) + uHash ^= pState[i] * s_FPrimes[i & 0x7F]; + return uHash % nTableSize; +} + +/**Function************************************************************* + + Synopsis [Inserts value into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_TsiStateLookup( Aig_Tsi_t * p, unsigned * pState, int nWords ) +{ + unsigned * pEntry; + int Hash; + Hash = Aig_TsiStateHash( pState, nWords, p->nBins ); + for ( pEntry = p->pBins[Hash]; pEntry; pEntry = Aig_TsiNext(pEntry, nWords) ) + if ( !memcmp( pEntry, pState, sizeof(unsigned) * nWords ) ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Inserts value into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_TsiStateInsert( Aig_Tsi_t * p, unsigned * pState, int nWords ) +{ + int Hash = Aig_TsiStateHash( pState, nWords, p->nBins ); + assert( !Aig_TsiStateLookup( p, pState, nWords ) ); + Aig_TsiSetNext( pState, nWords, p->pBins[Hash] ); + p->pBins[Hash] = pState; +} + +/**Function************************************************************* + + Synopsis [Inserts value into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Aig_TsiStateNew( Aig_Tsi_t * p ) +{ + unsigned * pState; + pState = (unsigned *)Aig_MmFixedEntryFetch( p->pMem ); + memset( pState, 0, sizeof(unsigned) * p->nWords ); + Vec_PtrPush( p->vStates, pState ); + return pState; +} + +/**Function************************************************************* + + Synopsis [Inserts value into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_TsiStatePrint( Aig_Tsi_t * p, unsigned * pState ) +{ + int i, Value, nZeros = 0, nOnes = 0, nDcs = 0; + for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ ) + { + Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); + if ( Value == 1 ) + printf( "0" ), nZeros++; + else if ( Value == 2 ) + printf( "1" ), nOnes++; + else if ( Value == 3 ) + printf( "x" ), nDcs++; + else + assert( 0 ); + } + printf( " (0=%5d, 1=%5d, x=%5d)\n", nZeros, nOnes, nDcs ); +} + +/**Function************************************************************* + + Synopsis [Count constant values in the state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_TsiStateCount( Aig_Tsi_t * p, unsigned * pState ) +{ + Aig_Obj_t * pObjLi, * pObjLo; + int i, Value, nCounter = 0; + Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObjLo, i ) + { + Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); + nCounter += (Value == 1 || Value == 2); + } + return nCounter; +} + +/**Function************************************************************* + + Synopsis [Count constant values in the state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_TsiStateOrAll( Aig_Tsi_t * pTsi, unsigned * pState ) +{ + unsigned * pPrev; + int i, k; + Vec_PtrForEachEntry( unsigned *, pTsi->vStates, pPrev, i ) + { + for ( k = 0; k < pTsi->nWords; k++ ) + pState[k] |= pPrev[k]; + } +} + + +/**Function************************************************************* + + Synopsis [Cycles the circuit to create a new initial state.] + + Description [Simulates the circuit with random input for the given + number of timeframes to get a better initial state.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManTernarySimulate( Aig_Man_t * p, int fVerbose, int fVeryVerbose ) +{ + Aig_Tsi_t * pTsi; + Vec_Ptr_t * vMap; + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + unsigned * pState;//, * pPrev; + int i, f, fConstants, Value, nCounter, nRetired; + // allocate the simulation manager + pTsi = Aig_TsiStart( p ); + // initialize the values + Aig_ObjSetXsim( Aig_ManConst1(p), AIG_XVS1 ); + Aig_ManForEachPiSeq( p, pObj, i ) + Aig_ObjSetXsim( pObj, AIG_XVSX ); + Aig_ManForEachLoSeq( p, pObj, i ) + Aig_ObjSetXsim( pObj, AIG_XVS0 ); + // simulate for the given number of timeframes + for ( f = 0; f < TSI_MAX_ROUNDS; f++ ) + { + // collect this state + pState = Aig_TsiStateNew( pTsi ); + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + { + Value = Aig_ObjGetXsim(pObjLo); + if ( Value & 1 ) + Abc_InfoSetBit( pState, 2 * i ); + if ( Value & 2 ) + Abc_InfoSetBit( pState, 2 * i + 1 ); + } + +// printf( "%d ", Aig_TsiStateCount(pTsi, pState) ); +if ( fVeryVerbose ) +{ +printf( "%3d : ", f ); +Aig_TsiStatePrint( pTsi, pState ); +} + // check if this state exists + if ( Aig_TsiStateLookup( pTsi, pState, pTsi->nWords ) ) + break; +// nCounter = 0; +// Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) +// nCounter += (Aig_ObjGetXsim(pObjLo) == AIG_XVS0); +//printf( "%d -> ", nCounter ); + // insert this state + Aig_TsiStateInsert( pTsi, pState, pTsi->nWords ); + // simulate internal nodes + Aig_ManForEachNode( p, pObj, i ) + { + Aig_ObjSetXsim( pObj, Aig_XsimAnd(Aig_ObjGetXsimFanin0(pObj), Aig_ObjGetXsimFanin1(pObj)) ); +// printf( "%d %d Id = %2d. Value = %d.\n", +// Aig_ObjGetXsimFanin0(pObj), Aig_ObjGetXsimFanin1(pObj), +// i, Aig_XsimAnd(Aig_ObjGetXsimFanin0(pObj), Aig_ObjGetXsimFanin1(pObj)) ); + } + // transfer the latch values + Aig_ManForEachLiSeq( p, pObj, i ) + Aig_ObjSetXsim( pObj, Aig_ObjGetXsimFanin0(pObj) ); + nCounter = 0; + nRetired = 0; + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + { + if ( f < TSI_ONE_SERIES ) + Aig_ObjSetXsim( pObjLo, Aig_ObjGetXsim(pObjLi) ); + else + { + if ( Aig_ObjGetXsim(pObjLi) != Aig_ObjGetXsim(pObjLo) ) + { + Aig_ObjSetXsim( pObjLo, AIG_XVSX ); + nRetired++; + } + } + nCounter += (Aig_ObjGetXsim(pObjLo) == AIG_XVS0); + } +// if ( nRetired ) +// printf( "Retired %d registers.\n", nRetired ); + +// if ( f && (f % 1000 == 0) ) +// printf( "%d \n", f ); +//printf( "%d ", nCounter ); + } +//printf( "\n" ); + if ( f == TSI_MAX_ROUNDS ) + { + printf( "Aig_ManTernarySimulate(): Did not reach a fixed point after %d iterations (not a bug).\n", TSI_MAX_ROUNDS ); + Aig_TsiStop( pTsi ); + return NULL; + } + // OR all the states + pState = (unsigned *)Vec_PtrEntry( pTsi->vStates, 0 ); + Aig_TsiStateOrAll( pTsi, pState ); + // check if there are constants + fConstants = 0; + if ( 2*Aig_ManRegNum(p) == 32*pTsi->nWords ) + { + for ( i = 0; i < pTsi->nWords; i++ ) + if ( pState[i] != ~0 ) + fConstants = 1; + } + else + { + for ( i = 0; i < pTsi->nWords - 1; i++ ) + if ( pState[i] != ~0 ) + fConstants = 1; + if ( pState[i] != Abc_InfoMask( 2*Aig_ManRegNum(p) - 32*(pTsi->nWords-1) ) ) + fConstants = 1; + } + if ( fConstants == 0 ) + { + if ( fVerbose ) + printf( "Detected 0 constants after %d iterations of ternary simulation.\n", f ); + Aig_TsiStop( pTsi ); + return NULL; + } + + // start mapping by adding the true PIs + vMap = Vec_PtrAlloc( Aig_ManCiNum(p) ); + Aig_ManForEachPiSeq( p, pObj, i ) + Vec_PtrPush( vMap, pObj ); + // find constant registers + nCounter = 0; + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + { + Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); + nCounter += (Value == 1 || Value == 2); + if ( Value == 1 ) + Vec_PtrPush( vMap, Aig_ManConst0(p) ); + else if ( Value == 2 ) + Vec_PtrPush( vMap, Aig_ManConst1(p) ); + else if ( Value == 3 ) + Vec_PtrPush( vMap, pObjLo ); + else + assert( 0 ); +// Aig_XsimPrint( stdout, Value ); + } +// printf( "\n" ); + Aig_TsiStop( pTsi ); + if ( fVerbose ) + printf( "Detected %d constants after %d iterations of ternary simulation.\n", nCounter, f ); + return vMap; +} + +/**Function************************************************************* + + Synopsis [Reduces the circuit using ternary simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManConstReduce( Aig_Man_t * p, int fUseMvSweep, int nFramesSymb, int nFramesSatur, int fVerbose, int fVeryVerbose ) +{ + Aig_Man_t * pTemp; + Vec_Ptr_t * vMap; + while ( Aig_ManRegNum(p) > 0 ) + { + if ( fUseMvSweep ) + vMap = Saig_MvManSimulate( p, nFramesSymb, nFramesSatur, fVerbose, fVeryVerbose ); + else + vMap = Aig_ManTernarySimulate( p, fVerbose, fVeryVerbose ); + if ( vMap == NULL ) + break; + p = Aig_ManRemap( pTemp = p, vMap ); + Vec_PtrFree( vMap ); + Aig_ManSeqCleanup( p ); + if ( fVerbose ) + Aig_ManReportImprovement( pTemp, p ); + Aig_ManStop( pTemp ); + } + return p; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigUtil.c b/yosys/abc/src/aig/aig/aigUtil.c new file mode 100644 index 00000000000..aad8c250c46 --- /dev/null +++ b/yosys/abc/src/aig/aig/aigUtil.c @@ -0,0 +1,1580 @@ +/**CFile**************************************************************** + + FileName [aigUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Various procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigUtil.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Increments the current traversal ID of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManIncrementTravId( Aig_Man_t * p ) +{ + if ( p->nTravIds >= (1<<30)-1 ) + Aig_ManCleanData( p ); + p->nTravIds++; +} + +/**Function************************************************************* + + Synopsis [Returns the time stamp.] + + Description [The file should be closed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Aig_TimeStamp() +{ + static char Buffer[100]; + char * TimeStamp; + time_t ltime; + // get the current time + time( <ime ); + TimeStamp = asctime( localtime( <ime ) ); + TimeStamp[ strlen(TimeStamp) - 1 ] = 0; + strcpy( Buffer, TimeStamp ); + return Buffer; +} + +/**Function************************************************************* + + Synopsis [Make sure AIG has not gaps in the numeric order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManHasNoGaps( Aig_Man_t * p ) +{ + return (int)(Aig_ManObjNum(p) == Aig_ManCiNum(p) + Aig_ManCoNum(p) + Aig_ManNodeNum(p) + 1); +} + +/**Function************************************************************* + + Synopsis [Collect the latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManLevels( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, LevelMax = 0; + Aig_ManForEachCo( p, pObj, i ) + LevelMax = Abc_MaxInt( LevelMax, (int)Aig_ObjFanin0(pObj)->Level ); + return LevelMax; +} + +/**Function************************************************************* + + Synopsis [Reset reference counters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManResetRefs( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachObj( p, pObj, i ) + pObj->nRefs = 0; + Aig_ManForEachObj( p, pObj, i ) + { + if ( Aig_ObjFanin0(pObj) ) + Aig_ObjFanin0(pObj)->nRefs++; + if ( Aig_ObjFanin1(pObj) ) + Aig_ObjFanin1(pObj)->nRefs++; + } +} + +/**Function************************************************************* + + Synopsis [Cleans fMarkA.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManCleanMarkA( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachObj( p, pObj, i ) + pObj->fMarkA = 0; +} + +/**Function************************************************************* + + Synopsis [Cleans fMarkB.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManCleanMarkB( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachObj( p, pObj, i ) + pObj->fMarkB = 0; +} + +/**Function************************************************************* + + Synopsis [Cleans fMarkB.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManCleanMarkAB( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachObj( p, pObj, i ) + pObj->fMarkA = pObj->fMarkB = 0; +} + +/**Function************************************************************* + + Synopsis [Cleans the data pointers for the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManCleanData( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachObj( p, pObj, i ) + pObj->pData = NULL; +} + +/**Function************************************************************* + + Synopsis [Cleans the data pointers for the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManCleanNext( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachObj( p, pObj, i ) + pObj->pNext = NULL; +} + +/**Function************************************************************* + + Synopsis [Recursively cleans the data pointers in the cone of the node.] + + Description [Applicable to small AIGs only because no caching is performed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjCleanData_rec( Aig_Obj_t * pObj ) +{ + assert( !Aig_IsComplement(pObj) ); + assert( !Aig_ObjIsCo(pObj) ); + if ( Aig_ObjIsAnd(pObj) ) + { + Aig_ObjCleanData_rec( Aig_ObjFanin0(pObj) ); + Aig_ObjCleanData_rec( Aig_ObjFanin1(pObj) ); + } + pObj->pData = NULL; +} + + +/**Function************************************************************* + + Synopsis [Detects multi-input gate rooted at this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjCollectMulti_rec( Aig_Obj_t * pRoot, Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) +{ + if ( pRoot != pObj && (Aig_IsComplement(pObj) || Aig_ObjIsCi(pObj) || Aig_ObjType(pRoot) != Aig_ObjType(pObj)) ) + { + Vec_PtrPushUnique(vSuper, pObj); + return; + } + Aig_ObjCollectMulti_rec( pRoot, Aig_ObjChild0(pObj), vSuper ); + Aig_ObjCollectMulti_rec( pRoot, Aig_ObjChild1(pObj), vSuper ); +} + +/**Function************************************************************* + + Synopsis [Detects multi-input gate rooted at this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjCollectMulti( Aig_Obj_t * pRoot, Vec_Ptr_t * vSuper ) +{ + assert( !Aig_IsComplement(pRoot) ); + Vec_PtrClear( vSuper ); + Aig_ObjCollectMulti_rec( pRoot, pRoot, vSuper ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjIsMuxType( Aig_Obj_t * pNode ) +{ + Aig_Obj_t * pNode0, * pNode1; + // check that the node is regular + assert( !Aig_IsComplement(pNode) ); + // if the node is not AND, this is not MUX + if ( !Aig_ObjIsAnd(pNode) ) + return 0; + // if the children are not complemented, this is not MUX + if ( !Aig_ObjFaninC0(pNode) || !Aig_ObjFaninC1(pNode) ) + return 0; + // get children + pNode0 = Aig_ObjFanin0(pNode); + pNode1 = Aig_ObjFanin1(pNode); + // if the children are not ANDs, this is not MUX + if ( !Aig_ObjIsAnd(pNode0) || !Aig_ObjIsAnd(pNode1) ) + return 0; + // otherwise the node is MUX iff it has a pair of equal grandchildren + return (Aig_ObjFanin0(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC0(pNode1))) || + (Aig_ObjFanin0(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC1(pNode1))) || + (Aig_ObjFanin1(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC0(pNode1))) || + (Aig_ObjFanin1(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC1(pNode1))); +} + + +/**Function************************************************************* + + Synopsis [Recognizes what nodes are inputs of the EXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjRecognizeExor( Aig_Obj_t * pObj, Aig_Obj_t ** ppFan0, Aig_Obj_t ** ppFan1 ) +{ + Aig_Obj_t * p0, * p1; + assert( !Aig_IsComplement(pObj) ); + if ( !Aig_ObjIsNode(pObj) ) + return 0; + if ( Aig_ObjIsExor(pObj) ) + { + *ppFan0 = Aig_ObjChild0(pObj); + *ppFan1 = Aig_ObjChild1(pObj); + return 1; + } + assert( Aig_ObjIsAnd(pObj) ); + p0 = Aig_ObjChild0(pObj); + p1 = Aig_ObjChild1(pObj); + if ( !Aig_IsComplement(p0) || !Aig_IsComplement(p1) ) + return 0; + p0 = Aig_Regular(p0); + p1 = Aig_Regular(p1); + if ( !Aig_ObjIsAnd(p0) || !Aig_ObjIsAnd(p1) ) + return 0; + if ( Aig_ObjFanin0(p0) != Aig_ObjFanin0(p1) || Aig_ObjFanin1(p0) != Aig_ObjFanin1(p1) ) + return 0; + if ( Aig_ObjFaninC0(p0) == Aig_ObjFaninC0(p1) || Aig_ObjFaninC1(p0) == Aig_ObjFaninC1(p1) ) + return 0; + *ppFan0 = Aig_ObjChild0(p0); + *ppFan1 = Aig_ObjChild1(p0); + return 1; +} + +/**Function************************************************************* + + Synopsis [Recognizes what nodes are control and data inputs of a MUX.] + + Description [If the node is a MUX, returns the control variable C. + Assigns nodes T and E to be the then and else variables of the MUX. + Node C is never complemented. Nodes T and E can be complemented. + This function also recognizes EXOR/NEXOR gates as MUXes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ObjRecognizeMux( Aig_Obj_t * pNode, Aig_Obj_t ** ppNodeT, Aig_Obj_t ** ppNodeE ) +{ + Aig_Obj_t * pNode0, * pNode1; + assert( !Aig_IsComplement(pNode) ); + assert( Aig_ObjIsMuxType(pNode) ); + // get children + pNode0 = Aig_ObjFanin0(pNode); + pNode1 = Aig_ObjFanin1(pNode); + + // find the control variable + if ( Aig_ObjFanin1(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC1(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p2) ) + if ( Aig_ObjFaninC1(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1); + return Aig_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1); + return Aig_ObjChild1(pNode0);//pNode1->p2; + } + } + else if ( Aig_ObjFanin0(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC0(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p1) ) + if ( Aig_ObjFaninC0(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2); + return Aig_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2); + return Aig_ObjChild0(pNode0);//pNode1->p1; + } + } + else if ( Aig_ObjFanin0(pNode0) == Aig_ObjFanin1(pNode1) && (Aig_ObjFaninC0(pNode0) ^ Aig_ObjFaninC1(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p1) ) + if ( Aig_ObjFaninC0(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2); + return Aig_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Aig_Not(Aig_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Aig_Not(Aig_ObjChild0(pNode1));//pNode2->p1); + return Aig_ObjChild0(pNode0);//pNode1->p1; + } + } + else if ( Aig_ObjFanin1(pNode0) == Aig_ObjFanin0(pNode1) && (Aig_ObjFaninC1(pNode0) ^ Aig_ObjFaninC0(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p2) ) + if ( Aig_ObjFaninC1(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1); + return Aig_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Aig_Not(Aig_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Aig_Not(Aig_ObjChild1(pNode1));//pNode2->p2); + return Aig_ObjChild1(pNode0);//pNode1->p2; + } + } + assert( 0 ); // this is not MUX + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Aig_ObjReal_rec( Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pObjNew, * pObjR = Aig_Regular(pObj); + if ( !Aig_ObjIsBuf(pObjR) ) + return pObj; + pObjNew = Aig_ObjReal_rec( Aig_ObjChild0(pObjR) ); + return Aig_NotCond( pObjNew, Aig_IsComplement(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Procedure used for sorting the nodes in increasing order of IDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ObjCompareIdIncrease( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 ) +{ + int Diff = Aig_ObjId(*pp1) - Aig_ObjId(*pp2); + if ( Diff < 0 ) + return -1; + if ( Diff > 0 ) + return 1; + return 0; +} + + +/**Function************************************************************* + + Synopsis [Prints Eqn formula for the AIG rooted at this node.] + + Description [The formula is in terms of PIs, which should have + their names assigned in pObj->pData fields.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjPrintEqn( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ) +{ + Vec_Ptr_t * vSuper; + Aig_Obj_t * pFanin; + int fCompl, i; + // store the complemented attribute + fCompl = Aig_IsComplement(pObj); + pObj = Aig_Regular(pObj); + // constant case + if ( Aig_ObjIsConst1(pObj) ) + { + fprintf( pFile, "%d", !fCompl ); + return; + } + // PI case + if ( Aig_ObjIsCi(pObj) ) + { + fprintf( pFile, "%s%s", fCompl? "!" : "", (char*)pObj->pData ); + return; + } + // AND case + Vec_VecExpand( vLevels, Level ); + vSuper = Vec_VecEntry(vLevels, Level); + Aig_ObjCollectMulti( pObj, vSuper ); + fprintf( pFile, "%s", (Level==0? "" : "(") ); + Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i ) + { + Aig_ObjPrintEqn( pFile, Aig_NotCond(pFanin, fCompl), vLevels, Level+1 ); + if ( i < Vec_PtrSize(vSuper) - 1 ) + fprintf( pFile, " %s ", fCompl? "+" : "*" ); + } + fprintf( pFile, "%s", (Level==0? "" : ")") ); + return; +} + +/**Function************************************************************* + + Synopsis [Prints Verilog formula for the AIG rooted at this node.] + + Description [The formula is in terms of PIs, which should have + their names assigned in pObj->pData fields.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjPrintVerilog( FILE * pFile, Aig_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ) +{ + Vec_Ptr_t * vSuper; + Aig_Obj_t * pFanin, * pFanin0, * pFanin1, * pFaninC; + int fCompl, i; + // store the complemented attribute + fCompl = Aig_IsComplement(pObj); + pObj = Aig_Regular(pObj); + // constant case + if ( Aig_ObjIsConst1(pObj) ) + { + fprintf( pFile, "1\'b%d", !fCompl ); + return; + } + // PI case + if ( Aig_ObjIsCi(pObj) ) + { + fprintf( pFile, "%s%s", fCompl? "~" : "", (char*)pObj->pData ); + return; + } + // EXOR case + if ( Aig_ObjIsExor(pObj) ) + { + Vec_VecExpand( vLevels, Level ); + vSuper = Vec_VecEntry( vLevels, Level ); + Aig_ObjCollectMulti( pObj, vSuper ); + fprintf( pFile, "%s", (Level==0? "" : "(") ); + Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i ) + { + Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin, (fCompl && i==0)), vLevels, Level+1 ); + if ( i < Vec_PtrSize(vSuper) - 1 ) + fprintf( pFile, " ^ " ); + } + fprintf( pFile, "%s", (Level==0? "" : ")") ); + return; + } + // MUX case + if ( Aig_ObjIsMuxType(pObj) ) + { + if ( Aig_ObjRecognizeExor( pObj, &pFanin0, &pFanin1 ) ) + { + fprintf( pFile, "%s", (Level==0? "" : "(") ); + Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin0, fCompl), vLevels, Level+1 ); + fprintf( pFile, " ^ " ); + Aig_ObjPrintVerilog( pFile, pFanin1, vLevels, Level+1 ); + fprintf( pFile, "%s", (Level==0? "" : ")") ); + } + else + { + pFaninC = Aig_ObjRecognizeMux( pObj, &pFanin1, &pFanin0 ); + fprintf( pFile, "%s", (Level==0? "" : "(") ); + Aig_ObjPrintVerilog( pFile, pFaninC, vLevels, Level+1 ); + fprintf( pFile, " ? " ); + Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin1, fCompl), vLevels, Level+1 ); + fprintf( pFile, " : " ); + Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin0, fCompl), vLevels, Level+1 ); + fprintf( pFile, "%s", (Level==0? "" : ")") ); + } + return; + } + // AND case + Vec_VecExpand( vLevels, Level ); + vSuper = Vec_VecEntry(vLevels, Level); + Aig_ObjCollectMulti( pObj, vSuper ); + fprintf( pFile, "%s", (Level==0? "" : "(") ); + Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pFanin, i ) + { + Aig_ObjPrintVerilog( pFile, Aig_NotCond(pFanin, fCompl), vLevels, Level+1 ); + if ( i < Vec_PtrSize(vSuper) - 1 ) + fprintf( pFile, " %s ", fCompl? "|" : "&" ); + } + fprintf( pFile, "%s", (Level==0? "" : ")") ); + return; +} + + +/**Function************************************************************* + + Synopsis [Prints node in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ObjPrintVerbose( Aig_Obj_t * pObj, int fHaig ) +{ + assert( !Aig_IsComplement(pObj) ); + printf( "Node %d : ", pObj->Id ); + if ( Aig_ObjIsConst1(pObj) ) + printf( "constant 1" ); + else if ( Aig_ObjIsCi(pObj) ) + printf( "CI" ); + else if ( Aig_ObjIsCo(pObj) ) + { + printf( "CO( " ); + printf( "%d%s )", + Aig_ObjFanin0(pObj)->Id, (Aig_ObjFaninC0(pObj)? "\'" : " ") ); + } + else + printf( "AND( %d%s, %d%s )", + Aig_ObjFanin0(pObj)->Id, (Aig_ObjFaninC0(pObj)? "\'" : " "), + Aig_ObjFanin1(pObj)->Id, (Aig_ObjFaninC1(pObj)? "\'" : " ") ); + printf( " (refs = %3d)", Aig_ObjRefs(pObj) ); +} +void Aig_ObjPrintVerboseCone( Aig_Man_t * p, Aig_Obj_t * pRoot, int fHaig ) +{ + extern Vec_Ptr_t * Aig_ManDfsArray( Aig_Man_t * p, Aig_Obj_t ** pNodes, int nNodes ); + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + vNodes = Aig_ManDfsArray( p, &pRoot, 1 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + Aig_ObjPrintVerbose( pObj, fHaig ), printf( "\n" ); + printf( "\n" ); + Vec_PtrFree( vNodes ); + +} + +/**Function************************************************************* + + Synopsis [Prints node in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManPrintVerbose( Aig_Man_t * p, int fHaig ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj; + int i; + printf( "PIs: " ); + Aig_ManForEachCi( p, pObj, i ) + printf( " %p", pObj ); + printf( "\n" ); + vNodes = Aig_ManDfs( p, 0 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + Aig_ObjPrintVerbose( pObj, fHaig ), printf( "\n" ); + printf( "\n" ); + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Write speculative miter for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManDump( Aig_Man_t * p ) +{ + static int Counter = 0; + char FileName[200]; + // dump the logic into a file + sprintf( FileName, "aigbug\\%03d.blif", ++Counter ); + Aig_ManDumpBlif( p, FileName, NULL, NULL ); + printf( "Intermediate AIG with %d nodes was written into file \"%s\".\n", Aig_ManNodeNum(p), FileName ); +} + +/**Function************************************************************* + + Synopsis [Writes the AIG into a BLIF file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManDumpBlif( Aig_Man_t * p, char * pFileName, Vec_Ptr_t * vPiNames, Vec_Ptr_t * vPoNames ) +{ + FILE * pFile; + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pConst1 = NULL; + int i, nDigits, Counter = 0; + if ( Aig_ManCoNum(p) == 0 ) + { + printf( "Aig_ManDumpBlif(): AIG manager does not have POs.\n" ); + return; + } + // check if constant is used + Aig_ManForEachCo( p, pObj, i ) + if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) + pConst1 = Aig_ManConst1(p); + // collect nodes in the DFS order + vNodes = Aig_ManDfs( p, 1 ); + // assign IDs to objects + Aig_ManConst1(p)->iData = Counter++; + Aig_ManForEachCi( p, pObj, i ) + pObj->iData = Counter++; + Aig_ManForEachCo( p, pObj, i ) + pObj->iData = Counter++; + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + pObj->iData = Counter++; + nDigits = Abc_Base10Log( Counter ); + // write the file + pFile = fopen( pFileName, "w" ); + fprintf( pFile, "# BLIF file written by procedure Aig_ManDumpBlif()\n" ); +// fprintf( pFile, "# http://www.eecs.berkeley.edu/~alanmi/abc/\n" ); + fprintf( pFile, ".model %s\n", p->pName ); + // write PIs + fprintf( pFile, ".inputs" ); + Aig_ManForEachPiSeq( p, pObj, i ) + if ( vPiNames ) + fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, i) ); + else + fprintf( pFile, " n%0*d", nDigits, pObj->iData ); + fprintf( pFile, "\n" ); + // write POs + fprintf( pFile, ".outputs" ); + Aig_ManForEachPoSeq( p, pObj, i ) + if ( vPoNames ) + fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPoNames, i) ); + else + fprintf( pFile, " n%0*d", nDigits, pObj->iData ); + fprintf( pFile, "\n" ); + // write latches + if ( Aig_ManRegNum(p) ) + { + fprintf( pFile, "\n" ); + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + { + fprintf( pFile, ".latch" ); + if ( vPoNames ) + fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPoNames, Aig_ManCoNum(p)-Aig_ManRegNum(p)+i) ); + else + fprintf( pFile, " n%0*d", nDigits, pObjLi->iData ); + if ( vPiNames ) + fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, Aig_ManCiNum(p)-Aig_ManRegNum(p)+i) ); + else + fprintf( pFile, " n%0*d", nDigits, pObjLo->iData ); + fprintf( pFile, " 0\n" ); + } + fprintf( pFile, "\n" ); + } + // write nodes + if ( pConst1 ) + fprintf( pFile, ".names n%0*d\n 1\n", nDigits, pConst1->iData ); + Aig_ManSetCioIds( p ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + fprintf( pFile, ".names" ); + if ( vPiNames && Aig_ObjIsCi(Aig_ObjFanin0(pObj)) ) + fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, Aig_ObjCioId(Aig_ObjFanin0(pObj))) ); + else + fprintf( pFile, " n%0*d", nDigits, Aig_ObjFanin0(pObj)->iData ); + if ( vPiNames && Aig_ObjIsCi(Aig_ObjFanin1(pObj)) ) + fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, Aig_ObjCioId(Aig_ObjFanin1(pObj))) ); + else + fprintf( pFile, " n%0*d", nDigits, Aig_ObjFanin1(pObj)->iData ); + fprintf( pFile, " n%0*d\n", nDigits, pObj->iData ); + fprintf( pFile, "%d%d 1\n", !Aig_ObjFaninC0(pObj), !Aig_ObjFaninC1(pObj) ); + } + // write POs + Aig_ManForEachCo( p, pObj, i ) + { + fprintf( pFile, ".names" ); + if ( vPiNames && Aig_ObjIsCi(Aig_ObjFanin0(pObj)) ) + fprintf( pFile, " %s", (char*)Vec_PtrEntry(vPiNames, Aig_ObjCioId(Aig_ObjFanin0(pObj))) ); + else + fprintf( pFile, " n%0*d", nDigits, Aig_ObjFanin0(pObj)->iData ); + if ( vPoNames ) + fprintf( pFile, " %s\n", (char*)Vec_PtrEntry(vPoNames, Aig_ObjCioId(pObj)) ); + else + fprintf( pFile, " n%0*d\n", nDigits, pObj->iData ); + fprintf( pFile, "%d 1\n", !Aig_ObjFaninC0(pObj) ); + } + Aig_ManCleanCioIds( p ); + fprintf( pFile, ".end\n\n" ); + fclose( pFile ); + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Writes the AIG into a Verilog file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManDumpVerilog( Aig_Man_t * p, char * pFileName ) +{ + FILE * pFile; + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pConst1 = NULL; + int i, nDigits, Counter = 0; + if ( Aig_ManCoNum(p) == 0 ) + { + printf( "Aig_ManDumpBlif(): AIG manager does not have POs.\n" ); + return; + } + // check if constant is used + Aig_ManForEachCo( p, pObj, i ) + if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) + pConst1 = Aig_ManConst1(p); + // collect nodes in the DFS order + vNodes = Aig_ManDfs( p, 1 ); + // assign IDs to objects + Aig_ManConst1(p)->iData = Counter++; + Aig_ManForEachCi( p, pObj, i ) + pObj->iData = Counter++; + Aig_ManForEachCo( p, pObj, i ) + pObj->iData = Counter++; + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + pObj->iData = Counter++; + nDigits = Abc_Base10Log( Counter ); + // write the file + pFile = fopen( pFileName, "w" ); + fprintf( pFile, "// Verilog file written by procedure Aig_ManDumpVerilog()\n" ); +// fprintf( pFile, "// http://www.eecs.berkeley.edu/~alanmi/abc/\n" ); + if ( Aig_ManRegNum(p) ) + fprintf( pFile, "module %s ( clock", p->pName? p->pName: "test" ); + else + fprintf( pFile, "module %s (", p->pName? p->pName: "test" ); + Aig_ManForEachPiSeq( p, pObj, i ) + fprintf( pFile, "%s n%0*d", ((Aig_ManRegNum(p) || i)? ",":""), nDigits, pObj->iData ); + Aig_ManForEachPoSeq( p, pObj, i ) + fprintf( pFile, ", n%0*d", nDigits, pObj->iData ); + fprintf( pFile, " );\n" ); + + // write PIs + if ( Aig_ManRegNum(p) ) + fprintf( pFile, "input clock;\n" ); + Aig_ManForEachPiSeq( p, pObj, i ) + fprintf( pFile, "input n%0*d;\n", nDigits, pObj->iData ); + // write POs + Aig_ManForEachPoSeq( p, pObj, i ) + fprintf( pFile, "output n%0*d;\n", nDigits, pObj->iData ); + // write latches + if ( Aig_ManRegNum(p) ) + { + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + fprintf( pFile, "reg n%0*d;\n", nDigits, pObjLo->iData ); + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + fprintf( pFile, "wire n%0*d;\n", nDigits, pObjLi->iData ); + } + // write nodes + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + fprintf( pFile, "wire n%0*d;\n", nDigits, pObj->iData ); + if ( pConst1 ) + fprintf( pFile, "wire n%0*d;\n", nDigits, pConst1->iData ); + // write nodes + if ( pConst1 ) + fprintf( pFile, "assign n%0*d = 1\'b1;\n", nDigits, pConst1->iData ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + fprintf( pFile, "assign n%0*d = %sn%0*d & %sn%0*d;\n", + nDigits, pObj->iData, + !Aig_ObjFaninC0(pObj) ? " " : "~", nDigits, Aig_ObjFanin0(pObj)->iData, + !Aig_ObjFaninC1(pObj) ? " " : "~", nDigits, Aig_ObjFanin1(pObj)->iData + ); + } + // write POs + Aig_ManForEachPoSeq( p, pObj, i ) + { + fprintf( pFile, "assign n%0*d = %sn%0*d;\n", + nDigits, pObj->iData, + !Aig_ObjFaninC0(pObj) ? " " : "~", nDigits, Aig_ObjFanin0(pObj)->iData ); + } + if ( Aig_ManRegNum(p) ) + { + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + { + fprintf( pFile, "assign n%0*d = %sn%0*d;\n", + nDigits, pObjLi->iData, + !Aig_ObjFaninC0(pObjLi) ? " " : "~", nDigits, Aig_ObjFanin0(pObjLi)->iData ); + } + } + + // write initial state + if ( Aig_ManRegNum(p) ) + { + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + fprintf( pFile, "always @ (posedge clock) begin n%0*d <= n%0*d; end\n", + nDigits, pObjLo->iData, + nDigits, pObjLi->iData ); + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + fprintf( pFile, "initial begin n%0*d <= 1\'b0; end\n", + nDigits, pObjLo->iData ); + } + + fprintf( pFile, "endmodule\n\n" ); + fclose( pFile ); + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Sets the PI/PO numbers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManSetCioIds( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachCi( p, pObj, i ) + pObj->CioId = i; + Aig_ManForEachCo( p, pObj, i ) + pObj->CioId = i; +} + +/**Function************************************************************* + + Synopsis [Sets the PI/PO numbers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManCleanCioIds( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManForEachCi( p, pObj, i ) + pObj->pNext = NULL; + Aig_ManForEachCo( p, pObj, i ) + pObj->pNext = NULL; +} + +/**Function************************************************************* + + Synopsis [Sets the PI/PO numbers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManChoiceNum( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + Aig_ManForEachNode( p, pObj, i ) + Counter += Aig_ObjIsChoice( p, pObj ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Prints the fanouts of the control register.] + + Description [Useful only for Intel MC benchmarks.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManPrintControlFanouts( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj, * pFanin0, * pFanin1, * pCtrl; + int i; + + pCtrl = Aig_ManCi( p, Aig_ManCiNum(p) - 1 ); + + printf( "Control signal:\n" ); + Aig_ObjPrint( p, pCtrl ); printf( "\n\n" ); + + Aig_ManForEachObj( p, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) ) + continue; + assert( pObj != pCtrl ); + pFanin0 = Aig_ObjFanin0(pObj); + pFanin1 = Aig_ObjFanin1(pObj); + if ( pFanin0 == pCtrl && Aig_ObjIsCi(pFanin1) ) + { + Aig_ObjPrint( p, pObj ); printf( "\n" ); + Aig_ObjPrint( p, pFanin1 ); printf( "\n" ); + printf( "\n" ); + } + if ( pFanin1 == pCtrl && Aig_ObjIsCi(pFanin0) ) + { + Aig_ObjPrint( p, pObj ); printf( "\n" ); + Aig_ObjPrint( p, pFanin0 ); printf( "\n" ); + printf( "\n" ); + } + } +} + +/**Function************************************************************* + + Synopsis [Returns the composite name of the file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Aig_FileNameGenericAppend( char * pBase, char * pSuffix ) +{ + static char Buffer[1000]; + char * pDot; + strcpy( Buffer, pBase ); + if ( (pDot = strrchr( Buffer, '.' )) ) + *pDot = 0; + strcat( Buffer, pSuffix ); + if ( (pDot = strrchr( Buffer, '\\' )) || (pDot = strrchr( Buffer, '/' )) ) + return pDot+1; + return Buffer; +} + +/**Function************************************************************* + + Synopsis [Creates a sequence of random numbers.] + + Description [] + + SideEffects [] + + SeeAlso [http://en.wikipedia.org/wiki/LFSR] + +***********************************************************************/ +void Aig_ManRandomTest2() +{ + FILE * pFile; + unsigned int lfsr = 1; + unsigned int period = 0; + pFile = fopen( "rand.txt", "w" ); + do { +// lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xd0000001u); // taps 32 31 29 1 + lfsr = 1; // to prevent the warning + ++period; + fprintf( pFile, "%10d : %10d ", period, lfsr ); +// Extra_PrintBinary( pFile, &lfsr, 32 ); + fprintf( pFile, "\n" ); + if ( period == 20000 ) + break; + } while(lfsr != 1u); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Creates a sequence of random numbers.] + + Description [] + + SideEffects [] + + SeeAlso [http://www.codeproject.com/KB/recipes/SimpleRNG.aspx] + +***********************************************************************/ +void Aig_ManRandomTest1() +{ + FILE * pFile; + unsigned int lfsr; + unsigned int period = 0; + pFile = fopen( "rand.txt", "w" ); + do { + lfsr = Aig_ManRandom( 0 ); + ++period; + fprintf( pFile, "%10d : %10d ", period, lfsr ); +// Extra_PrintBinary( pFile, &lfsr, 32 ); + fprintf( pFile, "\n" ); + if ( period == 20000 ) + break; + } while(lfsr != 1u); + fclose( pFile ); +} + + +#define NUMBER1 3716960521u +#define NUMBER2 2174103536u + +/**Function************************************************************* + + Synopsis [Creates a sequence of random numbers.] + + Description [] + + SideEffects [] + + SeeAlso [http://www.codeproject.com/KB/recipes/SimpleRNG.aspx] + +***********************************************************************/ +unsigned Aig_ManRandom( int fReset ) +{ +#ifdef _MSC_VER + static unsigned int m_z = NUMBER1; + static unsigned int m_w = NUMBER2; +#else + static __thread unsigned int m_z = NUMBER1; + static __thread unsigned int m_w = NUMBER2; +#endif + if ( fReset ) + { + m_z = NUMBER1; + m_w = NUMBER2; + } + m_z = 36969 * (m_z & 65535) + (m_z >> 16); + m_w = 18000 * (m_w & 65535) + (m_w >> 16); + return (m_z << 16) + m_w; +} + +/**Function************************************************************* + + Synopsis [Creates a sequence of random numbers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word Aig_ManRandom64( int fReset ) +{ + word Res = (word)Aig_ManRandom(fReset); + return Res | ((word)Aig_ManRandom(0) << 32); +} + + +/**Function************************************************************* + + Synopsis [Creates random info for the primary inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManRandomInfo( Vec_Ptr_t * vInfo, int iInputStart, int iWordStart, int iWordStop ) +{ + unsigned * pInfo; + int i, w; + Vec_PtrForEachEntryStart( unsigned *, vInfo, pInfo, i, iInputStart ) + for ( w = iWordStart; w < iWordStop; w++ ) + pInfo[w] = Aig_ManRandom(0); +} + +/**Function************************************************************* + + Synopsis [Returns the result of merging the two vectors.] + + Description [Assumes that the vectors are sorted in the increasing order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_NodeUnionLists( Vec_Ptr_t * vArr1, Vec_Ptr_t * vArr2, Vec_Ptr_t * vArr ) +{ + Aig_Obj_t ** pBeg = (Aig_Obj_t **)vArr->pArray; + Aig_Obj_t ** pBeg1 = (Aig_Obj_t **)vArr1->pArray; + Aig_Obj_t ** pBeg2 = (Aig_Obj_t **)vArr2->pArray; + Aig_Obj_t ** pEnd1 = (Aig_Obj_t **)vArr1->pArray + vArr1->nSize; + Aig_Obj_t ** pEnd2 = (Aig_Obj_t **)vArr2->pArray + vArr2->nSize; + Vec_PtrGrow( vArr, Vec_PtrSize(vArr1) + Vec_PtrSize(vArr2) ); + pBeg = (Aig_Obj_t **)vArr->pArray; + while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) + { + if ( (*pBeg1)->Id == (*pBeg2)->Id ) + *pBeg++ = *pBeg1++, pBeg2++; + else if ( (*pBeg1)->Id < (*pBeg2)->Id ) + *pBeg++ = *pBeg1++; + else + *pBeg++ = *pBeg2++; + } + while ( pBeg1 < pEnd1 ) + *pBeg++ = *pBeg1++; + while ( pBeg2 < pEnd2 ) + *pBeg++ = *pBeg2++; + vArr->nSize = pBeg - (Aig_Obj_t **)vArr->pArray; + assert( vArr->nSize <= vArr->nCap ); + assert( vArr->nSize >= vArr1->nSize ); + assert( vArr->nSize >= vArr2->nSize ); +} + +/**Function************************************************************* + + Synopsis [Returns the result of intersecting the two vectors.] + + Description [Assumes that the vectors are sorted in the increasing order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_NodeIntersectLists( Vec_Ptr_t * vArr1, Vec_Ptr_t * vArr2, Vec_Ptr_t * vArr ) +{ + Aig_Obj_t ** pBeg = (Aig_Obj_t **)vArr->pArray; + Aig_Obj_t ** pBeg1 = (Aig_Obj_t **)vArr1->pArray; + Aig_Obj_t ** pBeg2 = (Aig_Obj_t **)vArr2->pArray; + Aig_Obj_t ** pEnd1 = (Aig_Obj_t **)vArr1->pArray + vArr1->nSize; + Aig_Obj_t ** pEnd2 = (Aig_Obj_t **)vArr2->pArray + vArr2->nSize; + Vec_PtrGrow( vArr, Abc_MaxInt( Vec_PtrSize(vArr1), Vec_PtrSize(vArr2) ) ); + pBeg = (Aig_Obj_t **)vArr->pArray; + while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) + { + if ( (*pBeg1)->Id == (*pBeg2)->Id ) + *pBeg++ = *pBeg1++, pBeg2++; + else if ( (*pBeg1)->Id < (*pBeg2)->Id ) +// *pBeg++ = *pBeg1++; + pBeg1++; + else +// *pBeg++ = *pBeg2++; + pBeg2++; + } +// while ( pBeg1 < pEnd1 ) +// *pBeg++ = *pBeg1++; +// while ( pBeg2 < pEnd2 ) +// *pBeg++ = *pBeg2++; + vArr->nSize = pBeg - (Aig_Obj_t **)vArr->pArray; + assert( vArr->nSize <= vArr->nCap ); + assert( vArr->nSize <= vArr1->nSize ); + assert( vArr->nSize <= vArr2->nSize ); +} + +ABC_NAMESPACE_IMPL_END + +#include "proof/fra/fra.h" +#include "aig/saig/saig.h" + +ABC_NAMESPACE_IMPL_START + + +extern void Aig_ManCounterExampleValueStart( Aig_Man_t * pAig, Abc_Cex_t * pCex ); +extern void Aig_ManCounterExampleValueStop( Aig_Man_t * pAig ); +extern int Aig_ManCounterExampleValueLookup( Aig_Man_t * pAig, int Id, int iFrame ); + +/**Function************************************************************* + + Synopsis [Starts the process of retuning values for internal nodes.] + + Description [Should be called when pCex is available, before probing + any object for its value using Aig_ManCounterExampleValueLookup().] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManCounterExampleValueStart( Aig_Man_t * pAig, Abc_Cex_t * pCex ) +{ + Aig_Obj_t * pObj, * pObjRi, * pObjRo; + int Val0, Val1, nObjs, i, k, iBit = 0; + assert( Aig_ManRegNum(pAig) > 0 ); // makes sense only for sequential AIGs + assert( pAig->pData2 == NULL ); // if this fail, there may be a memory leak + // allocate memory to store simulation bits for internal nodes + pAig->pData2 = ABC_CALLOC( unsigned, Abc_BitWordNum( (pCex->iFrame + 1) * Aig_ManObjNumMax(pAig) ) ); + // the register values in the counter-example should be zero + Saig_ManForEachLo( pAig, pObj, k ) + assert( Abc_InfoHasBit(pCex->pData, iBit) == 0 ), iBit++; + // iterate through the timeframes + nObjs = Aig_ManObjNumMax(pAig); + for ( i = 0; i <= pCex->iFrame; i++ ) + { + // set constant 1 node + Abc_InfoSetBit( (unsigned *)pAig->pData2, nObjs * i + 0 ); + // set primary inputs according to the counter-example + Saig_ManForEachPi( pAig, pObj, k ) + if ( Abc_InfoHasBit(pCex->pData, iBit++) ) + Abc_InfoSetBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjId(pObj) ); + // compute values for each node + Aig_ManForEachNode( pAig, pObj, k ) + { + Val0 = Abc_InfoHasBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjFaninId0(pObj) ); + Val1 = Abc_InfoHasBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjFaninId1(pObj) ); + if ( (Val0 ^ Aig_ObjFaninC0(pObj)) & (Val1 ^ Aig_ObjFaninC1(pObj)) ) + Abc_InfoSetBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjId(pObj) ); + } + // derive values for combinational outputs + Aig_ManForEachCo( pAig, pObj, k ) + { + Val0 = Abc_InfoHasBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjFaninId0(pObj) ); + if ( Val0 ^ Aig_ObjFaninC0(pObj) ) + Abc_InfoSetBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjId(pObj) ); + } + if ( i == pCex->iFrame ) + continue; + // transfer values to the register output of the next frame + Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k ) + if ( Abc_InfoHasBit( (unsigned *)pAig->pData2, nObjs * i + Aig_ObjId(pObjRi) ) ) + Abc_InfoSetBit( (unsigned *)pAig->pData2, nObjs * (i+1) + Aig_ObjId(pObjRo) ); + } + assert( iBit == pCex->nBits ); + // check that the counter-example is correct, that is, the corresponding output is asserted + assert( Abc_InfoHasBit( (unsigned *)pAig->pData2, nObjs * pCex->iFrame + Aig_ObjId(Aig_ManCo(pAig, pCex->iPo)) ) ); +} + +/**Function************************************************************* + + Synopsis [Stops the process of retuning values for internal nodes.] + + Description [Should be called when probing is no longer needed] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManCounterExampleValueStop( Aig_Man_t * pAig ) +{ + assert( pAig->pData2 != NULL ); // if this fail, we try to call this procedure more than once + free( pAig->pData2 ); + pAig->pData2 = NULL; +} + +/**Function************************************************************* + + Synopsis [Returns the value of the given object in the given timeframe.] + + Description [Should be called to probe the value of an object with + the given ID (iFrame is a 0-based number of a time frame - should not + exceed the number of timeframes in the original counter-example).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManCounterExampleValueLookup( Aig_Man_t * pAig, int Id, int iFrame ) +{ + assert( Id >= 0 && Id < Aig_ManObjNumMax(pAig) ); + return Abc_InfoHasBit( (unsigned *)pAig->pData2, Aig_ManObjNumMax(pAig) * iFrame + Id ); +} + +/**Function************************************************************* + + Synopsis [Procedure to test the above code.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManCounterExampleValueTest( Aig_Man_t * pAig, Abc_Cex_t * pCex ) +{ + Aig_Obj_t * pObj = Aig_ManObj( pAig, Aig_ManObjNumMax(pAig)/2 ); + int iFrame = Abc_MaxInt( 0, pCex->iFrame - 1 ); + printf( "\nUsing counter-example, which asserts output %d in frame %d.\n", pCex->iPo, pCex->iFrame ); + Aig_ManCounterExampleValueStart( pAig, pCex ); + printf( "Value of object %d in frame %d is %d.\n", Aig_ObjId(pObj), iFrame, + Aig_ManCounterExampleValueLookup(pAig, Aig_ObjId(pObj), iFrame) ); + Aig_ManCounterExampleValueStop( pAig ); +} + +/**Function************************************************************* + + Synopsis [Handle the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManSetPhase( Aig_Man_t * pAig ) +{ + Aig_Obj_t * pObj; + int i; + // set the PI simulation information + Aig_ManConst1( pAig )->fPhase = 1; + Aig_ManForEachCi( pAig, pObj, i ) + pObj->fPhase = 0; + // simulate internal nodes + Aig_ManForEachNode( pAig, pObj, i ) + pObj->fPhase = ( Aig_ObjFanin0(pObj)->fPhase ^ Aig_ObjFaninC0(pObj) ) + & ( Aig_ObjFanin1(pObj)->fPhase ^ Aig_ObjFaninC1(pObj) ); + // simulate PO nodes + Aig_ManForEachCo( pAig, pObj, i ) + pObj->fPhase = Aig_ObjFanin0(pObj)->fPhase ^ Aig_ObjFaninC0(pObj); +} + + +/**Function************************************************************* + + Synopsis [Collects muxes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Aig_ManMuxesCollect( Aig_Man_t * pAig ) +{ + Vec_Ptr_t * vMuxes; + Aig_Obj_t * pObj; + int i; + vMuxes = Vec_PtrAlloc( 100 ); + Aig_ManForEachNode( pAig, pObj, i ) + if ( Aig_ObjIsMuxType(pObj) ) + Vec_PtrPush( vMuxes, pObj ); + return vMuxes; +} + +/**Function************************************************************* + + Synopsis [Dereferences muxes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManMuxesDeref( Aig_Man_t * pAig, Vec_Ptr_t * vMuxes ) +{ + Aig_Obj_t * pObj, * pNodeT, * pNodeE, * pNodeC; + int i; + Vec_PtrForEachEntry( Aig_Obj_t *, vMuxes, pObj, i ) + { + if ( Aig_ObjRecognizeExor( pObj, &pNodeT, &pNodeE ) ) + { + pNodeT->nRefs--; + pNodeE->nRefs--; + } + else + { + pNodeC = Aig_ObjRecognizeMux( pObj, &pNodeT, &pNodeE ); + pNodeC->nRefs--; + } + } +} + +/**Function************************************************************* + + Synopsis [References muxes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManMuxesRef( Aig_Man_t * pAig, Vec_Ptr_t * vMuxes ) +{ + Aig_Obj_t * pObj, * pNodeT, * pNodeE, * pNodeC; + int i; + Vec_PtrForEachEntry( Aig_Obj_t *, vMuxes, pObj, i ) + { + if ( Aig_ObjRecognizeExor( pObj, &pNodeT, &pNodeE ) ) + { + pNodeT->nRefs++; + pNodeE->nRefs++; + } + else + { + pNodeC = Aig_ObjRecognizeMux( pObj, &pNodeT, &pNodeE ); + pNodeC->nRefs++; + } + } +} + +/**Function************************************************************* + + Synopsis [Complements the constraint outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManInvertConstraints( Aig_Man_t * pAig ) +{ + Aig_Obj_t * pObj; + int i; + if ( Aig_ManConstrNum(pAig) == 0 ) + return; + Saig_ManForEachPo( pAig, pObj, i ) + { + if ( i >= Saig_ManPoNum(pAig) - Aig_ManConstrNum(pAig) ) + Aig_ObjChild0Flip( pObj ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aigWin.c b/yosys/abc/src/aig/aig/aigWin.c new file mode 100644 index 00000000000..cc179267074 --- /dev/null +++ b/yosys/abc/src/aig/aig/aigWin.c @@ -0,0 +1,189 @@ +/**CFile**************************************************************** + + FileName [aigWin.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Window computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigWin.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Evaluate the cost of removing the node from the set of leaves.] + + Description [Returns the number of new leaves that will be brought in. + Returns large number if the node cannot be removed from the set of leaves.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_NodeGetLeafCostOne( Aig_Obj_t * pNode, int nFanoutLimit ) +{ + int Cost; + // make sure the node is in the construction zone + assert( pNode->fMarkA ); + // cannot expand over the PI node + if ( Aig_ObjIsCi(pNode) ) + return 999; + // get the cost of the cone + Cost = (!Aig_ObjFanin0(pNode)->fMarkA) + (!Aig_ObjFanin1(pNode)->fMarkA); + // always accept if the number of leaves does not increase + if ( Cost < 2 ) + return Cost; + // skip nodes with many fanouts + if ( (int)pNode->nRefs > nFanoutLimit ) + return 999; + // return the number of nodes that will be on the leaves if this node is removed + return Cost; +} + +/**Function************************************************************* + + Synopsis [Builds reconvergence-driven cut by changing one leaf at a time.] + + Description [This procedure looks at the current leaves and tries to change + one leaf at a time in such a way that the cut grows as little as possible. + In evaluating the fanins, this procedure looks only at their immediate + predecessors (this is why it is called a one-level construction procedure).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_ManFindCut_int( Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited, int nSizeLimit, int nFanoutLimit ) +{ + Aig_Obj_t * pNode, * pFaninBest, * pNext; + int CostBest, CostCur, i; + // find the best fanin + CostBest = 100; + pFaninBest = NULL; +//printf( "Evaluating fanins of the cut:\n" ); + Vec_PtrForEachEntry( Aig_Obj_t *, vFront, pNode, i ) + { + CostCur = Aig_NodeGetLeafCostOne( pNode, nFanoutLimit ); +//printf( " Fanin %s has cost %d.\n", Aig_ObjName(pNode), CostCur ); + if ( CostBest > CostCur || + (CostBest == CostCur && pNode->Level > pFaninBest->Level) ) + { + CostBest = CostCur; + pFaninBest = pNode; + } + if ( CostBest == 0 ) + break; + } + if ( pFaninBest == NULL ) + return 0; + assert( CostBest < 3 ); + if ( Vec_PtrSize(vFront) - 1 + CostBest > nSizeLimit ) + return 0; + assert( Aig_ObjIsNode(pFaninBest) ); + // remove the node from the array + Vec_PtrRemove( vFront, pFaninBest ); +//printf( "Removing fanin %s.\n", Aig_ObjName(pFaninBest) ); + + // add the left child to the fanins + pNext = Aig_ObjFanin0(pFaninBest); + if ( !pNext->fMarkA ) + { +//printf( "Adding fanin %s.\n", Aig_ObjName(pNext) ); + pNext->fMarkA = 1; + Vec_PtrPush( vFront, pNext ); + Vec_PtrPush( vVisited, pNext ); + } + // add the right child to the fanins + pNext = Aig_ObjFanin1(pFaninBest); + if ( !pNext->fMarkA ) + { +//printf( "Adding fanin %s.\n", Aig_ObjName(pNext) ); + pNext->fMarkA = 1; + Vec_PtrPush( vFront, pNext ); + Vec_PtrPush( vVisited, pNext ); + } + assert( Vec_PtrSize(vFront) <= nSizeLimit ); + // keep doing this + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes one sequential cut of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManFindCut( Aig_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vVisited, int nSizeLimit, int nFanoutLimit ) +{ + Aig_Obj_t * pNode; + int i; + + assert( !Aig_IsComplement(pRoot) ); + assert( Aig_ObjIsNode(pRoot) ); + assert( Aig_ObjChild0(pRoot) ); + assert( Aig_ObjChild1(pRoot) ); + + // start the cut + Vec_PtrClear( vFront ); + Vec_PtrPush( vFront, Aig_ObjFanin0(pRoot) ); + Vec_PtrPush( vFront, Aig_ObjFanin1(pRoot) ); + + // start the visited nodes + Vec_PtrClear( vVisited ); + Vec_PtrPush( vVisited, pRoot ); + Vec_PtrPush( vVisited, Aig_ObjFanin0(pRoot) ); + Vec_PtrPush( vVisited, Aig_ObjFanin1(pRoot) ); + + // mark these nodes + assert( !pRoot->fMarkA ); + assert( !Aig_ObjFanin0(pRoot)->fMarkA ); + assert( !Aig_ObjFanin1(pRoot)->fMarkA ); + pRoot->fMarkA = 1; + Aig_ObjFanin0(pRoot)->fMarkA = 1; + Aig_ObjFanin1(pRoot)->fMarkA = 1; + + // compute the cut + while ( Aig_ManFindCut_int( vFront, vVisited, nSizeLimit, nFanoutLimit ) ); + assert( Vec_PtrSize(vFront) <= nSizeLimit ); + + // clean the visit markings + Vec_PtrForEachEntry( Aig_Obj_t *, vVisited, pNode, i ) + pNode->fMarkA = 0; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/aig_.c b/yosys/abc/src/aig/aig/aig_.c new file mode 100644 index 00000000000..ae0cb568619 --- /dev/null +++ b/yosys/abc/src/aig/aig/aig_.c @@ -0,0 +1,53 @@ +/**CFile**************************************************************** + + FileName [aig_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aig_.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/aig/module.make b/yosys/abc/src/aig/aig/module.make new file mode 100644 index 00000000000..c291433ffa1 --- /dev/null +++ b/yosys/abc/src/aig/aig/module.make @@ -0,0 +1,31 @@ +SRC += src/aig/aig/aigCheck.c \ + src/aig/aig/aigCanon.c \ + src/aig/aig/aigCuts.c \ + src/aig/aig/aigDfs.c \ + src/aig/aig/aigDup.c \ + src/aig/aig/aigFanout.c \ + src/aig/aig/aigFrames.c \ + src/aig/aig/aigInter.c \ + src/aig/aig/aigJust.c \ + src/aig/aig/aigMan.c \ + src/aig/aig/aigMem.c \ + src/aig/aig/aigMffc.c \ + src/aig/aig/aigObj.c \ + src/aig/aig/aigOper.c \ + src/aig/aig/aigOrder.c \ + src/aig/aig/aigPack.c \ + src/aig/aig/aigPart.c \ + src/aig/aig/aigPartReg.c \ + src/aig/aig/aigPartSat.c \ + src/aig/aig/aigRepr.c \ + src/aig/aig/aigRet.c \ + src/aig/aig/aigRetF.c \ + src/aig/aig/aigScl.c \ + src/aig/aig/aigShow.c \ + src/aig/aig/aigSplit.c \ + src/aig/aig/aigTable.c \ + src/aig/aig/aigTiming.c \ + src/aig/aig/aigTruth.c \ + src/aig/aig/aigTsim.c \ + src/aig/aig/aigUtil.c \ + src/aig/aig/aigWin.c \ No newline at end of file diff --git a/yosys/abc/src/aig/gia/gia.c b/yosys/abc/src/aig/gia/gia.c new file mode 100644 index 00000000000..ed6e276ac98 --- /dev/null +++ b/yosys/abc/src/aig/gia/gia.c @@ -0,0 +1,402 @@ +/**CFile**************************************************************** + + FileName [gia.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/util/utilTruth.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Slv_Man_t_ Slv_Man_t; +struct Slv_Man_t_ +{ + Vec_Int_t vCis; + Vec_Int_t vCos; + Vec_Int_t vFanins; + Vec_Int_t vFanoutN; + Vec_Int_t vFanout0; + Vec_Str_t vValues; + Vec_Int_t vCopies; +}; + +static inline int Slv_ManObjNum ( Slv_Man_t * p ) { return Vec_IntSize(&p->vFanins)/2; } + +static inline int Slv_ObjFaninLit ( Slv_Man_t * p, int iObj, int f ) { return Vec_IntEntry(&p->vFanins, Abc_Var2Lit(iObj, f)); } +static inline int Slv_ObjFanin ( Slv_Man_t * p, int iObj, int f ) { return Abc_Lit2Var(Slv_ObjFaninLit(p, iObj, f)); } +static inline int Slv_ObjFaninC ( Slv_Man_t * p, int iObj, int f ) { return Abc_LitIsCompl(Slv_ObjFaninLit(p, iObj, f)); } + +static inline int Slv_ObjIsCi ( Slv_Man_t * p, int iObj ) { return !Slv_ObjFaninLit(p, iObj, 0) && Slv_ObjFaninLit(p, iObj, 1); } +static inline int Slv_ObjIsCo ( Slv_Man_t * p, int iObj ) { return Slv_ObjFaninLit(p, iObj, 0) && !Slv_ObjFaninLit(p, iObj, 1); } +static inline int Slv_ObjIsAnd ( Slv_Man_t * p, int iObj ) { return Slv_ObjFaninLit(p, iObj, 0) && Slv_ObjFaninLit(p, iObj, 1); } + +static inline int Slv_ObjFanout0 ( Slv_Man_t * p, int iObj ) { return Vec_IntEntry(&p->vFanout0, iObj); } +static inline void Slv_ObjSetFanout0 ( Slv_Man_t * p, int iObj, int iLit ) { Vec_IntWriteEntry(&p->vFanout0, iObj, iLit); } + +static inline int Slv_ObjNextFanout ( Slv_Man_t * p, int iLit ) { return Vec_IntEntry(&p->vFanoutN, iLit); } +static inline void Slv_ObjSetNextFanout( Slv_Man_t * p, int iLit, int iLitF ) { Vec_IntWriteEntry(&p->vFanoutN, iLit, iLitF); } + +static inline int Slv_ObjCopyLit ( Slv_Man_t * p, int iObj ) { return Vec_IntEntry(&p->vCopies, iObj); } +static inline void Slv_ObjSetCopyLit ( Slv_Man_t * p, int iObj, int iLit ) { Vec_IntWriteEntry(&p->vCopies, iObj, iLit); } + +#define Slv_ManForEachObj( p, iObj ) \ + for ( iObj = 1; iObj < Slv_ManObjNum(p); iObj++ ) + +#define Slv_ObjForEachFanout( p, iObj, iFanLit ) \ + for ( iFanLit = Slv_ObjFanout0(p, iObj); iFanLit; iFanLit = Slv_ObjNextFanout(p, iFanLit) ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Slv_Man_t * Slv_ManAlloc( int nObjs ) +{ + Slv_Man_t * p = ABC_CALLOC( Slv_Man_t, 1 ); + Vec_IntGrow( &p->vCis, 100 ); + Vec_IntGrow( &p->vCos, 100 ); + Vec_IntGrow( &p->vFanins, 2*nObjs ); + Vec_IntGrow( &p->vFanoutN, 2*nObjs ); + Vec_IntGrow( &p->vFanout0, nObjs ); + Vec_StrGrow( &p->vValues, nObjs ); + // constant node + Vec_IntFill( &p->vFanins, 2, 0 ); + Vec_IntFill( &p->vFanoutN, 2, 0 ); + Vec_IntFill( &p->vFanout0, 1, 0 ); + return p; +} +void Slv_ManFree( Slv_Man_t * p ) +{ + Vec_IntErase( &p->vCis ); + Vec_IntErase( &p->vCos ); + Vec_IntErase( &p->vFanins ); + Vec_IntErase( &p->vFanoutN ); + Vec_IntErase( &p->vFanout0 ); + Vec_StrErase( &p->vValues ); + Vec_IntErase( &p->vCopies ); + ABC_FREE( p ); +} +void Slv_ManPrintFanouts( Slv_Man_t * p ) +{ + int iObj, iFanLit; + Slv_ManForEachObj( p, iObj ) + { + printf( "Fanouts of node %d: ", iObj ); + Slv_ObjForEachFanout( p, iObj, iFanLit ) + printf( "%d ", Abc_Lit2Var(iFanLit) ); + printf( "\n" ); + } +} +static inline int Slv_ManAppendObj( Slv_Man_t * p, int iLit0, int iLit1 ) +{ + int iObj = Slv_ManObjNum(p); + Vec_StrPush( &p->vValues, 0 ); + Vec_IntPush( &p->vFanout0, 0 ); + Vec_IntPushTwo( &p->vFanoutN, 0, 0 ); + if ( !iLit0 ) // primary input + assert(!iLit1), iLit1 = Vec_IntSize(&p->vCis)+1, Vec_IntPush(&p->vCis, iObj); + else if ( !iLit1 ) // primary output + assert(iLit0), Vec_IntPush(&p->vCos, iObj); + else + { + Slv_ObjSetNextFanout( p, Abc_Var2Lit(iObj, 0), Slv_ObjFanout0(p, Abc_Lit2Var(iLit0)) ); + Slv_ObjSetNextFanout( p, Abc_Var2Lit(iObj, 1), Slv_ObjFanout0(p, Abc_Lit2Var(iLit1)) ); + Slv_ObjSetFanout0( p, Abc_Lit2Var(iLit0), Abc_Var2Lit(iObj, 0) ); + Slv_ObjSetFanout0( p, Abc_Lit2Var(iLit1), Abc_Var2Lit(iObj, 1) ); + } + Vec_IntPushTwo( &p->vFanins, iLit0, iLit1 ); + return Abc_Var2Lit( iObj, 0 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Slv_Man_t * Slv_ManFromGia( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; int i; + Slv_Man_t * pNew = Slv_ManAlloc( Gia_ManObjNum(p) ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Slv_ManAppendObj( pNew, Abc_LitNotCond(Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj)), Abc_LitNotCond(Gia_ObjFanin1(pObj)->Value, Gia_ObjFaninC1(pObj)) ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Slv_ManAppendObj( pNew, Abc_LitNotCond(Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj)), 0 ); + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Slv_ManAppendObj( pNew, 0, 0 ); + else + assert( 0 ); + } + assert( Gia_ManObjNum(p) == Slv_ManObjNum(pNew) ); + return pNew; +} +Gia_Man_t * Slv_ManToGia( Slv_Man_t * p ) +{ + int iObj; + Gia_Man_t * pNew = Gia_ManStart( Slv_ManObjNum(p) ); + Vec_IntFill( &p->vCopies, Slv_ManObjNum(p), 0 ); + Slv_ManForEachObj( p, iObj ) + if ( Slv_ObjIsCi(p, iObj) ) + Slv_ObjSetCopyLit( p, iObj, Gia_ManAppendCi(pNew) ); + else if ( Slv_ObjIsCo(p, iObj) ) + { + int iLit0 = Abc_LitNotCond( Slv_ObjCopyLit(p, Slv_ObjFanin(p, iObj, 0)), Slv_ObjFaninC(p, iObj, 0) ); + Slv_ObjSetCopyLit( p, iObj, Gia_ManAppendCo(pNew, iLit0) ); + } + else if ( Slv_ObjIsAnd(p, iObj) ) + { + int iLit0 = Abc_LitNotCond( Slv_ObjCopyLit(p, Slv_ObjFanin(p, iObj, 0)), Slv_ObjFaninC(p, iObj, 0) ); + int iLit1 = Abc_LitNotCond( Slv_ObjCopyLit(p, Slv_ObjFanin(p, iObj, 1)), Slv_ObjFaninC(p, iObj, 1) ); + Slv_ObjSetCopyLit( p, iObj, Gia_ManAppendAnd(pNew, iLit0, iLit1) ); + } + else assert(0); + assert( Gia_ManObjNum(pNew) == Slv_ManObjNum(p) ); + return pNew; +} + +Gia_Man_t * Slv_ManToAig( Gia_Man_t * pGia ) +{ + Slv_Man_t * p = Slv_ManFromGia( pGia ); + Gia_Man_t * pNew = Slv_ManToGia( p ); + pNew->pName = Abc_UtilStrsav( pGia->pName ); + pNew->pSpec = Abc_UtilStrsav( pGia->pSpec ); + Slv_ManPrintFanouts( p ); + Slv_ManFree( p ); + return pNew; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManCofPisVars( Gia_Man_t * p, int nVars ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; int i, m; + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManForEachPi( p, pObj, i ) + Gia_ManAppendCi( pNew ); + Gia_ManHashStart( pNew ); + for ( m = 0; m < (1 << nVars); m++ ) + { + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachPi( p, pObj, i ) + { + if ( i < nVars ) + pObj->Value = (m >> i) & 1; + else + pObj->Value = Gia_ObjToLit(pNew, Gia_ManCi(pNew, i)); + } + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachPo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManStructExperiment( Gia_Man_t * p ) +{ + extern int Cec_ManVerifyTwo( Gia_Man_t * p0, Gia_Man_t * p1, int fVerbose ); + Gia_Man_t * pTemp, * pUsed; + Vec_Ptr_t * vGias = Vec_PtrAlloc( 100 ); + Gia_Obj_t * pObj; int i, k; + Gia_ManForEachCo( p, pObj, i ) + { + int iFan0 = Gia_ObjFaninId0p(p, pObj); + pTemp = Gia_ManDupAndCones( p, &iFan0, 1, 1 ); + Vec_PtrForEachEntry( Gia_Man_t *, vGias, pUsed, k ) + if ( Gia_ManCiNum(pTemp) == Gia_ManCiNum(pUsed) && Cec_ManVerifyTwo(pTemp, pUsed, 0) == 1 ) + { + ABC_SWAP( void *, Vec_PtrArray(vGias)[0], Vec_PtrArray(vGias)[k] ); + break; + } + else + ABC_FREE( pTemp->pCexComb ); + + printf( "\nOut %6d : ", i ); + if ( k == Vec_PtrSize(vGias) ) + printf( "Equiv to none " ); + else + printf( "Equiv to %6d ", k ); + Gia_ManPrintStats( pTemp, NULL ); + + if ( k == Vec_PtrSize(vGias) ) + Vec_PtrPush( vGias, pTemp ); + else + Gia_ManStop( pTemp ); + } + printf( "\nComputed %d classes.\n\n", Vec_PtrSize(vGias) ); + Vec_PtrForEachEntry( Gia_Man_t *, vGias, pTemp, i ) + Gia_ManStop( pTemp ); + Vec_PtrFree( vGias ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_EnumFirstUnused( int * pUsed, int nVars ) +{ + int i; + for ( i = 0; i < nVars; i++ ) + if ( pUsed[i] == 0 ) + return i; + return -1; +} +void Gia_EnumPerms_rec( int * pUsed, int nVars, int * pPerm, int nPerm, int * pCount, FILE * pFile, int nLogVars ) +{ + int i, k, New; + if ( nPerm == nVars ) + { + if ( pFile ) + { + for ( i = 0; i < nLogVars; i++ ) + fprintf( pFile, "%c", '0' + ((*pCount) >> (nLogVars-1-i) & 1) ); + fprintf( pFile, " " ); + for ( i = 0; i < nVars; i++ ) + for ( k = 0; k < nVars; k++ ) + fprintf( pFile, "%c", '0' + (pPerm[i] == k) ); + fprintf( pFile, "\n" ); + } + else + { + if ( *pCount < 20 ) + { + printf( "%5d : ", (*pCount) ); + for ( i = 0; i < nVars; i += 2 ) + printf( "%d %d ", pPerm[i], pPerm[i+1] ); + printf( "\n" ); + } + } + (*pCount)++; + return; + } + New = Gia_EnumFirstUnused( pUsed, nVars ); + assert( New >= 0 ); + pPerm[nPerm] = New; + assert( pUsed[New] == 0 ); + pUsed[New] = 1; + // try remaining ones + for ( i = 0; i < nVars; i++ ) + { + if ( pUsed[i] == 1 ) + continue; + pPerm[nPerm+1] = i; + assert( pUsed[i] == 0 ); + pUsed[i] = 1; + Gia_EnumPerms_rec( pUsed, nVars, pPerm, nPerm+2, pCount, pFile, nLogVars ); + assert( pUsed[i] == 1 ); + pUsed[i] = 0; + } + assert( pUsed[New] == 1 ); + pUsed[New] = 0; +} +void Gia_EnumPerms( int nVars ) +{ + int nLogVars = 0, Count = 0; + int * pUsed = ABC_CALLOC( int, nVars ); + int * pPerm = ABC_CALLOC( int, nVars ); + FILE * pFile = fopen( "pairset.pla", "wb" ); + assert( nVars % 2 == 0 ); + + printf( "Printing sets of pairs for %d objects:\n", nVars ); + Gia_EnumPerms_rec( pUsed, nVars, pPerm, 0, &Count, NULL, -1 ); + if ( Count > 20 ) + printf( "...\n" ); + printf( "Finished enumerating %d sets of pairs.\n", Count ); + + nLogVars = Abc_Base2Log( Count ); + printf( "Need %d variables to encode %d sets.\n", nLogVars, Count ); + Count = 0; + fprintf( pFile, ".i %d\n", nLogVars ); + fprintf( pFile, ".o %d\n", nVars*nVars ); + Gia_EnumPerms_rec( pUsed, nVars, pPerm, 0, &Count, pFile, nLogVars ); + fprintf( pFile, ".e\n" ); + fclose( pFile ); + printf( "Finished dumping file \"%s\".\n", "pairset.pla" ); + + ABC_FREE( pUsed ); + ABC_FREE( pPerm ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/gia.h b/yosys/abc/src/aig/gia/gia.h new file mode 100644 index 00000000000..273c530eca1 --- /dev/null +++ b/yosys/abc/src/aig/gia/gia.h @@ -0,0 +1,1865 @@ +/**CFile**************************************************************** + + FileName [gia.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: gia.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__gia__gia_h +#define ABC__aig__gia__gia_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#include "misc/vec/vec.h" +#include "misc/vec/vecWec.h" +#include "misc/util/utilCex.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_HEADER_START + +#define GIA_NONE 0x1FFFFFFF +#define GIA_VOID 0x0FFFFFFF + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Gia_MmFixed_t_ Gia_MmFixed_t; +typedef struct Gia_MmFlex_t_ Gia_MmFlex_t; +typedef struct Gia_MmStep_t_ Gia_MmStep_t; +typedef struct Gia_Dat_t_ Gia_Dat_t; + +typedef struct Gia_Rpr_t_ Gia_Rpr_t; +struct Gia_Rpr_t_ +{ + unsigned iRepr : 28; // representative node + unsigned fProved : 1; // marks the proved equivalence + unsigned fFailed : 1; // marks the failed equivalence + unsigned fColorA : 1; // marks cone of A + unsigned fColorB : 1; // marks cone of B +}; + +typedef struct Gia_Plc_t_ Gia_Plc_t; +struct Gia_Plc_t_ +{ + unsigned fFixed : 1; // the placement of this object is fixed + unsigned xCoord : 15; // x-ooordinate of the placement + unsigned fUndef : 1; // the placement of this object is not assigned + unsigned yCoord : 15; // y-ooordinate of the placement +}; + +typedef struct Gia_Obj_t_ Gia_Obj_t; +struct Gia_Obj_t_ +{ + unsigned iDiff0 : 29; // the diff of the first fanin + unsigned fCompl0: 1; // the complemented attribute + unsigned fMark0 : 1; // first user-controlled mark + unsigned fTerm : 1; // terminal node (CI/CO) + + unsigned iDiff1 : 29; // the diff of the second fanin + unsigned fCompl1: 1; // the complemented attribute + unsigned fMark1 : 1; // second user-controlled mark + unsigned fPhase : 1; // value under 000 pattern + + unsigned Value; // application-specific value +}; +// Value is currently used to store several types of information +// - pointer to the next node in the hash table during structural hashing +// - pointer to the node copy during duplication + +// new AIG manager +typedef struct Gia_Man_t_ Gia_Man_t; +struct Gia_Man_t_ +{ + char * pName; // name of the AIG + char * pSpec; // name of the input file + int nRegs; // number of registers + int nRegsAlloc; // number of allocated registers + int nObjs; // number of objects + int nObjsAlloc; // number of allocated objects + Gia_Obj_t * pObjs; // the array of objects + unsigned * pMuxes; // control signals of MUXes + int nXors; // the number of XORs + int nMuxes; // the number of MUXes + int nBufs; // the number of buffers + Vec_Int_t * vCis; // the vector of CIs (PIs + LOs) + Vec_Int_t * vCos; // the vector of COs (POs + LIs) + Vec_Int_t vHash; // hash links + Vec_Int_t vHTable; // hash table + int fAddStrash; // performs additional structural hashing + int fSweeper; // sweeper is running + int fGiaSimple; // simple mode (no const-propagation and strashing) + Vec_Int_t vRefs; // the reference count + int * pRefs; // the reference count + int * pLutRefs; // the reference count + Vec_Int_t * vLevels; // levels of the nodes + int nLevels; // the mamixum level + int nConstrs; // the number of constraints + int nTravIds; // the current traversal ID + int nFront; // frontier size + int * pReprsOld; // representatives (for CIs and ANDs) + Gia_Rpr_t * pReprs; // representatives (for CIs and ANDs) + int * pNexts; // next nodes in the equivalence classes + int * pSibls; // next nodes in the choice nodes + int * pIso; // pairs of structurally isomorphic nodes + int nTerLoop; // the state where loop begins + int nTerStates; // the total number of ternary states + int * pFanData; // the database to store fanout information + int nFansAlloc; // the size of fanout representation + Vec_Int_t * vFanoutNums; // static fanout + Vec_Int_t * vFanout; // static fanout + Vec_Int_t * vMapping; // mapping for each node + Vec_Wec_t * vMapping2; // mapping for each node + Vec_Wec_t * vFanouts2; // mapping fanouts + Vec_Int_t * vCellMapping; // mapping for each node + void * pSatlutWinman; // windowing for SAT-based mapping + Vec_Int_t * vPacking; // packing information + Vec_Int_t * vConfigs; // cell configurations + char * pCellStr; // cell description + Vec_Int_t * vLutConfigs; // LUT configurations + Vec_Int_t * vEdgeDelay; // special edge information + Vec_Int_t * vEdgeDelayR; // special edge information + Vec_Int_t * vEdge1; // special edge information + Vec_Int_t * vEdge2; // special edge information + Abc_Cex_t * pCexComb; // combinational counter-example + Abc_Cex_t * pCexSeq; // sequential counter-example + Vec_Ptr_t * vSeqModelVec; // sequential counter-examples + Vec_Int_t vCopies; // intermediate copies + Vec_Int_t vCopies2; // intermediate copies + Vec_Int_t * vVar2Obj; // mapping of variables into objects + Vec_Int_t * vTruths; // used for truth table computation + Vec_Int_t * vFlopClasses; // classes of flops for retiming/merging/etc + Vec_Int_t * vGateClasses; // classes of gates for abstraction + Vec_Int_t * vObjClasses; // classes of objects for abstraction + Vec_Int_t * vInitClasses; // classes of flops for retiming/merging/etc + Vec_Int_t * vRegClasses; // classes of registers for sequential synthesis + Vec_Int_t * vRegInits; // initial state + Vec_Int_t * vDoms; // dominators + Vec_Int_t * vBarBufs; // barrier buffers + Vec_Int_t * vXors; // temporary XORs + unsigned char* pSwitching; // switching activity for each object + Gia_Plc_t * pPlacement; // placement of the objects + Gia_Man_t * pAigExtra; // combinational logic of holes + Vec_Flt_t * vInArrs; // PI arrival times + Vec_Flt_t * vOutReqs; // PO required times + Vec_Int_t * vCiArrs; // CI arrival times + Vec_Int_t * vCoReqs; // CO required times + Vec_Int_t * vCoArrs; // CO arrival times + Vec_Int_t * vCoAttrs; // CO attributes + Vec_Int_t * vWeights; // object attributes + int And2Delay; // delay of the AND gate + float DefInArrs; // default PI arrival times + float DefOutReqs; // default PO required times + Vec_Int_t * vSwitching; // switching activity + int * pTravIds; // separate traversal ID representation + int nTravIdsAlloc; // the number of trav IDs allocated + Vec_Ptr_t * vNamesIn; // the input names + Vec_Ptr_t * vNamesOut; // the output names + Vec_Ptr_t * vNamesNode; // the node names + Vec_Int_t * vUserPiIds; // numbers assigned to PIs by the user + Vec_Int_t * vUserPoIds; // numbers assigned to POs by the user + Vec_Int_t * vUserFfIds; // numbers assigned to FFs by the user + Vec_Int_t * vCiNumsOrig; // original CI names + Vec_Int_t * vCoNumsOrig; // original CO names + Vec_Int_t * vIdsOrig; // original object IDs + Vec_Int_t * vIdsEquiv; // original object IDs proved equivalent + Vec_Int_t * vCofVars; // cofactoring variables + Vec_Vec_t * vClockDoms; // clock domains + Vec_Flt_t * vTiming; // arrival/required/slack + void * pManTime; // the timing manager + void * pLutLib; // LUT library + word nHashHit; // hash table hit + word nHashMiss; // hash table miss + void * pData; // various user data + unsigned * pData2; // various user data + int iData; // various user data + int iData2; // various user data + int nAnd2Delay; // AND2 delay scaled to match delay numbers used + int fVerbose; // verbose reports + int MappedArea; // area after mapping + int MappedDelay; // delay after mapping + // bit-parallel simulation + int fBuiltInSim; + int iPatsPi; + int nSimWords; + int nSimWordsT; + int iPastPiMax; + int nSimWordsMax; + Vec_Wrd_t * vSims; + Vec_Wrd_t * vSimsT; + Vec_Wrd_t * vSimsPi; + Vec_Wrd_t * vSimsPo; + Vec_Int_t * vClassOld; + Vec_Int_t * vClassNew; + Vec_Int_t * vPats; + Vec_Bit_t * vPolars; + // incremental simulation + int fIncrSim; + int iNextPi; + int iTimeStamp; + Vec_Int_t * vTimeStamps; + // truth table computation for small functions + int nTtVars; // truth table variables + int nTtWords; // truth table words + Vec_Int_t * vTtNums; // object numbers + Vec_Int_t * vTtNodes; // internal nodes + Vec_Ptr_t * vTtInputs; // truth tables for constant and primary inputs + Vec_Wrd_t * vTtMemory; // truth tables for internal nodes + // balancing + Vec_Int_t * vSuper; // supergate + Vec_Int_t * vStore; // node storage + // existential quantification + int iSuppPi; // the number of support variables + int nSuppWords; // the number of support words + Vec_Wrd_t * vSuppWords; // support information + Vec_Int_t vCopiesTwo; // intermediate copies + Vec_Int_t vSuppVars; // used variables + Vec_Int_t vVarMap; // used variables + Gia_Dat_t * pUData; + // retiming data + Vec_Str_t * vStopsF; + Vec_Str_t * vStopsB; + // iteration with boxes + int iFirstNonPiId; + int iFirstPoId; + int iFirstAndObj; + int iFirstPoObj; + Vec_Str_t * vTTISOPs; // truth tables from ISOP computation + Vec_Int_t * vTTLut; // truth tables from ISOP computation + Vec_Int_t * vMFFCsInfo; // MFFC information + Vec_Int_t * vMFFCsLuts; // MFFCs for each lut + Vec_Ptr_t * vLutsRankings; // LUTs rankings of inputs +}; + + +typedef struct Gps_Par_t_ Gps_Par_t; +struct Gps_Par_t_ +{ + int fTents; + int fSwitch; + int fCut; + int fNpn; + int fLutProf; + int fMuxXor; + int fMiter; + int fSkipMap; + int fSlacks; + int fNoColor; + char * pDumpFile; +}; + +typedef struct Emb_Par_t_ Emb_Par_t; +struct Emb_Par_t_ +{ + int nDims; // the number of dimension + int nSols; // the number of solutions (typically, 2) + int nIters; // the number of iterations of FORCE + int fRefine; // use refinement by FORCE + int fCluster; // use clustered representation + int fDump; // dump Gnuplot file + int fDumpLarge; // dump Gnuplot file for large benchmarks + int fShowImage; // shows image if Gnuplot is installed + int fVerbose; // verbose flag +}; + + +// frames parameters +typedef struct Gia_ParFra_t_ Gia_ParFra_t; +struct Gia_ParFra_t_ +{ + int nFrames; // the number of frames to unroll + int fInit; // initialize the timeframes + int fSaveLastLit; // adds POs for outputs of each frame + int fDisableSt; // disables strashing + int fOrPos; // ORs respective POs in each timeframe + int fVerbose; // enables verbose output +}; + + +// simulation parameters +typedef struct Gia_ParSim_t_ Gia_ParSim_t; +struct Gia_ParSim_t_ +{ + // user-controlled parameters + int nWords; // the number of machine words + int nIters; // the number of timeframes + int RandSeed; // seed to generate random numbers + int TimeLimit; // time limit in seconds + int fCheckMiter; // check if miter outputs are non-zero + int fVerbose; // enables verbose output + int iOutFail; // index of the failed output +}; + +typedef struct Gia_ManSim_t_ Gia_ManSim_t; +struct Gia_ManSim_t_ +{ + Gia_Man_t * pAig; + Gia_ParSim_t * pPars; + int nWords; + Vec_Int_t * vCis2Ids; + Vec_Int_t * vConsts; + // simulation information + unsigned * pDataSim; // simulation data + unsigned * pDataSimCis; // simulation data for CIs + unsigned * pDataSimCos; // simulation data for COs +}; + +typedef struct Jf_Par_t_ Jf_Par_t; +struct Jf_Par_t_ +{ + int nLutSize; + int nCutNum; + int nProcNum; + int nRounds; + int nRoundsEla; + int nRelaxRatio; + int nCoarseLimit; + int nAreaTuner; + int nReqTimeFlex; + int nVerbLimit; + int nDelayLut1; + int nDelayLut2; + int nFastEdges; + int DelayTarget; + int fAreaOnly; + int fPinPerm; + int fPinQuick; + int fPinFilter; + int fOptEdge; + int fUseMux7; + int fPower; + int fCoarsen; + int fCutMin; + int fFuncDsd; + int fGenCnf; + int fGenLit; + int fCnfObjIds; + int fAddOrCla; + int fCnfMapping; + int fPureAig; + int fDoAverage; + int fCutHashing; + int fCutSimple; + int fCutGroup; + int fVerbose; + int fVeryVerbose; + int nLutSizeMax; + int nCutNumMax; + int nProcNumMax; + int nLutSizeMux; + word Delay; + word Area; + word Edge; + word Clause; + word Mux7; + word WordMapDelay; + word WordMapArea; + word WordMapDelayTarget; + int MapDelay; + float MapArea; + float MapAreaF; + float MapDelayTarget; + float Epsilon; + float * pTimesArr; + float * pTimesReq; +}; + +static inline unsigned Gia_ObjCutSign( unsigned ObjId ) { return (1 << (ObjId & 31)); } +static inline int Gia_WordHasOneBit( unsigned uWord ) { return (uWord & (uWord-1)) == 0; } +static inline int Gia_WordHasOnePair( unsigned uWord ) { return Gia_WordHasOneBit(uWord & (uWord>>1) & 0x55555555); } +static inline int Gia_WordCountOnes( unsigned uWord ) +{ + uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555); + uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333); + uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F); + uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF); + return (uWord & 0x0000FFFF) + (uWord>>16); +} +static inline int Gia_WordFindFirstBit( unsigned uWord ) +{ + int i; + for ( i = 0; i < 32; i++ ) + if ( uWord & (1 << i) ) + return i; + return -1; +} + +static inline int Gia_ManTruthIsConst0( unsigned * pIn, int nVars ) +{ + int w; + for ( w = Abc_TruthWordNum(nVars)-1; w >= 0; w-- ) + if ( pIn[w] ) + return 0; + return 1; +} +static inline int Gia_ManTruthIsConst1( unsigned * pIn, int nVars ) +{ + int w; + for ( w = Abc_TruthWordNum(nVars)-1; w >= 0; w-- ) + if ( pIn[w] != ~(unsigned)0 ) + return 0; + return 1; +} +static inline void Gia_ManTruthCopy( unsigned * pOut, unsigned * pIn, int nVars ) +{ + int w; + for ( w = Abc_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = pIn[w]; +} +static inline void Gia_ManTruthClear( unsigned * pOut, int nVars ) +{ + int w; + for ( w = Abc_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = 0; +} +static inline void Gia_ManTruthFill( unsigned * pOut, int nVars ) +{ + int w; + for ( w = Abc_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = ~(unsigned)0; +} +static inline void Gia_ManTruthNot( unsigned * pOut, unsigned * pIn, int nVars ) +{ + int w; + for ( w = Abc_TruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = ~pIn[w]; +} + +static inline int Gia_ManConst0Lit() { return 0; } +static inline int Gia_ManConst1Lit() { return 1; } +static inline int Gia_ManIsConst0Lit( int iLit ) { return (iLit == 0); } +static inline int Gia_ManIsConst1Lit( int iLit ) { return (iLit == 1); } +static inline int Gia_ManIsConstLit( int iLit ) { return (iLit <= 1); } + +static inline Gia_Obj_t * Gia_Regular( Gia_Obj_t * p ) { return (Gia_Obj_t *)((ABC_PTRUINT_T)(p) & ~01); } +static inline Gia_Obj_t * Gia_Not( Gia_Obj_t * p ) { return (Gia_Obj_t *)((ABC_PTRUINT_T)(p) ^ 01); } +static inline Gia_Obj_t * Gia_NotCond( Gia_Obj_t * p, int c ) { return (Gia_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c)); } +static inline int Gia_IsComplement( Gia_Obj_t * p ) { return (int)((ABC_PTRUINT_T)(p) & 01); } + +static inline char * Gia_ManName( Gia_Man_t * p ) { return p->pName; } +static inline int Gia_ManCiNum( Gia_Man_t * p ) { return Vec_IntSize(p->vCis); } +static inline int Gia_ManCoNum( Gia_Man_t * p ) { return Vec_IntSize(p->vCos); } +static inline int Gia_ManPiNum( Gia_Man_t * p ) { return Vec_IntSize(p->vCis) - p->nRegs; } +static inline int Gia_ManPoNum( Gia_Man_t * p ) { return Vec_IntSize(p->vCos) - p->nRegs; } +static inline int Gia_ManRegNum( Gia_Man_t * p ) { return p->nRegs; } +static inline int Gia_ManObjNum( Gia_Man_t * p ) { return p->nObjs; } +static inline int Gia_ManAndNum( Gia_Man_t * p ) { return p->nObjs - Vec_IntSize(p->vCis) - Vec_IntSize(p->vCos) - 1; } +static inline int Gia_ManXorNum( Gia_Man_t * p ) { return p->nXors; } +static inline int Gia_ManMuxNum( Gia_Man_t * p ) { return p->nMuxes; } +static inline int Gia_ManBufNum( Gia_Man_t * p ) { return p->nBufs; } +static inline int Gia_ManAndNotBufNum( Gia_Man_t * p ){ return Gia_ManAndNum(p) - Gia_ManBufNum(p); } +static inline int Gia_ManCandNum( Gia_Man_t * p ) { return Gia_ManCiNum(p) + Gia_ManAndNum(p); } +static inline int Gia_ManConstrNum( Gia_Man_t * p ) { return p->nConstrs; } +static inline void Gia_ManFlipVerbose( Gia_Man_t * p ) { p->fVerbose ^= 1; } +static inline int Gia_ManHasChoices( Gia_Man_t * p ) { return p->pSibls != NULL; } +static inline int Gia_ManChoiceNum( Gia_Man_t * p ) { int c = 0; if (p->pSibls) { int i; for (i = 0; i < p->nObjs; i++) c += (int)(p->pSibls[i] > 0); } return c; } + +static inline Gia_Obj_t * Gia_ManConst0( Gia_Man_t * p ) { return p->pObjs; } +static inline Gia_Obj_t * Gia_ManConst1( Gia_Man_t * p ) { return Gia_Not(Gia_ManConst0(p)); } +static inline Gia_Obj_t * Gia_ManObj( Gia_Man_t * p, int v ) { assert( v >= 0 && v < p->nObjs ); return p->pObjs + v; } +static inline Gia_Obj_t * Gia_ManCi( Gia_Man_t * p, int v ) { return Gia_ManObj( p, Vec_IntEntry(p->vCis,v) ); } +static inline Gia_Obj_t * Gia_ManCo( Gia_Man_t * p, int v ) { return Gia_ManObj( p, Vec_IntEntry(p->vCos,v) ); } +static inline Gia_Obj_t * Gia_ManPi( Gia_Man_t * p, int v ) { assert( v < Gia_ManPiNum(p) ); return Gia_ManCi( p, v ); } +static inline Gia_Obj_t * Gia_ManPo( Gia_Man_t * p, int v ) { assert( v < Gia_ManPoNum(p) ); return Gia_ManCo( p, v ); } +static inline Gia_Obj_t * Gia_ManRo( Gia_Man_t * p, int v ) { assert( v < Gia_ManRegNum(p) ); return Gia_ManCi( p, Gia_ManPiNum(p)+v ); } +static inline Gia_Obj_t * Gia_ManRi( Gia_Man_t * p, int v ) { assert( v < Gia_ManRegNum(p) ); return Gia_ManCo( p, Gia_ManPoNum(p)+v ); } + +static inline int Gia_ObjId( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( p->pObjs <= pObj && pObj < p->pObjs + p->nObjs ); return pObj - p->pObjs; } +static inline int Gia_ObjCioId( Gia_Obj_t * pObj ) { assert( pObj->fTerm ); return pObj->iDiff1; } +static inline void Gia_ObjSetCioId( Gia_Obj_t * pObj, int v ) { assert( pObj->fTerm ); pObj->iDiff1 = v; } +static inline int Gia_ObjValue( Gia_Obj_t * pObj ) { return pObj->Value; } +static inline void Gia_ObjSetValue( Gia_Obj_t * pObj, int i ) { pObj->Value = i; } +static inline int Gia_ObjPhase( Gia_Obj_t * pObj ) { return pObj->fPhase; } +static inline int Gia_ObjPhaseReal( Gia_Obj_t * pObj ) { return Gia_Regular(pObj)->fPhase ^ Gia_IsComplement(pObj); } +static inline int Gia_ObjPhaseDiff( Gia_Man_t * p, int i, int k ) { return Gia_ManObj(p, i)->fPhase ^ Gia_ManObj(p, k)->fPhase; } +static inline char * Gia_ObjCiName( Gia_Man_t * p, int i ) { return p->vNamesIn ? (char*)Vec_PtrEntry(p->vNamesIn, i) : NULL; } +static inline char * Gia_ObjCoName( Gia_Man_t * p, int i ) { return p->vNamesOut ? (char*)Vec_PtrEntry(p->vNamesOut, i) : NULL; } +static inline char * Gia_ObjName( Gia_Man_t * p, int i ) { return p->vNamesNode ? (char*)Vec_PtrEntry(p->vNamesNode, i) : NULL; } +static inline char * Gia_ObjNameObj( Gia_Man_t * p, Gia_Obj_t * pObj ) { return p->vNamesNode ? (char*)Vec_PtrEntry(p->vNamesNode, Gia_ObjId(p, pObj)) : NULL; } + +static inline int Gia_ObjIsTerm( Gia_Obj_t * pObj ) { return pObj->fTerm; } +static inline int Gia_ObjIsAndOrConst0( Gia_Obj_t * pObj ) { return!pObj->fTerm; } +static inline int Gia_ObjIsCi( Gia_Obj_t * pObj ) { return pObj->fTerm && pObj->iDiff0 == GIA_NONE; } +static inline int Gia_ObjIsCo( Gia_Obj_t * pObj ) { return pObj->fTerm && pObj->iDiff0 != GIA_NONE; } +static inline int Gia_ObjIsAnd( Gia_Obj_t * pObj ) { return!pObj->fTerm && pObj->iDiff0 != GIA_NONE; } +static inline int Gia_ObjIsXor( Gia_Obj_t * pObj ) { return Gia_ObjIsAnd(pObj) && pObj->iDiff0 < pObj->iDiff1; } +static inline int Gia_ObjIsMuxId( Gia_Man_t * p, int iObj ) { return p->pMuxes && p->pMuxes[iObj] > 0; } +static inline int Gia_ObjIsMux( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjIsMuxId( p, Gia_ObjId(p, pObj) ); } +static inline int Gia_ObjIsAndReal( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjIsAnd(pObj) && pObj->iDiff0 > pObj->iDiff1 && !Gia_ObjIsMux(p, pObj); } +static inline int Gia_ObjIsBuf( Gia_Obj_t * pObj ) { return pObj->iDiff0 == pObj->iDiff1 && pObj->iDiff0 != GIA_NONE && !pObj->fTerm; } +static inline int Gia_ObjIsAndNotBuf( Gia_Obj_t * pObj ) { return Gia_ObjIsAnd(pObj) && pObj->iDiff0 != pObj->iDiff1; } +static inline int Gia_ObjIsCand( Gia_Obj_t * pObj ) { return Gia_ObjIsAnd(pObj) || Gia_ObjIsCi(pObj); } +static inline int Gia_ObjIsConst0( Gia_Obj_t * pObj ) { return pObj->iDiff0 == GIA_NONE && pObj->iDiff1 == GIA_NONE; } +static inline int Gia_ManObjIsConst0( Gia_Man_t * p, Gia_Obj_t * pObj){ return pObj == p->pObjs; } + +static inline int Gia_Obj2Lit( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Abc_Var2Lit(Gia_ObjId(p, Gia_Regular(pObj)), Gia_IsComplement(pObj)); } +static inline Gia_Obj_t * Gia_Lit2Obj( Gia_Man_t * p, int iLit ) { return Gia_NotCond(Gia_ManObj(p, Abc_Lit2Var(iLit)), Abc_LitIsCompl(iLit)); } +static inline int Gia_ManCiLit( Gia_Man_t * p, int CiId ) { return Gia_Obj2Lit( p, Gia_ManCi(p, CiId) ); } + +static inline int Gia_ManIdToCioId( Gia_Man_t * p, int Id ) { return Gia_ObjCioId( Gia_ManObj(p, Id) ); } +static inline int Gia_ManCiIdToId( Gia_Man_t * p, int CiId ) { return Gia_ObjId( p, Gia_ManCi(p, CiId) ); } +static inline int Gia_ManCoIdToId( Gia_Man_t * p, int CoId ) { return Gia_ObjId( p, Gia_ManCo(p, CoId) ); } + +static inline int Gia_ObjIsPi( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjIsCi(pObj) && Gia_ObjCioId(pObj) < Gia_ManPiNum(p); } +static inline int Gia_ObjIsPo( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjIsCo(pObj) && Gia_ObjCioId(pObj) < Gia_ManPoNum(p); } +static inline int Gia_ObjIsRo( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjIsCi(pObj) && Gia_ObjCioId(pObj) >= Gia_ManPiNum(p); } +static inline int Gia_ObjIsRi( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjIsCo(pObj) && Gia_ObjCioId(pObj) >= Gia_ManPoNum(p); } + +static inline Gia_Obj_t * Gia_ObjRoToRi( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsRo(p, pObj) ); return Gia_ManCo(p, Gia_ManCoNum(p) - Gia_ManCiNum(p) + Gia_ObjCioId(pObj)); } +static inline Gia_Obj_t * Gia_ObjRiToRo( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsRi(p, pObj) ); return Gia_ManCi(p, Gia_ManCiNum(p) - Gia_ManCoNum(p) + Gia_ObjCioId(pObj)); } +static inline int Gia_ObjRoToRiId( Gia_Man_t * p, int ObjId ) { return Gia_ObjId( p, Gia_ObjRoToRi( p, Gia_ManObj(p, ObjId) ) ); } +static inline int Gia_ObjRiToRoId( Gia_Man_t * p, int ObjId ) { return Gia_ObjId( p, Gia_ObjRiToRo( p, Gia_ManObj(p, ObjId) ) ); } + +static inline int Gia_ObjDiff0( Gia_Obj_t * pObj ) { return pObj->iDiff0; } +static inline int Gia_ObjDiff1( Gia_Obj_t * pObj ) { return pObj->iDiff1; } +static inline int Gia_ObjFaninC0( Gia_Obj_t * pObj ) { return pObj->fCompl0; } +static inline int Gia_ObjFaninC1( Gia_Obj_t * pObj ) { return pObj->fCompl1; } +static inline int Gia_ObjFaninC2( Gia_Man_t * p, Gia_Obj_t * pObj ) { return p->pMuxes && Abc_LitIsCompl(p->pMuxes[Gia_ObjId(p, pObj)]); } +static inline int Gia_ObjFaninC( Gia_Obj_t * pObj, int n ) { return n ? Gia_ObjFaninC1(pObj) : Gia_ObjFaninC0(pObj); } +static inline Gia_Obj_t * Gia_ObjFanin0( Gia_Obj_t * pObj ) { return pObj - pObj->iDiff0; } +static inline Gia_Obj_t * Gia_ObjFanin1( Gia_Obj_t * pObj ) { return pObj - pObj->iDiff1; } +static inline Gia_Obj_t * Gia_ObjFanin2( Gia_Man_t * p, Gia_Obj_t * pObj ) { return p->pMuxes ? Gia_ManObj(p, Abc_Lit2Var(p->pMuxes[Gia_ObjId(p, pObj)])) : NULL; } +static inline Gia_Obj_t * Gia_ObjFanin( Gia_Obj_t * pObj, int n ) { return n ? Gia_ObjFanin1(pObj) : Gia_ObjFanin0(pObj); } +static inline Gia_Obj_t * Gia_ObjChild0( Gia_Obj_t * pObj ) { return Gia_NotCond( Gia_ObjFanin0(pObj), Gia_ObjFaninC0(pObj) ); } +static inline Gia_Obj_t * Gia_ObjChild1( Gia_Obj_t * pObj ) { return Gia_NotCond( Gia_ObjFanin1(pObj), Gia_ObjFaninC1(pObj) ); } +static inline Gia_Obj_t * Gia_ObjChild2( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_NotCond( Gia_ObjFanin2(p, pObj), Gia_ObjFaninC2(p, pObj) ); } +static inline int Gia_ObjFaninId0( Gia_Obj_t * pObj, int ObjId ) { return ObjId - pObj->iDiff0; } +static inline int Gia_ObjFaninId1( Gia_Obj_t * pObj, int ObjId ) { return ObjId - pObj->iDiff1; } +static inline int Gia_ObjFaninId2( Gia_Man_t * p, int ObjId ) { return (p->pMuxes && p->pMuxes[ObjId]) ? Abc_Lit2Var(p->pMuxes[ObjId]) : -1; } +static inline int Gia_ObjFaninId( Gia_Obj_t * pObj, int ObjId, int n ){ return n ? Gia_ObjFaninId1(pObj, ObjId) : Gia_ObjFaninId0(pObj, ObjId); } +static inline int Gia_ObjFaninId0p( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjFaninId0( pObj, Gia_ObjId(p, pObj) ); } +static inline int Gia_ObjFaninId1p( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjFaninId1( pObj, Gia_ObjId(p, pObj) ); } +static inline int Gia_ObjFaninId2p( Gia_Man_t * p, Gia_Obj_t * pObj ) { return (p->pMuxes && p->pMuxes[Gia_ObjId(p, pObj)]) ? Abc_Lit2Var(p->pMuxes[Gia_ObjId(p, pObj)]) : -1; } +static inline int Gia_ObjFaninIdp( Gia_Man_t * p, Gia_Obj_t * pObj, int n){ return n ? Gia_ObjFaninId1p(p, pObj) : Gia_ObjFaninId0p(p, pObj); } +static inline int Gia_ObjFaninLit0( Gia_Obj_t * pObj, int ObjId ) { return Abc_Var2Lit( Gia_ObjFaninId0(pObj, ObjId), Gia_ObjFaninC0(pObj) ); } +static inline int Gia_ObjFaninLit1( Gia_Obj_t * pObj, int ObjId ) { return Abc_Var2Lit( Gia_ObjFaninId1(pObj, ObjId), Gia_ObjFaninC1(pObj) ); } +static inline int Gia_ObjFaninLit2( Gia_Man_t * p, int ObjId ) { return (p->pMuxes && p->pMuxes[ObjId]) ? p->pMuxes[ObjId] : -1; } +static inline int Gia_ObjFaninLit( Gia_Obj_t * pObj, int ObjId, int n ){ return n ? Gia_ObjFaninLit1(pObj, ObjId) : Gia_ObjFaninLit0(pObj, ObjId);} +static inline int Gia_ObjFaninLit0p( Gia_Man_t * p, Gia_Obj_t * pObj) { return Abc_Var2Lit( Gia_ObjFaninId0p(p, pObj), Gia_ObjFaninC0(pObj) ); } +static inline int Gia_ObjFaninLit1p( Gia_Man_t * p, Gia_Obj_t * pObj) { return Abc_Var2Lit( Gia_ObjFaninId1p(p, pObj), Gia_ObjFaninC1(pObj) ); } +static inline int Gia_ObjFaninLit2p( Gia_Man_t * p, Gia_Obj_t * pObj) { return (p->pMuxes && p->pMuxes[Gia_ObjId(p, pObj)]) ? p->pMuxes[Gia_ObjId(p, pObj)] : -1; } +static inline int Gia_ObjFaninLitp( Gia_Man_t * p, Gia_Obj_t * pObj, int n ){ return n ? Gia_ObjFaninLit1p(p, pObj) : Gia_ObjFaninLit0p(p, pObj);} +static inline void Gia_ObjFlipFaninC0( Gia_Obj_t * pObj ) { assert( Gia_ObjIsCo(pObj) ); pObj->fCompl0 ^= 1; } +static inline int Gia_ObjFaninNum( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( Gia_ObjIsMux(p, pObj) ) return 3; if ( Gia_ObjIsAnd(pObj) ) return 2; if ( Gia_ObjIsCo(pObj) ) return 1; return 0; } +static inline int Gia_ObjWhatFanin( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanin ) { if ( Gia_ObjFanin0(pObj) == pFanin ) return 0; if ( Gia_ObjFanin1(pObj) == pFanin ) return 1; if ( Gia_ObjFanin2(p, pObj) == pFanin ) return 2; assert(0); return -1; } + +static inline int Gia_ManCoDriverId( Gia_Man_t * p, int iCoIndex ) { return Gia_ObjFaninId0p(p, Gia_ManCo(p, iCoIndex)); } +static inline int Gia_ManPoIsConst( Gia_Man_t * p, int iPoIndex ) { return Gia_ObjFaninId0p(p, Gia_ManPo(p, iPoIndex)) == 0; } +static inline int Gia_ManPoIsConst0( Gia_Man_t * p, int iPoIndex ) { return Gia_ManIsConst0Lit( Gia_ObjFaninLit0p(p, Gia_ManPo(p, iPoIndex)) ); } +static inline int Gia_ManPoIsConst1( Gia_Man_t * p, int iPoIndex ) { return Gia_ManIsConst1Lit( Gia_ObjFaninLit0p(p, Gia_ManPo(p, iPoIndex)) ); } + +static inline Gia_Obj_t * Gia_ObjCopy( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ManObj( p, Abc_Lit2Var(pObj->Value) ); } +static inline int Gia_ObjLitCopy( Gia_Man_t * p, int iLit ) { return Abc_LitNotCond( Gia_ManObj(p, Abc_Lit2Var(iLit))->Value, Abc_LitIsCompl(iLit)); } + +static inline int Gia_ObjFanin0Copy( Gia_Obj_t * pObj ) { return Abc_LitNotCond( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) ); } +static inline int Gia_ObjFanin1Copy( Gia_Obj_t * pObj ) { return Abc_LitNotCond( Gia_ObjFanin1(pObj)->Value, Gia_ObjFaninC1(pObj) ); } +static inline int Gia_ObjFanin2Copy( Gia_Man_t * p, Gia_Obj_t * pObj ){ return Abc_LitNotCond(Gia_ObjFanin2(p, pObj)->Value, Gia_ObjFaninC2(p, pObj)); } + +static inline int Gia_ObjCopyF( Gia_Man_t * p, int f, Gia_Obj_t * pObj ) { return Vec_IntEntry(&p->vCopies, Gia_ManObjNum(p) * f + Gia_ObjId(p,pObj)); } +static inline void Gia_ObjSetCopyF( Gia_Man_t * p, int f, Gia_Obj_t * pObj, int iLit ) { Vec_IntWriteEntry(&p->vCopies, Gia_ManObjNum(p) * f + Gia_ObjId(p,pObj), iLit); } +static inline int Gia_ObjCopyArray( Gia_Man_t * p, int iObj ) { return Vec_IntEntry(&p->vCopies, iObj); } +static inline void Gia_ObjSetCopyArray( Gia_Man_t * p, int iObj, int iLit ) { Vec_IntWriteEntry(&p->vCopies, iObj, iLit); } +static inline void Gia_ManCleanCopyArray( Gia_Man_t * p ) { Vec_IntFill( &p->vCopies, Gia_ManObjNum(p), -1 ); } + +static inline int Gia_ObjCopy2Array( Gia_Man_t * p, int iObj ) { return Vec_IntEntry(&p->vCopies2, iObj); } +static inline void Gia_ObjSetCopy2Array( Gia_Man_t * p, int iObj, int iLit ) { Vec_IntWriteEntry(&p->vCopies2, iObj, iLit); } +static inline void Gia_ManCleanCopy2Array( Gia_Man_t * p ) { Vec_IntFill( &p->vCopies2, Gia_ManObjNum(p), -1 ); } + +static inline int Gia_ObjFanin0CopyF( Gia_Man_t * p, int f, Gia_Obj_t * pObj ) { return Abc_LitNotCond(Gia_ObjCopyF(p, f, Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj)); } +static inline int Gia_ObjFanin1CopyF( Gia_Man_t * p, int f, Gia_Obj_t * pObj ) { return Abc_LitNotCond(Gia_ObjCopyF(p, f, Gia_ObjFanin1(pObj)), Gia_ObjFaninC1(pObj)); } +static inline int Gia_ObjFanin0CopyArray( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Abc_LitNotCond(Gia_ObjCopyArray(p, Gia_ObjFaninId0p(p,pObj)), Gia_ObjFaninC0(pObj)); } +static inline int Gia_ObjFanin1CopyArray( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Abc_LitNotCond(Gia_ObjCopyArray(p, Gia_ObjFaninId1p(p,pObj)), Gia_ObjFaninC1(pObj)); } + +static inline Gia_Obj_t * Gia_ObjFromLit( Gia_Man_t * p, int iLit ) { return Gia_NotCond( Gia_ManObj(p, Abc_Lit2Var(iLit)), Abc_LitIsCompl(iLit) ); } +static inline int Gia_ObjToLit( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Abc_Var2Lit( Gia_ObjId(p, Gia_Regular(pObj)), Gia_IsComplement(pObj) ); } +static inline int Gia_ObjPhaseRealLit( Gia_Man_t * p, int iLit ) { return Gia_ObjPhaseReal( Gia_ObjFromLit(p, iLit) ); } + +static inline int Gia_ObjLevelId( Gia_Man_t * p, int Id ) { return Vec_IntGetEntry(p->vLevels, Id); } +static inline int Gia_ObjLevel( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjLevelId( p, Gia_ObjId(p,pObj) ); } +static inline void Gia_ObjUpdateLevelId( Gia_Man_t * p, int Id, int l ) { Vec_IntSetEntry(p->vLevels, Id, Abc_MaxInt(Vec_IntEntry(p->vLevels, Id), l)); } +static inline void Gia_ObjSetLevelId( Gia_Man_t * p, int Id, int l ) { Vec_IntSetEntry(p->vLevels, Id, l); } +static inline void Gia_ObjSetLevel( Gia_Man_t * p, Gia_Obj_t * pObj, int l ) { Gia_ObjSetLevelId( p, Gia_ObjId(p,pObj), l ); } +static inline void Gia_ObjSetCoLevel( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsCo(pObj) ); Gia_ObjSetLevel( p, pObj, Gia_ObjLevel(p,Gia_ObjFanin0(pObj)) ); } +static inline void Gia_ObjSetBufLevel( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsAnd(pObj) ); Gia_ObjSetLevel( p, pObj, Gia_ObjLevel(p,Gia_ObjFanin0(pObj)) ); } +static inline void Gia_ObjSetAndLevel( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsAnd(pObj) ); Gia_ObjSetLevel( p, pObj, 1+Abc_MaxInt(Gia_ObjLevel(p,Gia_ObjFanin0(pObj)),Gia_ObjLevel(p,Gia_ObjFanin1(pObj))) ); } +static inline void Gia_ObjSetXorLevel( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsXor(pObj) ); Gia_ObjSetLevel( p, pObj, 2+Abc_MaxInt(Gia_ObjLevel(p,Gia_ObjFanin0(pObj)),Gia_ObjLevel(p,Gia_ObjFanin1(pObj))) ); } +static inline void Gia_ObjSetMuxLevel( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjIsMux(p,pObj) ); Gia_ObjSetLevel( p, pObj, 2+Abc_MaxInt( Abc_MaxInt(Gia_ObjLevel(p,Gia_ObjFanin0(pObj)),Gia_ObjLevel(p,Gia_ObjFanin1(pObj))), Gia_ObjLevel(p,Gia_ObjFanin2(p,pObj))) ); } +static inline void Gia_ObjSetGateLevel( Gia_Man_t * p, Gia_Obj_t * pObj ){ if ( !p->fGiaSimple && Gia_ObjIsBuf(pObj) ) Gia_ObjSetBufLevel(p, pObj); else if ( Gia_ObjIsMux(p,pObj) ) Gia_ObjSetMuxLevel(p, pObj); else if ( Gia_ObjIsXor(pObj) ) Gia_ObjSetXorLevel(p, pObj); else if ( Gia_ObjIsAnd(pObj) ) Gia_ObjSetAndLevel(p, pObj); } + +static inline int Gia_ObjHasNumId( Gia_Man_t * p, int Id ) { return Vec_IntEntry(p->vTtNums, Id) > -ABC_INFINITY; } +static inline int Gia_ObjNumId( Gia_Man_t * p, int Id ) { return Vec_IntEntry(p->vTtNums, Id); } +static inline int Gia_ObjNum( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Vec_IntEntry(p->vTtNums, Gia_ObjId(p,pObj)); } +static inline void Gia_ObjSetNumId( Gia_Man_t * p, int Id, int n ) { Vec_IntWriteEntry(p->vTtNums, Id, n); } +static inline void Gia_ObjSetNum( Gia_Man_t * p, Gia_Obj_t * pObj, int n ) { Vec_IntWriteEntry(p->vTtNums, Gia_ObjId(p,pObj), n); } +static inline void Gia_ObjResetNumId( Gia_Man_t * p, int Id ) { Vec_IntWriteEntry(p->vTtNums, Id, -ABC_INFINITY); } + +static inline int Gia_ObjRefNumId( Gia_Man_t * p, int Id ) { return p->pRefs[Id]; } +static inline int Gia_ObjRefIncId( Gia_Man_t * p, int Id ) { return p->pRefs[Id]++; } +static inline int Gia_ObjRefDecId( Gia_Man_t * p, int Id ) { return --p->pRefs[Id]; } +static inline int Gia_ObjRefNum( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjRefNumId( p, Gia_ObjId(p, pObj) ); } +static inline int Gia_ObjRefInc( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjRefIncId( p, Gia_ObjId(p, pObj) ); } +static inline int Gia_ObjRefDec( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjRefDecId( p, Gia_ObjId(p, pObj) ); } +static inline void Gia_ObjRefFanin0Inc(Gia_Man_t * p, Gia_Obj_t * pObj) { Gia_ObjRefInc(p, Gia_ObjFanin0(pObj)); } +static inline void Gia_ObjRefFanin1Inc(Gia_Man_t * p, Gia_Obj_t * pObj) { Gia_ObjRefInc(p, Gia_ObjFanin1(pObj)); } +static inline void Gia_ObjRefFanin2Inc(Gia_Man_t * p, Gia_Obj_t * pObj) { Gia_ObjRefInc(p, Gia_ObjFanin2(p, pObj)); } +static inline void Gia_ObjRefFanin0Dec(Gia_Man_t * p, Gia_Obj_t * pObj) { Gia_ObjRefDec(p, Gia_ObjFanin0(pObj)); } +static inline void Gia_ObjRefFanin1Dec(Gia_Man_t * p, Gia_Obj_t * pObj) { Gia_ObjRefDec(p, Gia_ObjFanin1(pObj)); } +static inline void Gia_ObjRefFanin2Dec(Gia_Man_t * p, Gia_Obj_t * pObj) { Gia_ObjRefDec(p, Gia_ObjFanin2(p, pObj)); } + +static inline int Gia_ObjLutRefNumId( Gia_Man_t * p, int Id ) { assert(p->pLutRefs); return p->pLutRefs[Id]; } +static inline int Gia_ObjLutRefIncId( Gia_Man_t * p, int Id ) { assert(p->pLutRefs); return p->pLutRefs[Id]++; } +static inline int Gia_ObjLutRefDecId( Gia_Man_t * p, int Id ) { assert(p->pLutRefs); return --p->pLutRefs[Id]; } +static inline int Gia_ObjLutRefNum( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert(p->pLutRefs); return p->pLutRefs[Gia_ObjId(p, pObj)]; } +static inline int Gia_ObjLutRefInc( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert(p->pLutRefs); return p->pLutRefs[Gia_ObjId(p, pObj)]++; } +static inline int Gia_ObjLutRefDec( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert(p->pLutRefs); return --p->pLutRefs[Gia_ObjId(p, pObj)]; } + +static inline void Gia_ObjSetTravIdCurrent( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjId(p, pObj) < p->nTravIdsAlloc ); p->pTravIds[Gia_ObjId(p, pObj)] = p->nTravIds; } +static inline void Gia_ObjSetTravIdPrevious( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjId(p, pObj) < p->nTravIdsAlloc ); p->pTravIds[Gia_ObjId(p, pObj)] = p->nTravIds - 1; } +static inline int Gia_ObjIsTravIdCurrent( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjId(p, pObj) < p->nTravIdsAlloc ); return (p->pTravIds[Gia_ObjId(p, pObj)] == p->nTravIds); } +static inline int Gia_ObjIsTravIdPrevious( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert( Gia_ObjId(p, pObj) < p->nTravIdsAlloc ); return (p->pTravIds[Gia_ObjId(p, pObj)] == p->nTravIds - 1); } +static inline int Gia_ObjUpdateTravIdCurrent( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( Gia_ObjIsTravIdCurrent(p, pObj) ) return 1; Gia_ObjSetTravIdCurrent(p, pObj); return 0; } +static inline int Gia_ObjUpdateTravIdPrevious( Gia_Man_t * p, Gia_Obj_t * pObj ) { if ( Gia_ObjIsTravIdPrevious(p, pObj) ) return 1; Gia_ObjSetTravIdPrevious(p, pObj); return 0; } +static inline void Gia_ObjSetTravIdCurrentId( Gia_Man_t * p, int Id ) { assert( Id < p->nTravIdsAlloc ); p->pTravIds[Id] = p->nTravIds; } +static inline void Gia_ObjSetTravIdPreviousId( Gia_Man_t * p, int Id ) { assert( Id < p->nTravIdsAlloc ); p->pTravIds[Id] = p->nTravIds - 1; } +static inline int Gia_ObjIsTravIdCurrentId( Gia_Man_t * p, int Id ) { assert( Id < p->nTravIdsAlloc ); return (p->pTravIds[Id] == p->nTravIds); } +static inline int Gia_ObjIsTravIdPreviousId( Gia_Man_t * p, int Id ) { assert( Id < p->nTravIdsAlloc ); return (p->pTravIds[Id] == p->nTravIds - 1); } +static inline int Gia_ObjUpdateTravIdCurrentId( Gia_Man_t * p, int Id ) { if ( Gia_ObjIsTravIdCurrentId(p, Id) ) return 1; Gia_ObjSetTravIdCurrentId(p, Id); return 0; } +static inline int Gia_ObjUpdateTravIdPreviousId( Gia_Man_t * p, int Id ) { if ( Gia_ObjIsTravIdPreviousId(p, Id) ) return 1; Gia_ObjSetTravIdPreviousId(p, Id); return 0; } + +static inline void Gia_ManTimeClean( Gia_Man_t * p ) { int i; assert( p->vTiming != NULL ); Vec_FltFill(p->vTiming, 3*Gia_ManObjNum(p), 0); for ( i = 0; i < Gia_ManObjNum(p); i++ ) Vec_FltWriteEntry( p->vTiming, 3*i+1, (float)(ABC_INFINITY) ); } +static inline void Gia_ManTimeStart( Gia_Man_t * p ) { assert( p->vTiming == NULL ); p->vTiming = Vec_FltAlloc(0); Gia_ManTimeClean( p ); } +static inline void Gia_ManTimeStop( Gia_Man_t * p ) { assert( p->vTiming != NULL ); Vec_FltFreeP(&p->vTiming); } +static inline float Gia_ObjTimeArrival( Gia_Man_t * p, int Id ) { return Vec_FltEntry(p->vTiming, 3*Id+0); } +static inline float Gia_ObjTimeRequired( Gia_Man_t * p, int Id ) { return Vec_FltEntry(p->vTiming, 3*Id+1); } +static inline float Gia_ObjTimeSlack( Gia_Man_t * p, int Id ) { return Vec_FltEntry(p->vTiming, 3*Id+2); } +static inline float Gia_ObjTimeArrivalObj( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjTimeArrival( p, Gia_ObjId(p, pObj) ); } +static inline float Gia_ObjTimeRequiredObj( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjTimeRequired( p, Gia_ObjId(p, pObj) ); } +static inline float Gia_ObjTimeSlackObj( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjTimeSlack( p, Gia_ObjId(p, pObj) ); } +static inline void Gia_ObjSetTimeArrival( Gia_Man_t * p, int Id, float t ) { Vec_FltWriteEntry( p->vTiming, 3*Id+0, t ); } +static inline void Gia_ObjSetTimeRequired( Gia_Man_t * p, int Id, float t ) { Vec_FltWriteEntry( p->vTiming, 3*Id+1, t ); } +static inline void Gia_ObjSetTimeSlack( Gia_Man_t * p, int Id, float t ) { Vec_FltWriteEntry( p->vTiming, 3*Id+2, t ); } +static inline void Gia_ObjSetTimeArrivalObj( Gia_Man_t * p, Gia_Obj_t * pObj, float t ) { Gia_ObjSetTimeArrival( p, Gia_ObjId(p, pObj), t ); } +static inline void Gia_ObjSetTimeRequiredObj( Gia_Man_t * p, Gia_Obj_t * pObj, float t ) { Gia_ObjSetTimeRequired( p, Gia_ObjId(p, pObj), t ); } +static inline void Gia_ObjSetTimeSlackObj( Gia_Man_t * p, Gia_Obj_t * pObj, float t ) { Gia_ObjSetTimeSlack( p, Gia_ObjId(p, pObj), t ); } + +static inline int Gia_ObjSimWords( Gia_Man_t * p ) { return Vec_WrdSize( p->vSimsPi ) / Gia_ManPiNum( p ); } +static inline word * Gia_ObjSimPi( Gia_Man_t * p, int PiId ) { return Vec_WrdEntryP( p->vSimsPi, PiId * Gia_ObjSimWords(p) ); } +static inline word * Gia_ObjSim( Gia_Man_t * p, int Id ) { return Vec_WrdEntryP( p->vSims, Id * Gia_ObjSimWords(p) ); } +static inline word * Gia_ObjSimObj( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjSim( p, Gia_ObjId(p, pObj) ); } + +// AIG construction +extern void Gia_ObjAddFanout( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanout ); +static inline Gia_Obj_t * Gia_ManAppendObj( Gia_Man_t * p ) +{ + if ( p->nObjs == p->nObjsAlloc ) + { + int nObjNew = Abc_MinInt( 2 * p->nObjsAlloc, (1 << 29) ); + if ( p->nObjs == (1 << 29) ) + printf( "Hard limit on the number of nodes (2^29) is reached. Quitting...\n" ), exit(1); + assert( p->nObjs < nObjNew ); + if ( p->fVerbose ) + printf("Extending GIA object storage: %d -> %d.\n", p->nObjsAlloc, nObjNew ); + assert( p->nObjsAlloc > 0 ); + p->pObjs = ABC_REALLOC( Gia_Obj_t, p->pObjs, nObjNew ); + memset( p->pObjs + p->nObjsAlloc, 0, sizeof(Gia_Obj_t) * (nObjNew - p->nObjsAlloc) ); + if ( p->pMuxes ) + { + p->pMuxes = ABC_REALLOC( unsigned, p->pMuxes, nObjNew ); + memset( p->pMuxes + p->nObjsAlloc, 0, sizeof(unsigned) * (nObjNew - p->nObjsAlloc) ); + } + p->nObjsAlloc = nObjNew; + } + if ( Vec_IntSize(&p->vHTable) ) Vec_IntPush( &p->vHash, 0 ); + return Gia_ManObj( p, p->nObjs++ ); +} +static inline int Gia_ManAppendCi( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj = Gia_ManAppendObj( p ); + pObj->fTerm = 1; + pObj->iDiff0 = GIA_NONE; + pObj->iDiff1 = Vec_IntSize( p->vCis ); + Vec_IntPush( p->vCis, Gia_ObjId(p, pObj) ); + return Gia_ObjId( p, pObj ) << 1; +} + +extern void Gia_ManQuantSetSuppAnd( Gia_Man_t * p, Gia_Obj_t * pObj ); +extern void Gia_ManBuiltInSimPerform( Gia_Man_t * p, int iObj ); + +static inline int Gia_ManAppendAnd( Gia_Man_t * p, int iLit0, int iLit1 ) +{ + Gia_Obj_t * pObj = Gia_ManAppendObj( p ); + assert( iLit0 >= 0 && Abc_Lit2Var(iLit0) < Gia_ManObjNum(p) ); + assert( iLit1 >= 0 && Abc_Lit2Var(iLit1) < Gia_ManObjNum(p) ); + assert( p->fGiaSimple || Abc_Lit2Var(iLit0) != Abc_Lit2Var(iLit1) ); + if ( iLit0 < iLit1 ) + { + pObj->iDiff0 = (unsigned)(Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0)); + pObj->fCompl0 = (unsigned)(Abc_LitIsCompl(iLit0)); + pObj->iDiff1 = (unsigned)(Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1)); + pObj->fCompl1 = (unsigned)(Abc_LitIsCompl(iLit1)); + } + else + { + pObj->iDiff1 = (unsigned)(Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0)); + pObj->fCompl1 = (unsigned)(Abc_LitIsCompl(iLit0)); + pObj->iDiff0 = (unsigned)(Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1)); + pObj->fCompl0 = (unsigned)(Abc_LitIsCompl(iLit1)); + } + if ( p->pFanData ) + { + Gia_ObjAddFanout( p, Gia_ObjFanin0(pObj), pObj ); + Gia_ObjAddFanout( p, Gia_ObjFanin1(pObj), pObj ); + } + if ( p->fSweeper ) + { + Gia_Obj_t * pFan0 = Gia_ObjFanin0(pObj); + Gia_Obj_t * pFan1 = Gia_ObjFanin1(pObj); + if ( pFan0->fMark0 ) pFan0->fMark1 = 1; else pFan0->fMark0 = 1; + if ( pFan1->fMark0 ) pFan1->fMark1 = 1; else pFan1->fMark0 = 1; + pObj->fPhase = (Gia_ObjPhase(pFan0) ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjPhase(pFan1) ^ Gia_ObjFaninC1(pObj)); + } + if ( p->fBuiltInSim ) + { + Gia_Obj_t * pFan0 = Gia_ObjFanin0(pObj); + Gia_Obj_t * pFan1 = Gia_ObjFanin1(pObj); + pObj->fPhase = (Gia_ObjPhase(pFan0) ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjPhase(pFan1) ^ Gia_ObjFaninC1(pObj)); + Gia_ManBuiltInSimPerform( p, Gia_ObjId( p, pObj ) ); + } + if ( p->vSuppWords ) + Gia_ManQuantSetSuppAnd( p, pObj ); + return Gia_ObjId( p, pObj ) << 1; +} +static inline int Gia_ManAppendXorReal( Gia_Man_t * p, int iLit0, int iLit1 ) +{ + Gia_Obj_t * pObj = Gia_ManAppendObj( p ); + assert( iLit0 >= 0 && Abc_Lit2Var(iLit0) < Gia_ManObjNum(p) ); + assert( iLit1 >= 0 && Abc_Lit2Var(iLit1) < Gia_ManObjNum(p) ); + assert( Abc_Lit2Var(iLit0) != Abc_Lit2Var(iLit1) ); + //assert( !Abc_LitIsCompl(iLit0) ); + //assert( !Abc_LitIsCompl(iLit1) ); + if ( Abc_Lit2Var(iLit0) > Abc_Lit2Var(iLit1) ) + { + pObj->iDiff0 = (unsigned)(Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0)); + pObj->fCompl0 = (unsigned)(Abc_LitIsCompl(iLit0)); + pObj->iDiff1 = (unsigned)(Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1)); + pObj->fCompl1 = (unsigned)(Abc_LitIsCompl(iLit1)); + } + else + { + pObj->iDiff1 = (unsigned)(Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0)); + pObj->fCompl1 = (unsigned)(Abc_LitIsCompl(iLit0)); + pObj->iDiff0 = (unsigned)(Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1)); + pObj->fCompl0 = (unsigned)(Abc_LitIsCompl(iLit1)); + } + p->nXors++; + return Gia_ObjId( p, pObj ) << 1; +} +static inline int Gia_ManAppendMuxReal( Gia_Man_t * p, int iLitC, int iLit1, int iLit0 ) +{ + Gia_Obj_t * pObj = Gia_ManAppendObj( p ); + assert( p->pMuxes != NULL ); + assert( iLit0 >= 0 && Abc_Lit2Var(iLit0) < Gia_ManObjNum(p) ); + assert( iLit1 >= 0 && Abc_Lit2Var(iLit1) < Gia_ManObjNum(p) ); + assert( iLitC >= 0 && Abc_Lit2Var(iLitC) < Gia_ManObjNum(p) ); + assert( Abc_Lit2Var(iLit0) != Abc_Lit2Var(iLit1) ); + assert( Abc_Lit2Var(iLitC) != Abc_Lit2Var(iLit0) ); + assert( Abc_Lit2Var(iLitC) != Abc_Lit2Var(iLit1) ); + assert( !Vec_IntSize(&p->vHTable) || !Abc_LitIsCompl(iLit1) ); + if ( Abc_Lit2Var(iLit0) < Abc_Lit2Var(iLit1) ) + { + pObj->iDiff0 = (unsigned)(Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0)); + pObj->fCompl0 = (unsigned)(Abc_LitIsCompl(iLit0)); + pObj->iDiff1 = (unsigned)(Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1)); + pObj->fCompl1 = (unsigned)(Abc_LitIsCompl(iLit1)); + p->pMuxes[Gia_ObjId(p, pObj)] = iLitC; + } + else + { + pObj->iDiff1 = (unsigned)(Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0)); + pObj->fCompl1 = (unsigned)(Abc_LitIsCompl(iLit0)); + pObj->iDiff0 = (unsigned)(Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit1)); + pObj->fCompl0 = (unsigned)(Abc_LitIsCompl(iLit1)); + p->pMuxes[Gia_ObjId(p, pObj)] = Abc_LitNot(iLitC); + } + p->nMuxes++; + return Gia_ObjId( p, pObj ) << 1; +} +static inline int Gia_ManAppendBuf( Gia_Man_t * p, int iLit ) +{ + Gia_Obj_t * pObj = Gia_ManAppendObj( p ); + assert( iLit >= 0 && Abc_Lit2Var(iLit) < Gia_ManObjNum(p) ); + pObj->iDiff0 = pObj->iDiff1 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit); + pObj->fCompl0 = pObj->fCompl1 = Abc_LitIsCompl(iLit); + p->nBufs++; + return Gia_ObjId( p, pObj ) << 1; +} +static inline int Gia_ManAppendCo( Gia_Man_t * p, int iLit0 ) +{ + Gia_Obj_t * pObj; + assert( iLit0 >= 0 && Abc_Lit2Var(iLit0) < Gia_ManObjNum(p) ); + assert( !Gia_ObjIsCo(Gia_ManObj(p, Abc_Lit2Var(iLit0))) ); + pObj = Gia_ManAppendObj( p ); + pObj->fTerm = 1; + pObj->iDiff0 = Gia_ObjId(p, pObj) - Abc_Lit2Var(iLit0); + pObj->fCompl0 = Abc_LitIsCompl(iLit0); + pObj->iDiff1 = Vec_IntSize( p->vCos ); + Vec_IntPush( p->vCos, Gia_ObjId(p, pObj) ); + if ( p->pFanData ) + Gia_ObjAddFanout( p, Gia_ObjFanin0(pObj), pObj ); + return Gia_ObjId( p, pObj ) << 1; +} +static inline int Gia_ManAppendOr( Gia_Man_t * p, int iLit0, int iLit1 ) +{ + return Abc_LitNot(Gia_ManAppendAnd( p, Abc_LitNot(iLit0), Abc_LitNot(iLit1) )); +} +static inline int Gia_ManAppendMux( Gia_Man_t * p, int iCtrl, int iData1, int iData0 ) +{ + int iTemp0 = Gia_ManAppendAnd( p, Abc_LitNot(iCtrl), iData0 ); + int iTemp1 = Gia_ManAppendAnd( p, iCtrl, iData1 ); + return Abc_LitNotCond( Gia_ManAppendAnd( p, Abc_LitNot(iTemp0), Abc_LitNot(iTemp1) ), 1 ); +} +static inline int Gia_ManAppendMaj( Gia_Man_t * p, int iData0, int iData1, int iData2 ) +{ + int iTemp0 = Gia_ManAppendOr( p, iData1, iData2 ); + int iTemp1 = Gia_ManAppendAnd( p, iData0, iTemp0 ); + int iTemp2 = Gia_ManAppendAnd( p, iData1, iData2 ); + return Gia_ManAppendOr( p, iTemp1, iTemp2 ); +} +static inline int Gia_ManAppendXor( Gia_Man_t * p, int iLit0, int iLit1 ) +{ + return Gia_ManAppendMux( p, iLit0, Abc_LitNot(iLit1), iLit1 ); +} + +static inline int Gia_ManAppendAnd2( Gia_Man_t * p, int iLit0, int iLit1 ) +{ + if ( !p->fGiaSimple ) + { + if ( iLit0 < 2 ) + return iLit0 ? iLit1 : 0; + if ( iLit1 < 2 ) + return iLit1 ? iLit0 : 0; + if ( iLit0 == iLit1 ) + return iLit1; + if ( iLit0 == Abc_LitNot(iLit1) ) + return 0; + } + return Gia_ManAppendAnd( p, iLit0, iLit1 ); +} +static inline int Gia_ManAppendOr2( Gia_Man_t * p, int iLit0, int iLit1 ) +{ + return Abc_LitNot(Gia_ManAppendAnd2( p, Abc_LitNot(iLit0), Abc_LitNot(iLit1) )); +} +static inline int Gia_ManAppendMux2( Gia_Man_t * p, int iCtrl, int iData1, int iData0 ) +{ + int iTemp0 = Gia_ManAppendAnd2( p, Abc_LitNot(iCtrl), iData0 ); + int iTemp1 = Gia_ManAppendAnd2( p, iCtrl, iData1 ); + return Abc_LitNotCond( Gia_ManAppendAnd2( p, Abc_LitNot(iTemp0), Abc_LitNot(iTemp1) ), 1 ); +} +static inline int Gia_ManAppendMaj2( Gia_Man_t * p, int iData0, int iData1, int iData2 ) +{ + int iTemp0 = Gia_ManAppendOr2( p, iData1, iData2 ); + int iTemp1 = Gia_ManAppendAnd2( p, iData0, iTemp0 ); + int iTemp2 = Gia_ManAppendAnd2( p, iData1, iData2 ); + return Gia_ManAppendOr2( p, iTemp1, iTemp2 ); +} +static inline int Gia_ManAppendXor2( Gia_Man_t * p, int iLit0, int iLit1 ) +{ + return Gia_ManAppendMux2( p, iLit0, Abc_LitNot(iLit1), iLit1 ); +} + +static inline int Gia_ManAppendXorReal2( Gia_Man_t * p, int iLit0, int iLit1 ) +{ + if ( !p->fGiaSimple ) + { + if ( iLit0 < 2 ) + return iLit0 ? Abc_LitNot(iLit1) : iLit1; + if ( iLit1 < 2 ) + return iLit1 ? Abc_LitNot(iLit0) : iLit0; + if ( iLit0 == iLit1 ) + return 0; + if ( iLit0 == Abc_LitNot(iLit1) ) + return 1; + } + return Gia_ManAppendXorReal( p, iLit0, iLit1 ); +} + +static inline void Gia_ManPatchCoDriver( Gia_Man_t * p, int iCoIndex, int iLit0 ) +{ + Gia_Obj_t * pObjCo = Gia_ManCo( p, iCoIndex ); + assert( Gia_ObjId(p, pObjCo) > Abc_Lit2Var(iLit0) ); + pObjCo->iDiff0 = Gia_ObjId(p, pObjCo) - Abc_Lit2Var(iLit0); + pObjCo->fCompl0 = Abc_LitIsCompl(iLit0); +} + +#define GIA_ZER 1 +#define GIA_ONE 2 +#define GIA_UND 3 + +static inline int Gia_XsimNotCond( int Value, int fCompl ) +{ + if ( Value == GIA_UND ) + return GIA_UND; + if ( Value == GIA_ZER + fCompl ) + return GIA_ZER; + return GIA_ONE; +} +static inline int Gia_XsimAndCond( int Value0, int fCompl0, int Value1, int fCompl1 ) +{ + if ( Value0 == GIA_ZER + fCompl0 || Value1 == GIA_ZER + fCompl1 ) + return GIA_ZER; + if ( Value0 == GIA_UND || Value1 == GIA_UND ) + return GIA_UND; + return GIA_ONE; +} + + +static inline void Gia_ObjTerSimSetC( Gia_Obj_t * pObj ) { pObj->fMark0 = 0; pObj->fMark1 = 0; } +static inline void Gia_ObjTerSimSet0( Gia_Obj_t * pObj ) { pObj->fMark0 = 1; pObj->fMark1 = 0; } +static inline void Gia_ObjTerSimSet1( Gia_Obj_t * pObj ) { pObj->fMark0 = 0; pObj->fMark1 = 1; } +static inline void Gia_ObjTerSimSetX( Gia_Obj_t * pObj ) { pObj->fMark0 = 1; pObj->fMark1 = 1; } + +static inline int Gia_ObjTerSimGetC( Gia_Obj_t * pObj ) { return !pObj->fMark0 && !pObj->fMark1; } +static inline int Gia_ObjTerSimGet0( Gia_Obj_t * pObj ) { return pObj->fMark0 && !pObj->fMark1; } +static inline int Gia_ObjTerSimGet1( Gia_Obj_t * pObj ) { return !pObj->fMark0 && pObj->fMark1; } +static inline int Gia_ObjTerSimGetX( Gia_Obj_t * pObj ) { return pObj->fMark0 && pObj->fMark1; } + +static inline int Gia_ObjTerSimGet0Fanin0( Gia_Obj_t * pObj ) { return (Gia_ObjTerSimGet1(Gia_ObjFanin0(pObj)) && Gia_ObjFaninC0(pObj)) || (Gia_ObjTerSimGet0(Gia_ObjFanin0(pObj)) && !Gia_ObjFaninC0(pObj)); } +static inline int Gia_ObjTerSimGet1Fanin0( Gia_Obj_t * pObj ) { return (Gia_ObjTerSimGet0(Gia_ObjFanin0(pObj)) && Gia_ObjFaninC0(pObj)) || (Gia_ObjTerSimGet1(Gia_ObjFanin0(pObj)) && !Gia_ObjFaninC0(pObj)); } + +static inline int Gia_ObjTerSimGet0Fanin1( Gia_Obj_t * pObj ) { return (Gia_ObjTerSimGet1(Gia_ObjFanin1(pObj)) && Gia_ObjFaninC1(pObj)) || (Gia_ObjTerSimGet0(Gia_ObjFanin1(pObj)) && !Gia_ObjFaninC1(pObj)); } +static inline int Gia_ObjTerSimGet1Fanin1( Gia_Obj_t * pObj ) { return (Gia_ObjTerSimGet0(Gia_ObjFanin1(pObj)) && Gia_ObjFaninC1(pObj)) || (Gia_ObjTerSimGet1(Gia_ObjFanin1(pObj)) && !Gia_ObjFaninC1(pObj)); } + +static inline void Gia_ObjTerSimAnd( Gia_Obj_t * pObj ) +{ + assert( Gia_ObjIsAnd(pObj) ); + assert( !Gia_ObjTerSimGetC( Gia_ObjFanin0(pObj) ) ); + assert( !Gia_ObjTerSimGetC( Gia_ObjFanin1(pObj) ) ); + if ( Gia_ObjTerSimGet0Fanin0(pObj) || Gia_ObjTerSimGet0Fanin1(pObj) ) + Gia_ObjTerSimSet0( pObj ); + else if ( Gia_ObjTerSimGet1Fanin0(pObj) && Gia_ObjTerSimGet1Fanin1(pObj) ) + Gia_ObjTerSimSet1( pObj ); + else + Gia_ObjTerSimSetX( pObj ); +} +static inline void Gia_ObjTerSimCo( Gia_Obj_t * pObj ) +{ + assert( Gia_ObjIsCo(pObj) ); + assert( !Gia_ObjTerSimGetC( Gia_ObjFanin0(pObj) ) ); + if ( Gia_ObjTerSimGet0Fanin0(pObj) ) + Gia_ObjTerSimSet0( pObj ); + else if ( Gia_ObjTerSimGet1Fanin0(pObj) ) + Gia_ObjTerSimSet1( pObj ); + else + Gia_ObjTerSimSetX( pObj ); +} +static inline void Gia_ObjTerSimRo( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + Gia_Obj_t * pTemp = Gia_ObjRoToRi(p, pObj); + assert( Gia_ObjIsRo(p, pObj) ); + assert( !Gia_ObjTerSimGetC( pTemp ) ); + pObj->fMark0 = pTemp->fMark0; + pObj->fMark1 = pTemp->fMark1; +} + +static inline void Gia_ObjTerSimPrint( Gia_Obj_t * pObj ) +{ + if ( Gia_ObjTerSimGet0(pObj) ) + printf( "0" ); + else if ( Gia_ObjTerSimGet1(pObj) ) + printf( "1" ); + else if ( Gia_ObjTerSimGetX(pObj) ) + printf( "X" ); +} + +static inline int Gia_AigerReadInt( unsigned char * pPos ) +{ + int i, Value = 0; + for ( i = 0; i < 4; i++ ) + Value = (Value << 8) | *pPos++; + return Value; +} +static inline void Gia_AigerWriteInt( unsigned char * pPos, int Value ) +{ + int i; + for ( i = 3; i >= 0; i-- ) + *pPos++ = (Value >> (8*i)) & 255; +} +static inline unsigned Gia_AigerReadUnsigned( unsigned char ** ppPos ) +{ + unsigned x = 0, i = 0; + unsigned char ch; + while ((ch = *(*ppPos)++) & 0x80) + x |= (ch & 0x7f) << (7 * i++); + return x | (ch << (7 * i)); +} +static inline void Gia_AigerWriteUnsigned( Vec_Str_t * vStr, unsigned x ) +{ + unsigned char ch; + while (x & ~0x7f) + { + ch = (x & 0x7f) | 0x80; + Vec_StrPush( vStr, ch ); + x >>= 7; + } + ch = x; + Vec_StrPush( vStr, ch ); +} +static inline void Gia_AigerWriteUnsignedFile( FILE * pFile, unsigned x ) +{ + unsigned char ch; + while (x & ~0x7f) + { + ch = (x & 0x7f) | 0x80; + fputc( ch, pFile ); + x >>= 7; + } + ch = x; + fputc( ch, pFile ); +} +static inline int Gia_AigerWriteUnsignedBuffer( unsigned char * pBuffer, int Pos, unsigned x ) +{ + unsigned char ch; + while (x & ~0x7f) + { + ch = (x & 0x7f) | 0x80; + pBuffer[Pos++] = ch; + x >>= 7; + } + ch = x; + pBuffer[Pos++] = ch; + return Pos; +} + +static inline Gia_Obj_t * Gia_ObjReprObj( Gia_Man_t * p, int Id ) { return p->pReprs[Id].iRepr == GIA_VOID ? NULL : Gia_ManObj( p, p->pReprs[Id].iRepr ); } +static inline int Gia_ObjRepr( Gia_Man_t * p, int Id ) { return p->pReprs[Id].iRepr; } +static inline void Gia_ObjSetRepr( Gia_Man_t * p, int Id, int Num ) { assert( Num == GIA_VOID || Num < Id ); p->pReprs[Id].iRepr = Num; } +static inline void Gia_ObjSetReprRev( Gia_Man_t * p, int Id, int Num ){ assert( Num == GIA_VOID || Num > Id ); p->pReprs[Id].iRepr = Num; } +static inline void Gia_ObjUnsetRepr( Gia_Man_t * p, int Id ) { p->pReprs[Id].iRepr = GIA_VOID; } +static inline int Gia_ObjHasRepr( Gia_Man_t * p, int Id ) { return p->pReprs[Id].iRepr != GIA_VOID; } +static inline int Gia_ObjReprSelf( Gia_Man_t * p, int Id ) { return Gia_ObjHasRepr(p, Id) ? Gia_ObjRepr(p, Id) : Id; } +static inline int Gia_ObjSibl( Gia_Man_t * p, int Id ) { return p->pSibls ? p->pSibls[Id] : 0; } +static inline Gia_Obj_t * Gia_ObjSiblObj( Gia_Man_t * p, int Id ) { return (p->pSibls && p->pSibls[Id]) ? Gia_ManObj(p, p->pSibls[Id]) : NULL; } + +static inline int Gia_ObjProved( Gia_Man_t * p, int Id ) { return p->pReprs[Id].fProved; } +static inline void Gia_ObjSetProved( Gia_Man_t * p, int Id ) { p->pReprs[Id].fProved = 1; } +static inline void Gia_ObjUnsetProved( Gia_Man_t * p, int Id ) { p->pReprs[Id].fProved = 0; } + +static inline int Gia_ObjFailed( Gia_Man_t * p, int Id ) { return p->pReprs[Id].fFailed; } +static inline void Gia_ObjSetFailed( Gia_Man_t * p, int Id ) { p->pReprs[Id].fFailed = 1; } + +static inline int Gia_ObjColor( Gia_Man_t * p, int Id, int c ) { return c? p->pReprs[Id].fColorB : p->pReprs[Id].fColorA; } +static inline int Gia_ObjColors( Gia_Man_t * p, int Id ) { return p->pReprs[Id].fColorB * 2 + p->pReprs[Id].fColorA; } +static inline void Gia_ObjSetColor( Gia_Man_t * p, int Id, int c ) { if (c) p->pReprs[Id].fColorB = 1; else p->pReprs[Id].fColorA = 1; } +static inline void Gia_ObjSetColors( Gia_Man_t * p, int Id ) { p->pReprs[Id].fColorB = p->pReprs[Id].fColorA = 1; } +static inline int Gia_ObjVisitColor( Gia_Man_t * p, int Id, int c ) { int x; if (c) { x = p->pReprs[Id].fColorB; p->pReprs[Id].fColorB = 1; } else { x = p->pReprs[Id].fColorA; p->pReprs[Id].fColorA = 1; } return x; } +static inline int Gia_ObjDiffColors( Gia_Man_t * p, int i, int j ) { return (p->pReprs[i].fColorA ^ p->pReprs[j].fColorA) && (p->pReprs[i].fColorB ^ p->pReprs[j].fColorB); } +static inline int Gia_ObjDiffColors2( Gia_Man_t * p, int i, int j ) { return (p->pReprs[i].fColorA ^ p->pReprs[j].fColorA) || (p->pReprs[i].fColorB ^ p->pReprs[j].fColorB); } + +static inline Gia_Obj_t * Gia_ObjNextObj( Gia_Man_t * p, int Id ) { return p->pNexts[Id] == 0 ? NULL : Gia_ManObj( p, p->pNexts[Id] );} +static inline int Gia_ObjNext( Gia_Man_t * p, int Id ) { return p->pNexts[Id]; } +static inline void Gia_ObjSetNext( Gia_Man_t * p, int Id, int Num ) { p->pNexts[Id] = Num; } + +static inline int Gia_ObjIsConst( Gia_Man_t * p, int Id ) { return Gia_ObjRepr(p, Id) == 0; } +static inline int Gia_ObjIsHead( Gia_Man_t * p, int Id ) { return Gia_ObjRepr(p, Id) == GIA_VOID && Gia_ObjNext(p, Id) > 0; } +static inline int Gia_ObjIsNone( Gia_Man_t * p, int Id ) { return Gia_ObjRepr(p, Id) == GIA_VOID && Gia_ObjNext(p, Id) <= 0; } +static inline int Gia_ObjIsTail( Gia_Man_t * p, int Id ) { return (Gia_ObjRepr(p, Id) > 0 && Gia_ObjRepr(p, Id) != GIA_VOID) && Gia_ObjNext(p, Id) <= 0; } +static inline int Gia_ObjIsClass( Gia_Man_t * p, int Id ) { return (Gia_ObjRepr(p, Id) > 0 && Gia_ObjRepr(p, Id) != GIA_VOID) || Gia_ObjNext(p, Id) > 0; } +static inline int Gia_ObjHasSameRepr( Gia_Man_t * p, int i, int k ) { assert( k ); return i? (Gia_ObjRepr(p, i) == Gia_ObjRepr(p, k) && Gia_ObjRepr(p, i) != GIA_VOID) : Gia_ObjRepr(p, k) == 0; } +static inline int Gia_ObjIsFailedPair( Gia_Man_t * p, int i, int k ) { assert( k ); return i? (Gia_ObjFailed(p, i) || Gia_ObjFailed(p, k)) : Gia_ObjFailed(p, k); } +static inline int Gia_ClassIsPair( Gia_Man_t * p, int i ) { assert( Gia_ObjIsHead(p, i) ); assert( Gia_ObjNext(p, i) ); return Gia_ObjNext(p, Gia_ObjNext(p, i)) <= 0; } +static inline void Gia_ClassUndoPair( Gia_Man_t * p, int i ) { assert( Gia_ClassIsPair(p,i) ); Gia_ObjSetRepr(p, Gia_ObjNext(p, i), GIA_VOID); Gia_ObjSetNext(p, i, 0); } + +#define Gia_ManForEachConst( p, i ) \ + for ( i = 1; i < Gia_ManObjNum(p); i++ ) if ( !Gia_ObjIsConst(p, i) ) {} else +#define Gia_ManForEachClass( p, i ) \ + for ( i = 1; i < Gia_ManObjNum(p); i++ ) if ( !Gia_ObjIsHead(p, i) ) {} else +#define Gia_ManForEachClass0( p, i ) \ + for ( i = 0; i < Gia_ManObjNum(p); i++ ) if ( !Gia_ObjIsHead(p, i) ) {} else +#define Gia_ManForEachClassReverse( p, i ) \ + for ( i = Gia_ManObjNum(p) - 1; i > 0; i-- ) if ( !Gia_ObjIsHead(p, i) ) {} else +#define Gia_ClassForEachObj( p, i, iObj ) \ + for ( assert(Gia_ObjIsHead(p, i) && i), iObj = i; iObj > 0; iObj = Gia_ObjNext(p, iObj) ) +#define Gia_ClassForEachObj1( p, i, iObj ) \ + for ( assert(Gia_ObjIsHead(p, i)), iObj = Gia_ObjNext(p, i); iObj > 0; iObj = Gia_ObjNext(p, iObj) ) +#define Gia_ClassForEachObjStart( p, i, iObj, Start ) \ + for ( assert(Gia_ObjIsHead(p, i)), iObj = Gia_ObjNext(p, Start); iObj > 0; iObj = Gia_ObjNext(p, iObj) ) + + +static inline int Gia_ObjFoffsetId( Gia_Man_t * p, int Id ) { return Vec_IntEntry( p->vFanout, Id ); } +static inline int Gia_ObjFoffset( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjFoffsetId( p, Gia_ObjId(p, pObj) ); } +static inline int Gia_ObjFanoutNumId( Gia_Man_t * p, int Id ) { return Vec_IntEntry( p->vFanoutNums, Id ); } +static inline int Gia_ObjFanoutNum( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjFanoutNumId( p, Gia_ObjId(p, pObj) ); } +static inline int Gia_ObjFanoutId( Gia_Man_t * p, int Id, int i ) { return Vec_IntEntry( p->vFanout, Gia_ObjFoffsetId(p, Id) + i ); } +static inline Gia_Obj_t * Gia_ObjFanout0( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ManObj( p, Gia_ObjFanoutId(p, Gia_ObjId(p, pObj), 0) ); } +static inline Gia_Obj_t * Gia_ObjFanout( Gia_Man_t * p, Gia_Obj_t * pObj, int i ) { return Gia_ManObj( p, Gia_ObjFanoutId(p, Gia_ObjId(p, pObj), i) ); } +static inline void Gia_ObjSetFanout( Gia_Man_t * p, Gia_Obj_t * pObj, int i, Gia_Obj_t * pFan ) { Vec_IntWriteEntry( p->vFanout, Gia_ObjFoffset(p, pObj) + i, Gia_ObjId(p, pFan) ); } +static inline void Gia_ObjSetFanoutInt( Gia_Man_t * p, Gia_Obj_t * pObj, int i, int x ) { Vec_IntWriteEntry( p->vFanout, Gia_ObjFoffset(p, pObj) + i, x ); } + +#define Gia_ObjForEachFanoutStatic( p, pObj, pFanout, i ) \ + for ( i = 0; (i < Gia_ObjFanoutNum(p, pObj)) && (((pFanout) = Gia_ObjFanout(p, pObj, i)), 1); i++ ) +#define Gia_ObjForEachFanoutStaticId( p, Id, FanId, i ) \ + for ( i = 0; (i < Gia_ObjFanoutNumId(p, Id)) && ((FanId = Gia_ObjFanoutId(p, Id, i)), 1); i++ ) +#define Gia_ObjForEachFanoutStaticIndex( p, Id, FanId, i, Index ) \ + for ( i = 0; (i < Gia_ObjFanoutNumId(p, Id)) && (Index = Vec_IntEntry(p->vFanout, Id)+i) && ((FanId = Vec_IntEntry(p->vFanout, Index)), 1); i++ ) + +static inline int Gia_ManHasMapping( Gia_Man_t * p ) { return p->vMapping != NULL; } +static inline int Gia_ObjIsLut( Gia_Man_t * p, int Id ) { return Vec_IntEntry(p->vMapping, Id) != 0; } +static inline int Gia_ObjLutSize( Gia_Man_t * p, int Id ) { return Vec_IntEntry(p->vMapping, Vec_IntEntry(p->vMapping, Id)); } +static inline int * Gia_ObjLutFanins( Gia_Man_t * p, int Id ) { return Vec_IntEntryP(p->vMapping, Vec_IntEntry(p->vMapping, Id)) + 1; } +static inline int Gia_ObjLutFanin( Gia_Man_t * p, int Id, int i ) { return Gia_ObjLutFanins(p, Id)[i]; } +static inline int Gia_ObjLutMuxId( Gia_Man_t * p, int Id ) { return Gia_ObjLutFanins(p, Id)[Gia_ObjLutSize(p, Id)]; } +static inline int Gia_ObjLutIsMux( Gia_Man_t * p, int Id ) { return (int)(Gia_ObjLutMuxId(p, Id) < 0); } + +static inline int Gia_ManHasMapping2( Gia_Man_t * p ) { return p->vMapping2 != NULL; } +static inline int Gia_ObjIsLut2( Gia_Man_t * p, int Id ) { return Vec_IntSize(Vec_WecEntry(p->vMapping2, Id)) != 0; } +static inline int Gia_ObjLutSize2( Gia_Man_t * p, int Id ) { return Vec_IntSize(Vec_WecEntry(p->vMapping2, Id)); } +static inline Vec_Int_t * Gia_ObjLutFanins2( Gia_Man_t * p, int Id ) { return Vec_WecEntry(p->vMapping2, Id); } +static inline int Gia_ObjLutFanin2( Gia_Man_t * p, int Id, int i ) { return Vec_IntEntry(Vec_WecEntry(p->vMapping2, Id), i); } +static inline int Gia_ObjLutFanoutNum2( Gia_Man_t * p, int Id ) { return Vec_IntSize(Vec_WecEntry(p->vFanouts2, Id)); } +static inline int Gia_ObjLutFanout2( Gia_Man_t * p, int Id, int i ) { return Vec_IntEntry(Vec_WecEntry(p->vFanouts2, Id), i); } + +static inline int Gia_ManHasCellMapping( Gia_Man_t * p ) { return p->vCellMapping != NULL; } +static inline int Gia_ObjIsCell( Gia_Man_t * p, int iLit ) { return Vec_IntEntry(p->vCellMapping, iLit) != 0; } +static inline int Gia_ObjIsCellInv( Gia_Man_t * p, int iLit ) { return Vec_IntEntry(p->vCellMapping, iLit) == -1; } +static inline int Gia_ObjIsCellBuf( Gia_Man_t * p, int iLit ) { return Vec_IntEntry(p->vCellMapping, iLit) == -2; } +static inline int Gia_ObjCellSize( Gia_Man_t * p, int iLit ) { return Vec_IntEntry(p->vCellMapping, Vec_IntEntry(p->vCellMapping, iLit)); } +static inline int * Gia_ObjCellFanins( Gia_Man_t * p, int iLit ) { return Vec_IntEntryP(p->vCellMapping, Vec_IntEntry(p->vCellMapping, iLit))+1; } +static inline int Gia_ObjCellFanin( Gia_Man_t * p, int iLit, int i ){ return Gia_ObjCellFanins(p, iLit)[i]; } +static inline int Gia_ObjCellId( Gia_Man_t * p, int iLit ) { return Gia_ObjCellFanins(p, iLit)[Gia_ObjCellSize(p, iLit)]; } + +#define Gia_ManForEachLut( p, i ) \ + for ( i = 1; i < Gia_ManObjNum(p); i++ ) if ( !Gia_ObjIsLut(p, i) ) {} else +#define Gia_ManForEachLutReverse( p, i ) \ + for ( i = Gia_ManObjNum(p) - 1; i > 0; i-- ) if ( !Gia_ObjIsLut(p, i) ) {} else +#define Gia_LutForEachFanin( p, i, iFan, k ) \ + for ( k = 0; k < Gia_ObjLutSize(p,i) && ((iFan = Gia_ObjLutFanins(p,i)[k]),1); k++ ) +#define Gia_LutForEachFaninIndex( p, i, iFan, k, Index ) \ + for ( k = 0; k < Gia_ObjLutSize(p,i) && (Index = Vec_IntEntry(p->vMapping, i)+1+k) && ((iFan = Vec_IntEntry(p->vMapping, Index)),1); k++ ) +#define Gia_LutForEachFaninObj( p, i, pFanin, k ) \ + for ( k = 0; k < Gia_ObjLutSize(p,i) && ((pFanin = Gia_ManObj(p, Gia_ObjLutFanins(p,i)[k])),1); k++ ) + +#define Gia_ManForEachLut2( p, i ) \ + for ( i = 1; i < Gia_ManObjNum(p); i++ ) if ( !Gia_ObjIsLut2(p, i) ) {} else +#define Gia_ManForEachLut2Reverse( p, i ) \ + for ( i = Gia_ManObjNum(p) - 1; i > 0; i-- ) if ( !Gia_ObjIsLut2(p, i) ) {} else +#define Gia_ManForEachLut2Vec( vIds, p, vVec, iObj, i ) \ + for ( i = 0; i < Vec_IntSize(vIds) && (vVec = Vec_WecEntry(p->vMapping2, (iObj = Vec_IntEntry(vIds, i)))); i++ ) +#define Gia_ManForEachLut2VecReverse( vIds, p, vVec, iObj, i ) \ + for ( i = Vec_IntSize(vIds)-1; i >= 0 && (vVec = Vec_WecEntry(p->vMapping2, (iObj = Vec_IntEntry(vIds, i)))); i-- ) +#define Gia_LutForEachFanin2( p, i, iFan, k ) \ + for ( k = 0; k < Gia_ObjLutSize2(p,i) && ((iFan = Gia_ObjLutFanin2(p,i,k)),1); k++ ) +#define Gia_LutForEachFanout2( p, i, iFan, k ) \ + for ( k = 0; k < Gia_ObjLutFanoutNum2(p,i) && ((iFan = Gia_ObjLutFanout2(p,i,k)),1); k++ ) + +#define Gia_ManForEachCell( p, i ) \ + for ( i = 2; i < 2*Gia_ManObjNum(p); i++ ) if ( !Gia_ObjIsCell(p, i) ) {} else +#define Gia_CellForEachFanin( p, i, iFanLit, k ) \ + for ( k = 0; k < Gia_ObjCellSize(p,i) && ((iFanLit = Gia_ObjCellFanins(p,i)[k]),1); k++ ) + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define Gia_ManForEachObj( p, pObj, i ) \ + for ( i = 0; (i < p->nObjs) && ((pObj) = Gia_ManObj(p, i)); i++ ) +#define Gia_ManForEachObj1( p, pObj, i ) \ + for ( i = 1; (i < p->nObjs) && ((pObj) = Gia_ManObj(p, i)); i++ ) +#define Gia_ManForEachObjVec( vVec, p, pObj, i ) \ + for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Gia_ManObj(p, Vec_IntEntry(vVec,i))); i++ ) +#define Gia_ManForEachObjVecStart( vVec, p, pObj, i, Start ) \ + for ( i = Start; (i < Vec_IntSize(vVec)) && ((pObj) = Gia_ManObj(p, Vec_IntEntry(vVec,i))); i++ ) +#define Gia_ManForEachObjVecStop( vVec, p, pObj, i, Stop ) \ + for ( i = 0; (i < Stop) && ((pObj) = Gia_ManObj(p, Vec_IntEntry(vVec,i))); i++ ) +#define Gia_ManForEachObjVecStartStop( vVec, p, pObj, i, Start, Stop ) \ + for ( i = Start; (i < Stop) && ((pObj) = Gia_ManObj(p, Vec_IntEntry(vVec,i))); i++ ) +#define Gia_ManForEachObjVecReverse( vVec, p, pObj, i ) \ + for ( i = Vec_IntSize(vVec) - 1; (i >= 0) && ((pObj) = Gia_ManObj(p, Vec_IntEntry(vVec,i))); i-- ) +#define Gia_ManForEachObjVecLit( vVec, p, pObj, fCompl, i ) \ + for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Gia_ManObj(p, Abc_Lit2Var(Vec_IntEntry(vVec,i)))) && (((fCompl) = Abc_LitIsCompl(Vec_IntEntry(vVec,i))),1); i++ ) +#define Gia_ManForEachObjReverse( p, pObj, i ) \ + for ( i = p->nObjs - 1; (i >= 0) && ((pObj) = Gia_ManObj(p, i)); i-- ) +#define Gia_ManForEachObjReverse1( p, pObj, i ) \ + for ( i = p->nObjs - 1; (i > 0) && ((pObj) = Gia_ManObj(p, i)); i-- ) +#define Gia_ManForEachBuf( p, pObj, i ) \ + for ( i = Gia_ManBufNum(p) ? 0 : p->nObjs; (i < p->nObjs) && ((pObj) = Gia_ManObj(p, i)); i++ ) if ( !Gia_ObjIsBuf(pObj) ) {} else +#define Gia_ManForEachBufId( p, i ) \ + for ( i = 0; (i < p->nObjs); i++ ) if ( !Gia_ObjIsBuf(Gia_ManObj(p, i)) ) {} else +#define Gia_ManForEachAnd( p, pObj, i ) \ + for ( i = 0; (i < p->nObjs) && ((pObj) = Gia_ManObj(p, i)); i++ ) if ( !Gia_ObjIsAnd(pObj) ) {} else +#define Gia_ManForEachAndId( p, i ) \ + for ( i = 0; (i < p->nObjs); i++ ) if ( !Gia_ObjIsAnd(Gia_ManObj(p, i)) ) {} else +#define Gia_ManForEachMuxId( p, i ) \ + for ( i = 0; (i < p->nObjs); i++ ) if ( !Gia_ObjIsMuxId(p, i) ) {} else +#define Gia_ManForEachCand( p, pObj, i ) \ + for ( i = 0; (i < p->nObjs) && ((pObj) = Gia_ManObj(p, i)); i++ ) if ( !Gia_ObjIsCand(pObj) ) {} else +#define Gia_ManForEachAndReverse( p, pObj, i ) \ + for ( i = p->nObjs - 1; (i > 0) && ((pObj) = Gia_ManObj(p, i)); i-- ) if ( !Gia_ObjIsAnd(pObj) ) {} else +#define Gia_ManForEachAndReverseId( p, i ) \ + for ( i = p->nObjs - 1; (i > 0); i-- ) if ( !Gia_ObjIsAnd(Gia_ManObj(p, i)) ) {} else +#define Gia_ManForEachMux( p, pObj, i ) \ + for ( i = 0; (i < p->nObjs) && ((pObj) = Gia_ManObj(p, i)); i++ ) if ( !Gia_ObjIsMuxId(p, i) ) {} else +#define Gia_ManForEachCi( p, pObj, i ) \ + for ( i = 0; (i < Vec_IntSize(p->vCis)) && ((pObj) = Gia_ManCi(p, i)); i++ ) +#define Gia_ManForEachCiId( p, Id, i ) \ + for ( i = 0; (i < Vec_IntSize(p->vCis)) && ((Id) = Gia_ObjId(p, Gia_ManCi(p, i))); i++ ) +#define Gia_ManForEachCiVec( vVec, p, pObj, i ) \ + for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Gia_ManCi(p, Vec_IntEntry(vVec,i))); i++ ) +#define Gia_ManForEachCiReverse( p, pObj, i ) \ + for ( i = Vec_IntSize(p->vCis) - 1; (i >= 0) && ((pObj) = Gia_ManCi(p, i)); i-- ) +#define Gia_ManForEachCo( p, pObj, i ) \ + for ( i = 0; (i < Vec_IntSize(p->vCos)) && ((pObj) = Gia_ManCo(p, i)); i++ ) +#define Gia_ManForEachCoVec( vVec, p, pObj, i ) \ + for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Gia_ManCo(p, Vec_IntEntry(vVec,i))); i++ ) +#define Gia_ManForEachCoId( p, Id, i ) \ + for ( i = 0; (i < Vec_IntSize(p->vCos)) && ((Id) = Gia_ObjId(p, Gia_ManCo(p, i))); i++ ) +#define Gia_ManForEachCoReverse( p, pObj, i ) \ + for ( i = Vec_IntSize(p->vCos) - 1; (i >= 0) && ((pObj) = Gia_ManCo(p, i)); i-- ) +#define Gia_ManForEachCoDriver( p, pObj, i ) \ + for ( i = 0; (i < Vec_IntSize(p->vCos)) && ((pObj) = Gia_ObjFanin0(Gia_ManCo(p, i))); i++ ) +#define Gia_ManForEachCoDriverId( p, DriverId, i ) \ + for ( i = 0; (i < Vec_IntSize(p->vCos)) && (((DriverId) = Gia_ObjFaninId0p(p, Gia_ManCo(p, i))), 1); i++ ) +#define Gia_ManForEachPi( p, pObj, i ) \ + for ( i = 0; (i < Gia_ManPiNum(p)) && ((pObj) = Gia_ManCi(p, i)); i++ ) +#define Gia_ManForEachPo( p, pObj, i ) \ + for ( i = 0; (i < Gia_ManPoNum(p)) && ((pObj) = Gia_ManCo(p, i)); i++ ) +#define Gia_ManForEachRo( p, pObj, i ) \ + for ( i = 0; (i < Gia_ManRegNum(p)) && ((pObj) = Gia_ManCi(p, Gia_ManPiNum(p)+i)); i++ ) +#define Gia_ManForEachRi( p, pObj, i ) \ + for ( i = 0; (i < Gia_ManRegNum(p)) && ((pObj) = Gia_ManCo(p, Gia_ManPoNum(p)+i)); i++ ) +#define Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) \ + for ( i = 0; (i < Gia_ManRegNum(p)) && ((pObjRi) = Gia_ManCo(p, Gia_ManPoNum(p)+i)) && ((pObjRo) = Gia_ManCi(p, Gia_ManPiNum(p)+i)); i++ ) +#define Gia_ManForEachRoToRiVec( vRoIds, p, pObj, i ) \ + for ( i = 0; (i < Vec_IntSize(vRoIds)) && ((pObj) = Gia_ObjRoToRi(p, Gia_ManObj(p, Vec_IntEntry(vRoIds, i)))); i++ ) + +#define Gia_ManForEachObjWithBoxes( p, pObj, i ) \ + for ( i = p->iFirstAndObj; (i < p->iFirstPoObj) && ((pObj) = Gia_ManObj(p, i)); i++ ) +#define Gia_ManForEachObjReverseWithBoxes( p, pObj, i ) \ + for ( i = p->iFirstPoObj - 1; (i >= p->iFirstAndObj) && ((pObj) = Gia_ManObj(p, i)); i-- ) +#define Gia_ManForEachCiIdWithBoxes( p, Id, i ) \ + for ( i = 0; (i < p->iFirstNonPiId) && ((Id) = Gia_ObjId(p, Gia_ManCi(p, i))); i++ ) +#define Gia_ManForEachCoWithBoxes( p, pObj, i ) \ + for ( i = p->iFirstPoId; (i < Vec_IntSize(p->vCos)) && ((pObj) = Gia_ManCo(p, i)); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== giaAiger.c ===========================================================*/ +extern int Gia_FileSize( char * pFileName ); +extern Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSimple, int fSkipStrash, int fCheck ); +extern Gia_Man_t * Gia_AigerRead( char * pFileName, int fGiaSimple, int fSkipStrash, int fCheck ); +extern void Gia_AigerWrite( Gia_Man_t * p, char * pFileName, int fWriteSymbols, int fCompact, int fWriteNewLine ); +extern void Gia_AigerWriteS( Gia_Man_t * p, char * pFileName, int fWriteSymbols, int fCompact, int fWriteNewLine, int fSkipComment ); +extern void Gia_DumpAiger( Gia_Man_t * p, char * pFilePrefix, int iFileNum, int nFileNumDigits ); +extern Vec_Str_t * Gia_AigerWriteIntoMemoryStr( Gia_Man_t * p ); +extern Vec_Str_t * Gia_AigerWriteIntoMemoryStrPart( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos, int nRegs ); +extern void Gia_AigerWriteSimple( Gia_Man_t * pInit, char * pFileName ); +/*=== giaBalance.c ===========================================================*/ +extern Gia_Man_t * Gia_ManBalance( Gia_Man_t * p, int fSimpleAnd, int fStrict, int fVerbose ); +extern Gia_Man_t * Gia_ManAreaBalance( Gia_Man_t * p, int fSimpleAnd, int nNewNodesMax, int fVerbose, int fVeryVerbose ); +extern Gia_Man_t * Gia_ManAigSyn2( Gia_Man_t * p, int fOldAlgo, int fCoarsen, int fCutMin, int nRelaxRatio, int fDelayMin, int fVerbose, int fVeryVerbose ); +extern Gia_Man_t * Gia_ManAigSyn3( Gia_Man_t * p, int fVerbose, int fVeryVerbose ); +extern Gia_Man_t * Gia_ManAigSyn4( Gia_Man_t * p, int fVerbose, int fVeryVerbose ); +/*=== giaBidec.c ===========================================================*/ +extern unsigned * Gia_ManConvertAigToTruth( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vTruth, Vec_Int_t * vVisited ); +extern Gia_Man_t * Gia_ManPerformBidec( Gia_Man_t * p, int fVerbose ); +/*=== giaCex.c ============================================================*/ +extern int Gia_ManVerifyCex( Gia_Man_t * pAig, Abc_Cex_t * p, int fDualOut ); +extern int Gia_ManFindFailedPoCex( Gia_Man_t * pAig, Abc_Cex_t * p, int nOutputs ); +extern int Gia_ManSetFailedPoCex( Gia_Man_t * pAig, Abc_Cex_t * p ); +extern void Gia_ManCounterExampleValueStart( Gia_Man_t * pGia, Abc_Cex_t * pCex ); +extern void Gia_ManCounterExampleValueStop( Gia_Man_t * pGia ); +extern int Gia_ManCounterExampleValueLookup( Gia_Man_t * pGia, int Id, int iFrame ); +extern Abc_Cex_t * Gia_ManCexExtendToIncludeCurrentStates( Gia_Man_t * p, Abc_Cex_t * pCex ); +extern Abc_Cex_t * Gia_ManCexExtendToIncludeAllObjects( Gia_Man_t * p, Abc_Cex_t * pCex ); +/*=== giaCsatOld.c ============================================================*/ +extern Vec_Int_t * Cbs_ManSolveMiter( Gia_Man_t * pGia, int nConfs, Vec_Str_t ** pvStatus, int fVerbose ); +/*=== giaCsat.c ============================================================*/ +typedef struct Cbs_Man_t_ Cbs_Man_t; +extern Cbs_Man_t * Cbs_ManAlloc( Gia_Man_t * pGia ); +extern void Cbs_ManStop( Cbs_Man_t * p ); +extern int Cbs_ManSolve( Cbs_Man_t * p, Gia_Obj_t * pObj ); +extern int Cbs_ManSolve2( Cbs_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pObj2 ); +extern Vec_Int_t * Cbs_ManSolveMiterNc( Gia_Man_t * pGia, int nConfs, Vec_Str_t ** pvStatus, int f0Proved, int fVerbose ); +extern void Cbs_ManSetConflictNum( Cbs_Man_t * p, int Num ); +extern Vec_Int_t * Cbs_ReadModel( Cbs_Man_t * p ); +/*=== giaCTas.c ============================================================*/ +extern Vec_Int_t * Tas_ManSolveMiterNc( Gia_Man_t * pGia, int nConfs, Vec_Str_t ** pvStatus, int fVerbose ); +/*=== giaCof.c =============================================================*/ +extern void Gia_ManPrintFanio( Gia_Man_t * pGia, int nNodes ); +extern Gia_Man_t * Gia_ManDupCof( Gia_Man_t * p, int iVar ); +extern Gia_Man_t * Gia_ManDupCofAllInt( Gia_Man_t * p, Vec_Int_t * vSigs, int fVerbose ); +extern Gia_Man_t * Gia_ManDupCofAll( Gia_Man_t * p, int nFanLim, int fVerbose ); +/*=== giaDecs.c ============================================================*/ +extern int Gia_ResubVarNum( Vec_Int_t * vResub ); +extern word Gia_ResubToTruth6( Vec_Int_t * vResub ); +extern int Gia_ManEvalSolutionOne( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * vSet, int nWords, int fVerbose ); +extern Vec_Int_t * Gia_ManDeriveSolutionOne( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * vSet, int nWords, int Type ); +/*=== giaDfs.c ============================================================*/ +extern void Gia_ManCollectCis( Gia_Man_t * p, int * pNodes, int nNodes, Vec_Int_t * vSupp ); +extern void Gia_ManCollectAnds_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vNodes ); +extern void Gia_ManCollectAnds( Gia_Man_t * p, int * pNodes, int nNodes, Vec_Int_t * vNodes, Vec_Int_t * vLeaves ); +extern Vec_Int_t * Gia_ManCollectAndsAll( Gia_Man_t * p ); +extern Vec_Int_t * Gia_ManCollectNodesCis( Gia_Man_t * p, int * pNodes, int nNodes ); +extern int Gia_ManSuppSize( Gia_Man_t * p, int * pNodes, int nNodes ); +extern int Gia_ManConeSize( Gia_Man_t * p, int * pNodes, int nNodes ); +extern Vec_Vec_t * Gia_ManLevelize( Gia_Man_t * p ); +extern Vec_Wec_t * Gia_ManLevelizeR( Gia_Man_t * p ); +extern Vec_Int_t * Gia_ManOrderReverse( Gia_Man_t * p ); +extern void Gia_ManCollectTfi( Gia_Man_t * p, Vec_Int_t * vRoots, Vec_Int_t * vNodes ); +extern void Gia_ManCollectTfo( Gia_Man_t * p, Vec_Int_t * vRoots, Vec_Int_t * vNodes ); +/*=== giaDup.c ============================================================*/ +extern void Gia_ManDupRemapLiterals( Vec_Int_t * vLits, Gia_Man_t * p ); +extern void Gia_ManDupRemapEquiv( Gia_Man_t * pNew, Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupOrderDfs( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupOrderDfsChoices( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupOrderDfsReverse( Gia_Man_t * p, int fRevFans, int fRevOuts ); +extern Gia_Man_t * Gia_ManDupOutputGroup( Gia_Man_t * p, int iOutStart, int iOutStop ); +extern Gia_Man_t * Gia_ManDupOutputVec( Gia_Man_t * p, Vec_Int_t * vOutPres ); +extern Gia_Man_t * Gia_ManDupSelectedOutputs( Gia_Man_t * p, Vec_Int_t * vOutsLeft ); +extern Gia_Man_t * Gia_ManDupOrderAiger( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupLastPis( Gia_Man_t * p, int nLastPis ); +extern Gia_Man_t * Gia_ManDupFlip( Gia_Man_t * p, int * pInitState ); +extern Gia_Man_t * Gia_ManDupCycled( Gia_Man_t * pAig, Abc_Cex_t * pCex, int nFrames ); +extern Gia_Man_t * Gia_ManDup( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupNoBuf( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupMap( Gia_Man_t * p, Vec_Int_t * vMap ); +extern Gia_Man_t * Gia_ManDup2( Gia_Man_t * p1, Gia_Man_t * p2 ); +extern Gia_Man_t * Gia_ManDupWithAttributes( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupRemovePis( Gia_Man_t * p, int nRemPis ); +extern Gia_Man_t * Gia_ManDupZero( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupPerm( Gia_Man_t * p, Vec_Int_t * vPiPerm ); +extern Gia_Man_t * Gia_ManDupPermFlop( Gia_Man_t * p, Vec_Int_t * vFfPerm ); +extern Gia_Man_t * Gia_ManDupPermFlopGap( Gia_Man_t * p, Vec_Int_t * vFfPerm ); +extern void Gia_ManDupAppend( Gia_Man_t * p, Gia_Man_t * pTwo ); +extern void Gia_ManDupAppendShare( Gia_Man_t * p, Gia_Man_t * pTwo ); +extern Gia_Man_t * Gia_ManDupAppendNew( Gia_Man_t * pOne, Gia_Man_t * pTwo ); +extern Gia_Man_t * Gia_ManDupAppendCones( Gia_Man_t * p, Gia_Man_t ** ppCones, int nCones, int fOnlyRegs ); +extern Gia_Man_t * Gia_ManDupSelf( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupFlopClass( Gia_Man_t * p, int iClass ); +extern Gia_Man_t * Gia_ManDupMarked( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupTimes( Gia_Man_t * p, int nTimes ); +extern Gia_Man_t * Gia_ManDupDfs( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupDfsOnePo( Gia_Man_t * p, int iPo ); +extern Gia_Man_t * Gia_ManDupDfsRehash( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupCofactorVar( Gia_Man_t * p, int iVar, int Value ); +extern Gia_Man_t * Gia_ManDupCofactorObj( Gia_Man_t * p, int iObj, int Value ); +extern Gia_Man_t * Gia_ManDupMux( int iVar, Gia_Man_t * pCof1, Gia_Man_t * pCof0 ); +extern Gia_Man_t * Gia_ManDupBlock( Gia_Man_t * p, int nBlock ); +extern Gia_Man_t * Gia_ManDupExist( Gia_Man_t * p, int iVar ); +extern Gia_Man_t * Gia_ManDupUniv( Gia_Man_t * p, int iVar ); +extern Gia_Man_t * Gia_ManDupDfsSkip( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupDfsCone( Gia_Man_t * p, Gia_Obj_t * pObj ); +extern Gia_Man_t * Gia_ManDupConeSupp( Gia_Man_t * p, int iLit, Vec_Int_t * vCiIds ); +extern int Gia_ManDupConeBack( Gia_Man_t * p, Gia_Man_t * pNew, Vec_Int_t * vCiIds ); +extern int Gia_ManDupConeBackObjs( Gia_Man_t * p, Gia_Man_t * pNew, Vec_Int_t * vObjs ); +extern Gia_Man_t * Gia_ManDupDfsNode( Gia_Man_t * p, Gia_Obj_t * pObj ); +extern Gia_Man_t * Gia_ManDupDfsLitArray( Gia_Man_t * p, Vec_Int_t * vLits ); +extern Gia_Man_t * Gia_ManDupTrimmed( Gia_Man_t * p, int fTrimCis, int fTrimCos, int fDualOut, int OutValue ); +extern Gia_Man_t * Gia_ManDupOntop( Gia_Man_t * p, Gia_Man_t * p2 ); +extern Gia_Man_t * Gia_ManDupWithNewPo( Gia_Man_t * p1, Gia_Man_t * p2 ); +extern Gia_Man_t * Gia_ManDupDfsCiMap( Gia_Man_t * p, int * pCi2Lit, Vec_Int_t * vLits ); +extern Gia_Man_t * Gia_ManPermuteInputs( Gia_Man_t * p, int nPpis, int nExtra ); +extern Gia_Man_t * Gia_ManDupDfsClasses( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupTopAnd( Gia_Man_t * p, int fVerbose ); +extern Gia_Man_t * Gia_ManMiter( Gia_Man_t * pAig0, Gia_Man_t * pAig1, int nInsDup, int fDualOut, int fSeq, int fImplic, int fVerbose ); +extern Gia_Man_t * Gia_ManMiterInverse( Gia_Man_t * pBot, Gia_Man_t * pTop, int fDualOut, int fVerbose ); +extern Gia_Man_t * Gia_ManDupAndOr( Gia_Man_t * p, int nOuts, int fUseOr, int fCompl ); +extern Gia_Man_t * Gia_ManDupZeroUndc( Gia_Man_t * p, char * pInit, int nNewPis, int fGiaSimple, int fVerbose ); +extern Gia_Man_t * Gia_ManMiter2( Gia_Man_t * p, char * pInit, int fVerbose ); +extern Gia_Man_t * Gia_ManTransformMiter( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManTransformMiter2( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManTransformToDual( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManTransformTwoWord2DualOutput( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManChoiceMiter( Vec_Ptr_t * vGias ); +extern Gia_Man_t * Gia_ManDupWithConstraints( Gia_Man_t * p, Vec_Int_t * vPoTypes ); +extern Gia_Man_t * Gia_ManDupCones( Gia_Man_t * p, int * pPos, int nPos, int fTrimPis ); +extern Gia_Man_t * Gia_ManDupAndCones( Gia_Man_t * p, int * pAnds, int nAnds, int fTrimPis ); +extern Gia_Man_t * Gia_ManDupAndConesLimit( Gia_Man_t * p, int * pAnds, int nAnds, int Level ); +extern Gia_Man_t * Gia_ManDupAndConesLimit2( Gia_Man_t * p, int * pAnds, int nAnds, int Level ); +extern Gia_Man_t * Gia_ManDupOneHot( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupLevelized( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupFromVecs( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos, int nRegs ); +extern Gia_Man_t * Gia_ManDupSliced( Gia_Man_t * p, int nSuppMax ); +extern Gia_Man_t * Gia_ManDupDemiter( Gia_Man_t * p, int fVerbose ); +extern Gia_Man_t * Gia_ManDemiterToDual( Gia_Man_t * p ); +extern int Gia_ManDemiterDual( Gia_Man_t * p, Gia_Man_t ** pp0, Gia_Man_t ** pp1 ); +extern int Gia_ManDemiterTwoWords( Gia_Man_t * p, Gia_Man_t ** pp0, Gia_Man_t ** pp1 ); +extern void Gia_ManProdAdderGen( int nArgA, int nArgB, int Seed, int fSigned, int fCla ); +/*=== giaEdge.c ==========================================================*/ +extern void Gia_ManEdgeFromArray( Gia_Man_t * p, Vec_Int_t * vArray ); +extern Vec_Int_t * Gia_ManEdgeToArray( Gia_Man_t * p ); +extern void Gia_ManConvertPackingToEdges( Gia_Man_t * p ); +extern int Gia_ObjCheckEdge( Gia_Man_t * p, int iObj, int iNext ); +extern int Gia_ManEvalEdgeDelay( Gia_Man_t * p ); +extern int Gia_ManEvalEdgeCount( Gia_Man_t * p ); +extern int Gia_ManComputeEdgeDelay( Gia_Man_t * p, int fUseTwo ); +extern int Gia_ManComputeEdgeDelay2( Gia_Man_t * p ); +extern void Gia_ManUpdateMapping( Gia_Man_t * p, Vec_Int_t * vNodes, Vec_Wec_t * vWin ); +extern int Gia_ManEvalWindow( Gia_Man_t * p, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Wec_t * vWin, Vec_Int_t * vTemp, int fUseTwo ); +/*=== giaEnable.c ==========================================================*/ +extern void Gia_ManDetectSeqSignals( Gia_Man_t * p, int fSetReset, int fVerbose ); +extern Gia_Man_t * Gia_ManUnrollAndCofactor( Gia_Man_t * p, int nFrames, int nFanMax, int fVerbose ); +extern Gia_Man_t * Gia_ManRemoveEnables( Gia_Man_t * p ); +/*=== giaEquiv.c ==========================================================*/ +extern void Gia_ManOrigIdsInit( Gia_Man_t * p ); +extern void Gia_ManOrigIdsStart( Gia_Man_t * p ); +extern void Gia_ManOrigIdsRemap( Gia_Man_t * p, Gia_Man_t * pNew ); +extern Gia_Man_t * Gia_ManOrigIdsReduce( Gia_Man_t * p, Vec_Int_t * vPairs ); +extern Gia_Man_t * Gia_ManComputeGiaEquivs( Gia_Man_t * pGia, int nConfs, int fVerbose ); +extern void Gia_ManEquivFixOutputPairs( Gia_Man_t * p ); +extern int Gia_ManCheckTopoOrder( Gia_Man_t * p ); +extern int * Gia_ManDeriveNexts( Gia_Man_t * p ); +extern void Gia_ManDeriveReprs( Gia_Man_t * p ); +extern void Gia_ManDeriveReprsFromSibls( Gia_Man_t *p ); +extern int Gia_ManEquivCountLits( Gia_Man_t * p ); +extern int Gia_ManEquivCountLitsAll( Gia_Man_t * p ); +extern int Gia_ManEquivCountClasses( Gia_Man_t * p ); +extern void Gia_ManEquivPrintOne( Gia_Man_t * p, int i, int Counter ); +extern void Gia_ManEquivPrintClasses( Gia_Man_t * p, int fVerbose, float Mem ); +extern Gia_Man_t * Gia_ManEquivReduce( Gia_Man_t * p, int fUseAll, int fDualOut, int fSkipPhase, int fVerbose ); +extern Gia_Man_t * Gia_ManEquivReduceAndRemap( Gia_Man_t * p, int fSeq, int fMiterPairs ); +extern int Gia_ManEquivSetColors( Gia_Man_t * p, int fVerbose ); +extern Gia_Man_t * Gia_ManSpecReduce( Gia_Man_t * p, int fDualOut, int fSynthesis, int fReduce, int fSkipSome, int fVerbose ); +extern Gia_Man_t * Gia_ManSpecReduceInit( Gia_Man_t * p, Abc_Cex_t * pInit, int nFrames, int fDualOut ); +extern Gia_Man_t * Gia_ManSpecReduceInitFrames( Gia_Man_t * p, Abc_Cex_t * pInit, int nFramesMax, int * pnFrames, int fDualOut, int nMinOutputs ); +extern void Gia_ManEquivTransform( Gia_Man_t * p, int fVerbose ); +extern void Gia_ManEquivImprove( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManEquivToChoices( Gia_Man_t * p, int nSnapshots ); +extern int Gia_ManCountChoiceNodes( Gia_Man_t * p ); +extern int Gia_ManCountChoices( Gia_Man_t * p ); +extern int Gia_ManFilterEquivsForSpeculation( Gia_Man_t * pGia, char * pName1, char * pName2, int fLatchA, int fLatchB ); +extern int Gia_ManFilterEquivsUsingParts( Gia_Man_t * pGia, char * pName1, char * pName2 ); +extern void Gia_ManFilterEquivsUsingLatches( Gia_Man_t * pGia, int fFlopsOnly, int fFlopsWith, int fUseRiDrivers ); +/*=== giaExist.c =========================================================*/ +extern void Gia_ManQuantSetSuppStart( Gia_Man_t * p ); +extern void Gia_ManQuantSetSuppZero( Gia_Man_t * p ); +extern void Gia_ManQuantSetSuppCi( Gia_Man_t * p, Gia_Obj_t * pObj ); +extern void Gia_ManQuantUpdateCiSupp( Gia_Man_t * p, int iObj ); +extern int Gia_ManQuantExist( Gia_Man_t * p, int iLit, int(*pFuncCiToKeep)(void *, int), void * pData ); +/*=== giaFanout.c =========================================================*/ +extern void Gia_ObjAddFanout( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanout ); +extern void Gia_ObjRemoveFanout( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanout ); +extern void Gia_ManFanoutStart( Gia_Man_t * p ); +extern void Gia_ManFanoutStop( Gia_Man_t * p ); +extern void Gia_ManStaticFanoutStart( Gia_Man_t * p ); +extern void Gia_ManStaticFanoutStop( Gia_Man_t * p ); +extern void Gia_ManStaticMappingFanoutStart( Gia_Man_t * p, Vec_Int_t ** pvIndex ); +/*=== giaForce.c =========================================================*/ +extern void For_ManExperiment( Gia_Man_t * pGia, int nIters, int fClustered, int fVerbose ); +/*=== giaFrames.c =========================================================*/ +extern Gia_Man_t * Gia_ManUnrollDup( Gia_Man_t * p, Vec_Int_t * vLimit ); +extern Vec_Ptr_t * Gia_ManUnrollAbs( Gia_Man_t * p, int nFrames ); +extern void * Gia_ManUnrollStart( Gia_Man_t * pAig, Gia_ParFra_t * pPars ); +extern void * Gia_ManUnrollAdd( void * pMan, int fMax ); +extern void Gia_ManUnrollStop( void * pMan ); +extern int Gia_ManUnrollLastLit( void * pMan ); +extern void Gia_ManFraSetDefaultParams( Gia_ParFra_t * p ); +extern Gia_Man_t * Gia_ManFrames( Gia_Man_t * pAig, Gia_ParFra_t * pPars ); +extern Gia_Man_t * Gia_ManFramesInitSpecial( Gia_Man_t * pAig, int nFrames, int fVerbose ); +/*=== giaFront.c ==========================================================*/ +extern Gia_Man_t * Gia_ManFront( Gia_Man_t * p ); +extern void Gia_ManFrontTest( Gia_Man_t * p ); +/*=== giaFx.c ==========================================================*/ +extern Gia_Man_t * Gia_ManPerformFx( Gia_Man_t * p, int nNewNodesMax, int LitCountMax, int fReverse, int fVerbose, int fVeryVerbose ); +/*=== giaHash.c ===========================================================*/ +extern void Gia_ManHashAlloc( Gia_Man_t * p ); +extern void Gia_ManHashStart( Gia_Man_t * p ); +extern void Gia_ManHashStop( Gia_Man_t * p ); +extern int Gia_ManHashXorReal( Gia_Man_t * p, int iLit0, int iLit1 ); +extern int Gia_ManHashMuxReal( Gia_Man_t * p, int iLitC, int iLit1, int iLit0 ); +extern int Gia_ManHashAnd( Gia_Man_t * p, int iLit0, int iLit1 ); +extern int Gia_ManHashOr( Gia_Man_t * p, int iLit0, int iLit1 ); +extern int Gia_ManHashXor( Gia_Man_t * p, int iLit0, int iLit1 ); +extern int Gia_ManHashMux( Gia_Man_t * p, int iCtrl, int iData1, int iData0 ); +extern int Gia_ManHashMaj( Gia_Man_t * p, int iData0, int iData1, int iData2 ); +extern int Gia_ManHashAndTry( Gia_Man_t * p, int iLit0, int iLit1 ); +extern Gia_Man_t * Gia_ManRehash( Gia_Man_t * p, int fAddStrash ); +extern void Gia_ManHashProfile( Gia_Man_t * p ); +extern int Gia_ManHashLookupInt( Gia_Man_t * p, int iLit0, int iLit1 ); +extern int Gia_ManHashLookup( Gia_Man_t * p, Gia_Obj_t * p0, Gia_Obj_t * p1 ); +extern int Gia_ManHashAndMulti( Gia_Man_t * p, Vec_Int_t * vLits ); +extern int Gia_ManHashAndMulti2( Gia_Man_t * p, Vec_Int_t * vLits ); +extern int Gia_ManHashDualMiter( Gia_Man_t * p, Vec_Int_t * vOuts ); +/*=== giaIf.c ===========================================================*/ +extern void Gia_ManPrintMappingStats( Gia_Man_t * p, char * pDumpFile ); +extern void Gia_ManPrintPackingStats( Gia_Man_t * p ); +extern void Gia_ManPrintLutStats( Gia_Man_t * p ); +extern int Gia_ManLutFaninCount( Gia_Man_t * p ); +extern int Gia_ManLutSizeMax( Gia_Man_t * p ); +extern int Gia_ManLutNum( Gia_Man_t * p ); +extern int Gia_ManLutLevel( Gia_Man_t * p, int ** ppLevels ); +extern void Gia_ManLutParams( Gia_Man_t * p, int * pnCurLuts, int * pnCurEdges, int * pnCurLevels ); +extern void Gia_ManSetRefsMapped( Gia_Man_t * p ); +extern void Gia_ManSetLutRefs( Gia_Man_t * p ); +extern void Gia_ManSetIfParsDefault( void * pIfPars ); +extern void Gia_ManMappingVerify( Gia_Man_t * p ); +extern void Gia_ManTransferMapping( Gia_Man_t * p, Gia_Man_t * pGia ); +extern void Gia_ManTransferPacking( Gia_Man_t * p, Gia_Man_t * pGia ); +extern void Gia_ManTransferTiming( Gia_Man_t * p, Gia_Man_t * pGia ); +extern Gia_Man_t * Gia_ManPerformMapping( Gia_Man_t * p, void * pIfPars ); +extern Gia_Man_t * Gia_ManPerformSopBalance( Gia_Man_t * p, int nCutNum, int nRelaxRatio, int fVerbose ); +extern Gia_Man_t * Gia_ManPerformDsdBalance( Gia_Man_t * p, int nLutSize, int nCutNum, int nRelaxRatio, int fVerbose ); +extern Gia_Man_t * Gia_ManDupHashMapping( Gia_Man_t * p ); +/*=== giaJf.c ===========================================================*/ +extern void Jf_ManSetDefaultPars( Jf_Par_t * pPars ); +extern Gia_Man_t * Jf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ); +extern Gia_Man_t * Jf_ManDeriveCnf( Gia_Man_t * p, int fCnfObjIds ); +/*=== giaIso.c ===========================================================*/ +extern Gia_Man_t * Gia_ManIsoCanonicize( Gia_Man_t * p, int fVerbose ); +extern Gia_Man_t * Gia_ManIsoReduce( Gia_Man_t * p, Vec_Ptr_t ** pvPosEquivs, Vec_Ptr_t ** pvPiPerms, int fEstimate, int fDualOut, int fVerbose, int fVeryVerbose ); +extern Gia_Man_t * Gia_ManIsoReduce2( Gia_Man_t * p, Vec_Ptr_t ** pvPosEquivs, Vec_Ptr_t ** pvPiPerms, int fEstimate, int fBetterQual, int fDualOut, int fVerbose, int fVeryVerbose ); +/*=== giaLf.c ===========================================================*/ +extern void Lf_ManSetDefaultPars( Jf_Par_t * pPars ); +extern Gia_Man_t * Lf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ); +extern Gia_Man_t * Gia_ManPerformLfMapping( Gia_Man_t * p, Jf_Par_t * pPars, int fNormalized ); +/*=== giaLogic.c ===========================================================*/ +extern void Gia_ManTestDistance( Gia_Man_t * p ); +extern void Gia_ManSolveProblem( Gia_Man_t * pGia, Emb_Par_t * pPars ); + /*=== giaMan.c ===========================================================*/ +extern Gia_Man_t * Gia_ManStart( int nObjsMax ); +extern void Gia_ManStop( Gia_Man_t * p ); +extern void Gia_ManStopP( Gia_Man_t ** p ); +extern double Gia_ManMemory( Gia_Man_t * p ); +extern void Gia_ManPrintStats( Gia_Man_t * p, Gps_Par_t * pPars ); +extern void Gia_ManPrintStatsShort( Gia_Man_t * p ); +extern void Gia_ManPrintMiterStatus( Gia_Man_t * p ); +extern void Gia_ManPrintStatsMiter( Gia_Man_t * p, int fVerbose ); +extern void Gia_ManSetRegNum( Gia_Man_t * p, int nRegs ); +extern void Gia_ManReportImprovement( Gia_Man_t * p, Gia_Man_t * pNew ); +extern void Gia_ManPrintNpnClasses( Gia_Man_t * p ); +extern void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter, int fInterComb, int fAssign, int fReverse ); +extern void Gia_ManDumpVerilogNand( Gia_Man_t * p, char * pFileName ); +/*=== giaMem.c ===========================================================*/ +extern Gia_MmFixed_t * Gia_MmFixedStart( int nEntrySize, int nEntriesMax ); +extern void Gia_MmFixedStop( Gia_MmFixed_t * p, int fVerbose ); +extern char * Gia_MmFixedEntryFetch( Gia_MmFixed_t * p ); +extern void Gia_MmFixedEntryRecycle( Gia_MmFixed_t * p, char * pEntry ); +extern void Gia_MmFixedRestart( Gia_MmFixed_t * p ); +extern int Gia_MmFixedReadMemUsage( Gia_MmFixed_t * p ); +extern int Gia_MmFixedReadMaxEntriesUsed( Gia_MmFixed_t * p ); +extern Gia_MmFlex_t * Gia_MmFlexStart(); +extern void Gia_MmFlexStop( Gia_MmFlex_t * p, int fVerbose ); +extern char * Gia_MmFlexEntryFetch( Gia_MmFlex_t * p, int nBytes ); +extern void Gia_MmFlexRestart( Gia_MmFlex_t * p ); +extern int Gia_MmFlexReadMemUsage( Gia_MmFlex_t * p ); +extern Gia_MmStep_t * Gia_MmStepStart( int nSteps ); +extern void Gia_MmStepStop( Gia_MmStep_t * p, int fVerbose ); +extern char * Gia_MmStepEntryFetch( Gia_MmStep_t * p, int nBytes ); +extern void Gia_MmStepEntryRecycle( Gia_MmStep_t * p, char * pEntry, int nBytes ); +extern int Gia_MmStepReadMemUsage( Gia_MmStep_t * p ); +/*=== giaMf.c ===========================================================*/ +extern void Mf_ManSetDefaultPars( Jf_Par_t * pPars ); +extern Gia_Man_t * Mf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ); +extern void * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fMapping, int fVerbose ); +/*=== giaMini.c ===========================================================*/ +extern Gia_Man_t * Gia_ManReadMiniAig( char * pFileName, int fGiaSimple ); +extern void Gia_ManWriteMiniAig( Gia_Man_t * pGia, char * pFileName ); +extern Gia_Man_t * Gia_ManReadMiniLut( char * pFileName ); +extern void Gia_ManWriteMiniLut( Gia_Man_t * pGia, char * pFileName ); +/*=== giaMinLut.c ===========================================================*/ +extern word * Gia_ManCountFraction( Gia_Man_t * p, Vec_Wrd_t * vSimI, Vec_Int_t * vSupp, int Thresh, int fVerbose, int * pCare ); +extern Vec_Int_t * Gia_ManCollectSuppNew( Gia_Man_t * p, int iOut, int nOuts ); +/*=== giaMuxes.c ===========================================================*/ +extern void Gia_ManCountMuxXor( Gia_Man_t * p, int * pnMuxes, int * pnXors ); +extern void Gia_ManPrintMuxStats( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupMuxes( Gia_Man_t * p, int Limit ); +extern Gia_Man_t * Gia_ManDupNoMuxes( Gia_Man_t * p, int fSkipBufs ); +/*=== giaPat.c ===========================================================*/ +extern void Gia_SatVerifyPattern( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vCex, Vec_Int_t * vVisit ); +/*=== giaRetime.c ===========================================================*/ +extern Gia_Man_t * Gia_ManRetimeForward( Gia_Man_t * p, int nMaxIters, int fVerbose ); +/*=== giaSat.c ============================================================*/ +extern int Sat_ManTest( Gia_Man_t * pGia, Gia_Obj_t * pObj, int nConfsMax ); +/*=== giaScl.c ============================================================*/ +extern int Gia_ManSeqMarkUsed( Gia_Man_t * p ); +extern int Gia_ManCombMarkUsed( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManCleanup( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManCleanupOutputs( Gia_Man_t * p, int nOutputs ); +extern Gia_Man_t * Gia_ManSeqCleanup( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManSeqStructSweep( Gia_Man_t * p, int fConst, int fEquiv, int fVerbose ); +/*=== giaShow.c ===========================================================*/ +extern void Gia_ManShow( Gia_Man_t * pMan, Vec_Int_t * vBold, int fAdders, int fFadds, int fPath ); +/*=== giaShrink.c ===========================================================*/ +extern Gia_Man_t * Gia_ManMapShrink4( Gia_Man_t * p, int fKeepLevel, int fVerbose ); +extern Gia_Man_t * Gia_ManMapShrink6( Gia_Man_t * p, int nFanoutMax, int fKeepLevel, int fVerbose ); +/*=== giaSopb.c ============================================================*/ +extern Gia_Man_t * Gia_ManExtractWindow( Gia_Man_t * p, int LevelMax, int nTimeWindow, int fVerbose ); +extern Gia_Man_t * Gia_ManPerformSopBalanceWin( Gia_Man_t * p, int LevelMax, int nTimeWindow, int nCutNum, int nRelaxRatio, int fVerbose ); +extern Gia_Man_t * Gia_ManPerformDsdBalanceWin( Gia_Man_t * p, int LevelMax, int nTimeWindow, int nLutSize, int nCutNum, int nRelaxRatio, int fVerbose ); +/*=== giaSort.c ============================================================*/ +extern int * Gia_SortFloats( float * pArray, int * pPerm, int nSize ); +/*=== giaSim.c ============================================================*/ +extern void Gia_ManSimSetDefaultParams( Gia_ParSim_t * p ); +extern int Gia_ManSimSimulate( Gia_Man_t * pAig, Gia_ParSim_t * pPars ); +extern unsigned * Gia_SimDataExt( Gia_ManSim_t * p, int i ); +extern unsigned * Gia_SimDataCiExt( Gia_ManSim_t * p, int i ); +extern unsigned * Gia_SimDataCoExt( Gia_ManSim_t * p, int i ); +extern void Gia_ManSimInfoInit( Gia_ManSim_t * p ); +extern void Gia_ManSimInfoTransfer( Gia_ManSim_t * p ); +extern void Gia_ManSimulateRound( Gia_ManSim_t * p ); +extern void Gia_ManBuiltInSimStart( Gia_Man_t * p, int nWords, int nObjs ); +extern void Gia_ManBuiltInSimPerform( Gia_Man_t * p, int iObj ); +extern int Gia_ManBuiltInSimCheckOver( Gia_Man_t * p, int iLit0, int iLit1 ); +extern int Gia_ManBuiltInSimCheckEqual( Gia_Man_t * p, int iLit0, int iLit1 ); +extern void Gia_ManBuiltInSimResimulateCone( Gia_Man_t * p, int iLit0, int iLit1 ); +extern void Gia_ManBuiltInSimResimulate( Gia_Man_t * p ); +extern int Gia_ManBuiltInSimAddPat( Gia_Man_t * p, Vec_Int_t * vPat ); +extern void Gia_ManIncrSimStart( Gia_Man_t * p, int nWords, int nObjs ); +extern void Gia_ManIncrSimSet( Gia_Man_t * p, Vec_Int_t * vObjLits ); +extern int Gia_ManIncrSimCheckOver( Gia_Man_t * p, int iLit0, int iLit1 ); +extern int Gia_ManIncrSimCheckEqual( Gia_Man_t * p, int iLit0, int iLit1 ); +/*=== giaSimBase.c ============================================================*/ +extern Vec_Wrd_t * Gia_ManSimPatSim( Gia_Man_t * p ); +extern Vec_Wrd_t * Gia_ManSimPatSimOut( Gia_Man_t * pGia, Vec_Wrd_t * vSimsPi, int fOuts ); +extern void Gia_ManSim2ArrayOne( Vec_Wrd_t * vSimsPi, Vec_Int_t * vRes ); +extern Vec_Wec_t * Gia_ManSim2Array( Vec_Ptr_t * vSims ); +extern Vec_Wrd_t * Gia_ManArray2SimOne( Vec_Int_t * vRes ); +extern Vec_Ptr_t * Gia_ManArray2Sim( Vec_Wec_t * vRes ); +extern void Gia_ManPtrWrdDumpBin( char * pFileName, Vec_Ptr_t * p, int fVerbose ); +extern Vec_Ptr_t * Gia_ManPtrWrdReadBin( char * pFileName, int fVerbose ); +extern Vec_Str_t * Gia_ManComputeRange( Gia_Man_t * p ); +/*=== giaSpeedup.c ============================================================*/ +extern float Gia_ManDelayTraceLut( Gia_Man_t * p ); +extern float Gia_ManDelayTraceLutPrint( Gia_Man_t * p, int fVerbose ); +extern Gia_Man_t * Gia_ManSpeedup( Gia_Man_t * p, int Percentage, int Degree, int fVerbose, int fVeryVerbose ); +/*=== giaSplit.c ============================================================*/ +extern void Gia_ManComputeOneWinStart( Gia_Man_t * p, int nAnds, int fReverse ); +extern int Gia_ManComputeOneWin( Gia_Man_t * p, int iPivot, Vec_Int_t ** pvRoots, Vec_Int_t ** pvNodes, Vec_Int_t ** pvLeaves, Vec_Int_t ** pvAnds ); +/*=== giaStg.c ============================================================*/ +extern void Gia_ManStgPrint( FILE * pFile, Vec_Int_t * vLines, int nIns, int nOuts, int nStates ); +extern Gia_Man_t * Gia_ManStgRead( char * pFileName, int kHot, int fVerbose ); +/*=== giaSupp.c ============================================================*/ +typedef struct Gia_ManMin_t_ Gia_ManMin_t; +extern Gia_ManMin_t * Gia_ManSuppStart( Gia_Man_t * pGia ); +extern void Gia_ManSuppStop( Gia_ManMin_t * p ); +extern int Gia_ManSupportAnd( Gia_ManMin_t * p, int iLit0, int iLit1 ); +typedef struct Gia_Man2Min_t_ Gia_Man2Min_t; +extern Gia_Man2Min_t * Gia_Man2SuppStart( Gia_Man_t * pGia ); +extern void Gia_Man2SuppStop( Gia_Man2Min_t * p ); +extern int Gia_Man2SupportAnd( Gia_Man2Min_t * p, int iLit0, int iLit1 ); +/*=== giaSweep.c ============================================================*/ +extern Gia_Man_t * Gia_ManFraigSweepSimple( Gia_Man_t * p, void * pPars ); +extern Gia_Man_t * Gia_ManSweepWithBoxes( Gia_Man_t * p, void * pParsC, void * pParsS, int fConst, int fEquiv, int fVerbose, int fVerbEquivs ); +extern void Gia_ManCheckIntegrityWithBoxes( Gia_Man_t * p ); +/*=== giaSweeper.c ============================================================*/ +extern Gia_Man_t * Gia_SweeperStart( Gia_Man_t * p ); +extern void Gia_SweeperStop( Gia_Man_t * p ); +extern int Gia_SweeperIsRunning( Gia_Man_t * p ); +extern void Gia_SweeperPrintStats( Gia_Man_t * p ); +extern void Gia_SweeperSetConflictLimit( Gia_Man_t * p, int nConfMax ); +extern void Gia_SweeperSetRuntimeLimit( Gia_Man_t * p, int nSeconds ); +extern Vec_Int_t * Gia_SweeperGetCex( Gia_Man_t * p ); +extern int Gia_SweeperProbeCreate( Gia_Man_t * p, int iLit ); +extern int Gia_SweeperProbeDelete( Gia_Man_t * p, int ProbeId ); +extern int Gia_SweeperProbeUpdate( Gia_Man_t * p, int ProbeId, int iLitNew ); +extern int Gia_SweeperProbeLit( Gia_Man_t * p, int ProbeId ); +extern Vec_Int_t * Gia_SweeperCollectValidProbeIds( Gia_Man_t * p ); +extern int Gia_SweeperCondPop( Gia_Man_t * p ); +extern void Gia_SweeperCondPush( Gia_Man_t * p, int ProbeId ); +extern Vec_Int_t * Gia_SweeperCondVector( Gia_Man_t * p ); +extern int Gia_SweeperCondCheckUnsat( Gia_Man_t * p ); +extern int Gia_SweeperCheckEquiv( Gia_Man_t * p, int ProbeId1, int ProbeId2 ); +extern Gia_Man_t * Gia_SweeperExtractUserLogic( Gia_Man_t * p, Vec_Int_t * vProbeIds, Vec_Ptr_t * vInNames, Vec_Ptr_t * vOutNames ); +extern void Gia_SweeperLogicDump( Gia_Man_t * p, Vec_Int_t * vProbeIds, int fDumpConds, char * pFileName ); +extern Gia_Man_t * Gia_SweeperCleanup( Gia_Man_t * p, char * pCommLime ); +extern Vec_Int_t * Gia_SweeperGraft( Gia_Man_t * pDst, Vec_Int_t * vProbes, Gia_Man_t * pSrc ); +extern int Gia_SweeperFraig( Gia_Man_t * p, Vec_Int_t * vProbeIds, char * pCommLime, int nWords, int nConfs, int fVerify, int fVerbose ); +extern int Gia_SweeperRun( Gia_Man_t * p, Vec_Int_t * vProbeIds, char * pCommLime, int fVerbose ); +/*=== giaSwitch.c ============================================================*/ +extern float Gia_ManEvaluateSwitching( Gia_Man_t * p ); +extern float Gia_ManComputeSwitching( Gia_Man_t * p, int nFrames, int nPref, int fProbOne ); +extern Vec_Int_t * Gia_ManComputeSwitchProbs( Gia_Man_t * pGia, int nFrames, int nPref, int fProbOne ); +extern Vec_Int_t * Gia_ManComputeSwitchProbs2( Gia_Man_t * pGia, int nFrames, int nPref, int fProbOne, int nRandPiFactor ); +extern Vec_Flt_t * Gia_ManPrintOutputProb( Gia_Man_t * p ); +/*=== giaTim.c ===========================================================*/ +extern int Gia_ManBoxNum( Gia_Man_t * p ); +extern int Gia_ManRegBoxNum( Gia_Man_t * p ); +extern int Gia_ManNonRegBoxNum( Gia_Man_t * p ); +extern int Gia_ManBlackBoxNum( Gia_Man_t * p ); +extern int Gia_ManBoxCiNum( Gia_Man_t * p ); +extern int Gia_ManBoxCoNum( Gia_Man_t * p ); +extern int Gia_ManClockDomainNum( Gia_Man_t * p ); +extern int Gia_ManIsSeqWithBoxes( Gia_Man_t * p ); +extern int Gia_ManIsNormalized( Gia_Man_t * p ); +extern Vec_Int_t * Gia_ManOrderWithBoxes( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupNormalize( Gia_Man_t * p, int fHashMapping ); +extern Gia_Man_t * Gia_ManDupUnnormalize( Gia_Man_t * p ); +extern Gia_Man_t * Gia_ManDupUnshuffleInputs( Gia_Man_t * p ); +extern int Gia_ManLevelWithBoxes( Gia_Man_t * p ); +extern int Gia_ManLutLevelWithBoxes( Gia_Man_t * p ); +extern void * Gia_ManUpdateTimMan( Gia_Man_t * p, Vec_Int_t * vBoxPres ); +extern void * Gia_ManUpdateTimMan2( Gia_Man_t * p, Vec_Int_t * vBoxesLeft, int nTermsDiff ); +extern Gia_Man_t * Gia_ManUpdateExtraAig( void * pTime, Gia_Man_t * pAig, Vec_Int_t * vBoxPres ); +extern Gia_Man_t * Gia_ManUpdateExtraAig2( void * pTime, Gia_Man_t * pAig, Vec_Int_t * vBoxesLeft ); +extern Gia_Man_t * Gia_ManDupCollapse( Gia_Man_t * p, Gia_Man_t * pBoxes, Vec_Int_t * vBoxPres, int fSeq ); +extern int Gia_ManVerifyWithBoxes( Gia_Man_t * pGia, int nBTLimit, int nTimeLim, int fSeq, int fDumpFiles, int fVerbose, char * pFileSpec ); +/*=== giaTruth.c ===========================================================*/ +extern word Gia_LutComputeTruth6( Gia_Man_t * p, int iObj, Vec_Wrd_t * vTruths ); +extern word Gia_ObjComputeTruthTable6Lut( Gia_Man_t * p, int iObj, Vec_Wrd_t * vTemp ); +extern word Gia_ObjComputeTruthTable6( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp, Vec_Wrd_t * vTruths ); +extern word Gia_ObjComputeTruth6Cis( Gia_Man_t * p, int iLit, Vec_Int_t * vSupp, Vec_Wrd_t * vTemp ); +extern void Gia_ObjCollectInternal( Gia_Man_t * p, Gia_Obj_t * pObj ); +extern word * Gia_ObjComputeTruthTable( Gia_Man_t * p, Gia_Obj_t * pObj ); +extern void Gia_ObjComputeTruthTableStart( Gia_Man_t * p, int nVarsMax ); +extern void Gia_ObjComputeTruthTableStop( Gia_Man_t * p ); +extern word * Gia_ObjComputeTruthTableCut( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vLeaves ); +/*=== giaTsim.c ============================================================*/ +extern Gia_Man_t * Gia_ManReduceConst( Gia_Man_t * pAig, int fVerbose ); +/*=== giaUtil.c ===========================================================*/ +extern unsigned Gia_ManRandom( int fReset ); +extern word Gia_ManRandomW( int fReset ); +extern void Gia_ManRandomInfo( Vec_Ptr_t * vInfo, int iInputStart, int iWordStart, int iWordStop ); +extern char * Gia_TimeStamp(); +extern char * Gia_FileNameGenericAppend( char * pBase, char * pSuffix ); +extern Vec_Ptr_t * Gia_GetFakeNames( int nNames, int fCaps ); +extern void Gia_ManIncrementTravId( Gia_Man_t * p ); +extern void Gia_ManCleanMark01( Gia_Man_t * p ); +extern void Gia_ManSetMark0( Gia_Man_t * p ); +extern void Gia_ManCleanMark0( Gia_Man_t * p ); +extern void Gia_ManCheckMark0( Gia_Man_t * p ); +extern void Gia_ManSetMark1( Gia_Man_t * p ); +extern void Gia_ManCleanMark1( Gia_Man_t * p ); +extern void Gia_ManCheckMark1( Gia_Man_t * p ); +extern void Gia_ManCleanValue( Gia_Man_t * p ); +extern void Gia_ManCleanLevels( Gia_Man_t * p, int Size ); +extern void Gia_ManCleanTruth( Gia_Man_t * p ); +extern void Gia_ManFillValue( Gia_Man_t * p ); +extern void Gia_ObjSetPhase( Gia_Man_t * p, Gia_Obj_t * pObj ); +extern void Gia_ManSetPhase( Gia_Man_t * p ); +extern void Gia_ManSetPhasePattern( Gia_Man_t * p, Vec_Int_t * vCiValues ); +extern void Gia_ManSetPhase1( Gia_Man_t * p ); +extern void Gia_ManCleanPhase( Gia_Man_t * p ); +extern int Gia_ManCheckCoPhase( Gia_Man_t * p ); +extern int Gia_ManLevelNum( Gia_Man_t * p ); +extern int Gia_ManLevelRNum( Gia_Man_t * p ); +extern Vec_Int_t * Gia_ManGetCiLevels( Gia_Man_t * p ); +extern int Gia_ManSetLevels( Gia_Man_t * p, Vec_Int_t * vCiLevels ); +extern Vec_Int_t * Gia_ManReverseLevel( Gia_Man_t * p ); +extern Vec_Int_t * Gia_ManRequiredLevel( Gia_Man_t * p ); +extern void Gia_ManCreateValueRefs( Gia_Man_t * p ); +extern void Gia_ManCreateRefs( Gia_Man_t * p ); +extern void Gia_ManCreateLitRefs( Gia_Man_t * p ); +extern int * Gia_ManCreateMuxRefs( Gia_Man_t * p ); +extern int Gia_ManCrossCut( Gia_Man_t * p, int fReverse ); +extern Vec_Int_t * Gia_ManCollectPoIds( Gia_Man_t * p ); +extern int Gia_ObjIsMuxType( Gia_Obj_t * pNode ); +extern int Gia_ObjRecognizeExor( Gia_Obj_t * pObj, Gia_Obj_t ** ppFan0, Gia_Obj_t ** ppFan1 ); +extern Gia_Obj_t * Gia_ObjRecognizeMux( Gia_Obj_t * pNode, Gia_Obj_t ** ppNodeT, Gia_Obj_t ** ppNodeE ); +extern int Gia_ObjRecognizeMuxLits( Gia_Man_t * p, Gia_Obj_t * pNode, int * iLitT, int * iLitE ); +extern int Gia_NodeMffcSize( Gia_Man_t * p, Gia_Obj_t * pNode ); +extern int Gia_NodeMffcSizeMark( Gia_Man_t * p, Gia_Obj_t * pNode ); +extern int Gia_NodeMffcSizeSupp( Gia_Man_t * p, Gia_Obj_t * pNode, Vec_Int_t * vSupp ); +extern int Gia_NodeMffcMapping( Gia_Man_t * p ); +extern int Gia_ManHasDangling( Gia_Man_t * p ); +extern int Gia_ManMarkDangling( Gia_Man_t * p ); +extern Vec_Int_t * Gia_ManGetDangling( Gia_Man_t * p ); +extern void Gia_ObjPrint( Gia_Man_t * p, Gia_Obj_t * pObj ); +extern void Gia_ManPrint( Gia_Man_t * p ); +extern void Gia_ManPrintCo( Gia_Man_t * p, Gia_Obj_t * pObj ); +extern void Gia_ManPrintCone( Gia_Man_t * p, Gia_Obj_t * pObj, int * pLeaves, int nLeaves, Vec_Int_t * vNodes ); +extern void Gia_ManPrintConeMulti( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ); +extern void Gia_ManPrintCone2( Gia_Man_t * p, Gia_Obj_t * pObj ); +extern void Gia_ManInvertConstraints( Gia_Man_t * pAig ); +extern void Gia_ManInvertPos( Gia_Man_t * pAig ); +extern int Gia_ManCompare( Gia_Man_t * p1, Gia_Man_t * p2 ); +extern void Gia_ManMarkFanoutDrivers( Gia_Man_t * p ); +extern void Gia_ManSwapPos( Gia_Man_t * p, int i ); +extern Vec_Int_t * Gia_ManSaveValue( Gia_Man_t * p ); +extern void Gia_ManLoadValue( Gia_Man_t * p, Vec_Int_t * vValues ); +extern Vec_Int_t * Gia_ManFirstFanouts( Gia_Man_t * p ); +extern int Gia_ManCheckSuppOverlap( Gia_Man_t * p, int iNode1, int iNode2 ); +extern int Gia_ManCountPisWithFanout( Gia_Man_t * p ); +extern int Gia_ManCountPosWithNonZeroDrivers( Gia_Man_t * p ); +extern void Gia_ManUpdateCopy( Vec_Int_t * vCopy, Gia_Man_t * p ); +extern Vec_Int_t * Gia_ManComputeDistance( Gia_Man_t * p, int iObj, Vec_Int_t * vObjs, int fVerbose ); + +/*=== giaTtopt.cpp ===========================================================*/ +extern Gia_Man_t * Gia_ManTtopt( Gia_Man_t * p, int nIns, int nOuts, int nRounds ); +extern Gia_Man_t * Gia_ManTtoptCare( Gia_Man_t * p, int nIns, int nOuts, int nRounds, char * pFileName, int nRarity ); + +/*=== giaTransduction.cpp ===========================================================*/ +extern Gia_Man_t * Gia_ManTransductionBdd( Gia_Man_t * pGia, int nType, int fMspf, int nRandom, int nSortType, int nPiShuffle, int nParameter, int fLevel, Gia_Man_t * pExdc, int fNewLine, int nVerbose ); +extern Gia_Man_t * Gia_ManTransductionTt( Gia_Man_t * pGia, int nType, int fMspf, int nRandom, int nSortType, int nPiShuffle, int nParameter, int fLevel, Gia_Man_t * pExdc, int fNewLine, int nVerbose ); + +/*=== giaRrr.cpp ===========================================================*/ +extern Gia_Man_t * Gia_ManRrr( Gia_Man_t *pGia, int iSeed, int nWords, int nTimeout, int nSchedulerVerbose, int nPartitionerVerbose, int nOptimizerVerbose, int nAnalyzerVerbose, int nSimulatorVerbose, int nSatSolverVerbose, int fUseBddCspf, int fUseBddMspf, int nConflictLimit, int nSortType, int nOptimizerFlow, int nSchedulerFlow, int nPartitionType, int nDistance, int nJobs, int nThreads, int nPartitionSize, int nPartitionSizeMin, int fDeterministic, int nParallelPartitions, int fOptOnInsert, int fGreedy ); + +/*=== giaCTas.c ===========================================================*/ +typedef struct Tas_Man_t_ Tas_Man_t; +extern Tas_Man_t * Tas_ManAlloc( Gia_Man_t * pAig, int nBTLimit ); +extern void Tas_ManStop( Tas_Man_t * p ); +extern Vec_Int_t * Tas_ReadModel( Tas_Man_t * p ); +extern void Tas_ManSatPrintStats( Tas_Man_t * p ); +extern int Tas_ManSolve( Tas_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pObj2 ); +extern int Tas_ManSolveArray( Tas_Man_t * p, Vec_Ptr_t * vObjs ); + +/*=== giaBound.c ===========================================================*/ +typedef struct Bnd_Man_t_ Bnd_Man_t; + +extern Bnd_Man_t* Bnd_ManStart( Gia_Man_t *pSpec, Gia_Man_t *pImpl, int fVerbose ); +extern void Bnd_ManStop(); + +// getter +extern int Bnd_ManGetNInternal(); +extern int Bnd_ManGetNExtra(); + +//for fraig +extern void Bnd_ManMap( int iLit, int id, int spec ); +extern void Bnd_ManMerge( int id1, int id2, int phaseDiff ); +extern void Bnd_ManFinalizeMappings(); +extern void Bnd_ManPrintMappings(); +extern Gia_Man_t* Bnd_ManStackGias( Gia_Man_t *pSpec, Gia_Man_t *pImpl ); +extern int Bnd_ManCheckCoMerged( Gia_Man_t *p ); + +// for eco +extern int Bnd_ManCheckBound( Gia_Man_t *p, int fVerbose ); +extern void Bnd_ManFindBound( Gia_Man_t *p, Gia_Man_t *pImpl ); +extern Gia_Man_t* Bnd_ManGenSpecOut( Gia_Man_t *p ); +extern Gia_Man_t* Bnd_ManGenImplOut( Gia_Man_t *p ); +extern Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPatch ); +extern Gia_Man_t* Bnd_ManGenPatched1( Gia_Man_t *pOut, Gia_Man_t *pSpec ); +extern Gia_Man_t* Bnd_ManGenPatched2( Gia_Man_t *pImpl, Gia_Man_t *pPatch, int fSkiptStrash, int fVerbose ); +extern void Bnd_ManSetEqOut( int eq ); +extern void Bnd_ManSetEqRes( int eq ); +extern void Bnd_ManPrintStats(); + +// util +extern Gia_Man_t* Bnd_ManCutBoundary( Gia_Man_t *p, Vec_Int_t* vEI, Vec_Int_t* vEO, Vec_Bit_t* vEI_phase, Vec_Bit_t* vEO_phase ); + +extern int Gia_ObjCheckMffc( Gia_Man_t * p, Gia_Obj_t * pRoot, int Limit, Vec_Int_t * vNodes, Vec_Int_t * vLeaves, Vec_Int_t * vInners ); + +ABC_NAMESPACE_HEADER_END + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/yosys/abc/src/aig/gia/giaAgi.c b/yosys/abc/src/aig/gia/giaAgi.c new file mode 100644 index 00000000000..2db087d5191 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaAgi.c @@ -0,0 +1,238 @@ +/**CFile**************************************************************** + + FileName [giaAig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define AGI_PI ABC_CONST(0xFFFFFFFF00000000) +#define AGI_RO ABC_CONST(0xFFFFFFFE00000000) +#define AGI_PO ABC_CONST(0xFFFFFFFD00000000) +#define AGI_RI ABC_CONST(0xFFFFFFFC00000000) +#define AGI_C0 ABC_CONST(0xFFFFFFFBFFFFFFFA) +#define AGI_M0 ABC_CONST(0x00000000FFFFFFFF) +#define AGI_M1 ABC_CONST(0xFFFFFFFF00000000) + +typedef struct Agi_Man_t_ Agi_Man_t; +struct Agi_Man_t_ +{ + char * pName; // name of the AIG + char * pSpec; // name of the input file + int nCap; // number of objects + int nObjs; // number of objects + int nNodes; // number of objects + int nRegs; // number of registers + unsigned nTravIds; // number of objects + Vec_Int_t vCis; // comb inputs + Vec_Int_t vCos; // comb outputs + word * pObjs; // objects + unsigned * pThird; // third input + unsigned * pTravIds; // traversal IDs + unsigned * pNext; // next values + unsigned * pTable; // hash table + unsigned * pCopy; // hash table +}; + +static inline int Agi_ManObjNum( Agi_Man_t * p ) { return p->nObjs; } +static inline int Agi_ManCiNum( Agi_Man_t * p ) { return Vec_IntSize( &p->vCis ); } +static inline int Agi_ManCoNum( Agi_Man_t * p ) { return Vec_IntSize( &p->vCos ); } +static inline int Agi_ManNodeNum( Agi_Man_t * p ) { return p->nNodes; } + +static inline unsigned Agi_ObjLit0( Agi_Man_t * p, int i ) { return (unsigned)(p->pObjs[i]); } +static inline unsigned Agi_ObjLit1( Agi_Man_t * p, int i ) { return (unsigned)(p->pObjs[i] >> 32); } +static inline unsigned Agi_ObjLit2( Agi_Man_t * p, int i ) { return p->pThird[i]; } +static inline int Agi_ObjVar0( Agi_Man_t * p, int i ) { return Agi_ObjLit0(p, i) >> 1; } +static inline int Agi_ObjVar1( Agi_Man_t * p, int i ) { return Agi_ObjLit1(p, i) >> 1; } +static inline int Agi_ObjVar2( Agi_Man_t * p, int i ) { return Agi_ObjLit2(p, i) >> 1; } +static inline void Agi_ObjSetLit0( Agi_Man_t * p, int i, unsigned l ) { p->pObjs[i] = (p->pObjs[i] & AGI_M1) | (word)l; } +static inline void Agi_ObjSetLit1( Agi_Man_t * p, int i, unsigned l ) { p->pObjs[i] = (p->pObjs[i] & AGI_M0) | ((word)l << 32); } +static inline void Agi_ObjSetLit2( Agi_Man_t * p, int i, unsigned l ) { p->pThird[i] = l; } + +static inline int Agi_ObjIsC0( Agi_Man_t * p, int i ) { return (i == 0); } +static inline int Agi_ObjIsPi( Agi_Man_t * p, int i ) { return (p->pObjs[i] & AGI_PI) == AGI_PI; } +static inline int Agi_ObjIsRo( Agi_Man_t * p, int i ) { return (p->pObjs[i] & AGI_PI) == AGI_RO; } +static inline int Agi_ObjIsPo( Agi_Man_t * p, int i ) { return (p->pObjs[i] & AGI_PI) == AGI_PO; } +static inline int Agi_ObjIsRi( Agi_Man_t * p, int i ) { return (p->pObjs[i] & AGI_PI) == AGI_RI; } +static inline int Agi_ObjIsCi( Agi_Man_t * p, int i ) { return (p->pObjs[i] & AGI_RO) == AGI_RO; } +static inline int Agi_ObjIsCo( Agi_Man_t * p, int i ) { return (p->pObjs[i] & AGI_PO) == AGI_PO; } +static inline int Agi_ObjIsNode( Agi_Man_t * p, int i ) { return p->pObjs[i] < AGI_C0; } +static inline int Agi_ObjIsBuf( Agi_Man_t * p, int i ) { return Agi_ObjLit0(p, i) == Agi_ObjLit1(p, i); } +static inline int Agi_ObjIsAnd( Agi_Man_t * p, int i ) { return Agi_ObjIsNode(p, i) && Agi_ObjLit0(p, i) < Agi_ObjLit1(p, i); } +static inline int Agi_ObjIsXor( Agi_Man_t * p, int i ) { return Agi_ObjIsNode(p, i) && Agi_ObjLit0(p, i) > Agi_ObjLit1(p, i); } +static inline int Agi_ObjIsMux( Agi_Man_t * p, int i ) { return Agi_ObjIsAnd(p, i) && ~Agi_ObjLit2(p, i); } +static inline int Agi_ObjIsMaj( Agi_Man_t * p, int i ) { return Agi_ObjIsXor(p, i) && ~Agi_ObjLit2(p, i); } + +static inline int Agi_ManAppendObj( Agi_Man_t * p ) +{ + assert( p->nObjs < p->nCap ); + return p->nObjs++; // return var +} +static inline int Agi_ManAppendCi( Agi_Man_t * p ) +{ + int iObj = Agi_ManAppendObj( p ); + p->pObjs[iObj] = AGI_PI | (word)Vec_IntSize(&p->vCis); + Vec_IntPush( &p->vCis, iObj ); + return Abc_Var2Lit( iObj, 0 ); // return lit +} +static inline int Agi_ManAppendCo( Agi_Man_t * p, int iLit0 ) +{ + int iObj = Agi_ManAppendObj( p ); + p->pObjs[iObj] = AGI_PO | (word)iLit0; + Vec_IntPush( &p->vCos, iObj ); + return Abc_Var2Lit( iObj, 0 ); // return lit +} +static inline int Agi_ManAppendAnd( Agi_Man_t * p, int iLit0, int iLit1 ) +{ + int iObj = Agi_ManAppendObj( p ); + assert( iLit0 < iLit1 ); + p->pObjs[iObj] = ((word)iLit1 << 32) | (word)iLit0; + p->nNodes++; + return Abc_Var2Lit( iObj, 0 ); // return lit +} + +#define Agi_ManForEachCi( p, iCi, i ) Vec_IntForEachEntry( &p->vCis, iCi, i ) +#define Agi_ManForEachCo( p, iCo, i ) Vec_IntForEachEntry( &p->vCos, iCo, i ) +#define Agi_ManForEachObj( p, i ) for ( i = 0; i < Agi_ManObjNum(p); i++ ) +#define Agi_ManForEachObj1( p, i ) for ( i = 1; i < Agi_ManObjNum(p); i++ ) +#define Agi_ManForEachNode( p, i ) for ( i = 1; i < Agi_ManObjNum(p); i++ ) if ( !Agi_ObjIsNode(p, i) ) {} else + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Agi_Man_t * Agi_ManAlloc( int nCap ) +{ + Agi_Man_t * p; + nCap = Abc_MaxInt( nCap, 16 ); + p = ABC_CALLOC( Agi_Man_t, 1 ); + p->nCap = nCap; + p->pObjs = ABC_CALLOC( word, nCap ); + p->pTravIds = ABC_CALLOC( unsigned, nCap ); + p->pObjs[0] = AGI_C0; + p->nObjs = 1; + return p; +} +void Agi_ManFree( Agi_Man_t * p ) +{ + ABC_FREE( p->pObjs ); + ABC_FREE( p->pTravIds ); + ABC_FREE( p->vCis.pArray ); + ABC_FREE( p->vCos.pArray ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Agi_Man_t * Agi_ManFromGia( Gia_Man_t * p ) +{ + Agi_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Agi_ManAlloc( Gia_ManObjNum(p) ); + Gia_ManForEachObj1( p, pObj, i ) + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Agi_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Agi_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Agi_ManAppendCi( pNew ); + else assert( 0 ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Agi_ManSuppSize_rec( Agi_Man_t * p, int i ) +{ + if ( p->pTravIds[i] == p->nTravIds ) + return 0; + p->pTravIds[i] = p->nTravIds; + if ( Agi_ObjIsCi(p, i) ) + return 1; + assert( Agi_ObjIsAnd(p, i) ); + return Agi_ManSuppSize_rec( p, Agi_ObjVar0(p, i) ) + Agi_ManSuppSize_rec( p, Agi_ObjVar1(p, i) ); +} +int Agi_ManSuppSizeOne( Agi_Man_t * p, int i ) +{ + p->nTravIds++; + return Agi_ManSuppSize_rec( p, i ); +} +int Agi_ManSuppSizeTest( Agi_Man_t * p ) +{ + abctime clk = Abc_Clock(); + int i, Counter = 0; + Agi_ManForEachNode( p, i ) + Counter += (Agi_ManSuppSizeOne(p, i) <= 16); + printf( "Nodes with small support %d (out of %d)\n", Counter, Agi_ManNodeNum(p) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return Counter; + +} +void Agi_ManTest( Gia_Man_t * pGia ) +{ + extern int Gia_ManSuppSizeTest( Gia_Man_t * p ); + Agi_Man_t * p; + Gia_ManSuppSizeTest( pGia ); + p = Agi_ManFromGia( pGia ); + Agi_ManSuppSizeTest( p ); + Agi_ManFree( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaAig.c b/yosys/abc/src/aig/gia/giaAig.c new file mode 100644 index 00000000000..07bab5fec2f --- /dev/null +++ b/yosys/abc/src/aig/gia/giaAig.c @@ -0,0 +1,742 @@ +/**CFile**************************************************************** + + FileName [giaAig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Transformation between AIG manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "giaAig.h" +#include "aig/gia/gia.h" +#include "proof/fra/fra.h" +#include "proof/dch/dch.h" +#include "opt/dar/dar.h" +#include "opt/dau/dau.h" +#include + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Gia_ObjChild0Copy( Aig_Obj_t * pObj ) { return Abc_LitNotCond( Aig_ObjFanin0(pObj)->iData, Aig_ObjFaninC0(pObj) ); } +static inline int Gia_ObjChild1Copy( Aig_Obj_t * pObj ) { return Abc_LitNotCond( Aig_ObjFanin1(pObj)->iData, Aig_ObjFaninC1(pObj) ); } + +static inline Aig_Obj_t * Gia_ObjChild0Copy2( Aig_Obj_t ** ppNodes, Gia_Obj_t * pObj, int Id ) { return Aig_NotCond( ppNodes[Gia_ObjFaninId0(pObj, Id)], Gia_ObjFaninC0(pObj) ); } +static inline Aig_Obj_t * Gia_ObjChild1Copy2( Aig_Obj_t ** ppNodes, Gia_Obj_t * pObj, int Id ) { return Aig_NotCond( ppNodes[Gia_ObjFaninId1(pObj, Id)], Gia_ObjFaninC1(pObj) ); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Duplicates AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManFromAig_rec( Gia_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pNext; + if ( pObj->iData ) + return; + assert( Aig_ObjIsNode(pObj) ); + Gia_ManFromAig_rec( pNew, p, Aig_ObjFanin0(pObj) ); + Gia_ManFromAig_rec( pNew, p, Aig_ObjFanin1(pObj) ); + pObj->iData = Gia_ManAppendAnd( pNew, Gia_ObjChild0Copy(pObj), Gia_ObjChild1Copy(pObj) ); + if ( p->pEquivs && (pNext = Aig_ObjEquiv(p, pObj)) ) + { + int iObjNew, iNextNew; + Gia_ManFromAig_rec( pNew, p, pNext ); + iObjNew = Abc_Lit2Var(pObj->iData); + iNextNew = Abc_Lit2Var(pNext->iData); + if ( pNew->pNexts ) + pNew->pNexts[iObjNew] = iNextNew; + } +} +Gia_Man_t * Gia_ManFromAig( Aig_Man_t * p ) +{ + Gia_Man_t * pNew; + Aig_Obj_t * pObj; + int i; + // create the new manager + pNew = Gia_ManStart( Aig_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nConstrs = p->nConstrs; + // create room to store equivalences + if ( p->pEquivs ) + pNew->pNexts = ABC_CALLOC( int, Aig_ManObjNum(p) ); + // create the PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->iData = 1; + Aig_ManForEachCi( p, pObj, i ) + pObj->iData = Gia_ManAppendCi( pNew ); + // add logic for the POs + Aig_ManForEachCo( p, pObj, i ) + Gia_ManFromAig_rec( pNew, p, Aig_ObjFanin0(pObj) ); + Aig_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjChild0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Aig_ManRegNum(p) ); + if ( pNew->pNexts ) + Gia_ManDeriveReprs( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Checks integrity of choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCheckChoices_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( !pObj || !Gia_ObjIsAnd(pObj) || pObj->fPhase ) + return; + pObj->fPhase = 1; + Gia_ManCheckChoices_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ManCheckChoices_rec( p, Gia_ObjFanin1(pObj) ); + Gia_ManCheckChoices_rec( p, Gia_ObjSiblObj(p, Gia_ObjId(p, pObj)) ); +} +void Gia_ManCheckChoices( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, fFound = 0; + Gia_ManCleanPhase( p ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManCheckChoices_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachAnd( p, pObj, i ) + if ( !pObj->fPhase ) + printf( "Object %d is dangling.\n", i ), fFound = 1; + if ( !fFound ) + printf( "There are no dangling objects.\n" ); + Gia_ManCleanPhase( p ); +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManFromAigChoices_rec( Gia_Man_t * pNew, Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( pObj == NULL || pObj->iData ) + return; + assert( Aig_ObjIsNode(pObj) ); + Gia_ManFromAigChoices_rec( pNew, p, Aig_ObjFanin0(pObj) ); + Gia_ManFromAigChoices_rec( pNew, p, Aig_ObjFanin1(pObj) ); + Gia_ManFromAigChoices_rec( pNew, p, Aig_ObjEquiv(p, pObj) ); + pObj->iData = Gia_ManAppendAnd( pNew, Gia_ObjChild0Copy(pObj), Gia_ObjChild1Copy(pObj) ); + if ( Aig_ObjEquiv(p, pObj) ) + { + int iObjNew, iNextNew; + iObjNew = Abc_Lit2Var(pObj->iData); + iNextNew = Abc_Lit2Var(Aig_ObjEquiv(p, pObj)->iData); + assert( iObjNew > iNextNew ); + assert( Gia_ObjIsAnd(Gia_ManObj(pNew, iNextNew)) ); + pNew->pSibls[iObjNew] = iNextNew; + } +} +Gia_Man_t * Gia_ManFromAigChoices( Aig_Man_t * p ) +{ + Gia_Man_t * pNew; + Aig_Obj_t * pObj; + int i; + assert( p->pEquivs != NULL ); + // create the new manager + pNew = Gia_ManStart( Aig_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nConstrs = p->nConstrs; + // create room to store equivalences + pNew->pSibls = ABC_CALLOC( int, Aig_ManObjNum(p) ); + // create the PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->iData = 1; + Aig_ManForEachCi( p, pObj, i ) + pObj->iData = Gia_ManAppendCi( pNew ); + // add logic for the POs + Aig_ManForEachCo( p, pObj, i ) + Gia_ManFromAigChoices_rec( pNew, p, Aig_ObjFanin0(pObj) ); + Aig_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjChild0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Aig_ManRegNum(p) ); + //assert( Gia_ManObjNum(pNew) == Aig_ManObjNum(p) ); + //Gia_ManCheckChoices( pNew ); + if ( pNew->pSibls ) + Gia_ManDeriveReprsFromSibls( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManFromAigSimple( Aig_Man_t * p ) +{ + Gia_Man_t * pNew; + Aig_Obj_t * pObj; + int i; + // create the new manager + pNew = Gia_ManStart( Aig_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nConstrs = p->nConstrs; + // create the PIs + Aig_ManCleanData( p ); + Aig_ManForEachObj( p, pObj, i ) + { + if ( Aig_ObjIsAnd(pObj) ) + pObj->iData = Gia_ManAppendAnd( pNew, Gia_ObjChild0Copy(pObj), Gia_ObjChild1Copy(pObj) ); + else if ( Aig_ObjIsCi(pObj) ) + pObj->iData = Gia_ManAppendCi( pNew ); + else if ( Aig_ObjIsCo(pObj) ) + pObj->iData = Gia_ManAppendCo( pNew, Gia_ObjChild0Copy(pObj) ); + else if ( Aig_ObjIsConst1(pObj) ) + pObj->iData = 1; + else + assert( 0 ); + } + Gia_ManSetRegNum( pNew, Aig_ManRegNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Handles choices as additional combinational outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManFromAigSwitch( Aig_Man_t * p ) +{ + Gia_Man_t * pNew; + Aig_Obj_t * pObj; + int i; + // create the new manager + pNew = Gia_ManStart( Aig_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nConstrs = p->nConstrs; + // create the PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->iData = 1; + Aig_ManForEachCi( p, pObj, i ) + pObj->iData = Gia_ManAppendCi( pNew ); + // add POs corresponding to the nodes with choices + Aig_ManForEachNode( p, pObj, i ) + if ( Aig_ObjRefs(pObj) == 0 ) + { + Gia_ManFromAig_rec( pNew, p, pObj ); + Gia_ManAppendCo( pNew, pObj->iData ); + } + // add logic for the POs + Aig_ManForEachCo( p, pObj, i ) + Gia_ManFromAig_rec( pNew, p, Aig_ObjFanin0(pObj) ); + Aig_ManForEachCo( p, pObj, i ) + pObj->iData = Gia_ManAppendCo( pNew, Gia_ObjChild0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Aig_ManRegNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManToAig_rec( Aig_Man_t * pNew, Aig_Obj_t ** ppNodes, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + Gia_Obj_t * pNext; + if ( ppNodes[Gia_ObjId(p, pObj)] ) + return; + if ( Gia_ObjIsCi(pObj) ) + ppNodes[Gia_ObjId(p, pObj)] = Aig_ObjCreateCi( pNew ); + else + { + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManToAig_rec( pNew, ppNodes, p, Gia_ObjFanin0(pObj) ); + Gia_ManToAig_rec( pNew, ppNodes, p, Gia_ObjFanin1(pObj) ); + ppNodes[Gia_ObjId(p, pObj)] = Aig_And( pNew, Gia_ObjChild0Copy2(ppNodes, pObj, Gia_ObjId(p, pObj)), Gia_ObjChild1Copy2(ppNodes, pObj, Gia_ObjId(p, pObj)) ); + } + if ( pNew->pEquivs && (pNext = Gia_ObjNextObj(p, Gia_ObjId(p, pObj))) ) + { + Aig_Obj_t * pObjNew, * pNextNew; + Gia_ManToAig_rec( pNew, ppNodes, p, pNext ); + pObjNew = ppNodes[Gia_ObjId(p, pObj)]; + pNextNew = ppNodes[Gia_ObjId(p, pNext)]; + if ( pNew->pEquivs ) + pNew->pEquivs[Aig_Regular(pObjNew)->Id] = Aig_Regular(pNextNew); + } +} +Aig_Man_t * Gia_ManToAig( Gia_Man_t * p, int fChoices ) +{ + Aig_Man_t * pNew; + Aig_Obj_t ** ppNodes; + Gia_Obj_t * pObj; + int i; + assert( !fChoices || (p->pNexts && p->pReprs) ); + // create the new manager + pNew = Aig_ManStart( Gia_ManAndNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nConstrs = p->nConstrs; +// pNew->pSpec = Abc_UtilStrsav( p->pName ); + // duplicate representation of choice nodes + if ( fChoices ) + pNew->pEquivs = ABC_CALLOC( Aig_Obj_t *, Gia_ManObjNum(p) ); + // create the PIs + ppNodes = ABC_CALLOC( Aig_Obj_t *, Gia_ManObjNum(p) ); + ppNodes[0] = Aig_ManConst0(pNew); + Gia_ManForEachCi( p, pObj, i ) + ppNodes[Gia_ObjId(p, pObj)] = Aig_ObjCreateCi( pNew ); + // transfer level + if ( p->vLevels ) + Gia_ManForEachCi( p, pObj, i ) + Aig_ObjSetLevel( ppNodes[Gia_ObjId(p, pObj)], Gia_ObjLevel(p, pObj) ); + // add logic for the POs + Gia_ManForEachCo( p, pObj, i ) + { + Gia_ManToAig_rec( pNew, ppNodes, p, Gia_ObjFanin0(pObj) ); + ppNodes[Gia_ObjId(p, pObj)] = Aig_ObjCreateCo( pNew, Gia_ObjChild0Copy2(ppNodes, pObj, Gia_ObjId(p, pObj)) ); + } + Aig_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + ABC_FREE( ppNodes ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Gia_ManToAigSkip( Gia_Man_t * p, int nOutDelta ) +{ + Aig_Man_t * pNew; + Aig_Obj_t ** ppNodes; + Gia_Obj_t * pObj; + int i; + assert( p->pNexts == NULL && p->pReprs == NULL ); + assert( nOutDelta > 0 && Gia_ManCoNum(p) % nOutDelta == 0 ); + // create the new manager + pNew = Aig_ManStart( Gia_ManAndNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nConstrs = p->nConstrs; +// pNew->pSpec = Abc_UtilStrsav( p->pName ); + // create the PIs + ppNodes = ABC_CALLOC( Aig_Obj_t *, Gia_ManObjNum(p) ); + ppNodes[0] = Aig_ManConst0(pNew); + Gia_ManForEachCi( p, pObj, i ) + ppNodes[Gia_ObjId(p, pObj)] = Aig_ObjCreateCi( pNew ); + // add logic for the POs + Gia_ManForEachCo( p, pObj, i ) + { + Gia_ManToAig_rec( pNew, ppNodes, p, Gia_ObjFanin0(pObj) ); + if ( i % nOutDelta != 0 ) + continue; + ppNodes[Gia_ObjId(p, pObj)] = Aig_ObjCreateCo( pNew, Gia_ObjChild0Copy2(ppNodes, pObj, Gia_ObjId(p, pObj)) ); + } + Aig_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + ABC_FREE( ppNodes ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Gia_ManToAigSimple( Gia_Man_t * p ) +{ + Aig_Man_t * pNew; + Aig_Obj_t ** ppNodes; + Gia_Obj_t * pObj; + int i; + ppNodes = ABC_FALLOC( Aig_Obj_t *, Gia_ManObjNum(p) ); + // create the new manager + pNew = Aig_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nConstrs = p->nConstrs; + // create the PIs + Gia_ManForEachObj( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + ppNodes[i] = Aig_And( pNew, Gia_ObjChild0Copy2(ppNodes, pObj, Gia_ObjId(p, pObj)), Gia_ObjChild1Copy2(ppNodes, pObj, Gia_ObjId(p, pObj)) ); + else if ( Gia_ObjIsCi(pObj) ) + ppNodes[i] = Aig_ObjCreateCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + ppNodes[i] = Aig_ObjCreateCo( pNew, Gia_ObjChild0Copy2(ppNodes, pObj, Gia_ObjId(p, pObj)) ); + else if ( Gia_ObjIsConst0(pObj) ) + ppNodes[i] = Aig_ManConst0(pNew); + else + assert( 0 ); + pObj->Value = Abc_Var2Lit( Aig_ObjId(Aig_Regular(ppNodes[i])), Aig_IsComplement(ppNodes[i]) ); + assert( i == 0 || Aig_ObjId(ppNodes[i]) == i ); + } + Aig_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + ABC_FREE( ppNodes ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Gia_ManCofactorAig( Aig_Man_t * p, int nFrames, int nCofFanLit ) +{ + Aig_Man_t * pMan; + Gia_Man_t * pGia, * pTemp; + pGia = Gia_ManFromAig( p ); + pGia = Gia_ManUnrollAndCofactor( pTemp = pGia, nFrames, nCofFanLit, 1 ); + Gia_ManStop( pTemp ); + pMan = Gia_ManToAig( pGia, 0 ); + Gia_ManStop( pGia ); + return pMan; +} + + +/**Function************************************************************* + + Synopsis [Transfers representatives from pGia to pAig.] + + Description [Assumes that pGia was created from pAig.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManReprToAigRepr( Aig_Man_t * pAig, Gia_Man_t * pGia ) +{ + Aig_Obj_t * pObj; + Gia_Obj_t * pGiaObj, * pGiaRepr; + int i; + assert( pAig->pReprs == NULL ); + assert( pGia->pReprs != NULL ); + // move pointers from AIG to GIA + Aig_ManForEachObj( pAig, pObj, i ) + { + assert( i == 0 || !Abc_LitIsCompl(pObj->iData) ); + pGiaObj = Gia_ManObj( pGia, Abc_Lit2Var(pObj->iData) ); + pGiaObj->Value = i; + } + // set the pointers to the nodes in AIG + Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) ); + Gia_ManForEachObj( pGia, pGiaObj, i ) + { + pGiaRepr = Gia_ObjReprObj( pGia, i ); + if ( pGiaRepr == NULL ) + continue; + Aig_ObjCreateRepr( pAig, Aig_ManObj(pAig, pGiaRepr->Value), Aig_ManObj(pAig, pGiaObj->Value) ); + } +} +void Gia_ManReprToAigRepr2( Aig_Man_t * pAig, Gia_Man_t * pGia ) +{ + Gia_Obj_t * pGiaObj, * pGiaRepr; + int i; + assert( pAig->pReprs == NULL ); + assert( pGia->pReprs != NULL ); + // set the pointers to the nodes in AIG + Aig_ManReprStart( pAig, Aig_ManObjNumMax(pAig) ); + Gia_ManForEachObj( pGia, pGiaObj, i ) + { + pGiaRepr = Gia_ObjReprObj( pGia, i ); + if ( pGiaRepr == NULL ) + continue; + Aig_ObjCreateRepr( pAig, Aig_ManObj(pAig, Abc_Lit2Var(pGiaRepr->Value)), Aig_ManObj(pAig, Abc_Lit2Var(pGiaObj->Value)) ); + } +} + +/**Function************************************************************* + + Synopsis [Transfers representatives from pAig to pGia.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManReprFromAigRepr( Aig_Man_t * pAig, Gia_Man_t * pGia ) +{ + Gia_Obj_t * pObjGia; + Aig_Obj_t * pObjAig, * pReprAig; + int i; + assert( pAig->pReprs != NULL ); + assert( pGia->pReprs == NULL ); + assert( Gia_ManObjNum(pGia) - Gia_ManCoNum(pGia) == Aig_ManObjNum(pAig) - Aig_ManCoNum(pAig) ); + pGia->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(pGia) ); + for ( i = 0; i < Gia_ManObjNum(pGia); i++ ) + Gia_ObjSetRepr( pGia, i, GIA_VOID ); + // move pointers from GIA to AIG + Gia_ManForEachObj( pGia, pObjGia, i ) + { + if ( Gia_ObjIsCo(pObjGia) ) + continue; + assert( i == 0 || !Abc_LitIsCompl(Gia_ObjValue(pObjGia)) ); + pObjAig = Aig_ManObj( pAig, Abc_Lit2Var(Gia_ObjValue(pObjGia)) ); + pObjAig->iData = i; + } + Aig_ManForEachObj( pAig, pObjAig, i ) + { + if ( Aig_ObjIsCo(pObjAig) ) + continue; + if ( pAig->pReprs[i] == NULL ) + continue; + pReprAig = pAig->pReprs[i]; + Gia_ObjSetRepr( pGia, pObjAig->iData, pReprAig->iData ); + } + pGia->pNexts = Gia_ManDeriveNexts( pGia ); +} +void Gia_ManReprFromAigRepr2( Aig_Man_t * pAig, Gia_Man_t * pGia ) +{ + Aig_Obj_t * pObjAig, * pReprAig; + int i; + assert( pAig->pReprs != NULL ); + assert( pGia->pReprs == NULL ); + assert( Gia_ManObjNum(pGia) - Gia_ManCoNum(pGia) == Aig_ManObjNum(pAig) - Aig_ManCoNum(pAig) ); + pGia->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(pGia) ); + for ( i = 0; i < Gia_ManObjNum(pGia); i++ ) + Gia_ObjSetRepr( pGia, i, GIA_VOID ); + Aig_ManForEachObj( pAig, pObjAig, i ) + { + if ( Aig_ObjIsCo(pObjAig) ) + continue; + if ( pAig->pReprs[i] == NULL ) + continue; + pReprAig = pAig->pReprs[i]; + Gia_ObjSetRepr( pGia, Abc_Lit2Var(pObjAig->iData), Abc_Lit2Var(pReprAig->iData) ); + } + pGia->pNexts = Gia_ManDeriveNexts( pGia ); +} + +/**Function************************************************************* + + Synopsis [Applies DC2 to the GIA manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManCompress2( Gia_Man_t * p, int fUpdateLevel, int fVerbose ) +{ + Gia_Man_t * pGia; + Aig_Man_t * pNew, * pTemp; + if ( p->pManTime && p->vLevels == NULL ) + Gia_ManLevelWithBoxes( p ); + pNew = Gia_ManToAig( p, 0 ); + pNew = Dar_ManCompress2( pTemp = pNew, 1, fUpdateLevel, 1, 0, fVerbose ); + Aig_ManStop( pTemp ); + pGia = Gia_ManFromAig( pNew ); + Aig_ManStop( pNew ); + Gia_ManTransferTiming( pGia, p ); + return pGia; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManTestChoices( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; int i; + Vec_Int_t * vPointed = Vec_IntStart( Gia_ManObjNum(p) ); + Gia_ManForEachAnd( p, pObj, i ) + if ( Gia_ObjSibl(p, i) ) + Vec_IntWriteEntry( vPointed, Gia_ObjSibl(p, i), 1 ); + Gia_ManCreateRefs( p ); + Gia_ManForEachAnd( p, pObj, i ) + if ( Vec_IntEntry(vPointed, i) && Gia_ObjRefNumId(p, i) > 0 ) + { + printf( "Gia_ManCheckChoices: Member %d", i ); + printf( " of a choice node has %d fanouts.\n", Gia_ObjRefNumId(p, i) ); + ABC_FREE( p->pRefs ); + Vec_IntFree( vPointed ); + return 0; + } + ABC_FREE( p->pRefs ); + Vec_IntFree( vPointed ); + return 1; +} +Gia_Man_t * Gia_ManPerformDch( Gia_Man_t * p, void * pPars ) +{ + int fUseMapping = 0; + Gia_Man_t * pGia, * pGia1; + Aig_Man_t * pNew; + if ( p->pManTime && p->vLevels == NULL ) + Gia_ManLevelWithBoxes( p ); + if ( fUseMapping && Gia_ManHasMapping(p) ) + pGia1 = (Gia_Man_t *)Dsm_ManDeriveGia( p, 0 ); + else + pGia1 = Gia_ManDup( p ); + pNew = Gia_ManToAig( pGia1, 0 ); + Gia_ManStop( pGia1 ); + pNew = Dar_ManChoiceNew( pNew, (Dch_Pars_t *)pPars ); +// pGia = Gia_ManFromAig( pNew ); + pGia = Gia_ManFromAigChoices( pNew ); + Aig_ManStop( pNew ); + if ( !p->pManTime && !Gia_ManTestChoices(pGia) ) + { + Gia_ManStop( pGia ); + pGia = Gia_ManDup( p ); + } + Gia_ManTransferTiming( pGia, p ); + return pGia; +} + +/**Function************************************************************* + + Synopsis [Computes equivalences after structural sequential cleanup.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSeqCleanupClasses( Gia_Man_t * p, int fConst, int fEquiv, int fVerbose ) +{ + Aig_Man_t * pNew, * pTemp; + pNew = Gia_ManToAigSimple( p ); + pTemp = Aig_ManScl( pNew, fConst, fEquiv, 0, -1, -1, fVerbose, 0 ); + Gia_ManReprFromAigRepr( pNew, p ); + Aig_ManStop( pTemp ); + Aig_ManStop( pNew ); +} + +/**Function************************************************************* + + Synopsis [Solves SAT problem.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSolveSat( Gia_Man_t * p ) +{ +// extern int Fra_FraigSat( Aig_Man_t * pMan, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int fFlipBits, int fAndOuts, int fNewSolver, int fVerbose ); + Aig_Man_t * pNew; + int RetValue;//, clk = Abc_Clock(); + pNew = Gia_ManToAig( p, 0 ); + RetValue = Fra_FraigSat( pNew, 10000000, 0, 0, 0, 0, 1, 1, 0, 0 ); + if ( RetValue == 0 ) + { + Gia_Obj_t * pObj; + int i, * pInit = (int *)pNew->pData; + Gia_ManConst0(p)->fMark0 = 0; + Gia_ManForEachPi( p, pObj, i ) + pObj->fMark0 = pInit[i]; + Gia_ManForEachAnd( p, pObj, i ) + pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & + (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)); + Gia_ManForEachPo( p, pObj, i ) + pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)); + Gia_ManForEachPo( p, pObj, i ) + if ( pObj->fMark0 != 1 ) + break; + if ( i != Gia_ManPoNum(p) ) + Abc_Print( 1, "Counter-example verification has failed. " ); +// else +// Abc_Print( 1, "Counter-example verification succeeded. " ); + } +/* + else if ( RetValue == 1 ) + Abc_Print( 1, "The SAT problem is unsatisfiable. " ); + else if ( RetValue == -1 ) + Abc_Print( 1, "The SAT problem is undecided. " ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +*/ + Aig_ManStop( pNew ); + return RetValue; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaAig.h b/yosys/abc/src/aig/gia/giaAig.h new file mode 100644 index 00000000000..6498ec52238 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaAig.h @@ -0,0 +1,78 @@ +/**CFile**************************************************************** + + FileName [giaAig.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaAig.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__gia__giaAig_h +#define ABC__aig__gia__giaAig_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "aig/aig/aig.h" +#include "gia.h" + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== giaAig.c =============================================================*/ +extern Gia_Man_t * Gia_ManFromAig( Aig_Man_t * p ); +extern Gia_Man_t * Gia_ManFromAigChoices( Aig_Man_t * p ); +extern Gia_Man_t * Gia_ManFromAigSimple( Aig_Man_t * p ); +extern Gia_Man_t * Gia_ManFromAigSwitch( Aig_Man_t * p ); +extern Aig_Man_t * Gia_ManToAig( Gia_Man_t * p, int fChoices ); +extern Aig_Man_t * Gia_ManToAigSkip( Gia_Man_t * p, int nOutDelta ); +extern Aig_Man_t * Gia_ManToAigSimple( Gia_Man_t * p ); +extern void Gia_ManReprToAigRepr( Aig_Man_t * pAig, Gia_Man_t * pGia ); +extern void Gia_ManReprToAigRepr2( Aig_Man_t * pAig, Gia_Man_t * pGia ); +extern void Gia_ManReprFromAigRepr( Aig_Man_t * pAig, Gia_Man_t * pGia ); +extern void Gia_ManReprFromAigRepr2( Aig_Man_t * pAig, Gia_Man_t * pGia ); +extern Gia_Man_t * Gia_ManCompress2( Gia_Man_t * p, int fUpdateLevel, int fVerbose ); +extern Gia_Man_t * Gia_ManPerformDch( Gia_Man_t * p, void * pPars ); +extern Gia_Man_t * Gia_ManAbstraction( Gia_Man_t * p, Vec_Int_t * vFlops ); +extern void Gia_ManSeqCleanupClasses( Gia_Man_t * p, int fConst, int fEquiv, int fVerbose ); +extern int Gia_ManSolveSat( Gia_Man_t * p ); + + +ABC_NAMESPACE_HEADER_END + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/yosys/abc/src/aig/gia/giaAiger.c b/yosys/abc/src/aig/gia/giaAiger.c new file mode 100644 index 00000000000..107faaceb40 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaAiger.c @@ -0,0 +1,1800 @@ +/**CFile**************************************************************** + + FileName [giaAiger.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Procedures to read/write binary AIGER format developed by + Armin Biere, Johannes Kepler University (http://fmv.jku.at/)] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaAiger.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/tim/tim.h" +#include "base/main/main.h" + +ABC_NAMESPACE_IMPL_START + +#define XAIG_VERBOSE 0 + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_FileFixName( char * pFileName ) +{ + char * pName; + for ( pName = pFileName; *pName; pName++ ) + if ( *pName == '>' ) + *pName = '\\'; +} +char * Gia_FileNameGeneric( char * FileName ) +{ + char * pDot, * pRes; + pRes = Abc_UtilStrsav( FileName ); + if ( (pDot = strrchr( pRes, '.' )) ) + *pDot = 0; + return pRes; +} +int Gia_FileSize( char * pFileName ) +{ + FILE * pFile; + int nFileSize; + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + printf( "Gia_FileSize(): The file is unavailable (absent or open).\n" ); + return 0; + } + fseek( pFile, 0, SEEK_END ); + nFileSize = ftell( pFile ); + fclose( pFile ); + return nFileSize; +} +void Gia_FileWriteBufferSize( FILE * pFile, int nSize ) +{ + unsigned char Buffer[5]; + Gia_AigerWriteInt( Buffer, nSize ); + fwrite( Buffer, 1, 4, pFile ); +} + +/**Function************************************************************* + + Synopsis [Create the array of literals to be written.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_AigerCollectLiterals( Gia_Man_t * p ) +{ + Vec_Int_t * vLits; + Gia_Obj_t * pObj; + int i; + vLits = Vec_IntAlloc( Gia_ManPoNum(p) ); + Gia_ManForEachRi( p, pObj, i ) + Vec_IntPush( vLits, Gia_ObjFaninLit0p(p, pObj) ); + Gia_ManForEachPo( p, pObj, i ) + Vec_IntPush( vLits, Gia_ObjFaninLit0p(p, pObj) ); + return vLits; +} +Vec_Int_t * Gia_AigerReadLiterals( unsigned char ** ppPos, int nEntries ) +{ + Vec_Int_t * vLits; + int Lit, LitPrev, Diff, i; + vLits = Vec_IntAlloc( nEntries ); + LitPrev = Gia_AigerReadUnsigned( ppPos ); + Vec_IntPush( vLits, LitPrev ); + for ( i = 1; i < nEntries; i++ ) + { +// Diff = Lit - LitPrev; +// Diff = (Lit < LitPrev)? -Diff : Diff; +// Diff = ((2 * Diff) << 1) | (int)(Lit < LitPrev); + Diff = Gia_AigerReadUnsigned( ppPos ); + Diff = (Diff & 1)? -(Diff >> 1) : Diff >> 1; + Lit = Diff + LitPrev; + Vec_IntPush( vLits, Lit ); + LitPrev = Lit; + } + return vLits; +} +Vec_Str_t * Gia_AigerWriteLiterals( Vec_Int_t * vLits ) +{ + Vec_Str_t * vBinary; + int Pos = 0, Lit, LitPrev, Diff, i; + vBinary = Vec_StrAlloc( 2 * Vec_IntSize(vLits) ); + LitPrev = Vec_IntEntry( vLits, 0 ); + Pos = Gia_AigerWriteUnsignedBuffer( (unsigned char *)Vec_StrArray(vBinary), Pos, LitPrev ); + Vec_IntForEachEntryStart( vLits, Lit, i, 1 ) + { + Diff = Lit - LitPrev; + Diff = (Lit < LitPrev)? -Diff : Diff; + Diff = (Diff << 1) | (int)(Lit < LitPrev); + Pos = Gia_AigerWriteUnsignedBuffer( (unsigned char *)Vec_StrArray(vBinary), Pos, Diff ); + LitPrev = Lit; + if ( Pos + 10 > vBinary->nCap ) + Vec_StrGrow( vBinary, vBinary->nCap+1 ); + } + vBinary->nSize = Pos; +/* + // verify + { + extern Vec_Int_t * Gia_AigerReadLiterals( char ** ppPos, int nEntries ); + char * pPos = Vec_StrArray( vBinary ); + Vec_Int_t * vTemp = Gia_AigerReadLiterals( &pPos, Vec_IntSize(vLits) ); + for ( i = 0; i < Vec_IntSize(vLits); i++ ) + { + int Entry1 = Vec_IntEntry(vLits,i); + int Entry2 = Vec_IntEntry(vTemp,i); + assert( Entry1 == Entry2 ); + } + Vec_IntFree( vTemp ); + } +*/ + return vBinary; +} + +/**Function************************************************************* + + Synopsis [Reads the AIG in the binary AIGER format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSimple, int fSkipStrash, int fCheck ) +{ + Gia_Man_t * pNew, * pTemp; + Vec_Ptr_t * vNamesIn = NULL, * vNamesOut = NULL, * vNamesRegIn = NULL, * vNamesRegOut = NULL, * vNamesNode = NULL; + Vec_Int_t * vLits = NULL, * vPoTypes = NULL; + Vec_Int_t * vNodes, * vDrivers, * vInits = NULL; + int iObj, iNode0, iNode1, fHieOnly = 0; + int nTotal, nInputs, nOutputs, nLatches, nAnds, i; + int nBad = 0, nConstr = 0, nJust = 0, nFair = 0; + unsigned char * pDrivers, * pSymbols, * pCur; + unsigned uLit0, uLit1, uLit; + + // read the parameters (M I L O A + B C J F) + pCur = (unsigned char *)pContents; while ( *pCur != ' ' ) pCur++; pCur++; + // read the number of objects + nTotal = atoi( (const char *)pCur ); while ( *pCur != ' ' ) pCur++; pCur++; + // read the number of inputs + nInputs = atoi( (const char *)pCur ); while ( *pCur != ' ' ) pCur++; pCur++; + // read the number of latches + nLatches = atoi( (const char *)pCur ); while ( *pCur != ' ' ) pCur++; pCur++; + // read the number of outputs + nOutputs = atoi( (const char *)pCur ); while ( *pCur != ' ' ) pCur++; pCur++; + // read the number of nodes + nAnds = atoi( (const char *)pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; + if ( *pCur == ' ' ) + { +// assert( nOutputs == 0 ); + // read the number of properties + pCur++; + nBad = atoi( (const char *)pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; + nOutputs += nBad; + } + if ( *pCur == ' ' ) + { + // read the number of properties + pCur++; + nConstr = atoi( (const char *)pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; + nOutputs += nConstr; + } + if ( *pCur == ' ' ) + { + // read the number of properties + pCur++; + nJust = atoi( (const char *)pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; + nOutputs += nJust; + } + if ( *pCur == ' ' ) + { + // read the number of properties + pCur++; + nFair = atoi( (const char *)pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; + nOutputs += nFair; + } + if ( *pCur != '\n' ) + { + fprintf( stdout, "The parameter line is in a wrong format.\n" ); + return NULL; + } + pCur++; + + // check the parameters + if ( nTotal != nInputs + nLatches + nAnds ) + { + fprintf( stdout, "The number of objects does not match.\n" ); + return NULL; + } + if ( nJust || nFair ) + { + fprintf( stdout, "Reading AIGER files with liveness properties is currently not supported.\n" ); + return NULL; + } + + if ( nConstr ) + { + if ( nConstr == 1 ) + fprintf( stdout, "Warning: The last output is interpreted as a constraint.\n" ); + else + fprintf( stdout, "Warning: The last %d outputs are interpreted as constraints.\n", nConstr ); + } + + // allocate the empty AIG + pNew = Gia_ManStart( nTotal + nLatches + nOutputs + 1 ); + pNew->nConstrs = nConstr; + pNew->fGiaSimple = fGiaSimple; + + // prepare the array of nodes + vNodes = Vec_IntAlloc( 1 + nTotal ); + Vec_IntPush( vNodes, 0 ); + + // create the PIs + for ( i = 0; i < nInputs + nLatches; i++ ) + { + iObj = Gia_ManAppendCi(pNew); + Vec_IntPush( vNodes, iObj ); + } + + // remember the beginning of latch/PO literals + pDrivers = pCur; + if ( pContents[3] == ' ' ) // standard AIGER + { + // scroll to the beginning of the binary data + for ( i = 0; i < nLatches + nOutputs; ) + if ( *pCur++ == '\n' ) + i++; + } + else // modified AIGER + { + vLits = Gia_AigerReadLiterals( &pCur, nLatches + nOutputs ); + } + + // create the AND gates + if ( !fGiaSimple && !fSkipStrash ) + Gia_ManHashAlloc( pNew ); + for ( i = 0; i < nAnds; i++ ) + { + uLit = ((i + 1 + nInputs + nLatches) << 1); + uLit1 = uLit - Gia_AigerReadUnsigned( &pCur ); + uLit0 = uLit1 - Gia_AigerReadUnsigned( &pCur ); +// assert( uLit1 > uLit0 ); + iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), uLit0 & 1 ); + iNode1 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit1 >> 1), uLit1 & 1 ); + assert( Vec_IntSize(vNodes) == i + 1 + nInputs + nLatches ); + if ( !fGiaSimple && fSkipStrash ) + { + if ( iNode0 == iNode1 ) + Vec_IntPush( vNodes, Gia_ManAppendBuf(pNew, iNode0) ); + else + Vec_IntPush( vNodes, Gia_ManAppendAnd(pNew, iNode0, iNode1) ); + } + else + Vec_IntPush( vNodes, Gia_ManHashAnd(pNew, iNode0, iNode1) ); + } + if ( !fGiaSimple && !fSkipStrash ) + Gia_ManHashStop( pNew ); + + // remember the place where symbols begin + pSymbols = pCur; + + // read the latch driver literals + vDrivers = Vec_IntAlloc( nLatches + nOutputs ); + if ( pContents[3] == ' ' ) // standard AIGER + { + vInits = Vec_IntAlloc( nLatches ); + pCur = pDrivers; + for ( i = 0; i < nLatches; i++ ) + { + uLit0 = atoi( (char *)pCur ); + while ( *pCur != ' ' && *pCur != '\n' ) + pCur++; + if ( *pCur == ' ' ) + { + pCur++; + Vec_IntPush( vInits, atoi( (char *)pCur ) ); + while ( *pCur++ != '\n' ); + } + else + { + pCur++; + Vec_IntPush( vInits, 0 ); + } + iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); + Vec_IntPush( vDrivers, iNode0 ); + } + // read the PO driver literals + for ( i = 0; i < nOutputs; i++ ) + { + uLit0 = atoi( (char *)pCur ); while ( *pCur++ != '\n' ); + iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); + Vec_IntPush( vDrivers, iNode0 ); + } + + } + else + { + // read the latch driver literals + for ( i = 0; i < nLatches; i++ ) + { + uLit0 = Vec_IntEntry( vLits, i ); + iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); + Vec_IntPush( vDrivers, iNode0 ); + } + // read the PO driver literals + for ( i = 0; i < nOutputs; i++ ) + { + uLit0 = Vec_IntEntry( vLits, i+nLatches ); + iNode0 = Abc_LitNotCond( Vec_IntEntry(vNodes, uLit0 >> 1), (uLit0 & 1) ); + Vec_IntPush( vDrivers, iNode0 ); + } + Vec_IntFree( vLits ); + } + + // create the POs + for ( i = 0; i < nOutputs; i++ ) + Gia_ManAppendCo( pNew, Vec_IntEntry(vDrivers, nLatches + i) ); + for ( i = 0; i < nLatches; i++ ) + Gia_ManAppendCo( pNew, Vec_IntEntry(vDrivers, i) ); + Vec_IntFree( vDrivers ); + + // create the latches + Gia_ManSetRegNum( pNew, nLatches ); + + // read signal names if they are of the special type + pCur = pSymbols; + if ( pCur < (unsigned char *)pContents + nFileSize && *pCur != 'c' ) + { + int fReadNames = 1; + if ( fReadNames ) + { + int fError = 0; + while ( !fError && pCur < (unsigned char *)pContents + nFileSize && *pCur != 'c' ) + { + int iTerm; + char * pType = (char *)pCur; + char * pName = NULL; + // check terminal type + if ( *pCur != 'i' && *pCur != 'o' && *pCur != 'l' && *pCur != 'n' ) + { + fError = 1; + break; + } + // get terminal number + iTerm = atoi( (char *)++pCur ); while ( *pCur++ != ' ' ); + // skip spaces + while ( *pCur == ' ' ) + pCur++; + // skip till the end of line + for ( pName = (char *)pCur; *pCur && *pCur != '\n'; pCur++ ); + if ( *pCur == '\n' ) + *pCur = 0; + // save the name + if ( *pType == 'i' ) + { + if ( vNamesIn == NULL ) + vNamesIn = Vec_PtrStart( nInputs ); + if ( Vec_PtrSize(vNamesIn) <= iTerm ) + { + fError = 1; + break; + } + Vec_PtrWriteEntry( vNamesIn, iTerm, Abc_UtilStrsav(pName) ); + } + else if ( *pType == 'o' ) + { + if ( vNamesOut == NULL ) + vNamesOut = Vec_PtrStart( nOutputs ); + if ( Vec_PtrSize(vNamesOut) <= iTerm ) + { + fError = 1; + break; + } + Vec_PtrWriteEntry( vNamesOut, iTerm, Abc_UtilStrsav(pName) ); + } + else if ( *pType == 'l' ) + { + char Buffer[1000]; + assert( strlen(pName) < 995 ); + sprintf( Buffer, "%s_in", pName ); + if ( vNamesRegIn == NULL ) + vNamesRegIn = Vec_PtrStart( nLatches ); + if ( vNamesRegOut == NULL ) + vNamesRegOut = Vec_PtrStart( nLatches ); + if ( Vec_PtrSize(vNamesRegIn) <= iTerm ) + { + fError = 1; + break; + } + Vec_PtrWriteEntry( vNamesRegIn, iTerm, Abc_UtilStrsav(Buffer) ); + Vec_PtrWriteEntry( vNamesRegOut, iTerm, Abc_UtilStrsav(pName) ); + } + else if ( *pType == 'n' ) + { + if ( Vec_IntSize(&pNew->vHTable) != 0 ) + { + printf( "Structural hashing should be disabled to read internal nodes names.\n" ); + fError = 1; + break; + } + if ( vNamesNode == NULL ) + vNamesNode = Vec_PtrStart( Gia_ManObjNum(pNew) ); + Vec_PtrWriteEntry( vNamesNode, iTerm, Abc_UtilStrsav(pName) ); + } + else + { + fError = 1; + break; + } + pCur++; + } + if ( fError ) + { + printf( "Error occurred when reading signal names. Signal names ignored.\n" ); + if ( vNamesIn ) Vec_PtrFreeFree( vNamesIn ), vNamesIn = NULL; + if ( vNamesOut ) Vec_PtrFreeFree( vNamesOut ), vNamesOut = NULL; + if ( vNamesRegIn ) Vec_PtrFreeFree( vNamesRegIn ), vNamesRegIn = NULL; + if ( vNamesRegOut ) Vec_PtrFreeFree( vNamesRegOut ), vNamesRegOut = NULL; + if ( vNamesNode ) Vec_PtrFreeFree( vNamesNode ), vNamesNode = NULL; + } + } + else + { + int fBreakUsed = 0; + unsigned char * pCurOld = pCur; + pNew->vUserPiIds = Vec_IntStartFull( nInputs ); + pNew->vUserPoIds = Vec_IntStartFull( nOutputs ); + pNew->vUserFfIds = Vec_IntStartFull( nLatches ); + while ( pCur < (unsigned char *)pContents + nFileSize && *pCur != 'c' ) + { + int iTerm; + char * pType = (char *)pCur; + // check terminal type + if ( *pCur != 'i' && *pCur != 'o' && *pCur != 'l' ) + { +// fprintf( stdout, "Wrong terminal type.\n" ); + fBreakUsed = 1; + break; + } + // get terminal number + iTerm = atoi( (char *)++pCur ); while ( *pCur++ != ' ' ); + // skip spaces + while ( *pCur == ' ' ) + pCur++; + // decode the user numbers: + // flops are named: @l + // PIs are named: @i + // POs are named: @o + if ( *pCur++ != '@' ) + { + fBreakUsed = 1; + break; + } + if ( *pCur == 'i' && *pType == 'i' ) + Vec_IntWriteEntry( pNew->vUserPiIds, iTerm, atoi((char *)pCur+1) ); + else if ( *pCur == 'o' && *pType == 'o' ) + Vec_IntWriteEntry( pNew->vUserPoIds, iTerm, atoi((char *)pCur+1) ); + else if ( *pCur == 'l' && *pType == 'l' ) + Vec_IntWriteEntry( pNew->vUserFfIds, iTerm, atoi((char *)pCur+1) ); + else + { + fprintf( stdout, "Wrong name format.\n" ); + fBreakUsed = 1; + break; + } + // skip digits + while ( *pCur++ != '\n' ); + } + // in case of abnormal termination, remove the arrays + if ( fBreakUsed ) + { + unsigned char * pName; + int Entry, nInvars, nConstr, iTerm; + + Vec_Int_t * vPoNames = Vec_IntStartFull( nOutputs ); + + Vec_IntFreeP( &pNew->vUserPiIds ); + Vec_IntFreeP( &pNew->vUserPoIds ); + Vec_IntFreeP( &pNew->vUserFfIds ); + + // try to figure out signal names + fBreakUsed = 0; + pCur = (unsigned char *)pCurOld; + while ( pCur < (unsigned char *)pContents + nFileSize && *pCur != 'c' ) + { + // get the terminal type + if ( *pCur == 'i' || *pCur == 'l' ) + { + // skip till the end of the line + while ( *pCur++ != '\n' ); + *(pCur-1) = 0; + continue; + } + if ( *pCur != 'o' ) + { +// fprintf( stdout, "Wrong terminal type.\n" ); + fBreakUsed = 1; + break; + } + // get the terminal number + iTerm = atoi( (char *)++pCur ); while ( *pCur++ != ' ' ); + // get the node + if ( iTerm < 0 || iTerm >= nOutputs ) + { + fprintf( stdout, "The output number (%d) is out of range.\n", iTerm ); + fBreakUsed = 1; + break; + } + if ( Vec_IntEntry(vPoNames, iTerm) != ~0 ) + { + fprintf( stdout, "The output number (%d) is listed twice.\n", iTerm ); + fBreakUsed = 1; + break; + } + + // get the name + pName = pCur; while ( *pCur++ != '\n' ); + *(pCur-1) = 0; + // assign the name + Vec_IntWriteEntry( vPoNames, iTerm, pName - (unsigned char *)pContents ); + } + + // check that all names are assigned + if ( !fBreakUsed ) + { + nInvars = nConstr = 0; + vPoTypes = Vec_IntStart( Gia_ManPoNum(pNew) ); + Vec_IntForEachEntry( vPoNames, Entry, i ) + { + if ( Entry == ~0 ) + continue; + if ( strncmp( pContents+Entry, "constraint:", 11 ) == 0 ) + { + Vec_IntWriteEntry( vPoTypes, i, 1 ); + nConstr++; + } + if ( strncmp( pContents+Entry, "invariant:", 10 ) == 0 ) + { + Vec_IntWriteEntry( vPoTypes, i, 2 ); + nInvars++; + } + } + if ( nConstr ) + fprintf( stdout, "Recognized and added %d constraints.\n", nConstr ); + if ( nInvars ) + fprintf( stdout, "Recognized and skipped %d invariants.\n", nInvars ); + if ( nConstr == 0 && nInvars == 0 ) + Vec_IntFreeP( &vPoTypes ); + } + Vec_IntFree( vPoNames ); + } + } + } + + + // check if there are other types of information to read + if ( pCur + 1 < (unsigned char *)pContents + nFileSize && *pCur == 'c' ) + { + int fVerbose = XAIG_VERBOSE; + Vec_Str_t * vStr; + unsigned char * pCurTemp; + pCur++; + // skip new line if present +// if ( *pCur == '\n' ) +// pCur++; + while ( pCur < (unsigned char *)pContents + nFileSize ) + { + // read extra AIG + if ( *pCur == 'a' ) + { + pCur++; + vStr = Vec_StrStart( Gia_AigerReadInt(pCur) ); pCur += 4; + memcpy( Vec_StrArray(vStr), pCur, (size_t)Vec_StrSize(vStr) ); + pCur += Vec_StrSize(vStr); + pNew->pAigExtra = Gia_AigerReadFromMemory( Vec_StrArray(vStr), Vec_StrSize(vStr), 0, 0, 0 ); + Vec_StrFree( vStr ); + if ( fVerbose ) printf( "Finished reading extension \"a\".\n" ); + } + // read number of constraints + else if ( *pCur == 'c' ) + { + pCur++; + assert( Gia_AigerReadInt(pCur) == 4 ); pCur += 4; + pNew->nConstrs = Gia_AigerReadInt( pCur ); pCur += 4; + if ( fVerbose ) printf( "Finished reading extension \"c\".\n" ); + } + // read delay information + else if ( *pCur == 'd' ) + { + pCur++; + assert( Gia_AigerReadInt(pCur) == 4 ); pCur += 4; + pNew->nAnd2Delay = Gia_AigerReadInt(pCur); pCur += 4; + if ( fVerbose ) printf( "Finished reading extension \"d\".\n" ); + } + else if ( *pCur == 'i' ) + { + pCur++; + nInputs = Gia_AigerReadInt(pCur)/4; pCur += 4; + pNew->vInArrs = Vec_FltStart( nInputs ); + memcpy( Vec_FltArray(pNew->vInArrs), pCur, (size_t)4*nInputs ); pCur += 4*nInputs; + if ( fVerbose ) printf( "Finished reading extension \"i\".\n" ); + } + else if ( *pCur == 'o' ) + { + pCur++; + nOutputs = Gia_AigerReadInt(pCur)/4; pCur += 4; + pNew->vOutReqs = Vec_FltStart( nOutputs ); + memcpy( Vec_FltArray(pNew->vOutReqs), pCur, (size_t)4*nOutputs ); pCur += 4*nOutputs; + if ( fVerbose ) printf( "Finished reading extension \"o\".\n" ); + } + // read equivalence classes + else if ( *pCur == 'e' ) + { + extern Gia_Rpr_t * Gia_AigerReadEquivClasses( unsigned char ** ppPos, int nSize ); + pCur++; + pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4; + pNew->pReprs = Gia_AigerReadEquivClasses( &pCur, Gia_ManObjNum(pNew) ); + pNew->pNexts = Gia_ManDeriveNexts( pNew ); + assert( pCur == pCurTemp ); + if ( fVerbose ) printf( "Finished reading extension \"e\".\n" ); + } + // read flop classes + else if ( *pCur == 'f' ) + { + pCur++; + assert( Gia_AigerReadInt(pCur) == 4*Gia_ManRegNum(pNew) ); pCur += 4; + pNew->vFlopClasses = Vec_IntStart( Gia_ManRegNum(pNew) ); + memcpy( Vec_IntArray(pNew->vFlopClasses), pCur, (size_t)4*Gia_ManRegNum(pNew) ); pCur += 4*Gia_ManRegNum(pNew); + if ( fVerbose ) printf( "Finished reading extension \"f\".\n" ); + } + // read gate classes + else if ( *pCur == 'g' ) + { + pCur++; + assert( Gia_AigerReadInt(pCur) == 4*Gia_ManObjNum(pNew) ); pCur += 4; + pNew->vGateClasses = Vec_IntStart( Gia_ManObjNum(pNew) ); + memcpy( Vec_IntArray(pNew->vGateClasses), pCur, (size_t)4*Gia_ManObjNum(pNew) ); pCur += 4*Gia_ManObjNum(pNew); + if ( fVerbose ) printf( "Finished reading extension \"g\".\n" ); + } + // read hierarchy information + else if ( *pCur == 'h' ) + { + pCur++; + vStr = Vec_StrStart( Gia_AigerReadInt(pCur) ); pCur += 4; + memcpy( Vec_StrArray(vStr), pCur, (size_t)Vec_StrSize(vStr) ); + pCur += Vec_StrSize(vStr); + pNew->pManTime = Tim_ManLoad( vStr, 1 ); + Vec_StrFree( vStr ); + fHieOnly = 1; + if ( fVerbose ) printf( "Finished reading extension \"h\".\n" ); + } + // read packing + else if ( *pCur == 'k' ) + { + extern Vec_Int_t * Gia_AigerReadPacking( unsigned char ** ppPos, int nSize ); + int nSize; + pCur++; + nSize = Gia_AigerReadInt(pCur); + pCurTemp = pCur + nSize + 4; pCur += 4; + pNew->vPacking = Gia_AigerReadPacking( &pCur, nSize ); + assert( pCur == pCurTemp ); + if ( fVerbose ) printf( "Finished reading extension \"k\".\n" ); + } + // read mapping + else if ( *pCur == 'm' ) + { + extern int * Gia_AigerReadMapping( unsigned char ** ppPos, int nSize ); + extern int * Gia_AigerReadMappingSimple( unsigned char ** ppPos, int nSize ); + extern Vec_Int_t * Gia_AigerReadMappingDoc( unsigned char ** ppPos, int nObjs ); + int nSize; + pCur++; + nSize = Gia_AigerReadInt(pCur); + pCurTemp = pCur + nSize + 4; pCur += 4; + pNew->vMapping = Gia_AigerReadMappingDoc( &pCur, Gia_ManObjNum(pNew) ); + assert( pCur == pCurTemp ); + if ( fVerbose ) printf( "Finished reading extension \"m\".\n" ); + } + // read model name + else if ( *pCur == 'n' ) + { + pCur++; + if ( (*pCur >= 'a' && *pCur <= 'z') || (*pCur >= 'A' && *pCur <= 'Z') || (*pCur >= '0' && *pCur <= '9') ) + { + ABC_FREE( pNew->pName ); + pNew->pName = Abc_UtilStrsav( (char *)pCur ); pCur += strlen(pNew->pName) + 1; + } + else + { + pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4; + ABC_FREE( pNew->pName ); + pNew->pName = Abc_UtilStrsav( (char *)pCur ); pCur += strlen(pNew->pName) + 1; + assert( pCur == pCurTemp ); + } + } + // read placement + else if ( *pCur == 'p' ) + { + Gia_Plc_t * pPlacement; + pCur++; + pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4; + pPlacement = ABC_ALLOC( Gia_Plc_t, Gia_ManObjNum(pNew) ); + memcpy( pPlacement, pCur, (size_t)4*Gia_ManObjNum(pNew) ); pCur += 4*Gia_ManObjNum(pNew); + assert( pCur == pCurTemp ); + pNew->pPlacement = pPlacement; + if ( fVerbose ) printf( "Finished reading extension \"p\".\n" ); + } + // read register classes + else if ( *pCur == 'r' ) + { + int i, nRegs; + pCur++; + pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4; + nRegs = Gia_AigerReadInt(pCur); pCur += 4; + //nRegs = (pCurTemp - pCur)/4; + pNew->vRegClasses = Vec_IntAlloc( nRegs ); + for ( i = 0; i < nRegs; i++ ) + Vec_IntPush( pNew->vRegClasses, Gia_AigerReadInt(pCur) ), pCur += 4; + assert( pCur == pCurTemp ); + if ( fVerbose ) printf( "Finished reading extension \"r\".\n" ); + } + // read register inits + else if ( *pCur == 's' ) + { + int i, nRegs; + pCur++; + pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4; + nRegs = Gia_AigerReadInt(pCur); pCur += 4; + pNew->vRegInits = Vec_IntAlloc( nRegs ); + for ( i = 0; i < nRegs; i++ ) + Vec_IntPush( pNew->vRegInits, Gia_AigerReadInt(pCur) ), pCur += 4; + assert( pCur == pCurTemp ); + if ( fVerbose ) printf( "Finished reading extension \"s\".\n" ); + } + // read configuration data + else if ( *pCur == 'b' ) + { + int nSize; + pCur++; + nSize = Gia_AigerReadInt(pCur); + pCurTemp = pCur + nSize + 4; pCur += 4; + pNew->pCellStr = Abc_UtilStrsav( (char*)pCur ); pCur += strlen((char*)pCur) + 1; + nSize = nSize - strlen(pNew->pCellStr) - 1; + assert( nSize % 4 == 0 ); + pNew->vConfigs = Vec_IntAlloc(nSize / 4); +// memcpy(Vec_IntArray(pNew->vConfigs), pCur, (size_t)nSize); pCur += nSize; + for ( i = 0; i < nSize / 4; i++ ) + Vec_IntPush( pNew->vConfigs, Gia_AigerReadInt(pCur) ), pCur += 4; + assert( pCur == pCurTemp ); + if ( fVerbose ) printf( "Finished reading extension \"b\".\n" ); + } + // read choices + else if ( *pCur == 'q' ) + { + int i, nPairs, iRepr, iNode; + assert( !Gia_ManHasChoices(pNew) ); + pNew->pSibls = ABC_CALLOC( int, Gia_ManObjNum(pNew) ); + pCur++; + pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4; + nPairs = Gia_AigerReadInt(pCur); pCur += 4; + for ( i = 0; i < nPairs; i++ ) + { + iRepr = Gia_AigerReadInt(pCur); pCur += 4; + iNode = Gia_AigerReadInt(pCur); pCur += 4; + pNew->pSibls[iRepr] = iNode; + assert( iRepr > iNode ); + } + assert( pCur == pCurTemp ); + if ( fVerbose ) printf( "Finished reading extension \"q\".\n" ); + } + // read switching activity + else if ( *pCur == 'u' ) + { + unsigned char * pSwitching; + pCur++; + pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4; + pSwitching = ABC_ALLOC( unsigned char, Gia_ManObjNum(pNew) ); + memcpy( pSwitching, pCur, (size_t)Gia_ManObjNum(pNew) ); pCur += Gia_ManObjNum(pNew); + assert( pCur == pCurTemp ); + if ( fVerbose ) printf( "Finished reading extension \"s\".\n" ); + } + // read timing manager + else if ( *pCur == 't' ) + { + pCur++; + vStr = Vec_StrStart( Gia_AigerReadInt(pCur) ); pCur += 4; + memcpy( Vec_StrArray(vStr), pCur, (size_t)Vec_StrSize(vStr) ); pCur += Vec_StrSize(vStr); + pNew->pManTime = Tim_ManLoad( vStr, 0 ); + Vec_StrFree( vStr ); + if ( fVerbose ) printf( "Finished reading extension \"t\".\n" ); + } + // read object classes + else if ( *pCur == 'v' ) + { + pCur++; + pNew->vObjClasses = Vec_IntStart( Gia_AigerReadInt(pCur)/4 ); pCur += 4; + memcpy( Vec_IntArray(pNew->vObjClasses), pCur, (size_t)4*Vec_IntSize(pNew->vObjClasses) ); + pCur += 4*Vec_IntSize(pNew->vObjClasses); + if ( fVerbose ) printf( "Finished reading extension \"v\".\n" ); + } + // read edge information + else if ( *pCur == 'w' ) + { + Vec_Int_t * vPairs; + int i, nPairs; + pCur++; + pCurTemp = pCur + Gia_AigerReadInt(pCur) + 4; pCur += 4; + nPairs = Gia_AigerReadInt(pCur); pCur += 4; + vPairs = Vec_IntAlloc( 2*nPairs ); + for ( i = 0; i < 2*nPairs; i++ ) + Vec_IntPush( vPairs, Gia_AigerReadInt(pCur) ), pCur += 4; + assert( pCur == pCurTemp ); + if ( fSkipStrash ) + { + Gia_ManEdgeFromArray( pNew, vPairs ); + if ( fVerbose ) printf( "Finished reading extension \"w\".\n" ); + } + else + printf( "Cannot read extension \"w\" because AIG is rehashed. Use \"&r -s \".\n" ); + Vec_IntFree( vPairs ); + } + else break; + } + } + + // skipping the comments + Vec_IntFree( vNodes ); + + // update polarity of the additional outputs + if ( nBad || nConstr || nJust || nFair ) + Gia_ManInvertConstraints( pNew ); + + // clean the PO drivers + if ( vPoTypes ) + { + pNew = Gia_ManDupWithConstraints( pTemp = pNew, vPoTypes ); + Gia_ManStop( pTemp ); + Vec_IntFreeP( &vPoTypes ); + } + + if ( !fGiaSimple && !fSkipStrash && Gia_ManHasDangling(pNew) ) + { + Tim_Man_t * pManTime; + Gia_Man_t * pAigExtra; + Vec_Int_t * vFlopMap, * vGateMap, * vObjMap, * vRegClasses, * vRegInits; + vRegClasses = pNew->vRegClasses; pNew->vRegClasses = NULL; + vRegInits = pNew->vRegInits; pNew->vRegInits = NULL; + vFlopMap = pNew->vFlopClasses; pNew->vFlopClasses = NULL; + vGateMap = pNew->vGateClasses; pNew->vGateClasses = NULL; + vObjMap = pNew->vObjClasses; pNew->vObjClasses = NULL; + pManTime = (Tim_Man_t *)pNew->pManTime; pNew->pManTime = NULL; + pAigExtra = pNew->pAigExtra; pNew->pAigExtra = NULL; + pNew = Gia_ManCleanup( pTemp = pNew ); + if ( (vGateMap || vObjMap) && (Gia_ManObjNum(pNew) < Gia_ManObjNum(pTemp)) ) + printf( "Cleanup removed objects after reading. Old gate/object abstraction maps are invalid!\n" ); + Gia_ManStop( pTemp ); + pNew->vRegClasses = vRegClasses; + pNew->vRegInits = vRegInits; + pNew->vFlopClasses = vFlopMap; + pNew->vGateClasses = vGateMap; + pNew->vObjClasses = vObjMap; + pNew->pManTime = pManTime; + pNew->pAigExtra = pAigExtra; + } + + if ( fHieOnly ) + { +// Tim_ManPrint( (Tim_Man_t *)pNew->pManTime ); + if ( Abc_FrameReadLibBox() == NULL ) + printf( "Warning: Creating unit-delay box delay tables because box library is not available.\n" ); + Tim_ManCreate( (Tim_Man_t *)pNew->pManTime, Abc_FrameReadLibBox(), pNew->vInArrs, pNew->vOutReqs ); + } + Vec_FltFreeP( &pNew->vInArrs ); + Vec_FltFreeP( &pNew->vOutReqs ); +/* + // check the result + if ( fCheck && !Gia_ManCheck( pNew ) ) + { + printf( "Gia_AigerRead: The network check has failed.\n" ); + Gia_ManStop( pNew ); + return NULL; + } +*/ + + if ( vInits && Vec_IntSum(vInits) ) + { + char * pInit = ABC_ALLOC( char, Vec_IntSize(vInits) + 1 ); + Gia_Obj_t * pObj; + int i; + assert( Vec_IntSize(vInits) == Gia_ManRegNum(pNew) ); + Gia_ManForEachRo( pNew, pObj, i ) + { + if ( Vec_IntEntry(vInits, i) == 0 ) + pInit[i] = '0'; + else if ( Vec_IntEntry(vInits, i) == 1 ) + pInit[i] = '1'; + else + { + assert( Vec_IntEntry(vInits, i) == Abc_Var2Lit(Gia_ObjId(pNew, pObj), 0) ); + // unitialized value of the latch is the latch literal according to http://fmv.jku.at/hwmcc11/beyond1.pdf + pInit[i] = 'X'; + } + } + pInit[i] = 0; + if ( !fSkipStrash ) + { + pNew = Gia_ManDupZeroUndc( pTemp = pNew, pInit, 0, fGiaSimple, 1 ); + pNew->nConstrs = pTemp->nConstrs; pTemp->nConstrs = 0; + Gia_ManStop( pTemp ); + } + ABC_FREE( pInit ); + } + Vec_IntFreeP( &vInits ); + if ( !fGiaSimple && !fSkipStrash && pNew->vMapping ) + { + Abc_Print( 0, "Structural hashing enabled while reading AIGER invalidated the mapping. Consider using \"&r -s\".\n" ); + Vec_IntFreeP( &pNew->vMapping ); + } + if ( vNamesIn && Gia_ManPiNum(pNew) != Vec_PtrSize(vNamesIn) ) + Abc_Print( 0, "The number of inputs does not match the number of input names.\n" ); + else if ( vNamesOut && Gia_ManPoNum(pNew) != Vec_PtrSize(vNamesOut) ) + Abc_Print( 0, "The number of output does not match the number of output names.\n" ); + else if ( vNamesRegOut && Gia_ManRegNum(pNew) != Vec_PtrSize(vNamesRegOut) ) + Abc_Print( 0, "The number of inputs does not match the number of flop names.\n" ); + else if ( vNamesIn && vNamesOut ) + { + pNew->vNamesIn = vNamesIn; vNamesIn = NULL; + pNew->vNamesOut = vNamesOut; vNamesOut = NULL; + if ( vNamesRegOut ) + { + Vec_PtrAppend( pNew->vNamesIn, vNamesRegOut ); + Vec_PtrClear( vNamesRegOut ); + Vec_PtrFree( vNamesRegOut ); + vNamesRegOut = NULL; + } + if ( vNamesRegIn ) + { + Vec_PtrAppend( pNew->vNamesOut, vNamesRegIn ); + Vec_PtrClear( vNamesRegIn ); + Vec_PtrFree( vNamesRegIn ); + vNamesRegIn = NULL; + } + } + if ( vNamesNode && Gia_ManObjNum(pNew) != Vec_PtrSize(vNamesNode) ) + Abc_Print( 0, "The size of the node name array does not match the number of objects. Names are not entered.\n" ); + else if ( vNamesNode ) + pNew->vNamesNode = vNamesNode, vNamesNode = NULL; + if ( vNamesIn ) Vec_PtrFreeFree( vNamesIn ); + if ( vNamesOut ) Vec_PtrFreeFree( vNamesOut ); + if ( vNamesRegIn ) Vec_PtrFreeFree( vNamesRegIn ); + if ( vNamesRegOut ) Vec_PtrFreeFree( vNamesRegOut ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Reads the AIG in the binary AIGER format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_AigerRead( char * pFileName, int fGiaSimple, int fSkipStrash, int fCheck ) +{ + FILE * pFile; + Gia_Man_t * pNew; + char * pName, * pContents; + int nFileSize; + int RetValue; + + // read the file into the buffer + Gia_FileFixName( pFileName ); + nFileSize = Gia_FileSize( pFileName ); + pFile = fopen( pFileName, "rb" ); + pContents = ABC_ALLOC( char, nFileSize ); + RetValue = fread( pContents, nFileSize, 1, pFile ); + fclose( pFile ); + + pNew = Gia_AigerReadFromMemory( pContents, nFileSize, fGiaSimple, fSkipStrash, fCheck ); + ABC_FREE( pContents ); + if ( pNew ) + { + ABC_FREE( pNew->pName ); + pName = Gia_FileNameGeneric( pFileName ); + pNew->pName = Abc_UtilStrsav( pName ); + ABC_FREE( pName ); + + assert( pNew->pSpec == NULL ); + pNew->pSpec = Abc_UtilStrsav( pFileName ); + } + return pNew; +} + + + +/**Function************************************************************* + + Synopsis [Writes the AIG in into the memory buffer.] + + Description [The resulting buffer constains the AIG in AIGER format. + The resulting buffer should be deallocated by the user.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Str_t * Gia_AigerWriteIntoMemoryStr( Gia_Man_t * p ) +{ + Vec_Str_t * vBuffer; + Gia_Obj_t * pObj; + int nNodes = 0, i, uLit, uLit0, uLit1; + // set the node numbers to be used in the output file + Gia_ManConst0(p)->Value = nNodes++; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = nNodes++; + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = nNodes++; + + // write the header "M I L O A" where M = I + L + A + vBuffer = Vec_StrAlloc( 3*Gia_ManObjNum(p) ); + Vec_StrPrintStr( vBuffer, "aig " ); + Vec_StrPrintNum( vBuffer, Gia_ManCandNum(p) ); + Vec_StrPrintStr( vBuffer, " " ); + Vec_StrPrintNum( vBuffer, Gia_ManPiNum(p) ); + Vec_StrPrintStr( vBuffer, " " ); + Vec_StrPrintNum( vBuffer, Gia_ManRegNum(p) ); + Vec_StrPrintStr( vBuffer, " " ); + Vec_StrPrintNum( vBuffer, Gia_ManPoNum(p) ); + Vec_StrPrintStr( vBuffer, " " ); + Vec_StrPrintNum( vBuffer, Gia_ManAndNum(p) ); + Vec_StrPrintStr( vBuffer, "\n" ); + + // write latch drivers + Gia_ManForEachRi( p, pObj, i ) + { + uLit = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) ); + Vec_StrPrintNum( vBuffer, uLit ); + Vec_StrPrintStr( vBuffer, "\n" ); + } + + // write PO drivers + Gia_ManForEachPo( p, pObj, i ) + { + uLit = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) ); + Vec_StrPrintNum( vBuffer, uLit ); + Vec_StrPrintStr( vBuffer, "\n" ); + } + // write the nodes into the buffer + Gia_ManForEachAnd( p, pObj, i ) + { + uLit = Abc_Var2Lit( Gia_ObjValue(pObj), 0 ); + uLit0 = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) ); + uLit1 = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin1(pObj)), Gia_ObjFaninC1(pObj) ); + assert( uLit0 != uLit1 ); + if ( uLit0 > uLit1 ) + { + int Temp = uLit0; + uLit0 = uLit1; + uLit1 = Temp; + } + Gia_AigerWriteUnsigned( vBuffer, uLit - uLit1 ); + Gia_AigerWriteUnsigned( vBuffer, uLit1 - uLit0 ); + } + Vec_StrPrintStr( vBuffer, "c" ); + return vBuffer; +} + +/**Function************************************************************* + + Synopsis [Writes the AIG in into the memory buffer.] + + Description [The resulting buffer constains the AIG in AIGER format. + The CI/CO/AND nodes are assumed to be ordered according to some rule. + The resulting buffer should be deallocated by the user.] + + SideEffects [Note that in vCos, PIs are order first, followed by latches!] + + SeeAlso [] + +***********************************************************************/ +Vec_Str_t * Gia_AigerWriteIntoMemoryStrPart( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos, int nRegs ) +{ + Vec_Str_t * vBuffer; + Gia_Obj_t * pObj; + int nNodes = 0, i, uLit, uLit0, uLit1; + // set the node numbers to be used in the output file + Gia_ManConst0(p)->Value = nNodes++; + Gia_ManForEachObjVec( vCis, p, pObj, i ) + { + assert( Gia_ObjIsCi(pObj) ); + pObj->Value = nNodes++; + } + Gia_ManForEachObjVec( vAnds, p, pObj, i ) + { + assert( Gia_ObjIsAnd(pObj) ); + pObj->Value = nNodes++; + } + + // write the header "M I L O A" where M = I + L + A + vBuffer = Vec_StrAlloc( 3*Gia_ManObjNum(p) ); + Vec_StrPrintStr( vBuffer, "aig " ); + Vec_StrPrintNum( vBuffer, Vec_IntSize(vCis) + Vec_IntSize(vAnds) ); + Vec_StrPrintStr( vBuffer, " " ); + Vec_StrPrintNum( vBuffer, Vec_IntSize(vCis) - nRegs ); + Vec_StrPrintStr( vBuffer, " " ); + Vec_StrPrintNum( vBuffer, nRegs ); + Vec_StrPrintStr( vBuffer, " " ); + Vec_StrPrintNum( vBuffer, Vec_IntSize(vCos) - nRegs ); + Vec_StrPrintStr( vBuffer, " " ); + Vec_StrPrintNum( vBuffer, Vec_IntSize(vAnds) ); + Vec_StrPrintStr( vBuffer, "\n" ); + + // write latch drivers + Gia_ManForEachObjVec( vCos, p, pObj, i ) + { + assert( Gia_ObjIsCo(pObj) ); + if ( i < Vec_IntSize(vCos) - nRegs ) + continue; + uLit = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) ); + Vec_StrPrintNum( vBuffer, uLit ); + Vec_StrPrintStr( vBuffer, "\n" ); + } + // write output drivers + Gia_ManForEachObjVec( vCos, p, pObj, i ) + { + assert( Gia_ObjIsCo(pObj) ); + if ( i >= Vec_IntSize(vCos) - nRegs ) + continue; + uLit = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) ); + Vec_StrPrintNum( vBuffer, uLit ); + Vec_StrPrintStr( vBuffer, "\n" ); + } + + // write the nodes into the buffer + Gia_ManForEachObjVec( vAnds, p, pObj, i ) + { + uLit = Abc_Var2Lit( Gia_ObjValue(pObj), 0 ); + uLit0 = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin0(pObj)), Gia_ObjFaninC0(pObj) ); + uLit1 = Abc_Var2Lit( Gia_ObjValue(Gia_ObjFanin1(pObj)), Gia_ObjFaninC1(pObj) ); + assert( uLit0 != uLit1 ); + if ( uLit0 > uLit1 ) + { + int Temp = uLit0; + uLit0 = uLit1; + uLit1 = Temp; + } + Gia_AigerWriteUnsigned( vBuffer, uLit - uLit1 ); + Gia_AigerWriteUnsigned( vBuffer, uLit1 - uLit0 ); + } + Vec_StrPrintStr( vBuffer, "c" ); + return vBuffer; +} + +/**Function************************************************************* + + Synopsis [Writes the AIG in the binary AIGER format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_AigerWriteS( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int fCompact, int fWriteNewLine, int fSkipComment ) +{ + int fVerbose = XAIG_VERBOSE; + FILE * pFile; + Gia_Man_t * p; + Gia_Obj_t * pObj; + Vec_Str_t * vStrExt; + int i, nBufferSize, Pos; + unsigned char * pBuffer; + unsigned uLit0, uLit1, uLit; + assert( pInit->nXors == 0 && pInit->nMuxes == 0 ); + + if ( Gia_ManCoNum(pInit) == 0 ) + { + printf( "AIG cannot be written because it has no POs.\n" ); + return; + } + + // start the output stream + pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Gia_AigerWrite(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + + // create normalized AIG + if ( !Gia_ManIsNormalized(pInit) ) + { +// printf( "Gia_AigerWrite(): Normalizing AIG for writing.\n" ); + p = Gia_ManDupNormalize( pInit, 0 ); + Gia_ManTransferMapping( p, pInit ); + Gia_ManTransferPacking( p, pInit ); + Gia_ManTransferTiming( p, pInit ); + p->nConstrs = pInit->nConstrs; + } + else + p = pInit; + + // write the header "M I L O A" where M = I + L + A + fprintf( pFile, "aig%s %u %u %u %u %u", + fCompact? "2" : "", + Gia_ManCiNum(p) + Gia_ManAndNum(p), + Gia_ManPiNum(p), + Gia_ManRegNum(p), + Gia_ManConstrNum(p) ? 0 : Gia_ManPoNum(p), + Gia_ManAndNum(p) ); + // write the extended header "B C J F" + if ( Gia_ManConstrNum(p) ) + fprintf( pFile, " %u %u", Gia_ManPoNum(p) - Gia_ManConstrNum(p), Gia_ManConstrNum(p) ); + fprintf( pFile, "\n" ); + + Gia_ManInvertConstraints( p ); + if ( !fCompact ) + { + // write latch drivers + Gia_ManForEachRi( p, pObj, i ) + fprintf( pFile, "%u\n", Gia_ObjFaninLit0p(p, pObj) ); + // write PO drivers + Gia_ManForEachPo( p, pObj, i ) + fprintf( pFile, "%u\n", Gia_ObjFaninLit0p(p, pObj) ); + } + else + { + Vec_Int_t * vLits = Gia_AigerCollectLiterals( p ); + Vec_Str_t * vBinary = Gia_AigerWriteLiterals( vLits ); + fwrite( Vec_StrArray(vBinary), 1, Vec_StrSize(vBinary), pFile ); + Vec_StrFree( vBinary ); + Vec_IntFree( vLits ); + } + Gia_ManInvertConstraints( p ); + + // write the nodes into the buffer + Pos = 0; + nBufferSize = 8 * Gia_ManAndNum(p) + 100; // skeptically assuming 3 chars per one AIG edge + pBuffer = ABC_ALLOC( unsigned char, nBufferSize ); + Gia_ManForEachAnd( p, pObj, i ) + { + uLit = Abc_Var2Lit( i, 0 ); + uLit0 = Gia_ObjFaninLit0( pObj, i ); + uLit1 = Gia_ObjFaninLit1( pObj, i ); + assert( p->fGiaSimple || Gia_ManBufNum(p) || uLit0 < uLit1 ); + Pos = Gia_AigerWriteUnsignedBuffer( pBuffer, Pos, uLit - uLit1 ); + Pos = Gia_AigerWriteUnsignedBuffer( pBuffer, Pos, uLit1 - uLit0 ); + if ( Pos > nBufferSize - 10 ) + { + printf( "Gia_AigerWrite(): AIGER generation has failed because the allocated buffer is too small.\n" ); + fclose( pFile ); + if ( p != pInit ) + Gia_ManStop( p ); + return; + } + } + assert( Pos < nBufferSize ); + + // write the buffer + fwrite( pBuffer, 1, Pos, pFile ); + ABC_FREE( pBuffer ); + + // write the symbol table + if ( p->vNamesIn && p->vNamesOut ) + { + assert( Vec_PtrSize(p->vNamesIn) == Gia_ManCiNum(p) ); + assert( Vec_PtrSize(p->vNamesOut) == Gia_ManCoNum(p) ); + // write PIs + Gia_ManForEachPi( p, pObj, i ) + fprintf( pFile, "i%d %s\n", i, (char *)Vec_PtrEntry(p->vNamesIn, i) ); + // write latches + Gia_ManForEachRo( p, pObj, i ) + fprintf( pFile, "l%d %s\n", i, (char *)Vec_PtrEntry(p->vNamesIn, Gia_ManPiNum(p) + i) ); + // write POs + Gia_ManForEachPo( p, pObj, i ) + fprintf( pFile, "o%d %s\n", i, (char *)Vec_PtrEntry(p->vNamesOut, i) ); + } + if ( p->vNamesNode && Vec_PtrSize(p->vNamesNode) != Gia_ManObjNum(p) ) + Abc_Print( 0, "The size of the node name array does not match the number of objects. Names are not written.\n" ); + else if ( p->vNamesNode ) + { + Gia_ManForEachAnd( p, pObj, i ) + if ( Vec_PtrEntry(p->vNamesNode, i) ) + fprintf( pFile, "n%d %s\n", i, (char *)Vec_PtrEntry(p->vNamesNode, i) ); + } + + // write the comment + if ( fWriteNewLine ) + fprintf( pFile, "c\n" ); + else + fprintf( pFile, "c" ); + + // write additional AIG + if ( p->pAigExtra ) + { + fprintf( pFile, "a" ); + vStrExt = Gia_AigerWriteIntoMemoryStr( p->pAigExtra ); + Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) ); + fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile ); + Vec_StrFree( vStrExt ); + if ( fVerbose ) printf( "Finished writing extension \"a\".\n" ); + } + // write constraints + if ( p->nConstrs ) + { + fprintf( pFile, "c" ); + Gia_FileWriteBufferSize( pFile, 4 ); + Gia_FileWriteBufferSize( pFile, p->nConstrs ); + } + // write timing information + if ( p->nAnd2Delay ) + { + fprintf( pFile, "d" ); + Gia_FileWriteBufferSize( pFile, 4 ); + Gia_FileWriteBufferSize( pFile, p->nAnd2Delay ); + } + if ( p->pManTime ) + { + float * pTimes; + pTimes = Tim_ManGetArrTimes( (Tim_Man_t *)p->pManTime ); + if ( pTimes ) + { + fprintf( pFile, "i" ); + Gia_FileWriteBufferSize( pFile, 4*Tim_ManPiNum((Tim_Man_t *)p->pManTime) ); + fwrite( pTimes, 1, 4*Tim_ManPiNum((Tim_Man_t *)p->pManTime), pFile ); + ABC_FREE( pTimes ); + if ( fVerbose ) printf( "Finished writing extension \"i\".\n" ); + } + pTimes = Tim_ManGetReqTimes( (Tim_Man_t *)p->pManTime ); + if ( pTimes ) + { + fprintf( pFile, "o" ); + Gia_FileWriteBufferSize( pFile, 4*Tim_ManPoNum((Tim_Man_t *)p->pManTime) ); + fwrite( pTimes, 1, 4*Tim_ManPoNum((Tim_Man_t *)p->pManTime), pFile ); + ABC_FREE( pTimes ); + if ( fVerbose ) printf( "Finished writing extension \"o\".\n" ); + } + } + // write equivalences + if ( p->pReprs && p->pNexts ) + { + extern Vec_Str_t * Gia_WriteEquivClasses( Gia_Man_t * p ); + fprintf( pFile, "e" ); + vStrExt = Gia_WriteEquivClasses( p ); + Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) ); + fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile ); + Vec_StrFree( vStrExt ); + } + // write flop classes + if ( p->vFlopClasses ) + { + fprintf( pFile, "f" ); + Gia_FileWriteBufferSize( pFile, 4*Gia_ManRegNum(p) ); + assert( Vec_IntSize(p->vFlopClasses) == Gia_ManRegNum(p) ); + fwrite( Vec_IntArray(p->vFlopClasses), 1, 4*Gia_ManRegNum(p), pFile ); + } + // write gate classes + if ( p->vGateClasses ) + { + fprintf( pFile, "g" ); + Gia_FileWriteBufferSize( pFile, 4*Gia_ManObjNum(p) ); + assert( Vec_IntSize(p->vGateClasses) == Gia_ManObjNum(p) ); + fwrite( Vec_IntArray(p->vGateClasses), 1, 4*Gia_ManObjNum(p), pFile ); + } + // write hierarchy info + if ( p->pManTime ) + { + fprintf( pFile, "h" ); + vStrExt = Tim_ManSave( (Tim_Man_t *)p->pManTime, 1 ); + Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) ); + fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile ); + Vec_StrFree( vStrExt ); + if ( fVerbose ) printf( "Finished writing extension \"h\".\n" ); + } + // write packing + if ( p->vPacking ) + { + extern Vec_Str_t * Gia_WritePacking( Vec_Int_t * vPacking ); + fprintf( pFile, "k" ); + vStrExt = Gia_WritePacking( p->vPacking ); + Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) ); + fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile ); + Vec_StrFree( vStrExt ); + if ( fVerbose ) printf( "Finished writing extension \"k\".\n" ); + } + // write edges + if ( p->vEdge1 ) + { + Vec_Int_t * vPairs = Gia_ManEdgeToArray( p ); + int i; + fprintf( pFile, "w" ); + Gia_FileWriteBufferSize( pFile, 4*(Vec_IntSize(vPairs)+1) ); + Gia_FileWriteBufferSize( pFile, Vec_IntSize(vPairs)/2 ); + for ( i = 0; i < Vec_IntSize(vPairs); i++ ) + Gia_FileWriteBufferSize( pFile, Vec_IntEntry(vPairs, i) ); + Vec_IntFree( vPairs ); + } + // write mapping + if ( Gia_ManHasMapping(p) ) + { + extern Vec_Str_t * Gia_AigerWriteMapping( Gia_Man_t * p ); + extern Vec_Str_t * Gia_AigerWriteMappingSimple( Gia_Man_t * p ); + extern Vec_Str_t * Gia_AigerWriteMappingDoc( Gia_Man_t * p ); + fprintf( pFile, "m" ); + vStrExt = Gia_AigerWriteMappingDoc( p ); + Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) ); + fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile ); + Vec_StrFree( vStrExt ); + if ( fVerbose ) printf( "Finished writing extension \"m\".\n" ); + } + // write cell mapping + if ( Gia_ManHasCellMapping(p) ) + { + extern Vec_Str_t * Gia_AigerWriteCellMappingDoc( Gia_Man_t * p ); + fprintf( pFile, "M" ); + vStrExt = Gia_AigerWriteCellMappingDoc( p ); + Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) ); + fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile ); + Vec_StrFree( vStrExt ); + if ( fVerbose ) printf( "Finished writing extension \"M\".\n" ); + + } + // write placement + if ( p->pPlacement ) + { + fprintf( pFile, "p" ); + Gia_FileWriteBufferSize( pFile, 4*Gia_ManObjNum(p) ); + fwrite( p->pPlacement, 1, 4*Gia_ManObjNum(p), pFile ); + } + // write register classes + if ( p->vRegClasses ) + { + int i; + fprintf( pFile, "r" ); + Gia_FileWriteBufferSize( pFile, 4*(Vec_IntSize(p->vRegClasses)+1) ); + Gia_FileWriteBufferSize( pFile, Vec_IntSize(p->vRegClasses) ); + for ( i = 0; i < Vec_IntSize(p->vRegClasses); i++ ) + Gia_FileWriteBufferSize( pFile, Vec_IntEntry(p->vRegClasses, i) ); + } + // write register inits + if ( p->vRegInits ) + { + int i; + fprintf( pFile, "s" ); + Gia_FileWriteBufferSize( pFile, 4*(Vec_IntSize(p->vRegInits)+1) ); + Gia_FileWriteBufferSize( pFile, Vec_IntSize(p->vRegInits) ); + for ( i = 0; i < Vec_IntSize(p->vRegInits); i++ ) + Gia_FileWriteBufferSize( pFile, Vec_IntEntry(p->vRegInits, i) ); + } + // write configuration data + if ( p->vConfigs ) + { + fprintf( pFile, "b" ); + assert( p->pCellStr != NULL ); + Gia_FileWriteBufferSize( pFile, 4*Vec_IntSize(p->vConfigs) + strlen(p->pCellStr) + 1 ); + fwrite( p->pCellStr, 1, strlen(p->pCellStr) + 1, pFile ); +// fwrite( Vec_IntArray(p->vConfigs), 1, 4*Vec_IntSize(p->vConfigs), pFile ); + for ( i = 0; i < Vec_IntSize(p->vConfigs); i++ ) + Gia_FileWriteBufferSize( pFile, Vec_IntEntry(p->vConfigs, i) ); + } + // write choices + if ( Gia_ManHasChoices(p) ) + { + int i, nPairs = 0; + fprintf( pFile, "q" ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + nPairs += (Gia_ObjSibl(p, i) > 0); + Gia_FileWriteBufferSize( pFile, 4*(nPairs * 2 + 1) ); + Gia_FileWriteBufferSize( pFile, nPairs ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + if ( Gia_ObjSibl(p, i) ) + { + assert( i > Gia_ObjSibl(p, i) ); + Gia_FileWriteBufferSize( pFile, i ); + Gia_FileWriteBufferSize( pFile, Gia_ObjSibl(p, i) ); + } + if ( fVerbose ) printf( "Finished writing extension \"q\".\n" ); + } + // write switching activity + if ( p->pSwitching ) + { + fprintf( pFile, "u" ); + Gia_FileWriteBufferSize( pFile, Gia_ManObjNum(p) ); + fwrite( p->pSwitching, 1, Gia_ManObjNum(p), pFile ); + } +/* + // write timing information + if ( p->pManTime ) + { + fprintf( pFile, "t" ); + vStrExt = Tim_ManSave( (Tim_Man_t *)p->pManTime, 0 ); + Gia_FileWriteBufferSize( pFile, Vec_StrSize(vStrExt) ); + fwrite( Vec_StrArray(vStrExt), 1, Vec_StrSize(vStrExt), pFile ); + Vec_StrFree( vStrExt ); + } +*/ + // write object classes + if ( p->vObjClasses ) + { + fprintf( pFile, "v" ); + Gia_FileWriteBufferSize( pFile, 4*Gia_ManObjNum(p) ); + assert( Vec_IntSize(p->vObjClasses) == Gia_ManObjNum(p) ); + fwrite( Vec_IntArray(p->vObjClasses), 1, 4*Gia_ManObjNum(p), pFile ); + } + // write name + if ( p->pName ) + { + fprintf( pFile, "n" ); + Gia_FileWriteBufferSize( pFile, strlen(p->pName)+1 ); + fwrite( p->pName, 1, strlen(p->pName), pFile ); + fprintf( pFile, "%c", '\0' ); + } + // write comments + if ( fWriteNewLine ) + fprintf( pFile, "c\n" ); + if ( !fSkipComment ) { + fprintf( pFile, "\nThis file was produced by the GIA package in ABC on %s\n", Gia_TimeStamp() ); + fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" ); + } + fclose( pFile ); + if ( p != pInit ) + { + Gia_ManTransferTiming( pInit, p ); + Gia_ManStop( p ); + } +} + +/**Function************************************************************* + + Synopsis [Writes the AIG in the binary AIGER format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_AigerWrite( Gia_Man_t * pInit, char * pFileName, int fWriteSymbols, int fCompact, int fWriteNewLine ) +{ + Gia_AigerWriteS( pInit, pFileName, fWriteSymbols, fCompact, fWriteNewLine, 0 ); +} + +/**Function************************************************************* + + Synopsis [Writes the AIG in the binary AIGER format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_DumpAiger( Gia_Man_t * p, char * pFilePrefix, int iFileNum, int nFileNumDigits ) +{ + char Buffer[100]; + sprintf( Buffer, "%s%0*d.aig", pFilePrefix, nFileNumDigits, iFileNum ); + Gia_AigerWrite( p, Buffer, 0, 0, 0 ); +} + +/**Function************************************************************* + + Synopsis [Writes the AIG in the binary AIGER format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_AigerWriteSimple( Gia_Man_t * pInit, char * pFileName ) +{ + FILE * pFile; + Vec_Str_t * vStr; + if ( Gia_ManPoNum(pInit) == 0 ) + { + printf( "Gia_AigerWriteSimple(): AIG cannot be written because it has no POs.\n" ); + return; + } + // start the output stream + pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Gia_AigerWriteSimple(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + // write the buffer + vStr = Gia_AigerWriteIntoMemoryStr( pInit ); + fwrite( Vec_StrArray(vStr), 1, Vec_StrSize(vStr), pFile ); + Vec_StrFree( vStr ); + fclose( pFile ); +} + + + +/**Function************************************************************* + + Synopsis [Simple AIGER reader/writer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Aiger_ReadUnsigned( FILE * pFile ) +{ + unsigned x = 0, i = 0; + unsigned char ch; + while ((ch = fgetc(pFile)) & 0x80) + x |= (ch & 0x7f) << (7 * i++); + return x | (ch << (7 * i)); +} +static inline void Aiger_WriteUnsigned( FILE * pFile, unsigned x ) +{ + unsigned char ch; + while (x & ~0x7f) + { + ch = (x & 0x7f) | 0x80; + fputc( ch, pFile ); + x >>= 7; + } + ch = x; + fputc( ch, pFile ); +} +int * Aiger_Read( char * pFileName, int * pnObjs, int * pnIns, int * pnLats, int * pnOuts, int * pnAnds ) +{ + int i, Temp, Value = 0, nTotal, nObjs, nIns, nLats, nOuts, nAnds, * pObjs; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Aiger_Read(): Cannot open the output file \"%s\".\n", pFileName ); + return NULL; + } + if ( fgetc(pFile) != 'a' || fgetc(pFile) != 'i' || fgetc(pFile) != 'g' ) + { + fprintf( stdout, "Aiger_Read(): Can only read binary AIGER.\n" ); + fclose( pFile ); + return NULL; + } + if ( fscanf(pFile, "%d %d %d %d %d", &nTotal, &nIns, &nLats, &nOuts, &nAnds) != 5 ) + { + fprintf( stdout, "Aiger_Read(): Cannot read the header line.\n" ); + fclose( pFile ); + return NULL; + } + if ( nTotal != nIns + nLats + nAnds ) + { + fprintf( stdout, "The number of objects does not match.\n" ); + fclose( pFile ); + return NULL; + } + nObjs = 1 + nIns + 2*nLats + nOuts + nAnds; + pObjs = ABC_CALLOC( int, nObjs * 2 ); + // read flop input literals + for ( i = 0; i < nLats; i++ ) + { + while ( fgetc(pFile) != '\n' ); + Value += fscanf( pFile, "%d", &Temp ); + pObjs[2*(nObjs-nLats+i)+0] = Temp; + pObjs[2*(nObjs-nLats+i)+1] = Temp; + } + // read output literals + for ( i = 0; i < nOuts; i++ ) + { + while ( fgetc(pFile) != '\n' ); + Value += fscanf( pFile, "%d", &Temp ); + pObjs[2*(nObjs-nOuts-nLats+i)+0] = Temp; + pObjs[2*(nObjs-nOuts-nLats+i)+1] = Temp; + } + assert( Value == nLats + nOuts ); + // read the binary part + while ( fgetc(pFile) != '\n' ); + for ( i = 0; i < nAnds; i++ ) + { + int uLit = 2*(1 + nIns + nLats + i); + int uLit1 = uLit - Aiger_ReadUnsigned( pFile ); + int uLit0 = uLit1 - Aiger_ReadUnsigned( pFile ); + pObjs[2*(1+nIns+nLats+i)+0] = uLit0; + pObjs[2*(1+nIns+nLats+i)+1] = uLit1; + } + fclose( pFile ); + if ( pnObjs ) *pnObjs = nObjs; + if ( pnIns ) *pnIns = nIns; + if ( pnLats ) *pnLats = nLats; + if ( pnOuts ) *pnOuts = nOuts; + if ( pnAnds ) *pnAnds = nAnds; + return pObjs; +} +void Aiger_Write( char * pFileName, int * pObjs, int nObjs, int nIns, int nLats, int nOuts, int nAnds ) +{ + FILE * pFile = fopen( pFileName, "wb" ); int i; + if ( pFile == NULL ) + { + fprintf( stdout, "Aiger_Write(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + fprintf( pFile, "aig %d %d %d %d %d\n", nIns + nLats + nAnds, nIns, nLats, nOuts, nAnds ); + for ( i = 0; i < nLats; i++ ) + fprintf( pFile, "%d\n", pObjs[2*(nObjs-nLats+i)+0] ); + for ( i = 0; i < nOuts; i++ ) + fprintf( pFile, "%d\n", pObjs[2*(nObjs-nOuts-nLats+i)+0] ); + for ( i = 0; i < nAnds; i++ ) + { + int uLit = 2*(1 + nIns + nLats + i); + int uLit0 = pObjs[2*(1+nIns+nLats+i)+0]; + int uLit1 = pObjs[2*(1+nIns+nLats+i)+1]; + Aiger_WriteUnsigned( pFile, uLit - uLit1 ); + Aiger_WriteUnsigned( pFile, uLit1 - uLit0 ); + } + fprintf( pFile, "c\n" ); + fclose( pFile ); +} +void Aiger_Test( char * pFileNameIn, char * pFileNameOut ) +{ + int nObjs, nIns, nLats, nOuts, nAnds, * pObjs = Aiger_Read( pFileNameIn, &nObjs, &nIns, &nLats, &nOuts, &nAnds ); + if ( pObjs == NULL ) + return; + printf( "Read input file \"%s\".\n", pFileNameIn ); + Aiger_Write( pFileNameOut, pObjs, nObjs, nIns, nLats, nOuts, nAnds ); + printf( "Written output file \"%s\".\n", pFileNameOut ); + ABC_FREE( pObjs ); +} + +/* +int main( int argc, char ** argv ) +{ + if ( argc != 3 ) + return 0; + Aiger_Test( argv[1], argv[2] ); + return 1; +} +*/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaAigerExt.c b/yosys/abc/src/aig/gia/giaAigerExt.c new file mode 100644 index 00000000000..d9f86f29428 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaAigerExt.c @@ -0,0 +1,424 @@ +/**CFile**************************************************************** + + FileName [giaAigerExt.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Custom AIGER extensions.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaAigerExt.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/st/st.h" +#include "map/mio/mio.h" +#include "map/mio/mioInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Read/write equivalence classes information.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Rpr_t * Gia_AigerReadEquivClasses( unsigned char ** ppPos, int nSize ) +{ + Gia_Rpr_t * pReprs; + unsigned char * pStop; + int i, Item, fProved, iRepr, iNode; + pStop = *ppPos; + pStop += Gia_AigerReadInt( *ppPos ); *ppPos += 4; + pReprs = ABC_CALLOC( Gia_Rpr_t, nSize ); + for ( i = 0; i < nSize; i++ ) + pReprs[i].iRepr = GIA_VOID; + iRepr = iNode = 0; + while ( *ppPos < pStop ) + { + Item = Gia_AigerReadUnsigned( ppPos ); + if ( Item & 1 ) + { + iRepr += (Item >> 1); + iNode = iRepr; + continue; + } + Item >>= 1; + fProved = (Item & 1); + Item >>= 1; + iNode += Item; + pReprs[iNode].fProved = fProved; + pReprs[iNode].iRepr = iRepr; + assert( iRepr < iNode ); + } + return pReprs; +} +unsigned char * Gia_WriteEquivClassesInt( Gia_Man_t * p, int * pEquivSize ) +{ + unsigned char * pBuffer; + int iRepr, iNode, iPrevRepr, iPrevNode, iLit, nItems, iPos; + assert( p->pReprs && p->pNexts ); + // count the number of entries to be written + nItems = 0; + for ( iRepr = 1; iRepr < Gia_ManObjNum(p); iRepr++ ) + { + nItems += Gia_ObjIsConst( p, iRepr ); + if ( !Gia_ObjIsHead(p, iRepr) ) + continue; + Gia_ClassForEachObj( p, iRepr, iNode ) + nItems++; + } + pBuffer = ABC_ALLOC( unsigned char, sizeof(int) * (nItems + 10) ); + // write constant class + iPos = Gia_AigerWriteUnsignedBuffer( pBuffer, 4, Abc_Var2Lit(0, 1) ); + iPrevNode = 0; + for ( iNode = 1; iNode < Gia_ManObjNum(p); iNode++ ) + if ( Gia_ObjIsConst(p, iNode) ) + { + iLit = Abc_Var2Lit( iNode - iPrevNode, Gia_ObjProved(p, iNode) ); + iPrevNode = iNode; + iPos = Gia_AigerWriteUnsignedBuffer( pBuffer, iPos, Abc_Var2Lit(iLit, 0) ); + } + // write non-constant classes + iPrevRepr = 0; + Gia_ManForEachClass( p, iRepr ) + { + iPos = Gia_AigerWriteUnsignedBuffer( pBuffer, iPos, Abc_Var2Lit(iRepr - iPrevRepr, 1) ); + iPrevRepr = iPrevNode = iRepr; + Gia_ClassForEachObj1( p, iRepr, iNode ) + { + iLit = Abc_Var2Lit( iNode - iPrevNode, Gia_ObjProved(p, iNode) ); + iPrevNode = iNode; + iPos = Gia_AigerWriteUnsignedBuffer( pBuffer, iPos, Abc_Var2Lit(iLit, 0) ); + } + } + Gia_AigerWriteInt( pBuffer, iPos ); + *pEquivSize = iPos; + return pBuffer; +} +Vec_Str_t * Gia_WriteEquivClasses( Gia_Man_t * p ) +{ + int nEquivSize; + unsigned char * pBuffer = Gia_WriteEquivClassesInt( p, &nEquivSize ); + return Vec_StrAllocArray( (char *)pBuffer, nEquivSize ); +} + +/**Function************************************************************* + + Synopsis [Read/write mapping information.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Gia_AigerReadDiffValue( unsigned char ** ppPos, int iPrev ) +{ + int Item = Gia_AigerReadUnsigned( ppPos ); + if ( Item & 1 ) + return iPrev + (Item >> 1); + return iPrev - (Item >> 1); +} +int * Gia_AigerReadMapping( unsigned char ** ppPos, int nSize ) +{ + int * pMapping; + unsigned char * pStop; + int k, j, nFanins, nAlloc, iNode = 0, iOffset = nSize; + pStop = *ppPos; + pStop += Gia_AigerReadInt( *ppPos ); *ppPos += 4; + nAlloc = nSize + pStop - *ppPos; + pMapping = ABC_CALLOC( int, nAlloc ); + while ( *ppPos < pStop ) + { + k = iOffset; + pMapping[k++] = nFanins = Gia_AigerReadUnsigned( ppPos ); + for ( j = 0; j <= nFanins; j++ ) + pMapping[k++] = iNode = Gia_AigerReadDiffValue( ppPos, iNode ); + pMapping[iNode] = iOffset; + iOffset = k; + } + assert( iOffset <= nAlloc ); + return pMapping; +} +static inline int Gia_AigerWriteDiffValue( unsigned char * pPos, int iPos, int iPrev, int iThis ) +{ + if ( iPrev < iThis ) + return Gia_AigerWriteUnsignedBuffer( pPos, iPos, Abc_Var2Lit(iThis - iPrev, 1) ); + return Gia_AigerWriteUnsignedBuffer( pPos, iPos, Abc_Var2Lit(iPrev - iThis, 0) ); +} +unsigned char * Gia_AigerWriteMappingInt( Gia_Man_t * p, int * pMapSize ) +{ + unsigned char * pBuffer; + int i, k, iPrev, iFan, nItems, iPos = 4; + assert( Gia_ManHasMapping(p) ); + // count the number of entries to be written + nItems = 0; + Gia_ManForEachLut( p, i ) + nItems += 2 + Gia_ObjLutSize( p, i ); + pBuffer = ABC_ALLOC( unsigned char, sizeof(int) * (nItems + 1) ); + // write non-constant classes + iPrev = 0; + Gia_ManForEachLut( p, i ) + { +//printf( "\nSize = %d ", Gia_ObjLutSize(p, i) ); + iPos = Gia_AigerWriteUnsignedBuffer( pBuffer, iPos, Gia_ObjLutSize(p, i) ); + Gia_LutForEachFanin( p, i, iFan, k ) + { +//printf( "Fan = %d ", iFan ); + iPos = Gia_AigerWriteDiffValue( pBuffer, iPos, iPrev, iFan ); + iPrev = iFan; + } + iPos = Gia_AigerWriteDiffValue( pBuffer, iPos, iPrev, i ); + iPrev = i; +//printf( "Node = %d ", i ); + } +//printf( "\n" ); + Gia_AigerWriteInt( pBuffer, iPos ); + *pMapSize = iPos; + return pBuffer; +} +Vec_Str_t * Gia_AigerWriteMapping( Gia_Man_t * p ) +{ + int nMapSize; + unsigned char * pBuffer = Gia_AigerWriteMappingInt( p, &nMapSize ); + return Vec_StrAllocArray( (char *)pBuffer, nMapSize ); +} + +/**Function************************************************************* + + Synopsis [Read/write mapping information.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Gia_AigerReadMappingSimple( unsigned char ** ppPos, int nSize ) +{ + int * pMapping = ABC_ALLOC( int, (size_t)nSize/4 ); + memcpy( pMapping, *ppPos, nSize ); + assert( nSize % 4 == 0 ); + return pMapping; +} +Vec_Str_t * Gia_AigerWriteMappingSimple( Gia_Man_t * p ) +{ + unsigned char * pBuffer = ABC_ALLOC( unsigned char, 4*Vec_IntSize(p->vMapping) ); + memcpy( pBuffer, Vec_IntArray(p->vMapping), (size_t)4*Vec_IntSize(p->vMapping) ); + assert( Vec_IntSize(p->vMapping) >= Gia_ManObjNum(p) ); + return Vec_StrAllocArray( (char *)pBuffer, 4*Vec_IntSize(p->vMapping) ); +} + +/**Function************************************************************* + + Synopsis [Read/write mapping information.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_AigerReadMappingDoc( unsigned char ** ppPos, int nObjs ) +{ + int * pMapping, nLuts, LutSize, iRoot, nFanins, i, k, nOffset; + nLuts = Gia_AigerReadInt( *ppPos ); *ppPos += 4; + LutSize = Gia_AigerReadInt( *ppPos ); *ppPos += 4; + pMapping = ABC_CALLOC( int, nObjs + (LutSize + 2) * nLuts ); + nOffset = nObjs; + for ( i = 0; i < nLuts; i++ ) + { + iRoot = Gia_AigerReadInt( *ppPos ); *ppPos += 4; + nFanins = Gia_AigerReadInt( *ppPos ); *ppPos += 4; + pMapping[iRoot] = nOffset; + // write one + pMapping[ nOffset++ ] = nFanins; + for ( k = 0; k < nFanins; k++ ) + { + pMapping[ nOffset++ ] = Gia_AigerReadInt( *ppPos ); *ppPos += 4; + } + pMapping[ nOffset++ ] = iRoot; + } + return Vec_IntAllocArray( pMapping, nOffset ); +} +Vec_Str_t * Gia_AigerWriteMappingDoc( Gia_Man_t * p ) +{ + unsigned char * pBuffer; + int i, k, iFan, nLuts = 0, LutSize = 0, nSize = 2, nSize2 = 0; + Gia_ManForEachLut( p, i ) + { + nLuts++; + nSize += Gia_ObjLutSize(p, i) + 2; + LutSize = Abc_MaxInt( LutSize, Gia_ObjLutSize(p, i) ); + } + pBuffer = ABC_ALLOC( unsigned char, 4 * nSize ); + Gia_AigerWriteInt( pBuffer + 4 * nSize2++, nLuts ); + Gia_AigerWriteInt( pBuffer + 4 * nSize2++, LutSize ); + Gia_ManForEachLut( p, i ) + { + Gia_AigerWriteInt( pBuffer + 4 * nSize2++, i ); + Gia_AigerWriteInt( pBuffer + 4 * nSize2++, Gia_ObjLutSize(p, i) ); + Gia_LutForEachFanin( p, i, iFan, k ) + Gia_AigerWriteInt( pBuffer + 4 * nSize2++, iFan ); + } + assert( nSize2 == nSize ); + return Vec_StrAllocArray( (char *)pBuffer, 4*nSize ); +} + +int Gia_AigerWriteCellMappingInstance( Gia_Man_t * p, unsigned char * pBuffer, int nSize2, int i ) +{ + int k, iFan; + if ( !Gia_ObjIsCellInv(p, i) ) { + Gia_AigerWriteInt( pBuffer + nSize2, Gia_ObjCellId(p, i) ); nSize2 += 4; + Gia_AigerWriteInt( pBuffer + nSize2, i ); nSize2 += 4; + Gia_CellForEachFanin( p, i, iFan, k ) + { + Gia_AigerWriteInt( pBuffer + nSize2, iFan ); + nSize2 += 4; + } + } else { + Gia_AigerWriteInt( pBuffer + nSize2, 3 ); nSize2 += 4; + Gia_AigerWriteInt( pBuffer + nSize2, i ); nSize2 += 4; + Gia_AigerWriteInt( pBuffer + nSize2, Abc_LitNot(i) ); nSize2 += 4; + } + + return nSize2; +} + +Vec_Str_t * Gia_AigerWriteCellMappingDoc( Gia_Man_t * p ) +{ + unsigned char * pBuffer; + int i, nCells = 0, nInstances = 0, nSize = 8, nSize2 = 0; + Mio_Cell2_t * pCells = Mio_CollectRootsNewDefault2( 6, &nCells, 0 ); + assert( pCells ); + + for (int i = 0; i < nCells; i++) + { + Mio_Gate_t *pGate = (Mio_Gate_t *) pCells[i].pMioGate; + Mio_Pin_t *pPin; + nSize += strlen(Mio_GateReadName(pGate)) + 1; + nSize += strlen(Mio_GateReadOutName(pGate)) + 1 + 4; + Mio_GateForEachPin( pGate, pPin ) + nSize += strlen(Mio_PinReadName(pPin)) + 1; + } + + Gia_ManForEachCell( p, i ) + { + assert ( !Gia_ObjIsCellBuf(p, i) ); // not implemented + nInstances++; + if ( Gia_ObjIsCellInv(p, i) ) + nSize += 12; + else + nSize += Gia_ObjCellSize(p, i) * 4 + 8; + } + + pBuffer = ABC_ALLOC( unsigned char, nSize ); + Gia_AigerWriteInt( pBuffer + nSize2, nCells ); nSize2 += 4; + Gia_AigerWriteInt( pBuffer + nSize2, nInstances ); nSize2 += 4; + + for (int i = 0; i < nCells; i++) + { + int nPins = 0; + Mio_Gate_t *pGate = (Mio_Gate_t *) pCells[i].pMioGate; + Mio_Pin_t *pPin; + + strcpy((char *) pBuffer + nSize2, Mio_GateReadName(pGate)); + nSize2 += strlen(Mio_GateReadName(pGate)) + 1; + strcpy((char *) pBuffer + nSize2, Mio_GateReadOutName(pGate)); + nSize2 += strlen(Mio_GateReadOutName(pGate)) + 1; + + Mio_GateForEachPin( pGate, pPin ) + nPins++; + Gia_AigerWriteInt( pBuffer + nSize2, nPins ); nSize2 += 4; + + Mio_GateForEachPin( pGate, pPin ) + { + strcpy((char *) pBuffer + nSize2, Mio_PinReadName(pPin)); + nSize2 += strlen(Mio_PinReadName(pPin)) + 1; + } + } + + Gia_ManForEachCell( p, i ) + { + if ( Gia_ObjIsCellBuf(p, i) ) + continue; + + if ( Gia_ObjIsCellInv(p, i) && !Abc_LitIsCompl(i) ) { + // swap the order so that the inverter is after the driver + // of the inverter's input + nSize2 = Gia_AigerWriteCellMappingInstance(p, pBuffer, nSize2, Abc_LitNot(i) ); + nSize2 = Gia_AigerWriteCellMappingInstance(p, pBuffer, nSize2, i ); + i += 1; + continue; + } + + nSize2 = Gia_AigerWriteCellMappingInstance(p, pBuffer, nSize2, i ); + } + + assert( nSize2 == nSize ); + ABC_FREE( pCells ); + return Vec_StrAllocArray( (char *)pBuffer, nSize ); +} + +/**Function************************************************************* + + Synopsis [Read/write packing information.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_AigerReadPacking( unsigned char ** ppPos, int nSize ) +{ + Vec_Int_t * vPacking = Vec_IntAlloc( nSize/4 ); + int i; + assert( nSize % 4 == 0 ); + for ( i = 0; i < nSize/4; i++, *ppPos += 4 ) + Vec_IntPush( vPacking, Gia_AigerReadInt( *ppPos ) ); + return vPacking; +} +Vec_Str_t * Gia_WritePacking( Vec_Int_t * vPacking ) +{ + unsigned char * pBuffer = ABC_ALLOC( unsigned char, 4*Vec_IntSize(vPacking) ); + int i, Entry, nSize = 0; + Vec_IntForEachEntry( vPacking, Entry, i ) + Gia_AigerWriteInt( pBuffer + 4 * nSize++, Entry ); + return Vec_StrAllocArray( (char *)pBuffer, 4*Vec_IntSize(vPacking) ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaBalAig.c b/yosys/abc/src/aig/gia/giaBalAig.c new file mode 100644 index 00000000000..5603b4108b6 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaBalAig.c @@ -0,0 +1,1107 @@ +/**CFile**************************************************************** + + FileName [giaBalance.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [AIG balancing.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaBalance.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/vec/vecHash.h" +#include "misc/vec/vecQue.h" +#include "opt/dau/dau.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// operation manager +typedef struct Dam_Man_t_ Dam_Man_t; +struct Dam_Man_t_ +{ + Gia_Man_t * pGia; // user's AIG + Vec_Int_t * vNod2Set; // node ID into fanin set + Vec_Int_t * vDiv2Nod; // div ID into root node set + Vec_Int_t * vSetStore; // fanin set storage + Vec_Int_t * vNodStore; // root node set storage + Vec_Flt_t * vCounts; // occur counts + Vec_Int_t * vNodLevR; // node reverse level + Vec_Int_t * vDivLevR; // divisor reverse level + Vec_Int_t * vVisit; // visited MUXes + Vec_Que_t * vQue; // pairs by their weight + Hash_IntMan_t * vHash; // pair hash table + abctime clkStart; // starting the clock + int nLevelMax; // maximum level + int nDivs; // extracted divisor count + int nAnds; // total AND node count + int nGain; // total gain in AND nodes + int nGainX; // gain from XOR nodes +}; + +static inline int Dam_ObjHand( Dam_Man_t * p, int i ) { return i < Vec_IntSize(p->vNod2Set) ? Vec_IntEntry(p->vNod2Set, i) : 0; } +static inline int * Dam_ObjSet( Dam_Man_t * p, int i ) { int h = Dam_ObjHand(p, i); if ( h == 0 ) return NULL; return Vec_IntEntryP(p->vSetStore, h); } + +static inline int Dam_DivHand( Dam_Man_t * p, int d ) { return d < Vec_IntSize(p->vDiv2Nod) ? Vec_IntEntry(p->vDiv2Nod, d) : 0; } +static inline int * Dam_DivSet( Dam_Man_t * p, int d ) { int h = Dam_DivHand(p, d); if ( h == 0 ) return NULL; return Vec_IntEntryP(p->vNodStore, h); } + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Simplify multi-input AND/XOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimplifyXor( Vec_Int_t * vSuper ) +{ + int i, k = 0, Prev = -1, This, fCompl = 0; + Vec_IntForEachEntry( vSuper, This, i ) + { + if ( This == 0 ) + continue; + if ( This == 1 ) + fCompl ^= 1; + else if ( Prev != This ) + Vec_IntWriteEntry( vSuper, k++, This ), Prev = This; + else + Prev = -1, k--; + } + Vec_IntShrink( vSuper, k ); + if ( Vec_IntSize( vSuper ) == 0 ) + Vec_IntPush( vSuper, fCompl ); + else if ( fCompl ) + Vec_IntWriteEntry( vSuper, 0, Abc_LitNot(Vec_IntEntry(vSuper, 0)) ); +} +void Gia_ManSimplifyAnd( Vec_Int_t * vSuper ) +{ + int i, k = 0, Prev = -1, This; + Vec_IntForEachEntry( vSuper, This, i ) + { + if ( This == 0 ) + { Vec_IntFill(vSuper, 1, 0); return; } + if ( This == 1 ) + continue; + if ( Prev == -1 || Abc_Lit2Var(Prev) != Abc_Lit2Var(This) ) + Vec_IntWriteEntry( vSuper, k++, This ), Prev = This; + else if ( Prev != This ) + { Vec_IntFill(vSuper, 1, 0); return; } + } + Vec_IntShrink( vSuper, k ); + if ( Vec_IntSize( vSuper ) == 0 ) + Vec_IntPush( vSuper, 1 ); +} + +/**Function************************************************************* + + Synopsis [Collect multi-input AND/XOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSuperCollectXor_rec( Gia_Man_t * p, Gia_Obj_t * pObj, int fStrict ) +{ + assert( !Gia_IsComplement(pObj) ); + if ( !Gia_ObjIsXor(pObj) || + (fStrict && Gia_ObjRefNum(p, pObj) > 1) || + Gia_ObjRefNum(p, pObj) > 2 || + (Gia_ObjRefNum(p, pObj) == 2 && (Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) == 1 || Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) == 1)) || + Vec_IntSize(p->vSuper) > 50 ) + { + Vec_IntPush( p->vSuper, Gia_ObjToLit(p, pObj) ); + return; + } + assert( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ); + Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin0(pObj), fStrict ); + Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin1(pObj), fStrict ); +} +void Gia_ManSuperCollectAnd_rec( Gia_Man_t * p, Gia_Obj_t * pObj, int fStrict ) +{ + if ( Gia_IsComplement(pObj) || + !Gia_ObjIsAndReal(p, pObj) || + (fStrict && Gia_ObjRefNum(p, pObj) > 1) || + Gia_ObjRefNum(p, pObj) > 2 || + (Gia_ObjRefNum(p, pObj) == 2 && (Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) == 1 || Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) == 1)) || + Vec_IntSize(p->vSuper) > 50 ) + { + Vec_IntPush( p->vSuper, Gia_ObjToLit(p, pObj) ); + return; + } + Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild0(pObj), fStrict ); + Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild1(pObj), fStrict ); +} +void Gia_ManSuperCollect( Gia_Man_t * p, Gia_Obj_t * pObj, int fStrict ) +{ +// int nSize; + if ( p->vSuper == NULL ) + p->vSuper = Vec_IntAlloc( 1000 ); + else + Vec_IntClear( p->vSuper ); + if ( Gia_ObjIsXor(pObj) ) + { + assert( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ); + Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin0(pObj), fStrict ); + Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin1(pObj), fStrict ); +// nSize = Vec_IntSize(vSuper); + Vec_IntSort( p->vSuper, 0 ); + Gia_ManSimplifyXor( p->vSuper ); +// if ( nSize != Vec_IntSize(vSuper) ) +// printf( "X %d->%d ", nSize, Vec_IntSize(vSuper) ); + } + else if ( Gia_ObjIsAndReal(p, pObj) ) + { + Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild0(pObj), fStrict ); + Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild1(pObj), fStrict ); +// nSize = Vec_IntSize(vSuper); + Vec_IntSort( p->vSuper, 0 ); + Gia_ManSimplifyAnd( p->vSuper ); +// if ( nSize != Vec_IntSize(vSuper) ) +// printf( "A %d->%d ", nSize, Vec_IntSize(vSuper) ); + } + else assert( 0 ); +// if ( nSize > 10 ) +// printf( "%d ", nSize ); + assert( Vec_IntSize(p->vSuper) > 0 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManFindSharedNode( Gia_Man_t * pNew, Vec_Int_t * vSuper, int iLit0 ) +{ + int i, iLit1 = Vec_IntEntryLast(vSuper); + // iterate through the nodes whose level is equal to that of the last one + int iLit1Level = Gia_ObjLevelId(pNew, Abc_Lit2Var(iLit1)); + for ( i = Vec_IntSize(vSuper)-1; i >= 0; i-- ) + { + int iLit2 = Vec_IntEntry(vSuper, i); + if ( iLit1Level != Gia_ObjLevelId(pNew, Abc_Lit2Var(iLit2)) ) + break; + if ( Abc_Lit2Var(iLit0) != Abc_Lit2Var(iLit2) && !Gia_ManHashLookupInt(pNew, iLit0, iLit2) ) // new node + continue; + // swap iLit2 and iLit1 + if ( iLit2 != iLit1 ) + { + Vec_IntWriteEntry( vSuper, i, iLit1 ); + Vec_IntWriteEntry( vSuper, Vec_IntSize(vSuper)-1, iLit2 ); + } + break; + } + return Vec_IntPop(vSuper); +} +void Gia_ManPrepareLastTwo( Gia_Man_t * pNew, Vec_Int_t * vSuper ) +{ + int i, k, Stop, Lit1, Lit2, Level1, Level2, * pArray; + int nSize = Vec_IntSize(vSuper); + if ( nSize == 2 ) + return; + assert( nSize > 2 ); + Level1 = Gia_ObjLevelId( pNew, Abc_Lit2Var(Vec_IntEntry(vSuper, nSize-2)) ); + // find the first one with Level1 + for ( Stop = nSize-3; Stop >= 0; Stop-- ) + { + Level2 = Gia_ObjLevelId( pNew, Abc_Lit2Var(Vec_IntEntry(vSuper, Stop)) ); + if ( Level1 != Level2 ) + break; + } + if ( Stop == nSize-3 ) + return; + // avoid worst-case quadratic behavior by looking at the last 8 nodes + Stop = Abc_MaxInt( Stop, nSize - 9 ); + for ( i = nSize - 1; i > Stop; i-- ) + for ( k = i - 1; k > Stop; k-- ) + { + Lit1 = Vec_IntEntry(vSuper, i); + Lit2 = Vec_IntEntry(vSuper, k); + if ( Abc_Lit2Var(Lit1) != Abc_Lit2Var(Lit2) && !Gia_ManHashLookupInt(pNew, Lit1, Lit2) ) // new node + continue; + // move Lit1 to be last and Lit2 to be the one before + pArray = Vec_IntArray( vSuper ); + if ( i != nSize-1 ) + ABC_SWAP( int, pArray[i], pArray[nSize-1] ); + if ( k != nSize-2 ) + ABC_SWAP( int, pArray[k], pArray[nSize-2] ); + } +} +void Gia_ManCreateGate( Gia_Man_t * pNew, Gia_Obj_t * pObj, Vec_Int_t * vSuper ) +{ + int iLit0 = Vec_IntPop(vSuper); + int iLit1 = Vec_IntPop(vSuper); +// int iLit1 = Gia_ManFindSharedNode(pNew, vSuper, iLit0); + int iLit, i; + if ( !Gia_ObjIsXor(pObj) ) + iLit = Gia_ManHashAnd( pNew, iLit0, iLit1 ); + else if ( pNew->pMuxes ) + iLit = Gia_ManHashXorReal( pNew, iLit0, iLit1 ); + else + iLit = Gia_ManHashXor( pNew, iLit0, iLit1 ); + Vec_IntPush( vSuper, iLit ); + Gia_ObjSetGateLevel( pNew, Gia_ManObj(pNew, Abc_Lit2Var(iLit)) ); + // shift to the corrent location + for ( i = Vec_IntSize(vSuper)-1; i > 0; i-- ) + { + int iLit1 = Vec_IntEntry(vSuper, i); + int iLit2 = Vec_IntEntry(vSuper, i-1); + if ( Gia_ObjLevelId(pNew, Abc_Lit2Var(iLit1)) <= Gia_ObjLevelId(pNew, Abc_Lit2Var(iLit2)) ) + break; + Vec_IntWriteEntry( vSuper, i, iLit2 ); + Vec_IntWriteEntry( vSuper, i-1, iLit1 ); + } +} +int Gia_ManBalanceGate( Gia_Man_t * pNew, Gia_Obj_t * pObj, Vec_Int_t * vSuper, int * pLits, int nLits ) +{ + assert( !Gia_ObjIsBuf(pObj) ); + Vec_IntClear( vSuper ); + if ( nLits == 1 ) + Vec_IntPush( vSuper, pLits[0] ); + else if ( nLits == 2 ) + { + Vec_IntPush( vSuper, pLits[0] ); + Vec_IntPush( vSuper, pLits[1] ); + Gia_ManCreateGate( pNew, pObj, vSuper ); + } + else if ( nLits > 2 ) + { + // collect levels + int i, * pArray, * pPerm; //int iLit; + for ( i = 0; i < nLits; i++ ) + Vec_IntPush( vSuper, Gia_ObjLevelId(pNew, Abc_Lit2Var(pLits[i])) ); + // sort by level + Vec_IntGrow( vSuper, 4 * nLits ); + pArray = Vec_IntArray( vSuper ); + pPerm = pArray + nLits; + Abc_QuickSortCostData( pArray, nLits, 1, (word *)(pArray + 2 * nLits), pPerm ); + // collect in the increasing order of level + for ( i = 0; i < nLits; i++ ) + Vec_IntWriteEntry( vSuper, i, pLits[pPerm[i]] ); + Vec_IntShrink( vSuper, nLits ); +/* + Vec_IntForEachEntry( vSuper, iLit, i ) + printf( "%d ", Gia_ObjLevel(pNew, Gia_ManObj( pNew, Abc_Lit2Var(iLit) )) ); + printf( "\n" ); +*/ + // perform incremental extraction + while ( Vec_IntSize(vSuper) > 1 ) + { + if ( !Gia_ObjIsXor(pObj) ) + Gia_ManPrepareLastTwo( pNew, vSuper ); + Gia_ManCreateGate( pNew, pObj, vSuper ); + } + } + // consider trivial case + assert( Vec_IntSize(vSuper) == 1 ); + return Vec_IntEntry(vSuper, 0); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManBalance_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int fStrict ) +{ + int i, iLit, iBeg, iEnd; + if ( ~pObj->Value ) + return; + assert( Gia_ObjIsAnd(pObj) ); + assert( !Gia_ObjIsBuf(pObj) ); + // handle MUX + if ( Gia_ObjIsMux(p, pObj) ) + { + Gia_ManBalance_rec( pNew, p, Gia_ObjFanin0(pObj), fStrict ); + Gia_ManBalance_rec( pNew, p, Gia_ObjFanin1(pObj), fStrict ); + Gia_ManBalance_rec( pNew, p, Gia_ObjFanin2(p, pObj), fStrict ); + pObj->Value = Gia_ManHashMuxReal( pNew, Gia_ObjFanin2Copy(p, pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin0Copy(pObj) ); + Gia_ObjSetGateLevel( pNew, Gia_ManObj(pNew, Abc_Lit2Var(pObj->Value)) ); + return; + } + // find supergate + Gia_ManSuperCollect( p, pObj, fStrict ); + // save entries + if ( p->vStore == NULL ) + p->vStore = Vec_IntAlloc( 1000 ); + iBeg = Vec_IntSize( p->vStore ); + Vec_IntAppend( p->vStore, p->vSuper ); + iEnd = Vec_IntSize( p->vStore ); + // call recursively + Vec_IntForEachEntryStartStop( p->vStore, iLit, i, iBeg, iEnd ) + { + Gia_Obj_t * pTemp = Gia_ManObj( p, Abc_Lit2Var(iLit) ); + Gia_ManBalance_rec( pNew, p, pTemp, fStrict ); + Vec_IntWriteEntry( p->vStore, i, Abc_LitNotCond(pTemp->Value, Abc_LitIsCompl(iLit)) ); + } + assert( Vec_IntSize(p->vStore) == iEnd ); + // consider general case + pObj->Value = Gia_ManBalanceGate( pNew, pObj, p->vSuper, Vec_IntEntryP(p->vStore, iBeg), iEnd-iBeg ); + Vec_IntShrink( p->vStore, iBeg ); +} +Gia_Man_t * Gia_ManBalanceInt( Gia_Man_t * p, int fStrict ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i; + Gia_ManFillValue( p ); + Gia_ManCreateRefs( p ); + // start the new manager + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc ); + pNew->vLevels = Vec_IntStart( pNew->nObjsAlloc ); + // create constant and inputs + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + // set arrival times for the input of the new AIG + if ( p->vCiArrs ) + { + int Id, And2Delay = p->And2Delay ? p->And2Delay : 1; + Gia_ManForEachCiId( pNew, Id, i ) + Vec_IntWriteEntry( pNew->vLevels, Id, Vec_IntEntry(p->vCiArrs, i)/And2Delay ); + } + else if ( p->vInArrs ) + { + int Id, And2Delay = p->And2Delay ? p->And2Delay : 1; + Gia_ManForEachCiId( pNew, Id, i ) + Vec_IntWriteEntry( pNew->vLevels, Id, (int)(Vec_FltEntry(p->vInArrs, i)/And2Delay) ); + } + // create internal nodes + Gia_ManHashStart( pNew ); + Gia_ManForEachBuf( p, pObj, i ) + { + Gia_ManBalance_rec( pNew, p, Gia_ObjFanin0(pObj), fStrict ); + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ObjSetGateLevel( pNew, Gia_ManObj(pNew, Abc_Lit2Var(pObj->Value)) ); + } + Gia_ManForEachCo( p, pObj, i ) + { + Gia_ManBalance_rec( pNew, p, Gia_ObjFanin0(pObj), fStrict ); + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + assert( !fStrict || Gia_ManObjNum(pNew) <= Gia_ManObjNum(p) ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + // perform cleanup + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManBalance( Gia_Man_t * p, int fSimpleAnd, int fStrict, int fVerbose ) +{ + Gia_Man_t * pNew, * pNew1, * pNew2; + if ( fVerbose ) Gia_ManPrintStats( p, NULL ); + pNew = fSimpleAnd ? Gia_ManDup( p ) : Gia_ManDupMuxes( p, 2 ); + Gia_ManTransferTiming( pNew, p ); + if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); + pNew1 = Gia_ManBalanceInt( pNew, fStrict ); + Gia_ManTransferTiming( pNew1, pNew ); + if ( fVerbose ) Gia_ManPrintStats( pNew1, NULL ); + Gia_ManStop( pNew ); + pNew2 = Gia_ManDupNoMuxes( pNew1, 0 ); + Gia_ManTransferTiming( pNew2, pNew1 ); + if ( fVerbose ) Gia_ManPrintStats( pNew2, NULL ); + Gia_ManStop( pNew1 ); + return pNew2; +} + + + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dam_Man_t * Dam_ManAlloc( Gia_Man_t * pGia ) +{ + Dam_Man_t * p; + p = ABC_CALLOC( Dam_Man_t, 1 ); + p->clkStart = Abc_Clock(); + p->vVisit = Vec_IntAlloc( 1000 ); + p->pGia = pGia; + return p; +} +void Dam_ManFree( Dam_Man_t * p ) +{ + Vec_IntFreeP( &p->vVisit ); + Vec_IntFreeP( &p->vDivLevR ); + Vec_IntFreeP( &p->vNodLevR ); + Vec_IntFreeP( &p->vNod2Set ); + Vec_IntFreeP( &p->vDiv2Nod ); + Vec_IntFreeP( &p->vSetStore ); + Vec_IntFreeP( &p->vNodStore ); + Vec_FltFreeP( &p->vCounts ); + Vec_QueFreeP( &p->vQue ); + Hash_IntManStop( p->vHash ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Collect initial multi-input gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dam_ManCollectSets_rec( Dam_Man_t * p, int Id ) +{ + Gia_Obj_t * pObj; + int i, iBeg, iEnd, iLit; + if ( Dam_ObjHand(p, Id) || Id == 0 ) + return; + pObj = Gia_ManObj(p->pGia, Id); + if ( Gia_ObjIsCi(pObj) ) + return; + if ( Gia_ObjIsBuf(pObj) ) + { + Dam_ManCollectSets_rec( p, Gia_ObjFaninId0(pObj, Id) ); + return; + } + if ( Gia_ObjIsMux(p->pGia, pObj) ) + { + if ( pObj->fMark0 ) + return; + pObj->fMark0 = 1; + Vec_IntPush( p->vVisit, Id ); + Dam_ManCollectSets_rec( p, Gia_ObjFaninId0(pObj, Id) ); + Dam_ManCollectSets_rec( p, Gia_ObjFaninId1(pObj, Id) ); + Dam_ManCollectSets_rec( p, Gia_ObjFaninId2(p->pGia, Id) ); + p->nAnds += 3; + return; + } + Gia_ManSuperCollect( p->pGia, pObj, 0 ); + Vec_IntWriteEntry( p->vNod2Set, Id, Vec_IntSize(p->vSetStore) ); + Vec_IntPush( p->vSetStore, Vec_IntSize(p->pGia->vSuper) ); + p->nAnds += (1 + 2 * Gia_ObjIsXor(pObj)) * (Vec_IntSize(p->pGia->vSuper) - 1); + // save entries + iBeg = Vec_IntSize( p->vSetStore ); + Vec_IntAppend( p->vSetStore, p->pGia->vSuper ); + iEnd = Vec_IntSize( p->vSetStore ); + // call recursively + Vec_IntForEachEntryStartStop( p->vSetStore, iLit, i, iBeg, iEnd ) + Dam_ManCollectSets_rec( p, Abc_Lit2Var(iLit) ); +} +void Dam_ManCollectSets( Dam_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManCreateRefs( p->pGia ); + p->vNod2Set = Vec_IntStart( Gia_ManObjNum(p->pGia) ); + p->vSetStore = Vec_IntAlloc( Gia_ManObjNum(p->pGia) ); + Vec_IntPush( p->vSetStore, -1 ); + Vec_IntClear( p->vVisit ); + Gia_ManForEachCo( p->pGia, pObj, i ) + Dam_ManCollectSets_rec( p, Gia_ObjFaninId0p(p->pGia, pObj) ); + ABC_FREE( p->pGia->pRefs ); + Gia_ManForEachObjVec( p->vVisit, p->pGia, pObj, i ) + pObj->fMark0 = 0; +} + +/**Function************************************************************* + + Synopsis [Create divisors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Dam_ManDivSlack( Dam_Man_t * p, int iLit0, int iLit1, int LevR ) +{ + int Lev0 = Gia_ObjLevel(p->pGia, Gia_ManObj(p->pGia, Abc_Lit2Var(iLit0))); + int Lev1 = Gia_ObjLevel(p->pGia, Gia_ManObj(p->pGia, Abc_Lit2Var(iLit1))); + int Slack = p->nLevelMax - LevR - Abc_MaxInt(Lev0, Lev1) - 1 - (int)(iLit0 > iLit1); + return Abc_MinInt( Slack, 100 ); +} +void Dam_ManCreateMultiRefs( Dam_Man_t * p, Vec_Int_t ** pvRefsAnd, Vec_Int_t ** pvRefsXor ) +{ + Vec_Int_t * vRefsAnd, * vRefsXor; + Gia_Obj_t * pObj; + int i, k, * pSet; + vRefsAnd = Vec_IntStart( 2 * Gia_ManObjNum(p->pGia) ); + vRefsXor = Vec_IntStart( Gia_ManObjNum(p->pGia) ); + Gia_ManForEachAnd( p->pGia, pObj, i ) + { + if ( !Dam_ObjHand(p, i) ) + continue; + pSet = Dam_ObjSet(p, i); + if ( Gia_ObjIsXor(pObj) ) + for ( k = 1; k <= pSet[0]; k++ ) + { + assert( !Abc_LitIsCompl(pSet[k]) ); + Vec_IntAddToEntry( vRefsXor, Abc_Lit2Var(pSet[k]), 1 ); + } + else if ( Gia_ObjIsAndReal(p->pGia, pObj) ) + for ( k = 1; k <= pSet[0]; k++ ) + Vec_IntAddToEntry( vRefsAnd, pSet[k], 1 ); + else assert( 0 ); + } + *pvRefsAnd = vRefsAnd; + *pvRefsXor = vRefsXor; +} +void Dam_ManCreatePairs( Dam_Man_t * p, int fVerbose ) +{ + Gia_Obj_t * pObj; + Hash_IntMan_t * vHash; + Vec_Int_t * vRefsAnd, * vRefsXor, * vSuper, * vDivs, * vRemap, * vLevRMax; + int i, j, k, Num, FanK, FanJ, nRefs, iNode, iDiv, * pSet; + int nPairsAll = 0, nPairsTried = 0, nPairsUsed = 0, nPairsXor = 0; + int nDivsAll = 0, nDivsUsed = 0, nDivsXor = 0; + Dam_ManCollectSets( p ); + vSuper = p->pGia->vSuper; + vDivs = Vec_IntAlloc( Gia_ManObjNum(p->pGia) ); + vHash = Hash_IntManStart( Gia_ManObjNum(p->pGia)/2 ); + vLevRMax = Vec_IntStart( 1000 ); + Dam_ManCreateMultiRefs( p, &vRefsAnd, &vRefsXor ); + Gia_ManForEachAnd( p->pGia, pObj, i ) + { + if ( !Dam_ObjHand(p, i) ) + continue; + pSet = Dam_ObjSet(p, i); + nPairsAll += pSet[0] * (pSet[0] - 1) / 2; + Vec_IntClear(vSuper); + if ( Gia_ObjIsXor(pObj) ) + { + for ( k = 1; k <= pSet[0]; k++ ) + if ( Vec_IntEntry(vRefsXor, Abc_Lit2Var(pSet[k])) > 1 ) + Vec_IntPush( vSuper, pSet[k] ); + } + else if ( Gia_ObjIsAndReal(p->pGia, pObj) ) + { + for ( k = 1; k <= pSet[0]; k++ ) + if ( Vec_IntEntry(vRefsAnd, pSet[k]) > 1 ) + Vec_IntPush( vSuper, pSet[k] ); + } + else assert( 0 ); + if ( Vec_IntSize(vSuper) < 2 ) + continue; + // enumerate pairs + nPairsTried += Vec_IntSize(vSuper) * (Vec_IntSize(vSuper) - 1) / 2; + Vec_IntPush( vDivs, -i ); // remember node + Vec_IntForEachEntry( vSuper, FanK, k ) + Vec_IntForEachEntryStart( vSuper, FanJ, j, k+1 ) + { + if ( (FanK > FanJ) ^ Gia_ObjIsXor(pObj) ) + Num = Hash_Int2ManInsert( vHash, FanJ, FanK, 0 ); + else + Num = Hash_Int2ManInsert( vHash, FanK, FanJ, 0 ); + if ( Hash_Int2ObjInc( vHash, Num ) == 1 ) + { + nDivsUsed++; + nDivsXor += Gia_ObjIsXor(pObj); + } + Vec_IntPush( vDivs, Num ); // remember devisor + // update reverse level + if ( Num >= Vec_IntSize(vLevRMax) ) + Vec_IntFillExtra( vLevRMax, 3 * Vec_IntSize(vLevRMax) / 2, 0 ); + Vec_IntUpdateEntry( vLevRMax, Num, Vec_IntEntry(p->vNodLevR, i) ); + } + } + Vec_IntFree( vRefsAnd ); + Vec_IntFree( vRefsXor ); +// Hash_IntManProfile( vHash ); + // remove entries that appear only once + p->vHash = Hash_IntManStart( 3 * nDivsUsed /2 ); + p->vCounts = Vec_FltAlloc( 2 * nDivsUsed ); Vec_FltPush( p->vCounts, ABC_INFINITY ); + p->vQue = Vec_QueAlloc( Vec_FltCap(p->vCounts) ); + Vec_QueSetPriority( p->vQue, Vec_FltArrayP(p->vCounts) ); + // mapping div to node + p->vDiv2Nod = Vec_IntAlloc( 2 * nDivsUsed ); Vec_IntPush( p->vDiv2Nod, ABC_INFINITY ); + p->vNodStore = Vec_IntAlloc( Gia_ManObjNum(p->pGia) ); Vec_IntPush( p->vNodStore, -1 ); + nDivsAll = Hash_IntManEntryNum(vHash); + vRemap = Vec_IntStartFull( nDivsAll+1 ); + for ( i = 1; i <= nDivsAll; i++ ) + { + nRefs = Hash_IntObjData2(vHash, i); + if ( nRefs < 2 ) + continue; + nPairsUsed += nRefs; + if ( Hash_IntObjData0(vHash, i) > Hash_IntObjData1(vHash, i) ) + nPairsXor += nRefs; + Num = Hash_Int2ManInsert( p->vHash, Hash_IntObjData0(vHash, i), Hash_IntObjData1(vHash, i), 0 ); + assert( Num == Hash_IntManEntryNum(p->vHash) ); + assert( Num == Vec_FltSize(p->vCounts) ); + Vec_FltPush( p->vCounts, nRefs + 0.005*Dam_ManDivSlack(p, Hash_IntObjData0(vHash, i), Hash_IntObjData1(vHash, i), Vec_IntEntry(vLevRMax, i)) ); + Vec_QuePush( p->vQue, Num ); + // remember divisors + assert( Num == Vec_IntSize(p->vDiv2Nod) ); + Vec_IntPush( p->vDiv2Nod, Vec_IntSize(p->vNodStore) ); + Vec_IntPush( p->vNodStore, 0 ); + Vec_IntFillExtra( p->vNodStore, Vec_IntSize(p->vNodStore) + nRefs, -1 ); + // remember entry + Vec_IntWriteEntry( vRemap, i, Num ); + } + assert( Vec_FltSize(p->vCounts) == Hash_IntManEntryNum(p->vHash)+1 ); + assert( Vec_IntSize(p->vDiv2Nod) == nDivsUsed+1 ); + Hash_IntManStop( vHash ); + Vec_IntFree( vLevRMax ); + // fill in the divisors + iNode = -1; + Vec_IntForEachEntry( vDivs, iDiv, i ) + { + if ( iDiv < 0 ) + { + iNode = -iDiv; + continue; + } + Num = Vec_IntEntry( vRemap, iDiv ); + if ( Num == -1 ) + continue; + pSet = Dam_DivSet( p, Num ); + pSet[++pSet[0]] = iNode; + } + Vec_IntFree( vRemap ); + Vec_IntFree( vDivs ); + // create storage for reverse level of divisor during update + p->vDivLevR = Vec_IntStart( 2 * nDivsUsed ); + // make sure divisors are added correctly +// for ( i = 1; i <= nDivsUsed; i++ ) +// assert( Dam_DivSet(p, i)[0] == Vec_FltEntry(p->vCounts, i)+1 ); + if ( !fVerbose ) + return; + // print stats + printf( "Pairs:" ); + printf( " Total =%9d (%6.2f %%)", nPairsAll, 100.0 * nPairsAll / Abc_MaxInt(nPairsAll, 1) ); + printf( " Tried =%9d (%6.2f %%)", nPairsTried, 100.0 * nPairsTried / Abc_MaxInt(nPairsAll, 1) ); + printf( " Used =%9d (%6.2f %%)", nPairsUsed, 100.0 * nPairsUsed / Abc_MaxInt(nPairsAll, 1) ); + printf( " Xor =%9d (%6.2f %%)", nPairsXor, 100.0 * nPairsXor / Abc_MaxInt(nPairsAll, 1) ); + printf( "\n" ); + printf( "Div: " ); + printf( " Total =%9d (%6.2f %%)", nDivsAll, 100.0 * nDivsAll / Abc_MaxInt(nDivsAll, 1) ); + printf( " Tried =%9d (%6.2f %%)", nDivsAll, 100.0 * nDivsAll / Abc_MaxInt(nDivsAll, 1) ); + printf( " Used =%9d (%6.2f %%)", nDivsUsed, 100.0 * nDivsUsed / Abc_MaxInt(nDivsAll, 1) ); + printf( " Xor =%9d (%6.2f %%)", nDivsXor, 100.0 * nDivsXor / Abc_MaxInt(nDivsAll, 1) ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Derives new AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dam_ManMultiAig_rec( Dam_Man_t * pMan, Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + int i, * pSet; + if ( ~pObj->Value ) + return; + assert( Gia_ObjIsAnd(pObj) ); + pSet = Dam_ObjSet(pMan, Gia_ObjId(p, pObj)); + if ( pSet == NULL ) + { + Dam_ManMultiAig_rec( pMan, pNew, p, Gia_ObjFanin0(pObj) ); + Dam_ManMultiAig_rec( pMan, pNew, p, Gia_ObjFanin1(pObj) ); + if ( Gia_ObjIsMux(p, pObj) ) + { + Dam_ManMultiAig_rec( pMan, pNew, p, Gia_ObjFanin2(p, pObj) ); + pObj->Value = Gia_ManHashMuxReal( pNew, Gia_ObjFanin2Copy(p, pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin0Copy(pObj) ); + } + else if ( Gia_ObjIsXor(pObj) ) + pObj->Value = Gia_ManHashXorReal( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ObjSetGateLevel( pNew, Gia_ManObj(pNew, Abc_Lit2Var(pObj->Value)) ); + return; + } + assert( Gia_ObjIsXor(pObj) || Gia_ObjIsAndReal(p, pObj) ); + // call recursively + for ( i = 1; i <= pSet[0]; i++ ) + { + Gia_Obj_t * pTemp = Gia_ManObj( p, Abc_Lit2Var(pSet[i]) ); + Dam_ManMultiAig_rec( pMan, pNew, p, pTemp ); + pSet[i] = Abc_LitNotCond( pTemp->Value, Abc_LitIsCompl(pSet[i]) ); + } + // create balanced gate + pObj->Value = Gia_ManBalanceGate( pNew, pObj, p->vSuper, pSet + 1, pSet[0] ); +} +Gia_Man_t * Dam_ManMultiAig( Dam_Man_t * pMan ) +{ + Gia_Man_t * p = pMan->pGia; + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i; + // start the new manager + pNew = Gia_ManStart( 2*Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc ); + pNew->vLevels = Vec_IntStart( pNew->nObjsAlloc ); + // create constant and inputs + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + { + pObj->Value = Gia_ManAppendCi( pNew ); + Vec_IntWriteEntry( pNew->vLevels, Abc_Lit2Var(pObj->Value), Gia_ObjLevel(p, pObj) ); + } + // create internal nodes + Gia_ManHashStart( pNew ); + Gia_ManForEachBuf( p, pObj, i ) + { + Dam_ManMultiAig_rec( pMan, pNew, p, Gia_ObjFanin0(pObj) ); + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ObjSetGateLevel( pNew, Gia_ManObj(pNew, Abc_Lit2Var(pObj->Value)) ); + } + Gia_ManForEachCo( p, pObj, i ) + { + Dam_ManMultiAig_rec( pMan, pNew, p, Gia_ObjFanin0(pObj) ); + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } +// assert( Gia_ManObjNum(pNew) <= Gia_ManObjNum(p) ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + // perform cleanup + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Updates the data-structure after extracting one divisor.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Dam_PrintDiv( Dam_Man_t * p, int iDiv ) +{ + if ( iDiv == 0 ) + printf( "Final statistics after extracting %6d divisors: ", p->nDivs ); + else + { + char Buffer[100]; + int iData0 = Hash_IntObjData0(p->vHash, iDiv); + int iData1 = Hash_IntObjData1(p->vHash, iDiv); + printf( "Div%5d : ", p->nDivs+1 ); + printf( "D%-8d = ", iDiv ); + sprintf( Buffer, "%c%d", Abc_LitIsCompl(iData0)? '!':' ', Abc_Lit2Var(iData0) ); + printf( "%8s ", Buffer ); + printf( "%c ", (iData0 < iData1) ? '*' : '+' ); + sprintf( Buffer, "%c%d", Abc_LitIsCompl(iData1)? '!':' ', Abc_Lit2Var(iData1) ); + printf( "%8s ", Buffer ); + printf( "Weight %9.2f ", Vec_FltEntry(p->vCounts, iDiv) ); + } + printf( "Divs =%8d ", Hash_IntManEntryNum(p->vHash) ); + printf( "Ands =%8d ", p->nAnds - p->nGain ); + Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); +} +void Dam_PrintQue( Dam_Man_t * p ) +{ + int i; + printf( "Divisor queue: \n" ); + for ( i = 1; i <= Hash_IntManEntryNum(p->vHash); i++ ) + { + int iLit0 = Hash_IntObjData0(p->vHash, i); + int iLit1 = Hash_IntObjData1(p->vHash, i); + printf( "Div %7d : ", i ); + printf( "Weight %9.2f ", Vec_FltEntry(p->vCounts, i) ); + printf( "F = %c%c ", Abc_LitIsCompl(iLit0) ? '!': ' ', 'a' + Abc_Lit2Var(iLit0)-1 ); + printf( "%c ", (Hash_IntObjData0(p->vHash, i) < Hash_IntObjData1(p->vHash, i)) ? '*':'+' ); + printf( "%c%c ", Abc_LitIsCompl(iLit1) ? '!': ' ', 'a' + Abc_Lit2Var(iLit1)-1 ); + printf( "\n" ); + } +} +int Dam_ManUpdateNode( Dam_Man_t * p, int iObj, int iLit0, int iLit1, int iLitNew, Vec_Int_t * vDivs ) +{ + int * pSet = Dam_ObjSet( p, iObj ); + int i, k, c, Num, iLit, iLit2, fPres; + // check if literal can be found + for ( i = 1; i <= pSet[0]; i++ ) + if ( pSet[i] == iLit0 ) + break; + if ( i > pSet[0] ) + return 0; + // check if literal can be found + for ( i = 1; i <= pSet[0]; i++ ) + if ( pSet[i] == iLit1 ) + break; + if ( i > pSet[0] ) + return 0; + // compact literals + Vec_IntPush( vDivs, -iObj ); + for ( k = i = 1; i <= pSet[0]; i++ ) + { + if ( iLit0 == pSet[i] || iLit1 == pSet[i] ) + continue; + pSet[k++] = iLit = pSet[i]; + // reduce weights of the divisors + fPres = 0; + for ( c = 0; c < 2; c++ ) + { + iLit2 = c ? iLit1 : iLit0; + if ( (iLit > iLit2) ^ (iLit0 > iLit1) ) + Num = *Hash_Int2ManLookup( p->vHash, iLit2, iLit ); + else + Num = *Hash_Int2ManLookup( p->vHash, iLit, iLit2 ); + if ( Num > 0 ) + { + Vec_FltAddToEntry( p->vCounts, Num, -1 ); + if ( Vec_QueIsMember(p->vQue, Num) ) + { + Vec_QueUpdate( p->vQue, Num ); + fPres |= (1 << c); + } + } + } + if ( fPres != 3 ) + continue; + if ( (iLit > iLitNew) ^ (iLit0 > iLit1) ) + Num = Hash_Int2ManInsert( p->vHash, iLitNew, iLit, 0 ); + else + Num = Hash_Int2ManInsert( p->vHash, iLit, iLitNew, 0 ); + Hash_Int2ObjInc( p->vHash, Num ); + Vec_IntPush( vDivs, Num ); + // update reverse level + if ( Num >= Vec_IntSize(p->vDivLevR) ) + Vec_IntFillExtra( p->vDivLevR, 3 * Vec_IntSize(p->vDivLevR) / 2, 0 ); + Vec_IntUpdateEntry( p->vDivLevR, Num, Vec_IntEntry(p->vNodLevR, iObj) ); + } + pSet[k] = iLitNew; + pSet[0] = k; + return 1; +} +void Dam_ManUpdate( Dam_Man_t * p, int iDiv ) +{ + Vec_Int_t * vDivs = p->pGia->vSuper; + int iLit0 = Hash_IntObjData0(p->vHash, iDiv); + int iLit1 = Hash_IntObjData1(p->vHash, iDiv); + int i, iLitNew, * pSet, * pNods = Dam_DivSet( p, iDiv ); + int nPresent = 0, nPairsStart, nPairsStop, pPairsNew, nRefs; + int fThisIsXor = (iLit0 > iLit1), iDivTemp, iNode; +// Dam_PrintQue( p ); + if ( fThisIsXor ) + iLitNew = Gia_ManAppendXorReal( p->pGia, iLit0, iLit1 ); + else + iLitNew = Gia_ManAppendAnd( p->pGia, iLit0, iLit1 ); + Gia_ObjSetGateLevel( p->pGia, Gia_ManObj(p->pGia, Abc_Lit2Var(iLitNew)) ); +// printf( "%d ", Gia_ObjLevel(p->pGia, Gia_ManObj(p->pGia, Abc_Lit2Var(iLitNew))) ); + // replace entries + assert( pNods[0] >= 2 ); + nPairsStart = Hash_IntManEntryNum(p->vHash) + 1; + Vec_IntClear( vDivs ); + for ( i = 1; i <= pNods[0]; i++ ) + nPresent += Dam_ManUpdateNode( p, pNods[i], iLit0, iLit1, iLitNew, vDivs ); + nPairsStop = Hash_IntManEntryNum(p->vHash) + 1; + // extend arrayvs + pPairsNew = 0; + Vec_FltFillExtra( p->vCounts, nPairsStop, 0 ); + Vec_IntFillExtra( p->vDiv2Nod, nPairsStop, -1 ); + for ( i = nPairsStart; i < nPairsStop; i++ ) + { + nRefs = Hash_IntObjData2(p->vHash, i); + if ( nRefs < 2 ) + continue; + Vec_FltWriteEntry( p->vCounts, i, nRefs + 0.001*Dam_ManDivSlack(p, Hash_IntObjData0(p->vHash, i), Hash_IntObjData1(p->vHash, i), Vec_IntEntry(p->vDivLevR, i)) ); + Vec_QuePush( p->vQue, i ); + // remember divisors + Vec_IntWriteEntry( p->vDiv2Nod, i, Vec_IntSize(p->vNodStore) ); + Vec_IntPush( p->vNodStore, 0 ); + Vec_IntFillExtra( p->vNodStore, Vec_IntSize(p->vNodStore) + nRefs, -1 ); + pPairsNew++; + } +// printf( "Added %d new pairs\n", pPairsNew ); + // fill in the divisors + iNode = -1; + Vec_IntForEachEntry( vDivs, iDivTemp, i ) + { + if ( iDivTemp < 0 ) + { + iNode = -iDivTemp; + continue; + } + if ( Vec_IntEntry(p->vDiv2Nod, iDivTemp) == -1 ) + continue; + pSet = Dam_DivSet( p, iDivTemp ); + pSet[++pSet[0]] = iNode; + } + // make sure divisors are added correctly + for ( i = nPairsStart; i < nPairsStop; i++ ) + if ( Vec_IntEntry(p->vDiv2Nod, i) > 0 ) + assert( Dam_DivSet(p, i)[0] == Hash_IntObjData2(p->vHash, i) ); + // update costs + Vec_FltWriteEntry( p->vCounts, iDiv, 0 ); + p->nGain += (1 + 2 * fThisIsXor) * (nPresent - 1); + p->nGainX += 3 * fThisIsXor * (nPresent - 1); + p->nDivs++; +} + +/**Function************************************************************* + + Synopsis [Perform extraction for multi-input AND/XOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Dam_ManAreaBalanceInt( Gia_Man_t * pGia, Vec_Int_t * vCiLevels, int nNewNodesMax, int fVerbose, int fVeryVerbose ) +{ + Gia_Man_t * pNew; + Dam_Man_t * p; + int i, iDiv; + p = Dam_ManAlloc( pGia ); + p->nLevelMax = Gia_ManSetLevels( p->pGia, vCiLevels ); + p->vNodLevR = Gia_ManReverseLevel( p->pGia ); + Vec_IntFillExtra( p->pGia->vLevels, 3*Gia_ManObjNum(p->pGia)/2, 0 ); + Dam_ManCreatePairs( p, fVerbose ); + for ( i = 0; i < nNewNodesMax && Vec_QueTopPriority(p->vQue) >= 2; i++ ) + { + iDiv = Vec_QuePop(p->vQue); + if ( fVeryVerbose ) + Dam_PrintDiv( p, iDiv ); + Dam_ManUpdate( p, iDiv ); + } + if ( fVeryVerbose ) + Dam_PrintDiv( p, 0 ); + pNew = Dam_ManMultiAig( p ); + if ( fVerbose ) + { + int nDivsAll = Hash_IntManEntryNum(p->vHash); + int nDivsUsed = p->nDivs; + printf( "Div: " ); + printf( " Total =%9d (%6.2f %%) ", nDivsAll, 100.0 * nDivsAll / Abc_MaxInt(nDivsAll, 1) ); + printf( " Used =%9d (%6.2f %%)", nDivsUsed, 100.0 * nDivsUsed / Abc_MaxInt(nDivsAll, 1) ); + printf( " Gain =%6d (%6.2f %%)", p->nGain, 100.0 * p->nGain / Abc_MaxInt(p->nAnds, 1) ); + printf( " GainX = %d ", p->nGainX ); + Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); + } + Dam_ManFree( p ); + return pNew; +} +Gia_Man_t * Gia_ManAreaBalance( Gia_Man_t * p, int fSimpleAnd, int nNewNodesMax, int fVerbose, int fVeryVerbose ) +{ + Gia_Man_t * pNew0, * pNew, * pNew1, * pNew2; + Vec_Int_t * vCiLevels; + // set arrival times for the input of the new AIG + if ( p->vCiArrs ) + { + int i, Id, And2Delay = p->And2Delay ? p->And2Delay : 1; + Vec_IntFreeP( &p->vLevels ); + p->vLevels = Vec_IntStart( Gia_ManObjNum(p) ); + Gia_ManForEachCiId( p, Id, i ) + Vec_IntWriteEntry( p->vLevels, Id, Vec_IntEntry(p->vCiArrs, i)/And2Delay ); + } + else if ( p->vInArrs ) + { + int i, Id, And2Delay = p->And2Delay ? p->And2Delay : 1; + Gia_ManForEachCiId( p, Id, i ) + Vec_IntWriteEntry( p->vLevels, Id, (int)(Vec_FltEntry(p->vInArrs, i)/And2Delay) ); + } + // determine CI levels + if ( p->pManTime && p->vLevels == NULL ) + Gia_ManLevelWithBoxes( p ); + vCiLevels = Gia_ManGetCiLevels( p ); + // get the starting manager + pNew0 = Gia_ManHasMapping(p) ? (Gia_Man_t *)Dsm_ManDeriveGia(p, 0) : Gia_ManDup(p); + Gia_ManTransferTiming( pNew0, p ); + if ( fVerbose ) Gia_ManPrintStats( pNew0, NULL ); + // derive internal manager + pNew = fSimpleAnd ? Gia_ManDup( pNew0 ) : Gia_ManDupMuxes( pNew0, 2 ); + Gia_ManTransferTiming( pNew, pNew0 ); + if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); + if ( pNew0 != p ) Gia_ManStop( pNew0 ); + // perform the operation + pNew1 = Dam_ManAreaBalanceInt( pNew, vCiLevels, nNewNodesMax, fVerbose, fVeryVerbose ); + Gia_ManTransferTiming( pNew1, pNew ); + if ( fVerbose ) Gia_ManPrintStats( pNew1, NULL ); + Gia_ManStop( pNew ); + Vec_IntFreeP( &vCiLevels ); + // derive the final result + pNew2 = Gia_ManDupNoMuxes( pNew1, 0 ); + Gia_ManTransferTiming( pNew2, pNew1 ); + if ( fVerbose ) Gia_ManPrintStats( pNew2, NULL ); + Gia_ManStop( pNew1 ); + // normalize if needed + if ( !Gia_ManIsNormalized(pNew2) ) + { + pNew2 = Gia_ManDupNormalize( pNew1 = pNew2, 0 ); + Gia_ManTransferTiming( pNew2, pNew1 ); + Gia_ManStop( pNew1 ); + } + //Gia_ManTransferTiming( pNew2, p ); + return pNew2; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaBalLut.c b/yosys/abc/src/aig/gia/giaBalLut.c new file mode 100644 index 00000000000..c90910c9734 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaBalLut.c @@ -0,0 +1,982 @@ +/**CFile**************************************************************** + + FileName [giaBalance.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [AIG balancing.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaBalance.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/vec/vecHash.h" +#include "misc/vec/vecQue.h" +#include "opt/dau/dau.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define BAL_LEAF_MAX 6 +#define BAL_CUT_MAX 8 +#define BAL_SUPER 50 +#define BAL_NO_LEAF 31 +#define BAL_NO_FUNC 134217727 // (1<<27)-1 + +typedef struct Bal_Cut_t_ Bal_Cut_t; +struct Bal_Cut_t_ +{ + word Sign; // signature + int Delay; // delay + unsigned iFunc : 27; // function (BAL_NO_FUNC) + unsigned nLeaves : 5; // leaf number (Bal_NO_LEAF) + int pLeaves[BAL_LEAF_MAX]; // leaves +}; + +// operation manager +typedef struct Bal_Man_t_ Bal_Man_t; +struct Bal_Man_t_ +{ + Gia_Man_t * pGia; // user AIG + int nLutSize; // LUT size + int nCutNum; // cut number + int fCutMin; // cut minimization + int fVerbose; // verbose + Gia_Man_t * pNew; // derived AIG + Vec_Int_t * vCosts; // cost of supergate nodes + Vec_Ptr_t * vCutSets; // object cutsets + abctime clkStart; // starting the clock +}; + +static inline Bal_Man_t * Bal_GiaMan( Gia_Man_t * p ) { return (Bal_Man_t *)p->pData; } + +static inline int Bal_ObjCost( Bal_Man_t * p, int i ) { return Vec_IntEntry(p->vCosts, i); } +static inline int Bal_LitCost( Bal_Man_t * p, int i ) { return Bal_ObjCost(p, Abc_Lit2Var(i)); } +static inline int Bal_ObjDelay( Bal_Man_t * p, int i ) { return Bal_ObjCost(p, i) >> 4; } +static inline int Bal_LitDelay( Bal_Man_t * p, int i ) { return Bal_ObjDelay(p, Abc_Lit2Var(i)); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Bal_Man_t * Bal_ManAlloc( Gia_Man_t * pGia, Gia_Man_t * pNew, int nLutSize, int nCutNum, int fVerbose ) +{ + Bal_Man_t * p; + p = ABC_CALLOC( Bal_Man_t, 1 ); + p->clkStart = Abc_Clock(); + p->pGia = pGia; + p->pNew = pNew; + p->nLutSize = nLutSize; + p->nCutNum = nCutNum; + p->fVerbose = fVerbose; + p->vCosts = Vec_IntAlloc( 3 * Gia_ManObjNum(pGia) / 2 ); + p->vCutSets = Vec_PtrAlloc( 3 * Gia_ManObjNum(pGia) / 2 ); + Vec_IntFill( p->vCosts, Gia_ManObjNum(pNew), 0 ); + Vec_PtrFill( p->vCutSets, Gia_ManObjNum(pNew), NULL ); + pNew->pData = p; + return p; +} +void Bal_ManFree( Bal_Man_t * p ) +{ + Vec_PtrFreeFree( p->vCutSets ); + Vec_IntFree( p->vCosts ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Bal_CutCountBits( word i ) +{ + i = i - ((i >> 1) & 0x5555555555555555); + i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333); + i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F); + return (i*(0x0101010101010101))>>56; +} +static inline word Bal_CutGetSign( int * pLeaves, int nLeaves ) +{ + word Sign = 0; int i; + for ( i = 0; i < nLeaves; i++ ) + Sign |= ((word)1) << (pLeaves[i] & 0x3F); + return Sign; +} +static inline int Bal_CutCreateUnit( Bal_Cut_t * p, int i, int Delay ) +{ + p->iFunc = 2; + p->Delay = Delay; + p->nLeaves = 1; + p->pLeaves[0] = i; + p->Sign = ((word)1) << (i & 0x3F); + return 1; +} +static inline int Bal_ManPrepareSet( Bal_Man_t * p, int iObj, int Index, int fUnit, Bal_Cut_t ** ppCutSet ) +{ + static Bal_Cut_t CutTemp[3]; int i; + if ( Vec_PtrEntry(p->vCutSets, iObj) == NULL || fUnit ) + return Bal_CutCreateUnit( (*ppCutSet = CutTemp + Index), iObj, Bal_ObjDelay(p, iObj)+1 ); + *ppCutSet = (Bal_Cut_t *)Vec_PtrEntry(p->vCutSets, iObj); + for ( i = 0; i < p->nCutNum; i++ ) + if ( (*ppCutSet)[i].nLeaves == BAL_NO_LEAF ) + return i; + return i; +} + + +/**Function************************************************************* + + Synopsis [Check correctness of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Bal_CutCheck( Bal_Cut_t * pBase, Bal_Cut_t * pCut ) // check if pCut is contained in pBase +{ + int nSizeB = pBase->nLeaves; + int nSizeC = pCut->nLeaves; + int i, * pB = pBase->pLeaves; + int k, * pC = pCut->pLeaves; + for ( i = 0; i < nSizeC; i++ ) + { + for ( k = 0; k < nSizeB; k++ ) + if ( pC[i] == pB[k] ) + break; + if ( k == nSizeB ) + return 0; + } + return 1; +} +static inline int Bal_SetCheckArray( Bal_Cut_t ** ppCuts, int nCuts ) +{ + Bal_Cut_t * pCut0, * pCut1; + int i, k, m, n, Value; + assert( nCuts > 0 ); + for ( i = 0; i < nCuts; i++ ) + { + pCut0 = ppCuts[i]; + assert( pCut0->nLeaves <= BAL_LEAF_MAX ); + assert( pCut0->Sign == Bal_CutGetSign(pCut0->pLeaves, pCut0->nLeaves) ); + // check duplicates + for ( m = 0; m < (int)pCut0->nLeaves; m++ ) + for ( n = m + 1; n < (int)pCut0->nLeaves; n++ ) + assert( pCut0->pLeaves[m] < pCut0->pLeaves[n] ); + // check pairs + for ( k = 0; k < nCuts; k++ ) + { + pCut1 = ppCuts[k]; + if ( pCut0 == pCut1 ) + continue; + // check containments + Value = Bal_CutCheck( pCut0, pCut1 ); + assert( Value == 0 ); + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Bal_CutMergeOrder( Bal_Cut_t * pCut0, Bal_Cut_t * pCut1, Bal_Cut_t * pCut, int nLutSize ) +{ + int nSize0 = pCut0->nLeaves; + int nSize1 = pCut1->nLeaves; + int i, * pC0 = pCut0->pLeaves; + int k, * pC1 = pCut1->pLeaves; + int c, * pC = pCut->pLeaves; + // the case of the largest cut sizes + if ( nSize0 == nLutSize && nSize1 == nLutSize ) + { + for ( i = 0; i < nSize0; i++ ) + { + if ( pC0[i] != pC1[i] ) return 0; + pC[i] = pC0[i]; + } + pCut->nLeaves = nLutSize; + pCut->iFunc = BAL_NO_FUNC; + pCut->Sign = pCut0->Sign | pCut1->Sign; + pCut->Delay = Abc_MaxInt( pCut0->Delay, pCut1->Delay ); + return 1; + } + // compare two cuts with different numbers + i = k = c = 0; + while ( 1 ) + { + if ( c == nLutSize ) return 0; + if ( pC0[i] < pC1[k] ) + { + pC[c++] = pC0[i++]; + if ( i >= nSize0 ) goto FlushCut1; + } + else if ( pC0[i] > pC1[k] ) + { + pC[c++] = pC1[k++]; + if ( k >= nSize1 ) goto FlushCut0; + } + else + { + pC[c++] = pC0[i++]; k++; + if ( i >= nSize0 ) goto FlushCut1; + if ( k >= nSize1 ) goto FlushCut0; + } + } + +FlushCut0: + if ( c + nSize0 > nLutSize + i ) return 0; + while ( i < nSize0 ) + pC[c++] = pC0[i++]; + pCut->nLeaves = c; + pCut->iFunc = BAL_NO_FUNC; + pCut->Sign = pCut0->Sign | pCut1->Sign; + pCut->Delay = Abc_MaxInt( pCut0->Delay, pCut1->Delay ); + return 1; + +FlushCut1: + if ( c + nSize1 > nLutSize + k ) return 0; + while ( k < nSize1 ) + pC[c++] = pC1[k++]; + pCut->nLeaves = c; + pCut->iFunc = BAL_NO_FUNC; + pCut->Sign = pCut0->Sign | pCut1->Sign; + pCut->Delay = Abc_MaxInt( pCut0->Delay, pCut1->Delay ); + return 1; +} +static inline int Bal_CutMergeOrderMux( Bal_Cut_t * pCut0, Bal_Cut_t * pCut1, Bal_Cut_t * pCut2, Bal_Cut_t * pCut, int nLutSize ) +{ + int x0, i0 = 0, nSize0 = pCut0->nLeaves, * pC0 = pCut0->pLeaves; + int x1, i1 = 0, nSize1 = pCut1->nLeaves, * pC1 = pCut1->pLeaves; + int x2, i2 = 0, nSize2 = pCut2->nLeaves, * pC2 = pCut2->pLeaves; + int xMin, c = 0, * pC = pCut->pLeaves; + while ( 1 ) + { + x0 = (i0 == nSize0) ? ABC_INFINITY : pC0[i0]; + x1 = (i1 == nSize1) ? ABC_INFINITY : pC1[i1]; + x2 = (i2 == nSize2) ? ABC_INFINITY : pC2[i2]; + xMin = Abc_MinInt( Abc_MinInt(x0, x1), x2 ); + if ( xMin == ABC_INFINITY ) break; + if ( c == nLutSize ) return 0; + pC[c++] = xMin; + if (x0 == xMin) i0++; + if (x1 == xMin) i1++; + if (x2 == xMin) i2++; + } + pCut->nLeaves = c; + pCut->iFunc = BAL_NO_FUNC; + pCut->Sign = pCut0->Sign | pCut1->Sign | pCut2->Sign; + pCut->Delay = Abc_MaxInt( pCut0->Delay, Abc_MaxInt(pCut1->Delay, pCut2->Delay) ); + return 1; +} +static inline int Bal_SetCutIsContainedOrder( Bal_Cut_t * pBase, Bal_Cut_t * pCut ) // check if pCut is contained in pBase +{ + int i, nSizeB = pBase->nLeaves; + int k, nSizeC = pCut->nLeaves; + if ( nSizeB == nSizeC ) + { + for ( i = 0; i < nSizeB; i++ ) + if ( pBase->pLeaves[i] != pCut->pLeaves[i] ) + return 0; + return 1; + } + assert( nSizeB > nSizeC ); + if ( nSizeC == 0 ) + return 1; + for ( i = k = 0; i < nSizeB; i++ ) + { + if ( pBase->pLeaves[i] > pCut->pLeaves[k] ) + return 0; + if ( pBase->pLeaves[i] == pCut->pLeaves[k] ) + { + if ( ++k == nSizeC ) + return 1; + } + } + return 0; +} +static inline int Bal_SetLastCutIsContained( Bal_Cut_t ** pCuts, int nCuts ) +{ + int i; + for ( i = 0; i < nCuts; i++ ) + if ( pCuts[i]->nLeaves <= pCuts[nCuts]->nLeaves && (pCuts[i]->Sign & pCuts[nCuts]->Sign) == pCuts[i]->Sign && Bal_SetCutIsContainedOrder(pCuts[nCuts], pCuts[i]) ) + return 1; + return 0; +} +static inline int Bal_SetLastCutContains( Bal_Cut_t ** pCuts, int nCuts ) +{ + int i, k, fChanges = 0; + for ( i = 0; i < nCuts; i++ ) + if ( pCuts[nCuts]->nLeaves < pCuts[i]->nLeaves && (pCuts[nCuts]->Sign & pCuts[i]->Sign) == pCuts[nCuts]->Sign && Bal_SetCutIsContainedOrder(pCuts[i], pCuts[nCuts]) ) + pCuts[i]->nLeaves = BAL_NO_LEAF, fChanges = 1; + if ( !fChanges ) + return nCuts; + for ( i = k = 0; i <= nCuts; i++ ) + { + if ( pCuts[i]->nLeaves == BAL_NO_LEAF ) + continue; + if ( k < i ) + ABC_SWAP( Bal_Cut_t *, pCuts[k], pCuts[i] ); + k++; + } + return k - 1; +} +static inline int Bal_CutCompareArea( Bal_Cut_t * pCut0, Bal_Cut_t * pCut1 ) +{ + if ( pCut0->Delay < pCut1->Delay ) return -1; + if ( pCut0->Delay > pCut1->Delay ) return 1; + if ( pCut0->nLeaves < pCut1->nLeaves ) return -1; + if ( pCut0->nLeaves > pCut1->nLeaves ) return 1; + return 0; +} +static inline void Bal_SetSortByDelay( Bal_Cut_t ** pCuts, int nCuts ) +{ + int i; + for ( i = nCuts; i > 0; i-- ) + { + if ( Bal_CutCompareArea(pCuts[i - 1], pCuts[i]) < 0 )//!= 1 ) + return; + ABC_SWAP( Bal_Cut_t *, pCuts[i - 1], pCuts[i] ); + } +} +static inline int Bal_SetAddCut( Bal_Cut_t ** pCuts, int nCuts, int nCutNum ) +{ + if ( nCuts == 0 ) + return 1; + nCuts = Bal_SetLastCutContains(pCuts, nCuts); + Bal_SetSortByDelay( pCuts, nCuts ); + return Abc_MinInt( nCuts + 1, nCutNum - 1 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bal_ManDeriveCuts( Bal_Man_t * p, int iFan0, int iFan1, int iFan2, int fCompl0, int fCompl1, int fCompl2, int fUnit0, int fUnit1, int fUnit2, int fIsXor, int Target, int fSave ) +{ + Bal_Cut_t pCutSet[BAL_CUT_MAX], * pCutsR[BAL_CUT_MAX]; + Bal_Cut_t * pCutSet0, * pCutSet1, * pCutSet2; + int nCuts0 = Bal_ManPrepareSet( p, iFan0, 0, fUnit0, &pCutSet0 ); + int nCuts1 = Bal_ManPrepareSet( p, iFan1, 1, fUnit1, &pCutSet1 ); + Bal_Cut_t * pCut0, * pCut0Lim = pCutSet0 + nCuts0; + Bal_Cut_t * pCut1, * pCut1Lim = pCutSet1 + nCuts1; + int i, Cost, nCutsR = 0; + memset( pCutSet, 0, sizeof(Bal_Cut_t) * p->nCutNum ); + for ( i = 0; i < p->nCutNum; i++ ) + pCutsR[i] = pCutSet + i; + // enumerate cuts + if ( iFan2 > 0 ) + { + int nCuts2 = Bal_ManPrepareSet( p, iFan2, 2, fUnit2, &pCutSet2 ); + Bal_Cut_t * pCut2, * pCut2Lim = pCutSet2 + nCuts2; + for ( pCut0 = pCutSet0; pCut0 < pCut0Lim; pCut0++ ) + for ( pCut1 = pCutSet1; pCut1 < pCut1Lim; pCut1++ ) + for ( pCut2 = pCutSet2; pCut2 < pCut2Lim; pCut2++ ) + { + if ( Bal_CutCountBits(pCut0->Sign | pCut1->Sign | pCut2->Sign) > p->nLutSize ) + continue; + if ( !Bal_CutMergeOrderMux(pCut0, pCut1, pCut2, pCutsR[nCutsR], p->nLutSize) ) + continue; + assert( pCutsR[nCutsR]->Delay == Target ); + if ( Bal_SetLastCutIsContained(pCutsR, nCutsR) ) + continue; +// if ( p->fCutMin && Bal_CutComputeTruthMux(p, pCut0, pCut1, pCut2, fCompl0, fCompl1, fCompl2, pCutsR[nCutsR]) ) +// pCutsR[nCutsR]->Sign = Bal_CutGetSign(pCutsR[nCutsR]->pLeaves, pCutsR[nCutsR]->nLeaves); + nCutsR = Bal_SetAddCut( pCutsR, nCutsR, p->nCutNum ); + } + } + else + { + for ( pCut0 = pCutSet0; pCut0 < pCut0Lim; pCut0++ ) + for ( pCut1 = pCutSet1; pCut1 < pCut1Lim; pCut1++ ) + { + if ( Bal_CutCountBits(pCut0->Sign | pCut1->Sign) > p->nLutSize ) + continue; + if ( !Bal_CutMergeOrder(pCut0, pCut1, pCutsR[nCutsR], p->nLutSize) ) + continue; + assert( pCutsR[nCutsR]->Delay == Target ); + if ( Bal_SetLastCutIsContained(pCutsR, nCutsR) ) + continue; +// if ( p->fCutMin && Bal_CutComputeTruth(p, pCut0, pCut1, fCompl0, fCompl1, pCutsR[nCutsR], fIsXor) ) +// pCutsR[nCutsR]->Sign = Bal_CutGetSign(pCutsR[nCutsR]->pLeaves, pCutsR[nCutsR]->nLeaves); + nCutsR = Bal_SetAddCut( pCutsR, nCutsR, p->nCutNum ); + } + } + if ( nCutsR == 0 ) + return -1; +//printf( "%d ", nCutsR ); + Cost = ((pCutsR[0]->Delay << 4) | pCutsR[0]->nLeaves); + // verify + assert( nCutsR > 0 && nCutsR < p->nCutNum ); + assert( Bal_SetCheckArray(pCutsR, nCutsR) ); + // save cuts + if ( fSave && Cost >= 0 ) + { + pCutSet0 = ABC_CALLOC( Bal_Cut_t, p->nCutNum ); + Vec_PtrPush( p->vCutSets, pCutSet0 ); + assert( Vec_PtrSize(p->vCutSets) == Gia_ManObjNum(p->pNew) ); + for ( i = 0; i < nCutsR; i++ ) + pCutSet0[i] = *pCutsR[i]; + for ( ; i < p->nCutNum; i++ ) + pCutSet0[i].nLeaves = BAL_NO_LEAF; + Vec_IntPush( p->vCosts, Cost ); + assert( Vec_IntSize(p->vCosts) == Gia_ManObjNum(p->pNew) ); + } + return Cost; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bal_ManSetGateLevel( Bal_Man_t * p, Gia_Obj_t * pObjOld, int iLitNew ) +{ + int iFan0, iFan1, iFan2, Cost; + int fCompl0, fCompl1, fCompl2; + int fUnit0, fUnit1, fUnit2; + int Delay0, Delay1, Delay2, DelayMax; + int iObjNew = Abc_Lit2Var(iLitNew); + Gia_Obj_t * pObjNew = Gia_ManObj( p->pNew, iObjNew ); + int fMux = Gia_ObjIsMux(p->pNew, pObjNew); + if ( iObjNew < Vec_PtrSize(p->vCutSets) ) + return -1; + iFan0 = Gia_ObjFaninId0( pObjNew, iObjNew ); + iFan1 = Gia_ObjFaninId1( pObjNew, iObjNew ); + iFan2 = fMux ? Gia_ObjFaninId2(p->pNew, iObjNew) : 0; + fCompl0 = Gia_ObjFaninC0( pObjNew ); + fCompl1 = Gia_ObjFaninC1( pObjNew ); + fCompl2 = fMux ? Gia_ObjFaninC2(p->pNew, pObjNew) : 0; + Delay0 = Bal_ObjDelay( p, iFan0 ); + Delay1 = Bal_ObjDelay( p, iFan1 ); + Delay2 = Bal_ObjDelay( p, iFan2 ); + DelayMax = Abc_MaxInt( Delay0, Abc_MaxInt(Delay1, Delay2) ); + fUnit0 = (int)(Delay0 != DelayMax); + fUnit1 = (int)(Delay1 != DelayMax); + fUnit2 = (int)(Delay2 != DelayMax); + if ( DelayMax > 0 ) + { +//printf( "A" ); + Cost = Bal_ManDeriveCuts(p, iFan0, iFan1, iFan2, fCompl0, fCompl1, fCompl2, fUnit0, fUnit1, fUnit2, Gia_ObjIsXor(pObjNew), DelayMax, 1 ); +//printf( "B" ); + if ( Cost >= 0 ) + return Cost; + } + DelayMax++; + fUnit0 = fUnit1 = fUnit2 = 1; +//printf( "A" ); + Cost = Bal_ManDeriveCuts(p, iFan0, iFan1, iFan2, fCompl0, fCompl1, fCompl2, fUnit0, fUnit1, fUnit2, Gia_ObjIsXor(pObjNew), DelayMax, 1 ); +//printf( "B" ); + assert( Cost >= 0 ); + return Cost; +} +int Bal_ManEvalTwo( Bal_Man_t * p, int iLitNew0, int iLitNew1, int iLitNew2, int fIsXor ) +{ + int iFan0 = Abc_Lit2Var( iLitNew0 ); + int iFan1 = Abc_Lit2Var( iLitNew1 ); + int iFan2 = Abc_Lit2Var( iLitNew2 ); + int fCompl0 = Abc_LitIsCompl( iLitNew0 ); + int fCompl1 = Abc_LitIsCompl( iLitNew1 ); + int fCompl2 = Abc_LitIsCompl( iLitNew2 ); + int Delay0 = Bal_ObjDelay( p, iFan0 ); + int Delay1 = Bal_ObjDelay( p, iFan1 ); + int Delay2 = Bal_ObjDelay( p, iFan2 ); + int DelayMax = Abc_MaxInt( Delay0, Abc_MaxInt(Delay1, Delay2) ); + int fUnit0 = (int)(Delay0 != DelayMax); + int fUnit1 = (int)(Delay1 != DelayMax); + int fUnit2 = (int)(Delay2 != DelayMax); + if ( DelayMax == 0 ) + return -1; + return Bal_ManDeriveCuts(p, iFan0, iFan1, iFan2, fCompl0, fCompl1, fCompl2, fUnit0, fUnit1, fUnit2, fIsXor, DelayMax, 0 ); +} + +/**Function************************************************************* + + Synopsis [Sort literals by their cost.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntSelectSortCostLit( Vec_Int_t * vSuper, Vec_Int_t * vCosts ) +{ + int * pArray = Vec_IntArray(vSuper); + int nSize = Vec_IntSize(vSuper); + int i, j, best_i; + for ( i = 0; i < nSize-1; i++ ) + { + best_i = i; + for ( j = i+1; j < nSize; j++ ) + if ( Vec_IntEntry(vCosts, Abc_Lit2Var(pArray[j])) > Vec_IntEntry(vCosts, Abc_Lit2Var(pArray[best_i])) ) + best_i = j; + ABC_SWAP( int, pArray[i], pArray[best_i] ); + } +} +static inline void Vec_IntPushOrderCost2( Vec_Int_t * vSuper, Vec_Int_t * vCosts, int iLit ) +{ + int i, nSize, * pArray; + Vec_IntPush( vSuper, iLit ); + pArray = Vec_IntArray(vSuper); + nSize = Vec_IntSize(vSuper); + for ( i = nSize-1; i > 0; i-- ) + { + if ( Vec_IntEntry(vCosts, Abc_Lit2Var(pArray[i])) <= Vec_IntEntry(vCosts, Abc_Lit2Var(pArray[i - 1])) ) + return; + ABC_SWAP( int, pArray[i], pArray[i - 1] ); + } +} +static inline int Vec_IntFindFirstSameDelayAsLast( Bal_Man_t * p, Vec_Int_t * vSuper ) +{ + int i, DelayCur, Delay = Bal_LitDelay( p, Vec_IntEntryLast(vSuper) ); + assert( Vec_IntSize(vSuper) > 1 ); + for ( i = Vec_IntSize(vSuper)-1; i > 0; i-- ) + { + DelayCur = Bal_LitDelay( p, Vec_IntEntry(vSuper, i-1) ); + assert( DelayCur >= Delay ); + if ( DelayCur > Delay ) + return i; + } + return i; +} + + +/**Function************************************************************* + + Synopsis [Select the best pair to merge.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Bal_ManFindBestPair( Bal_Man_t * p, Vec_Int_t * vSuper, Gia_Obj_t * pObj ) +{ + int * pSuper = Vec_IntArray(vSuper); + int iBeg = Vec_IntFindFirstSameDelayAsLast( p, vSuper ); + int iEnd = Vec_IntSize(vSuper)-1; + int i, k, iBest = -1, kBest = -1, BestCost = ABC_INFINITY, Cost; + assert( iBeg <= iEnd ); + // check if we can add to the higher levels without increasing cost + for ( k = iBeg-1; k >= 0; k-- ) + for ( i = iEnd; i >= iBeg; i-- ) + { + Cost = Bal_ManEvalTwo( p, pSuper[i], pSuper[k], 0, Gia_ObjIsXor(pObj) ); + if ( Cost == -1 ) + continue; + if ( Cost == Bal_LitCost(p, pSuper[k]) ) + { +// printf( "A" ); + return (k << 16)|i; + } + if ( BestCost > Cost ) + BestCost = Cost, iBest = i, kBest = k; + } + if ( BestCost != ABC_INFINITY && (BestCost >> 4) == Bal_LitDelay(p, pSuper[kBest]) ) + { +// printf( "B" ); + return (kBest << 16)|iBest; + } + // check if some can be added to lowest level without increasing cost + BestCost = ABC_INFINITY; + for ( i = iBeg; i <= iEnd; i++ ) + for ( k = i+1; k <= iEnd; k++ ) + { + Cost = Bal_ManEvalTwo( p, pSuper[i], pSuper[k], 0, Gia_ObjIsXor(pObj) ); + if ( Cost == -1 ) + continue; + if ( Cost == Abc_MaxInt(Bal_LitCost(p, pSuper[i]), Bal_LitCost(p, pSuper[k])) ) + { +// printf( "C" ); + return (k << 16)|i; + } + if ( BestCost > Cost ) + BestCost = Cost, iBest = i, kBest = k; + } + if ( BestCost != ABC_INFINITY ) + { +// printf( "D" ); + return (kBest << 16)|iBest; + } +// printf( "E" ); + // group pairs from lowest level based on proximity + return (iEnd << 16)|(iEnd-1); +} + +/**Function************************************************************* + + Synopsis [Simplify multi-input AND/XOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSimplifyXor( Vec_Int_t * vSuper ) +{ + int i, k = 0, Prev = -1, This, fCompl = 0; + Vec_IntForEachEntry( vSuper, This, i ) + { + if ( This == 0 ) + continue; + if ( This == 1 ) + fCompl ^= 1; + else if ( Prev != This ) + Vec_IntWriteEntry( vSuper, k++, This ), Prev = This; + else + Prev = -1, k--; + } + Vec_IntShrink( vSuper, k ); + if ( Vec_IntSize( vSuper ) == 0 ) + Vec_IntPush( vSuper, fCompl ); + else if ( fCompl ) + Vec_IntWriteEntry( vSuper, 0, Abc_LitNot(Vec_IntEntry(vSuper, 0)) ); +} +static inline void Gia_ManSimplifyAnd( Vec_Int_t * vSuper ) +{ + int i, k = 0, Prev = -1, This; + Vec_IntForEachEntry( vSuper, This, i ) + { + if ( This == 0 ) + { Vec_IntFill(vSuper, 1, 0); return; } + if ( This == 1 ) + continue; + if ( Prev == -1 || Abc_Lit2Var(Prev) != Abc_Lit2Var(This) ) + Vec_IntWriteEntry( vSuper, k++, This ), Prev = This; + else if ( Prev != This ) + { Vec_IntFill(vSuper, 1, 0); return; } + } + Vec_IntShrink( vSuper, k ); + if ( Vec_IntSize( vSuper ) == 0 ) + Vec_IntPush( vSuper, 1 ); +} + +/**Function************************************************************* + + Synopsis [Collect multi-input AND/XOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSuperCollectXor_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + assert( !Gia_IsComplement(pObj) ); + if ( !Gia_ObjIsXor(pObj) || +// Gia_ObjRefNum(p, pObj) > 1 || + Gia_ObjRefNum(p, pObj) > 3 || +// (Gia_ObjRefNum(p, pObj) == 2 && (Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) == 1 || Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) == 1)) || + Vec_IntSize(p->vSuper) > BAL_SUPER ) + { + Vec_IntPush( p->vSuper, Gia_ObjToLit(p, pObj) ); + return; + } + assert( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ); + Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin1(pObj) ); +} +static inline void Gia_ManSuperCollectAnd_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( Gia_IsComplement(pObj) || + !Gia_ObjIsAndReal(p, pObj) || +// Gia_ObjRefNum(p, pObj) > 1 || + Gia_ObjRefNum(p, pObj) > 3 || +// (Gia_ObjRefNum(p, pObj) == 2 && (Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) == 1 || Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) == 1)) || + Vec_IntSize(p->vSuper) > BAL_SUPER ) + { + Vec_IntPush( p->vSuper, Gia_ObjToLit(p, pObj) ); + return; + } + Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild0(pObj) ); + Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild1(pObj) ); +} +static inline void Gia_ManSuperCollect( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ +// int nSize; + if ( p->vSuper == NULL ) + p->vSuper = Vec_IntAlloc( 1000 ); + else + Vec_IntClear( p->vSuper ); + if ( Gia_ObjIsXor(pObj) ) + { + assert( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ); + Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin1(pObj) ); +// nSize = Vec_IntSize(vSuper); + Vec_IntSort( p->vSuper, 0 ); + Gia_ManSimplifyXor( p->vSuper ); +// if ( nSize != Vec_IntSize(vSuper) ) +// printf( "X %d->%d ", nSize, Vec_IntSize(vSuper) ); + } + else if ( Gia_ObjIsAndReal(p, pObj) ) + { + Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild0(pObj) ); + Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild1(pObj) ); +// nSize = Vec_IntSize(vSuper); + Vec_IntSort( p->vSuper, 0 ); + Gia_ManSimplifyAnd( p->vSuper ); +// if ( nSize != Vec_IntSize(vSuper) ) +// printf( "A %d->%d ", nSize, Vec_IntSize(vSuper) ); + } + else assert( 0 ); +// if ( nSize > 10 ) +// printf( "%d ", nSize ); + assert( Vec_IntSize(p->vSuper) > 0 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManCreateGate( Gia_Man_t * pNew, Gia_Obj_t * pObj, Vec_Int_t * vSuper ) +{ + int iLit0 = Vec_IntPop(vSuper); + int iLit1 = Vec_IntPop(vSuper); + int iLit, i; + if ( !Gia_ObjIsXor(pObj) ) + iLit = Gia_ManHashAnd( pNew, iLit0, iLit1 ); + else if ( pNew->pMuxes ) + iLit = Gia_ManHashXorReal( pNew, iLit0, iLit1 ); + else + iLit = Gia_ManHashXor( pNew, iLit0, iLit1 ); + Vec_IntPush( vSuper, iLit ); + Bal_ManSetGateLevel( Bal_GiaMan(pNew), pObj, iLit ); +// Gia_ObjSetGateLevel( pNew, Gia_ManObj(pNew, Abc_Lit2Var(iLit)) ); + // shift to the corrent location + for ( i = Vec_IntSize(vSuper)-1; i > 0; i-- ) + { + int iLit1 = Vec_IntEntry(vSuper, i); + int iLit2 = Vec_IntEntry(vSuper, i-1); + if ( Gia_ObjLevelId(pNew, Abc_Lit2Var(iLit1)) <= Gia_ObjLevelId(pNew, Abc_Lit2Var(iLit2)) ) + break; + Vec_IntWriteEntry( vSuper, i, iLit2 ); + Vec_IntWriteEntry( vSuper, i-1, iLit1 ); + } +} +static inline int Gia_ManBalanceGate( Gia_Man_t * pNew, Gia_Obj_t * pObj, Vec_Int_t * vSuper, int * pLits, int nLits ) +{ + Vec_IntClear( vSuper ); + if ( nLits == 1 ) + Vec_IntPush( vSuper, pLits[0] ); + else if ( nLits == 2 ) + { + Vec_IntPush( vSuper, pLits[0] ); + Vec_IntPush( vSuper, pLits[1] ); + Gia_ManCreateGate( pNew, pObj, vSuper ); + } + else if ( nLits > 2 ) + { + Bal_Man_t * p = Bal_GiaMan(pNew); int i; + for ( i = 0; i < nLits; i++ ) + Vec_IntPush( vSuper, pLits[i] ); + // sort by level/cut-size + Vec_IntSelectSortCostLit( vSuper, p->vCosts ); + // iterate till everything is grouped + while ( Vec_IntSize(vSuper) > 1 ) + { + int iLit, Res = Bal_ManFindBestPair( p, vSuper, pObj ); + int iBest = Vec_IntEntry( vSuper, Res >> 16 ); + int kBest = Vec_IntEntry( vSuper, Res & 0xFFFF ); + Vec_IntRemove( vSuper, iBest ); + Vec_IntRemove( vSuper, kBest ); + if ( Gia_ObjIsXor(pObj) ) + iLit = Gia_ManHashXorReal( pNew, iBest, kBest ); + else + iLit = Gia_ManHashAnd( pNew, iBest, kBest ); + Bal_ManSetGateLevel( p, pObj, iLit ); + Vec_IntPushOrderCost2( vSuper, p->vCosts, iLit ); + } + } + // consider trivial case + assert( Vec_IntSize(vSuper) == 1 ); + return Vec_IntEntry(vSuper, 0); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManBalance_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + int i, iLit, iBeg, iEnd; + if ( ~pObj->Value ) + return; + assert( Gia_ObjIsAnd(pObj) ); + // handle MUX + if ( Gia_ObjIsMux(p, pObj) ) + { + Gia_ManBalance_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManBalance_rec( pNew, p, Gia_ObjFanin1(pObj) ); + Gia_ManBalance_rec( pNew, p, Gia_ObjFanin2(p, pObj) ); + pObj->Value = Gia_ManHashMuxReal( pNew, Gia_ObjFanin2Copy(p, pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin0Copy(pObj) ); + Bal_ManSetGateLevel( Bal_GiaMan(pNew), pObj, pObj->Value ); +// Gia_ObjSetGateLevel( pNew, Gia_ManObj(pNew, Abc_Lit2Var(pObj->Value)) ); + return; + } + // find supergate + Gia_ManSuperCollect( p, pObj ); + // save entries + if ( p->vStore == NULL ) + p->vStore = Vec_IntAlloc( 1000 ); + iBeg = Vec_IntSize( p->vStore ); + Vec_IntAppend( p->vStore, p->vSuper ); + iEnd = Vec_IntSize( p->vStore ); + // call recursively + Vec_IntForEachEntryStartStop( p->vStore, iLit, i, iBeg, iEnd ) + { + Gia_Obj_t * pTemp = Gia_ManObj( p, Abc_Lit2Var(iLit) ); + Gia_ManBalance_rec( pNew, p, pTemp ); + Vec_IntWriteEntry( p->vStore, i, Abc_LitNotCond(pTemp->Value, Abc_LitIsCompl(iLit)) ); + } + assert( Vec_IntSize(p->vStore) == iEnd ); + // consider general case + pObj->Value = Gia_ManBalanceGate( pNew, pObj, p->vSuper, Vec_IntEntryP(p->vStore, iBeg), iEnd-iBeg ); + Vec_IntShrink( p->vStore, iBeg ); +} +static inline Gia_Man_t * Gia_ManBalanceInt( Gia_Man_t * p, int nLutSize, int nCutNum, int fVerbose ) +{ + Bal_Man_t * pMan; + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i; + Gia_ManFillValue( p ); + Gia_ManCreateRefs( p ); + // start the new manager + pNew = Gia_ManStart( 3*Gia_ManObjNum(p)/2 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc ); + pNew->vLevels = Vec_IntStart( pNew->nObjsAlloc ); + // create constant and inputs + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + // create balancing manager + pMan = Bal_ManAlloc( p, pNew, nLutSize, nCutNum, fVerbose ); + // create internal nodes + Gia_ManHashStart( pNew ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManBalance_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); +// if ( fVerbose ) + { + int nLevelMax = 0; + Gia_ManForEachCo( pNew, pObj, i ) + { + nLevelMax = Abc_MaxInt( nLevelMax, Bal_ObjDelay(pMan, Gia_ObjFaninId0p(pNew, pObj)) ); +// printf( "%d=%d ", i, Bal_ObjDelay(pMan, Gia_ObjFaninId0p(pNew, pObj)) ); + } + printf( "Best delay = %d\n", nLevelMax ); + } + +// assert( Gia_ManObjNum(pNew) <= Gia_ManObjNum(p) ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + // delete manager + Bal_ManFree( pMan ); + // perform cleanup + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} +Gia_Man_t * Gia_ManBalanceLut( Gia_Man_t * p, int nLutSize, int nCutNum, int fVerbose ) +{ + Gia_Man_t * pNew, * pNew1, * pNew2; + if ( fVerbose ) Gia_ManPrintStats( p, NULL ); + pNew = Gia_ManDupMuxes( p, 2 ); + if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); + pNew1 = Gia_ManBalanceInt( pNew, nLutSize, nCutNum, fVerbose ); + if ( fVerbose ) Gia_ManPrintStats( pNew1, NULL ); + Gia_ManStop( pNew ); + pNew2 = Gia_ManDupNoMuxes( pNew1, 0 ); + if ( fVerbose ) Gia_ManPrintStats( pNew2, NULL ); + Gia_ManStop( pNew1 ); + return pNew2; +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaBalMap.c b/yosys/abc/src/aig/gia/giaBalMap.c new file mode 100644 index 00000000000..b285daea179 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaBalMap.c @@ -0,0 +1,326 @@ +/**CFile**************************************************************** + + FileName [giaSopb.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [SOP balancing for a window.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSopb.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManHighlight_rec( Gia_Man_t * p, int iObj ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return; + Gia_ObjSetTravIdCurrentId(p, iObj); + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsAnd(pObj) ) + Gia_ManHighlight_rec( p, Gia_ObjFaninId0(pObj, iObj) ); + if ( Gia_ObjIsAnd(pObj) ) + Gia_ManHighlight_rec( p, Gia_ObjFaninId1(pObj, iObj) ); +} +void Gia_ManPrepareWin( Gia_Man_t * p, Vec_Int_t * vOuts, Vec_Int_t ** pvPis, Vec_Int_t ** pvPos, Vec_Int_t ** pvAnds, int fPoOnly ) +{ + Gia_Obj_t * pObj; + int i; + // mark the section + Gia_ManIncrementTravId( p ); + Gia_ManForEachCoVec( vOuts, p, pObj, i ) + Gia_ManHighlight_rec( p, Gia_ObjFaninId0p(p, pObj) ); + // mark fanins of the outside area + Gia_ManCleanMark0( p ); + if ( fPoOnly ) + { + Gia_ManForEachCoVec( vOuts, p, pObj, i ) + Gia_ObjFanin0(pObj)->fMark0 = 1; + } + else + { + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + continue; + if ( Gia_ObjIsAnd(pObj) && !Gia_ObjIsTravIdCurrentId(p, i) ) + continue; + Gia_ObjFanin0(pObj)->fMark0 = 1; + if ( Gia_ObjIsAnd(pObj) ) + Gia_ObjFanin1(pObj)->fMark0 = 1; + } + } + // collect pointed nodes + *pvPis = Vec_IntAlloc( 1000 ); + *pvPos = Vec_IntAlloc( 1000 ); + *pvAnds = Vec_IntAlloc( 1000 ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( !Gia_ObjIsTravIdCurrentId(p, i) ) + continue; + if ( Gia_ObjIsCi(pObj) ) + Vec_IntPush( *pvPis, i ); + else if ( pObj->fMark0 ) + Vec_IntPush( *pvPos, i ); + if ( Gia_ObjIsAnd(pObj) ) + Vec_IntPush( *pvAnds, i ); + } + Gia_ManCleanMark0( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManExtractWin( Gia_Man_t * p, Vec_Int_t * vOuts, int fPoOnly ) +{ + Vec_Int_t * vPis, * vPos, * vAnds; + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + Gia_ManPrepareWin( p, vOuts, &vPis, &vPos, &vAnds, fPoOnly ); + // create AIG + pNew = Gia_ManStart( Vec_IntSize(vPis) + Vec_IntSize(vPos) + Vec_IntSize(vAnds) + 1 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObjVec( vPis, p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachObjVec( vAnds, p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachObjVec( vPos, p, pObj, i ) + Gia_ManAppendCo( pNew, pObj->Value ); + Vec_IntFree( vPis ); + Vec_IntFree( vPos ); + Vec_IntFree( vAnds ); + return pNew; +} +Gia_Man_t * Gia_ManInsertWin( Gia_Man_t * p, Vec_Int_t * vOuts, Gia_Man_t * pWin ) +{ + Vec_Int_t * vPos, * vPis, * vAnds; + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i; + Gia_ManPrepareWin( p, vOuts, &vPis, &vPos, &vAnds, 0 ); + // create AIG + pNew = Gia_ManStart( Gia_ManObjNum(p) - Vec_IntSize(vAnds) + Gia_ManAndNum(pWin) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + // inputs + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManConst0(pWin)->Value = 0; + Gia_ManForEachCi( pWin, pObj, i ) + pObj->Value = Gia_ManObj(p, Vec_IntEntry(vPis, i))->Value; + // internal nodes + Gia_ManHashAlloc( pNew ); + Gia_ManForEachAnd( pWin, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( pWin, pObj, i ) + Gia_ManObj( p, Vec_IntEntry(vPos, i) )->Value = Gia_ObjFanin0Copy(pObj); + Gia_ManForEachAnd( p, pObj, i ) + if ( !Gia_ObjIsTravIdCurrentId(p, i) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManHashStop( pNew ); + // cleanup + Vec_IntFree( vPis ); + Vec_IntFree( vPos ); + Vec_IntFree( vAnds ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManFindLatest( Gia_Man_t * p, int LevelMax, int nTimeWindow ) +{ + Gia_Obj_t * pObj; + Vec_Int_t * vOuts; + vOuts = Vec_IntAlloc( 1000 ); + if ( Gia_ManHasMapping(p) ) + { + int i, k, iFan, nLevels = 0; + int * pLevels = ABC_CALLOC( int, Gia_ManObjNum(p) ); + Gia_ManForEachLut( p, i ) + { + Gia_LutForEachFanin( p, i, iFan, k ) + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[iFan] ); + pLevels[i]++; + nLevels = Abc_MaxInt( nLevels, pLevels[i] ); + } + if ( nTimeWindow ) + LevelMax = (int)((1.0 - 0.01 * nTimeWindow) * nLevels); + if ( nLevels < LevelMax ) + printf( "The maximum mapped level (%d) is less than the target level (%d).\n", nLevels, LevelMax ); + Gia_ManForEachCo( p, pObj, i ) + if ( pLevels[Gia_ObjFaninId0p(p, pObj)] >= LevelMax ) + Vec_IntPush( vOuts, i ); + ABC_FREE( pLevels ); + } + else + { + int i, nLevels = Gia_ManLevelNum( p ); + if ( nTimeWindow ) + LevelMax = (int)((1.0 - 0.01 * nTimeWindow) * nLevels); + if ( nLevels < LevelMax ) + printf( "The maximum AIG level (%d) is less than the target level (%d).\n", nLevels, LevelMax ); + Gia_ManForEachCo( p, pObj, i ) + if ( Gia_ObjLevel(p, pObj) >= LevelMax ) + Vec_IntPush( vOuts, i ); + } + return vOuts; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManExtractWindow( Gia_Man_t * p, int LevelMax, int nTimeWindow, int fVerbose ) +{ + Vec_Int_t * vOuts; + Gia_Man_t * pWin; + assert( !LevelMax != !nTimeWindow ); + vOuts = Gia_ManFindLatest( p, LevelMax, nTimeWindow ); + if ( fVerbose ) + printf( "Collected %d outputs to extract.\n", Vec_IntSize(vOuts) ); + if ( Vec_IntSize(vOuts) == 0 ) + { + Vec_IntFree( vOuts ); + return Gia_ManDup( p ); + } + pWin = Gia_ManExtractWin( p, vOuts, 1 ); + Vec_IntFree( vOuts ); + return pWin; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManPerformSopBalanceWin( Gia_Man_t * p, int LevelMax, int nTimeWindow, int nCutNum, int nRelaxRatio, int fVerbose ) +{ + Vec_Int_t * vOuts; + Gia_Man_t * pNew, * pWin, * pWinNew; + assert( !LevelMax != !nTimeWindow ); + vOuts = Gia_ManFindLatest( p, LevelMax, nTimeWindow ); + if ( fVerbose ) + printf( "Collected %d outputs to extract.\n", Vec_IntSize(vOuts) ); + if ( Vec_IntSize(vOuts) == 0 ) + { + Vec_IntFree( vOuts ); + return Gia_ManDup( p ); + } + pWin = Gia_ManExtractWin( p, vOuts, 0 ); + pWinNew = Gia_ManPerformSopBalance( pWin, nCutNum, nRelaxRatio, fVerbose ); + Gia_ManStop( pWin ); + pNew = Gia_ManInsertWin( p, vOuts, pWinNew ); + Gia_ManStop( pWinNew ); + Vec_IntFree( vOuts ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManPerformDsdBalanceWin( Gia_Man_t * p, int LevelMax, int nTimeWindow, int nLutSize, int nCutNum, int nRelaxRatio, int fVerbose ) +{ + Vec_Int_t * vOuts; + Gia_Man_t * pNew, * pWin, * pWinNew; + assert( !LevelMax != !nTimeWindow ); + vOuts = Gia_ManFindLatest( p, LevelMax, nTimeWindow ); + if ( fVerbose ) + printf( "Collected %d outputs to extract.\n", Vec_IntSize(vOuts) ); + if ( Vec_IntSize(vOuts) == 0 ) + { + Vec_IntFree( vOuts ); + return Gia_ManDup( p ); + } + pWin = Gia_ManExtractWin( p, vOuts, 0 ); + pWinNew = Gia_ManPerformDsdBalance( pWin, nLutSize, nCutNum, nRelaxRatio, fVerbose ); + Gia_ManStop( pWin ); + pNew = Gia_ManInsertWin( p, vOuts, pWinNew ); + Gia_ManStop( pWinNew ); + Vec_IntFree( vOuts ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaBidec.c b/yosys/abc/src/aig/gia/giaBidec.c new file mode 100644 index 00000000000..4c807cdebc1 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaBidec.c @@ -0,0 +1,305 @@ +/**CFile**************************************************************** + + FileName [giaBidec.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Application of bi-decomposition to AIG minimization.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaBidec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "bool/bdc/bdc.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes truth table of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Gia_ManConvertAigToTruth_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vTruth, int nWords, Vec_Int_t * vVisited ) +{ + unsigned * pTruth, * pTruth0, * pTruth1; + int i; + assert( !Gia_IsComplement(pObj) ); + if ( Vec_IntGetEntry(p->vTruths, Gia_ObjId(p, pObj)) != -1 ) + return (unsigned *)Vec_IntEntryP( vTruth, nWords * Vec_IntGetEntry(p->vTruths, Gia_ObjId(p, pObj)) ); + // compute the truth tables of the fanins + pTruth0 = Gia_ManConvertAigToTruth_rec( p, Gia_ObjFanin0(pObj), vTruth, nWords, vVisited ); + pTruth1 = Gia_ManConvertAigToTruth_rec( p, Gia_ObjFanin1(pObj), vTruth, nWords, vVisited ); + // get room for the truth table + pTruth = Vec_IntFetch( vTruth, nWords ); + // create the truth table of the node + if ( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] & pTruth1[i]; + else if ( !Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] & ~pTruth1[i]; + else if ( Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ~pTruth0[i] & pTruth1[i]; + else // if ( Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ~pTruth0[i] & ~pTruth1[i]; + // save the visited node + Vec_IntSetEntry( p->vTruths, Gia_ObjId(p, pObj), Vec_IntSize(vVisited) ); + Vec_IntPush( vVisited, Gia_ObjId(p, pObj) ); + return pTruth; +} + +/**Function************************************************************* + + Synopsis [Computes truth table of the node.] + + Description [Assumes that the structural support is no more than 8 inputs. + Uses array vTruth to store temporary truth tables. The returned pointer should + be used immediately.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Gia_ManConvertAigToTruth( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vTruth, Vec_Int_t * vVisited ) +{ + static unsigned uTruths[8][8] = { // elementary truth tables + { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA }, + { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC }, + { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 }, + { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 }, + { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, + { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, + { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, + { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } + }; + Gia_Obj_t * pObj; + Vec_Ptr_t * vTtElems = NULL; + unsigned * pTruth;//, * pTruth2; + int i, nWords, nVars; + // get the number of variables and words + nVars = Vec_IntSize( vLeaves ); + nWords = Abc_TruthWordNum( nVars ); + // check the case of a constant + if ( Gia_ObjIsConst0( Gia_Regular(pRoot) ) ) + { + Vec_IntClear( vTruth ); + // get room for the truth table + pTruth = Vec_IntFetch( vTruth, nWords ); + if ( !Gia_IsComplement(pRoot) ) + Gia_ManTruthClear( pTruth, nVars ); + else + Gia_ManTruthFill( pTruth, nVars ); + return pTruth; + } + // if the number of variables is more than 8, allocate truth tables + if ( nVars > 8 ) + vTtElems = Vec_PtrAllocTruthTables( nVars ); + // assign elementary truth tables + Vec_IntClear( vTruth ); + Vec_IntClear( vVisited ); + Gia_ManForEachObjVec( vLeaves, p, pObj, i ) + { + // get room for the truth table + pTruth = Vec_IntFetch( vTruth, nWords ); + // assign elementary variable + if ( vTtElems ) + Gia_ManTruthCopy( pTruth, (unsigned *)Vec_PtrEntry(vTtElems, i), nVars ); + else + Gia_ManTruthCopy( pTruth, uTruths[i], nVars ); + // save the visited node + Vec_IntSetEntry( p->vTruths, Gia_ObjId(p, pObj), Vec_IntSize(vVisited) ); + Vec_IntPush( vVisited, Gia_ObjId(p, pObj) ); + } + if ( vTtElems ) + Vec_PtrFree( vTtElems ); + // clear the marks and compute the truth table +// pTruth2 = Gia_ManConvertAigToTruth_rec( p, Gia_Regular(pRoot), vTruth, nWords, vVisited ); + pTruth = Gia_ManConvertAigToTruth_rec( p, Gia_Regular(pRoot), vTruth, nWords, vVisited ); + // copy the result +// Gia_ManTruthCopy( pTruth, pTruth2, nVars ); + if ( Gia_IsComplement(pRoot) ) + Gia_ManTruthNot( pTruth, pTruth, nVars ); + // clean truth tables + Gia_ManForEachObjVec( vVisited, p, pObj, i ) + Vec_IntSetEntry( p->vTruths, Gia_ObjId(p, pObj), -1 ); + return pTruth; +} + +/**Function************************************************************* + + Synopsis [Resynthesizes nodes using bi-decomposition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ObjPerformBidec( Bdc_Man_t * pManDec, + Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pRoot, + Vec_Int_t * vLeaves, Vec_Int_t * vTruth, Vec_Int_t * vVisited ) +{ + unsigned * pTruth; + Bdc_Fun_t * pFunc; + Gia_Obj_t * pFanin; + int i, iFan, nVars, nNodes; + // collect leaves of this gate + Vec_IntClear( vLeaves ); + Gia_LutForEachFanin( p, Gia_ObjId(p, pRoot), iFan, i ) + Vec_IntPush( vLeaves, iFan ); + nVars = Vec_IntSize( vLeaves ); + assert( nVars < 16 ); + // derive truth table + pTruth = Gia_ManConvertAigToTruth( p, pRoot, vLeaves, vTruth, vVisited ); +//Extra_PrintBinary( stdout, pTruth, (1<nVarsMax = Gia_ManLutSizeMax( p ); + pPars->fVerbose = fVerbose; + if ( pPars->nVarsMax < 2 ) + { + printf( "Resynthesis is not performed when nodes have less than 2 inputs.\n" ); + return NULL; + } + if ( pPars->nVarsMax > 15 ) + { + printf( "Resynthesis is not performed when nodes have more than 15 inputs.\n" ); + return NULL; + } + vLeaves = Vec_IntAlloc( 0 ); + vTruth = Vec_IntAlloc( (1<<16) ); + vVisited = Vec_IntAlloc( 0 ); + // clean the old manager + Gia_ManCleanTruth( p ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + // start the new manager + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); +// Gia_ManCleanLevels( pNew, Gia_ManObjNum(p) ); + pManDec = Bdc_ManAlloc( pPars ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) // transfer the CI level (is it needed?) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsLut(p, i) ) + pObj->Value = Gia_ObjPerformBidec( pManDec, pNew, p, pObj, vLeaves, vTruth, vVisited ); + } + Bdc_ManFree( pManDec ); + // cleanup the AIG + Gia_ManHashStop( pNew ); + // check the presence of dangling nodes + if ( Gia_ManHasDangling(pNew) ) + { + pNew = Gia_ManCleanup( pTemp = pNew ); + if ( Gia_ManAndNum(pNew) != Gia_ManAndNum(pTemp) ) + printf( "Gia_ManPerformBidec() node count before and after: %6d and %6d.\n", Gia_ManAndNum(pNew), Gia_ManAndNum(pTemp) ); + Gia_ManStop( pTemp ); + } + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + Vec_IntFree( vLeaves ); + Vec_IntFree( vTruth ); + Vec_IntFree( vVisited ); + if ( fVerbose ) + { +// printf( "Total gain in AIG nodes = %d. ", Gia_ManObjNum(p)-Gia_ManObjNum(pNew) ); +// ABC_PRT( "Total runtime", Abc_Clock() - clk ); + } + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaBound.c b/yosys/abc/src/aig/gia/giaBound.c new file mode 100644 index 00000000000..f7811967d0b --- /dev/null +++ b/yosys/abc/src/aig/gia/giaBound.c @@ -0,0 +1,1374 @@ +#include "gia.h" +#include "misc/tim/tim.h" +#include "misc/vec/vecWec.h" +#include "proof/cec/cec.h" + + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Bnd_Man_t_ Bnd_Man_t; + +struct Bnd_Man_t_ +{ + int nBI; + int nBO; + int nBI_miss; + int nBO_miss; + int nInternal; + int nExtra; + int nMerged_spec; + int nMerged_impl; + + int nNode_spec; + int nNode_impl; + int nNode_patch; + int nNode_patched; + + int fVerbose; + + int combLoop_spec; + int combLoop_impl; + int eq_out; + int eq_res; + int nChoice_spec; + int nChoice_impl; + int feedthrough; + + int maxNumClass; + + Vec_Ptr_t* vBmiter2Spec; + Vec_Ptr_t* vBmiter2Impl; + Vec_Bit_t* vSpec2Impl_phase; // TODO: record all phases + + Vec_Int_t* vImpl2Bmiter; + Vec_Int_t* vSpec2Bmiter; + + Vec_Int_t* vBI; + Vec_Int_t* vBO; + Vec_Int_t* vEI_spec; + Vec_Int_t* vEO_spec; + Vec_Int_t* vEI_impl; + Vec_Int_t* vEO_impl; + Vec_Bit_t* vEI_phase; + Vec_Bit_t* vEO_phase; + +}; + +Bnd_Man_t* pBnd = 0; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +void Bnd_ManSetEqOut( int eq ) { pBnd -> eq_out = eq;} +void Bnd_ManSetEqRes( int eq ) { pBnd -> eq_res = eq;} + +Vec_Int_t* Bnd_ManSpec2Impl( int id ) { return (Vec_Int_t*)Vec_PtrEntry( pBnd -> vBmiter2Impl, Vec_IntEntry( pBnd->vSpec2Bmiter, id ) ); } +int Bnd_ManSpec2ImplNum( int id ) { return Vec_IntSize( (Vec_Int_t*)Vec_PtrEntry( pBnd -> vBmiter2Impl, Vec_IntEntry( pBnd->vSpec2Bmiter, id ) ) ); } + +Vec_Int_t* Bnd_ManImpl2Spec( int id ) { return (Vec_Int_t*)Vec_PtrEntry( pBnd -> vBmiter2Spec, Vec_IntEntry( pBnd->vImpl2Bmiter, id ) ); } +int Bnd_ManImpl2SpecNum( int id ) { return Vec_IntSize( (Vec_Int_t*)Vec_PtrEntry( pBnd -> vBmiter2Spec, Vec_IntEntry( pBnd->vImpl2Bmiter, id ) ) ); } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +Bnd_Man_t* Bnd_ManStart( Gia_Man_t *pSpec, Gia_Man_t *pImpl, int fVerbose ) +{ + int i; + Bnd_Man_t* p = ABC_CALLOC( Bnd_Man_t, 1 ); + + p -> maxNumClass = Gia_ManCiNum( pSpec ) + Gia_ManAndNotBufNum(pSpec) + Gia_ManAndNum(pImpl) + 2 + Gia_ManCoNum(pSpec) * 2; + // one for constant node and one for dummy + + p -> vBmiter2Spec = Vec_PtrAlloc( p -> maxNumClass ); + p -> vBmiter2Impl = Vec_PtrAlloc( p -> maxNumClass ); + Vec_PtrFill( p -> vBmiter2Spec, p -> maxNumClass, 0 ); + Vec_PtrFill( p -> vBmiter2Impl, p -> maxNumClass, 0 ); + for( i = 0; i < Vec_PtrSize( p -> vBmiter2Impl ); i ++ ) + { + Vec_PtrSetEntry( p -> vBmiter2Spec, i, Vec_IntAlloc(1) ); + Vec_PtrSetEntry( p -> vBmiter2Impl, i, Vec_IntAlloc(1) ); + } + + p -> vSpec2Impl_phase = Vec_BitAlloc( Gia_ManObjNum(pSpec) ); + Vec_BitFill( p -> vSpec2Impl_phase, Gia_ManObjNum(pSpec), 0 ); + + p -> vImpl2Bmiter = Vec_IntAlloc( Gia_ManObjNum(pImpl) ); + Vec_IntFill( p -> vImpl2Bmiter, Gia_ManObjNum(pImpl), p -> maxNumClass - 1 ); + p -> vSpec2Bmiter = Vec_IntAlloc( Gia_ManObjNum(pSpec) ); + Vec_IntFill( p -> vSpec2Bmiter, Gia_ManObjNum(pSpec), p -> maxNumClass - 1); + + p -> vBI = Vec_IntAlloc(16); + p -> vBO = Vec_IntAlloc(16); + p -> vEI_spec = Vec_IntAlloc(16); + p -> vEO_spec = Vec_IntAlloc(16); + p -> vEI_impl = Vec_IntAlloc(16); + p -> vEO_impl = Vec_IntAlloc(16); + p -> vEI_phase = Vec_BitAlloc(16); + p -> vEO_phase = Vec_BitAlloc(16); + + p -> nNode_spec = Gia_ManAndNum(pSpec) - Gia_ManBufNum(pSpec); + p -> nNode_impl = Gia_ManAndNum(pImpl); + p -> nNode_patch = 0; + p -> nNode_patched = 0; + + p -> fVerbose = fVerbose; + + p -> combLoop_spec = 0; + p -> combLoop_impl = 0; + p -> eq_out = 0; + p -> eq_res = 0; + + p -> nChoice_spec = 0; + p -> nChoice_impl = 0; + p -> feedthrough = 0; + + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bnd_ManStop() +{ + assert(pBnd); + + Vec_PtrFree( pBnd-> vBmiter2Spec ); + Vec_PtrFree( pBnd-> vBmiter2Impl ); + Vec_BitFree( pBnd-> vSpec2Impl_phase ); + Vec_IntFree( pBnd-> vImpl2Bmiter ); + Vec_IntFree( pBnd-> vSpec2Bmiter ); + + Vec_IntFree( pBnd->vBI ); + Vec_IntFree( pBnd->vBO ); + Vec_IntFree( pBnd->vEI_spec ); + Vec_IntFree( pBnd->vEO_spec ); + Vec_IntFree( pBnd->vEI_impl ); + Vec_IntFree( pBnd->vEO_impl ); + Vec_BitFree( pBnd->vEI_phase ); + Vec_BitFree( pBnd->vEO_phase ); + + ABC_FREE( pBnd ); +} + +int Bnd_ManGetNInternal() { assert(pBnd); return pBnd -> nInternal; } +int Bnd_ManGetNExtra() { assert(pBnd); return pBnd -> nExtra; } + +void Bnd_ManMap( int iLit, int id, int spec ) +{ + + if ( spec ) + { + Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry( pBnd -> vBmiter2Spec, iLit >> 1), id ); + Vec_BitSetEntry( pBnd -> vSpec2Impl_phase, id, iLit & 1 ); + } + else + { + assert( (iLit & 1) == 0 ); + Vec_IntPush( (Vec_Int_t *)Vec_PtrEntry( pBnd -> vBmiter2Impl, iLit >> 1), id ); + } +} + +void Bnd_ManMerge( int id_repr, int id_obj, int phaseDiff ) +{ + + + Vec_Ptr_t* vBmiter2Spec = pBnd -> vBmiter2Spec; + Vec_Ptr_t* vBmiter2Impl = pBnd -> vBmiter2Impl; + Vec_Bit_t* vSpec2Impl_phase = pBnd -> vSpec2Impl_phase; + int id, i; + + Vec_Int_t *vIds_spec_repr, *vIds_impl_repr, *vIds_spec_obj, *vIds_impl_obj; + + vIds_spec_repr = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Spec, id_repr ); + vIds_impl_repr = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Impl, id_repr ); + vIds_spec_obj = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Spec, id_obj ); + vIds_impl_obj = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Impl, id_obj ); + + Vec_IntForEachEntry( vIds_spec_obj, id, i ) + { + Vec_IntPush(vIds_spec_repr, id); + } + Vec_IntForEachEntry( vIds_impl_obj, id, i ) + { + Vec_IntPush(vIds_impl_repr, id); + } + + // handle spec2impl phase + if ( phaseDiff ) + { + Vec_IntForEachEntry( vIds_spec_obj, id, i ) + { + Vec_BitSetEntry( vSpec2Impl_phase, id, !Vec_BitEntry(vSpec2Impl_phase, id) ); + // printf( "spec id %d's phase set to %d\n", id, Vec_BitEntry(vSpec2Impl_phase, id) ); + } + } + + Vec_IntClear(vIds_spec_obj); + Vec_IntClear(vIds_impl_obj); + +} +void Bnd_ManFinalizeMappings() +{ + + Vec_Ptr_t* vBmiter2Spec = pBnd -> vBmiter2Spec; + Vec_Ptr_t* vBmiter2Impl = pBnd -> vBmiter2Impl; + + Vec_Int_t *vSpec, *vImpl; + int i, j, id; + + pBnd -> nMerged_impl = 0; + pBnd -> nMerged_spec = 0; + + + for( i = 0; i < Vec_PtrSize(vBmiter2Spec); i++ ) + { + vSpec = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Spec, i ); + vImpl = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Impl, i ); + + Vec_IntForEachEntry( vSpec, id, j ) + { + // vSpec2Bmiter + Vec_IntSetEntry( pBnd->vSpec2Bmiter, id, i ); + } + + Vec_IntForEachEntry( vImpl, id, j ) + { + // vImpl2Bmiter + Vec_IntSetEntry( pBnd->vImpl2Bmiter, id, i ); + } + + // count number of nodes merged into the same circuit + if ( Vec_IntSize(vSpec) != 0 ) + { + pBnd->nMerged_spec += Vec_IntSize(vSpec) - 1; + } + if ( Vec_IntSize(vImpl) != 0 ) + { + pBnd->nMerged_impl += Vec_IntSize(vImpl) - 1; + } + } + +} +void Bnd_ManPrintMappings() +{ + Vec_Ptr_t* vBmiter2Spec = pBnd -> vBmiter2Spec; + Vec_Ptr_t* vBmiter2Impl = pBnd -> vBmiter2Impl; + Vec_Int_t* vIds_spec, *vIds_impl; + int k, id; + for( int j=0; j < Vec_PtrSize(vBmiter2Spec); j++ ) + { + printf("node %d: ", j); + vIds_spec = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Spec, j); + vIds_impl = (Vec_Int_t *)Vec_PtrEntry( vBmiter2Impl, j); + Vec_IntForEachEntry(vIds_spec, id, k) + printf("%d ", id); + printf("| "); + Vec_IntForEachEntry(vIds_impl, id, k) + printf("%d ", id); + printf("\n"); + } + +} + +void Bnd_ManPrintBound() +{ + + // printf("%d nodes merged in spec\n", pBnd ->nMerged_spec - Vec_IntSize(pBnd->vBI) - Vec_IntSize(pBnd->vBO) ); + // printf("%d nodes merged in impl\n", pBnd ->nMerged_impl ); + printf("BI spec:\t"); Vec_IntPrint(pBnd -> vBI); + printf("BO spec:\t"); Vec_IntPrint(pBnd -> vBO); + printf("EI spec:\t"); Vec_IntPrint(pBnd -> vEI_spec); + printf("EI impl:\t"); Vec_IntPrint(pBnd -> vEI_impl); + printf("EI phase:\t"); Vec_BitPrint(pBnd -> vEI_phase); + printf("EO spec:\t"); Vec_IntPrint(pBnd -> vEO_spec); + printf("EO impl:\t"); Vec_IntPrint(pBnd -> vEO_impl); + printf("EO phase:\t"); Vec_BitPrint(pBnd -> vEO_phase); +} + +void Bnd_ManPrintStats() +{ + Bnd_Man_t* p = pBnd; + + + printf("\nSTATS\n"); + + int warning = 0; + if ( p->nChoice_spec > 0 ) + { + warning = 1; + printf("WARNING: multiple equiv nodes on the boundary of spec\n"); + } + if ( p->nChoice_impl > 0 ) + { + warning = 1; + printf("WARNING: multiple equiv nodes on the boundary of impl\n"); + } + + printf("The outsides of spec and impl are %sEQ.\n", p->eq_out ? "" : "NOT " ); + printf("The patched impl is %sEQ. to spec (and impl)\n", p->eq_res ? "" : "NOT " ); + + // #internal + // nBI, nBO + // nBI_miss, nBO_miss + // nEI, nEO, nExtra + // #spec, #impl, #patched + // combLoop_spec, combLoop_impl + // #choice_impl + // #choice_spec + // #feedthrough + // warning (may be neq) + // eq_out, eq_res + + printf("\nRESULT\n"); + printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", + p->nInternal, + p->nBI, p->nBO, + p->nBI_miss, p->nBO_miss, + Vec_IntSize(p->vEI_spec), Vec_IntSize(p->vEO_spec), p->nExtra, + p->nNode_spec, p->nNode_impl, p->nNode_patched, + p->combLoop_spec, p->combLoop_impl, + p->nChoice_impl, + p->nChoice_spec, + warning, + p->eq_out, p->eq_res + ); + + printf("#Choice Spec\t%d\n", p->nChoice_spec); + printf("#Choice Impl\t%d\n", p->nChoice_impl); + + + +} + +/**Function************************************************************* + + Synopsis [] + + Description [check if the given boundary is valid. Return 0 if + the boundary is invalid. Return k if the boundary is valid and + there're k boundary inputs. + Can be called even if Bnd_Man_t is not created] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bnd_ManCheckBound( Gia_Man_t * p, int fVerbose ) +{ + int i; + Gia_Obj_t *pObj; + int valid = 1; + int nBI = 0, nBO = 0, nInternal = 0; + + if ( fVerbose ) printf( "Checking boundary... \n"); + + Vec_Int_t *vPath; + vPath = Vec_IntAlloc( Gia_ManObjNum(p) ); + Vec_IntFill( vPath, Gia_ManObjNum(p), 0 ); + int path; + + Gia_ManForEachObjReverse1( p , pObj, i ) + { + if ( Gia_ObjIsCo( pObj ) ) + { + Vec_IntSetEntry( vPath, Gia_ObjId( p, pObj ), 1 ); + } + + path = Vec_IntEntry( vPath, Gia_ObjId(p, pObj) ); + // printf("path = %d\n", path); + + if ( path >= 8 ) + { + valid = 0; + printf("there're more than 2 bufs in a path\n"); + break; + } + + + if( Gia_ObjIsBuf( pObj ) ) + { + Vec_IntSetEntry( vPath, Gia_ObjId( p, Gia_ObjFanin0( pObj ) ), Vec_IntEntry( vPath, Gia_ObjId(p, Gia_ObjFanin0( pObj ) ) ) | path << 1 ); + if ( path == 1 ) // boundary input + { + // TODO: record BIs here since they may not be in the first n buffers + nBO ++; + } + } + else if ( Gia_ObjFaninNum( p, pObj ) >= 1 ) + { + Vec_IntSetEntry( vPath, Gia_ObjId( p, Gia_ObjFanin0( pObj ) ), Vec_IntEntry( vPath, Gia_ObjId(p, Gia_ObjFanin0( pObj ) ) ) | path ); + if ( Gia_ObjFaninNum( p, pObj ) >= 2 ) + { + assert( Gia_ObjFaninNum( p, pObj ) <= 2 ); + Vec_IntSetEntry( vPath, Gia_ObjId( p, Gia_ObjFanin1( pObj ) ), Vec_IntEntry( vPath, Gia_ObjId(p, Gia_ObjFanin1( pObj ) ) ) | path ); + } + if ( path == 2 ) // inside boundary + { + // TODO: record BIs here since they may not be in the first n buffers + nInternal ++; + } + } + else // PI or const, check validity + { + if ( (Vec_IntEntry( vPath, Gia_ObjId(p, pObj) ) | 5) != 5 ) + { + valid = 0; + printf("incorrect buf number at pi %d\n", Vec_IntEntry(vPath, Gia_ObjId(p, pObj)) ); + break; + } + } + } + + nBI = Gia_ManBufNum(p) - nBO; + + if ( !valid ) + { + printf("invalid boundary\n"); + return 0; + } + else if ( nBI == 0 ) + { + printf("no boundary\n"); + return 0; + } + else + { + if ( fVerbose ) + { + printf("valid boundary ("); + printf("#BI = %d\t#BO = %d\t", nBI, Gia_ManBufNum(p)- nBI); + printf("#Internal = %d)\n", nInternal ); + } + if ( pBnd ) + { + pBnd -> nBI = nBI; + pBnd -> nBO = nBO; + pBnd -> nInternal = nInternal; + } + return nBI; + } +} + + +int Bnd_CheckFlagRec( Gia_Man_t *p, Gia_Obj_t *pObj, Vec_Int_t* vFlag ) +{ + int id = Gia_ObjId(p, pObj); + if ( Vec_IntEntry(vFlag, id) == 1 ) return 1; + if ( Vec_IntEntry(vFlag, id) == 2 ) return 0; + + Vec_IntSetEntry(vFlag, id, 1); + + int ret = 1; + for( int i = 0; i < Gia_ObjFaninNum(p, pObj); i++ ) + { + if ( !Bnd_CheckFlagRec( p, Gia_ObjFanin(pObj, i), vFlag ) ) + { + ret = 0; + break; + } + } + return ret; + +} + +/**Function************************************************************* + + Synopsis [] + + Description [check if combnational loop exist in the extended boundary] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Bnd_ManCheckExtBound( Gia_Man_t * p, Vec_Int_t *vEI, Vec_Int_t *vEO ) +{ + Vec_Int_t *vFlag = Vec_IntAlloc( Gia_ManObjNum(p) ); + Vec_IntFill( vFlag, Gia_ManObjNum(p), 0 ); + int success = 1; + int i, id; + + Vec_IntForEachEntry( vEO, id, i ) + { + Vec_IntSetEntry( vFlag, id, 2 ); + } + + Vec_IntForEachEntry( vEI, id, i ) + { + if ( Vec_IntEntry(vFlag, id) == 2 ) continue; // BI connected to BO directly + + if ( !Bnd_CheckFlagRec( p, Gia_ManObj(p, id), vFlag ) ) + { + success = 0; + break; + } + } + + + Vec_IntFree(vFlag); + return success; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [find the extended boundary in spec + and compute the corresponding boundary in impl] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Bnd_ManFindBound( Gia_Man_t * p, Gia_Man_t * pImpl ) +{ + Vec_Int_t *vFlag; + Vec_Ptr_t *vQ; + Gia_Obj_t *pObj; + int i, j, id, cnt; + + Vec_Int_t *vAI = Vec_IntAlloc(16); + Vec_Int_t *vAO = Vec_IntAlloc(16); + + Vec_Bit_t *vSpec2Impl_phase = pBnd -> vSpec2Impl_phase; + Vec_Int_t *vBI = pBnd -> vBI; + Vec_Int_t *vBO = pBnd -> vBO; + Vec_Int_t *vEI_spec = pBnd -> vEI_spec; + Vec_Int_t *vEO_spec = pBnd -> vEO_spec; + Vec_Int_t *vEI_impl = pBnd -> vEI_impl; + Vec_Int_t *vEO_impl = pBnd -> vEO_impl; + Vec_Bit_t *vEI_phase = pBnd -> vEI_phase; + Vec_Bit_t *vEO_phase = pBnd -> vEO_phase; + + + // prepare to compute extended boundary + vQ = Vec_PtrAlloc(16); + vFlag = Vec_IntAlloc( Gia_ManObjNum(p) ); + Vec_IntFill( vFlag, Gia_ManObjNum(p), 0 ); + + Gia_ManStaticFanoutStart(p); + + // save bo, bi + cnt = 0; + Gia_ManForEachBuf(p, pObj, i) + { + if ( cnt < pBnd -> nBI ) + { + Vec_IntPush( vBI, Gia_ObjId(p, Gia_ObjFanin0(pObj) ) ); + } + else + { + Vec_IntPush( vBO, Gia_ObjId(p, pObj) ); + } + cnt++; + } + + // compute EO, travse with flag 1 + Vec_IntForEachEntry( vBO, id, i ) + { + if ( Bnd_ManSpec2ImplNum(id) == 0 ) // BO not matched + { + Vec_PtrPush( vQ, Gia_ManObj(p, id) ); + } + else + { + Vec_IntPush(vEO_spec, id); + } + } + if ( pBnd -> fVerbose ) printf("%d BO doesn't match. ", Vec_PtrSize(vQ) ); + pBnd -> nBO_miss = Vec_PtrSize(vQ); + + int cnt_extra = - Vec_PtrSize(vQ); + while( Vec_PtrSize(vQ) > 0 ) + { + pObj = (Gia_Obj_t *)Vec_PtrPop(vQ); + id = Gia_ObjId( p, pObj ); + + if ( Vec_IntEntry( vFlag, id ) == 1 ) continue; + Vec_IntSetEntry( vFlag, id, 1 ); + + // printf("%d\n", id); + + if ( Bnd_ManSpec2ImplNum(id) != 0 ) // matched + { + Vec_IntPush( vEO_spec, id ); + Vec_IntPush( vAO, id ); + } + else + { + for( j = 0; j < Gia_ObjFanoutNum(p, pObj); j++ ) + { + Vec_PtrPush( vQ, Gia_ObjFanout(p, pObj, j) ); + // printf("\t%d\n", Gia_ObjId( p1, Gia_ObjFanout(p1, pObj, j) ) ); + } + } + } + // printf("%d AO found with %d extra nodes\n", Vec_IntSize(vAO) , cnt_extra ); + if ( pBnd -> fVerbose ) printf("%d AO found\n", Vec_IntSize(vAO) ); + + + // mark TFOC of BO with flag 1 to prevent them from being selected into EI + // stop at CO + Vec_IntForEachEntry( pBnd -> vBO, id, i ) + { + Vec_PtrPush( vQ, Gia_ManObj(p, id) ); + } + Vec_IntForEachEntry( vFlag, id, i ) + { + Vec_IntSetEntry( vFlag, id, 0 ); + } + while( Vec_PtrSize(vQ) > 0 ) + { + pObj = (Gia_Obj_t *)Vec_PtrPop(vQ); + id = Gia_ObjId( p, pObj ); + + if ( Vec_IntEntry( vFlag, id ) == 1 ) continue; + Vec_IntSetEntry( vFlag, id, 1 ); + + for( j = 0; j < Gia_ObjFanoutNum(p, pObj); j++ ) + { + Vec_PtrPush( vQ, Gia_ObjFanout(p, pObj, j) ); + } + } + + + + // compute EI, traverse with flag 2 + + // add unmatched BI to queue + Vec_IntForEachEntry( vBI, id, i ) + { + if ( Bnd_ManSpec2ImplNum(id) == 0 ) // BO not matched + { + Vec_PtrPush( vQ, Gia_ManObj(p, id) ); + } + else + { + Vec_IntPush(vEI_spec, id); + } + } + if ( pBnd -> fVerbose ) printf("%d BI doesn't match. ", Vec_PtrSize(vQ) ); + pBnd -> nBI_miss = Vec_PtrSize(vQ); + cnt_extra -= Vec_PtrSize(vQ); + + // add AO to queue + Vec_IntForEachEntry( vAO, id, i ) + { + Vec_PtrPush( vQ, Gia_ManObj(p, id) ); + } + + // set flag 2 for BO + Vec_IntForEachEntry( vBO, id, i ) + { + Vec_IntSetEntry( vFlag, id, 2 ); + } + + // traverse down from AI and unmatched BI + while( Vec_PtrSize(vQ) > 0 ) + { + pObj = (Gia_Obj_t *)Vec_PtrPop(vQ); + id = Gia_ObjId( p, pObj ); + + if ( Vec_IntEntry( vFlag, id ) == 2 ) continue; + cnt_extra ++; + + // printf("%d\n", id); + + if ( Vec_IntEntry(vFlag, id) != 1 && Bnd_ManSpec2ImplNum(id) != 0 ) // matched + { + Vec_IntPush( vEI_spec, id ); + Vec_IntPush( vAI, id ); + } + else + { + for( j = 0; j < Gia_ObjFaninNum(p, pObj); j++ ) + { + Vec_PtrPush( vQ, Gia_ObjFanin(pObj, j) ); + // printf("\t%d\n", Gia_ObjId( p1, Gia_ObjFanout(p1, pObj, j) ) ); + } + } + + Vec_IntSetEntry( vFlag, id, 2 ); + } + if ( pBnd -> fVerbose ) printf("%d AI found with %d extra nodes in total\n", Vec_IntSize(vAI) , cnt_extra ); + pBnd -> nExtra = cnt_extra; + + + // gen vEI_impl, vEO_impl, vEI_phase, vEO_phase + Vec_IntForEachEntry( vEI_spec, id, i ) + { + Vec_IntPush( vEI_impl, Vec_IntEntry( Bnd_ManSpec2Impl(id) , 0 ) ); + Vec_BitPush( vEI_phase, Vec_BitEntry( vSpec2Impl_phase, id ) ); + } + Vec_IntForEachEntry( vEO_spec, id, i ) + { + Vec_IntPush( vEO_impl, Vec_IntEntry( Bnd_ManSpec2Impl(id), 0 ) ); + Vec_BitPush( vEO_phase, Vec_BitEntry( vSpec2Impl_phase, id ) ); + } + + + // count number of choice of boundary + Vec_IntForEachEntry( vEO_spec, id, i ) + { + pBnd -> nChoice_impl += Bnd_ManSpec2ImplNum( id ) - 1; + } + Vec_IntForEachEntry( vEO_impl, id, i ) + { + pBnd -> nChoice_spec += Bnd_ManImpl2SpecNum( id ) - 1; + } + + // print + if ( pBnd -> fVerbose ) + { + printf("#EI = %d\t#EO = %d\t#Extra Node = %d\n", Vec_IntSize(vEI_spec) , Vec_IntSize(vEO_spec), cnt_extra ); + Bnd_ManPrintBound(); + } + + // check boundary has comb loop + if ( !Bnd_ManCheckExtBound( p, vEI_spec, vEO_spec ) ) + { + + printf("Combinational loop exist\n"); + pBnd -> combLoop_spec = 1; + + } + + + // clean up + Vec_IntFree(vAI); + Vec_IntFree(vAO); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [create circuit with the boundary changed to CI/CO] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t* Bnd_ManCutBoundary( Gia_Man_t *p, Vec_Int_t* vEI, Vec_Int_t* vEO, Vec_Bit_t* vEI_phase, Vec_Bit_t* vEO_phase ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + Vec_Int_t * vValue; + int i, id, lit; + + // check if the boundary has loop (EO cannot be in the TFC of EI ) + if ( !Bnd_ManCheckExtBound( p, vEI, vEO ) ) + { + printf("Combinational loop exist\n"); + pBnd -> combLoop_impl = 1; + return 0; + } + + // initialize + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew -> pName = ABC_ALLOC( char, strlen(p->pName)+10); + sprintf( pNew -> pName, "%s_out", p -> pName ); + Gia_ManHashStart( pNew ); + Gia_ManFillValue(p); + Gia_ManConst0(p) -> Value = 0; + + + // record the original value for eo + vValue = Vec_IntAlloc( Gia_ManObjNum(p) ); + Vec_IntFill( vValue, Gia_ManObjNum(p), -1 ); + + // create ci for ci and eo + Gia_ManForEachCi( p, pObj, i ) + { + pObj -> Value = Gia_ManAppendCi( pNew ); + } + Vec_IntForEachEntry( vEO, id, i ) + { + if( Gia_ManObj(p, id) -> Value != ~0 ) + { + Vec_IntSetEntry( vValue, id, Gia_ManObj(p, id) -> Value ); + } + Gia_ManObj( p, id ) -> Value = Gia_ManAppendCi(pNew); + if ( vEO_phase && Vec_BitEntry( vEO_phase, i ) ) + { + Gia_ManObj( p, id ) -> Value ^= 1; + } + } + + // add aig nodes + Gia_ManForEachAnd(p, pObj, i) + { + if ( pObj -> Value != ~0 ) continue; + pObj -> Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + + // create co for co and ei + Gia_ManForEachCo(p, pObj, i) + { + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Vec_IntForEachEntry( vEI, id, i ) + { + pObj = Gia_ManObj(p, id); + // lit = Gia_ManObj(p, id)->Value; + if ( Gia_ObjIsAnd(pObj) ) lit = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else + { + assert(Gia_ObjIsCi(pObj) || Gia_ObjIsConst0(pObj)); + if ( Vec_IntEntry(vValue, id) != -1 ) + { + lit = Vec_IntEntry( vValue, id ); // EI at PI and EI merged with EO + } + else { + lit = pObj -> Value; // EI at PI + } + } + if ( vEI_phase && Vec_BitEntry( vEI_phase, i ) ) lit ^= 1; + Gia_ManAppendCo( pNew, lit ); + } + + // clean up + Vec_IntFree( vValue ); + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; + +} + +Gia_Man_t* Bnd_ManGenSpecOut( Gia_Man_t* p ) +{ + if ( pBnd -> fVerbose ) printf("Generating spec_out with given boundary.\n"); + Gia_Man_t *pNew = Bnd_ManCutBoundary( p, pBnd->vEI_spec, pBnd->vEO_spec, 0, 0 ); + return pNew; +} +Gia_Man_t* Bnd_ManGenImplOut( Gia_Man_t* p) +{ + if ( pBnd -> fVerbose ) printf("Generating impl_out with given boundary.\n"); + Gia_Man_t *pNew = Bnd_ManCutBoundary( p, pBnd->vEI_impl, pBnd->vEO_impl, pBnd->vEI_phase, pBnd->vEO_phase ); + if (!pNew) pBnd -> combLoop_impl = 1; + return pNew; +} + +void Bnd_AddNodeRec( Gia_Man_t *p, Gia_Man_t *pNew, Gia_Obj_t *pObj, int fSkipStrash ) +{ + // TODO does this mean constant zero node? + if ( pObj -> Value != ~0 ) return; + + for( int i = 0; i < Gia_ObjFaninNum(p, pObj); i++ ) + { + Bnd_AddNodeRec( p, pNew, Gia_ObjFanin(pObj, i), fSkipStrash ); + } + + if ( Gia_ObjIsAnd(pObj) ) + { + if ( fSkipStrash ) + { + if ( Gia_ObjIsBuf(pObj) ) pObj -> Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else pObj -> Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + else + { + pObj -> Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + } + else + { + assert( Gia_ObjIsCo(pObj) ); + // if ( Gia_ObjIsCi(pObj) ) printf("Ci with value ~0 encountered (id = %d)\n", Gia_ObjId(p, pObj) ); + pObj -> Value = Gia_ObjFanin0Copy(pObj); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [perform ECO directly (not used)] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t* Bnd_ManGenPatched( Gia_Man_t *pOut, Gia_Man_t *pSpec, Gia_Man_t *pPatch ) +{ + + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, id, cnt; + Vec_Int_t *vBI_patch, *vBO_patch; + + pBnd -> nNode_patch = Gia_ManAndNotBufNum( pPatch ); + + pNew = Gia_ManStart( Gia_ManObjNum(pOut) + Gia_ManObjNum( pSpec ) + Gia_ManObjNum(pPatch) ); + pNew -> pName = ABC_ALLOC( char, strlen(pOut->pName)+3); + sprintf( pNew -> pName, "%s_p", pOut -> pName ); + Gia_ManHashStart( pNew ); + Gia_ManFillValue(pOut); + Gia_ManFillValue(pSpec); + Gia_ManFillValue(pPatch); + Gia_ManConst0(pOut)->Value = 0; + Gia_ManConst0(pSpec)->Value = 0; + Gia_ManConst0(pPatch)->Value = 0; + + // get bi and bo in patch + cnt = 0; + vBI_patch = Vec_IntAlloc(16); + vBO_patch = Vec_IntAlloc(16); + Gia_ManForEachBuf( pPatch, pObj, i ) + { + if ( cnt < pBnd -> nBI ) + { + Vec_IntPush( vBI_patch, Gia_ObjId( pPatch, pObj ) ); + } + else + { + + Vec_IntPush( vBO_patch, Gia_ObjId( pPatch, pObj ) ); + } + cnt ++; + } + assert( Vec_IntSize( vBI_patch ) == Vec_IntSize(pBnd->vBI) ); + assert( Vec_IntSize( vBO_patch ) == Vec_IntSize(pBnd->vBO) ); + + + // add Impl (real) PI + for ( i = 0; i < Gia_ManCiNum(pSpec); i++ ) + { + pObj = Gia_ManCi(pOut, i); + pObj -> Value = Gia_ManAppendCi( pNew ); + } + + // add Impl EI to CI + // printf("adding EI to CI in Impl\n"); + for ( i = 0; i < Vec_IntSize( pBnd -> vEI_spec ); i++ ) + { + pObj = Gia_ManCo(pOut, i + Gia_ManCoNum(pSpec) ); + Bnd_AddNodeRec( pOut, pNew, pObj, 0 ); + + // set Spec EI + Gia_ManObj( pSpec, Vec_IntEntry(pBnd -> vEI_spec, i) ) -> Value = pObj -> Value; + // printf(" %d",pObj -> Value); + } + // printf("\n"); + + // add Spec BI to EI + // printf("adding BI to EI in Spec\n"); + Vec_IntForEachEntry( pBnd -> vBI, id, i ) + { + pObj = Gia_ManObj( pSpec, id ); + Bnd_AddNodeRec( pSpec, pNew, pObj, 0 ); + + // set patch bi + Gia_ManObj( pPatch, Vec_IntEntry( vBI_patch, i) ) -> Value = pObj -> Value; + // printf(" %d",pObj -> Value); + } + // printf("\n"); + + // add Patch BO to BI + // printf("adding BO to BI in Patch\n"); + Vec_IntForEachEntry( vBO_patch, id, i ) + { + pObj = Gia_ManObj( pPatch, id ); + Bnd_AddNodeRec( pPatch, pNew, pObj, 0 ); + + // set spec bo + Gia_ManObj( pSpec, Vec_IntEntry( pBnd -> vBO, i) ) -> Value = pObj -> Value; + // printf(" %d",pObj -> Value); + } + // printf("\n"); + + // add Spec EO to BO + // printf("adding EO to BO in Spec\n"); + Vec_IntForEachEntry( pBnd -> vEO_spec, id, i ) + { + pObj = Gia_ManObj( pSpec, id ); + Bnd_AddNodeRec( pSpec, pNew, pObj, 0 ); + + // set impl EO (PI) + Gia_ManCi( pOut, i + Gia_ManCiNum(pSpec) ) -> Value = pObj -> Value; + // printf(" %d",pObj -> Value); + } + // printf("\n"); + + // add Impl (real) PO to EO + // printf("adding CO to EO in Impl\n"); + for ( i = 0; i < Gia_ManCoNum(pSpec); i++ ) + { + pObj = Gia_ManCo( pOut, i ); + Bnd_AddNodeRec( pOut, pNew, pObj, 0 ); + Gia_ManAppendCo( pNew, pObj->Value ); + // printf(" %d",pObj -> Value); + } + // printf("\n"); + + + // clean up + Vec_IntFree( vBI_patch ); + Vec_IntFree( vBO_patch ); + Gia_ManHashStop( pNew ); + + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + + pBnd -> nNode_patched = Gia_ManAndNum( pNew ); + + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [recover bounadry] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t* Bnd_ManGenPatched1( Gia_Man_t *pOut, Gia_Man_t *pSpec ) +{ + + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, id; + + pNew = Gia_ManStart( Gia_ManObjNum(pOut) + Gia_ManObjNum( pSpec ) ); + pNew -> pName = ABC_ALLOC( char, strlen(pOut->pName)+3); + sprintf( pNew -> pName, "%s_p", pOut -> pName ); + + Gia_ManFillValue(pOut); + Gia_ManFillValue(pSpec); + Gia_ManConst0(pOut)->Value = 0; + Gia_ManConst0(pSpec)->Value = 0; + + + // add Impl (real) PI + for ( i = 0; i < Gia_ManCiNum(pSpec); i++ ) + { + pObj = Gia_ManCi(pOut, i); + pObj -> Value = Gia_ManAppendCi( pNew ); + } + + // add Impl EI to CI + // printf("adding EI to CI in Impl\n"); + for ( i = 0; i < Vec_IntSize( pBnd -> vEI_spec ); i++ ) + { + pObj = Gia_ManCo(pOut, i + Gia_ManCoNum(pSpec) ); + Bnd_AddNodeRec( pOut, pNew, pObj, 1 ); + + // set Spec EI + Gia_ManObj( pSpec, Vec_IntEntry(pBnd -> vEI_spec, i) ) -> Value = pObj -> Value; + // printf(" %d",pObj -> Value); + } + // printf("\n"); + + // add Spec EO to EI + // add BI -> BO -> EO to maintain the order of bufs + // Vec_IntForEachEntry( pBnd -> vBI, id, i ) + // { + // pObj = Gia_ManObj( pSpec, id ); + // Bnd_AddNodeRec( pSpec, pNew, pObj, 1 ); + // } + // Vec_IntForEachEntry( pBnd -> vBO, id, i ) + // { + // pObj = Gia_ManObj( pSpec, id ); + // Bnd_AddNodeRec( pSpec, pNew, pObj, 1 ); + // } + Gia_ManForEachBuf( pSpec, pObj, i ) + { + Bnd_AddNodeRec( pSpec, pNew, pObj, 1 ); + } + Vec_IntForEachEntry( pBnd -> vEO_spec, id, i ) + { + pObj = Gia_ManObj( pSpec, id ); + Bnd_AddNodeRec( pSpec, pNew, pObj, 1 ); + + // set impl EO (PI) + Gia_ManCi( pOut, i + Gia_ManCiNum(pSpec) ) -> Value = pObj -> Value; + // printf(" %d",pObj -> Value); + } + // printf("\n"); + + // add Impl (real) PO to EO + // printf("adding CO to EO in Impl\n"); + for ( i = 0; i < Gia_ManCoNum(pSpec); i++ ) + { + pObj = Gia_ManCo( pOut, i ); + Bnd_AddNodeRec( pOut, pNew, pObj, 1 ); + Gia_ManAppendCo( pNew, pObj->Value ); + // printf(" %d",pObj -> Value); + } + // printf("\n"); + + + // clean up + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + + pBnd -> nNode_patched = Gia_ManAndNum( pNew ); + + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [perform eco with recovered boundary. + bnd_man is not used] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t* Bnd_ManGenPatched2( Gia_Man_t *pImpl, Gia_Man_t *pPatch, int fSkipStrash, int fVerbose ) +{ + + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, nBI, nBI_patch, cnt; + Vec_Int_t* vLit; + + + // check boundary first + nBI = Bnd_ManCheckBound( pImpl, fVerbose ); + nBI_patch = Bnd_ManCheckBound( pPatch, fVerbose ); + if ( 0 == nBI_patch || Gia_ManBufNum(pImpl) != Gia_ManBufNum(pPatch) || nBI != nBI_patch ) + { + Abc_Print( -1, "Abc_CommandAbc9StrEco(): The given boundary is invalid.\n" ); + return 0; + } + + // prepare new network + pNew = Gia_ManStart( Gia_ManObjNum(pImpl) + Gia_ManObjNum( pPatch ) ); + pNew -> pName = ABC_ALLOC( char, strlen(pImpl->pName)+3); + sprintf( pNew -> pName, "%s_p", pImpl -> pName ); + if ( !fSkipStrash ) + { + Gia_ManHashAlloc( pNew ); + } + Gia_ManFillValue(pImpl); + Gia_ManFillValue(pPatch); + Gia_ManConst0(pImpl)->Value = 0; + Gia_ManConst0(pPatch)->Value = 0; + + vLit = Vec_IntAlloc( Gia_ManBufNum(pImpl) ); + + // add Impl (real) CI + Gia_ManForEachCi( pImpl, pObj, i ) + { + pObj -> Value = Gia_ManAppendCi( pNew ); + } + + // add Impl BI to CI + cnt = 0; + Gia_ManForEachBuf( pImpl, pObj, i ) + { + Bnd_AddNodeRec( pImpl, pNew, pObj, fSkipStrash ); + Vec_IntPush( vLit, pObj -> Value ); + cnt ++; + if ( cnt >= nBI ) break; + } + + // set BI in patch + // add patch BO to BI + cnt = 0; + Gia_ManForEachBuf( pPatch, pObj, i ) + { + if ( cnt < nBI ) + { + pObj -> Value = Vec_IntEntry( vLit, cnt ); + } + else + { + Bnd_AddNodeRec( pPatch, pNew, pObj, fSkipStrash ); + Vec_IntPush( vLit, pObj -> Value ); + } + cnt ++; + if ( cnt == nBI ) Vec_IntClear( vLit ); + } + + // set BO in impl + cnt = 0; + Gia_ManForEachBuf( pImpl, pObj, i ) + { + cnt ++; + if ( cnt <= nBI) continue; + pObj -> Value = Vec_IntEntry( vLit, cnt-nBI-1 ); + } + + // add impl CO to BO + Gia_ManForEachCo( pImpl, pObj, i ) + { + Bnd_AddNodeRec( pImpl, pNew, pObj, fSkipStrash ); + Gia_ManAppendCo( pNew, pObj -> Value ); + } + + // clean up + if ( !fSkipStrash ) + { + Gia_ManHashStop( pNew ); + } + Vec_IntFree( vLit ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + + return pNew; +} + + +Gia_Man_t* Bnd_ManStackGias( Gia_Man_t *pSpec, Gia_Man_t *pImpl ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + + int i, iLit; + if ( Gia_ManBufNum(pSpec) == 0 ) { + printf( "The spec AIG should have a boundary.\n" ); + return NULL; + } + if ( Gia_ManBufNum(pImpl) != 0 ) { + printf( "The impl AIG should have no boundary.\n" ); + return NULL; + } + + assert( Gia_ManBufNum(pSpec) > 0 ); + assert( Gia_ManBufNum(pImpl) == 0 ); + assert( Gia_ManRegNum(pSpec) == 0 ); + assert( Gia_ManRegNum(pImpl) == 0 ); + assert( Gia_ManCiNum(pSpec) == Gia_ManCiNum(pImpl) ); + assert( Gia_ManCoNum(pSpec) == Gia_ManCoNum(pImpl) ); + + pNew = Gia_ManStart( Gia_ManObjNum(pSpec) + Gia_ManObjNum(pImpl) ); + pNew->pName = ABC_ALLOC( char, strlen(pSpec->pName) + 10 ); + sprintf( pNew->pName, "%s_stack", pSpec->pName ); + + Gia_ManHashStart( pNew ); + Gia_ManConst0(pSpec)->Value = 0; + Gia_ManConst0(pImpl)->Value = 0; + + for( int i = 0; i < Gia_ManCiNum(pSpec); i++ ) + { + int iLit = Gia_ManCi(pSpec, i)->Value = Gia_ManCi(pImpl, i) -> Value = Gia_ManAppendCi(pNew); + + pObj = Gia_ManCi(pSpec, i); + Bnd_ManMap( iLit, Gia_ObjId( pSpec, pObj ), 1 ); + + pObj = Gia_ManCi(pImpl, i); + Bnd_ManMap( iLit, Gia_ObjId( pImpl, pObj) , 0 ); + } + + // record the corresponding impl node of each lit + Gia_ManForEachAnd( pImpl, pObj, i ) + { + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( pBnd ) Bnd_ManMap( pObj -> Value, Gia_ObjId(pImpl, pObj), 0 ); + } + + Vec_Int_t* vFlag = Vec_IntAlloc( Gia_ManObjNum( pSpec ) ); + Vec_IntFill( vFlag, Gia_ManObjNum(pSpec), 0 ); + int count = 0; + Gia_ManForEachBuf( pSpec, pObj, i ) + { + if ( count < pBnd -> nBI ) + { + // it's BI, don't record buf + Vec_IntSetEntry( vFlag, Gia_ObjId( pSpec, pObj ), 1 ); + } + else + { + // it's BO, don't record buf's fanin + Vec_IntSetEntry( vFlag, Gia_ObjId( pSpec, Gia_ObjFanin0( pObj ) ), 1 ); + } + count++; + } + + // record hashed equivalent nodes + Gia_ManForEachAnd( pSpec, pObj, i ) + { + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( Vec_IntEntry( vFlag, Gia_ObjId( pSpec, pObj ) ) == 0 ) + { + Bnd_ManMap( pObj -> Value, Gia_ObjId(pSpec, pObj), 1 ); + } + } + Vec_IntFree( vFlag ); + + Gia_ManForEachCo( pImpl, pObj, i ) + { + iLit = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManForEachCo( pSpec, pObj, i ) + { + iLit = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + + // miter + // Gia_ManForEachCo( pImpl, pObj, i ) + // { + // iLit = Gia_ManHashXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin0Copy(Gia_ManCo(pSpec,i)) ); + // Gia_ManAppendCo( pNew, iLit ); + // } + + + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +int Bnd_ManCheckCoMerged( Gia_Man_t* p ) +{ + int nCO = Gia_ManCoNum(p)/2; + + Gia_Obj_t* pObj1; + Gia_Obj_t* pObj2; + + for ( int i = 0; i < nCO; i++ ) + { + pObj1 = Gia_ManCo(p, i); + pObj2 = Gia_ManCo(p, i + nCO); + if ( Gia_ObjFaninLit0p(p, pObj1) != Gia_ObjFaninLit0p(p, pObj2) ) return 0; + } + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END \ No newline at end of file diff --git a/yosys/abc/src/aig/gia/giaCCof.c b/yosys/abc/src/aig/gia/giaCCof.c new file mode 100644 index 00000000000..19cdf9e6930 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaCCof.c @@ -0,0 +1,349 @@ +/**CFile**************************************************************** + + FileName [giaCCof.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Backward reachability using circuit cofactoring.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaCCof.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "sat/bsat/satSolver.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Ccf_Man_t_ Ccf_Man_t; // manager +struct Ccf_Man_t_ +{ + // user data + Gia_Man_t * pGia; // single-output AIG manager + int nFrameMax; // maximum number of frames + int nConfMax; // maximum number of conflicts + int nTimeMax; // maximum runtime in seconds + int fVerbose; // verbose flag + // internal data + void * pUnr; // unrolling manager + Gia_Man_t * pFrames; // unrolled timeframes + Vec_Int_t * vCopies; // copy pointers of the AIG + sat_solver * pSat; // SAT solver +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Create manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ccf_Man_t * Ccf_ManStart( Gia_Man_t * pGia, int nFrameMax, int nConfMax, int nTimeMax, int fVerbose ) +{ + static Gia_ParFra_t Pars, * pPars = &Pars; + Ccf_Man_t * p; + assert( nFrameMax > 0 ); + p = ABC_CALLOC( Ccf_Man_t, 1 ); + p->pGia = pGia; + p->nFrameMax = nFrameMax; + p->nConfMax = nConfMax; + p->nTimeMax = nTimeMax; + p->fVerbose = fVerbose; + // create unrolling manager + memset( pPars, 0, sizeof(Gia_ParFra_t) ); + pPars->fVerbose = fVerbose; + pPars->nFrames = nFrameMax; + pPars->fSaveLastLit = 1; + p->pUnr = Gia_ManUnrollStart( pGia, pPars ); + p->vCopies = Vec_IntAlloc( 1000 ); + // internal data + p->pSat = sat_solver_new(); +// sat_solver_setnvars( p->pSat, 10000 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Delete manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ccf_ManStop( Ccf_Man_t * p ) +{ + Vec_IntFree( p->vCopies ); + Gia_ManUnrollStop( p->pUnr ); + sat_solver_delete( p->pSat ); + Gia_ManStopP( &p->pFrames ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [Extends the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCofExtendSolver( Ccf_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + // add SAT clauses + for ( i = sat_solver_nvars(p->pSat); i < Gia_ManObjNum(p->pFrames); i++ ) + { + pObj = Gia_ManObj( p->pFrames, i ); + if ( Gia_ObjIsAnd(pObj) ) + sat_solver_add_and( p->pSat, i, + Gia_ObjFaninId0(pObj, i), + Gia_ObjFaninId1(pObj, i), + Gia_ObjFaninC0(pObj), + Gia_ObjFaninC1(pObj), 0 ); + } + sat_solver_setnvars( p->pSat, Gia_ManObjNum(p->pFrames) ); +} + +static inline int Gia_Obj0Copy( Vec_Int_t * vCopies, int Fan0, int fCompl0 ) +{ return Abc_LitNotCond( Vec_IntEntry(vCopies, Fan0), fCompl0 ); } + +static inline int Gia_Obj1Copy( Vec_Int_t * vCopies, int Fan1, int fCompl1 ) +{ return Abc_LitNotCond( Vec_IntEntry(vCopies, Fan1), fCompl1 ); } + +/**Function************************************************************* + + Synopsis [Cofactor the circuit w.r.t. the given assignment.] + + Description [Assumes that the solver has just returned SAT.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCofOneDerive_rec( Ccf_Man_t * p, int Id ) +{ + Gia_Obj_t * pObj; + int Res; + if ( Vec_IntEntry(p->vCopies, Id) != -1 ) + return; + pObj = Gia_ManObj(p->pFrames, Id); + assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) ); + if ( Gia_ObjIsAnd(pObj) ) + { + int fCompl0 = Gia_ObjFaninC0(pObj); + int fCompl1 = Gia_ObjFaninC1(pObj); + int Fan0 = Gia_ObjFaninId0p(p->pFrames, pObj); + int Fan1 = Gia_ObjFaninId1p(p->pFrames, pObj); + Gia_ManCofOneDerive_rec( p, Fan0 ); + Gia_ManCofOneDerive_rec( p, Fan1 ); + Res = Gia_ManHashAnd( p->pFrames, + Gia_Obj0Copy(p->vCopies, Fan0, fCompl0), + Gia_Obj1Copy(p->vCopies, Fan1, fCompl1) ); + } + else if ( Gia_ObjCioId(pObj) >= Gia_ManRegNum(p->pGia) ) // PI + Res = sat_solver_var_value( p->pSat, Id ); + else + Res = Abc_Var2Lit( Id, 0 ); + Vec_IntWriteEntry( p->vCopies, Id, Res ); +} + +/**Function************************************************************* + + Synopsis [Cofactor the circuit w.r.t. the given assignment.] + + Description [Assumes that the solver has just returned SAT.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCofOneDerive( Ccf_Man_t * p, int LitProp ) +{ + int LitOut; + // derive the cofactor of the property node + Vec_IntFill( p->vCopies, Gia_ManObjNum(p->pFrames), -1 ); + Gia_ManCofOneDerive_rec( p, Abc_Lit2Var(LitProp) ); + LitOut = Vec_IntEntry( p->vCopies, Abc_Lit2Var(LitProp) ); + LitOut = Abc_LitNotCond( LitOut, Abc_LitIsCompl(LitProp) ); + // add new PO for the cofactor + Gia_ManAppendCo( p->pFrames, LitOut ); + // add SAT clauses + Gia_ManCofExtendSolver( p ); + // return negative literal of the cofactor + return Abc_LitNot(LitOut); +} + +/**Function************************************************************* + + Synopsis [Enumerates backward reachable states.] + + Description [Return -1 if resource limit is reached. Returns 1 + if computation converged (there is no more reachable states). + Returns 0 if no more states to enumerate.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCofGetReachable( Ccf_Man_t * p, int Lit ) +{ + int ObjPrev = 0, ConfPrev = 0; + int Count = 0, LitOut, RetValue; + abctime clk; + // try solving for the first time and quit if converged + RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1, p->nConfMax, 0, 0, 0 ); + if ( RetValue == l_False ) + return 1; + // iterate circuit cofactoring + while ( RetValue == l_True ) + { + clk = Abc_Clock(); + // derive cofactor + LitOut = Gia_ManCofOneDerive( p, Lit ); + // add the blocking clause + RetValue = sat_solver_addclause( p->pSat, &LitOut, &LitOut + 1 ); + assert( RetValue ); + // try solving again + RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1, p->nConfMax, 0, 0, 0 ); + // derive cofactors + if ( p->fVerbose ) + { + printf( "%3d : AIG =%7d Conf =%7d. ", Count++, + Gia_ManObjNum(p->pFrames) - ObjPrev, sat_solver_nconflicts(p->pSat) - ConfPrev ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + ObjPrev = Gia_ManObjNum(p->pFrames); + ConfPrev = sat_solver_nconflicts(p->pSat); + } + } + if ( RetValue == l_Undef ) + return -1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManCofTest( Gia_Man_t * pGia, int nFrameMax, int nConfMax, int nTimeMax, int fVerbose ) +{ + Gia_Man_t * pNew; + Ccf_Man_t * p; + Gia_Obj_t * pObj; + int f, i, Lit, RetValue = -1, fFailed = 0; + abctime nTimeToStop = Abc_Clock() + nTimeMax * CLOCKS_PER_SEC; + abctime clk = Abc_Clock(); + assert( Gia_ManPoNum(pGia) == 1 ); + + // create reachability manager + p = Ccf_ManStart( pGia, nFrameMax, nConfMax, nTimeMax, fVerbose ); + + // set runtime limit + if ( nTimeMax ) + sat_solver_set_runtime_limit( p->pSat, nTimeToStop ); + + // perform backward image computation + for ( f = 0; f < nFrameMax; f++ ) + { + if ( fVerbose ) + printf( "ITER %3d :\n", f ); + // add to the mapping of nodes + p->pFrames = (Gia_Man_t *)Gia_ManUnrollAdd( p->pUnr, f+1 ); + // add SAT clauses + Gia_ManCofExtendSolver( p ); + // return output literal + Lit = Gia_ManUnrollLastLit( p->pUnr ); + // derives cofactors of the property literal till all states are blocked + RetValue = Gia_ManCofGetReachable( p, Lit ); + if ( RetValue ) + break; + + // check the property output + Gia_ManSetPhase( p->pFrames ); + Gia_ManForEachPo( p->pFrames, pObj, i ) + if ( pObj->fPhase ) + { + printf( "Property failed in frame %d.\n", f ); + fFailed = 1; + break; + } + if ( i < Gia_ManPoNum(p->pFrames) ) + break; + } + + // report the result + if ( nTimeToStop && Abc_Clock() > nTimeToStop ) + printf( "Runtime limit (%d sec) is reached after %d frames. ", nTimeMax, f ); + else if ( f == nFrameMax ) + printf( "Completed %d frames without converging. ", f ); + else if ( RetValue == 1 ) + printf( "Backward reachability converged after %d iterations. ", f-1 ); + else if ( RetValue == -1 ) + printf( "Conflict limit or timeout is reached after %d frames. ", f-1 ); + Abc_PrintTime( 1, "Runtime", Abc_Clock() - clk ); + + if ( !fFailed && RetValue == 1 ) + printf( "Property holds.\n" ); + else if ( !fFailed ) + printf( "Property is undecided.\n" ); + + // get the resulting AIG manager + Gia_ManHashStop( p->pFrames ); + pNew = p->pFrames; p->pFrames = NULL; + Ccf_ManStop( p ); + + // cleanup +// if ( fVerbose ) +// Gia_ManPrintStats( pNew, 0 ); + pNew = Gia_ManCleanup( pGia = pNew ); + Gia_ManStop( pGia ); +// if ( fVerbose ) +// Gia_ManPrintStats( pNew, 0 ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaCSat.c b/yosys/abc/src/aig/gia/giaCSat.c new file mode 100644 index 00000000000..67b62655e0f --- /dev/null +++ b/yosys/abc/src/aig/gia/giaCSat.c @@ -0,0 +1,1143 @@ +/**CFile**************************************************************** + + FileName [giaCSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [A simple circuit-based solver.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaCSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//#define gia_assert(exp) ((void)0) +//#define gia_assert(exp) (assert(exp)) + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Cbs_Par_t_ Cbs_Par_t; +struct Cbs_Par_t_ +{ + // conflict limits + int nBTLimit; // limit on the number of conflicts + int nJustLimit; // limit on the size of justification queue + // current parameters + int nBTThis; // number of conflicts + int nBTThisNc; // number of conflicts + int nJustThis; // max size of the frontier + int nBTTotal; // total number of conflicts + int nJustTotal; // total size of the frontier + // decision heuristics + int fUseHighest; // use node with the highest ID + int fUseLowest; // use node with the highest ID + int fUseMaxFF; // use node with the largest fanin fanout + // other + int fVerbose; +}; + +typedef struct Cbs_Que_t_ Cbs_Que_t; +struct Cbs_Que_t_ +{ + int iHead; // beginning of the queue + int iTail; // end of the queue + int nSize; // allocated size + Gia_Obj_t ** pData; // nodes stored in the queue +}; + +//typedef struct Cbs_Man_t_ Cbs_Man_t; +struct Cbs_Man_t_ +{ + Cbs_Par_t Pars; // parameters + Gia_Man_t * pAig; // AIG manager + Cbs_Que_t pProp; // propagation queue + Cbs_Que_t pJust; // justification queue + Cbs_Que_t pClauses; // clause queue + Gia_Obj_t ** pIter; // iterator through clause vars + Vec_Int_t * vLevReas; // levels and decisions + Vec_Int_t * vModel; // satisfying assignment + Vec_Ptr_t * vTemp; // temporary storage + // SAT calls statistics + int nSatUnsat; // the number of proofs + int nSatSat; // the number of failure + int nSatUndec; // the number of timeouts + int nSatTotal; // the number of calls + // conflicts + int nConfUnsat; // conflicts in unsat problems + int nConfSat; // conflicts in sat problems + int nConfUndec; // conflicts in undec problems + // runtime stats + abctime timeSatUnsat; // unsat + abctime timeSatSat; // sat + abctime timeSatUndec; // undecided + abctime timeTotal; // total runtime +}; + +static inline int Cbs_VarIsAssigned( Gia_Obj_t * pVar ) { return pVar->fMark0; } +static inline void Cbs_VarAssign( Gia_Obj_t * pVar ) { assert(!pVar->fMark0); pVar->fMark0 = 1; } +static inline void Cbs_VarUnassign( Gia_Obj_t * pVar ) { assert(pVar->fMark0); pVar->fMark0 = 0; pVar->fMark1 = 0; pVar->Value = ~0; } +static inline int Cbs_VarValue( Gia_Obj_t * pVar ) { assert(pVar->fMark0); return pVar->fMark1; } +static inline void Cbs_VarSetValue( Gia_Obj_t * pVar, int v ) { assert(pVar->fMark0); pVar->fMark1 = v; } +static inline int Cbs_VarIsJust( Gia_Obj_t * pVar ) { return Gia_ObjIsAnd(pVar) && !Cbs_VarIsAssigned(Gia_ObjFanin0(pVar)) && !Cbs_VarIsAssigned(Gia_ObjFanin1(pVar)); } +static inline int Cbs_VarFanin0Value( Gia_Obj_t * pVar ) { return !Cbs_VarIsAssigned(Gia_ObjFanin0(pVar)) ? 2 : (Cbs_VarValue(Gia_ObjFanin0(pVar)) ^ Gia_ObjFaninC0(pVar)); } +static inline int Cbs_VarFanin1Value( Gia_Obj_t * pVar ) { return !Cbs_VarIsAssigned(Gia_ObjFanin1(pVar)) ? 2 : (Cbs_VarValue(Gia_ObjFanin1(pVar)) ^ Gia_ObjFaninC1(pVar)); } + +static inline int Cbs_VarDecLevel( Cbs_Man_t * p, Gia_Obj_t * pVar ) { assert( pVar->Value != ~0 ); return Vec_IntEntry(p->vLevReas, 3*pVar->Value); } +static inline Gia_Obj_t * Cbs_VarReason0( Cbs_Man_t * p, Gia_Obj_t * pVar ) { assert( pVar->Value != ~0 ); return pVar + Vec_IntEntry(p->vLevReas, 3*pVar->Value+1); } +static inline Gia_Obj_t * Cbs_VarReason1( Cbs_Man_t * p, Gia_Obj_t * pVar ) { assert( pVar->Value != ~0 ); return pVar + Vec_IntEntry(p->vLevReas, 3*pVar->Value+2); } +static inline int Cbs_ClauseDecLevel( Cbs_Man_t * p, int hClause ) { return Cbs_VarDecLevel( p, p->pClauses.pData[hClause] ); } + +#define Cbs_QueForEachEntry( Que, pObj, i ) \ + for ( i = (Que).iHead; (i < (Que).iTail) && ((pObj) = (Que).pData[i]); i++ ) + +#define Cbs_ClauseForEachVar( p, hClause, pObj ) \ + for ( (p)->pIter = (p)->pClauses.pData + hClause; (pObj = *pIter); (p)->pIter++ ) +#define Cbs_ClauseForEachVar1( p, hClause, pObj ) \ + for ( (p)->pIter = (p)->pClauses.pData+hClause+1; (pObj = *pIter); (p)->pIter++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Sets default values of the parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs_SetDefaultParams( Cbs_Par_t * pPars ) +{ + memset( pPars, 0, sizeof(Cbs_Par_t) ); + pPars->nBTLimit = 1000; // limit on the number of conflicts + pPars->nJustLimit = 100; // limit on the size of justification queue + pPars->fUseHighest = 1; // use node with the highest ID + pPars->fUseLowest = 0; // use node with the highest ID + pPars->fUseMaxFF = 0; // use node with the largest fanin fanout + pPars->fVerbose = 1; // print detailed statistics +} +void Cbs_ManSetConflictNum( Cbs_Man_t * p, int Num ) +{ + p->Pars.nBTLimit = Num; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cbs_Man_t * Cbs_ManAlloc( Gia_Man_t * pGia ) +{ + Cbs_Man_t * p; + p = ABC_CALLOC( Cbs_Man_t, 1 ); + p->pProp.nSize = p->pJust.nSize = p->pClauses.nSize = 10000; + p->pProp.pData = ABC_ALLOC( Gia_Obj_t *, p->pProp.nSize ); + p->pJust.pData = ABC_ALLOC( Gia_Obj_t *, p->pJust.nSize ); + p->pClauses.pData = ABC_ALLOC( Gia_Obj_t *, p->pClauses.nSize ); + p->pClauses.iHead = p->pClauses.iTail = 1; + p->vModel = Vec_IntAlloc( 1000 ); + p->vLevReas = Vec_IntAlloc( 1000 ); + p->vTemp = Vec_PtrAlloc( 1000 ); + p->pAig = pGia; + Cbs_SetDefaultParams( &p->Pars ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs_ManStop( Cbs_Man_t * p ) +{ + Vec_IntFree( p->vLevReas ); + Vec_IntFree( p->vModel ); + Vec_PtrFree( p->vTemp ); + ABC_FREE( p->pClauses.pData ); + ABC_FREE( p->pProp.pData ); + ABC_FREE( p->pJust.pData ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Returns satisfying assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Cbs_ReadModel( Cbs_Man_t * p ) +{ + return p->vModel; +} + + + + +/**Function************************************************************* + + Synopsis [Returns 1 if the solver is out of limits.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs_ManCheckLimits( Cbs_Man_t * p ) +{ + return p->Pars.nJustThis > p->Pars.nJustLimit || p->Pars.nBTThis > p->Pars.nBTLimit; +} + +/**Function************************************************************* + + Synopsis [Saves the satisfying assignment as an array of literals.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs_ManSaveModel( Cbs_Man_t * p, Vec_Int_t * vCex ) +{ + Gia_Obj_t * pVar; + int i; + Vec_IntClear( vCex ); + p->pProp.iHead = 0; + Cbs_QueForEachEntry( p->pProp, pVar, i ) + if ( Gia_ObjIsCi(pVar) ) +// Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjId(p->pAig,pVar), !Cbs_VarValue(pVar)) ); + Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjCioId(pVar), !Cbs_VarValue(pVar)) ); +} +static inline void Cbs_ManSaveModelAll( Cbs_Man_t * p, Vec_Int_t * vCex ) +{ + Gia_Obj_t * pVar; + int i; + Vec_IntClear( vCex ); + p->pProp.iHead = 0; + Cbs_QueForEachEntry( p->pProp, pVar, i ) + Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjId(p->pAig,pVar), !Cbs_VarValue(pVar)) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs_QueIsEmpty( Cbs_Que_t * p ) +{ + return p->iHead == p->iTail; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs_QuePush( Cbs_Que_t * p, Gia_Obj_t * pObj ) +{ + assert( !Gia_IsComplement(pObj) ); + if ( p->iTail == p->nSize ) + { + p->nSize *= 2; + p->pData = ABC_REALLOC( Gia_Obj_t *, p->pData, p->nSize ); + } + p->pData[p->iTail++] = pObj; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the object in the queue.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs_QueHasNode( Cbs_Que_t * p, Gia_Obj_t * pObj ) +{ + Gia_Obj_t * pTemp; + int i; + Cbs_QueForEachEntry( *p, pTemp, i ) + if ( pTemp == pObj ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs_QueStore( Cbs_Que_t * p, int * piHeadOld, int * piTailOld ) +{ + int i; + *piHeadOld = p->iHead; + *piTailOld = p->iTail; + for ( i = *piHeadOld; i < *piTailOld; i++ ) + Cbs_QuePush( p, p->pData[i] ); + p->iHead = *piTailOld; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs_QueRestore( Cbs_Que_t * p, int iHeadOld, int iTailOld ) +{ + p->iHead = iHeadOld; + p->iTail = iTailOld; +} + +/**Function************************************************************* + + Synopsis [Finalized the clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs_QueFinish( Cbs_Que_t * p ) +{ + int iHeadOld = p->iHead; + assert( p->iHead < p->iTail ); + Cbs_QuePush( p, NULL ); + p->iHead = p->iTail; + return iHeadOld; +} + + +/**Function************************************************************* + + Synopsis [Max number of fanins fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs_VarFaninFanoutMax( Cbs_Man_t * p, Gia_Obj_t * pObj ) +{ + int Count0, Count1; + assert( !Gia_IsComplement(pObj) ); + assert( Gia_ObjIsAnd(pObj) ); + Count0 = Gia_ObjRefNum( p->pAig, Gia_ObjFanin0(pObj) ); + Count1 = Gia_ObjRefNum( p->pAig, Gia_ObjFanin1(pObj) ); + return Abc_MaxInt( Count0, Count1 ); +} + +/**Function************************************************************* + + Synopsis [Find variable with the highest ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * Cbs_ManDecideHighest( Cbs_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjMax = NULL; + int i; + Cbs_QueForEachEntry( p->pJust, pObj, i ) + if ( pObjMax == NULL || pObjMax < pObj ) + pObjMax = pObj; + return pObjMax; +} + +/**Function************************************************************* + + Synopsis [Find variable with the lowest ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * Cbs_ManDecideLowest( Cbs_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjMin = NULL; + int i; + Cbs_QueForEachEntry( p->pJust, pObj, i ) + if ( pObjMin == NULL || pObjMin > pObj ) + pObjMin = pObj; + return pObjMin; +} + +/**Function************************************************************* + + Synopsis [Find variable with the maximum number of fanin fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * Cbs_ManDecideMaxFF( Cbs_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjMax = NULL; + int i, iMaxFF = 0, iCurFF; + assert( p->pAig->pRefs != NULL ); + Cbs_QueForEachEntry( p->pJust, pObj, i ) + { + iCurFF = Cbs_VarFaninFanoutMax( p, pObj ); + assert( iCurFF > 0 ); + if ( iMaxFF < iCurFF ) + { + iMaxFF = iCurFF; + pObjMax = pObj; + } + } + return pObjMax; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs_ManCancelUntil( Cbs_Man_t * p, int iBound ) +{ + Gia_Obj_t * pVar; + int i; + assert( iBound <= p->pProp.iTail ); + p->pProp.iHead = iBound; + Cbs_QueForEachEntry( p->pProp, pVar, i ) + Cbs_VarUnassign( pVar ); + p->pProp.iTail = iBound; + Vec_IntShrink( p->vLevReas, 3*iBound ); +} + +int s_Counter = 0; + +/**Function************************************************************* + + Synopsis [Assigns the variables a value.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs_ManAssign( Cbs_Man_t * p, Gia_Obj_t * pObj, int Level, Gia_Obj_t * pRes0, Gia_Obj_t * pRes1 ) +{ + Gia_Obj_t * pObjR = Gia_Regular(pObj); + assert( Gia_ObjIsCand(pObjR) ); + assert( !Cbs_VarIsAssigned(pObjR) ); + Cbs_VarAssign( pObjR ); + Cbs_VarSetValue( pObjR, !Gia_IsComplement(pObj) ); + assert( pObjR->Value == ~0 ); + pObjR->Value = p->pProp.iTail; + Cbs_QuePush( &p->pProp, pObjR ); + Vec_IntPush( p->vLevReas, Level ); + Vec_IntPush( p->vLevReas, pRes0 ? pRes0-pObjR : 0 ); + Vec_IntPush( p->vLevReas, pRes1 ? pRes1-pObjR : 0 ); + assert( Vec_IntSize(p->vLevReas) == 3 * p->pProp.iTail ); +// s_Counter++; +// s_Counter = Abc_MaxIntInt( s_Counter, Vec_IntSize(p->vLevReas)/3 ); +} + + +/**Function************************************************************* + + Synopsis [Returns clause size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs_ManClauseSize( Cbs_Man_t * p, int hClause ) +{ + Cbs_Que_t * pQue = &(p->pClauses); + Gia_Obj_t ** pIter; + for ( pIter = pQue->pData + hClause; *pIter; pIter++ ); + return pIter - pQue->pData - hClause ; +} + +/**Function************************************************************* + + Synopsis [Prints conflict clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs_ManPrintClause( Cbs_Man_t * p, int Level, int hClause ) +{ + Cbs_Que_t * pQue = &(p->pClauses); + Gia_Obj_t * pObj; + int i; + assert( Cbs_QueIsEmpty( pQue ) ); + printf( "Level %2d : ", Level ); + for ( i = hClause; (pObj = pQue->pData[i]); i++ ) + printf( "%d=%d(%d) ", Gia_ObjId(p->pAig, pObj), Cbs_VarValue(pObj), Cbs_VarDecLevel(p, pObj) ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints conflict clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs_ManPrintClauseNew( Cbs_Man_t * p, int Level, int hClause ) +{ + Cbs_Que_t * pQue = &(p->pClauses); + Gia_Obj_t * pObj; + int i; + assert( Cbs_QueIsEmpty( pQue ) ); + printf( "Level %2d : ", Level ); + for ( i = hClause; (pObj = pQue->pData[i]); i++ ) + printf( "%c%d ", Cbs_VarValue(pObj)? '+':'-', Gia_ObjId(p->pAig, pObj) ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Returns conflict clause.] + + Description [Performs conflict analysis.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs_ManDeriveReason( Cbs_Man_t * p, int Level ) +{ + Cbs_Que_t * pQue = &(p->pClauses); + Gia_Obj_t * pObj, * pReason; + int i, k, iLitLevel; + assert( pQue->pData[pQue->iHead] == NULL ); + assert( pQue->iHead + 1 < pQue->iTail ); +/* + for ( i = pQue->iHead + 1; i < pQue->iTail; i++ ) + { + pObj = pQue->pData[i]; + assert( pObj->fMark0 == 1 ); + } +*/ + // compact literals + Vec_PtrClear( p->vTemp ); + for ( i = k = pQue->iHead + 1; i < pQue->iTail; i++ ) + { + pObj = pQue->pData[i]; + if ( !pObj->fMark0 ) // unassigned - seen again + continue; + // assigned - seen first time + pObj->fMark0 = 0; + Vec_PtrPush( p->vTemp, pObj ); + // check decision level + iLitLevel = Cbs_VarDecLevel( p, pObj ); + if ( iLitLevel < Level ) + { + pQue->pData[k++] = pObj; + continue; + } + assert( iLitLevel == Level ); + pReason = Cbs_VarReason0( p, pObj ); + if ( pReason == pObj ) // no reason + { + //assert( pQue->pData[pQue->iHead] == NULL ); + pQue->pData[pQue->iHead] = pObj; + continue; + } + Cbs_QuePush( pQue, pReason ); + pReason = Cbs_VarReason1( p, pObj ); + if ( pReason != pObj ) // second reason + Cbs_QuePush( pQue, pReason ); + } + assert( pQue->pData[pQue->iHead] != NULL ); + pQue->iTail = k; + // clear the marks + Vec_PtrForEachEntry( Gia_Obj_t *, p->vTemp, pObj, i ) + pObj->fMark0 = 1; +} + +/**Function************************************************************* + + Synopsis [Returns conflict clause.] + + Description [Performs conflict analysis.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs_ManAnalyze( Cbs_Man_t * p, int Level, Gia_Obj_t * pVar, Gia_Obj_t * pFan0, Gia_Obj_t * pFan1 ) +{ + Cbs_Que_t * pQue = &(p->pClauses); + assert( Cbs_VarIsAssigned(pVar) ); + assert( Cbs_VarIsAssigned(pFan0) ); + assert( pFan1 == NULL || Cbs_VarIsAssigned(pFan1) ); + assert( Cbs_QueIsEmpty( pQue ) ); + Cbs_QuePush( pQue, NULL ); + Cbs_QuePush( pQue, pVar ); + Cbs_QuePush( pQue, pFan0 ); + if ( pFan1 ) + Cbs_QuePush( pQue, pFan1 ); + Cbs_ManDeriveReason( p, Level ); + return Cbs_QueFinish( pQue ); +} + + +/**Function************************************************************* + + Synopsis [Performs resolution of two clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs_ManResolve( Cbs_Man_t * p, int Level, int hClause0, int hClause1 ) +{ + Cbs_Que_t * pQue = &(p->pClauses); + Gia_Obj_t * pObj; + int i, LevelMax = -1, LevelCur; + assert( pQue->pData[hClause0] != NULL ); + assert( pQue->pData[hClause0] == pQue->pData[hClause1] ); +/* + for ( i = hClause0 + 1; (pObj = pQue->pData[i]); i++ ) + assert( pObj->fMark0 == 1 ); + for ( i = hClause1 + 1; (pObj = pQue->pData[i]); i++ ) + assert( pObj->fMark0 == 1 ); +*/ + assert( Cbs_QueIsEmpty( pQue ) ); + Cbs_QuePush( pQue, NULL ); + for ( i = hClause0 + 1; (pObj = pQue->pData[i]); i++ ) + { + if ( !pObj->fMark0 ) // unassigned - seen again + continue; + // assigned - seen first time + pObj->fMark0 = 0; + Cbs_QuePush( pQue, pObj ); + LevelCur = Cbs_VarDecLevel( p, pObj ); + if ( LevelMax < LevelCur ) + LevelMax = LevelCur; + } + for ( i = hClause1 + 1; (pObj = pQue->pData[i]); i++ ) + { + if ( !pObj->fMark0 ) // unassigned - seen again + continue; + // assigned - seen first time + pObj->fMark0 = 0; + Cbs_QuePush( pQue, pObj ); + LevelCur = Cbs_VarDecLevel( p, pObj ); + if ( LevelMax < LevelCur ) + LevelMax = LevelCur; + } + for ( i = pQue->iHead + 1; i < pQue->iTail; i++ ) + pQue->pData[i]->fMark0 = 1; + Cbs_ManDeriveReason( p, LevelMax ); + return Cbs_QueFinish( pQue ); +} + +/**Function************************************************************* + + Synopsis [Propagates a variable.] + + Description [Returns clause handle if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs_ManPropagateOne( Cbs_Man_t * p, Gia_Obj_t * pVar, int Level ) +{ + int Value0, Value1; + assert( !Gia_IsComplement(pVar) ); + assert( Cbs_VarIsAssigned(pVar) ); + if ( Gia_ObjIsCi(pVar) ) + return 0; + assert( Gia_ObjIsAnd(pVar) ); + Value0 = Cbs_VarFanin0Value(pVar); + Value1 = Cbs_VarFanin1Value(pVar); + if ( Cbs_VarValue(pVar) ) + { // value is 1 + if ( Value0 == 0 || Value1 == 0 ) // one is 0 + { + if ( Value0 == 0 && Value1 != 0 ) + return Cbs_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), NULL ); + if ( Value0 != 0 && Value1 == 0 ) + return Cbs_ManAnalyze( p, Level, pVar, Gia_ObjFanin1(pVar), NULL ); + assert( Value0 == 0 && Value1 == 0 ); + return Cbs_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), Gia_ObjFanin1(pVar) ); + } + if ( Value0 == 2 ) // first is unassigned + Cbs_ManAssign( p, Gia_ObjChild0(pVar), Level, pVar, NULL ); + if ( Value1 == 2 ) // first is unassigned + Cbs_ManAssign( p, Gia_ObjChild1(pVar), Level, pVar, NULL ); + return 0; + } + // value is 0 + if ( Value0 == 0 || Value1 == 0 ) // one is 0 + return 0; + if ( Value0 == 1 && Value1 == 1 ) // both are 1 + return Cbs_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), Gia_ObjFanin1(pVar) ); + if ( Value0 == 1 || Value1 == 1 ) // one is 1 + { + if ( Value0 == 2 ) // first is unassigned + Cbs_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)), Level, pVar, Gia_ObjFanin1(pVar) ); + if ( Value1 == 2 ) // second is unassigned + Cbs_ManAssign( p, Gia_Not(Gia_ObjChild1(pVar)), Level, pVar, Gia_ObjFanin0(pVar) ); + return 0; + } + assert( Cbs_VarIsJust(pVar) ); + assert( !Cbs_QueHasNode( &p->pJust, pVar ) ); + Cbs_QuePush( &p->pJust, pVar ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Propagates a variable.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs_ManPropagateTwo( Cbs_Man_t * p, Gia_Obj_t * pVar, int Level ) +{ + int Value0, Value1; + assert( !Gia_IsComplement(pVar) ); + assert( Gia_ObjIsAnd(pVar) ); + assert( Cbs_VarIsAssigned(pVar) ); + assert( !Cbs_VarValue(pVar) ); + Value0 = Cbs_VarFanin0Value(pVar); + Value1 = Cbs_VarFanin1Value(pVar); + // value is 0 + if ( Value0 == 0 || Value1 == 0 ) // one is 0 + return 0; + if ( Value0 == 1 && Value1 == 1 ) // both are 1 + return Cbs_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), Gia_ObjFanin1(pVar) ); + assert( Value0 == 1 || Value1 == 1 ); + if ( Value0 == 2 ) // first is unassigned + Cbs_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)), Level, pVar, Gia_ObjFanin1(pVar) ); + if ( Value1 == 2 ) // first is unassigned + Cbs_ManAssign( p, Gia_Not(Gia_ObjChild1(pVar)), Level, pVar, Gia_ObjFanin0(pVar) ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Propagates all variables.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cbs_ManPropagate( Cbs_Man_t * p, int Level ) +{ + int hClause; + Gia_Obj_t * pVar; + int i, k; + while ( 1 ) + { + Cbs_QueForEachEntry( p->pProp, pVar, i ) + { + if ( (hClause = Cbs_ManPropagateOne( p, pVar, Level )) ) + return hClause; + } + p->pProp.iHead = p->pProp.iTail; + k = p->pJust.iHead; + Cbs_QueForEachEntry( p->pJust, pVar, i ) + { + if ( Cbs_VarIsJust( pVar ) ) + p->pJust.pData[k++] = pVar; + else if ( (hClause = Cbs_ManPropagateTwo( p, pVar, Level )) ) + return hClause; + } + if ( k == p->pJust.iTail ) + break; + p->pJust.iTail = k; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Solve the problem recursively.] + + Description [Returns learnt clause if unsat, NULL if sat or undecided.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cbs_ManSolve_rec( Cbs_Man_t * p, int Level ) +{ + Cbs_Que_t * pQue = &(p->pClauses); + Gia_Obj_t * pVar = NULL, * pDecVar; + int hClause, hLearn0, hLearn1; + int iPropHead, iJustHead, iJustTail; + // propagate assignments + assert( !Cbs_QueIsEmpty(&p->pProp) ); + if ( (hClause = Cbs_ManPropagate( p, Level )) ) + return hClause; + // check for satisfying assignment + assert( Cbs_QueIsEmpty(&p->pProp) ); + if ( Cbs_QueIsEmpty(&p->pJust) ) + return 0; + // quit using resource limits + p->Pars.nJustThis = Abc_MaxInt( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead ); + if ( Cbs_ManCheckLimits( p ) ) + return 0; + // remember the state before branching + iPropHead = p->pProp.iHead; + Cbs_QueStore( &p->pJust, &iJustHead, &iJustTail ); + // find the decision variable + if ( p->Pars.fUseHighest ) + pVar = Cbs_ManDecideHighest( p ); + else if ( p->Pars.fUseLowest ) + pVar = Cbs_ManDecideLowest( p ); + else if ( p->Pars.fUseMaxFF ) + pVar = Cbs_ManDecideMaxFF( p ); + else assert( 0 ); + assert( Cbs_VarIsJust( pVar ) ); + // chose decision variable using fanout count + if ( Gia_ObjRefNum(p->pAig, Gia_ObjFanin0(pVar)) > Gia_ObjRefNum(p->pAig, Gia_ObjFanin1(pVar)) ) + pDecVar = Gia_Not(Gia_ObjChild0(pVar)); + else + pDecVar = Gia_Not(Gia_ObjChild1(pVar)); +// pDecVar = Gia_NotCond( Gia_Regular(pDecVar), Gia_Regular(pDecVar)->fPhase ); +// pDecVar = Gia_Not(pDecVar); + // decide on first fanin + Cbs_ManAssign( p, pDecVar, Level+1, NULL, NULL ); + if ( !(hLearn0 = Cbs_ManSolve_rec( p, Level+1 )) ) + return 0; + if ( pQue->pData[hLearn0] != Gia_Regular(pDecVar) ) + return hLearn0; + Cbs_ManCancelUntil( p, iPropHead ); + Cbs_QueRestore( &p->pJust, iJustHead, iJustTail ); + // decide on second fanin + Cbs_ManAssign( p, Gia_Not(pDecVar), Level+1, NULL, NULL ); + if ( !(hLearn1 = Cbs_ManSolve_rec( p, Level+1 )) ) + return 0; + if ( pQue->pData[hLearn1] != Gia_Regular(pDecVar) ) + return hLearn1; + hClause = Cbs_ManResolve( p, Level, hLearn0, hLearn1 ); +// Cbs_ManPrintClauseNew( p, Level, hClause ); +// if ( Level > Cbs_ClauseDecLevel(p, hClause) ) +// p->Pars.nBTThisNc++; + p->Pars.nBTThis++; + return hClause; +} + +/**Function************************************************************* + + Synopsis [Looking for a satisfying assignment of the node.] + + Description [Assumes that each node has flag pObj->fMark0 set to 0. + Returns 1 if unsatisfiable, 0 if satisfiable, and -1 if undecided. + The node may be complemented. ] + + SideEffects [The two procedures differ in the CEX format.] + + SeeAlso [] + +***********************************************************************/ +int Cbs_ManSolve( Cbs_Man_t * p, Gia_Obj_t * pObj ) +{ + int RetValue = 0; + s_Counter = 0; + assert( !p->pProp.iHead && !p->pProp.iTail ); + assert( !p->pJust.iHead && !p->pJust.iTail ); + assert( p->pClauses.iHead == 1 && p->pClauses.iTail == 1 ); + p->Pars.nBTThis = p->Pars.nJustThis = p->Pars.nBTThisNc = 0; + Cbs_ManAssign( p, pObj, 0, NULL, NULL ); + if ( !Cbs_ManSolve_rec(p, 0) && !Cbs_ManCheckLimits(p) ) + Cbs_ManSaveModel( p, p->vModel ); + else + RetValue = 1; + Cbs_ManCancelUntil( p, 0 ); + p->pJust.iHead = p->pJust.iTail = 0; + p->pClauses.iHead = p->pClauses.iTail = 1; + p->Pars.nBTTotal += p->Pars.nBTThis; + p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis ); + if ( Cbs_ManCheckLimits( p ) ) + RetValue = -1; +// printf( "%d ", s_Counter ); + return RetValue; +} +int Cbs_ManSolve2( Cbs_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pObj2 ) +{ + int RetValue = 0; + s_Counter = 0; + assert( !p->pProp.iHead && !p->pProp.iTail ); + assert( !p->pJust.iHead && !p->pJust.iTail ); + assert( p->pClauses.iHead == 1 && p->pClauses.iTail == 1 ); + p->Pars.nBTThis = p->Pars.nJustThis = p->Pars.nBTThisNc = 0; + Cbs_ManAssign( p, pObj, 0, NULL, NULL ); + if ( pObj2 ) + Cbs_ManAssign( p, pObj2, 0, NULL, NULL ); + if ( !Cbs_ManSolve_rec(p, 0) && !Cbs_ManCheckLimits(p) ) + Cbs_ManSaveModelAll( p, p->vModel ); + else + RetValue = 1; + Cbs_ManCancelUntil( p, 0 ); + p->pJust.iHead = p->pJust.iTail = 0; + p->pClauses.iHead = p->pClauses.iTail = 1; + p->Pars.nBTTotal += p->Pars.nBTThis; + p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis ); + if ( Cbs_ManCheckLimits( p ) ) + RetValue = -1; +// printf( "%d ", s_Counter ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Prints statistics of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs_ManSatPrintStats( Cbs_Man_t * p ) +{ + printf( "CO = %8d ", Gia_ManCoNum(p->pAig) ); + printf( "AND = %8d ", Gia_ManAndNum(p->pAig) ); + printf( "Conf = %6d ", p->Pars.nBTLimit ); + printf( "JustMax = %5d ", p->Pars.nJustLimit ); + printf( "\n" ); + printf( "Unsat calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatUnsat, p->nSatTotal? 100.0*p->nSatUnsat/p->nSatTotal :0.0, p->nSatUnsat? 1.0*p->nConfUnsat/p->nSatUnsat :0.0 ); + ABC_PRTP( "Time", p->timeSatUnsat, p->timeTotal ); + printf( "Sat calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatSat, p->nSatTotal? 100.0*p->nSatSat/p->nSatTotal :0.0, p->nSatSat? 1.0*p->nConfSat/p->nSatSat : 0.0 ); + ABC_PRTP( "Time", p->timeSatSat, p->timeTotal ); + printf( "Undef calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatUndec, p->nSatTotal? 100.0*p->nSatUndec/p->nSatTotal :0.0, p->nSatUndec? 1.0*p->nConfUndec/p->nSatUndec : 0.0 ); + ABC_PRTP( "Time", p->timeSatUndec, p->timeTotal ); + ABC_PRT( "Total time", p->timeTotal ); +} + +/**Function************************************************************* + + Synopsis [Procedure to test the new SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Cbs_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int f0Proved, int fVerbose ) +{ + extern void Gia_ManCollectTest( Gia_Man_t * pAig ); + extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out ); + Cbs_Man_t * p; + Vec_Int_t * vCex, * vVisit, * vCexStore; + Vec_Str_t * vStatus; + Gia_Obj_t * pRoot; + int i, status; + abctime clk, clkTotal = Abc_Clock(); + assert( Gia_ManRegNum(pAig) == 0 ); +// Gia_ManCollectTest( pAig ); + // prepare AIG + Gia_ManCreateRefs( pAig ); + Gia_ManCleanMark0( pAig ); + Gia_ManCleanMark1( pAig ); + Gia_ManFillValue( pAig ); // maps nodes into trail ids + Gia_ManSetPhase( pAig ); // maps nodes into trail ids + // create logic network + p = Cbs_ManAlloc( pAig ); + p->Pars.nBTLimit = nConfs; + // create resulting data-structures + vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) ); + vCexStore = Vec_IntAlloc( 10000 ); + vVisit = Vec_IntAlloc( 100 ); + vCex = Cbs_ReadModel( p ); + // solve for each output + Gia_ManForEachCo( pAig, pRoot, i ) + { +// printf( "\n" ); + + Vec_IntClear( vCex ); + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pRoot)) ) + { + if ( Gia_ObjFaninC0(pRoot) ) + { +// printf( "Constant 1 output of SRM!!!\n" ); + Cec_ManSatAddToStore( vCexStore, vCex, i ); // trivial counter-example + Vec_StrPush( vStatus, 0 ); + } + else + { +// printf( "Constant 0 output of SRM!!!\n" ); + Vec_StrPush( vStatus, 1 ); + } + continue; + } + clk = Abc_Clock(); + p->Pars.fUseHighest = 1; + p->Pars.fUseLowest = 0; + status = Cbs_ManSolve( p, Gia_ObjChild0(pRoot) ); +// printf( "\n" ); +/* + if ( status == -1 ) + { + p->Pars.fUseHighest = 0; + p->Pars.fUseLowest = 1; + status = Cbs_ManSolve( p, Gia_ObjChild0(pRoot) ); + } +*/ + Vec_StrPush( vStatus, (char)status ); + if ( status == -1 ) + { + p->nSatUndec++; + p->nConfUndec += p->Pars.nBTThis; + Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout + p->timeSatUndec += Abc_Clock() - clk; + continue; + } + if ( status == 1 ) + { + if ( f0Proved ) + Gia_ManPatchCoDriver( pAig, i, 0 ); + p->nSatUnsat++; + p->nConfUnsat += p->Pars.nBTThis; + p->timeSatUnsat += Abc_Clock() - clk; + continue; + } + p->nSatSat++; + p->nConfSat += p->Pars.nBTThis; +// Gia_SatVerifyPattern( pAig, pRoot, vCex, vVisit ); + Cec_ManSatAddToStore( vCexStore, vCex, i ); + p->timeSatSat += Abc_Clock() - clk; + } + Vec_IntFree( vVisit ); + p->nSatTotal = Gia_ManPoNum(pAig); + p->timeTotal = Abc_Clock() - clkTotal; + if ( fVerbose ) + Cbs_ManSatPrintStats( p ); +// printf( "RecCalls = %8d. RecClause = %8d. RecNonChro = %8d.\n", p->nRecCall, p->nRecClause, p->nRecNonChro ); + Cbs_ManStop( p ); + *pvStatus = vStatus; + +// printf( "Total number of cex literals = %d. (Ave = %d)\n", +// Vec_IntSize(vCexStore)-2*p->nSatUndec-2*p->nSatSat, +// (Vec_IntSize(vCexStore)-2*p->nSatUndec-2*p->nSatSat)/p->nSatSat ); + return vCexStore; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaCSat2.c b/yosys/abc/src/aig/gia/giaCSat2.c new file mode 100644 index 00000000000..a9739e0287f --- /dev/null +++ b/yosys/abc/src/aig/gia/giaCSat2.c @@ -0,0 +1,1679 @@ +/**CFile**************************************************************** + + FileName [giaCSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [A simple circuit-based solver.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaCSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//#define gia_assert(exp) ((void)0) +//#define gia_assert(exp) (assert(exp)) + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Cbs2_Par_t_ Cbs2_Par_t; +struct Cbs2_Par_t_ +{ + // conflict limits + int nBTLimit; // limit on the number of conflicts + int nJustLimit; // limit on the size of justification queue + // current parameters + int nBTThis; // number of conflicts + int nBTThisNc; // number of conflicts + int nJustThis; // max size of the frontier + int nBTTotal; // total number of conflicts + int nJustTotal; // total size of the frontier + // decision heuristics + int fUseHighest; // use node with the highest ID + int fUseLowest; // use node with the highest ID + int fUseMaxFF; // use node with the largest fanin fanout + int fUseFanout; // use node with the largest fanin fanout + // other + int fVerbose; +}; + +typedef struct Cbs2_Que_t_ Cbs2_Que_t; +struct Cbs2_Que_t_ +{ + int iHead; // beginning of the queue + int iTail; // end of the queue + int nSize; // allocated size + int * pData; // nodes stored in the queue +}; + +typedef struct Cbs2_Man_t_ Cbs2_Man_t; +struct Cbs2_Man_t_ +{ + Cbs2_Par_t Pars; // parameters + Gia_Man_t * pAig; // AIG manager + Cbs2_Que_t pProp; // propagation queue + Cbs2_Que_t pJust; // justification queue + Cbs2_Que_t pClauses; // clause queue + Vec_Int_t * vModel; // satisfying assignment + Vec_Int_t * vTemp; // temporary storage + // internal data + Vec_Str_t vAssign; + Vec_Str_t vMark; + Vec_Int_t vLevReason; + Vec_Int_t vWatches; + Vec_Int_t vWatchUpds; + Vec_Int_t vFanoutN; + Vec_Int_t vFanout0; + Vec_Int_t vActivity; + Vec_Int_t vActStore; + Vec_Int_t vJStore; + // SAT calls statistics + int nSatUnsat; // the number of proofs + int nSatSat; // the number of failure + int nSatUndec; // the number of timeouts + int nSatTotal; // the number of calls + // conflicts + int nConfUnsat; // conflicts in unsat problems + int nConfSat; // conflicts in sat problems + int nConfUndec; // conflicts in undec problems + // runtime stats + abctime timeJFront; + abctime timeSatUnsat; // unsat + abctime timeSatSat; // sat + abctime timeSatUndec; // undecided + abctime timeTotal; // total runtime + // other statistics + int nPropCalls[3]; + int nFails[2]; + int nClauseConf; +}; + +static inline int Cbs2_VarUnused( Cbs2_Man_t * p, int iVar ) { return Vec_IntEntry(&p->vLevReason, 3*iVar) == -1; } +static inline void Cbs2_VarSetUnused( Cbs2_Man_t * p, int iVar ) { Vec_IntWriteEntry(&p->vLevReason, 3*iVar, -1); } + +/* +static inline int Cbs2_VarMark0( Cbs2_Man_t * p, int iVar ) { return Vec_StrEntry(&p->vAssign, iVar); } +static inline void Cbs2_VarSetMark0( Cbs2_Man_t * p, int iVar, int Value ) { Vec_StrWriteEntry(&p->vAssign, iVar, (char)Value); } + +static inline int Cbs2_VarMark1( Cbs2_Man_t * p, int iVar ) { return Vec_StrEntry(&p->vValue, iVar); } +static inline void Cbs2_VarSetMark1( Cbs2_Man_t * p, int iVar, int Value ) { Vec_StrWriteEntry(&p->vValue, iVar, (char)Value); } + +static inline int Cbs2_VarIsAssigned( Cbs2_Man_t * p, int iVar ) { return Cbs2_VarMark0(p, iVar); } +static inline void Cbs2_VarAssign( Cbs2_Man_t * p, int iVar ) { assert(!Cbs2_VarIsAssigned(p, iVar)); Cbs2_VarSetMark0(p, iVar, 1); } +static inline void Cbs2_VarUnassign( Cbs2_Man_t * p, int iVar ) { assert( Cbs2_VarIsAssigned(p, iVar)); Cbs2_VarSetMark0(p, iVar, 0); Cbs2_VarSetUnused(p, iVar); } +static inline int Cbs2_VarValue( Cbs2_Man_t * p, int iVar ) { assert( Cbs2_VarIsAssigned(p, iVar)); return Cbs2_VarMark1(p, iVar); } +static inline void Cbs2_VarSetValue( Cbs2_Man_t * p, int iVar, int v ) { assert( Cbs2_VarIsAssigned(p, iVar)); Cbs2_VarSetMark1(p, iVar, v); } + +static inline int Cbs2_VarIsJust( Cbs2_Man_t * p, Gia_Obj_t * pVar, int iVar ) { return Gia_ObjIsAnd(pVar) && !Cbs2_VarIsAssigned(p, Gia_ObjFaninId0(pVar, iVar)) && !Cbs2_VarIsAssigned(p, Gia_ObjFaninId1(pVar, iVar)); } +static inline int Cbs2_VarFanin0Value( Cbs2_Man_t * p, Gia_Obj_t * pVar, int iVar ) { return Cbs2_VarIsAssigned(p, Gia_ObjFaninId0(pVar, iVar)) ? (Cbs2_VarValue(p, Gia_ObjFaninId0(pVar, iVar)) ^ Gia_ObjFaninC0(pVar)) : 2; } +static inline int Cbs2_VarFanin1Value( Cbs2_Man_t * p, Gia_Obj_t * pVar, int iVar ) { return Cbs2_VarIsAssigned(p, Gia_ObjFaninId1(pVar, iVar)) ? (Cbs2_VarValue(p, Gia_ObjFaninId1(pVar, iVar)) ^ Gia_ObjFaninC1(pVar)) : 2; } +*/ + +static inline int Cbs2_VarMark0( Cbs2_Man_t * p, int iVar ) { return Vec_StrEntry(&p->vMark, iVar); } +static inline void Cbs2_VarSetMark0( Cbs2_Man_t * p, int iVar, int Value ) { Vec_StrWriteEntry(&p->vMark, iVar, (char)Value); } + +//static inline int Cbs2_VarMark0( Cbs2_Man_t * p, int iVar ) { return Vec_StrEntry(&p->vAssign, iVar) >= 2; } +//static inline void Cbs2_VarSetMark0( Cbs2_Man_t * p, int iVar, int Value ) { Vec_StrWriteEntry(&p->vAssign, iVar, (char)(2^Vec_StrEntry(&p->vAssign, iVar))); } + +static inline int Cbs2_VarIsAssigned( Cbs2_Man_t * p, int iVar ) { return Vec_StrEntry(&p->vAssign, iVar) < 2; } +static inline void Cbs2_VarUnassign( Cbs2_Man_t * p, int iVar ) { assert( Cbs2_VarIsAssigned(p, iVar)); Vec_StrWriteEntry(&p->vAssign, iVar, (char)(2+Vec_StrEntry(&p->vAssign, iVar))); Cbs2_VarSetUnused(p, iVar); } + +static inline int Cbs2_VarValue( Cbs2_Man_t * p, int iVar ) { return Vec_StrEntry(&p->vAssign, iVar); } +static inline void Cbs2_VarSetValue( Cbs2_Man_t * p, int iVar, int v ) { assert( !Cbs2_VarIsAssigned(p, iVar)); Vec_StrWriteEntry(&p->vAssign, iVar, (char)v); } + +static inline int Cbs2_VarIsJust( Cbs2_Man_t * p, Gia_Obj_t * pVar, int iVar ) { return Gia_ObjIsAnd(pVar) && !Cbs2_VarIsAssigned(p, Gia_ObjFaninId0(pVar, iVar)) && !Cbs2_VarIsAssigned(p, Gia_ObjFaninId1(pVar, iVar)); } +static inline int Cbs2_VarFanin0Value( Cbs2_Man_t * p, Gia_Obj_t * pVar, int iVar ) { return Cbs2_VarValue(p, Gia_ObjFaninId0(pVar, iVar)) ^ Gia_ObjFaninC0(pVar); } +static inline int Cbs2_VarFanin1Value( Cbs2_Man_t * p, Gia_Obj_t * pVar, int iVar ) { return Cbs2_VarValue(p, Gia_ObjFaninId1(pVar, iVar)) ^ Gia_ObjFaninC1(pVar); } + + +static inline int Cbs2_VarDecLevel( Cbs2_Man_t * p, int iVar ) { assert( !Cbs2_VarUnused(p, iVar) ); return Vec_IntEntry(&p->vLevReason, 3*iVar); } +static inline int Cbs2_VarReason0( Cbs2_Man_t * p, int iVar ) { assert( !Cbs2_VarUnused(p, iVar) ); return Vec_IntEntry(&p->vLevReason, 3*iVar+1); } +static inline int Cbs2_VarReason1( Cbs2_Man_t * p, int iVar ) { assert( !Cbs2_VarUnused(p, iVar) ); return Vec_IntEntry(&p->vLevReason, 3*iVar+2); } +static inline int * Cbs2_VarReasonP( Cbs2_Man_t * p, int iVar ) { assert( !Cbs2_VarUnused(p, iVar) ); return Vec_IntEntryP(&p->vLevReason, 3*iVar+1); } +//static inline int Cbs2_ClauseDecLevel( Cbs2_Man_t * p, int hClause ) { return Cbs2_VarDecLevel( p, p->pClauses.pData[hClause] ); } + +static inline int Cbs2_ClauseSize( Cbs2_Man_t * p, int hClause ) { return p->pClauses.pData[hClause]; } +static inline int * Cbs2_ClauseLits( Cbs2_Man_t * p, int hClause ) { return p->pClauses.pData+hClause+1; } +static inline int Cbs2_ClauseLit( Cbs2_Man_t * p, int hClause, int i ) { return p->pClauses.pData[hClause+1+i]; } +static inline int * Cbs2_ClauseNext1p( Cbs2_Man_t * p, int hClause ) { return p->pClauses.pData+hClause+Cbs2_ClauseSize(p, hClause)+2; } + +static inline void Cbs2_ClauseSetSize( Cbs2_Man_t * p, int hClause, int x ) { p->pClauses.pData[hClause] = x; } +static inline void Cbs2_ClauseSetLit( Cbs2_Man_t * p, int hClause, int i, int x ) { p->pClauses.pData[hClause+i+1] = x; } +static inline void Cbs2_ClauseSetNext( Cbs2_Man_t * p, int hClause, int n, int x ){ p->pClauses.pData[hClause+Cbs2_ClauseSize(p, hClause)+1+n] = x; } + + +#define Cbs2_QueForEachEntry( Que, iObj, i ) \ + for ( i = (Que).iHead; (i < (Que).iTail) && ((iObj) = (Que).pData[i]); i++ ) + +#define Cbs2_ClauseForEachEntry( p, hClause, iObj, i ) \ + for ( i = 1; i <= Cbs2_ClauseSize(p, hClause) && (iObj = (p)->pClauses.pData[hClause+i]); i++ ) +#define Cbs2_ClauseForEachEntry1( p, hClause, iObj, i ) \ + for ( i = 2; i <= Cbs2_ClauseSize(p, hClause) && (iObj = (p)->pClauses.pData[hClause+i]); i++ ) + +#define Cbs2_ObjForEachFanout( p, iObj, iFanLit ) \ + for ( iFanLit = Vec_IntEntry(&p->vFanout0, iObj); iFanLit; iFanLit = Vec_IntEntry(&p->vFanoutN, iFanLit) ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Sets default values of the parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs2_SetDefaultParams( Cbs2_Par_t * pPars ) +{ + memset( pPars, 0, sizeof(Cbs2_Par_t) ); + pPars->nBTLimit = 1000; // limit on the number of conflicts + pPars->nJustLimit = 500; // limit on the size of justification queue + pPars->fUseHighest = 1; // use node with the highest ID + pPars->fUseLowest = 0; // use node with the highest ID + pPars->fUseMaxFF = 0; // use node with the largest fanin fanout + pPars->fUseFanout = 1; + pPars->fVerbose = 1; // print detailed statistics +} +void Cbs2_ManSetConflictNum( Cbs2_Man_t * p, int Num ) +{ + p->Pars.nBTLimit = Num; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cbs2_Man_t * Cbs2_ManAlloc( Gia_Man_t * pGia ) +{ + Cbs2_Man_t * p; + p = ABC_CALLOC( Cbs2_Man_t, 1 ); + p->pProp.nSize = p->pJust.nSize = p->pClauses.nSize = 10000; + p->pProp.pData = ABC_ALLOC( int, p->pProp.nSize ); + p->pJust.pData = ABC_ALLOC( int, p->pJust.nSize ); + p->pClauses.pData = ABC_ALLOC( int, p->pClauses.nSize ); + p->pClauses.iHead = p->pClauses.iTail = 1; + p->vModel = Vec_IntAlloc( 1000 ); + p->vTemp = Vec_IntAlloc( 1000 ); + p->pAig = pGia; + Cbs2_SetDefaultParams( &p->Pars ); + Vec_StrFill( &p->vAssign, Gia_ManObjNum(pGia), 2 ); + Vec_StrFill( &p->vMark, Gia_ManObjNum(pGia), 0 ); + Vec_IntFill( &p->vLevReason, 3*Gia_ManObjNum(pGia), -1 ); + Vec_IntFill( &p->vWatches, 2*Gia_ManObjNum(pGia), 0 ); + Vec_IntFill( &p->vFanout0, Gia_ManObjNum(pGia), 0 ); + Vec_IntFill( &p->vFanoutN, 2*Gia_ManObjNum(pGia), 0 ); + Vec_IntFill( &p->vActivity, Gia_ManObjNum(pGia), 0 ); + Vec_IntGrow( &p->vActStore, 1000 ); + Vec_IntGrow( &p->vJStore, 1000 ); + Vec_IntGrow( &p->vWatchUpds, 1000 ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs2_ManStop( Cbs2_Man_t * p ) +{ + Vec_StrErase( &p->vAssign ); + Vec_StrErase( &p->vMark ); + Vec_IntErase( &p->vLevReason ); + Vec_IntErase( &p->vWatches ); + Vec_IntErase( &p->vFanout0 ); + Vec_IntErase( &p->vFanoutN ); + Vec_IntErase( &p->vActivity ); + Vec_IntErase( &p->vActStore ); + Vec_IntErase( &p->vJStore ); + Vec_IntErase( &p->vWatchUpds ); + Vec_IntFree( p->vModel ); + Vec_IntFree( p->vTemp ); + ABC_FREE( p->pClauses.pData ); + ABC_FREE( p->pProp.pData ); + ABC_FREE( p->pJust.pData ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Returns satisfying assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Cbs2_ReadModel( Cbs2_Man_t * p ) +{ + return p->vModel; +} + + + + +/**Function************************************************************* + + Synopsis [Returns 1 if the solver is out of limits.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs2_ManCheckLimits( Cbs2_Man_t * p ) +{ + p->nFails[0] += p->Pars.nJustThis > p->Pars.nJustLimit; + p->nFails[1] += p->Pars.nBTThis > p->Pars.nBTLimit; + return p->Pars.nJustThis > p->Pars.nJustLimit || p->Pars.nBTThis > p->Pars.nBTLimit; +} + +/**Function************************************************************* + + Synopsis [Saves the satisfying assignment as an array of literals.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs2_ManSaveModel( Cbs2_Man_t * p, Vec_Int_t * vCex ) +{ + int i, iLit; + Vec_IntClear( vCex ); + p->pProp.iHead = 0; + Cbs2_QueForEachEntry( p->pProp, iLit, i ) + { + int iVar = Abc_Lit2Var(iLit); + if ( Gia_ObjIsCi(Gia_ManObj(p->pAig, iVar)) ) + Vec_IntPush( vCex, Abc_Var2Lit(Gia_ManIdToCioId(p->pAig, iVar), !Cbs2_VarValue(p, iVar)) ); + } +} +static inline void Cbs2_ManSaveModelAll( Cbs2_Man_t * p, Vec_Int_t * vCex ) +{ + int i, iLit; + Vec_IntClear( vCex ); + p->pProp.iHead = 0; + Cbs2_QueForEachEntry( p->pProp, iLit, i ) + { + int iVar = Abc_Lit2Var(iLit); + Vec_IntPush( vCex, Abc_Var2Lit(iVar, !Cbs2_VarValue(p, iVar)) ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs2_QueIsEmpty( Cbs2_Que_t * p ) +{ + return p->iHead == p->iTail; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs2_QuePush( Cbs2_Que_t * p, int iObj ) +{ + if ( p->iTail == p->nSize ) + { + p->nSize *= 2; + p->pData = ABC_REALLOC( int, p->pData, p->nSize ); + } + p->pData[p->iTail++] = iObj; +} +static inline void Cbs2_QueGrow( Cbs2_Que_t * p, int Plus ) +{ + if ( p->iTail + Plus > p->nSize ) + { + p->nSize *= 2; + p->pData = ABC_REALLOC( int, p->pData, p->nSize ); + } + assert( p->iTail + Plus <= p->nSize ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the object in the queue.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs2_QueHasNode( Cbs2_Que_t * p, int iObj ) +{ + int i, iTemp; + Cbs2_QueForEachEntry( *p, iTemp, i ) + if ( iTemp == iObj ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs2_QueStore( Cbs2_Que_t * p, int * piHeadOld, int * piTailOld ) +{ + int i; + *piHeadOld = p->iHead; + *piTailOld = p->iTail; + for ( i = *piHeadOld; i < *piTailOld; i++ ) + Cbs2_QuePush( p, p->pData[i] ); + p->iHead = *piTailOld; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs2_QueRestore( Cbs2_Que_t * p, int iHeadOld, int iTailOld ) +{ + p->iHead = iHeadOld; + p->iTail = iTailOld; +} + + +/**Function************************************************************* + + Synopsis [Max number of fanins fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs2_VarFaninFanoutMax( Cbs2_Man_t * p, Gia_Obj_t * pObj ) +{ + int Count0, Count1; + assert( !Gia_IsComplement(pObj) ); + assert( Gia_ObjIsAnd(pObj) ); + Count0 = Gia_ObjRefNum( p->pAig, Gia_ObjFanin0(pObj) ); + Count1 = Gia_ObjRefNum( p->pAig, Gia_ObjFanin1(pObj) ); + return Abc_MaxInt( Count0, Count1 ); +} + +/**Function************************************************************* + + Synopsis [Find variable with the highest ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs2_ManDecideHighest( Cbs2_Man_t * p ) +{ + int i, iObj, iObjMax = 0; + Cbs2_QueForEachEntry( p->pJust, iObj, i ) + if ( iObjMax == 0 || iObjMax < iObj ) + iObjMax = iObj; + return iObjMax; +} + +/**Function************************************************************* + + Synopsis [Find variable with the lowest ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * Cbs2_ManDecideLowest( Cbs2_Man_t * p ) +{ + int i, iObj, iObjMin = 0; + Cbs2_QueForEachEntry( p->pJust, iObj, i ) + if ( iObjMin == 0 || iObjMin > iObj ) + iObjMin = iObj; + return Gia_ManObj(p->pAig, iObjMin); +} + +/**Function************************************************************* + + Synopsis [Find variable with the maximum number of fanin fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * Cbs2_ManDecideMaxFF( Cbs2_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjMax = NULL; + int i, iMaxFF = 0, iCurFF, iObj; + assert( p->pAig->pRefs != NULL ); + Cbs2_QueForEachEntry( p->pJust, iObj, i ) + { + pObj = Gia_ManObj(p->pAig, iObj); + iCurFF = Cbs2_VarFaninFanoutMax( p, pObj ); + assert( iCurFF > 0 ); + if ( iMaxFF < iCurFF ) + { + iMaxFF = iCurFF; + pObjMax = pObj; + } + } + return pObjMax; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs2_ManCancelUntil( Cbs2_Man_t * p, int iBound ) +{ + int i, iLit; + assert( iBound <= p->pProp.iTail ); + p->pProp.iHead = iBound; + Cbs2_QueForEachEntry( p->pProp, iLit, i ) + Cbs2_VarUnassign( p, Abc_Lit2Var(iLit) ); + p->pProp.iTail = iBound; +} + +/**Function************************************************************* + + Synopsis [Assigns the variables a value.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs2_ManAssign( Cbs2_Man_t * p, int iLit, int Level, int iRes0, int iRes1 ) +{ + int iObj = Abc_Lit2Var(iLit); + assert( Cbs2_VarUnused(p, iObj) ); + assert( !Cbs2_VarIsAssigned(p, iObj) ); + //Cbs2_VarAssign( p, iObj ); + Cbs2_VarSetValue( p, iObj, !Abc_LitIsCompl(iLit) ); + Cbs2_QuePush( &p->pProp, iLit ); + Vec_IntWriteEntry( &p->vLevReason, 3*iObj, Level ); + Vec_IntWriteEntry( &p->vLevReason, 3*iObj+1, iRes0 ); + Vec_IntWriteEntry( &p->vLevReason, 3*iObj+2, iRes1 ); +} + + + + + + + + + +/**Function************************************************************* + + Synopsis [Prints conflict clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs2_ManPrintClause( Cbs2_Man_t * p, int Level, int hClause ) +{ + int i, iLit; + assert( Cbs2_QueIsEmpty( &p->pClauses ) ); + printf( "Level %2d : ", Level ); + Cbs2_ClauseForEachEntry( p, hClause, iLit, i ) + printf( "%c%d ", Abc_LitIsCompl(iLit) ? '-':'+', Abc_Lit2Var(iLit) ); +// printf( "%d=%d(%d) ", iObj, Cbs2_VarValue(p, Abc_Lit2Var(iLit)), Cbs2_VarDecLevel(p, Abc_Lit2Var(iLit)) ); + printf( "\n" ); +} +static inline void Cbs2_ManPrintCube( Cbs2_Man_t * p, int Level, int hClause ) +{ + int i, iObj; + assert( Cbs2_QueIsEmpty( &p->pClauses ) ); + printf( "Level %2d : ", Level ); + Cbs2_ClauseForEachEntry( p, hClause, iObj, i ) + printf( "%c%d ", Cbs2_VarValue(p, iObj)? '+':'-', iObj ); + printf( "\n" ); +} +static inline void Cbs2_ManBumpClause( Cbs2_Man_t * p, int hClause ) +{ + int i, iObj; + assert( Cbs2_QueIsEmpty( &p->pClauses ) ); + Cbs2_ClauseForEachEntry( p, hClause, iObj, i ) + { + //if ( Vec_IntEntry(&p->vActivity, iObj) == 0 ) + // Vec_IntPush( &p->vActStore, iObj ); + //Vec_IntAddToEntry( &p->vActivity, iObj, 1 ); + } +} +static inline void Cbs2_ManBumpClean( Cbs2_Man_t * p ) +{ + int i, iObj; + Vec_IntForEachEntry( &p->vActStore, iObj, i ) + Vec_IntWriteEntry( &p->vActivity, iObj, 0 ); +} + +/**Function************************************************************* + + Synopsis [Finalized the clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs2_ManCleanWatch( Cbs2_Man_t * p ) +{ + int i, iLit; + Vec_IntForEachEntry( &p->vWatchUpds, iLit, i ) + Vec_IntWriteEntry( &p->vWatches, iLit, 0 ); + Vec_IntClear( &p->vWatchUpds ); + //Vec_IntForEachEntry( &p->vWatches, iLit, i ) + // assert( iLit == 0 ); +} +static inline void Cbs2_ManWatchClause( Cbs2_Man_t * p, int hClause, int Lit ) +{ + int * pLits = Cbs2_ClauseLits( p, hClause ); + int * pPlace = Vec_IntEntryP( &p->vWatches, Abc_LitNot(Lit) ); + if ( *pPlace == 0 ) + Vec_IntPush( &p->vWatchUpds, Abc_LitNot(Lit) ); +/* + if ( pClause->pLits[0] == Lit ) + pClause->pNext0 = p->pWatches[lit_neg(Lit)]; + else + { + assert( pClause->pLits[1] == Lit ); + pClause->pNext1 = p->pWatches[lit_neg(Lit)]; + } + p->pWatches[lit_neg(Lit)] = pClause; +*/ + assert( Lit == pLits[0] || Lit == pLits[1] ); + Cbs2_ClauseSetNext( p, hClause, Lit == pLits[1], *pPlace ); + *pPlace = hClause; +} +static inline int Cbs2_QueFinish( Cbs2_Man_t * p, int Level ) +{ + Cbs2_Que_t * pQue = &(p->pClauses); + int i, iObj, hClauseC, hClause = pQue->iHead, Size = pQue->iTail - pQue->iHead - 1; + assert( pQue->iHead+1 < pQue->iTail ); + Cbs2_ClauseSetSize( p, pQue->iHead, Size ); + hClauseC = pQue->iHead = pQue->iTail; + //printf( "Adding cube: " ); Cbs2_ManPrintCube(p, Level, hClause); + if ( Size == 1 ) + return hClause; + // create watched clause + pQue->iHead = hClause; + Cbs2_QueForEachEntry( p->pClauses, iObj, i ) + { + if ( i == hClauseC ) + break; + else if ( i == hClause ) // nlits + Cbs2_QuePush( pQue, iObj ); + else // literals + Cbs2_QuePush( pQue, Abc_Var2Lit(iObj, Cbs2_VarValue(p, iObj)) ); // complement + } + Cbs2_QuePush( pQue, 0 ); // next0 + Cbs2_QuePush( pQue, 0 ); // next1 + pQue->iHead = pQue->iTail; + Cbs2_ManWatchClause( p, hClauseC, Cbs2_ClauseLit(p, hClauseC, 0) ); + Cbs2_ManWatchClause( p, hClauseC, Cbs2_ClauseLit(p, hClauseC, 1) ); + //printf( "Adding clause %d: ", hClauseC ); Cbs2_ManPrintClause(p, Level, hClauseC); + return hClause; +} + +/**Function************************************************************* + + Synopsis [Returns conflict clause.] + + Description [Performs conflict analysis.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs2_ManDeriveReason( Cbs2_Man_t * p, int Level ) +{ + Cbs2_Que_t * pQue = &(p->pClauses); + int i, k, iObj, iLitLevel, * pReason; + assert( pQue->pData[pQue->iHead] == 0 ); + assert( pQue->pData[pQue->iHead+1] == 0 ); + assert( pQue->iHead + 2 < pQue->iTail ); + //for ( i = pQue->iHead + 2; i < pQue->iTail; i++ ) + // assert( !Cbs2_VarMark0(p, pQue->pData[i]) ); + // compact literals + Vec_IntClear( p->vTemp ); + for ( i = k = pQue->iHead + 2; i < pQue->iTail; i++ ) + { + iObj = pQue->pData[i]; + if ( Cbs2_VarMark0(p, iObj) ) // unassigned - seen again + continue; + //if ( Vec_IntEntry(&p->vActivity, iObj) == 0 ) + // Vec_IntPush( &p->vActStore, iObj ); + //Vec_IntAddToEntry( &p->vActivity, iObj, 1 ); + // assigned - seen first time + Cbs2_VarSetMark0(p, iObj, 1); + Vec_IntPush( p->vTemp, iObj ); + // check decision level + iLitLevel = Cbs2_VarDecLevel( p, iObj ); + if ( iLitLevel < Level ) + { + pQue->pData[k++] = iObj; + continue; + } + assert( iLitLevel == Level ); + pReason = Cbs2_VarReasonP( p, iObj ); + if ( pReason[0] == 0 && pReason[1] == 0 ) // no reason + { + assert( pQue->pData[pQue->iHead+1] == 0 ); + pQue->pData[pQue->iHead+1] = iObj; + } + else if ( pReason[0] != 0 ) // circuit reason + { + Cbs2_QuePush( pQue, pReason[0] ); + if ( pReason[1] ) + Cbs2_QuePush( pQue, pReason[1] ); + } + else // clause reason + { + int i, * pLits, nLits = Cbs2_ClauseSize( p, pReason[1] ); + assert( pReason[1] ); + Cbs2_QueGrow( pQue, nLits ); + pLits = Cbs2_ClauseLits( p, pReason[1] ); + assert( iObj == Abc_Lit2Var(pLits[0]) ); + for ( i = 1; i < nLits; i++ ) + Cbs2_QuePush( pQue, Abc_Lit2Var(pLits[i]) ); + } + } + assert( pQue->pData[pQue->iHead] == 0 ); + assert( pQue->pData[pQue->iHead+1] != 0 ); + pQue->iTail = k; + // clear the marks + Vec_IntForEachEntry( p->vTemp, iObj, i ) + Cbs2_VarSetMark0(p, iObj, 0); + return Cbs2_QueFinish( p, Level ); +} +static inline int Cbs2_ManAnalyze( Cbs2_Man_t * p, int Level, int iVar, int iFan0, int iFan1 ) +{ + Cbs2_Que_t * pQue = &(p->pClauses); + assert( Cbs2_VarIsAssigned(p, iVar) ); + assert( Cbs2_QueIsEmpty( pQue ) ); + Cbs2_QuePush( pQue, 0 ); + Cbs2_QuePush( pQue, 0 ); + if ( iFan0 ) // circuit conflict + { + assert( Cbs2_VarIsAssigned(p, iFan0) ); + assert( iFan1 == 0 || Cbs2_VarIsAssigned(p, iFan1) ); + Cbs2_QuePush( pQue, iVar ); + Cbs2_QuePush( pQue, iFan0 ); + if ( iFan1 ) + Cbs2_QuePush( pQue, iFan1 ); + } + else // clause conflict + { + int i, * pLits, nLits = Cbs2_ClauseSize( p, iFan1 ); + assert( iFan1 ); + Cbs2_QueGrow( pQue, nLits ); + pLits = Cbs2_ClauseLits( p, iFan1 ); + assert( iVar == Abc_Lit2Var(pLits[0]) ); + assert( Cbs2_VarValue(p, iVar) == Abc_LitIsCompl(pLits[0]) ); + for ( i = 0; i < nLits; i++ ) + Cbs2_QuePush( pQue, Abc_Lit2Var(pLits[i]) ); + } + return Cbs2_ManDeriveReason( p, Level ); +} + + +/**Function************************************************************* + + Synopsis [Propagate one assignment.] + + Description [Returns handle of the conflict clause, if conflict occurs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs2_ManPropagateClauses( Cbs2_Man_t * p, int Level, int Lit ) +{ + int i, Value, Cur, LitF = Abc_LitNot(Lit); + int * pPrev = Vec_IntEntryP( &p->vWatches, Lit ); + //for ( pCur = p->pWatches[Lit]; pCur; pCur = *ppPrev ) + for ( Cur = *pPrev; Cur; Cur = *pPrev ) + { + int nLits = Cbs2_ClauseSize( p, Cur ); + int * pLits = Cbs2_ClauseLits( p, Cur ); + p->nPropCalls[1]++; +//printf( " Watching literal %c%d on level %d.\n", Abc_LitIsCompl(Lit) ? '-':'+', Abc_Lit2Var(Lit), Level ); + // make sure the false literal is in the second literal of the clause + //if ( pCur->pLits[0] == LitF ) + if ( pLits[0] == LitF ) + { + //pCur->pLits[0] = pCur->pLits[1]; + pLits[0] = pLits[1]; + //pCur->pLits[1] = LitF; + pLits[1] = LitF; + //pTemp = pCur->pNext0; + //pCur->pNext0 = pCur->pNext1; + //pCur->pNext1 = pTemp; + ABC_SWAP( int, pLits[nLits], pLits[nLits+1] ); + } + //assert( pCur->pLits[1] == LitF ); + assert( pLits[1] == LitF ); + + // if the first literal is true, the clause is satisfied + //if ( pCur->pLits[0] == p->pAssigns[lit_var(pCur->pLits[0])] ) + if ( Cbs2_VarValue(p, Abc_Lit2Var(pLits[0])) == !Abc_LitIsCompl(pLits[0]) ) + { + //ppPrev = &pCur->pNext1; + pPrev = Cbs2_ClauseNext1p(p, Cur); + continue; + } + + // look for a new literal to watch + for ( i = 2; i < nLits; i++ ) + { + // skip the case when the literal is false + //if ( lit_neg(pCur->pLits[i]) == p->pAssigns[lit_var(pCur->pLits[i])] ) + if ( Cbs2_VarValue(p, Abc_Lit2Var(pLits[i])) == Abc_LitIsCompl(pLits[i]) ) + continue; + // the literal is either true or unassigned - watch it + //pCur->pLits[1] = pCur->pLits[i]; + //pCur->pLits[i] = LitF; + pLits[1] = pLits[i]; + pLits[i] = LitF; + // remove this clause from the watch list of Lit + //*ppPrev = pCur->pNext1; + *pPrev = *Cbs2_ClauseNext1p(p, Cur); + // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1]) + //Intb_ManWatchClause( p, pCur, pCur->pLits[1] ); + Cbs2_ManWatchClause( p, Cur, Cbs2_ClauseLit(p, Cur, 1) ); + break; + } + if ( i < nLits ) // found new watch + continue; + + // clause is unit - enqueue new implication + //if ( Inta_ManEnqueue(p, pCur->pLits[0], pCur) ) + //{ + // ppPrev = &pCur->pNext1; + // continue; + //} + + // clause is unit - enqueue new implication + Value = Cbs2_VarValue(p, Abc_Lit2Var(pLits[0])); + if ( Value >= 2 ) // unassigned + { + Cbs2_ManAssign( p, pLits[0], Level, 0, Cur ); + pPrev = Cbs2_ClauseNext1p(p, Cur); + continue; + } + + // conflict detected - return the conflict clause + //return pCur; + if ( Value == Abc_LitIsCompl(pLits[0]) ) + { + p->nClauseConf++; + return Cbs2_ManAnalyze( p, Level, Abc_Lit2Var(pLits[0]), 0, Cur ); + } + } + return 0; +} + + +/**Function************************************************************* + + Synopsis [Performs resolution of two clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs2_ManResolve( Cbs2_Man_t * p, int Level, int hClause0, int hClause1 ) +{ + Cbs2_Que_t * pQue = &(p->pClauses); + int i, iObj, LevelMax = -1, LevelCur; + assert( pQue->pData[hClause0+1] != 0 ); + assert( pQue->pData[hClause0+1] == pQue->pData[hClause1+1] ); + //Cbs2_ClauseForEachEntry1( p, hClause0, iObj, i ) + // assert( !Cbs2_VarMark0(p, iObj) ); + //Cbs2_ClauseForEachEntry1( p, hClause1, iObj, i ) + // assert( !Cbs2_VarMark0(p, iObj) ); + assert( Cbs2_QueIsEmpty( pQue ) ); + Cbs2_QuePush( pQue, 0 ); + Cbs2_QuePush( pQue, 0 ); +// for ( i = hClause0 + 1; (iObj = pQue->pData[i]); i++ ) + Cbs2_ClauseForEachEntry1( p, hClause0, iObj, i ) + { + if ( Cbs2_VarMark0(p, iObj) ) // unassigned - seen again + continue; + //if ( Vec_IntEntry(&p->vActivity, iObj) == 0 ) + // Vec_IntPush( &p->vActStore, iObj ); + //Vec_IntAddToEntry( &p->vActivity, iObj, 1 ); + // assigned - seen first time + Cbs2_VarSetMark0(p, iObj, 1); + Cbs2_QuePush( pQue, iObj ); + LevelCur = Cbs2_VarDecLevel( p, iObj ); + if ( LevelMax < LevelCur ) + LevelMax = LevelCur; + } +// for ( i = hClause1 + 1; (iObj = pQue->pData[i]); i++ ) + Cbs2_ClauseForEachEntry1( p, hClause1, iObj, i ) + { + if ( Cbs2_VarMark0(p, iObj) ) // unassigned - seen again + continue; + //if ( Vec_IntEntry(&p->vActivity, iObj) == 0 ) + // Vec_IntPush( &p->vActStore, iObj ); + //Vec_IntAddToEntry( &p->vActivity, iObj, 1 ); + // assigned - seen first time + Cbs2_VarSetMark0(p, iObj, 1); + Cbs2_QuePush( pQue, iObj ); + LevelCur = Cbs2_VarDecLevel( p, iObj ); + if ( LevelMax < LevelCur ) + LevelMax = LevelCur; + } + for ( i = pQue->iHead + 2; i < pQue->iTail; i++ ) + Cbs2_VarSetMark0(p, pQue->pData[i], 0); + return Cbs2_ManDeriveReason( p, LevelMax ); +} + +/**Function************************************************************* + + Synopsis [Propagates a variable.] + + Description [Returns clause handle if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs2_ManPropagateOne( Cbs2_Man_t * p, int iVar, int Level ) +{ + Gia_Obj_t * pVar = Gia_ManObj( p->pAig, iVar ); int Value0, Value1; + assert( !Gia_IsComplement(pVar) ); + assert( Cbs2_VarIsAssigned(p, iVar) ); + if ( Gia_ObjIsCi(pVar) ) + return 0; + p->nPropCalls[0]++; + assert( Gia_ObjIsAnd(pVar) ); + Value0 = Cbs2_VarFanin0Value(p, pVar, iVar); + Value1 = Cbs2_VarFanin1Value(p, pVar, iVar); + if ( Cbs2_VarValue(p, iVar) == 1 ) + { // value is 1 + if ( Value0 == 0 || Value1 == 0 ) // one is 0 + { + if ( Value0 == 0 && Value1 != 0 ) + return Cbs2_ManAnalyze( p, Level, iVar, Gia_ObjFaninId0(pVar, iVar), 0 ); + if ( Value0 != 0 && Value1 == 0 ) + return Cbs2_ManAnalyze( p, Level, iVar, Gia_ObjFaninId1(pVar, iVar), 0 ); + assert( Value0 == 0 && Value1 == 0 ); + return Cbs2_ManAnalyze( p, Level, iVar, Gia_ObjFaninId0(pVar, iVar), Gia_ObjFaninId1(pVar, iVar) ); + } + if ( Value0 >= 2 ) // first is unassigned + Cbs2_ManAssign( p, Gia_ObjFaninLit0(pVar, iVar), Level, iVar, 0 ); + if ( Value1 >= 2 ) // first is unassigned + Cbs2_ManAssign( p, Gia_ObjFaninLit1(pVar, iVar), Level, iVar, 0 ); + return 0; + } + // value is 0 + if ( Value0 == 0 || Value1 == 0 ) // one is 0 + return 0; + if ( Value0 == 1 && Value1 == 1 ) // both are 1 + return Cbs2_ManAnalyze( p, Level, iVar, Gia_ObjFaninId0(pVar, iVar), Gia_ObjFaninId1(pVar, iVar) ); + if ( Value0 == 1 || Value1 == 1 ) // one is 1 + { + if ( Value0 >= 2 ) // first is unassigned + Cbs2_ManAssign( p, Abc_LitNot(Gia_ObjFaninLit0(pVar, iVar)), Level, iVar, Gia_ObjFaninId1(pVar, iVar) ); + if ( Value1 >= 2 ) // second is unassigned + Cbs2_ManAssign( p, Abc_LitNot(Gia_ObjFaninLit1(pVar, iVar)), Level, iVar, Gia_ObjFaninId0(pVar, iVar) ); + return 0; + } + assert( Cbs2_VarIsJust(p, pVar, iVar) ); + //assert( !Cbs2_QueHasNode( &p->pJust, iVar ) ); + if ( !p->Pars.fUseFanout ) + Cbs2_QuePush( &p->pJust, iVar ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Propagates a variable.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs2_ManPropagateTwo( Cbs2_Man_t * p, int iVar, int Level ) +{ + Gia_Obj_t * pVar = Gia_ManObj( p->pAig, iVar ); int Value0, Value1; + assert( !Gia_IsComplement(pVar) ); + assert( Gia_ObjIsAnd(pVar) ); + assert( Cbs2_VarIsAssigned(p, iVar) ); + assert( Cbs2_VarValue(p, iVar) == 0 ); + Value0 = Cbs2_VarFanin0Value(p, pVar, iVar); + Value1 = Cbs2_VarFanin1Value(p, pVar, iVar); + p->nPropCalls[1]++; + // value is 0 + if ( Value0 == 0 || Value1 == 0 ) // one is 0 + return 0; + if ( Value0 == 1 && Value1 == 1 ) // both are 1 + return Cbs2_ManAnalyze( p, Level, iVar, Gia_ObjFaninId0(pVar, iVar), Gia_ObjFaninId1(pVar, iVar) ); + assert( Value0 == 1 || Value1 == 1 ); + if ( Value0 >= 2 ) // first is unassigned + Cbs2_ManAssign( p, Abc_LitNot(Gia_ObjFaninLit0(pVar, iVar)), Level, iVar, Gia_ObjFaninId1(pVar, iVar) ); + if ( Value1 >= 2 ) // first is unassigned + Cbs2_ManAssign( p, Abc_LitNot(Gia_ObjFaninLit1(pVar, iVar)), Level, iVar, Gia_ObjFaninId0(pVar, iVar) ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Propagates a variable.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs2_ManPropagateUnassigned( Cbs2_Man_t * p, int iVar, int Level ) +{ + Gia_Obj_t * pVar = Gia_ManObj( p->pAig, iVar ); int Value0, Value1; + assert( !Gia_IsComplement(pVar) ); + assert( Gia_ObjIsAnd(pVar) ); + assert( !Cbs2_VarIsAssigned(p, iVar) ); + Value0 = Cbs2_VarFanin0Value(p, pVar, iVar); + Value1 = Cbs2_VarFanin1Value(p, pVar, iVar); + p->nPropCalls[2]++; + if ( Value0 == 0 && Value1 == 0 ) // the output becomes 1 + Cbs2_ManAssign( p, Abc_Var2Lit(iVar, 1), Level, Gia_ObjFaninId0(pVar, iVar), Gia_ObjFaninId1(pVar, iVar) ); + else if ( Value0 == 0 ) // the output becomes 0 + Cbs2_ManAssign( p, Abc_Var2Lit(iVar, 1), Level, Gia_ObjFaninId0(pVar, iVar), 0 ); + else if ( Value1 == 0 ) // the output becomes 0 + Cbs2_ManAssign( p, Abc_Var2Lit(iVar, 1), Level, Gia_ObjFaninId1(pVar, iVar), 0 ); + else if ( Value0 == 1 && Value1 == 1 ) // the output becomes 1 + Cbs2_ManAssign( p, Abc_Var2Lit(iVar, 0), Level, Gia_ObjFaninId0(pVar, iVar), Gia_ObjFaninId1(pVar, iVar) ); +} + +/**Function************************************************************* + + Synopsis [Propagates all variables.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cbs2_ManPropagate( Cbs2_Man_t * p, int Level ) +{ + while ( 1 ) + { + int i, k, iVar, iLit, hClause; + Cbs2_QueForEachEntry( p->pProp, iLit, i ) + { + if ( (hClause = Cbs2_ManPropagateOne( p, Abc_Lit2Var(iLit), Level )) ) + return hClause; + } + p->pProp.iHead = p->pProp.iTail; + k = p->pJust.iHead; + Cbs2_QueForEachEntry( p->pJust, iVar, i ) + { + if ( Cbs2_VarIsJust(p, Gia_ManObj(p->pAig, iVar), iVar) ) + p->pJust.pData[k++] = iVar; + else if ( (hClause = Cbs2_ManPropagateTwo( p, iVar, Level )) ) + return hClause; + } + if ( k == p->pJust.iTail ) + break; + p->pJust.iTail = k; + } + return 0; +} + + +int Cbs2_ManPropagate2( Cbs2_Man_t * p, int Level ) +{ + int i, iLit, iFan, hClause; + Cbs2_QueForEachEntry( p->pProp, iLit, i ) + { + if ( (hClause = Cbs2_ManPropagateClauses(p, Level, iLit)) ) + return hClause; + Cbs2_ObjForEachFanout( p, Abc_Lit2Var(iLit), iFan ) + { + int iFanout = Abc_Lit2Var(iFan); + if ( !Cbs2_VarIsAssigned(p, iFanout) ) + Cbs2_ManPropagateUnassigned( p, iFanout, Level ); + else if ( (hClause = Cbs2_ManPropagateOne(p, iFanout, Level)) ) + return hClause; + } + if ( (hClause = Cbs2_ManPropagateOne( p, Abc_Lit2Var(iLit), Level )) ) + return hClause; + } + p->pProp.iHead = p->pProp.iTail; + return 0; +} + + +/**Function************************************************************* + + Synopsis [Updates J-frontier.] + + Description [Returns 1 if found SAT; 0 if continues solving.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs2_ManUpdateDecVar2( Cbs2_Man_t * p, int iObj, int iDecLit ) +{ + Gia_Obj_t * pObj = Gia_ManObj(p->pAig, iObj); int iFan; + + iFan = Gia_ObjFaninId0(pObj, iObj); + if ( iDecLit == -1 || Gia_ObjLevelId(p->pAig, Abc_Lit2Var(iDecLit)) < Gia_ObjLevelId(p->pAig, iFan) ) + iDecLit = Abc_LitNot(Gia_ObjFaninLit0(pObj, iObj)); + + iFan = Gia_ObjFaninId1(pObj, iObj); + if ( iDecLit == -1 || Gia_ObjLevelId(p->pAig, Abc_Lit2Var(iDecLit)) < Gia_ObjLevelId(p->pAig, iFan) ) + iDecLit = Abc_LitNot(Gia_ObjFaninLit1(pObj, iObj)); + + return iDecLit; +} +static inline int Cbs2_ManUpdateDecVar3( Cbs2_Man_t * p, int iObj, int iDecLit ) +{ + Gia_Obj_t * pObj = Gia_ManObj(p->pAig, iObj); int iFan; + + iFan = Gia_ObjFaninId0(pObj, iObj); + if ( iDecLit == -1 || Vec_IntEntry(&p->vActivity, Abc_Lit2Var(iDecLit)) < Vec_IntEntry(&p->vActivity, iFan) ) + iDecLit = Abc_LitNot(Gia_ObjFaninLit0(pObj, iObj)); + + iFan = Gia_ObjFaninId1(pObj, iObj); + if ( iDecLit == -1 || Vec_IntEntry(&p->vActivity, Abc_Lit2Var(iDecLit)) < Vec_IntEntry(&p->vActivity, iFan) ) + iDecLit = Abc_LitNot(Gia_ObjFaninLit1(pObj, iObj)); + + return iDecLit; +} +static inline int Cbs2_ManUpdateDecVar( Cbs2_Man_t * p, int iObj, int iDecLit ) +{ + Gia_Obj_t * pObj = Gia_ManObj(p->pAig, iObj); int iFan; + + iFan = Gia_ObjFaninId0(pObj, iObj); + if ( iDecLit == -1 || Gia_ObjRefNumId(p->pAig, Abc_Lit2Var(iDecLit)) < Gia_ObjRefNumId(p->pAig, iFan) ) + iDecLit = Abc_LitNot(Gia_ObjFaninLit0(pObj, iObj)); + + iFan = Gia_ObjFaninId1(pObj, iObj); + if ( iDecLit == -1 || Gia_ObjRefNumId(p->pAig, Abc_Lit2Var(iDecLit)) < Gia_ObjRefNumId(p->pAig, iFan) ) + iDecLit = Abc_LitNot(Gia_ObjFaninLit1(pObj, iObj)); + + return iDecLit; +} +int Cbs2_ManUpdateFrontier( Cbs2_Man_t * p, int iPropHeadOld, int * piDecLit ) +{ + abctime clk = Abc_Clock(); + int i, iVar, iLit, iJustTailOld = p->pJust.iTail; + *piDecLit = -1; + assert( Cbs2_QueIsEmpty(&p->pProp) ); + // visit old frontier nodes + Cbs2_QueForEachEntry( p->pJust, iVar, i ) + if ( i == iJustTailOld ) + break; + else if ( Cbs2_VarIsJust(p, Gia_ManObj(p->pAig, iVar), iVar) ) + { + Cbs2_QuePush( &p->pJust, iVar ); + //*piDecLit = Cbs2_ManUpdateDecVar( p, iVar, *piDecLit ); + } + // append new nodes + p->pProp.iHead = iPropHeadOld; + Cbs2_QueForEachEntry( p->pProp, iLit, i ) + { + iVar = Abc_Lit2Var(iLit); + if ( Cbs2_VarIsJust(p, Gia_ManObj(p->pAig, iVar), iVar) ) + { + Cbs2_QuePush( &p->pJust, iVar ); + //*piDecLit = Cbs2_ManUpdateDecVar( p, iVar, *piDecLit ); + } + } + p->pProp.iHead = p->pProp.iTail; + // update the head of the frontier + p->pJust.iHead = iJustTailOld; + // return 1 if the queue is empty + p->timeJFront += Abc_Clock() - clk; +//printf( "%d ", p->pJust.iTail - p->pJust.iHead ); + return Cbs2_QueIsEmpty(&p->pJust); +} + +/**Function************************************************************* + + Synopsis [Solve the problem recursively.] + + Description [Returns learnt clause if unsat, NULL if sat or undecided.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +int Cbs2_ManSolve1_rec( Cbs2_Man_t * p, int Level ) +{ + Gia_Obj_t * pVar; + Cbs2_Que_t * pQue = &(p->pClauses); + int iPropHead, iJustHead, iJustTail; + int hClause, hLearn0, hLearn1, iVar, iDecLit; + // propagate assignments + assert( !Cbs2_QueIsEmpty(&p->pProp) ); + if ( (hClause = Cbs2_ManPropagate( p, Level )) ) + return hClause; + // check for satisfying assignment + assert( Cbs2_QueIsEmpty(&p->pProp) ); + if ( Cbs2_QueIsEmpty(&p->pJust) ) + return 0; + // quit using resource limits + p->Pars.nJustThis = Abc_MaxInt( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead ); + if ( Cbs2_ManCheckLimits( p ) ) + return 0; + // remember the state before branching + iPropHead = p->pProp.iHead; + Cbs2_QueStore( &p->pJust, &iJustHead, &iJustTail ); + // find the decision variable + assert( p->Pars.fUseHighest ); + iVar = Cbs2_ManDecideHighest( p ); + pVar = Gia_ManObj( p->pAig, iVar ); + assert( Cbs2_VarIsJust(p, pVar, iVar) ); + // chose decision variable using fanout count + if ( Gia_ObjRefNum(p->pAig, Gia_ObjFanin0(pVar)) > Gia_ObjRefNum(p->pAig, Gia_ObjFanin1(pVar)) ) + iDecLit = Abc_LitNot(Gia_ObjFaninLit0(pVar, iVar)); + else + iDecLit = Abc_LitNot(Gia_ObjFaninLit1(pVar, iVar)); + // decide on first fanin + Cbs2_ManAssign( p, iDecLit, Level+1, 0, 0 ); + if ( !(hLearn0 = Cbs2_ManSolve1_rec( p, Level+1 )) ) + return 0; + if ( pQue->pData[hLearn0+1] != Abc_Lit2Var(iDecLit) ) + return hLearn0; + Cbs2_ManCancelUntil( p, iPropHead ); + Cbs2_QueRestore( &p->pJust, iJustHead, iJustTail ); + // decide on second fanin + Cbs2_ManAssign( p, Abc_LitNot(iDecLit), Level+1, 0, 0 ); + if ( !(hLearn1 = Cbs2_ManSolve1_rec( p, Level+1 )) ) + return 0; + if ( pQue->pData[hLearn1+1] != Abc_Lit2Var(iDecLit) ) + return hLearn1; + hClause = Cbs2_ManResolve( p, Level, hLearn0, hLearn1 ); + Cbs2_ManBumpClause( p, hClause ); +// Cbs2_ManPrintCube( p, Level, hClause ); +// if ( Level > Cbs2_ClauseDecLevel(p, hClause) ) +// p->Pars.nBTThisNc++; + p->Pars.nBTThis++; + return hClause; +} + +int Cbs2_ManSolve2_rec( Cbs2_Man_t * p, int Level ) +{ + Gia_Obj_t * pVar; + Cbs2_Que_t * pQue = &(p->pClauses); + int iPropHead, iJustHead, iJustTail; + int hClause, hLearn0, hLearn1, iVar, iDecLit, iDecLit2; + int iPropHeadOld = p->pProp.iHead; + // propagate assignments + assert( !Cbs2_QueIsEmpty(&p->pProp) ); + if ( (hClause = Cbs2_ManPropagate2( p, Level )) ) + return hClause; + // check for satisfying assignment + assert( Cbs2_QueIsEmpty(&p->pProp) ); +// if ( Cbs2_QueIsEmpty(&p->pJust) ) +// return 0; + if ( Cbs2_ManUpdateFrontier(p, iPropHeadOld, &iDecLit2) ) + return 0; + // quit using resource limits + p->Pars.nJustThis = Abc_MaxInt( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead ); + if ( Cbs2_ManCheckLimits( p ) ) + return 0; + // remember the state before branching + iPropHead = p->pProp.iHead; +// Cbs2_QueStore( &p->pJust, &iJustHead, &iJustTail ); + iJustHead = p->pJust.iHead; + iJustTail = p->pJust.iTail; + // find the decision variable + + assert( p->Pars.fUseHighest ); + iVar = Cbs2_ManDecideHighest( p ); + pVar = Gia_ManObj( p->pAig, iVar ); + assert( Cbs2_VarIsJust(p, pVar, iVar) ); + // chose decision variable using fanout count + if ( Gia_ObjRefNum(p->pAig, Gia_ObjFanin0(pVar)) > Gia_ObjRefNum(p->pAig, Gia_ObjFanin1(pVar)) ) +// if ( Vec_IntEntry(&p->vActivity, Gia_ObjFaninId0(pVar, iVar)) > Vec_IntEntry(&p->vActivity, Gia_ObjFaninId1(pVar, iVar)) ) + iDecLit = Abc_LitNot(Gia_ObjFaninLit0(pVar, iVar)); + else + iDecLit = Abc_LitNot(Gia_ObjFaninLit1(pVar, iVar)); + + //iDecLit = iDecLit2; + + // decide on first fanin + Cbs2_ManAssign( p, iDecLit, Level+1, 0, 0 ); + if ( !(hLearn0 = Cbs2_ManSolve2_rec( p, Level+1 )) ) + return 0; + if ( pQue->pData[hLearn0+1] != Abc_Lit2Var(iDecLit) ) + return hLearn0; + Cbs2_ManCancelUntil( p, iPropHead ); + Cbs2_QueRestore( &p->pJust, iJustHead, iJustTail ); + // decide on second fanin + Cbs2_ManAssign( p, Abc_LitNot(iDecLit), Level+1, 0, 0 ); + if ( !(hLearn1 = Cbs2_ManSolve2_rec( p, Level+1 )) ) + return 0; + if ( pQue->pData[hLearn1+1] != Abc_Lit2Var(iDecLit) ) + return hLearn1; + hClause = Cbs2_ManResolve( p, Level, hLearn0, hLearn1 ); + Cbs2_ManBumpClause( p, hClause ); + //Cbs2_ManPrintCube( p, Level, hClause ); +// if ( Level > Cbs2_ClauseDecLevel(p, hClause) ) +// p->Pars.nBTThisNc++; + p->Pars.nBTThis++; + return hClause; +} + +int Cbs2_ManSolve_rec( Cbs2_Man_t * p, int Level ) +{ + return p->Pars.fUseFanout ? Cbs2_ManSolve2_rec(p, Level) : Cbs2_ManSolve1_rec(p, Level); +} + +/**Function************************************************************* + + Synopsis [Looking for a satisfying assignment of the node.] + + Description [Assumes that each node has flag pObj->fMark0 set to 0. + Returns 1 if unsatisfiable, 0 if satisfiable, and -1 if undecided. + The node may be complemented. ] + + SideEffects [The two procedures differ in the CEX format.] + + SeeAlso [] + +***********************************************************************/ +int Cbs2_ManSolve( Cbs2_Man_t * p, int iLit ) +{ + int RetValue = 0; + assert( !p->pProp.iHead && !p->pProp.iTail ); + assert( !p->pJust.iHead && !p->pJust.iTail ); + assert( p->pClauses.iHead == 1 && p->pClauses.iTail == 1 ); + p->Pars.nBTThis = p->Pars.nJustThis = p->Pars.nBTThisNc = 0; + Cbs2_ManAssign( p, iLit, 0, 0, 0 ); + if ( !Cbs2_ManSolve_rec(p, 0) && !Cbs2_ManCheckLimits(p) ) + Cbs2_ManSaveModel( p, p->vModel ); + else + RetValue = 1; + Cbs2_ManCancelUntil( p, 0 ); + Cbs2_ManCleanWatch( p ); + Cbs2_ManBumpClean( p ); + p->pJust.iHead = p->pJust.iTail = 0; + p->pClauses.iHead = p->pClauses.iTail = 1; + p->Pars.nBTTotal += p->Pars.nBTThis; + p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis ); + if ( Cbs2_ManCheckLimits( p ) ) + RetValue = -1; + return RetValue; +} +int Cbs2_ManSolve2( Cbs2_Man_t * p, int iLit, int iLit2 ) +{ + int RetValue = 0; + assert( !p->pProp.iHead && !p->pProp.iTail ); + assert( !p->pJust.iHead && !p->pJust.iTail ); + assert( p->pClauses.iHead == 1 && p->pClauses.iTail == 1 ); + p->Pars.nBTThis = p->Pars.nJustThis = p->Pars.nBTThisNc = 0; + Cbs2_ManAssign( p, iLit, 0, 0, 0 ); + if ( iLit2 ) + Cbs2_ManAssign( p, iLit2, 0, 0, 0 ); + if ( !Cbs2_ManSolve_rec(p, 0) && !Cbs2_ManCheckLimits(p) ) + Cbs2_ManSaveModelAll( p, p->vModel ); + else + RetValue = 1; + Cbs2_ManCancelUntil( p, 0 ); + Cbs2_ManCleanWatch( p ); + Cbs2_ManBumpClean( p ); + p->pJust.iHead = p->pJust.iTail = 0; + p->pClauses.iHead = p->pClauses.iTail = 1; + p->Pars.nBTTotal += p->Pars.nBTThis; + p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis ); + if ( Cbs2_ManCheckLimits( p ) ) + RetValue = -1; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Prints statistics of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs2_ManSatPrintStats( Cbs2_Man_t * p ) +{ + printf( "CO = %8d ", Gia_ManCoNum(p->pAig) ); + printf( "AND = %8d ", Gia_ManAndNum(p->pAig) ); + printf( "Conf = %6d ", p->Pars.nBTLimit ); + printf( "JustMax = %5d ", p->Pars.nJustLimit ); + printf( "\n" ); + printf( "Unsat calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatUnsat, p->nSatTotal? 100.0*p->nSatUnsat/p->nSatTotal :0.0, p->nSatUnsat? 1.0*p->nConfUnsat/p->nSatUnsat :0.0 ); + ABC_PRTP( "Time", p->timeSatUnsat, p->timeTotal ); + printf( "Sat calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatSat, p->nSatTotal? 100.0*p->nSatSat/p->nSatTotal :0.0, p->nSatSat? 1.0*p->nConfSat/p->nSatSat : 0.0 ); + ABC_PRTP( "Time", p->timeSatSat, p->timeTotal ); + printf( "Undef calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatUndec, p->nSatTotal? 100.0*p->nSatUndec/p->nSatTotal :0.0, p->nSatUndec? 1.0*p->nConfUndec/p->nSatUndec : 0.0 ); + ABC_PRTP( "Time", p->timeSatUndec, p->timeTotal ); + ABC_PRT( "Total time", p->timeTotal ); +} + +/**Function************************************************************* + + Synopsis [Create fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs2_ObjPrintFanouts( Cbs2_Man_t * p, int iObj ) +{ + int iFanLit; + printf( "Fanouts of node %d: ", iObj ); + Cbs2_ObjForEachFanout( p, iObj, iFanLit ) + printf( "%d ", Abc_Lit2Var(iFanLit) ); + printf( "\n" ); +} + +void Cbs2_ManPrintFanouts( Cbs2_Man_t * p ) +{ + Gia_Obj_t * pObj; int iObj; + Gia_ManForEachObj( p->pAig, pObj, iObj ) + if ( Vec_IntEntry(&p->vFanout0, iObj) ) + Cbs2_ObjPrintFanouts( p, iObj ); +} +void Cbs2_ObjCreateFanout( Cbs2_Man_t * p, int iObj, int iFan0, int iFan1 ) +{ + Vec_IntWriteEntry( &p->vFanoutN, Abc_Var2Lit(iObj, 0), Vec_IntEntry(&p->vFanout0, iFan0) ); + Vec_IntWriteEntry( &p->vFanoutN, Abc_Var2Lit(iObj, 1), Vec_IntEntry(&p->vFanout0, iFan1) ); + Vec_IntWriteEntry( &p->vFanout0, iFan0, Abc_Var2Lit(iObj, 0) ); + Vec_IntWriteEntry( &p->vFanout0, iFan1, Abc_Var2Lit(iObj, 1) ); +} +void Cbs2_ObjDeleteFanout( Cbs2_Man_t * p, int iObj ) +{ + Vec_IntWriteEntry( &p->vFanoutN, Abc_Var2Lit(iObj, 0), 0 ); + Vec_IntWriteEntry( &p->vFanoutN, Abc_Var2Lit(iObj, 1), 0 ); + Vec_IntWriteEntry( &p->vFanout0, iObj, 0 ); +} +void Cbs2_ManCreateFanout_rec( Cbs2_Man_t * p, int iObj ) +{ + Gia_Obj_t * pObj; int iFan0, iFan1; + if ( !iObj || Gia_ObjIsTravIdCurrentId(p->pAig, iObj) ) + return; + Gia_ObjSetTravIdCurrentId(p->pAig, iObj); + pObj = Gia_ManObj(p->pAig, iObj); + if ( Gia_ObjIsCi(pObj) ) + return; + assert( Gia_ObjIsAnd(pObj) ); + iFan0 = Gia_ObjFaninId0(pObj, iObj); + iFan1 = Gia_ObjFaninId1(pObj, iObj); + Cbs2_ManCreateFanout_rec( p, iFan0 ); + Cbs2_ManCreateFanout_rec( p, iFan1 ); + Cbs2_ObjCreateFanout( p, iObj, iFan0, iFan1 ); +} +void Cbs2_ManDeleteFanout_rec( Cbs2_Man_t * p, int iObj ) +{ + Gia_Obj_t * pObj = Gia_ManObj(p->pAig, iObj); int iFan0, iFan1; + Cbs2_ObjDeleteFanout( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + return; + assert( Gia_ObjIsAnd(pObj) ); + iFan0 = Gia_ObjFaninId0(pObj, iObj); + iFan1 = Gia_ObjFaninId1(pObj, iObj); + if ( Vec_IntEntry(&p->vFanout0, iFan0) ) Cbs2_ManDeleteFanout_rec( p, iFan0 ); + if ( Vec_IntEntry(&p->vFanout0, iFan1) ) Cbs2_ManDeleteFanout_rec( p, iFan1 ); +} +void Cbs2_ManCheckFanouts( Cbs2_Man_t * p ) +{ + Gia_Obj_t * pObj; + int iObj; + Gia_ManForEachObj( p->pAig, pObj, iObj ) + { + assert( Vec_IntEntry(&p->vFanout0, iObj) == 0 ); + assert( Vec_IntEntry(&p->vFanoutN, Abc_Var2Lit(iObj, 0)) == 0 ); + assert( Vec_IntEntry(&p->vFanoutN, Abc_Var2Lit(iObj, 1)) == 0 ); + } +} + +/**Function************************************************************* + + Synopsis [Procedure to test the new SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Cbs2_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int fVerbose ) +{ + extern void Gia_ManCollectTest( Gia_Man_t * pAig ); + extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out ); + Cbs2_Man_t * p; + Vec_Int_t * vCex, * vVisit, * vCexStore; + Vec_Str_t * vStatus; + Gia_Obj_t * pRoot; + int i, status; + abctime clk, clkTotal = Abc_Clock(); + assert( Gia_ManRegNum(pAig) == 0 ); +// Gia_ManCollectTest( pAig ); + // prepare AIG + Gia_ManCreateRefs( pAig ); + //Gia_ManLevelNum( pAig ); + //Gia_ManCleanMark0( pAig ); + //Gia_ManCleanMark1( pAig ); + //Gia_ManFillValue( pAig ); // maps nodes into trail ids + //Gia_ManSetPhase( pAig ); // maps nodes into trail ids + // create logic network + p = Cbs2_ManAlloc( pAig ); + p->Pars.nBTLimit = nConfs; + // create resulting data-structures + vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) ); + vCexStore = Vec_IntAlloc( 10000 ); + vVisit = Vec_IntAlloc( 100 ); + vCex = Cbs2_ReadModel( p ); + // solve for each output + Gia_ManForEachCo( pAig, pRoot, i ) + { + //printf( "\nOutput %d\n", i ); + + Vec_IntClear( vCex ); + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pRoot)) ) + { + if ( Gia_ObjFaninC0(pRoot) ) + { +// printf( "Constant 1 output of SRM!!!\n" ); + Cec_ManSatAddToStore( vCexStore, vCex, i ); // trivial counter-example + Vec_StrPush( vStatus, 0 ); + } + else + { +// printf( "Constant 0 output of SRM!!!\n" ); + Vec_StrPush( vStatus, 1 ); + } + continue; + } + clk = Abc_Clock(); + p->Pars.fUseHighest = 1; + p->Pars.fUseLowest = 0; + + Gia_ManIncrementTravId( pAig ); + Cbs2_ManCreateFanout_rec( p, Gia_ObjFaninId0p(pAig, pRoot) ); + //Cbs2_ManPrintFanouts( p ); + + status = Cbs2_ManSolve( p, Gia_ObjFaninLit0p(pAig, pRoot) ); + //printf( "\n" ); + + Cbs2_ManDeleteFanout_rec( p, Gia_ObjFaninId0p(pAig, pRoot) ); + //Cbs2_ManCheckFanouts( p ); + +/* + if ( status == -1 ) + { + p->Pars.fUseHighest = 0; + p->Pars.fUseLowest = 1; + status = Cbs2_ManSolve( p, Gia_ObjChild0(pRoot) ); + } +*/ + Vec_StrPush( vStatus, (char)status ); + if ( status == -1 ) + { + p->nSatUndec++; + p->nConfUndec += p->Pars.nBTThis; + Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout + p->timeSatUndec += Abc_Clock() - clk; + continue; + } + if ( status == 1 ) + { + p->nSatUnsat++; + p->nConfUnsat += p->Pars.nBTThis; + p->timeSatUnsat += Abc_Clock() - clk; + continue; + } + p->nSatSat++; + p->nConfSat += p->Pars.nBTThis; +// Gia_SatVerifyPattern( pAig, pRoot, vCex, vVisit ); + Cec_ManSatAddToStore( vCexStore, vCex, i ); + p->timeSatSat += Abc_Clock() - clk; + } + Vec_IntFree( vVisit ); + p->nSatTotal = Gia_ManPoNum(pAig); + p->timeTotal = Abc_Clock() - clkTotal; + if ( fVerbose ) + Cbs2_ManSatPrintStats( p ); + if ( fVerbose ) + { +// printf( "RecCalls = %8d. RecClause = %8d. RecNonChro = %8d.\n", p->nRecCall, p->nRecClause, p->nRecNonChro ); + printf( "Prop1 = %d. Prop2 = %d. Prop3 = %d. ClaConf = %d. FailJ = %d. FailC = %d. ", p->nPropCalls[0], p->nPropCalls[1], p->nPropCalls[2], p->nClauseConf, p->nFails[0], p->nFails[1] ); + Abc_PrintTime( 1, "JFront", p->timeJFront ); + } + + Cbs2_ManStop( p ); + *pvStatus = vStatus; + +// printf( "Total number of cex literals = %d. (Ave = %d)\n", +// Vec_IntSize(vCexStore)-2*p->nSatUndec-2*p->nSatSat, +// (Vec_IntSize(vCexStore)-2*p->nSatUndec-2*p->nSatSat)/p->nSatSat ); + return vCexStore; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaCSat3.c b/yosys/abc/src/aig/gia/giaCSat3.c new file mode 100644 index 00000000000..c34c84ca636 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaCSat3.c @@ -0,0 +1,1365 @@ +/**CFile**************************************************************** + + FileName [giaCSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [A simple circuit-based solver.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaCSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Cbs3_Par_t_ Cbs3_Par_t; +struct Cbs3_Par_t_ +{ + // conflict limits + int nBTLimit; // limit on the number of conflicts + int nJustLimit; // limit on the size of justification queue + int nRestLimit; // limit on the number of restarts + // current parameters + int nBTThis; // number of conflicts + int nJustThis; // max size of the frontier + int nBTTotal; // total number of conflicts + int nJustTotal; // total size of the frontier + // other + int fVerbose; +}; + +typedef struct Cbs3_Que_t_ Cbs3_Que_t; +struct Cbs3_Que_t_ +{ + int iHead; // beginning of the queue + int iTail; // end of the queue + int nSize; // allocated size + int * pData; // nodes stored in the queue +}; + +typedef struct Cbs3_Man_t_ Cbs3_Man_t; +struct Cbs3_Man_t_ +{ + Cbs3_Par_t Pars; // parameters + Gia_Man_t * pAig; // AIG manager + Cbs3_Que_t pProp; // propagation queue + Cbs3_Que_t pJust; // justification queue + Cbs3_Que_t pClauses; // clause queue + Vec_Int_t * vModel; // satisfying assignment + Vec_Int_t * vTemp; // temporary storage + // circuit structure + int nVars; + int nVarsAlloc; + int var_inc; + Vec_Int_t vMap; + Vec_Int_t vRef; + Vec_Int_t vFans; + Vec_Wec_t vImps; + // internal data + Vec_Str_t vAssign; + Vec_Str_t vMark; + Vec_Int_t vLevReason; + Vec_Int_t vActs; + Vec_Int_t vWatches; + Vec_Int_t vWatchUpds; + // SAT calls statistics + int nSatUnsat; // the number of proofs + int nSatSat; // the number of failure + int nSatUndec; // the number of timeouts + int nSatTotal; // the number of calls + // conflicts + int nConfUnsat; // conflicts in unsat problems + int nConfSat; // conflicts in sat problems + int nConfUndec; // conflicts in undec problems + // runtime stats + abctime timeJFront; + abctime timeSatLoad; // SAT solver loading time + abctime timeSatUnsat; // unsat + abctime timeSatSat; // sat + abctime timeSatUndec; // undecided + abctime timeTotal; // total runtime + // other statistics + int nPropCalls[3]; + int nFails[2]; + int nClauseConf; + int nDecs; +}; + +static inline int Cbs3_VarUnused( Cbs3_Man_t * p, int iVar ) { return Vec_IntEntry(&p->vLevReason, 3*iVar) == -1; } +static inline void Cbs3_VarSetUnused( Cbs3_Man_t * p, int iVar ) { Vec_IntWriteEntry(&p->vLevReason, 3*iVar, -1); } + +static inline int Cbs3_VarMark0( Cbs3_Man_t * p, int iVar ) { return Vec_StrEntry(&p->vMark, iVar); } +static inline void Cbs3_VarSetMark0( Cbs3_Man_t * p, int iVar, int Value ) { Vec_StrWriteEntry(&p->vMark, iVar, (char)Value); } + +static inline int Cbs3_VarIsAssigned( Cbs3_Man_t * p, int iVar ) { return Vec_StrEntry(&p->vAssign, iVar) < 2; } +static inline void Cbs3_VarUnassign( Cbs3_Man_t * p, int iVar ) { assert( Cbs3_VarIsAssigned(p, iVar)); Vec_StrWriteEntry(&p->vAssign, iVar, (char)(2+Vec_StrEntry(&p->vAssign, iVar))); Cbs3_VarSetUnused(p, iVar); } + +static inline int Cbs3_VarValue( Cbs3_Man_t * p, int iVar ) { return Vec_StrEntry(&p->vAssign, iVar); } +static inline void Cbs3_VarSetValue( Cbs3_Man_t * p, int iVar, int v ) { assert( !Cbs3_VarIsAssigned(p, iVar)); Vec_StrWriteEntry(&p->vAssign, iVar, (char)v); } + +static inline int Cbs3_VarLit0( Cbs3_Man_t * p, int iVar ) { return Vec_IntEntry( &p->vFans, Abc_Var2Lit(iVar, 0) ); } +static inline int Cbs3_VarLit1( Cbs3_Man_t * p, int iVar ) { return Vec_IntEntry( &p->vFans, Abc_Var2Lit(iVar, 1) ); } +static inline int Cbs3_VarIsPi( Cbs3_Man_t * p, int iVar ) { return Vec_IntEntry( &p->vFans, Abc_Var2Lit(iVar, 0) ) == 0; } +static inline int Cbs3_VarIsJust( Cbs3_Man_t * p, int iVar ) { int * pLits = Vec_IntEntryP(&p->vFans, Abc_Var2Lit(iVar, 0)); return pLits[0] > 0 && Cbs3_VarValue(p, Abc_Lit2Var(pLits[0])) >= 2 && Cbs3_VarValue(p, Abc_Lit2Var(pLits[1])) >= 2; } + +static inline int Cbs3_VarDecLevel( Cbs3_Man_t * p, int iVar ) { assert( !Cbs3_VarUnused(p, iVar) ); return Vec_IntEntry(&p->vLevReason, 3*iVar); } +static inline int Cbs3_VarReason0( Cbs3_Man_t * p, int iVar ) { assert( !Cbs3_VarUnused(p, iVar) ); return Vec_IntEntry(&p->vLevReason, 3*iVar+1); } +static inline int Cbs3_VarReason1( Cbs3_Man_t * p, int iVar ) { assert( !Cbs3_VarUnused(p, iVar) ); return Vec_IntEntry(&p->vLevReason, 3*iVar+2); } +static inline int * Cbs3_VarReasonP( Cbs3_Man_t * p, int iVar ) { assert( !Cbs3_VarUnused(p, iVar) ); return Vec_IntEntryP(&p->vLevReason, 3*iVar+1); } +static inline int Cbs3_ClauseDecLevel( Cbs3_Man_t * p, int hClause ) { return Cbs3_VarDecLevel( p, p->pClauses.pData[hClause] ); } + +static inline int Cbs3_ClauseSize( Cbs3_Man_t * p, int hClause ) { return p->pClauses.pData[hClause]; } +static inline int * Cbs3_ClauseLits( Cbs3_Man_t * p, int hClause ) { return p->pClauses.pData+hClause+1; } +static inline int Cbs3_ClauseLit( Cbs3_Man_t * p, int hClause, int i ) { return p->pClauses.pData[hClause+1+i]; } +static inline int * Cbs3_ClauseNext1p( Cbs3_Man_t * p, int hClause ) { return p->pClauses.pData+hClause+Cbs3_ClauseSize(p, hClause)+2; } + +static inline void Cbs3_ClauseSetSize( Cbs3_Man_t * p, int hClause, int x ) { p->pClauses.pData[hClause] = x; } +static inline void Cbs3_ClauseSetLit( Cbs3_Man_t * p, int hClause, int i, int x ) { p->pClauses.pData[hClause+i+1] = x; } +static inline void Cbs3_ClauseSetNext( Cbs3_Man_t * p, int hClause, int n, int x ){ p->pClauses.pData[hClause+Cbs3_ClauseSize(p, hClause)+1+n] = x; } + + +#define Cbs3_QueForEachEntry( Que, iObj, i ) \ + for ( i = (Que).iHead; (i < (Que).iTail) && ((iObj) = (Que).pData[i]); i++ ) + +#define Cbs3_ClauseForEachEntry( p, hClause, iObj, i ) \ + for ( i = 1; i <= Cbs3_ClauseSize(p, hClause) && (iObj = (p)->pClauses.pData[hClause+i]); i++ ) +#define Cbs3_ClauseForEachEntry1( p, hClause, iObj, i ) \ + for ( i = 2; i <= Cbs3_ClauseSize(p, hClause) && (iObj = (p)->pClauses.pData[hClause+i]); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Sets default values of the parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs3_SetDefaultParams( Cbs3_Par_t * pPars ) +{ + memset( pPars, 0, sizeof(Cbs3_Par_t) ); + pPars->nBTLimit = 1000; // limit on the number of conflicts + pPars->nJustLimit = 500; // limit on the size of justification queue + pPars->nRestLimit = 10; // limit on the number of restarts + pPars->fVerbose = 1; // print detailed statistics +} +void Cbs3_ManSetConflictNum( Cbs3_Man_t * p, int Num ) +{ + p->Pars.nBTLimit = Num; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cbs3_Man_t * Cbs3_ManAlloc( Gia_Man_t * pGia ) +{ + Cbs3_Man_t * p; + p = ABC_CALLOC( Cbs3_Man_t, 1 ); + p->pProp.nSize = p->pJust.nSize = p->pClauses.nSize = 10000; + p->pProp.pData = ABC_ALLOC( int, p->pProp.nSize ); + p->pJust.pData = ABC_ALLOC( int, p->pJust.nSize ); + p->pClauses.pData = ABC_ALLOC( int, p->pClauses.nSize ); + p->pClauses.iHead = p->pClauses.iTail = 1; + p->vModel = Vec_IntAlloc( 1000 ); + p->vTemp = Vec_IntAlloc( 1000 ); + p->pAig = pGia; + Cbs3_SetDefaultParams( &p->Pars ); + // circuit structure + Vec_IntPush( &p->vMap, -1 ); + Vec_IntPush( &p->vRef, -1 ); + Vec_IntPushTwo( &p->vFans, -1, -1 ); + Vec_WecPushLevel( &p->vImps ); + Vec_WecPushLevel( &p->vImps ); + p->nVars = 1; + // internal data + p->nVarsAlloc = 1000; + Vec_StrFill( &p->vAssign, p->nVarsAlloc, 2 ); + Vec_StrFill( &p->vMark, p->nVarsAlloc, 0 ); + Vec_IntFill( &p->vLevReason, 3*p->nVarsAlloc, -1 ); + Vec_IntFill( &p->vActs, p->nVarsAlloc, 0 ); + Vec_IntFill( &p->vWatches, 2*p->nVarsAlloc, 0 ); + Vec_IntGrow( &p->vWatchUpds, 1000 ); + return p; +} +static inline void Cbs3_ManReset( Cbs3_Man_t * p ) +{ + assert( p->nVars == Vec_IntSize(&p->vMap) ); + Vec_IntShrink( &p->vMap, 1 ); + Vec_IntShrink( &p->vRef, 1 ); + Vec_IntShrink( &p->vFans, 2 ); + Vec_WecShrink( &p->vImps, 2 ); + p->nVars = 1; +} +static inline void Cbs3_ManGrow( Cbs3_Man_t * p ) +{ + if ( p->nVarsAlloc < p->nVars ) + { + p->nVarsAlloc = 2*p->nVars; + Vec_StrFill( &p->vAssign, p->nVarsAlloc, 2 ); + Vec_StrFill( &p->vMark, p->nVarsAlloc, 0 ); + Vec_IntFill( &p->vLevReason, 3*p->nVarsAlloc, -1 ); + Vec_IntFill( &p->vActs, p->nVarsAlloc, 0 ); + Vec_IntFill( &p->vWatches, 2*p->nVarsAlloc, 0 ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs3_ManStop( Cbs3_Man_t * p ) +{ + // circuit structure + Vec_IntErase( &p->vMap ); + Vec_IntErase( &p->vRef ); + Vec_IntErase( &p->vFans ); + Vec_WecErase( &p->vImps ); + // internal data + Vec_StrErase( &p->vAssign ); + Vec_StrErase( &p->vMark ); + Vec_IntErase( &p->vLevReason ); + Vec_IntErase( &p->vActs ); + Vec_IntErase( &p->vWatches ); + Vec_IntErase( &p->vWatchUpds ); + Vec_IntFree( p->vModel ); + Vec_IntFree( p->vTemp ); + ABC_FREE( p->pClauses.pData ); + ABC_FREE( p->pProp.pData ); + ABC_FREE( p->pJust.pData ); + ABC_FREE( p ); +} +int Cbs3_ManMemory( Cbs3_Man_t * p ) +{ + int nMem = sizeof(Cbs3_Man_t); + nMem += (int)Vec_IntMemory( &p->vMap ); + nMem += (int)Vec_IntMemory( &p->vRef ); + nMem += (int)Vec_IntMemory( &p->vFans ); + nMem += (int)Vec_WecMemory( &p->vImps ); + nMem += (int)Vec_StrMemory( &p->vAssign ); + nMem += (int)Vec_StrMemory( &p->vMark ); + nMem += (int)Vec_IntMemory( &p->vActs ); + nMem += (int)Vec_IntMemory( &p->vWatches ); + nMem += (int)Vec_IntMemory( &p->vWatchUpds ); + nMem += (int)Vec_IntMemory( p->vModel ); + nMem += (int)Vec_IntMemory( p->vTemp ); + nMem += 4*p->pClauses.nSize; + nMem += 4*p->pProp.nSize; + nMem += 4*p->pJust.nSize; + return nMem; +} + +/**Function************************************************************* + + Synopsis [Returns satisfying assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Cbs3_ReadModel( Cbs3_Man_t * p ) +{ + return p->vModel; +} + + +/**Function************************************************************* + + Synopsis [Activity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +//#define USE_ACTIVITY + +#ifdef USE_ACTIVITY +static inline void Cbs3_ActReset( Cbs3_Man_t * p ) +{ + int i, * pAct = Vec_IntArray(&p->vActs); + for ( i = 0; i < p->nVars; i++ ) + pAct[i] = (1 << 10); + p->var_inc = (1 << 5); +} +static inline void Cbs3_ActRescale( Cbs3_Man_t * p ) +{ + int i, * pAct = Vec_IntArray(&p->vActs); + for ( i = 0; i < p->nVars; i++ ) + pAct[i] >>= 19; + p->var_inc >>= 19; + p->var_inc = Abc_MaxInt( (unsigned)p->var_inc, (1<<5) ); +} +static inline void Cbs3_ActBumpVar( Cbs3_Man_t * p, int iVar ) +{ + int * pAct = Vec_IntArray(&p->vActs); + pAct[iVar] += p->var_inc; + if ((unsigned)pAct[iVar] & 0x80000000) + Cbs3_ActRescale(p); +} +static inline void Cbs3_ActDecay( Cbs3_Man_t * p ) +{ + p->var_inc += (p->var_inc >> 4); +} +#else +static inline void Cbs3_ActReset( Cbs3_Man_t * p ) {} +static inline void Cbs3_ActRescale( Cbs3_Man_t * p ) {} +static inline void Cbs3_ActBumpVar( Cbs3_Man_t * p, int iVar ) {} +static inline void Cbs3_ActDecay( Cbs3_Man_t * p ) {} +#endif + + +/**Function************************************************************* + + Synopsis [Returns 1 if the solver is out of limits.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_ManCheckLimits( Cbs3_Man_t * p ) +{ + p->nFails[0] += p->Pars.nJustThis > p->Pars.nJustLimit; + p->nFails[1] += p->Pars.nBTThis > p->Pars.nBTLimit; + return p->Pars.nJustThis > p->Pars.nJustLimit || p->Pars.nBTThis > p->Pars.nBTLimit; +} + +/**Function************************************************************* + + Synopsis [Saves the satisfying assignment as an array of literals.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_ManSaveModel( Cbs3_Man_t * p, Vec_Int_t * vCex ) +{ + int i, iLit; + Vec_IntClear( vCex ); + p->pProp.iHead = 0; + Cbs3_QueForEachEntry( p->pProp, iLit, i ) + if ( Cbs3_VarIsPi(p, Abc_Lit2Var(iLit)) ) + Vec_IntPush( vCex, Abc_Lit2LitV(Vec_IntArray(&p->vMap), iLit)-2 ); +} +static inline void Cbs3_ManSaveModelAll( Cbs3_Man_t * p, Vec_Int_t * vCex ) +{ + int i, iLit; + Vec_IntClear( vCex ); + p->pProp.iHead = 0; + Cbs3_QueForEachEntry( p->pProp, iLit, i ) + { + int iVar = Abc_Lit2Var(iLit); + Vec_IntPush( vCex, Abc_Var2Lit(iVar, !Cbs3_VarValue(p, iVar)) ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_QueIsEmpty( Cbs3_Que_t * p ) +{ + return p->iHead == p->iTail; +} +static inline int Cbs3_QueSize( Cbs3_Que_t * p ) +{ + return p->iTail - p->iHead; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_QuePush( Cbs3_Que_t * p, int iObj ) +{ + if ( p->iTail == p->nSize ) + { + p->nSize *= 2; + p->pData = ABC_REALLOC( int, p->pData, p->nSize ); + } + p->pData[p->iTail++] = iObj; +} +static inline void Cbs3_QueGrow( Cbs3_Que_t * p, int Plus ) +{ + if ( p->iTail + Plus > p->nSize ) + { + p->nSize *= 2; + p->pData = ABC_REALLOC( int, p->pData, p->nSize ); + } + assert( p->iTail + Plus <= p->nSize ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the object in the queue.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_QueHasNode( Cbs3_Que_t * p, int iObj ) +{ + int i, iTemp; + Cbs3_QueForEachEntry( *p, iTemp, i ) + if ( iTemp == iObj ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_QueStore( Cbs3_Que_t * p, int * piHeadOld, int * piTailOld ) +{ + int i; + *piHeadOld = p->iHead; + *piTailOld = p->iTail; + for ( i = *piHeadOld; i < *piTailOld; i++ ) + Cbs3_QuePush( p, p->pData[i] ); + p->iHead = *piTailOld; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_QueRestore( Cbs3_Que_t * p, int iHeadOld, int iTailOld ) +{ + p->iHead = iHeadOld; + p->iTail = iTailOld; +} + +/**Function************************************************************* + + Synopsis [Find variable with the highest ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_ManDecide( Cbs3_Man_t * p ) +{ + int i, iObj, iObjMax = 0; +#ifdef USE_ACTIVITY + Cbs3_QueForEachEntry( p->pJust, iObj, i ) + if ( iObjMax == 0 || + Vec_IntEntry(&p->vActs, iObjMax) < Vec_IntEntry(&p->vActs, iObj) || + (Vec_IntEntry(&p->vActs, iObjMax) == Vec_IntEntry(&p->vActs, iObj) && Vec_IntEntry(&p->vMap, iObjMax) < Vec_IntEntry(&p->vMap, iObj)) ) + iObjMax = iObj; +#else + Cbs3_QueForEachEntry( p->pJust, iObj, i ) +// if ( iObjMax == 0 || iObjMax < iObj ) + if ( iObjMax == 0 || Vec_IntEntry(&p->vMap, iObjMax) < Vec_IntEntry(&p->vMap, iObj) ) + iObjMax = iObj; +#endif + return iObjMax; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_ManCancelUntil( Cbs3_Man_t * p, int iBound ) +{ + int i, iLit; + assert( iBound <= p->pProp.iTail ); + p->pProp.iHead = iBound; + Cbs3_QueForEachEntry( p->pProp, iLit, i ) + Cbs3_VarUnassign( p, Abc_Lit2Var(iLit) ); + p->pProp.iTail = iBound; +} + +/**Function************************************************************* + + Synopsis [Assigns the variables a value.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_ManAssign( Cbs3_Man_t * p, int iLit, int Level, int iRes0, int iRes1 ) +{ + int iObj = Abc_Lit2Var(iLit); + assert( Cbs3_VarUnused(p, iObj) ); + assert( !Cbs3_VarIsAssigned(p, iObj) ); + Cbs3_VarSetValue( p, iObj, !Abc_LitIsCompl(iLit) ); + Cbs3_QuePush( &p->pProp, iLit ); + Vec_IntWriteEntry( &p->vLevReason, 3*iObj, Level ); + Vec_IntWriteEntry( &p->vLevReason, 3*iObj+1, iRes0 ); + Vec_IntWriteEntry( &p->vLevReason, 3*iObj+2, iRes1 ); +} + + + + +/**Function************************************************************* + + Synopsis [Prints conflict clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_ManPrintClause( Cbs3_Man_t * p, int Level, int hClause ) +{ + int i, iLit; + assert( Cbs3_QueIsEmpty( &p->pClauses ) ); + printf( "Level %2d : ", Level ); + Cbs3_ClauseForEachEntry( p, hClause, iLit, i ) + printf( "%c%d ", Abc_LitIsCompl(iLit) ? '-':'+', Abc_Lit2Var(iLit) ); +// printf( "%d=%d(%d) ", iObj, Cbs3_VarValue(p, Abc_Lit2Var(iLit)), Cbs3_VarDecLevel(p, Abc_Lit2Var(iLit)) ); + printf( "\n" ); +} +static inline void Cbs3_ManPrintCube( Cbs3_Man_t * p, int Level, int hClause ) +{ + int i, iObj; + assert( Cbs3_QueIsEmpty( &p->pClauses ) ); + printf( "Level %2d : ", Level ); + Cbs3_ClauseForEachEntry( p, hClause, iObj, i ) + printf( "%c%d ", Cbs3_VarValue(p, iObj)? '+':'-', iObj ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Finalized the clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_ManCleanWatch( Cbs3_Man_t * p ) +{ + int i, iLit; + Vec_IntForEachEntry( &p->vWatchUpds, iLit, i ) + Vec_IntWriteEntry( &p->vWatches, iLit, 0 ); + Vec_IntClear( &p->vWatchUpds ); + //Vec_IntForEachEntry( &p->vWatches, iLit, i ) + // assert( iLit == 0 ); +} +static inline void Cbs3_ManWatchClause( Cbs3_Man_t * p, int hClause, int Lit ) +{ + int * pLits = Cbs3_ClauseLits( p, hClause ); + int * pPlace = Vec_IntEntryP( &p->vWatches, Abc_LitNot(Lit) ); + if ( *pPlace == 0 ) + Vec_IntPush( &p->vWatchUpds, Abc_LitNot(Lit) ); +/* + if ( pClause->pLits[0] == Lit ) + pClause->pNext0 = p->pWatches[lit_neg(Lit)]; + else + { + assert( pClause->pLits[1] == Lit ); + pClause->pNext1 = p->pWatches[lit_neg(Lit)]; + } + p->pWatches[lit_neg(Lit)] = pClause; +*/ + assert( Lit == pLits[0] || Lit == pLits[1] ); + Cbs3_ClauseSetNext( p, hClause, Lit == pLits[1], *pPlace ); + *pPlace = hClause; +} +static inline int Cbs3_QueFinish( Cbs3_Man_t * p, int Level ) +{ + Cbs3_Que_t * pQue = &(p->pClauses); + int i, iObj, hClauseC, hClause = pQue->iHead, Size = pQue->iTail - pQue->iHead - 1; + assert( pQue->iHead+1 < pQue->iTail ); + Cbs3_ClauseSetSize( p, pQue->iHead, Size ); + hClauseC = pQue->iHead = pQue->iTail; + //printf( "Adding cube: " ); Cbs3_ManPrintCube(p, Level, hClause); + if ( Size == 1 ) + return hClause; + // create watched clause + pQue->iHead = hClause; + Cbs3_QueForEachEntry( p->pClauses, iObj, i ) + { + if ( i == hClauseC ) + break; + else if ( i == hClause ) // nlits + Cbs3_QuePush( pQue, iObj ); + else // literals + Cbs3_QuePush( pQue, Abc_Var2Lit(iObj, Cbs3_VarValue(p, iObj)) ); // complement + } + Cbs3_QuePush( pQue, 0 ); // next0 + Cbs3_QuePush( pQue, 0 ); // next1 + pQue->iHead = pQue->iTail; + Cbs3_ManWatchClause( p, hClauseC, Cbs3_ClauseLit(p, hClauseC, 0) ); + Cbs3_ManWatchClause( p, hClauseC, Cbs3_ClauseLit(p, hClauseC, 1) ); + //printf( "Adding clause %d: ", hClauseC ); Cbs3_ManPrintClause(p, Level, hClauseC); + Cbs3_ActDecay( p ); + return hClause; +} + +/**Function************************************************************* + + Synopsis [Returns conflict clause.] + + Description [Performs conflict analysis.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_ManDeriveReason( Cbs3_Man_t * p, int Level ) +{ + Cbs3_Que_t * pQue = &(p->pClauses); + int i, k, iObj, iLitLevel, * pReason; + assert( pQue->pData[pQue->iHead] == 0 ); + assert( pQue->pData[pQue->iHead+1] == 0 ); + assert( pQue->iHead + 2 < pQue->iTail ); + //for ( i = pQue->iHead + 2; i < pQue->iTail; i++ ) + // assert( !Cbs3_VarMark0(p, pQue->pData[i]) ); + // compact literals + Vec_IntClear( p->vTemp ); + for ( i = k = pQue->iHead + 2; i < pQue->iTail; i++ ) + { + iObj = pQue->pData[i]; + if ( Cbs3_VarMark0(p, iObj) ) // unassigned - seen again + continue; + //if ( Vec_IntEntry(&p->vActivity, iObj) == 0 ) + // Vec_IntPush( &p->vActStore, iObj ); + //Vec_IntAddToEntry( &p->vActivity, iObj, 1 ); + // assigned - seen first time + Cbs3_VarSetMark0(p, iObj, 1); + Cbs3_ActBumpVar(p, iObj); + Vec_IntPush( p->vTemp, iObj ); + // check decision level + iLitLevel = Cbs3_VarDecLevel( p, iObj ); + if ( iLitLevel < Level ) + { + pQue->pData[k++] = iObj; + continue; + } + assert( iLitLevel == Level ); + pReason = Cbs3_VarReasonP( p, iObj ); + if ( pReason[0] == 0 && pReason[1] == 0 ) // no reason + { + assert( pQue->pData[pQue->iHead+1] == 0 ); + pQue->pData[pQue->iHead+1] = iObj; + } + else if ( pReason[0] != 0 ) // circuit reason + { + Cbs3_QuePush( pQue, pReason[0] ); + if ( pReason[1] ) + Cbs3_QuePush( pQue, pReason[1] ); + } + else // clause reason + { + int i, * pLits, nLits = Cbs3_ClauseSize( p, pReason[1] ); + assert( pReason[1] ); + Cbs3_QueGrow( pQue, nLits ); + pLits = Cbs3_ClauseLits( p, pReason[1] ); + assert( iObj == Abc_Lit2Var(pLits[0]) ); + for ( i = 1; i < nLits; i++ ) + Cbs3_QuePush( pQue, Abc_Lit2Var(pLits[i]) ); + } + } + assert( pQue->pData[pQue->iHead] == 0 ); + assert( pQue->pData[pQue->iHead+1] != 0 ); + pQue->iTail = k; + // clear the marks + Vec_IntForEachEntry( p->vTemp, iObj, i ) + Cbs3_VarSetMark0(p, iObj, 0); + return Cbs3_QueFinish( p, Level ); +} +static inline int Cbs3_ManAnalyze( Cbs3_Man_t * p, int Level, int iVar, int iFan0, int iFan1 ) +{ + Cbs3_Que_t * pQue = &(p->pClauses); + assert( Cbs3_VarIsAssigned(p, iVar) ); + assert( Cbs3_QueIsEmpty( pQue ) ); + Cbs3_QuePush( pQue, 0 ); + Cbs3_QuePush( pQue, 0 ); + if ( iFan0 ) // circuit conflict + { + assert( Cbs3_VarIsAssigned(p, iFan0) ); + assert( iFan1 == 0 || Cbs3_VarIsAssigned(p, iFan1) ); + Cbs3_QuePush( pQue, iVar ); + Cbs3_QuePush( pQue, iFan0 ); + if ( iFan1 ) + Cbs3_QuePush( pQue, iFan1 ); + } + else // clause conflict + { + int i, * pLits, nLits = Cbs3_ClauseSize( p, iFan1 ); + assert( iFan1 ); + Cbs3_QueGrow( pQue, nLits ); + pLits = Cbs3_ClauseLits( p, iFan1 ); + assert( iVar == Abc_Lit2Var(pLits[0]) ); + assert( Cbs3_VarValue(p, iVar) == Abc_LitIsCompl(pLits[0]) ); + for ( i = 0; i < nLits; i++ ) + Cbs3_QuePush( pQue, Abc_Lit2Var(pLits[i]) ); + } + return Cbs3_ManDeriveReason( p, Level ); +} + + +/**Function************************************************************* + + Synopsis [Propagate one assignment.] + + Description [Returns handle of the conflict clause, if conflict occurs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_ManPropagateClauses( Cbs3_Man_t * p, int Level, int Lit ) +{ + int i, Value, Cur, LitF = Abc_LitNot(Lit); + int * pPrev = Vec_IntEntryP( &p->vWatches, Lit ); + //for ( pCur = p->pWatches[Lit]; pCur; pCur = *ppPrev ) + for ( Cur = *pPrev; Cur; Cur = *pPrev ) + { + int nLits = Cbs3_ClauseSize( p, Cur ); + int * pLits = Cbs3_ClauseLits( p, Cur ); + p->nPropCalls[1]++; +//printf( " Watching literal %c%d on level %d.\n", Abc_LitIsCompl(Lit) ? '-':'+', Abc_Lit2Var(Lit), Level ); + // make sure the false literal is in the second literal of the clause + //if ( pCur->pLits[0] == LitF ) + if ( pLits[0] == LitF ) + { + //pCur->pLits[0] = pCur->pLits[1]; + pLits[0] = pLits[1]; + //pCur->pLits[1] = LitF; + pLits[1] = LitF; + //pTemp = pCur->pNext0; + //pCur->pNext0 = pCur->pNext1; + //pCur->pNext1 = pTemp; + ABC_SWAP( int, pLits[nLits], pLits[nLits+1] ); + } + //assert( pCur->pLits[1] == LitF ); + assert( pLits[1] == LitF ); + + // if the first literal is true, the clause is satisfied + //if ( pCur->pLits[0] == p->pAssigns[lit_var(pCur->pLits[0])] ) + if ( Cbs3_VarValue(p, Abc_Lit2Var(pLits[0])) == !Abc_LitIsCompl(pLits[0]) ) + { + //ppPrev = &pCur->pNext1; + pPrev = Cbs3_ClauseNext1p(p, Cur); + continue; + } + + // look for a new literal to watch + for ( i = 2; i < nLits; i++ ) + { + // skip the case when the literal is false + //if ( lit_neg(pCur->pLits[i]) == p->pAssigns[lit_var(pCur->pLits[i])] ) + if ( Cbs3_VarValue(p, Abc_Lit2Var(pLits[i])) == Abc_LitIsCompl(pLits[i]) ) + continue; + // the literal is either true or unassigned - watch it + //pCur->pLits[1] = pCur->pLits[i]; + //pCur->pLits[i] = LitF; + pLits[1] = pLits[i]; + pLits[i] = LitF; + // remove this clause from the watch list of Lit + //*ppPrev = pCur->pNext1; + *pPrev = *Cbs3_ClauseNext1p(p, Cur); + // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1]) + //Intb_ManWatchClause( p, pCur, pCur->pLits[1] ); + Cbs3_ManWatchClause( p, Cur, Cbs3_ClauseLit(p, Cur, 1) ); + break; + } + if ( i < nLits ) // found new watch + continue; + + // clause is unit - enqueue new implication + //if ( Inta_ManEnqueue(p, pCur->pLits[0], pCur) ) + //{ + // ppPrev = &pCur->pNext1; + // continue; + //} + + // clause is unit - enqueue new implication + Value = Cbs3_VarValue(p, Abc_Lit2Var(pLits[0])); + if ( Value >= 2 ) // unassigned + { + Cbs3_ManAssign( p, pLits[0], Level, 0, Cur ); + pPrev = Cbs3_ClauseNext1p(p, Cur); + continue; + } + + // conflict detected - return the conflict clause + //return pCur; + if ( Value == Abc_LitIsCompl(pLits[0]) ) + { + p->nClauseConf++; + return Cbs3_ManAnalyze( p, Level, Abc_Lit2Var(pLits[0]), 0, Cur ); + } + } + return 0; +} + + +/**Function************************************************************* + + Synopsis [Performs resolution of two clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_ManResolve( Cbs3_Man_t * p, int Level, int hClause0, int hClause1 ) +{ + Cbs3_Que_t * pQue = &(p->pClauses); + int i, iObj, LevelMax = -1, LevelCur; + assert( pQue->pData[hClause0+1] != 0 ); + assert( pQue->pData[hClause0+1] == pQue->pData[hClause1+1] ); + //Cbs3_ClauseForEachEntry1( p, hClause0, iObj, i ) + // assert( !Cbs3_VarMark0(p, iObj) ); + //Cbs3_ClauseForEachEntry1( p, hClause1, iObj, i ) + // assert( !Cbs3_VarMark0(p, iObj) ); + assert( Cbs3_QueIsEmpty( pQue ) ); + Cbs3_QuePush( pQue, 0 ); + Cbs3_QuePush( pQue, 0 ); +// for ( i = hClause0 + 1; (iObj = pQue->pData[i]); i++ ) + Cbs3_ClauseForEachEntry1( p, hClause0, iObj, i ) + { + if ( Cbs3_VarMark0(p, iObj) ) // unassigned - seen again + continue; + //if ( Vec_IntEntry(&p->vActivity, iObj) == 0 ) + // Vec_IntPush( &p->vActStore, iObj ); + //Vec_IntAddToEntry( &p->vActivity, iObj, 1 ); + // assigned - seen first time + Cbs3_VarSetMark0(p, iObj, 1); + Cbs3_ActBumpVar(p, iObj); + Cbs3_QuePush( pQue, iObj ); + LevelCur = Cbs3_VarDecLevel( p, iObj ); + if ( LevelMax < LevelCur ) + LevelMax = LevelCur; + } +// for ( i = hClause1 + 1; (iObj = pQue->pData[i]); i++ ) + Cbs3_ClauseForEachEntry1( p, hClause1, iObj, i ) + { + if ( Cbs3_VarMark0(p, iObj) ) // unassigned - seen again + continue; + //if ( Vec_IntEntry(&p->vActivity, iObj) == 0 ) + // Vec_IntPush( &p->vActStore, iObj ); + //Vec_IntAddToEntry( &p->vActivity, iObj, 1 ); + // assigned - seen first time + Cbs3_VarSetMark0(p, iObj, 1); + Cbs3_ActBumpVar(p, iObj); + Cbs3_QuePush( pQue, iObj ); + LevelCur = Cbs3_VarDecLevel( p, iObj ); + if ( LevelMax < LevelCur ) + LevelMax = LevelCur; + } + for ( i = pQue->iHead + 2; i < pQue->iTail; i++ ) + Cbs3_VarSetMark0(p, pQue->pData[i], 0); + return Cbs3_ManDeriveReason( p, LevelMax ); +} + +/**Function************************************************************* + + Synopsis [Propagates a variable.] + + Description [Returns clause handle if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs3_ManUpdateJFrontier( Cbs3_Man_t * p ) +{ + //abctime clk = Abc_Clock(); + int iVar, iLit, i, k = p->pJust.iTail; + Cbs3_QueGrow( &p->pJust, Cbs3_QueSize(&p->pJust) + Cbs3_QueSize(&p->pProp) ); + Cbs3_QueForEachEntry( p->pJust, iVar, i ) + if ( Cbs3_VarIsJust(p, iVar) ) + p->pJust.pData[k++] = iVar; + Cbs3_QueForEachEntry( p->pProp, iLit, i ) + if ( Cbs3_VarIsJust(p, Abc_Lit2Var(iLit)) ) + p->pJust.pData[k++] = Abc_Lit2Var(iLit); + p->pJust.iHead = p->pJust.iTail; + p->pJust.iTail = k; + //p->timeJFront += Abc_Clock() - clk; +} +int Cbs3_ManPropagateNew( Cbs3_Man_t * p, int Level ) +{ + int i, k, iLit, hClause, nLits, * pLits; + p->nPropCalls[0]++; + Cbs3_QueForEachEntry( p->pProp, iLit, i ) + { + if ( (hClause = Cbs3_ManPropagateClauses(p, Level, iLit)) ) + return hClause; + p->nPropCalls[2]++; + nLits = Vec_IntSize(Vec_WecEntry(&p->vImps, iLit)); + pLits = Vec_IntArray(Vec_WecEntry(&p->vImps, iLit)); + for ( k = 0; k < nLits; k += 2 ) + { + int Value0 = Cbs3_VarValue(p, Abc_Lit2Var(pLits[k])); + int Value1 = pLits[k+1] ? Cbs3_VarValue(p, Abc_Lit2Var(pLits[k+1])) : -1; + if ( Value1 == -1 || Value1 == Abc_LitIsCompl(pLits[k+1]) ) // pLits[k+1] is false + { + if ( Value0 >= 2 ) // pLits[k] is unassigned + Cbs3_ManAssign( p, pLits[k], Level, Abc_Lit2Var(iLit), Abc_Lit2Var(pLits[k+1]) ); + else if ( Value0 == Abc_LitIsCompl(pLits[k]) ) // pLits[k] is false + return Cbs3_ManAnalyze( p, Level, Abc_Lit2Var(iLit), Abc_Lit2Var(pLits[k]), Abc_Lit2Var(pLits[k+1]) ); + } + if ( Value1 != -1 && Value0 == Abc_LitIsCompl(pLits[k]) ) // pLits[k] is false + { + if ( Value1 >= 2 ) // pLits[k+1] is unassigned + Cbs3_ManAssign( p, pLits[k+1], Level, Abc_Lit2Var(iLit), Abc_Lit2Var(pLits[k]) ); + else if ( Value1 == Abc_LitIsCompl(pLits[k+1]) ) // pLits[k+1] is false + return Cbs3_ManAnalyze( p, Level, Abc_Lit2Var(iLit), Abc_Lit2Var(pLits[k]), Abc_Lit2Var(pLits[k+1]) ); + } + } + } + Cbs3_ManUpdateJFrontier( p ); + // finalize propagation queue + p->pProp.iHead = p->pProp.iTail; + return 0; +} + +/**Function************************************************************* + + Synopsis [Solve the problem recursively.] + + Description [Returns learnt clause if unsat, NULL if sat or undecided.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cbs3_ManSolve2_rec( Cbs3_Man_t * p, int Level ) +{ + Cbs3_Que_t * pQue = &(p->pClauses); + int iPropHead, iJustHead, iJustTail; + int hClause, hLearn0, hLearn1, iVar, iDecLit; + int nRef0, nRef1; + // propagate assignments + assert( !Cbs3_QueIsEmpty(&p->pProp) ); + //if ( (hClause = Cbs3_ManPropagate( p, Level )) ) + if ( (hClause = Cbs3_ManPropagateNew( p, Level )) ) + return hClause; + // check for satisfying assignment + assert( Cbs3_QueIsEmpty(&p->pProp) ); + if ( Cbs3_QueIsEmpty(&p->pJust) ) + return 0; + // quit using resource limits + p->Pars.nJustThis = Abc_MaxInt( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead ); + if ( Cbs3_ManCheckLimits( p ) ) + return 0; + // remember the state before branching + iPropHead = p->pProp.iHead; + iJustHead = p->pJust.iHead; + iJustTail = p->pJust.iTail; + // find the decision variable + p->nDecs++; + iVar = Cbs3_ManDecide( p ); + assert( !Cbs3_VarIsPi(p, iVar) ); + assert( Cbs3_VarIsJust(p, iVar) ); + // chose decision variable using fanout count + nRef0 = Vec_IntEntry(&p->vRef, Abc_Lit2Var(Cbs3_VarLit0(p, iVar))); + nRef1 = Vec_IntEntry(&p->vRef, Abc_Lit2Var(Cbs3_VarLit1(p, iVar))); +// if ( nRef0 >= nRef1 || (nRef0 == nRef1) && (Abc_Random(0) & 1) ) + if ( nRef0 >= nRef1 ) + iDecLit = Abc_LitNot(Cbs3_VarLit0(p, iVar)); + else + iDecLit = Abc_LitNot(Cbs3_VarLit1(p, iVar)); + // decide on first fanin + Cbs3_ManAssign( p, iDecLit, Level+1, 0, 0 ); + if ( !(hLearn0 = Cbs3_ManSolve2_rec( p, Level+1 )) ) + return 0; + if ( pQue->pData[hLearn0+1] != Abc_Lit2Var(iDecLit) ) + return hLearn0; + Cbs3_ManCancelUntil( p, iPropHead ); + Cbs3_QueRestore( &p->pJust, iJustHead, iJustTail ); + // decide on second fanin + Cbs3_ManAssign( p, Abc_LitNot(iDecLit), Level+1, 0, 0 ); + if ( !(hLearn1 = Cbs3_ManSolve2_rec( p, Level+1 )) ) + return 0; + if ( pQue->pData[hLearn1+1] != Abc_Lit2Var(iDecLit) ) + return hLearn1; + hClause = Cbs3_ManResolve( p, Level, hLearn0, hLearn1 ); + p->Pars.nBTThis++; + return hClause; +} + +/**Function************************************************************* + + Synopsis [Looking for a satisfying assignment of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_ManSolveInt( Cbs3_Man_t * p, int iLit ) +{ + int RetValue = 0; + assert( !p->pProp.iHead && !p->pProp.iTail ); + assert( !p->pJust.iHead && !p->pJust.iTail ); + p->Pars.nBTThis = p->Pars.nJustThis = 0; + Cbs3_ManAssign( p, iLit, 0, 0, 0 ); + if ( !Cbs3_ManSolve2_rec(p, 0) && !Cbs3_ManCheckLimits(p) ) + Cbs3_ManSaveModel( p, p->vModel ); + else + RetValue = 1; + Cbs3_ManCancelUntil( p, 0 ); + p->pJust.iHead = p->pJust.iTail = 0; + p->Pars.nBTTotal += p->Pars.nBTThis; + p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis ); + if ( Cbs3_ManCheckLimits( p ) ) + RetValue = -1; + return RetValue; +} +int Cbs3_ManSolve( Cbs3_Man_t * p, int iLit, int nRestarts ) +{ + int i, RetValue = -1; + assert( p->pClauses.iHead == 1 && p->pClauses.iTail == 1 ); + for ( i = 0; i < nRestarts; i++ ) + if ( (RetValue = Cbs3_ManSolveInt(p, iLit)) != -1 ) + break; + Cbs3_ManCleanWatch( p ); + p->pClauses.iHead = p->pClauses.iTail = 1; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Prints statistics of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs3_ManSatPrintStats( Cbs3_Man_t * p ) +{ + printf( "CO = %8d ", Gia_ManCoNum(p->pAig) ); + printf( "AND = %8d ", Gia_ManAndNum(p->pAig) ); + printf( "Conf = %6d ", p->Pars.nBTLimit ); + printf( "Restart = %2d ", p->Pars.nRestLimit ); + printf( "JustMax = %5d ", p->Pars.nJustLimit ); + printf( "\n" ); + printf( "Unsat calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatUnsat, p->nSatTotal? 100.0*p->nSatUnsat/p->nSatTotal :0.0, p->nSatUnsat? 1.0*p->nConfUnsat/p->nSatUnsat :0.0 ); + ABC_PRTP( "Time", p->timeSatUnsat, p->timeTotal ); + printf( "Sat calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatSat, p->nSatTotal? 100.0*p->nSatSat/p->nSatTotal :0.0, p->nSatSat? 1.0*p->nConfSat/p->nSatSat : 0.0 ); + ABC_PRTP( "Time", p->timeSatSat, p->timeTotal ); + printf( "Undef calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatUndec, p->nSatTotal? 100.0*p->nSatUndec/p->nSatTotal :0.0, p->nSatUndec? 1.0*p->nConfUndec/p->nSatUndec : 0.0 ); + ABC_PRTP( "Time", p->timeSatUndec, p->timeTotal ); + ABC_PRT( "Total time", p->timeTotal ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs3_ManAddVar( Cbs3_Man_t * p, int iGiaObj ) +{ + assert( Vec_IntSize(&p->vMap) == p->nVars ); + Vec_IntPush( &p->vMap, iGiaObj ); + Vec_IntPush( &p->vRef, Gia_ObjRefNumId(p->pAig, iGiaObj) ); + Vec_IntPushTwo( &p->vFans, 0, 0 ); + Vec_WecPushLevel(&p->vImps); + Vec_WecPushLevel(&p->vImps); + return Abc_Var2Lit( p->nVars++, 0 ); +} +static inline void Cbs3_ManAddConstr( Cbs3_Man_t * p, int x, int x0, int x1 ) +{ + Vec_WecPushTwo( &p->vImps, x , x0, 0 ); // ~x + x0 + Vec_WecPushTwo( &p->vImps, x , x1, 0 ); // ~x + x1 + Vec_WecPushTwo( &p->vImps, 1^x0, 1^x , 0 ); // ~x + x0 + Vec_WecPushTwo( &p->vImps, 1^x1, 1^x , 0 ); // ~x + x1 + Vec_WecPushTwo( &p->vImps, 1^x , 1^x0, 1^x1 ); // x + ~x0 + ~x1 + Vec_WecPushTwo( &p->vImps, x0, x , 1^x1 ); // x + ~x0 + ~x1 + Vec_WecPushTwo( &p->vImps, x1, x , 1^x0 ); // x + ~x0 + ~x1 +} +static inline void Cbs3_ManAddAnd( Cbs3_Man_t * p, int x, int x0, int x1 ) +{ + assert( x > 0 && x0 > 0 && x1 > 0 ); + Vec_IntWriteEntry( &p->vFans, x, x0 ); + Vec_IntWriteEntry( &p->vFans, x+1, x1 ); + Cbs3_ManAddConstr( p, x, x0, x1 ); +} +static inline int Cbs3_ManToSolver1_rec( Cbs3_Man_t * pSol, Gia_Man_t * p, int iObj, int Depth ) +{ + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); int Lit0, Lit1; + if ( Gia_ObjUpdateTravIdCurrentId(p, iObj) ) + return pObj->Value; + pObj->Value = Cbs3_ManAddVar( pSol, iObj ); + if ( Gia_ObjIsCi(pObj) || Depth == 0 ) + return pObj->Value; + assert( Gia_ObjIsAnd(pObj) ); + Lit0 = Cbs3_ManToSolver1_rec( pSol, p, Gia_ObjFaninId0(pObj, iObj), Depth - Gia_ObjFaninC0(pObj) ); + Lit1 = Cbs3_ManToSolver1_rec( pSol, p, Gia_ObjFaninId1(pObj, iObj), Depth - Gia_ObjFaninC1(pObj) ); + Cbs3_ManAddAnd( pSol, pObj->Value, Lit0 ^ Gia_ObjFaninC0(pObj), Lit1 ^ Gia_ObjFaninC1(pObj) ); + return pObj->Value; +} +static inline int Cbs3_ManToSolver1( Cbs3_Man_t * pSol, Gia_Man_t * p, Gia_Obj_t * pRoot, int nRestarts, int Depth ) +{ + //abctime clk = Abc_Clock(); + assert( Gia_ObjIsCo(pRoot) ); + Cbs3_ManReset( pSol ); + Gia_ManIncrementTravId( p ); + Cbs3_ManToSolver1_rec( pSol, p, Gia_ObjFaninId0p(p, pRoot), Depth ); + Cbs3_ManGrow( pSol ); + Cbs3_ActReset( pSol ); + //pSol->timeSatLoad += Abc_Clock() - clk; + return Cbs3_ManSolve( pSol, Gia_ObjFanin0Copy(pRoot), nRestarts ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs3_ManPrepare( Cbs3_Man_t * p ) +{ + int x, x0, x1; + Vec_WecInit( &p->vImps, Abc_Var2Lit(p->nVars, 0) ); + Vec_IntForEachEntryDoubleStart( &p->vFans, x0, x1, x, 2 ) + if ( x0 ) Cbs3_ManAddConstr( p, x, x0, x1 ); +} +static inline int Cbs3_ManAddNode( Cbs3_Man_t * p, int iGiaObj, int iLit0, int iLit1 ) +{ + assert( Vec_IntSize(&p->vMap) == p->nVars ); + Vec_IntPush( &p->vMap, iGiaObj ); + Vec_IntPush( &p->vRef, Gia_ObjRefNumId(p->pAig, iGiaObj) ); + Vec_IntPushTwo( &p->vFans, iLit0, iLit1 ); + return Abc_Var2Lit( p->nVars++, 0 ); +} +static inline int Cbs3_ManToSolver2_rec( Cbs3_Man_t * pSol, Gia_Man_t * p, int iObj, int Depth ) +{ + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); int Lit0, Lit1; + if ( Gia_ObjUpdateTravIdCurrentId(p, iObj) ) + return pObj->Value; + if ( Gia_ObjIsCi(pObj) || Depth == 0 ) + return pObj->Value = Cbs3_ManAddNode(pSol, iObj, 0, 0); + assert( Gia_ObjIsAnd(pObj) ); + Lit0 = Cbs3_ManToSolver2_rec( pSol, p, Gia_ObjFaninId0(pObj, iObj), Depth - Gia_ObjFaninC0(pObj) ); + Lit1 = Cbs3_ManToSolver2_rec( pSol, p, Gia_ObjFaninId1(pObj, iObj), Depth - Gia_ObjFaninC1(pObj) ); + return pObj->Value = Cbs3_ManAddNode(pSol, iObj, Lit0 ^ Gia_ObjFaninC0(pObj), Lit1 ^ Gia_ObjFaninC1(pObj)); +} +static inline int Cbs3_ManToSolver2( Cbs3_Man_t * pSol, Gia_Man_t * p, Gia_Obj_t * pRoot, int nRestarts, int Depth ) +{ + //abctime clk = Abc_Clock(); + assert( Gia_ObjIsCo(pRoot) ); + Cbs3_ManReset( pSol ); + Gia_ManIncrementTravId( p ); + Cbs3_ManToSolver2_rec( pSol, p, Gia_ObjFaninId0p(p, pRoot), Depth ); + Cbs3_ManGrow( pSol ); + Cbs3_ManPrepare( pSol ); + Cbs3_ActReset( pSol ); + //pSol->timeSatLoad += Abc_Clock() - clk; + return Cbs3_ManSolve( pSol, Gia_ObjFanin0Copy(pRoot), nRestarts ); +} + + +/**Function************************************************************* + + Synopsis [Procedure to test the new SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Cbs3_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, int nRestarts, Vec_Str_t ** pvStatus, int fVerbose ) +{ + extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out ); + Cbs3_Man_t * p; + Vec_Int_t * vCex, * vVisit, * vCexStore; + Vec_Str_t * vStatus; + Gia_Obj_t * pRoot; + int i, status; // 1 = unsat, 0 = sat, -1 = undec + abctime clk, clkTotal = Abc_Clock(); + //assert( Gia_ManRegNum(pAig) == 0 ); + Gia_ManCreateRefs( pAig ); + //Gia_ManLevelNum( pAig ); + // create logic network + p = Cbs3_ManAlloc( pAig ); + p->Pars.nBTLimit = nConfs; + p->Pars.nRestLimit = nRestarts; + // create resulting data-structures + vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) ); + vCexStore = Vec_IntAlloc( 10000 ); + vVisit = Vec_IntAlloc( 100 ); + vCex = Cbs3_ReadModel( p ); + // solve for each output + Gia_ManForEachCo( pAig, pRoot, i ) + { + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pRoot)) ) + { + Vec_IntClear( vCex ); + Vec_StrPush( vStatus, (char)(!Gia_ObjFaninC0(pRoot)) ); + if ( Gia_ObjFaninC0(pRoot) ) // const1 + Cec_ManSatAddToStore( vCexStore, vCex, i ); // trivial counter-example + continue; + } + clk = Abc_Clock(); + status = Cbs3_ManToSolver2( p, pAig, pRoot, p->Pars.nRestLimit, 10000 ); + Vec_StrPush( vStatus, (char)status ); + if ( status == -1 ) + { + p->nSatUndec++; + p->nConfUndec += p->Pars.nBTThis; + Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout + p->timeSatUndec += Abc_Clock() - clk; + continue; + } + if ( status == 1 ) + { + p->nSatUnsat++; + p->nConfUnsat += p->Pars.nBTThis; + p->timeSatUnsat += Abc_Clock() - clk; + continue; + } + p->nSatSat++; + p->nConfSat += p->Pars.nBTThis; + //Gia_SatVerifyPattern( pAig, pRoot, vCex, vVisit ); + Cec_ManSatAddToStore( vCexStore, vCex, i ); + p->timeSatSat += Abc_Clock() - clk; + } + Vec_IntFree( vVisit ); + p->nSatTotal = Gia_ManPoNum(pAig); + p->timeTotal = Abc_Clock() - clkTotal; + if ( fVerbose ) + Cbs3_ManSatPrintStats( p ); + if ( fVerbose ) + { + printf( "Prop1 = %d. Prop2 = %d. Prop3 = %d. ClaConf = %d. FailJ = %d. FailC = %d. ", p->nPropCalls[0], p->nPropCalls[1], p->nPropCalls[2], p->nClauseConf, p->nFails[0], p->nFails[1] ); + printf( "Mem usage %.2f MB.\n", 1.0*Cbs3_ManMemory(p)/(1<<20) ); + //Abc_PrintTime( 1, "JFront", p->timeJFront ); + //Abc_PrintTime( 1, "Loading", p->timeSatLoad ); + //printf( "Decisions = %d.\n", p->nDecs ); + } + Cbs3_ManStop( p ); + *pvStatus = vStatus; + return vCexStore; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaCSatOld.c b/yosys/abc/src/aig/gia/giaCSatOld.c new file mode 100644 index 00000000000..43a65a4b5fe --- /dev/null +++ b/yosys/abc/src/aig/gia/giaCSatOld.c @@ -0,0 +1,804 @@ +/**CFile**************************************************************** + + FileName [giaCSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [A simple circuit-based solver.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaCSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Cbs0_Par_t_ Cbs0_Par_t; +struct Cbs0_Par_t_ +{ + // conflict limits + int nBTLimit; // limit on the number of conflicts + int nJustLimit; // limit on the size of justification queue + // current parameters + int nBTThis; // number of conflicts + int nJustThis; // max size of the frontier + int nBTTotal; // total number of conflicts + int nJustTotal; // total size of the frontier + // decision heuristics + int fUseHighest; // use node with the highest ID + int fUseLowest; // use node with the highest ID + int fUseMaxFF; // use node with the largest fanin fanout + // other + int fVerbose; +}; + +typedef struct Cbs0_Que_t_ Cbs0_Que_t; +struct Cbs0_Que_t_ +{ + int iHead; // beginning of the queue + int iTail; // end of the queue + int nSize; // allocated size + Gia_Obj_t ** pData; // nodes stored in the queue +}; + +typedef struct Cbs0_Man_t_ Cbs0_Man_t; +struct Cbs0_Man_t_ +{ + Cbs0_Par_t Pars; // parameters + Gia_Man_t * pAig; // AIG manager + Cbs0_Que_t pProp; // propagation queue + Cbs0_Que_t pJust; // justification queue + Vec_Int_t * vModel; // satisfying assignment + // SAT calls statistics + int nSatUnsat; // the number of proofs + int nSatSat; // the number of failure + int nSatUndec; // the number of timeouts + int nSatTotal; // the number of calls + // conflicts + int nConfUnsat; // conflicts in unsat problems + int nConfSat; // conflicts in sat problems + int nConfUndec; // conflicts in undec problems + // runtime stats + abctime timeSatUnsat; // unsat + abctime timeSatSat; // sat + abctime timeSatUndec; // undecided + abctime timeTotal; // total runtime +}; + +static inline int Cbs0_VarIsAssigned( Gia_Obj_t * pVar ) { return pVar->fMark0; } +static inline void Cbs0_VarAssign( Gia_Obj_t * pVar ) { assert(!pVar->fMark0); pVar->fMark0 = 1; } +static inline void Cbs0_VarUnassign( Gia_Obj_t * pVar ) { assert(pVar->fMark0); pVar->fMark0 = 0; pVar->fMark1 = 0; } +static inline int Cbs0_VarValue( Gia_Obj_t * pVar ) { assert(pVar->fMark0); return pVar->fMark1; } +static inline void Cbs0_VarSetValue( Gia_Obj_t * pVar, int v ) { assert(pVar->fMark0); pVar->fMark1 = v; } +static inline int Cbs0_VarIsJust( Gia_Obj_t * pVar ) { return Gia_ObjIsAnd(pVar) && !Cbs0_VarIsAssigned(Gia_ObjFanin0(pVar)) && !Cbs0_VarIsAssigned(Gia_ObjFanin1(pVar)); } +static inline int Cbs0_VarFanin0Value( Gia_Obj_t * pVar ) { return !Cbs0_VarIsAssigned(Gia_ObjFanin0(pVar)) ? 2 : (Cbs0_VarValue(Gia_ObjFanin0(pVar)) ^ Gia_ObjFaninC0(pVar)); } +static inline int Cbs0_VarFanin1Value( Gia_Obj_t * pVar ) { return !Cbs0_VarIsAssigned(Gia_ObjFanin1(pVar)) ? 2 : (Cbs0_VarValue(Gia_ObjFanin1(pVar)) ^ Gia_ObjFaninC1(pVar)); } + +#define Cbs0_QueForEachEntry( Que, pObj, i ) \ + for ( i = (Que).iHead; (i < (Que).iTail) && ((pObj) = (Que).pData[i]); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Sets default values of the parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs0_SetDefaultParams( Cbs0_Par_t * pPars ) +{ + memset( pPars, 0, sizeof(Cbs0_Par_t) ); + pPars->nBTLimit = 1000; // limit on the number of conflicts + pPars->nJustLimit = 100; // limit on the size of justification queue + pPars->fUseHighest = 1; // use node with the highest ID + pPars->fUseLowest = 0; // use node with the highest ID + pPars->fUseMaxFF = 0; // use node with the largest fanin fanout + pPars->fVerbose = 1; // print detailed statistics +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cbs0_Man_t * Cbs0_ManAlloc() +{ + Cbs0_Man_t * p; + p = ABC_CALLOC( Cbs0_Man_t, 1 ); + p->pProp.nSize = p->pJust.nSize = 10000; + p->pProp.pData = ABC_ALLOC( Gia_Obj_t *, p->pProp.nSize ); + p->pJust.pData = ABC_ALLOC( Gia_Obj_t *, p->pJust.nSize ); + p->vModel = Vec_IntAlloc( 1000 ); + Cbs0_SetDefaultParams( &p->Pars ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs0_ManStop( Cbs0_Man_t * p ) +{ + Vec_IntFree( p->vModel ); + ABC_FREE( p->pProp.pData ); + ABC_FREE( p->pJust.pData ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Returns satisfying assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Cbs0_ReadModel( Cbs0_Man_t * p ) +{ + return p->vModel; +} + + + + +/**Function************************************************************* + + Synopsis [Returns 1 if the solver is out of limits.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs0_ManCheckLimits( Cbs0_Man_t * p ) +{ + return p->Pars.nJustThis > p->Pars.nJustLimit || p->Pars.nBTThis > p->Pars.nBTLimit; +} + +/**Function************************************************************* + + Synopsis [Saves the satisfying assignment as an array of literals.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs0_ManSaveModel( Cbs0_Man_t * p, Vec_Int_t * vCex ) +{ + Gia_Obj_t * pVar; + int i; + Vec_IntClear( vCex ); + p->pProp.iHead = 0; + Cbs0_QueForEachEntry( p->pProp, pVar, i ) + if ( Gia_ObjIsCi(pVar) ) +// Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjId(p->pAig,pVar), !Cbs0_VarValue(pVar)) ); + Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjCioId(pVar), !Cbs0_VarValue(pVar)) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs0_QueIsEmpty( Cbs0_Que_t * p ) +{ + return p->iHead == p->iTail; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs0_QuePush( Cbs0_Que_t * p, Gia_Obj_t * pObj ) +{ + if ( p->iTail == p->nSize ) + { + p->nSize *= 2; + p->pData = ABC_REALLOC( Gia_Obj_t *, p->pData, p->nSize ); + } + p->pData[p->iTail++] = pObj; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the object in the queue.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs0_QueHasNode( Cbs0_Que_t * p, Gia_Obj_t * pObj ) +{ + Gia_Obj_t * pTemp; + int i; + Cbs0_QueForEachEntry( *p, pTemp, i ) + if ( pTemp == pObj ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs0_QueStore( Cbs0_Que_t * p, int * piHeadOld, int * piTailOld ) +{ + int i; + *piHeadOld = p->iHead; + *piTailOld = p->iTail; + for ( i = *piHeadOld; i < *piTailOld; i++ ) + Cbs0_QuePush( p, p->pData[i] ); + p->iHead = *piTailOld; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs0_QueRestore( Cbs0_Que_t * p, int iHeadOld, int iTailOld ) +{ + p->iHead = iHeadOld; + p->iTail = iTailOld; +} + + +/**Function************************************************************* + + Synopsis [Max number of fanins fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs0_VarFaninFanoutMax( Cbs0_Man_t * p, Gia_Obj_t * pObj ) +{ + int Count0, Count1; + assert( !Gia_IsComplement(pObj) ); + assert( Gia_ObjIsAnd(pObj) ); + Count0 = Gia_ObjRefNum( p->pAig, Gia_ObjFanin0(pObj) ); + Count1 = Gia_ObjRefNum( p->pAig, Gia_ObjFanin1(pObj) ); + return Abc_MaxInt( Count0, Count1 ); +} + +/**Function************************************************************* + + Synopsis [Find variable with the highest ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * Cbs0_ManDecideHighest( Cbs0_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjMax = NULL; + int i; + Cbs0_QueForEachEntry( p->pJust, pObj, i ) + if ( pObjMax == NULL || pObjMax < pObj ) + pObjMax = pObj; + return pObjMax; +} + +/**Function************************************************************* + + Synopsis [Find variable with the lowest ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * Cbs0_ManDecideLowest( Cbs0_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjMin = NULL; + int i; + Cbs0_QueForEachEntry( p->pJust, pObj, i ) + if ( pObjMin == NULL || pObjMin > pObj ) + pObjMin = pObj; + return pObjMin; +} + +/**Function************************************************************* + + Synopsis [Find variable with the maximum number of fanin fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * Cbs0_ManDecideMaxFF( Cbs0_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjMax = NULL; + int i, iMaxFF = 0, iCurFF; + assert( p->pAig->pRefs != NULL ); + Cbs0_QueForEachEntry( p->pJust, pObj, i ) + { + iCurFF = Cbs0_VarFaninFanoutMax( p, pObj ); + assert( iCurFF > 0 ); + if ( iMaxFF < iCurFF ) + { + iMaxFF = iCurFF; + pObjMax = pObj; + } + } + return pObjMax; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs0_ManCancelUntil( Cbs0_Man_t * p, int iBound ) +{ + Gia_Obj_t * pVar; + int i; + assert( iBound <= p->pProp.iTail ); + p->pProp.iHead = iBound; + Cbs0_QueForEachEntry( p->pProp, pVar, i ) + Cbs0_VarUnassign( pVar ); + p->pProp.iTail = iBound; +} + +/**Function************************************************************* + + Synopsis [Assigns the variables a value.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Cbs0_ManAssign( Cbs0_Man_t * p, Gia_Obj_t * pObj ) +{ + Gia_Obj_t * pObjR = Gia_Regular(pObj); + assert( Gia_ObjIsCand(pObjR) ); + assert( !Cbs0_VarIsAssigned(pObjR) ); + Cbs0_VarAssign( pObjR ); + Cbs0_VarSetValue( pObjR, !Gia_IsComplement(pObj) ); + Cbs0_QuePush( &p->pProp, pObjR ); +} + +/**Function************************************************************* + + Synopsis [Propagates a variable.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs0_ManPropagateOne( Cbs0_Man_t * p, Gia_Obj_t * pVar ) +{ + int Value0, Value1; + assert( !Gia_IsComplement(pVar) ); + assert( Cbs0_VarIsAssigned(pVar) ); + if ( Gia_ObjIsCi(pVar) ) + return 0; + assert( Gia_ObjIsAnd(pVar) ); + Value0 = Cbs0_VarFanin0Value(pVar); + Value1 = Cbs0_VarFanin1Value(pVar); + if ( Cbs0_VarValue(pVar) ) + { // value is 1 + if ( Value0 == 0 || Value1 == 0 ) // one is 0 + return 1; + if ( Value0 == 2 ) // first is unassigned + Cbs0_ManAssign( p, Gia_ObjChild0(pVar) ); + if ( Value1 == 2 ) // first is unassigned + Cbs0_ManAssign( p, Gia_ObjChild1(pVar) ); + return 0; + } + // value is 0 + if ( Value0 == 0 || Value1 == 0 ) // one is 0 + return 0; + if ( Value0 == 1 && Value1 == 1 ) // both are 1 + return 1; + if ( Value0 == 1 || Value1 == 1 ) // one is 1 + { + if ( Value0 == 2 ) // first is unassigned + Cbs0_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)) ); + if ( Value1 == 2 ) // first is unassigned + Cbs0_ManAssign( p, Gia_Not(Gia_ObjChild1(pVar)) ); + return 0; + } + assert( Cbs0_VarIsJust(pVar) ); + assert( !Cbs0_QueHasNode( &p->pJust, pVar ) ); + Cbs0_QuePush( &p->pJust, pVar ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Propagates a variable.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Cbs0_ManPropagateTwo( Cbs0_Man_t * p, Gia_Obj_t * pVar ) +{ + int Value0, Value1; + assert( !Gia_IsComplement(pVar) ); + assert( Gia_ObjIsAnd(pVar) ); + assert( Cbs0_VarIsAssigned(pVar) ); + assert( !Cbs0_VarValue(pVar) ); + Value0 = Cbs0_VarFanin0Value(pVar); + Value1 = Cbs0_VarFanin1Value(pVar); + // value is 0 + if ( Value0 == 0 || Value1 == 0 ) // one is 0 + return 0; + if ( Value0 == 1 && Value1 == 1 ) // both are 1 + return 1; + assert( Value0 == 1 || Value1 == 1 ); + if ( Value0 == 2 ) // first is unassigned + Cbs0_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)) ); + if ( Value1 == 2 ) // first is unassigned + Cbs0_ManAssign( p, Gia_Not(Gia_ObjChild1(pVar)) ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Propagates all variables.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cbs0_ManPropagate( Cbs0_Man_t * p ) +{ + Gia_Obj_t * pVar; + int i, k; + while ( 1 ) + { + Cbs0_QueForEachEntry( p->pProp, pVar, i ) + { + if ( Cbs0_ManPropagateOne( p, pVar ) ) + return 1; + } + p->pProp.iHead = p->pProp.iTail; + k = p->pJust.iHead; + Cbs0_QueForEachEntry( p->pJust, pVar, i ) + { + if ( Cbs0_VarIsJust( pVar ) ) + p->pJust.pData[k++] = pVar; + else if ( Cbs0_ManPropagateTwo( p, pVar ) ) + return 1; + } + if ( k == p->pJust.iTail ) + break; + p->pJust.iTail = k; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Solve the problem recursively.] + + Description [Returns 1 if unsat or undecided; 0 if satisfiable.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cbs0_ManSolve_rec( Cbs0_Man_t * p ) +{ + Gia_Obj_t * pVar = NULL, * pDecVar; + int iPropHead, iJustHead, iJustTail; + // propagate assignments + assert( !Cbs0_QueIsEmpty(&p->pProp) ); + if ( Cbs0_ManPropagate( p ) ) + return 1; + // check for satisfying assignment + assert( Cbs0_QueIsEmpty(&p->pProp) ); + if ( Cbs0_QueIsEmpty(&p->pJust) ) + return 0; + // quit using resource limits + p->Pars.nJustThis = Abc_MaxInt( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead ); + if ( Cbs0_ManCheckLimits( p ) ) + return 0; + // remember the state before branching + iPropHead = p->pProp.iHead; + Cbs0_QueStore( &p->pJust, &iJustHead, &iJustTail ); + // find the decision variable + if ( p->Pars.fUseHighest ) + pVar = Cbs0_ManDecideHighest( p ); + else if ( p->Pars.fUseLowest ) + pVar = Cbs0_ManDecideLowest( p ); + else if ( p->Pars.fUseMaxFF ) + pVar = Cbs0_ManDecideMaxFF( p ); + else assert( 0 ); + assert( Cbs0_VarIsJust( pVar ) ); + // chose decision variable using fanout count + if ( Gia_ObjRefNum(p->pAig, Gia_ObjFanin0(pVar)) > Gia_ObjRefNum(p->pAig, Gia_ObjFanin1(pVar)) ) + pDecVar = Gia_Not(Gia_ObjChild0(pVar)); + else + pDecVar = Gia_Not(Gia_ObjChild1(pVar)); + // decide on first fanin + Cbs0_ManAssign( p, pDecVar ); + if ( !Cbs0_ManSolve_rec( p ) ) + return 0; + Cbs0_ManCancelUntil( p, iPropHead ); + Cbs0_QueRestore( &p->pJust, iJustHead, iJustTail ); + // decide on second fanin + Cbs0_ManAssign( p, Gia_Not(pDecVar) ); + if ( !Cbs0_ManSolve_rec( p ) ) + return 0; + p->Pars.nBTThis++; + return 1; +} + +/**Function************************************************************* + + Synopsis [Looking for a satisfying assignment of the node.] + + Description [Assumes that each node has flag pObj->fMark0 set to 0. + Returns 1 if unsatisfiable, 0 if satisfiable, and -1 if undecided. + The node may be complemented. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cbs0_ManSolve( Cbs0_Man_t * p, Gia_Obj_t * pObj ) +{ + int RetValue; + assert( !p->pProp.iHead && !p->pProp.iTail ); + assert( !p->pJust.iHead && !p->pJust.iTail ); + p->Pars.nBTThis = p->Pars.nJustThis = 0; + Cbs0_ManAssign( p, pObj ); + RetValue = Cbs0_ManSolve_rec( p ); + if ( RetValue == 0 && !Cbs0_ManCheckLimits(p) ) + Cbs0_ManSaveModel( p, p->vModel ); + Cbs0_ManCancelUntil( p, 0 ); + p->pJust.iHead = p->pJust.iTail = 0; + p->Pars.nBTTotal += p->Pars.nBTThis; + p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis ); + if ( Cbs0_ManCheckLimits( p ) ) + RetValue = -1; +// printf( "Outcome = %2d. Confs = %6d. Decision level max = %3d.\n", +// RetValue, p->Pars.nBTThis, p->DecLevelMax ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Prints statistics of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cbs0_ManSatPrintStats( Cbs0_Man_t * p ) +{ + printf( "CO = %8d ", Gia_ManCoNum(p->pAig) ); + printf( "AND = %8d ", Gia_ManAndNum(p->pAig) ); + printf( "Conf = %6d ", p->Pars.nBTLimit ); + printf( "JustMax = %5d ", p->Pars.nJustLimit ); + printf( "\n" ); + printf( "Unsat calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatUnsat, p->nSatTotal? 100.0*p->nSatUnsat/p->nSatTotal :0.0, p->nSatUnsat? 1.0*p->nConfUnsat/p->nSatUnsat :0.0 ); + ABC_PRTP( "Time", p->timeSatUnsat, p->timeTotal ); + printf( "Sat calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatSat, p->nSatTotal? 100.0*p->nSatSat/p->nSatTotal :0.0, p->nSatSat? 1.0*p->nConfSat/p->nSatSat : 0.0 ); + ABC_PRTP( "Time", p->timeSatSat, p->timeTotal ); + printf( "Undef calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatUndec, p->nSatTotal? 100.0*p->nSatUndec/p->nSatTotal :0.0, p->nSatUndec? 1.0*p->nConfUndec/p->nSatUndec : 0.0 ); + ABC_PRTP( "Time", p->timeSatUndec, p->timeTotal ); + ABC_PRT( "Total time", p->timeTotal ); +} + +/**Function************************************************************* + + Synopsis [Procedure to test the new SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Cbs_ManSolveMiter( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int fVerbose ) +{ + extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out ); + Cbs0_Man_t * p; + Vec_Int_t * vCex, * vVisit, * vCexStore; + Vec_Str_t * vStatus; + Gia_Obj_t * pRoot; + int i, status; + abctime clk, clkTotal = Abc_Clock(); + assert( Gia_ManRegNum(pAig) == 0 ); + // prepare AIG + Gia_ManCreateRefs( pAig ); + Gia_ManCleanMark0( pAig ); + Gia_ManCleanMark1( pAig ); + // create logic network + p = Cbs0_ManAlloc(); + p->Pars.nBTLimit = nConfs; + p->pAig = pAig; + // create resulting data-structures + vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) ); + vCexStore = Vec_IntAlloc( 10000 ); + vVisit = Vec_IntAlloc( 100 ); + vCex = Cbs0_ReadModel( p ); + // solve for each output + Gia_ManForEachCo( pAig, pRoot, i ) + { + Vec_IntClear( vCex ); + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pRoot)) ) + { + if ( Gia_ObjFaninC0(pRoot) ) + { + printf( "Constant 1 output of SRM!!!\n" ); + Cec_ManSatAddToStore( vCexStore, vCex, i ); // trivial counter-example + Vec_StrPush( vStatus, 0 ); + } + else + { +// printf( "Constant 0 output of SRM!!!\n" ); + Vec_StrPush( vStatus, 1 ); + } + continue; + } + clk = Abc_Clock(); + p->Pars.fUseHighest = 1; + p->Pars.fUseLowest = 0; + status = Cbs0_ManSolve( p, Gia_ObjChild0(pRoot) ); +/* + if ( status == -1 ) + { + p->Pars.fUseHighest = 0; + p->Pars.fUseLowest = 1; + status = Cbs0_ManSolve( p, Gia_ObjChild0(pRoot) ); + } +*/ + Vec_StrPush( vStatus, (char)status ); + if ( status == -1 ) + { + p->nSatUndec++; + p->nConfUndec += p->Pars.nBTThis; + Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout + p->timeSatUndec += Abc_Clock() - clk; + continue; + } + if ( status == 1 ) + { + p->nSatUnsat++; + p->nConfUnsat += p->Pars.nBTThis; + p->timeSatUnsat += Abc_Clock() - clk; + continue; + } + p->nSatSat++; + p->nConfSat += p->Pars.nBTThis; +// Gia_SatVerifyPattern( pAig, pRoot, vCex, vVisit ); + Cec_ManSatAddToStore( vCexStore, vCex, i ); + p->timeSatSat += Abc_Clock() - clk; + } + Vec_IntFree( vVisit ); + p->nSatTotal = Gia_ManPoNum(pAig); + p->timeTotal = Abc_Clock() - clkTotal; + if ( fVerbose ) + Cbs0_ManSatPrintStats( p ); + Cbs0_ManStop( p ); + *pvStatus = vStatus; +// printf( "Total number of cex literals = %d. (Ave = %d)\n", +// Vec_IntSize(vCexStore)-2*p->nSatUndec-2*p->nSatSat, +// (Vec_IntSize(vCexStore)-2*p->nSatUndec-2*p->nSatSat)/p->nSatSat ); + return vCexStore; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaCSatP.c b/yosys/abc/src/aig/gia/giaCSatP.c new file mode 100644 index 00000000000..00ab880b248 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaCSatP.c @@ -0,0 +1,1209 @@ +/**CFile**************************************************************** + + FileName [giaCSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [A simple circuit-based solver.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaCSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "giaCSatP.h" + +ABC_NAMESPACE_IMPL_START + + +//#define gia_assert(exp) ((void)0) +//#define gia_assert(exp) (assert(exp)) + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + + +static inline int CbsP_VarIsAssigned( Gia_Obj_t * pVar ) { return pVar->fMark0; } +static inline void CbsP_VarAssign( Gia_Obj_t * pVar ) { assert(!pVar->fMark0); pVar->fMark0 = 1; } +static inline void CbsP_VarUnassign( CbsP_Man_t * pMan, Gia_Obj_t * pVar ) { assert(pVar->fMark0); pVar->fMark0 = 0; pVar->fMark1 = 0; pMan->vValue->pArray[Gia_ObjId(pMan->pAig,pVar)] = ~0; } +static inline int CbsP_VarValue( Gia_Obj_t * pVar ) { assert(pVar->fMark0); return pVar->fMark1; } +static inline void CbsP_VarSetValue( Gia_Obj_t * pVar, int v ) { assert(pVar->fMark0); pVar->fMark1 = v; } +static inline int CbsP_VarIsJust( Gia_Obj_t * pVar ) { return Gia_ObjIsAnd(pVar) && !CbsP_VarIsAssigned(Gia_ObjFanin0(pVar)) && !CbsP_VarIsAssigned(Gia_ObjFanin1(pVar)); } +static inline int CbsP_VarFanin0Value( Gia_Obj_t * pVar ) { return !CbsP_VarIsAssigned(Gia_ObjFanin0(pVar)) ? 2 : (CbsP_VarValue(Gia_ObjFanin0(pVar)) ^ Gia_ObjFaninC0(pVar)); } +static inline int CbsP_VarFanin1Value( Gia_Obj_t * pVar ) { return !CbsP_VarIsAssigned(Gia_ObjFanin1(pVar)) ? 2 : (CbsP_VarValue(Gia_ObjFanin1(pVar)) ^ Gia_ObjFaninC1(pVar)); } + +static inline int CbsP_VarDecLevel( CbsP_Man_t * p, Gia_Obj_t * pVar ) { int Value = p->vValue->pArray[Gia_ObjId(p->pAig,pVar)]; assert( Value != ~0 ); return Vec_IntEntry(p->vLevReas, 3*Value); } +static inline Gia_Obj_t * CbsP_VarReason0( CbsP_Man_t * p, Gia_Obj_t * pVar ) { int Value = p->vValue->pArray[Gia_ObjId(p->pAig,pVar)]; assert( Value != ~0 ); return pVar + Vec_IntEntry(p->vLevReas, 3*Value+1); } +static inline Gia_Obj_t * CbsP_VarReason1( CbsP_Man_t * p, Gia_Obj_t * pVar ) { int Value = p->vValue->pArray[Gia_ObjId(p->pAig,pVar)]; assert( Value != ~0 ); return pVar + Vec_IntEntry(p->vLevReas, 3*Value+2); } +static inline int CbsP_ClauseDecLevel( CbsP_Man_t * p, int hClause ) { return CbsP_VarDecLevel( p, p->pClauses.pData[hClause] ); } + +#define CbsP_QueForEachEntry( Que, pObj, i ) \ + for ( i = (Que).iHead; (i < (Que).iTail) && ((pObj) = (Que).pData[i]); i++ ) + +#define CbsP_ClauseForEachVar( p, hClause, pObj ) \ + for ( (p)->pIter = (p)->pClauses.pData + hClause; (pObj = *pIter); (p)->pIter++ ) +#define CbsP_ClauseForEachVar1( p, hClause, pObj ) \ + for ( (p)->pIter = (p)->pClauses.pData+hClause+1; (pObj = *pIter); (p)->pIter++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Sets default values of the parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CbsP_SetDefaultParams( CbsP_Par_t * pPars ) +{ + memset( pPars, 0, sizeof(CbsP_Par_t) ); + pPars->nBTLimit = 1000; // limit on the number of conflicts + pPars->nJustLimit = 100; // limit on the size of justification queue + pPars->fUseHighest = 1; // use node with the highest ID + pPars->fUseLowest = 0; // use node with the highest ID + pPars->fUseMaxFF = 0; // use node with the largest fanin fanout + pPars->fVerbose = 1; // print detailed statistics + + pPars->fUseProved = 1; + + + pPars->nJscanThis = 0; + pPars->nRscanThis = 0; + pPars->maxJscanUndec = 0; + pPars->maxRscanUndec = 0; + pPars->maxJscanSolved = 0; + pPars->maxRscanSolved = 0; + + + pPars->accJscanSat = 0; + pPars->accJscanUnsat = 0; + pPars->accJscanUndec = 0; + pPars->accRscanSat = 0; + pPars->accRscanUnsat = 0; + pPars->accRscanUndec = 0; + pPars->nSat = 0; + pPars->nUnsat = 0; + pPars->nUndec = 0; + + pPars->nJscanLimit = 100; + pPars->nRscanLimit = 100; + pPars->nPropLimit = 500; +} +void CbsP_ManSetConflictNum( CbsP_Man_t * p, int Num ) +{ + p->Pars.nBTLimit = Num; +} + +static inline void CbsP_UpdateRecord( CbsP_Par_t * pPars, int res ){ + if( CBS_UNDEC == res ){ + pPars->nUndec ++ ; + if( pPars-> maxJscanUndec < pPars->nJscanThis ) + pPars-> maxJscanUndec = pPars->nJscanThis; + if( pPars-> maxRscanUndec < pPars->nRscanThis ) + pPars-> maxRscanUndec = pPars->nRscanThis; + if( pPars-> maxPropUndec < pPars->nPropThis ) + pPars-> maxPropUndec = pPars->nPropThis; + + pPars->accJscanUndec += pPars->nJscanThis; + pPars->accRscanUndec += pPars->nRscanThis; + pPars-> accPropUndec += pPars->nPropThis; + } else { + if( pPars->maxJscanSolved < pPars->nJscanThis ) + pPars->maxJscanSolved = pPars->nJscanThis; + if( pPars->maxRscanSolved < pPars->nRscanThis ) + pPars->maxRscanSolved = pPars->nRscanThis; + if( pPars-> maxPropSolved < pPars->nPropThis ) + pPars-> maxPropSolved = pPars->nPropThis; + if( CBS_SAT == res ){ + pPars->nSat ++ ; + pPars->accJscanSat += pPars->nJscanThis; + pPars->accRscanSat += pPars->nRscanThis; + pPars-> accPropSat += pPars->nPropThis; + } else + if( CBS_UNSAT == res ){ + pPars->nUnsat ++ ; + pPars->accJscanUnsat += pPars->nJscanThis; + pPars->accRscanUnsat += pPars->nRscanThis; + pPars-> accPropUnsat += pPars->nPropThis; + } + } + +} + +void CbsP_PrintRecord( CbsP_Par_t * pPars ){ + printf("max of solved: jscan# %13d rscan %13d prop %13d\n" , pPars->maxJscanSolved, pPars->maxRscanSolved , pPars->maxPropSolved ); + printf("max of undec: jscan# %13d rscan %13d prop %13d\n" , pPars->maxJscanUndec , pPars->maxRscanUndec , pPars->maxPropUndec ); + printf("acc of sat: jscan# %13ld rscan %13ld prop %13ld\n", pPars->accJscanSat , pPars->accRscanSat , pPars->accPropSat ); + printf("acc of unsat: jscan# %13ld rscan %13ld prop %13ld\n", pPars->accJscanUnsat , pPars->accRscanUnsat , pPars->accPropUnsat ); + printf("acc of undec: jscan# %13ld rscan %13ld prop %13ld\n", pPars->accJscanUndec , pPars->accRscanUndec , pPars->accPropUndec ); + if( pPars->nSat ) + printf("avg of sat: jscan# %13ld rscan %13ld prop %13ld\n", pPars->accJscanSat / pPars->nSat , pPars->accRscanSat / pPars->nSat , pPars->accPropSat / pPars->nSat ); + if( pPars->nUnsat ) + printf("avg of unsat: jscan# %13ld rscan %13ld prop %13ld\n", pPars->accJscanUnsat / pPars->nUnsat , pPars->accRscanUnsat / pPars->nUnsat , pPars->accPropUnsat / pPars->nUnsat ); + if( pPars->nUndec ) + printf("avg of undec: jscan# %13ld rscan %13ld prop %13ld\n", pPars->accJscanUndec / pPars->nUndec , pPars->accRscanUndec / pPars->nUndec , pPars->accPropUndec / pPars->nUndec ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +CbsP_Man_t * CbsP_ManAlloc( Gia_Man_t * pGia ) +{ + CbsP_Man_t * p; + p = ABC_CALLOC( CbsP_Man_t, 1 ); + p->pProp.nSize = p->pJust.nSize = p->pClauses.nSize = 10000; + p->pProp.pData = ABC_ALLOC( Gia_Obj_t *, p->pProp.nSize ); + p->pJust.pData = ABC_ALLOC( Gia_Obj_t *, p->pJust.nSize ); + p->pClauses.pData = ABC_ALLOC( Gia_Obj_t *, p->pClauses.nSize ); + p->pClauses.iHead = p->pClauses.iTail = 1; + p->vModel = Vec_IntAlloc( 1000 ); + p->vLevReas = Vec_IntAlloc( 1000 ); + p->vTemp = Vec_PtrAlloc( 1000 ); + p->pAig = pGia; + p->vValue = Vec_IntAlloc( Gia_ManObjNum(pGia) ); + Vec_IntFill( p->vValue, Gia_ManObjNum(pGia), ~0 ); + //memset( p->vValue->pArray, (unsigned) ~0, sizeof(int) * Gia_ManObjNum(pGia) ); + CbsP_SetDefaultParams( &p->Pars ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CbsP_ManStop( CbsP_Man_t * p ) +{ + Vec_IntFree( p->vLevReas ); + Vec_IntFree( p->vModel ); + Vec_PtrFree( p->vTemp ); + Vec_IntFree( p->vValue ); + ABC_FREE( p->pClauses.pData ); + ABC_FREE( p->pProp.pData ); + ABC_FREE( p->pJust.pData ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Returns satisfying assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * CbsP_ReadModel( CbsP_Man_t * p ) +{ + return p->vModel; +} + + + + +/**Function************************************************************* + + Synopsis [Returns 1 if the solver is out of limits.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +static inline int CbsP_ManCheckPropLimits( CbsP_Man_t * p ) +{ + return p->Pars.nPropThis > p->Pars.nPropLimit; +} +static inline int CbsP_ManCheckLimits( CbsP_Man_t * p ) +{ + return CbsP_ManCheckPropLimits(p) || p->Pars.nJscanThis > p->Pars.nJscanLimit || p->Pars.nRscanThis > p->Pars.nRscanLimit || p->Pars.nJustThis > p->Pars.nJustLimit || p->Pars.nBTThis > p->Pars.nBTLimit; +} + +/**Function************************************************************* + + Synopsis [Saves the satisfying assignment as an array of literals.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void CbsP_ManSaveModel( CbsP_Man_t * p, Vec_Int_t * vCex ) +{ + Gia_Obj_t * pVar; + int i; + Vec_IntClear( vCex ); + p->pProp.iHead = 0; + CbsP_QueForEachEntry( p->pProp, pVar, i ) + if ( Gia_ObjIsCi(pVar) ) + Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjId(p->pAig,pVar), !CbsP_VarValue(pVar)) ); +// Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjCioId(pVar), !CbsP_VarValue(pVar)) ); +} +static inline void CbsP_ManSaveModelAll( CbsP_Man_t * p, Vec_Int_t * vCex ) +{ + Gia_Obj_t * pVar; + int i; + Vec_IntClear( vCex ); + p->pProp.iHead = 0; + CbsP_QueForEachEntry( p->pProp, pVar, i ) + Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjId(p->pAig,pVar), !CbsP_VarValue(pVar)) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int CbsP_QueIsEmpty( CbsP_Que_t * p ) +{ + return p->iHead == p->iTail; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void CbsP_QuePush( CbsP_Que_t * p, Gia_Obj_t * pObj ) +{ + assert( !Gia_IsComplement(pObj) ); + if ( p->iTail == p->nSize ) + { + p->nSize *= 2; + p->pData = ABC_REALLOC( Gia_Obj_t *, p->pData, p->nSize ); + } + p->pData[p->iTail++] = pObj; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the object in the queue.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int CbsP_QueHasNode( CbsP_Que_t * p, Gia_Obj_t * pObj ) +{ + Gia_Obj_t * pTemp; + int i; + CbsP_QueForEachEntry( *p, pTemp, i ) + if ( pTemp == pObj ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void CbsP_QueStore( CbsP_Que_t * p, int * piHeadOld, int * piTailOld ) +{ + int i; + *piHeadOld = p->iHead; + *piTailOld = p->iTail; + for ( i = *piHeadOld; i < *piTailOld; i++ ) + CbsP_QuePush( p, p->pData[i] ); + p->iHead = *piTailOld; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void CbsP_QueRestore( CbsP_Que_t * p, int iHeadOld, int iTailOld ) +{ + p->iHead = iHeadOld; + p->iTail = iTailOld; +} + +/**Function************************************************************* + + Synopsis [Finalized the clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int CbsP_QueFinish( CbsP_Que_t * p ) +{ + int iHeadOld = p->iHead; + assert( p->iHead < p->iTail ); + CbsP_QuePush( p, NULL ); + p->iHead = p->iTail; + return iHeadOld; +} + + +/**Function************************************************************* + + Synopsis [Max number of fanins fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int CbsP_VarFaninFanoutMax( CbsP_Man_t * p, Gia_Obj_t * pObj ) +{ + int Count0, Count1; + assert( !Gia_IsComplement(pObj) ); + assert( Gia_ObjIsAnd(pObj) ); + Count0 = Gia_ObjRefNum( p->pAig, Gia_ObjFanin0(pObj) ); + Count1 = Gia_ObjRefNum( p->pAig, Gia_ObjFanin1(pObj) ); + return Abc_MaxInt( Count0, Count1 ); +} + +/**Function************************************************************* + + Synopsis [Find variable with the highest ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * CbsP_ManDecideHighest( CbsP_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjMax = NULL; + int i; + CbsP_QueForEachEntry( p->pJust, pObj, i ) + if ( pObjMax == NULL || pObjMax < pObj ) + pObjMax = pObj; + return pObjMax; +} + +/**Function************************************************************* + + Synopsis [Find variable with the lowest ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * CbsP_ManDecideLowest( CbsP_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjMin = NULL; + int i; + CbsP_QueForEachEntry( p->pJust, pObj, i ) + if ( pObjMin == NULL || pObjMin > pObj ) + pObjMin = pObj; + return pObjMin; +} + +/**Function************************************************************* + + Synopsis [Find variable with the maximum number of fanin fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * CbsP_ManDecideMaxFF( CbsP_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjMax = NULL; + int i, iMaxFF = 0, iCurFF; + assert( p->pAig->pRefs != NULL ); + CbsP_QueForEachEntry( p->pJust, pObj, i ) + { + iCurFF = CbsP_VarFaninFanoutMax( p, pObj ); + assert( iCurFF > 0 ); + if ( iMaxFF < iCurFF ) + { + iMaxFF = iCurFF; + pObjMax = pObj; + } + } + return pObjMax; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void CbsP_ManCancelUntil( CbsP_Man_t * p, int iBound ) +{ + Gia_Obj_t * pVar; + int i; + assert( iBound <= p->pProp.iTail ); + p->pProp.iHead = iBound; + CbsP_QueForEachEntry( p->pProp, pVar, i ) + CbsP_VarUnassign( p, pVar ); + p->pProp.iTail = iBound; + Vec_IntShrink( p->vLevReas, 3*iBound ); +} + +//int s_Counter = 0; + +/**Function************************************************************* + + Synopsis [Assigns the variables a value.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void CbsP_ManAssign( CbsP_Man_t * p, Gia_Obj_t * pObj, int Level, Gia_Obj_t * pRes0, Gia_Obj_t * pRes1 ) +{ + Gia_Obj_t * pObjR = Gia_Regular(pObj); + assert( Gia_ObjIsCand(pObjR) ); + assert( !CbsP_VarIsAssigned(pObjR) ); + CbsP_VarAssign( pObjR ); + CbsP_VarSetValue( pObjR, !Gia_IsComplement(pObj) ); + assert( p->vValue->pArray[Gia_ObjId(p->pAig,pObjR)] == ~0 ); + p->vValue->pArray[Gia_ObjId(p->pAig,pObjR)] = p->pProp.iTail; + CbsP_QuePush( &p->pProp, pObjR ); + Vec_IntPush( p->vLevReas, Level ); + Vec_IntPush( p->vLevReas, pRes0 ? pRes0-pObjR : 0 ); + Vec_IntPush( p->vLevReas, pRes1 ? pRes1-pObjR : 0 ); + assert( Vec_IntSize(p->vLevReas) == 3 * p->pProp.iTail ); + if( pRes0 ) + p->Pars.nPropThis ++ ; +// s_Counter++; +// s_Counter = Abc_MaxIntInt( s_Counter, Vec_IntSize(p->vLevReas)/3 ); +} + + +/**Function************************************************************* + + Synopsis [Returns clause size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int CbsP_ManClauseSize( CbsP_Man_t * p, int hClause ) +{ + CbsP_Que_t * pQue = &(p->pClauses); + Gia_Obj_t ** pIter; + for ( pIter = pQue->pData + hClause; *pIter; pIter++ ); + return pIter - pQue->pData - hClause ; +} + +/**Function************************************************************* + + Synopsis [Prints conflict clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void CbsP_ManPrintClause( CbsP_Man_t * p, int Level, int hClause ) +{ + CbsP_Que_t * pQue = &(p->pClauses); + Gia_Obj_t * pObj; + int i; + assert( CbsP_QueIsEmpty( pQue ) ); + printf( "Level %2d : ", Level ); + for ( i = hClause; (pObj = pQue->pData[i]); i++ ) + printf( "%d=%d(%d) ", Gia_ObjId(p->pAig, pObj), CbsP_VarValue(pObj), CbsP_VarDecLevel(p, pObj) ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints conflict clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void CbsP_ManPrintClauseNew( CbsP_Man_t * p, int Level, int hClause ) +{ + CbsP_Que_t * pQue = &(p->pClauses); + Gia_Obj_t * pObj; + int i; + assert( CbsP_QueIsEmpty( pQue ) ); + printf( "Level %2d : ", Level ); + for ( i = hClause; (pObj = pQue->pData[i]); i++ ) + printf( "%c%d ", CbsP_VarValue(pObj)? '+':'-', Gia_ObjId(p->pAig, pObj) ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Returns conflict clause.] + + Description [Performs conflict analysis.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void CbsP_ManDeriveReason( CbsP_Man_t * p, int Level ) +{ + CbsP_Que_t * pQue = &(p->pClauses); + Gia_Obj_t * pObj, * pReason; + int i, k, iLitLevel; + assert( pQue->pData[pQue->iHead] == NULL ); + assert( pQue->iHead + 1 < pQue->iTail ); +/* + for ( i = pQue->iHead + 1; i < pQue->iTail; i++ ) + { + pObj = pQue->pData[i]; + assert( pObj->fMark0 == 1 ); + } +*/ + // compact literals + Vec_PtrClear( p->vTemp ); + for ( i = k = pQue->iHead + 1; i < pQue->iTail; i++ ) + { + pObj = pQue->pData[i]; + if ( !pObj->fMark0 ) // unassigned - seen again + continue; + // assigned - seen first time + pObj->fMark0 = 0; + Vec_PtrPush( p->vTemp, pObj ); + // check decision level + iLitLevel = CbsP_VarDecLevel( p, pObj ); + if ( iLitLevel < Level ) + { + pQue->pData[k++] = pObj; + continue; + } + assert( iLitLevel == Level ); + pReason = CbsP_VarReason0( p, pObj ); + if ( pReason == pObj ) // no reason + { + //assert( pQue->pData[pQue->iHead] == NULL ); + pQue->pData[pQue->iHead] = pObj; + continue; + } + CbsP_QuePush( pQue, pReason ); + pReason = CbsP_VarReason1( p, pObj ); + if ( pReason != pObj ) // second reason + CbsP_QuePush( pQue, pReason ); + } + assert( pQue->pData[pQue->iHead] != NULL ); + pQue->iTail = k; + // clear the marks + Vec_PtrForEachEntry( Gia_Obj_t *, p->vTemp, pObj, i ) + pObj->fMark0 = 1; +} + +/**Function************************************************************* + + Synopsis [Returns conflict clause.] + + Description [Performs conflict analysis.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int CbsP_ManAnalyze( CbsP_Man_t * p, int Level, Gia_Obj_t * pVar, Gia_Obj_t * pFan0, Gia_Obj_t * pFan1 ) +{ + CbsP_Que_t * pQue = &(p->pClauses); + assert( CbsP_VarIsAssigned(pVar) ); + assert( CbsP_VarIsAssigned(pFan0) ); + assert( pFan1 == NULL || CbsP_VarIsAssigned(pFan1) ); + assert( CbsP_QueIsEmpty( pQue ) ); + CbsP_QuePush( pQue, NULL ); + CbsP_QuePush( pQue, pVar ); + CbsP_QuePush( pQue, pFan0 ); + if ( pFan1 ) + CbsP_QuePush( pQue, pFan1 ); + CbsP_ManDeriveReason( p, Level ); + return CbsP_QueFinish( pQue ); +} + + +/**Function************************************************************* + + Synopsis [Performs resolution of two clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int CbsP_ManResolve( CbsP_Man_t * p, int Level, int hClause0, int hClause1 ) +{ + CbsP_Que_t * pQue = &(p->pClauses); + Gia_Obj_t * pObj; + int i, LevelMax = -1, LevelCur; + assert( pQue->pData[hClause0] != NULL ); + assert( pQue->pData[hClause0] == pQue->pData[hClause1] ); +/* + for ( i = hClause0 + 1; (pObj = pQue->pData[i]); i++ ) + assert( pObj->fMark0 == 1 ); + for ( i = hClause1 + 1; (pObj = pQue->pData[i]); i++ ) + assert( pObj->fMark0 == 1 ); +*/ + assert( CbsP_QueIsEmpty( pQue ) ); + CbsP_QuePush( pQue, NULL ); + for ( i = hClause0 + 1; (pObj = pQue->pData[i]); i++ ) + { + if ( !pObj->fMark0 ) // unassigned - seen again + continue; + // assigned - seen first time + pObj->fMark0 = 0; + CbsP_QuePush( pQue, pObj ); + p->Pars.nRscanThis ++ ; + LevelCur = CbsP_VarDecLevel( p, pObj ); + if ( LevelMax < LevelCur ) + LevelMax = LevelCur; + } + for ( i = hClause1 + 1; (pObj = pQue->pData[i]); i++ ) + { + if ( !pObj->fMark0 ) // unassigned - seen again + continue; + // assigned - seen first time + pObj->fMark0 = 0; + CbsP_QuePush( pQue, pObj ); + p->Pars.nRscanThis ++ ; + LevelCur = CbsP_VarDecLevel( p, pObj ); + if ( LevelMax < LevelCur ) + LevelMax = LevelCur; + } + for ( i = pQue->iHead + 1; i < pQue->iTail; i++ ) + pQue->pData[i]->fMark0 = 1; + CbsP_ManDeriveReason( p, LevelMax ); + return CbsP_QueFinish( pQue ); +} + +/**Function************************************************************* + + Synopsis [Propagates a variable.] + + Description [Returns clause handle if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int CbsP_ManPropagateOne( CbsP_Man_t * p, Gia_Obj_t * pVar, int Level ) +{ + int Value0, Value1; + assert( !Gia_IsComplement(pVar) ); + assert( CbsP_VarIsAssigned(pVar) ); + if ( Gia_ObjIsCi(pVar) ) + return 0; + assert( Gia_ObjIsAnd(pVar) ); + Value0 = CbsP_VarFanin0Value(pVar); + Value1 = CbsP_VarFanin1Value(pVar); + if ( CbsP_VarValue(pVar) ) + { // value is 1 + if ( Value0 == 0 || Value1 == 0 ) // one is 0 + { + if ( Value0 == 0 && Value1 != 0 ) + return CbsP_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), NULL ); + if ( Value0 != 0 && Value1 == 0 ) + return CbsP_ManAnalyze( p, Level, pVar, Gia_ObjFanin1(pVar), NULL ); + assert( Value0 == 0 && Value1 == 0 ); + return CbsP_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), Gia_ObjFanin1(pVar) ); + } + if ( Value0 == 2 ) // first is unassigned + CbsP_ManAssign( p, Gia_ObjChild0(pVar), Level, pVar, NULL ); + if ( Value1 == 2 ) // first is unassigned + CbsP_ManAssign( p, Gia_ObjChild1(pVar), Level, pVar, NULL ); + return 0; + } + // value is 0 + if ( Value0 == 0 || Value1 == 0 ) // one is 0 + return 0; + if ( Value0 == 1 && Value1 == 1 ) // both are 1 + return CbsP_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), Gia_ObjFanin1(pVar) ); + if ( Value0 == 1 || Value1 == 1 ) // one is 1 + { + if ( Value0 == 2 ) // first is unassigned + CbsP_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)), Level, pVar, Gia_ObjFanin1(pVar) ); + if ( Value1 == 2 ) // second is unassigned + CbsP_ManAssign( p, Gia_Not(Gia_ObjChild1(pVar)), Level, pVar, Gia_ObjFanin0(pVar) ); + return 0; + } + assert( CbsP_VarIsJust(pVar) ); + assert( !CbsP_QueHasNode( &p->pJust, pVar ) ); + CbsP_QuePush( &p->pJust, pVar ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Propagates a variable.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int CbsP_ManPropagateTwo( CbsP_Man_t * p, Gia_Obj_t * pVar, int Level ) +{ + int Value0, Value1; + assert( !Gia_IsComplement(pVar) ); + assert( Gia_ObjIsAnd(pVar) ); + assert( CbsP_VarIsAssigned(pVar) ); + assert( !CbsP_VarValue(pVar) ); + Value0 = CbsP_VarFanin0Value(pVar); + Value1 = CbsP_VarFanin1Value(pVar); + // value is 0 + if ( Value0 == 0 || Value1 == 0 ) // one is 0 + return 0; + if ( Value0 == 1 && Value1 == 1 ) // both are 1 + return CbsP_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), Gia_ObjFanin1(pVar) ); + assert( Value0 == 1 || Value1 == 1 ); + if ( Value0 == 2 ) // first is unassigned + CbsP_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)), Level, pVar, Gia_ObjFanin1(pVar) ); + if ( Value1 == 2 ) // first is unassigned + CbsP_ManAssign( p, Gia_Not(Gia_ObjChild1(pVar)), Level, pVar, Gia_ObjFanin0(pVar) ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Propagates all variables.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int CbsP_ManPropagate( CbsP_Man_t * p, int Level ) +{ + int hClause; + Gia_Obj_t * pVar; + int i, k; + while ( 1 ) + { + CbsP_QueForEachEntry( p->pProp, pVar, i ) + { + if ( (hClause = CbsP_ManPropagateOne( p, pVar, Level )) ) + return hClause; + if( CbsP_ManCheckPropLimits(p) ) + return 0; + } + p->pProp.iHead = p->pProp.iTail; + k = p->pJust.iHead; + CbsP_QueForEachEntry( p->pJust, pVar, i ) + { + if ( CbsP_VarIsJust( pVar ) ) + p->pJust.pData[k++] = pVar; + else if ( (hClause = CbsP_ManPropagateTwo( p, pVar, Level )) ) + return hClause; + if( CbsP_ManCheckPropLimits(p) ) + return 0; + } + if ( k == p->pJust.iTail ) + break; + p->pJust.iTail = k; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Solve the problem recursively.] + + Description [Returns learnt clause if unsat, NULL if sat or undecided.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int CbsP_ManSolve_rec( CbsP_Man_t * p, int Level ) +{ + CbsP_Que_t * pQue = &(p->pClauses); + Gia_Obj_t * pVar = NULL, * pDecVar; + int hClause, hLearn0, hLearn1; + int iPropHead, iJustHead, iJustTail; + // propagate assignments + assert( !CbsP_QueIsEmpty(&p->pProp) ); + if ( (hClause = CbsP_ManPropagate( p, Level )) ) + return hClause; + + // quit using resource limits + if ( CbsP_ManCheckLimits( p ) ) + return 0; + // check for satisfying assignment + assert( CbsP_QueIsEmpty(&p->pProp) ); + if ( CbsP_QueIsEmpty(&p->pJust) ) + return 0; + p->Pars.nJustThis = Abc_MaxInt( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead ); + // remember the state before branching + iPropHead = p->pProp.iHead; + CbsP_QueStore( &p->pJust, &iJustHead, &iJustTail ); + p->Pars.nJscanThis += iJustTail - iJustHead; + if ( CbsP_ManCheckLimits( p ) ) + return 0; + // find the decision variable + if ( p->Pars.fUseHighest ) + pVar = CbsP_ManDecideHighest( p ); + else if ( p->Pars.fUseLowest ) + pVar = CbsP_ManDecideLowest( p ); + else if ( p->Pars.fUseMaxFF ) + pVar = CbsP_ManDecideMaxFF( p ); + else assert( 0 ); + assert( CbsP_VarIsJust( pVar ) ); + // chose decision variable using fanout count + + if ( Gia_ObjRefNum(p->pAig, Gia_ObjFanin0(pVar)) > Gia_ObjRefNum(p->pAig, Gia_ObjFanin1(pVar)) ) + pDecVar = Gia_Not(Gia_ObjChild0(pVar)); + else + pDecVar = Gia_Not(Gia_ObjChild1(pVar)); + +// pDecVar = Gia_NotCond( Gia_Regular(pDecVar), Gia_Regular(pDecVar)->fPhase ); +// pDecVar = Gia_Not(pDecVar); + // decide on first fanin + CbsP_ManAssign( p, pDecVar, Level+1, NULL, NULL ); + if ( !(hLearn0 = CbsP_ManSolve_rec( p, Level+1 )) ) + return 0; + if ( CbsP_ManCheckLimits( p ) ) + return 0; + if ( pQue->pData[hLearn0] != Gia_Regular(pDecVar) ) + return hLearn0; + CbsP_ManCancelUntil( p, iPropHead ); + CbsP_QueRestore( &p->pJust, iJustHead, iJustTail ); + // decide on second fanin + CbsP_ManAssign( p, Gia_Not(pDecVar), Level+1, NULL, NULL ); + if ( !(hLearn1 = CbsP_ManSolve_rec( p, Level+1 )) ) + return 0; + if ( CbsP_ManCheckLimits( p ) ) + return 0; + if ( pQue->pData[hLearn1] != Gia_Regular(pDecVar) ) + return hLearn1; + hClause = CbsP_ManResolve( p, Level, hLearn0, hLearn1 ); +// CbsP_ManPrintClauseNew( p, Level, hClause ); +// if ( Level > CbsP_ClauseDecLevel(p, hClause) ) +// p->Pars.nBTThisNc++; + p->Pars.nBTThis++; + return hClause; +} + +/**Function************************************************************* + + Synopsis [Looking for a satisfying assignment of the node.] + + Description [Assumes that each node has flag pObj->fMark0 set to 0. + Returns 1 if unsatisfiable, 0 if satisfiable, and -1 if undecided. + The node may be complemented. ] + + SideEffects [The two procedures differ in the CEX format.] + + SeeAlso [] + +***********************************************************************/ +int CbsP_ManSolve( CbsP_Man_t * p, Gia_Obj_t * pObj ) +{ + int RetValue = 0; +// s_Counter = 0; + assert( !p->pProp.iHead && !p->pProp.iTail ); + assert( !p->pJust.iHead && !p->pJust.iTail ); + assert( p->pClauses.iHead == 1 && p->pClauses.iTail == 1 ); + p->Pars.nBTThis = p->Pars.nJustThis = p->Pars.nBTThisNc = 0; + CbsP_ManAssign( p, pObj, 0, NULL, NULL ); + if ( !CbsP_ManSolve_rec(p, 0) && !CbsP_ManCheckLimits(p) ) + CbsP_ManSaveModel( p, p->vModel ); + else + RetValue = 1; + CbsP_ManCancelUntil( p, 0 ); + p->pJust.iHead = p->pJust.iTail = 0; + p->pClauses.iHead = p->pClauses.iTail = 1; + p->Pars.nBTTotal += p->Pars.nBTThis; + p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis ); + if ( CbsP_ManCheckLimits( p ) ) + RetValue = -1; +// printf( "%d ", s_Counter ); + return RetValue; +} +int CbsP_ManSolve2( CbsP_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pObj2 ) +{ + abctime clk = Abc_Clock(); + int RetValue = 0; +// s_Counter = 0; + assert( !p->pProp.iHead && !p->pProp.iTail ); + assert( !p->pJust.iHead && !p->pJust.iTail ); + assert( p->pClauses.iHead == 1 && p->pClauses.iTail == 1 ); + p->Pars.nBTThis = p->Pars.nJustThis = p->Pars.nBTThisNc = 0; + p->Pars.nJscanThis = p->Pars.nRscanThis = p->Pars.nPropThis = 0; + CbsP_ManAssign( p, pObj, 0, NULL, NULL ); + if ( pObj2 ) + CbsP_ManAssign( p, pObj2, 0, NULL, NULL ); + if ( !CbsP_ManSolve_rec(p, 0) && !CbsP_ManCheckLimits(p) ) + CbsP_ManSaveModel( p, p->vModel ); + else + RetValue = 1; + CbsP_ManCancelUntil( p, 0 ); + + p->pJust.iHead = p->pJust.iTail = 0; + p->pClauses.iHead = p->pClauses.iTail = 1; + p->Pars.nBTTotal += p->Pars.nBTThis; + p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis ); + if ( CbsP_ManCheckLimits( p ) ) + RetValue = -1; + + if( CBS_SAT == RetValue ){ + p->nSatSat ++; + p->timeSatSat += Abc_Clock() - clk; + p->nConfSat += p->Pars.nBTThis; + } else + if( CBS_UNSAT == RetValue ){ + p->nSatUnsat ++; + p->timeSatUnsat += Abc_Clock() - clk; + p->nConfUnsat += p->Pars.nBTThis; + } else { + p->nSatUndec ++; + p->timeSatUndec += Abc_Clock() - clk; + p->nConfUndec += p->Pars.nBTThis; + } +// printf( "%d ", s_Counter ); + CbsP_UpdateRecord(&p->Pars,RetValue); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Prints statistics of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void CbsP_ManSatPrintStats( CbsP_Man_t * p ) +{ + printf( "CO = %8d ", Gia_ManCoNum(p->pAig) ); + printf( "AND = %8d ", Gia_ManAndNum(p->pAig) ); + printf( "Conf = %6d ", p->Pars.nBTLimit ); + printf( "JustMax = %5d ", p->Pars.nJustLimit ); + printf( "\n" ); + printf( "Unsat calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatUnsat, p->nSatTotal? 100.0*p->nSatUnsat/p->nSatTotal :0.0, p->nSatUnsat? 1.0*p->nConfUnsat/p->nSatUnsat :0.0 ); + ABC_PRTP( "Time", p->timeSatUnsat, p->timeTotal ); + printf( "Sat calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatSat, p->nSatTotal? 100.0*p->nSatSat/p->nSatTotal :0.0, p->nSatSat? 1.0*p->nConfSat/p->nSatSat : 0.0 ); + ABC_PRTP( "Time", p->timeSatSat, p->timeTotal ); + printf( "Undef calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatUndec, p->nSatTotal? 100.0*p->nSatUndec/p->nSatTotal :0.0, p->nSatUndec? 1.0*p->nConfUndec/p->nSatUndec : 0.0 ); + ABC_PRTP( "Time", p->timeSatUndec, p->timeTotal ); + ABC_PRT( "Total time", p->timeTotal ); +} + +/**Function************************************************************* + + Synopsis [Procedure to test the new SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * CbsP_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int f0Proved, int fVerbose ) +{ + extern void Gia_ManCollectTest( Gia_Man_t * pAig ); + extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out ); + CbsP_Man_t * p; + Vec_Int_t * vCex, * vVisit, * vCexStore; + Vec_Str_t * vStatus; + Gia_Obj_t * pRoot; + int i, status; + abctime clk, clkTotal = Abc_Clock(); + assert( Gia_ManRegNum(pAig) == 0 ); +// Gia_ManCollectTest( pAig ); + // prepare AIG + Gia_ManCreateRefs( pAig ); + Gia_ManCleanMark0( pAig ); + Gia_ManCleanMark1( pAig ); + Gia_ManFillValue( pAig ); // maps nodes into trail ids + Gia_ManSetPhase( pAig ); // maps nodes into trail ids + // create logic network + p = CbsP_ManAlloc( pAig ); + p->Pars.nBTLimit = nConfs; + // create resulting data-structures + vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) ); + vCexStore = Vec_IntAlloc( 10000 ); + vVisit = Vec_IntAlloc( 100 ); + vCex = CbsP_ReadModel( p ); + // solve for each output + Gia_ManForEachCo( pAig, pRoot, i ) + { +// printf( "\n" ); + + Vec_IntClear( vCex ); + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pRoot)) ) + { + if ( Gia_ObjFaninC0(pRoot) ) + { +// printf( "Constant 1 output of SRM!!!\n" ); + Cec_ManSatAddToStore( vCexStore, vCex, i ); // trivial counter-example + Vec_StrPush( vStatus, 0 ); + } + else + { +// printf( "Constant 0 output of SRM!!!\n" ); + Vec_StrPush( vStatus, 1 ); + } + continue; + } + clk = Abc_Clock(); + p->Pars.fUseHighest = 1; + p->Pars.fUseLowest = 0; + status = CbsP_ManSolve( p, Gia_ObjChild0(pRoot) ); +// printf( "\n" ); +/* + if ( status == -1 ) + { + p->Pars.fUseHighest = 0; + p->Pars.fUseLowest = 1; + status = CbsP_ManSolve( p, Gia_ObjChild0(pRoot) ); + } +*/ + Vec_StrPush( vStatus, (char)status ); + if ( status == -1 ) + { + p->nSatUndec++; + p->nConfUndec += p->Pars.nBTThis; + Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout + p->timeSatUndec += Abc_Clock() - clk; + continue; + } + if ( status == 1 ) + { + if ( f0Proved ) + Gia_ManPatchCoDriver( pAig, i, 0 ); + p->nSatUnsat++; + p->nConfUnsat += p->Pars.nBTThis; + p->timeSatUnsat += Abc_Clock() - clk; + continue; + } + p->nSatSat++; + p->nConfSat += p->Pars.nBTThis; +// Gia_SatVerifyPattern( pAig, pRoot, vCex, vVisit ); + Cec_ManSatAddToStore( vCexStore, vCex, i ); + p->timeSatSat += Abc_Clock() - clk; + } + Vec_IntFree( vVisit ); + p->nSatTotal = Gia_ManPoNum(pAig); + p->timeTotal = Abc_Clock() - clkTotal; + if ( fVerbose ) + CbsP_ManSatPrintStats( p ); +// printf( "RecCalls = %8d. RecClause = %8d. RecNonChro = %8d.\n", p->nRecCall, p->nRecClause, p->nRecNonChro ); + CbsP_ManStop( p ); + *pvStatus = vStatus; + +// printf( "Total number of cex literals = %d. (Ave = %d)\n", +// Vec_IntSize(vCexStore)-2*p->nSatUndec-2*p->nSatSat, +// (Vec_IntSize(vCexStore)-2*p->nSatUndec-2*p->nSatSat)/p->nSatSat ); + return vCexStore; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaCSatP.h b/yosys/abc/src/aig/gia/giaCSatP.h new file mode 100644 index 00000000000..4182cd14467 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaCSatP.h @@ -0,0 +1,117 @@ +#ifndef ABC__aig__gia__giaCSatP_h +#define ABC__aig__gia__giaCSatP_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "gia.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_HEADER_START + + +typedef struct CbsP_Par_t_ CbsP_Par_t; +struct CbsP_Par_t_ +{ + // conflict limits + int nBTLimit; // limit on the number of conflicts + int nJustLimit; // limit on the size of justification queue + // current parameters + int nBTThis; // number of conflicts + int nBTThisNc; // number of conflicts + int nJustThis; // max size of the frontier + int nBTTotal; // total number of conflicts + int nJustTotal; // total size of the frontier + // decision heuristics + int fUseHighest; // use node with the highest ID + int fUseLowest; // use node with the highest ID + int fUseMaxFF; // use node with the largest fanin fanout + // other + int fVerbose; + int fUseProved; + + // statistics + int nJscanThis; + int nRscanThis; + int nPropThis; + int maxJscanUndec; + int maxRscanUndec; + int maxPropUndec; + int maxJscanSolved; + int maxRscanSolved; + int maxPropSolved; + int nSat, nUnsat, nUndec; + long accJscanSat; + long accJscanUnsat; + long accJscanUndec; + long accRscanSat; + long accRscanUnsat; + long accRscanUndec; + long accPropSat; + long accPropUnsat; + long accPropUndec; + + // other limits + int nJscanLimit; + int nRscanLimit; + int nPropLimit; +}; + +typedef struct CbsP_Que_t_ CbsP_Que_t; +struct CbsP_Que_t_ +{ + int iHead; // beginning of the queue + int iTail; // end of the queue + int nSize; // allocated size + Gia_Obj_t ** pData; // nodes stored in the queue +}; + +typedef struct CbsP_Man_t_ CbsP_Man_t; +struct CbsP_Man_t_ +{ + CbsP_Par_t Pars; // parameters + Gia_Man_t * pAig; // AIG manager + CbsP_Que_t pProp; // propagation queue + CbsP_Que_t pJust; // justification queue + CbsP_Que_t pClauses; // clause queue + Gia_Obj_t ** pIter; // iterator through clause vars + Vec_Int_t * vLevReas; // levels and decisions + Vec_Int_t * vValue; + Vec_Int_t * vModel; // satisfying assignment + Vec_Ptr_t * vTemp; // temporary storage + // SAT calls statistics + int nSatUnsat; // the number of proofs + int nSatSat; // the number of failure + int nSatUndec; // the number of timeouts + int nSatTotal; // the number of calls + // conflicts + int nConfUnsat; // conflicts in unsat problems + int nConfSat; // conflicts in sat problems + int nConfUndec; // conflicts in undec problems + // runtime stats + abctime timeSatUnsat; // unsat + abctime timeSatSat; // sat + abctime timeSatUndec; // undecided + abctime timeTotal; // total runtime +}; + +CbsP_Man_t * CbsP_ManAlloc( Gia_Man_t * pGia ); +void CbsP_ManStop( CbsP_Man_t * p ); +void CbsP_ManSatPrintStats( CbsP_Man_t * p ); +void CbsP_PrintRecord( CbsP_Par_t * pPars ); +int CbsP_ManSolve2( CbsP_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pObj2 ); + +#define CBS_UNSAT 1 +#define CBS_SAT 0 +#define CBS_UNDEC -1 + +ABC_NAMESPACE_HEADER_END + + +#endif diff --git a/yosys/abc/src/aig/gia/giaCTas.c b/yosys/abc/src/aig/gia/giaCTas.c new file mode 100644 index 00000000000..cd0b4f480b5 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaCTas.c @@ -0,0 +1,1791 @@ +/**CFile**************************************************************** + + FileName [giaCSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [A simple circuit-based solver.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaCSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//#define gia_assert(exp) ((void)0) +//#define gia_assert(exp) (assert(exp)) + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Tas_Par_t_ Tas_Par_t; +struct Tas_Par_t_ +{ + // conflict limits + int nBTLimit; // limit on the number of conflicts + int nJustLimit; // limit on the size of justification queue + // current parameters + int nBTThis; // number of conflicts + int nBTThisNc; // number of conflicts + int nJustThis; // max size of the frontier + int nBTTotal; // total number of conflicts + int nJustTotal; // total size of the frontier + // activity + float VarDecay; // variable activity decay + int VarInc; // variable increment + // decision heuristics + int fUseActive; // use most active + int fUseHighest; // use node with the highest ID + int fUseLowest; // use node with the highest ID + int fUseMaxFF; // use node with the largest fanin fanout + // other + int fVerbose; +}; + +typedef struct Tas_Cls_t_ Tas_Cls_t; +struct Tas_Cls_t_ +{ + int iNext[2]; // beginning of the queue + int nLits; // the number of literals + int pLits[0]; // clause literals +}; + +typedef struct Tas_Sto_t_ Tas_Sto_t; +struct Tas_Sto_t_ +{ + int iCur; // current position + int nSize; // allocated size + int * pData; // clause information +}; + +typedef struct Tas_Que_t_ Tas_Que_t; +struct Tas_Que_t_ +{ + int iHead; // beginning of the queue + int iTail; // end of the queue + int nSize; // allocated size + Gia_Obj_t ** pData; // nodes stored in the queue +}; + +struct Tas_Man_t_ +{ + Tas_Par_t Pars; // parameters + Gia_Man_t * pAig; // AIG manager + Tas_Que_t pProp; // propagation queue + Tas_Que_t pJust; // justification queue + Tas_Que_t pClauses; // clause queue + Gia_Obj_t ** pIter; // iterator through clause vars + Vec_Int_t * vLevReas; // levels and decisions + Vec_Int_t * vModel; // satisfying assignment + Vec_Ptr_t * vTemp; // temporary storage + // watched clauses + Tas_Sto_t pStore; // storage for watched clauses + int * pWatches; // watched lists for each literal + Vec_Int_t * vWatchLits; // lits whose watched are assigned + int nClauses; // the counter of clauses + // activity + float * pActivity; // variable activity + Vec_Int_t * vActiveVars; // variables with activity + // SAT calls statistics + int nSatUnsat; // the number of proofs + int nSatSat; // the number of failure + int nSatUndec; // the number of timeouts + int nSatTotal; // the number of calls + // conflicts + int nConfUnsat; // conflicts in unsat problems + int nConfSat; // conflicts in sat problems + int nConfUndec; // conflicts in undec problems + // runtime stats + abctime timeSatUnsat; // unsat + abctime timeSatSat; // sat + abctime timeSatUndec; // undecided + abctime timeTotal; // total runtime +}; + +static inline int Tas_VarIsAssigned( Gia_Obj_t * pVar ) { return pVar->fMark0; } +static inline void Tas_VarAssign( Gia_Obj_t * pVar ) { assert(!pVar->fMark0); pVar->fMark0 = 1; } +static inline void Tas_VarUnassign( Gia_Obj_t * pVar ) { assert(pVar->fMark0); pVar->fMark0 = 0; pVar->fMark1 = 0; pVar->Value = ~0; } +static inline int Tas_VarValue( Gia_Obj_t * pVar ) { assert(pVar->fMark0); return pVar->fMark1; } +static inline void Tas_VarSetValue( Gia_Obj_t * pVar, int v ) { assert(pVar->fMark0); pVar->fMark1 = v; } +static inline int Tas_VarIsJust( Gia_Obj_t * pVar ) { return Gia_ObjIsAnd(pVar) && !Tas_VarIsAssigned(Gia_ObjFanin0(pVar)) && !Tas_VarIsAssigned(Gia_ObjFanin1(pVar)); } +static inline int Tas_VarFanin0Value( Gia_Obj_t * pVar ) { return !Tas_VarIsAssigned(Gia_ObjFanin0(pVar)) ? 2 : (Tas_VarValue(Gia_ObjFanin0(pVar)) ^ Gia_ObjFaninC0(pVar)); } +static inline int Tas_VarFanin1Value( Gia_Obj_t * pVar ) { return !Tas_VarIsAssigned(Gia_ObjFanin1(pVar)) ? 2 : (Tas_VarValue(Gia_ObjFanin1(pVar)) ^ Gia_ObjFaninC1(pVar)); } +static inline int Tas_VarToLit( Tas_Man_t * p, Gia_Obj_t * pObj ) { assert( Tas_VarIsAssigned(pObj) ); return Abc_Var2Lit( Gia_ObjId(p->pAig, pObj), !Tas_VarValue(pObj) ); } +static inline int Tas_LitIsTrue( Gia_Obj_t * pObj, int Lit ) { assert( Tas_VarIsAssigned(pObj) ); return Tas_VarValue(pObj) != Abc_LitIsCompl(Lit); } + +static inline int Tas_ClsHandle( Tas_Man_t * p, Tas_Cls_t * pClause ) { return ((int *)pClause) - p->pStore.pData; } +static inline Tas_Cls_t * Tas_ClsFromHandle( Tas_Man_t * p, int h ) { return (Tas_Cls_t *)(p->pStore.pData + h); } + +static inline int Tas_VarDecLevel( Tas_Man_t * p, Gia_Obj_t * pVar ) { assert( pVar->Value != ~0 ); return Vec_IntEntry(p->vLevReas, 3*pVar->Value); } +static inline Gia_Obj_t * Tas_VarReason0( Tas_Man_t * p, Gia_Obj_t * pVar ) { assert( pVar->Value != ~0 ); return pVar + Vec_IntEntry(p->vLevReas, 3*pVar->Value+1); } +static inline Gia_Obj_t * Tas_VarReason1( Tas_Man_t * p, Gia_Obj_t * pVar ) { assert( pVar->Value != ~0 ); return pVar + Vec_IntEntry(p->vLevReas, 3*pVar->Value+2); } +static inline int Tas_ClauseDecLevel( Tas_Man_t * p, int hClause ) { return Tas_VarDecLevel( p, p->pClauses.pData[hClause] ); } + +static inline int Tas_VarHasReasonCls( Tas_Man_t * p, Gia_Obj_t * pVar ) { assert( pVar->Value != ~0 ); return Vec_IntEntry(p->vLevReas, 3*pVar->Value+1) == 0 && Vec_IntEntry(p->vLevReas, 3*pVar->Value+2) != 0; } +static inline Tas_Cls_t * Tas_VarReasonCls( Tas_Man_t * p, Gia_Obj_t * pVar ) { assert( pVar->Value != ~0 ); return Tas_ClsFromHandle( p, Vec_IntEntry(p->vLevReas, 3*pVar->Value+2) ); } + +#define Tas_QueForEachEntry( Que, pObj, i ) \ + for ( i = (Que).iHead; (i < (Que).iTail) && ((pObj) = (Que).pData[i]); i++ ) + +#define Tas_ClauseForEachVar( p, hClause, pObj ) \ + for ( (p)->pIter = (p)->pClauses.pData + hClause; (pObj = *pIter); (p)->pIter++ ) +#define Tas_ClauseForEachVar1( p, hClause, pObj ) \ + for ( (p)->pIter = (p)->pClauses.pData+hClause+1; (pObj = *pIter); (p)->pIter++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Sets default values of the parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Tas_SetDefaultParams( Tas_Par_t * pPars ) +{ + memset( pPars, 0, sizeof(Tas_Par_t) ); + pPars->nBTLimit = 2000; // limit on the number of conflicts + pPars->nJustLimit = 2000; // limit on the size of justification queue + pPars->fUseActive = 0; // use node with the highest activity + pPars->fUseHighest = 1; // use node with the highest ID + pPars->fUseLowest = 0; // use node with the lowest ID + pPars->fUseMaxFF = 0; // use node with the largest fanin fanout + pPars->fVerbose = 1; // print detailed statistics + pPars->VarDecay = (float)0.95; // variable decay + pPars->VarInc = 1.0; // variable increment +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Tas_Man_t * Tas_ManAlloc( Gia_Man_t * pAig, int nBTLimit ) +{ + Tas_Man_t * p; + p = ABC_CALLOC( Tas_Man_t, 1 ); + Tas_SetDefaultParams( &p->Pars ); + p->pAig = pAig; + p->Pars.nBTLimit = nBTLimit; + p->pProp.nSize = p->pJust.nSize = p->pClauses.nSize = 10000; + p->pProp.pData = ABC_ALLOC( Gia_Obj_t *, p->pProp.nSize ); + p->pJust.pData = ABC_ALLOC( Gia_Obj_t *, p->pJust.nSize ); + p->pClauses.pData = ABC_ALLOC( Gia_Obj_t *, p->pClauses.nSize ); + p->pClauses.iHead = p->pClauses.iTail = 1; + p->vModel = Vec_IntAlloc( 1000 ); + p->vLevReas = Vec_IntAlloc( 1000 ); + p->vTemp = Vec_PtrAlloc( 1000 ); + p->pStore.iCur = 16; + p->pStore.nSize = 10000; + p->pStore.pData = ABC_ALLOC( int, p->pStore.nSize ); + p->pWatches = ABC_CALLOC( int, 2 * Gia_ManObjNum(pAig) ); + p->vWatchLits = Vec_IntAlloc( 100 ); + p->pActivity = ABC_CALLOC( float, Gia_ManObjNum(pAig) ); + p->vActiveVars = Vec_IntAlloc( 100 ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Tas_ManStop( Tas_Man_t * p ) +{ + Vec_IntFree( p->vActiveVars ); + Vec_IntFree( p->vWatchLits ); + Vec_IntFree( p->vLevReas ); + Vec_IntFree( p->vModel ); + Vec_PtrFree( p->vTemp ); + ABC_FREE( p->pActivity ); + ABC_FREE( p->pWatches ); + ABC_FREE( p->pStore.pData ); + ABC_FREE( p->pClauses.pData ); + ABC_FREE( p->pProp.pData ); + ABC_FREE( p->pJust.pData ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Returns satisfying assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Tas_ReadModel( Tas_Man_t * p ) +{ + return p->vModel; +} + + + + +/**Function************************************************************* + + Synopsis [Returns 1 if the solver is out of limits.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Tas_ManCheckLimits( Tas_Man_t * p ) +{ + return p->Pars.nJustThis > p->Pars.nJustLimit || p->Pars.nBTThis > p->Pars.nBTLimit; +} + +/**Function************************************************************* + + Synopsis [Saves the satisfying assignment as an array of literals.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Tas_ManSaveModel( Tas_Man_t * p, Vec_Int_t * vCex ) +{ + Gia_Obj_t * pVar; + int i; + Vec_IntClear( vCex ); + p->pProp.iHead = 0; +// printf( "\n" ); + Tas_QueForEachEntry( p->pProp, pVar, i ) + { + if ( Gia_ObjIsCi(pVar) ) +// Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjId(p->pAig,pVar), !Tas_VarValue(pVar)) ); + Vec_IntPush( vCex, Abc_Var2Lit(Gia_ObjCioId(pVar), !Tas_VarValue(pVar)) ); +/* + printf( "%5d(%d) = ", Gia_ObjId(p->pAig, pVar), Tas_VarValue(pVar) ); + if ( Gia_ObjIsCi(pVar) ) + printf( "pi %d\n", Gia_ObjCioId(pVar) ); + else + { + printf( "%5d %d & ", Gia_ObjFaninId0p(p->pAig, pVar), Gia_ObjFaninC0(pVar) ); + printf( "%5d %d ", Gia_ObjFaninId1p(p->pAig, pVar), Gia_ObjFaninC1(pVar) ); + printf( "\n" ); + } +*/ + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Tas_QueIsEmpty( Tas_Que_t * p ) +{ + return p->iHead == p->iTail; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Tas_QuePush( Tas_Que_t * p, Gia_Obj_t * pObj ) +{ + if ( p->iTail == p->nSize ) + { + p->nSize *= 2; + p->pData = ABC_REALLOC( Gia_Obj_t *, p->pData, p->nSize ); + } + p->pData[p->iTail++] = pObj; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the object in the queue.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Tas_QueHasNode( Tas_Que_t * p, Gia_Obj_t * pObj ) +{ + Gia_Obj_t * pTemp; + int i; + Tas_QueForEachEntry( *p, pTemp, i ) + if ( pTemp == pObj ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Tas_QueStore( Tas_Que_t * p, int * piHeadOld, int * piTailOld ) +{ + int i; + *piHeadOld = p->iHead; + *piTailOld = p->iTail; + for ( i = *piHeadOld; i < *piTailOld; i++ ) + Tas_QuePush( p, p->pData[i] ); + p->iHead = *piTailOld; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Tas_QueRestore( Tas_Que_t * p, int iHeadOld, int iTailOld ) +{ + p->iHead = iHeadOld; + p->iTail = iTailOld; +} + +/**Function************************************************************* + + Synopsis [Finalized the clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Tas_QueFinish( Tas_Que_t * p ) +{ + int iHeadOld = p->iHead; + assert( p->iHead < p->iTail ); + Tas_QuePush( p, NULL ); + p->iHead = p->iTail; + return iHeadOld; +} + + +/**Function************************************************************* + + Synopsis [Max number of fanins fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Tas_VarFaninFanoutMax( Tas_Man_t * p, Gia_Obj_t * pObj ) +{ + int Count0, Count1; + assert( !Gia_IsComplement(pObj) ); + assert( Gia_ObjIsAnd(pObj) ); + Count0 = Gia_ObjRefNum( p->pAig, Gia_ObjFanin0(pObj) ); + Count1 = Gia_ObjRefNum( p->pAig, Gia_ObjFanin1(pObj) ); + return Abc_MaxInt( Count0, Count1 ); +} + + + +/**Function************************************************************* + + Synopsis [Find variable with the highest activity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * Tas_ManFindActive( Tas_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjMax = NULL; + float BestCost = 0.0; + int i, ObjId; + Tas_QueForEachEntry( p->pJust, pObj, i ) + { + assert( Gia_ObjIsAnd(pObj) ); + ObjId = Gia_ObjId( p->pAig, pObj ); + if ( pObjMax == NULL || + p->pActivity[Gia_ObjFaninId0(pObj,ObjId)] > BestCost || + (p->pActivity[Gia_ObjFaninId0(pObj,ObjId)] == BestCost && pObjMax < Gia_ObjFanin0(pObj)) ) + { + pObjMax = Gia_ObjFanin0(pObj); + BestCost = p->pActivity[Gia_ObjFaninId0(pObj,ObjId)]; + } + if ( p->pActivity[Gia_ObjFaninId1(pObj,ObjId)] > BestCost || + (p->pActivity[Gia_ObjFaninId1(pObj,ObjId)] == BestCost && pObjMax < Gia_ObjFanin1(pObj)) ) + { + pObjMax = Gia_ObjFanin1(pObj); + BestCost = p->pActivity[Gia_ObjFaninId1(pObj,ObjId)]; + } + } + return pObjMax; +} + +/**Function************************************************************* + + Synopsis [Find variable with the highest activity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * Tas_ManDecideHighestFanin( Tas_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjMax = NULL; + int i, ObjId; + Tas_QueForEachEntry( p->pJust, pObj, i ) + { + assert( Gia_ObjIsAnd(pObj) ); + ObjId = Gia_ObjId( p->pAig, pObj ); + if ( pObjMax == NULL || pObjMax < Gia_ObjFanin0(pObj) ) + pObjMax = Gia_ObjFanin0(pObj); + if ( pObjMax < Gia_ObjFanin1(pObj) ) + pObjMax = Gia_ObjFanin1(pObj); + } + return pObjMax; +} + +/**Function************************************************************* + + Synopsis [Find variable with the highest ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * Tas_ManDecideHighest( Tas_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjMax = NULL; + int i; + Tas_QueForEachEntry( p->pJust, pObj, i ) + { +//printf( "%d %6.2f ", Gia_ObjId(p->pAig, pObj), p->pActivity[Gia_ObjId(p->pAig, pObj)] ); + if ( pObjMax == NULL || pObjMax < pObj ) + pObjMax = pObj; + } +//printf( "\n" ); + return pObjMax; +} + +/**Function************************************************************* + + Synopsis [Find variable with the highest ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * Tas_ManDecideHighestA( Tas_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjMax = NULL; + int i; + Tas_QueForEachEntry( p->pJust, pObj, i ) + { + if ( pObjMax == NULL || + p->pActivity[Gia_ObjId(p->pAig, pObjMax)] < p->pActivity[Gia_ObjId(p->pAig, pObj)] ) + pObjMax = pObj; + } + return pObjMax; +} + +/**Function************************************************************* + + Synopsis [Find variable with the lowest ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * Tas_ManDecideLowest( Tas_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjMin = NULL; + int i; + Tas_QueForEachEntry( p->pJust, pObj, i ) + if ( pObjMin == NULL || pObjMin > pObj ) + pObjMin = pObj; + return pObjMin; +} + +/**Function************************************************************* + + Synopsis [Find variable with the maximum number of fanin fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * Tas_ManDecideMaxFF( Tas_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjMax = NULL; + int i, iMaxFF = 0, iCurFF; + assert( p->pAig->pRefs != NULL ); + Tas_QueForEachEntry( p->pJust, pObj, i ) + { + iCurFF = Tas_VarFaninFanoutMax( p, pObj ); + assert( iCurFF > 0 ); + if ( iMaxFF < iCurFF ) + { + iMaxFF = iCurFF; + pObjMax = pObj; + } + } + return pObjMax; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Tas_ManCancelUntil( Tas_Man_t * p, int iBound ) +{ + Gia_Obj_t * pVar; + int i; + assert( iBound <= p->pProp.iTail ); + p->pProp.iHead = iBound; + Tas_QueForEachEntry( p->pProp, pVar, i ) + Tas_VarUnassign( pVar ); + p->pProp.iTail = iBound; + Vec_IntShrink( p->vLevReas, 3*iBound ); +} + +int s_Counter2 = 0; +int s_Counter3 = 0; +int s_Counter4 = 0; + +/**Function************************************************************* + + Synopsis [Assigns the variables a value.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Tas_ManAssign( Tas_Man_t * p, Gia_Obj_t * pObj, int Level, Gia_Obj_t * pRes0, Gia_Obj_t * pRes1 ) +{ + Gia_Obj_t * pObjR = Gia_Regular(pObj); + assert( Gia_ObjIsCand(pObjR) ); + assert( !Tas_VarIsAssigned(pObjR) ); + Tas_VarAssign( pObjR ); + Tas_VarSetValue( pObjR, !Gia_IsComplement(pObj) ); + assert( pObjR->Value == ~0 ); + pObjR->Value = p->pProp.iTail; + Tas_QuePush( &p->pProp, pObjR ); + Vec_IntPush( p->vLevReas, Level ); + if ( pRes0 == NULL && pRes1 != 0 ) // clause + { + Vec_IntPush( p->vLevReas, 0 ); + Vec_IntPush( p->vLevReas, Tas_ClsHandle( p, (Tas_Cls_t *)pRes1 ) ); + } + else + { + Vec_IntPush( p->vLevReas, pRes0 ? pRes0-pObjR : 0 ); + Vec_IntPush( p->vLevReas, pRes1 ? pRes1-pObjR : 0 ); + } + assert( Vec_IntSize(p->vLevReas) == 3 * p->pProp.iTail ); + s_Counter2++; +} + + +/**Function************************************************************* + + Synopsis [Returns clause size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Tas_ManClauseSize( Tas_Man_t * p, int hClause ) +{ + Tas_Que_t * pQue = &(p->pClauses); + Gia_Obj_t ** pIter; + for ( pIter = pQue->pData + hClause; *pIter; pIter++ ); + return pIter - pQue->pData - hClause ; +} + +/**Function************************************************************* + + Synopsis [Prints conflict clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Tas_ManPrintClause( Tas_Man_t * p, int Level, int hClause ) +{ + Tas_Que_t * pQue = &(p->pClauses); + Gia_Obj_t * pObj; + int i; + assert( Tas_QueIsEmpty( pQue ) ); + printf( "Level %2d : ", Level ); + for ( i = hClause; (pObj = pQue->pData[i]); i++ ) + printf( "%d=%d(%d) ", Gia_ObjId(p->pAig, pObj), Tas_VarValue(pObj), Tas_VarDecLevel(p, pObj) ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints conflict clause.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Tas_ManPrintClauseNew( Tas_Man_t * p, int Level, int hClause ) +{ + Tas_Que_t * pQue = &(p->pClauses); + Gia_Obj_t * pObj; + int i; + assert( Tas_QueIsEmpty( pQue ) ); + printf( "Level %2d : ", Level ); + for ( i = hClause; (pObj = pQue->pData[i]); i++ ) + printf( "%c%d ", Tas_VarValue(pObj)? '+':'-', Gia_ObjId(p->pAig, pObj) ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Returns conflict clause.] + + Description [Performs conflict analysis.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Tas_ManDeriveReason( Tas_Man_t * p, int Level ) +{ + Tas_Que_t * pQue = &(p->pClauses); + Gia_Obj_t * pObj, * pReason; + int i, k, j, iLitLevel, iLitLevel2;//, Id; + assert( pQue->pData[pQue->iHead] == NULL ); + assert( pQue->iHead + 1 < pQue->iTail ); +/* + for ( i = pQue->iHead + 1; i < pQue->iTail; i++ ) + { + pObj = pQue->pData[i]; + assert( pObj->fPhase == 0 ); + } +*/ + // compact literals + Vec_PtrClear( p->vTemp ); + for ( i = k = pQue->iHead + 1; i < pQue->iTail; i++ ) + { + pObj = pQue->pData[i]; + if ( pObj->fPhase ) // unassigned - seen again + continue; + // assigned - seen first time + pObj->fPhase = 1; + Vec_PtrPush( p->vTemp, pObj ); + // bump activity +// Id = Gia_ObjId( p->pAig, pObj ); +// if ( p->pActivity[Id] == 0.0 ) +// Vec_IntPush( p->vActiveVars, Id ); +// p->pActivity[Id] += p->Pars.VarInc; + // check decision level + iLitLevel = Tas_VarDecLevel( p, pObj ); + if ( iLitLevel < Level ) + { + pQue->pData[k++] = pObj; + continue; + } + assert( iLitLevel == Level ); + if ( Tas_VarHasReasonCls( p, pObj ) ) + { + Tas_Cls_t * pCls = Tas_VarReasonCls( p, pObj ); + pReason = Gia_ManObj( p->pAig, Abc_Lit2Var(pCls->pLits[0]) ); + assert( pReason == pObj ); + for ( j = 1; j < pCls->nLits; j++ ) + { + pReason = Gia_ManObj( p->pAig, Abc_Lit2Var(pCls->pLits[j]) ); + iLitLevel2 = Tas_VarDecLevel( p, pReason ); + assert( Tas_VarIsAssigned( pReason ) ); + assert( !Tas_LitIsTrue( pReason, pCls->pLits[j] ) ); + Tas_QuePush( pQue, pReason ); + } + } + else + { + pReason = Tas_VarReason0( p, pObj ); + if ( pReason == pObj ) // no reason + { + assert( pQue->pData[pQue->iHead] == NULL || Level == 0 ); + if ( pQue->pData[pQue->iHead] == NULL ) + pQue->pData[pQue->iHead] = pObj; + else + Tas_QuePush( pQue, pObj ); + continue; + } + Tas_QuePush( pQue, pReason ); + pReason = Tas_VarReason1( p, pObj ); + if ( pReason != pObj ) // second reason + Tas_QuePush( pQue, pReason ); + } + } + assert( pQue->pData[pQue->iHead] != NULL ); + if ( pQue->pData[pQue->iHead] == NULL ) + printf( "Tas_ManDeriveReason(): Failed to derive the clause!!!\n" ); + pQue->iTail = k; + // clear the marks + Vec_PtrForEachEntry( Gia_Obj_t *, p->vTemp, pObj, i ) + pObj->fPhase = 0; +} + +/**Function************************************************************* + + Synopsis [Returns conflict clause.] + + Description [Performs conflict analysis.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Tas_ManAnalyze( Tas_Man_t * p, int Level, Gia_Obj_t * pVar, Gia_Obj_t * pFan0, Gia_Obj_t * pFan1 ) +{ + Tas_Que_t * pQue = &(p->pClauses); + assert( Tas_VarIsAssigned(pVar) ); + assert( Tas_VarIsAssigned(pFan0) ); + assert( pFan1 == NULL || Tas_VarIsAssigned(pFan1) ); + assert( Tas_QueIsEmpty( pQue ) ); + Tas_QuePush( pQue, NULL ); + Tas_QuePush( pQue, pVar ); + Tas_QuePush( pQue, pFan0 ); + if ( pFan1 ) + Tas_QuePush( pQue, pFan1 ); + Tas_ManDeriveReason( p, Level ); + return Tas_QueFinish( pQue ); +} + + +/**Function************************************************************* + + Synopsis [Performs resolution of two clauses.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Tas_ManResolve( Tas_Man_t * p, int Level, int hClause0, int hClause1 ) +{ + Tas_Que_t * pQue = &(p->pClauses); + Gia_Obj_t * pObj; + int i, LevelMax = -1, LevelCur; + assert( pQue->pData[hClause0] != NULL ); + assert( pQue->pData[hClause0] == pQue->pData[hClause1] ); +/* + for ( i = hClause0 + 1; (pObj = pQue->pData[i]); i++ ) + assert( pObj->fPhase == 0 ); + for ( i = hClause1 + 1; (pObj = pQue->pData[i]); i++ ) + assert( pObj->fPhase == 0 ); +*/ + assert( Tas_QueIsEmpty( pQue ) ); + Tas_QuePush( pQue, NULL ); + for ( i = hClause0 + 1; (pObj = pQue->pData[i]); i++ ) + { + if ( pObj->fPhase ) // unassigned - seen again + continue; + // assigned - seen first time + pObj->fPhase = 1; + Tas_QuePush( pQue, pObj ); + LevelCur = Tas_VarDecLevel( p, pObj ); + if ( LevelMax < LevelCur ) + LevelMax = LevelCur; + } + for ( i = hClause1 + 1; (pObj = pQue->pData[i]); i++ ) + { + if ( pObj->fPhase ) // unassigned - seen again + continue; + // assigned - seen first time + pObj->fPhase = 1; + Tas_QuePush( pQue, pObj ); + LevelCur = Tas_VarDecLevel( p, pObj ); + if ( LevelMax < LevelCur ) + LevelMax = LevelCur; + } + for ( i = pQue->iHead + 1; i < pQue->iTail; i++ ) + pQue->pData[i]->fPhase = 0; + Tas_ManDeriveReason( p, LevelMax ); + return Tas_QueFinish( pQue ); +} + + + +/**Function************************************************************* + + Synopsis [Allocates clause of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Tas_Cls_t * Tas_ManAllocCls( Tas_Man_t * p, int nSize ) +{ + Tas_Cls_t * pCls; + if ( p->pStore.iCur + nSize > p->pStore.nSize ) + { + p->pStore.nSize *= 2; + p->pStore.pData = ABC_REALLOC( int, p->pStore.pData, p->pStore.nSize ); + } + pCls = Tas_ClsFromHandle( p, p->pStore.iCur ); p->pStore.iCur += nSize; + memset( pCls, 0, sizeof(int) * nSize ); + p->nClauses++; + return pCls; +} + +/**Function************************************************************* + + Synopsis [Adds one clause to the watcher list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Tas_ManWatchClause( Tas_Man_t * p, Tas_Cls_t * pClause, int Lit ) +{ + assert( Abc_Lit2Var(Lit) < Gia_ManObjNum(p->pAig) ); + assert( pClause->nLits >= 2 ); + assert( pClause->pLits[0] == Lit || pClause->pLits[1] == Lit ); + if ( pClause->pLits[0] == Lit ) + pClause->iNext[0] = p->pWatches[Abc_LitNot(Lit)]; + else + pClause->iNext[1] = p->pWatches[Abc_LitNot(Lit)]; + if ( p->pWatches[Abc_LitNot(Lit)] == 0 ) + Vec_IntPush( p->vWatchLits, Abc_LitNot(Lit) ); + p->pWatches[Abc_LitNot(Lit)] = Tas_ClsHandle( p, pClause ); +} + +/**Function************************************************************* + + Synopsis [Creates clause of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Tas_Cls_t * Tas_ManCreateCls( Tas_Man_t * p, int hClause ) +{ + Tas_Cls_t * pClause; + Tas_Que_t * pQue = &(p->pClauses); + Gia_Obj_t * pObj; + int i, nLits = 0; + assert( Tas_QueIsEmpty( pQue ) ); + assert( pQue->pData[hClause] != NULL ); + for ( i = hClause; (pObj = pQue->pData[i]); i++ ) + nLits++; + if ( nLits == 1 ) + return NULL; + // create this clause + pClause = Tas_ManAllocCls( p, nLits + 3 ); + pClause->nLits = nLits; + for ( i = hClause; (pObj = pQue->pData[i]); i++ ) + { + assert( Tas_VarIsAssigned( pObj ) ); + pClause->pLits[i-hClause] = Abc_LitNot( Tas_VarToLit(p, pObj) ); + } + // add the clause as watched one + if ( nLits >= 2 ) + { + Tas_ManWatchClause( p, pClause, pClause->pLits[0] ); + Tas_ManWatchClause( p, pClause, pClause->pLits[1] ); + } + // increment activity +// p->Pars.VarInc /= p->Pars.VarDecay; + return pClause; +} + +/**Function************************************************************* + + Synopsis [Creates clause of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Tas_ManCreateFromCls( Tas_Man_t * p, Tas_Cls_t * pCls, int Level ) +{ + Tas_Que_t * pQue = &(p->pClauses); + Gia_Obj_t * pObj; + int i; + assert( Tas_QueIsEmpty( pQue ) ); + Tas_QuePush( pQue, NULL ); + for ( i = 0; i < pCls->nLits; i++ ) + { + pObj = Gia_ManObj( p->pAig, Abc_Lit2Var(pCls->pLits[i]) ); + assert( Tas_VarIsAssigned(pObj) ); + assert( !Tas_LitIsTrue( pObj, pCls->pLits[i] ) ); + Tas_QuePush( pQue, pObj ); + } + Tas_ManDeriveReason( p, Level ); + return Tas_QueFinish( pQue ); +} + +/**Function************************************************************* + + Synopsis [Propagate one assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Tas_ManPropagateWatch( Tas_Man_t * p, int Level, int Lit ) +{ + Gia_Obj_t * pObj; + Tas_Cls_t * pCur; + int * piPrev, iCur, iTemp; + int i, LitF = Abc_LitNot(Lit); + // iterate through the clauses + piPrev = p->pWatches + Lit; + for ( iCur = p->pWatches[Lit]; iCur; iCur = *piPrev ) + { + pCur = Tas_ClsFromHandle( p, iCur ); + // make sure the false literal is in the second literal of the clause + if ( pCur->pLits[0] == LitF ) + { + pCur->pLits[0] = pCur->pLits[1]; + pCur->pLits[1] = LitF; + iTemp = pCur->iNext[0]; + pCur->iNext[0] = pCur->iNext[1]; + pCur->iNext[1] = iTemp; + } + assert( pCur->pLits[1] == LitF ); + + // if the first literal is true, the clause is satisfied +// if ( pCur->pLits[0] == p->pAssigns[Abc_Lit2Var(pCur->pLits[0])] ) + pObj = Gia_ManObj( p->pAig, Abc_Lit2Var(pCur->pLits[0]) ); + if ( Tas_VarIsAssigned(pObj) && Tas_LitIsTrue( pObj, pCur->pLits[0] ) ) + { + piPrev = &pCur->iNext[1]; + continue; + } + + // look for a new literal to watch + for ( i = 2; i < (int)pCur->nLits; i++ ) + { + // skip the case when the literal is false +// if ( Abc_LitNot(pCur->pLits[i]) == p->pAssigns[Abc_Lit2Var(pCur->pLits[i])] ) + pObj = Gia_ManObj( p->pAig, Abc_Lit2Var(pCur->pLits[i]) ); + if ( Tas_VarIsAssigned(pObj) && !Tas_LitIsTrue( pObj, pCur->pLits[i] ) ) + continue; + // the literal is either true or unassigned - watch it + pCur->pLits[1] = pCur->pLits[i]; + pCur->pLits[i] = LitF; + // remove this clause from the watch list of Lit + *piPrev = pCur->iNext[1]; + // add this clause to the watch list of pCur->pLits[i] (now it is pCur->pLits[1]) + Tas_ManWatchClause( p, pCur, pCur->pLits[1] ); + break; + } + if ( i < (int)pCur->nLits ) // found new watch + continue; + + // clause is unit - enqueue new implication + pObj = Gia_ManObj( p->pAig, Abc_Lit2Var(pCur->pLits[0]) ); + if ( !Tas_VarIsAssigned(pObj) ) + { +/* + { + int iLitLevel, iPlace; + for ( i = 1; i < (int)pCur->nLits; i++ ) + { + pObj = Gia_ManObj( p->pAig, Abc_Lit2Var(pCur->pLits[i]) ); + iLitLevel = Tas_VarDecLevel( p, pObj ); + iPlace = pObj->Value; + printf( "Lit = %d. Level = %d. Place = %d.\n", pCur->pLits[i], iLitLevel, iPlace ); + i = i; + } + } +*/ + Tas_ManAssign( p, Gia_ObjFromLit(p->pAig, pCur->pLits[0]), Level, NULL, (Gia_Obj_t *)pCur ); + piPrev = &pCur->iNext[1]; + continue; + } + // conflict detected - return the conflict clause + assert( !Tas_LitIsTrue( pObj, pCur->pLits[0] ) ); + return Tas_ManCreateFromCls( p, pCur, Level ); + } + return 0; +} + + + +/**Function************************************************************* + + Synopsis [Propagates a variable.] + + Description [Returns clause handle if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Tas_ManPropagateOne( Tas_Man_t * p, Gia_Obj_t * pVar, int Level ) +{ + int Value0, Value1, hClause; + assert( !Gia_IsComplement(pVar) ); + assert( Tas_VarIsAssigned(pVar) ); + s_Counter3++; + if ( (hClause = Tas_ManPropagateWatch( p, Level, Tas_VarToLit(p, pVar) )) ) + return hClause; + if ( Gia_ObjIsCi(pVar) ) + return 0; +/* + if ( pVar->iDiff0 == 570869 && pVar->iDiff1 == 546821 && Level == 3 ) + { + Gia_Obj_t * pFan0 = Gia_ObjFanin0(pVar); + Gia_Obj_t * pFan1 = Gia_ObjFanin1(pVar); + int s = 0; + } +*/ + assert( Gia_ObjIsAnd(pVar) ); + Value0 = Tas_VarFanin0Value(pVar); + Value1 = Tas_VarFanin1Value(pVar); + if ( Tas_VarValue(pVar) ) + { // value is 1 + if ( Value0 == 0 || Value1 == 0 ) // one is 0 + { + if ( Value0 == 0 && Value1 != 0 ) + return Tas_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), NULL ); + if ( Value0 != 0 && Value1 == 0 ) + return Tas_ManAnalyze( p, Level, pVar, Gia_ObjFanin1(pVar), NULL ); + assert( Value0 == 0 && Value1 == 0 ); + return Tas_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), Gia_ObjFanin1(pVar) ); + } + if ( Value0 == 2 ) // first is unassigned + Tas_ManAssign( p, Gia_ObjChild0(pVar), Level, pVar, NULL ); + if ( Value1 == 2 ) // first is unassigned + Tas_ManAssign( p, Gia_ObjChild1(pVar), Level, pVar, NULL ); + return 0; + } + // value is 0 + if ( Value0 == 0 || Value1 == 0 ) // one is 0 + return 0; + if ( Value0 == 1 && Value1 == 1 ) // both are 1 + return Tas_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), Gia_ObjFanin1(pVar) ); + if ( Value0 == 1 || Value1 == 1 ) // one is 1 + { + if ( Value0 == 2 ) // first is unassigned + Tas_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)), Level, pVar, Gia_ObjFanin1(pVar) ); + if ( Value1 == 2 ) // second is unassigned + Tas_ManAssign( p, Gia_Not(Gia_ObjChild1(pVar)), Level, pVar, Gia_ObjFanin0(pVar) ); + return 0; + } + assert( Tas_VarIsJust(pVar) ); + assert( !Tas_QueHasNode( &p->pJust, pVar ) ); + Tas_QuePush( &p->pJust, pVar ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Propagates a variable.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Tas_ManPropagateTwo( Tas_Man_t * p, Gia_Obj_t * pVar, int Level ) +{ + int Value0, Value1; + s_Counter4++; + assert( !Gia_IsComplement(pVar) ); + assert( Gia_ObjIsAnd(pVar) ); + assert( Tas_VarIsAssigned(pVar) ); + assert( !Tas_VarValue(pVar) ); + Value0 = Tas_VarFanin0Value(pVar); + Value1 = Tas_VarFanin1Value(pVar); + // value is 0 + if ( Value0 == 0 || Value1 == 0 ) // one is 0 + return 0; + if ( Value0 == 1 && Value1 == 1 ) // both are 1 + return Tas_ManAnalyze( p, Level, pVar, Gia_ObjFanin0(pVar), Gia_ObjFanin1(pVar) ); + assert( Value0 == 1 || Value1 == 1 ); + if ( Value0 == 2 ) // first is unassigned + Tas_ManAssign( p, Gia_Not(Gia_ObjChild0(pVar)), Level, pVar, Gia_ObjFanin1(pVar) ); + if ( Value1 == 2 ) // first is unassigned + Tas_ManAssign( p, Gia_Not(Gia_ObjChild1(pVar)), Level, pVar, Gia_ObjFanin0(pVar) ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Propagates all variables.] + + Description [Returns 1 if conflict; 0 if no conflict.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Tas_ManPropagate( Tas_Man_t * p, int Level ) +{ + int hClause; + Gia_Obj_t * pVar; + int i, k;//, nIter = 0; + while ( 1 ) + { +// nIter++; + Tas_QueForEachEntry( p->pProp, pVar, i ) + { + if ( (hClause = Tas_ManPropagateOne( p, pVar, Level )) ) + return hClause; + } + p->pProp.iHead = p->pProp.iTail; + k = p->pJust.iHead; + Tas_QueForEachEntry( p->pJust, pVar, i ) + { + if ( Tas_VarIsJust( pVar ) ) + p->pJust.pData[k++] = pVar; + else if ( (hClause = Tas_ManPropagateTwo( p, pVar, Level )) ) + return hClause; + } + if ( k == p->pJust.iTail ) + break; + p->pJust.iTail = k; + } +// printf( "%d ", nIter ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Solve the problem recursively.] + + Description [Returns learnt clause if unsat, NULL if sat or undecided.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Tas_ManSolve_rec( Tas_Man_t * p, int Level ) +{ + Tas_Que_t * pQue = &(p->pClauses); + Gia_Obj_t * pVar = NULL, * pDecVar = NULL; + int hClause, hLearn0, hLearn1; + int iPropHead, iJustHead, iJustTail; + // propagate assignments + assert( !Tas_QueIsEmpty(&p->pProp) ); + if ( (hClause = Tas_ManPropagate( p, Level )) ) + { + Tas_ManCreateCls( p, hClause ); + return hClause; + } + // check for satisfying assignment + assert( Tas_QueIsEmpty(&p->pProp) ); + if ( Tas_QueIsEmpty(&p->pJust) ) + return 0; + // quit using resource limits + p->Pars.nJustThis = Abc_MaxInt( p->Pars.nJustThis, p->pJust.iTail - p->pJust.iHead ); + if ( Tas_ManCheckLimits( p ) ) + return 0; + // remember the state before branching + iPropHead = p->pProp.iHead; + Tas_QueStore( &p->pJust, &iJustHead, &iJustTail ); + // find the decision variable + if ( p->Pars.fUseActive ) + pVar = NULL, pDecVar = Tas_ManFindActive( p ); + else if ( p->Pars.fUseHighest ) +// pVar = NULL, pDecVar = Tas_ManDecideHighestFanin( p ); + pVar = Tas_ManDecideHighest( p ); + else if ( p->Pars.fUseLowest ) + pVar = Tas_ManDecideLowest( p ); + else if ( p->Pars.fUseMaxFF ) + pVar = Tas_ManDecideMaxFF( p ); + else assert( 0 ); + // chose decision variable using fanout count + if ( pVar != NULL ) + { + assert( Tas_VarIsJust( pVar ) ); + if ( Gia_ObjRefNum(p->pAig, Gia_ObjFanin0(pVar)) > Gia_ObjRefNum(p->pAig, Gia_ObjFanin1(pVar)) ) + pDecVar = Gia_Not(Gia_ObjChild0(pVar)); + else + pDecVar = Gia_Not(Gia_ObjChild1(pVar)); +// pDecVar = Gia_NotCond( pDecVar, Gia_Regular(pDecVar)->fMark1 ^ !Gia_IsComplement(pDecVar) ); + } + // decide on first fanin + Tas_ManAssign( p, pDecVar, Level+1, NULL, NULL ); + if ( !(hLearn0 = Tas_ManSolve_rec( p, Level+1 )) ) + return 0; + if ( pQue->pData[hLearn0] != Gia_Regular(pDecVar) ) + return hLearn0; + Tas_ManCancelUntil( p, iPropHead ); + Tas_QueRestore( &p->pJust, iJustHead, iJustTail ); + // decide on second fanin + Tas_ManAssign( p, Gia_Not(pDecVar), Level+1, NULL, NULL ); + if ( !(hLearn1 = Tas_ManSolve_rec( p, Level+1 )) ) + return 0; + if ( pQue->pData[hLearn1] != Gia_Regular(pDecVar) ) + return hLearn1; + hClause = Tas_ManResolve( p, Level, hLearn0, hLearn1 ); + Tas_ManCreateCls( p, hClause ); +// Tas_ManPrintClauseNew( p, Level, hClause ); +// if ( Level > Tas_ClauseDecLevel(p, hClause) ) +// p->Pars.nBTThisNc++; + p->Pars.nBTThis++; + return hClause; +} + +/**Function************************************************************* + + Synopsis [Looking for a satisfying assignment of the node.] + + Description [Assumes that each node has flag pObj->fMark0 set to 0. + Returns 1 if unsatisfiable, 0 if satisfiable, and -1 if undecided. + The node may be complemented. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Tas_ManSolve( Tas_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pObj2 ) +{ + int i, Entry, RetValue = 0; + s_Counter2 = 0; + Vec_IntClear( p->vModel ); + if ( pObj == Gia_ManConst0(p->pAig) || pObj2 == Gia_ManConst0(p->pAig) || pObj == Gia_Not(pObj2) ) + return 1; + if ( pObj == Gia_ManConst1(p->pAig) && (pObj2 == NULL || pObj2 == Gia_ManConst1(p->pAig)) ) + return 0; + assert( !p->pProp.iHead && !p->pProp.iTail ); + assert( !p->pJust.iHead && !p->pJust.iTail ); + assert( p->pClauses.iHead == 1 && p->pClauses.iTail == 1 ); + p->Pars.nBTThis = p->Pars.nJustThis = p->Pars.nBTThisNc = 0; + Tas_ManAssign( p, pObj, 0, NULL, NULL ); + if ( pObj2 && !Tas_VarIsAssigned(Gia_Regular(pObj2)) ) + Tas_ManAssign( p, pObj2, 0, NULL, NULL ); + if ( !Tas_ManSolve_rec(p, 0) && !Tas_ManCheckLimits(p) ) + Tas_ManSaveModel( p, p->vModel ); + else + RetValue = 1; + Tas_ManCancelUntil( p, 0 ); + p->pJust.iHead = p->pJust.iTail = 0; + p->pClauses.iHead = p->pClauses.iTail = 1; + // clauses + if ( p->nClauses > 0 ) + { + p->pStore.iCur = 16; + Vec_IntForEachEntry( p->vWatchLits, Entry, i ) + p->pWatches[Entry] = 0; + Vec_IntClear( p->vWatchLits ); + p->nClauses = 0; + } + // activity + Vec_IntForEachEntry( p->vActiveVars, Entry, i ) + p->pActivity[Entry] = 0.0; + Vec_IntClear( p->vActiveVars ); + // statistics + p->Pars.nBTTotal += p->Pars.nBTThis; + p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis ); + if ( Tas_ManCheckLimits( p ) ) + RetValue = -1; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Looking for a satisfying assignment of the node.] + + Description [Assumes that each node has flag pObj->fMark0 set to 0. + Returns 1 if unsatisfiable, 0 if satisfiable, and -1 if undecided. + The node may be complemented. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Tas_ManSolveArray( Tas_Man_t * p, Vec_Ptr_t * vObjs ) +{ + Gia_Obj_t * pObj; + int i, Entry, RetValue = 0; + s_Counter2 = 0; + s_Counter3 = 0; + s_Counter4 = 0; + Vec_IntClear( p->vModel ); + Vec_PtrForEachEntry( Gia_Obj_t *, vObjs, pObj, i ) + if ( pObj == Gia_ManConst0(p->pAig) ) + return 1; + assert( !p->pProp.iHead && !p->pProp.iTail ); + assert( !p->pJust.iHead && !p->pJust.iTail ); + assert( p->pClauses.iHead == 1 && p->pClauses.iTail == 1 ); + p->Pars.nBTThis = p->Pars.nJustThis = p->Pars.nBTThisNc = 0; + Vec_PtrForEachEntry( Gia_Obj_t *, vObjs, pObj, i ) + if ( pObj != Gia_ManConst1(p->pAig) && !Tas_VarIsAssigned(Gia_Regular(pObj)) ) + Tas_ManAssign( p, pObj, 0, NULL, NULL ); + if ( !Tas_ManSolve_rec(p, 0) && !Tas_ManCheckLimits(p) ) + Tas_ManSaveModel( p, p->vModel ); + else + RetValue = 1; + Tas_ManCancelUntil( p, 0 ); + p->pJust.iHead = p->pJust.iTail = 0; + p->pClauses.iHead = p->pClauses.iTail = 1; + // clauses + if ( p->nClauses > 0 ) + { + p->pStore.iCur = 16; + Vec_IntForEachEntry( p->vWatchLits, Entry, i ) + p->pWatches[Entry] = 0; + Vec_IntClear( p->vWatchLits ); + p->nClauses = 0; + } + // activity + Vec_IntForEachEntry( p->vActiveVars, Entry, i ) + p->pActivity[Entry] = 0.0; + Vec_IntClear( p->vActiveVars ); + // statistics + p->Pars.nBTTotal += p->Pars.nBTThis; + p->Pars.nJustTotal = Abc_MaxInt( p->Pars.nJustTotal, p->Pars.nJustThis ); + if ( Tas_ManCheckLimits( p ) ) + RetValue = -1; + +// printf( "%d ", Gia_ManObjNum(p->pAig) ); +// printf( "%d ", p->Pars.nBTThis ); +// printf( "%d ", p->Pars.nJustThis ); +// printf( "%d ", s_Counter2 ); +// printf( "%d ", s_Counter3 ); +// printf( "%d ", s_Counter4 ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Prints statistics of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Tas_ManSatPrintStats( Tas_Man_t * p ) +{ + printf( "CO = %8d ", Gia_ManCoNum(p->pAig) ); + printf( "AND = %8d ", Gia_ManAndNum(p->pAig) ); + printf( "Conf = %6d ", p->Pars.nBTLimit ); + printf( "JustMax = %5d ", p->Pars.nJustLimit ); + printf( "\n" ); + printf( "Unsat calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatUnsat, p->nSatTotal? 100.0*p->nSatUnsat/p->nSatTotal :0.0, p->nSatUnsat? 1.0*p->nConfUnsat/p->nSatUnsat :0.0 ); + ABC_PRTP( "Time", p->timeSatUnsat, p->timeTotal ); + printf( "Sat calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatSat, p->nSatTotal? 100.0*p->nSatSat/p->nSatTotal :0.0, p->nSatSat? 1.0*p->nConfSat/p->nSatSat : 0.0 ); + ABC_PRTP( "Time", p->timeSatSat, p->timeTotal ); + printf( "Undef calls %6d (%6.2f %%) Ave conf = %8.1f ", + p->nSatUndec, p->nSatTotal? 100.0*p->nSatUndec/p->nSatTotal :0.0, p->nSatUndec? 1.0*p->nConfUndec/p->nSatUndec : 0.0 ); + ABC_PRTP( "Time", p->timeSatUndec, p->timeTotal ); + ABC_PRT( "Total time", p->timeTotal ); +} + +/**Function************************************************************* + + Synopsis [Procedure to test the new SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Tas_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int fVerbose ) +{ + extern void Gia_ManCollectTest( Gia_Man_t * pAig ); + extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out ); + Tas_Man_t * p; + Vec_Int_t * vCex, * vVisit, * vCexStore; + Vec_Str_t * vStatus; + Gia_Obj_t * pRoot;//, * pRootCopy; +// Gia_Man_t * pAigCopy = Gia_ManDup( pAig ), * pAigTemp; + + int i, status; + abctime clk, clkTotal = Abc_Clock(); + assert( Gia_ManRegNum(pAig) == 0 ); +// Gia_ManCollectTest( pAig ); + // prepare AIG + Gia_ManCreateRefs( pAig ); + Gia_ManCleanMark0( pAig ); + Gia_ManCleanMark1( pAig ); + Gia_ManFillValue( pAig ); // maps nodes into trail ids + Gia_ManCleanPhase( pAig ); // maps nodes into trail ids + // create logic network + p = Tas_ManAlloc( pAig, nConfs ); + p->pAig = pAig; + // create resulting data-structures + vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) ); + vCexStore = Vec_IntAlloc( 10000 ); + vVisit = Vec_IntAlloc( 100 ); + vCex = Tas_ReadModel( p ); + // solve for each output + Gia_ManForEachCo( pAig, pRoot, i ) + { +// printf( "%d=", i ); + + Vec_IntClear( vCex ); + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pRoot)) ) + { + if ( Gia_ObjFaninC0(pRoot) ) + { +// printf( "Constant 1 output of SRM!!!\n" ); + Cec_ManSatAddToStore( vCexStore, vCex, i ); // trivial counter-example + Vec_StrPush( vStatus, 0 ); + } + else + { +// printf( "Constant 0 output of SRM!!!\n" ); + Vec_StrPush( vStatus, 1 ); + } + continue; + } + clk = Abc_Clock(); +// p->Pars.fUseActive = 1; + p->Pars.fUseHighest = 1; + p->Pars.fUseLowest = 0; + status = Tas_ManSolve( p, Gia_ObjChild0(pRoot), NULL ); +// printf( "\n" ); +/* + if ( status == -1 ) + { + p->Pars.fUseHighest = 0; + p->Pars.fUseLowest = 1; + status = Tas_ManSolve( p, Gia_ObjChild0(pRoot) ); + } +*/ + Vec_StrPush( vStatus, (char)status ); + if ( status == -1 ) + { +// printf( "Unsolved %d.\n", i ); + + p->nSatUndec++; + p->nConfUndec += p->Pars.nBTThis; + Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout + p->timeSatUndec += Abc_Clock() - clk; + continue; + } + +// pRootCopy = Gia_ManCo( pAigCopy, i ); +// pRootCopy->iDiff0 = Gia_ObjId( pAigCopy, pRootCopy ); +// pRootCopy->fCompl0 = 0; + + if ( status == 1 ) + { + p->nSatUnsat++; + p->nConfUnsat += p->Pars.nBTThis; + p->timeSatUnsat += Abc_Clock() - clk; + continue; + } + p->nSatSat++; + p->nConfSat += p->Pars.nBTThis; +// Gia_SatVerifyPattern( pAig, pRoot, vCex, vVisit ); + Cec_ManSatAddToStore( vCexStore, vCex, i ); + p->timeSatSat += Abc_Clock() - clk; + +// printf( "%d ", Vec_IntSize(vCex) ); + } +// pAigCopy = Gia_ManCleanup( pAigTemp = pAigCopy ); +// Gia_ManStop( pAigTemp ); +// Gia_DumpAiger( pAigCopy, "test", 0, 2 ); +// Gia_ManStop( pAigCopy ); + + Vec_IntFree( vVisit ); + p->nSatTotal = Gia_ManPoNum(pAig); + p->timeTotal = Abc_Clock() - clkTotal; + if ( fVerbose ) + Tas_ManSatPrintStats( p ); +// printf( "RecCalls = %8d. RecClause = %8d. RecNonChro = %8d.\n", p->nRecCall, p->nRecClause, p->nRecNonChro ); + Tas_ManStop( p ); + *pvStatus = vStatus; + +// printf( "Total number of cex literals = %d. (Ave = %d)\n", +// Vec_IntSize(vCexStore)-2*p->nSatUndec-2*p->nSatSat, +// (Vec_IntSize(vCexStore)-2*p->nSatUndec-2*p->nSatSat)/p->nSatSat ); + return vCexStore; +} + +/**Function************************************************************* + + Synopsis [Packs patterns into array of simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +*************************************`**********************************/ +int Tas_StorePatternTry( Vec_Ptr_t * vInfo, Vec_Ptr_t * vPres, int iBit, int * pLits, int nLits ) +{ + unsigned * pInfo, * pPres; + int i; + for ( i = 0; i < nLits; i++ ) + { + pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i])); + pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i])); + if ( Abc_InfoHasBit( pPres, iBit ) && + Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) ) + return 0; + } + for ( i = 0; i < nLits; i++ ) + { + pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i])); + pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i])); + Abc_InfoSetBit( pPres, iBit ); + if ( Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) ) + Abc_InfoXorBit( pInfo, iBit ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Procedure to test the new SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Tas_StorePattern( Vec_Ptr_t * vSimInfo, Vec_Ptr_t * vPres, Vec_Int_t * vCex ) +{ + int k; + for ( k = 1; k < 32; k++ ) + if ( Tas_StorePatternTry( vSimInfo, vPres, k, (int *)Vec_IntArray(vCex), Vec_IntSize(vCex) ) ) + break; + return (int)(k < 32); +} + +/**Function************************************************************* + + Synopsis [Procedure to test the new SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Tas_ManSolveMiterNc2( Gia_Man_t * pAig, int nConfs, Gia_Man_t * pAigOld, Vec_Ptr_t * vOldRoots, Vec_Ptr_t * vSimInfo ) +{ + int nPatMax = 1000; + int fVerbose = 1; + extern void Gia_ManCollectTest( Gia_Man_t * pAig ); + extern void Cec_ManSatAddToStore( Vec_Int_t * vCexStore, Vec_Int_t * vCex, int Out ); + Tas_Man_t * p; + Vec_Ptr_t * vPres; + Vec_Int_t * vCex, * vVisit, * vCexStore; + Vec_Str_t * vStatus; + Gia_Obj_t * pRoot, * pOldRoot; + int i, status; + abctime clk, clkTotal = Abc_Clock(); + int Tried = 0, Stored = 0, Step = Gia_ManCoNum(pAig) / nPatMax; + assert( Gia_ManRegNum(pAig) == 0 ); +// Gia_ManCollectTest( pAig ); + // prepare AIG + Gia_ManCreateRefs( pAig ); + Gia_ManCleanMark0( pAig ); + Gia_ManCleanMark1( pAig ); + Gia_ManFillValue( pAig ); // maps nodes into trail ids + Gia_ManCleanPhase( pAig ); // maps nodes into trail ids + // create logic network + p = Tas_ManAlloc( pAig, nConfs ); + p->pAig = pAig; + // create resulting data-structures + vStatus = Vec_StrAlloc( Gia_ManPoNum(pAig) ); + vCexStore = Vec_IntAlloc( 10000 ); + vVisit = Vec_IntAlloc( 100 ); + vCex = Tas_ReadModel( p ); + // solve for each output + vPres = Vec_PtrAllocSimInfo( Gia_ManCiNum(pAig), 1 ); + Vec_PtrCleanSimInfo( vPres, 0, 1 ); + + Gia_ManForEachCo( pAig, pRoot, i ) + { + assert( !Gia_ObjIsConst0(Gia_ObjFanin0(pRoot)) ); + Vec_IntClear( vCex ); + clk = Abc_Clock(); + p->Pars.fUseHighest = 1; + p->Pars.fUseLowest = 0; + status = Tas_ManSolve( p, Gia_ObjChild0(pRoot), NULL ); + Vec_StrPush( vStatus, (char)status ); + if ( status == -1 ) + { + p->nSatUndec++; + p->nConfUndec += p->Pars.nBTThis; +// Cec_ManSatAddToStore( vCexStore, NULL, i ); // timeout + p->timeSatUndec += Abc_Clock() - clk; + + i += Step; + continue; + } + if ( status == 1 ) + { + p->nSatUnsat++; + p->nConfUnsat += p->Pars.nBTThis; + p->timeSatUnsat += Abc_Clock() - clk; + // record proved + pOldRoot = (Gia_Obj_t *)Vec_PtrEntry( vOldRoots, i ); + assert( !Gia_ObjProved( pAigOld, Gia_ObjId(pAigOld, pOldRoot) ) ); + Gia_ObjSetProved( pAigOld, Gia_ObjId(pAigOld, pOldRoot) ); + + i += Step; + continue; + } + p->nSatSat++; + p->nConfSat += p->Pars.nBTThis; +// Gia_SatVerifyPattern( pAig, pRoot, vCex, vVisit ); +// Cec_ManSatAddToStore( vCexStore, vCex, i ); + + // save pattern + Tried++; + Stored += Tas_StorePattern( vSimInfo, vPres, vCex ); + p->timeSatSat += Abc_Clock() - clk; + i += Step; + } + printf( "Tried = %d Stored = %d\n", Tried, Stored ); + Vec_IntFree( vVisit ); + p->nSatTotal = Gia_ManPoNum(pAig); + p->timeTotal = Abc_Clock() - clkTotal; + if ( fVerbose ) + Tas_ManSatPrintStats( p ); + Tas_ManStop( p ); + Vec_PtrFree( vPres ); + Vec_StrFree( vStatus ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaCTas2.c b/yosys/abc/src/aig/gia/giaCTas2.c new file mode 100644 index 00000000000..2b1d7169254 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaCTas2.c @@ -0,0 +1,208 @@ +/**CFile**************************************************************** + + FileName [giaCSat2.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Circuit-based SAT solver.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaCSat2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Tas_Par_t_ Tas_Par_t; +struct Tas_Par_t_ +{ + // conflict limits + int nBTLimit; // limit on the number of conflicts + // current parameters + int nBTThis; // number of conflicts + int nBTTotal; // total number of conflicts + // decision heuristics + int fUseHighest; // use node with the highest ID + // other parameters + int fVerbose; +}; + +typedef struct Tas_Sto_t_ Tas_Sto_t; +struct Tas_Sto_t_ +{ + int iCur; // currently used + int nSize; // allocated size + char * pBuffer; // handles of objects stored in the queue +}; + +typedef struct Tas_Que_t_ Tas_Que_t; +struct Tas_Que_t_ +{ + int iHead; // beginning of the queue + int iTail; // end of the queue + int nSize; // allocated size + int * pData; // handles of objects stored in the queue +}; + +typedef struct Tas_Var_t_ Tas_Var_t; +struct Tas_Var_t_ +{ + unsigned fTerm : 1; // terminal node + unsigned fVal : 1; // current value + unsigned fValOld : 1; // previous value + unsigned fAssign : 1; // assigned status + unsigned fJQueue : 1; // part of J-frontier + unsigned fCompl0 : 1; // complemented attribute + unsigned fCompl1 : 1; // complemented attribute + unsigned fMark0 : 1; // multi-purpose mark + unsigned fMark1 : 1; // multi-purpose mark + unsigned fPhase : 1; // polarity + unsigned Level : 22; // decision level + int Id; // unique ID of this variable + int IdAig; // original ID of this variable + int Reason0; // reason of this variable + int Reason1; // reason of this variable + int Diff0; // difference for the first fanin + int Diff1; // difference for the second fanin + int Watch0; // handle of first watch + int Watch1; // handle of second watch +}; + +typedef struct Tas_Cls_t_ Tas_Cls_t; +struct Tas_Cls_t_ +{ + int Watch0; // next clause to watch + int Watch1; // next clause to watch + int pVars[0]; // variable handles +}; + +typedef struct Tas_Man_t_ Tas_Man_t; +struct Tas_Man_t_ +{ + // user data + Gia_Man_t * pAig; // AIG manager + Tas_Par_t Pars; // parameters + // solver data + Tas_Sto_t * pVars; // variables + Tas_Sto_t * pClauses; // clauses + // state representation + Tas_Que_t pProp; // propagation queue + Tas_Que_t pJust; // justification queue + Vec_Int_t * vModel; // satisfying assignment + Vec_Ptr_t * vTemp; // temporary storage + // SAT calls statistics + int nSatUnsat; // the number of proofs + int nSatSat; // the number of failure + int nSatUndec; // the number of timeouts + int nSatTotal; // the number of calls + // conflicts + int nConfUnsat; // conflicts in unsat problems + int nConfSat; // conflicts in sat problems + int nConfUndec; // conflicts in undec problems + int nConfTotal; // total conflicts + // runtime stats + clock_t timeSatUnsat; // unsat + clock_t timeSatSat; // sat + clock_t timeSatUndec; // undecided + clock_t timeTotal; // total runtime +}; + +static inline int Tas_VarIsAssigned( Tas_Var_t * pVar ) { return pVar->fAssign; } +static inline void Tas_VarAssign( Tas_Var_t * pVar ) { assert(!pVar->fAssign); pVar->fAssign = 1; } +static inline void Tas_VarUnassign( Tas_Var_t * pVar ) { assert(pVar->fAssign); pVar->fAssign = 0; pVar->fVal = 0; } +static inline int Tas_VarValue( Tas_Var_t * pVar ) { assert(pVar->fAssign); return pVar->fVal; } +static inline void Tas_VarSetValue( Tas_Var_t * pVar, int v ) { assert(pVar->fAssign); pVar->fVal = v; } +static inline int Tas_VarIsJust( Tas_Var_t * pVar ) { return Gia_ObjIsAnd(pVar) && !Tas_VarIsAssigned(Gia_ObjFanin0(pVar)) && !Tas_VarIsAssigned(Gia_ObjFanin1(pVar)); } +static inline int Tas_VarFanin0Value( Tas_Var_t * pVar ) { return !Tas_VarIsAssigned(Gia_ObjFanin0(pVar)) ? 2 : (Tas_VarValue(Gia_ObjFanin0(pVar)) ^ Gia_ObjFaninC0(pVar)); } +static inline int Tas_VarFanin1Value( Tas_Var_t * pVar ) { return !Tas_VarIsAssigned(Gia_ObjFanin1(pVar)) ? 2 : (Tas_VarValue(Gia_ObjFanin1(pVar)) ^ Gia_ObjFaninC1(pVar)); } + +static inline int Tas_VarDecLevel( Tas_Man_t * p, Tas_Var_t * pVar ) { assert( pVar->Value != ~0 ); return Vec_IntEntry(p->vLevReas, 3*pVar->Value); } +static inline Tas_Var_t * Tas_VarReason0( Tas_Man_t * p, Tas_Var_t * pVar ) { assert( pVar->Value != ~0 ); return pVar + Vec_IntEntry(p->vLevReas, 3*pVar->Value+1); } +static inline Tas_Var_t * Tas_VarReason1( Tas_Man_t * p, Tas_Var_t * pVar ) { assert( pVar->Value != ~0 ); return pVar + Vec_IntEntry(p->vLevReas, 3*pVar->Value+2); } +static inline int Tas_ClauseDecLevel( Tas_Man_t * p, int hClause ) { return Tas_VarDecLevel( p, p->pClauses.pData[hClause] ); } + +static inline Tas_Var_t * Tas_ManVar( Tas_Man_t * p, int h ) { return (Tas_Var_t *)(p->pVars->pBuffer + h); } +static inline Tas_Cls_t * Tas_ManClause( Tas_Man_t * p, int h ) { return (Tas_Cls_t *)(p->pClauses->pBuffer + h); } + +#define Tas_ClaForEachVar( p, pClause, pVar, i ) \ + for ( pVar = Tas_ManVar(p, pClause->pVars[(i=0)]); pClause->pVars[i]; pVar = (Tas_Var_t *)(((char *)pVar + pClause->pVars[++i])) ) + +#define Tas_QueForEachVar( p, pQue, pVar, i ) \ + for ( pVar = Tas_ManVar(p, pQue->pVars[(i=pQue->iHead)]); i < pQue->iTail; pVar = Tas_ManVar(p, pQue->pVars[i++]) ) + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Tas_Var_t * Tas_ManCreateVar( Tas_Man_t * p ) +{ + Tas_Var_t * pVar; + if ( p->pVars->iCur + sizeof(Tas_Var_t) > p->pVars->nSize ) + { + p->pVars->nSize *= 2; + p->pVars->pData = ABC_REALLOC( char, p->pVars->pData, p->pVars->nSize ); + } + pVar = p->pVars->pData + p->pVars->iCur; + p->pVars->iCur += sizeof(Tas_Var_t); + memset( pVar, 0, sizeof(Tas_Var_t) ); + pVar->Id = pVar - ((Tas_Var_t *)p->pVars->pData); + return pVar; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Tas_Var_t * Tas_ManObj2Var( Tas_Man_t * p, Gia_Obj_t * pObj ) +{ + Tas_Var_t * pVar; + assert( !Gia_ObjIsComplement(pObj) ); + if ( pObj->Value == 0 ) + { + pVar = Tas_ManCreateVar( p ); + pVar-> + + } + return Tas_ManVar( p, pObj->Value ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaCex.c b/yosys/abc/src/aig/gia/giaCex.c new file mode 100644 index 00000000000..d124187309e --- /dev/null +++ b/yosys/abc/src/aig/gia/giaCex.c @@ -0,0 +1,616 @@ +/**CFile**************************************************************** + + FileName [giaAbs.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Counter-example-guided abstraction refinement.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaAbs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +#include "sat/bsat/satSolver.h" +#include "sat/cnf/cnf.h" +#include "sat/bmc/bmc.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Resimulates the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManVerifyCex( Gia_Man_t * pAig, Abc_Cex_t * p, int fDualOut ) +{ + Gia_Obj_t * pObj, * pObjRi, * pObjRo; + int RetValue, i, k, iBit = 0; + Gia_ManCleanMark0(pAig); + Gia_ManForEachRo( pAig, pObj, i ) + pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++); + for ( i = 0; i <= p->iFrame; i++ ) + { + Gia_ManForEachPi( pAig, pObj, k ) + pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++); + Gia_ManForEachAnd( pAig, pObj, k ) + pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & + (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)); + Gia_ManForEachCo( pAig, pObj, k ) + pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); + if ( i == p->iFrame ) + break; + Gia_ManForEachRiRo( pAig, pObjRi, pObjRo, k ) + { + pObjRo->fMark0 = pObjRi->fMark0; + } + } + assert( iBit == p->nBits ); + if ( fDualOut ) + RetValue = Gia_ManPo(pAig, 2*p->iPo)->fMark0 ^ Gia_ManPo(pAig, 2*p->iPo+1)->fMark0; + else + RetValue = Gia_ManPo(pAig, p->iPo)->fMark0; + Gia_ManCleanMark0(pAig); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Resimulates the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManFindFailedPoCex( Gia_Man_t * pAig, Abc_Cex_t * p, int nOutputs ) +{ + Gia_Obj_t * pObj, * pObjRi, * pObjRo; + int RetValue, i, k, iBit = 0; + assert( Gia_ManPiNum(pAig) == p->nPis ); + Gia_ManCleanMark0(pAig); + Gia_ManForEachRo( pAig, pObj, i ) + pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++); + iBit = p->nRegs; + for ( i = 0; i <= p->iFrame; i++ ) + { + Gia_ManForEachPi( pAig, pObj, k ) + pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++); + Gia_ManForEachAnd( pAig, pObj, k ) + pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & + (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)); + Gia_ManForEachCo( pAig, pObj, k ) + pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); + Gia_ManForEachRiRo( pAig, pObjRi, pObjRo, k ) + pObjRo->fMark0 = pObjRi->fMark0; + } + assert( iBit == p->nBits ); + // figure out the number of failed output + RetValue = -1; +// for ( i = Gia_ManPoNum(pAig) - 1; i >= nOutputs; i-- ) + for ( i = nOutputs; i < Gia_ManPoNum(pAig); i++ ) + { + if ( Gia_ManPo(pAig, i)->fMark0 ) + { + RetValue = i; + break; + } + } + Gia_ManCleanMark0(pAig); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Determines the failed PO when its exact frame is not known.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSetFailedPoCex( Gia_Man_t * pAig, Abc_Cex_t * p ) +{ + Gia_Obj_t * pObj, * pObjRi, * pObjRo; + int i, k, iBit = 0; + assert( Gia_ManPiNum(pAig) == p->nPis ); + Gia_ManCleanMark0(pAig); + p->iPo = -1; +// Gia_ManForEachRo( pAig, pObj, i ) +// pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++); + iBit = p->nRegs; + for ( i = 0; i <= p->iFrame; i++ ) + { + Gia_ManForEachPi( pAig, pObj, k ) + pObj->fMark0 = Abc_InfoHasBit(p->pData, iBit++); + Gia_ManForEachAnd( pAig, pObj, k ) + pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & + (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)); + Gia_ManForEachCo( pAig, pObj, k ) + pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); + Gia_ManForEachRiRo( pAig, pObjRi, pObjRo, k ) + pObjRo->fMark0 = pObjRi->fMark0; + // check the POs + Gia_ManForEachPo( pAig, pObj, k ) + { + if ( !pObj->fMark0 ) + continue; + p->iPo = k; + p->iFrame = i; + p->nBits = iBit; + break; + } + } + Gia_ManCleanMark0(pAig); + return p->iPo; +} + + +/**Function************************************************************* + + Synopsis [Starts the process of returning values for internal nodes.] + + Description [Should be called when pCex is available, before probing + any object for its value using Gia_ManCounterExampleValueLookup().] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCounterExampleValueStart( Gia_Man_t * pGia, Abc_Cex_t * pCex ) +{ + Gia_Obj_t * pObj, * pObjRi, * pObjRo; + int Val0, Val1, nObjs, i, k, iBit = 0; + assert( Gia_ManRegNum(pGia) > 0 ); // makes sense only for sequential AIGs + assert( pGia->pData2 == NULL ); // if this fail, there may be a memory leak + // allocate memory to store simulation bits for internal nodes + pGia->pData2 = ABC_CALLOC( unsigned, Abc_BitWordNum( (pCex->iFrame + 1) * Gia_ManObjNum(pGia) ) ); + // the register values in the counter-example should be zero + Gia_ManForEachRo( pGia, pObj, k ) + assert( Abc_InfoHasBit(pCex->pData, iBit) == 0 ), iBit++; + // iterate through the timeframes + nObjs = Gia_ManObjNum(pGia); + for ( i = 0; i <= pCex->iFrame; i++ ) + { + // no need to set constant-0 node + // set primary inputs according to the counter-example + Gia_ManForEachPi( pGia, pObj, k ) + if ( Abc_InfoHasBit(pCex->pData, iBit++) ) + Abc_InfoSetBit( (unsigned *)pGia->pData2, nObjs * i + Gia_ObjId(pGia, pObj) ); + // compute values for each node + Gia_ManForEachAnd( pGia, pObj, k ) + { + Val0 = Abc_InfoHasBit( (unsigned *)pGia->pData2, nObjs * i + Gia_ObjFaninId0p(pGia, pObj) ); + Val1 = Abc_InfoHasBit( (unsigned *)pGia->pData2, nObjs * i + Gia_ObjFaninId1p(pGia, pObj) ); + if ( (Val0 ^ Gia_ObjFaninC0(pObj)) & (Val1 ^ Gia_ObjFaninC1(pObj)) ) + Abc_InfoSetBit( (unsigned *)pGia->pData2, nObjs * i + Gia_ObjId(pGia, pObj) ); + } + // derive values for combinational outputs + Gia_ManForEachCo( pGia, pObj, k ) + { + Val0 = Abc_InfoHasBit( (unsigned *)pGia->pData2, nObjs * i + Gia_ObjFaninId0p(pGia, pObj) ); + if ( Val0 ^ Gia_ObjFaninC0(pObj) ) + Abc_InfoSetBit( (unsigned *)pGia->pData2, nObjs * i + Gia_ObjId(pGia, pObj) ); + } + if ( i == pCex->iFrame ) + continue; + // transfer values to the register output of the next frame + Gia_ManForEachRiRo( pGia, pObjRi, pObjRo, k ) + if ( Abc_InfoHasBit( (unsigned *)pGia->pData2, nObjs * i + Gia_ObjId(pGia, pObjRi) ) ) + Abc_InfoSetBit( (unsigned *)pGia->pData2, nObjs * (i+1) + Gia_ObjId(pGia, pObjRo) ); + } + assert( iBit == pCex->nBits ); + // check that the counter-example is correct, that is, the corresponding output is asserted + assert( Abc_InfoHasBit( (unsigned *)pGia->pData2, nObjs * pCex->iFrame + Gia_ObjId(pGia, Gia_ManCo(pGia, pCex->iPo)) ) ); +} + +/**Function************************************************************* + + Synopsis [Stops the process of returning values for internal nodes.] + + Description [Should be called when probing is no longer needed] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCounterExampleValueStop( Gia_Man_t * pGia ) +{ + assert( pGia->pData2 != NULL ); // if this fail, we try to call this procedure more than once + ABC_FREE( pGia->pData2 ); + pGia->pData2 = NULL; +} + +/**Function************************************************************* + + Synopsis [Returns the value of the given object in the given timeframe.] + + Description [Should be called to probe the value of an object with + the given ID (iFrame is a 0-based number of a time frame - should not + exceed the number of timeframes in the original counter-example).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCounterExampleValueLookup( Gia_Man_t * pGia, int Id, int iFrame ) +{ + assert( Id >= 0 && Id < Gia_ManObjNum(pGia) ); + return Abc_InfoHasBit( (unsigned *)pGia->pData2, Gia_ManObjNum(pGia) * iFrame + Id ); +} + +/**Function************************************************************* + + Synopsis [Procedure to test the above code.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCounterExampleValueTest( Gia_Man_t * pGia, Abc_Cex_t * pCex ) +{ + Gia_Obj_t * pObj = Gia_ManObj( pGia, Gia_ManObjNum(pGia)/2 ); + int iFrame = Abc_MaxInt( 0, pCex->iFrame - 1 ); + printf( "\nUsing counter-example, which asserts output %d in frame %d.\n", pCex->iPo, pCex->iFrame ); + Gia_ManCounterExampleValueStart( pGia, pCex ); + printf( "Value of object %d in frame %d is %d.\n", Gia_ObjId(pGia, pObj), iFrame, + Gia_ManCounterExampleValueLookup(pGia, Gia_ObjId(pGia, pObj), iFrame) ); + Gia_ManCounterExampleValueStop( pGia ); +} + + +/**Function************************************************************* + + Synopsis [Returns CEX containing PI+CS values for each timeframe.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Gia_ManCexExtendToIncludeCurrentStates( Gia_Man_t * p, Abc_Cex_t * pCex ) +{ + Abc_Cex_t * pNew; + Gia_Obj_t * pObj, * pObjRo, * pObjRi; + int i, k, iBit = 0; + assert( pCex->nRegs > 0 ); + // start the counter-example + pNew = Abc_CexAlloc( 0, Gia_ManCiNum(p), pCex->iFrame + 1 ); + pNew->iFrame = pCex->iFrame; + pNew->iPo = pCex->iPo; + // set const0 + Gia_ManConst0(p)->fMark0 = 0; + // set init state + Gia_ManForEachRi( p, pObjRi, k ) + pObjRi->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++); + assert( iBit == pCex->nRegs ); + for ( i = 0; i <= pCex->iFrame; i++ ) + { + Gia_ManForEachPi( p, pObj, k ) + pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++); + Gia_ManForEachRiRo( p, pObjRi, pObjRo, k ) + pObjRo->fMark0 = pObjRi->fMark0; + Gia_ManForEachCi( p, pObj, k ) + if ( pObj->fMark0 ) + Abc_InfoSetBit( pNew->pData, pNew->nPis * i + k ); + Gia_ManForEachAnd( p, pObj, k ) + pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)); + Gia_ManForEachCo( p, pObj, k ) + pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); + } + assert( iBit == pCex->nBits ); + assert( Gia_ManPo(p, pCex->iPo)->fMark0 == 1 ); + Gia_ManCleanMark0(p); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Returns CEX containing all object valuess for each timeframe.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Gia_ManCexExtendToIncludeAllObjects( Gia_Man_t * p, Abc_Cex_t * pCex ) +{ + Abc_Cex_t * pNew; + Gia_Obj_t * pObj, * pObjRo, * pObjRi; + int i, k, iBit = 0; + assert( pCex->nRegs > 0 ); + // start the counter-example + pNew = Abc_CexAlloc( 0, Gia_ManObjNum(p), pCex->iFrame + 1 ); + pNew->iFrame = pCex->iFrame; + pNew->iPo = pCex->iPo; + // set const0 + Gia_ManConst0(p)->fMark0 = 0; + // set init state + Gia_ManForEachRi( p, pObjRi, k ) + pObjRi->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++); + assert( iBit == pCex->nRegs ); + for ( i = 0; i <= pCex->iFrame; i++ ) + { + Gia_ManForEachPi( p, pObj, k ) + pObj->fMark0 = Abc_InfoHasBit(pCex->pData, iBit++); + Gia_ManForEachRiRo( p, pObjRi, pObjRo, k ) + pObjRo->fMark0 = pObjRi->fMark0; + Gia_ManForEachObj( p, pObj, k ) + if ( pObj->fMark0 ) + Abc_InfoSetBit( pNew->pData, pNew->nPis * i + k ); + Gia_ManForEachAnd( p, pObj, k ) + pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)); + Gia_ManForEachCo( p, pObj, k ) + pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); + } + assert( iBit == pCex->nBits ); + assert( Gia_ManPo(p, pCex->iPo)->fMark0 == 1 ); + Gia_ManCleanMark0(p); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManFramesForCexMin( Gia_Man_t * p, int nFrames ) +{ + Gia_Man_t * pFrames, * pTemp; + Gia_Obj_t * pObj; int i, f; + assert( Gia_ManPoNum(p) == 1 ); + pFrames = Gia_ManStart( Gia_ManObjNum(p) ); + pFrames->pName = Abc_UtilStrsav( p->pName ); + pFrames->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pFrames ); + Gia_ManConst0(p)->Value = 0; + for ( f = 0; f < nFrames; f++ ) + { + Gia_ManForEachRo( p, pObj, i ) + pObj->Value = f ? Gia_ObjRoToRi( p, pObj )->Value : 0; + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pFrames ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pFrames, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachRi( p, pObj, i ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + } + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pFrames, Gia_ObjFanin0Copy(pObj) ); + pFrames = Gia_ManCleanup( pTemp = pFrames ); + //printf( "Before cleanup = %d nodes. After cleanup = %d nodes.\n", + // Gia_ManAndNum(pTemp), Gia_ManAndNum(pFrames) ); + Gia_ManStop( pTemp ); + return pFrames; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManMinCex( Gia_Man_t * p, Abc_Cex_t * pCex ) +{ + abctime clk = Abc_Clock(); + int n, i, iFirstVar, iLit, status, Counter = 0;//, Id; + Vec_Int_t * vLits; + sat_solver * pSat; + Cnf_Dat_t * pCnf; + int nFinal, * pFinal; + Abc_Cex_t * pCexCare; + Gia_Man_t * pFrames; + + // CEX minimization + clk = Abc_Clock(); + pCexCare = Bmc_CexCareMinimizeAig( p, Gia_ManPiNum(p), pCex, 1, 1, 1 ); + for ( i = pCexCare->nRegs; i < pCexCare->nBits; i++ ) + Counter += Abc_InfoHasBit(pCexCare->pData, i); + Abc_CexFree( pCexCare ); + printf( "Care bits = %d. ", Counter ); + Abc_PrintTime( 1, "CEX minimization", Abc_Clock() - clk ); + + // SAT instance + clk = Abc_Clock(); + pFrames = Gia_ManFramesForCexMin( p, pCex->iFrame + 1 ); + pCnf = (Cnf_Dat_t*)Mf_ManGenerateCnf( pFrames, 8, 0, 0, 0, 0 ); + iFirstVar = pCnf->nVars - (pCex->iFrame+1) * pCex->nPis; + pSat = (sat_solver*)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + iLit = Abc_Var2Lit( 1, 1 ); + status = sat_solver_addclause( pSat, &iLit, &iLit + 1 ); + assert( status ); + // create literals + vLits = Vec_IntAlloc( 100 ); + for ( i = pCex->nRegs; i < pCex->nBits; i++ ) + Vec_IntPush( vLits, Abc_Var2Lit(iFirstVar + i - pCex->nRegs, !Abc_InfoHasBit(pCex->pData, i)) ); + Abc_PrintTime( 1, "SAT solver", Abc_Clock() - clk ); + + for ( n = 0; n < 2; n++ ) + { + if ( n ) Vec_IntReverseOrder( vLits ); + + // SAT-based minimization + clk = Abc_Clock(); + status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits), 0, 0, 0, 0 ); + nFinal = sat_solver_final( pSat, &pFinal ); + printf( "Status %d. Selected %d assumptions out of %d. ", status, nFinal, Vec_IntSize(vLits) ); + Abc_PrintTime( 1, "Analyze_final", Abc_Clock() - clk ); + + // SAT-based minimization + clk = Abc_Clock(); + nFinal = sat_solver_minimize_assumptions( pSat, Vec_IntArray(vLits), Vec_IntSize(vLits), 0 ); + printf( "Status %d. Selected %d assumptions out of %d. ", status, nFinal, Vec_IntSize(vLits) ); + Abc_PrintTime( 1, "LEXUNSAT", Abc_Clock() - clk ); + } + + // cleanup + Vec_IntFree( vLits ); + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + Gia_ManStop( pFrames ); +} + + +Abc_Cex_t * Bmc_CexCareDeriveCex( Abc_Cex_t * pCex, int iFirstVar, int * pLits, int nLits ) +{ + Abc_Cex_t * pCexMin; int i; + pCexMin = Abc_CexAlloc( pCex->nRegs, pCex->nPis, pCex->iFrame + 1 ); + pCexMin->iPo = pCex->iPo; + pCexMin->iFrame = pCex->iFrame; + for ( i = 0; i < nLits; i++ ) + { + int PiNum = Abc_Lit2Var(pLits[i]) - iFirstVar; + assert( PiNum >= 0 && PiNum < pCex->nBits - pCex->nRegs ); + Abc_InfoSetBit( pCexMin->pData, pCexMin->nRegs + PiNum ); + } + return pCexMin; +} +Abc_Cex_t * Bmc_CexCareSatBasedMinimizeAig( Gia_Man_t * p, Abc_Cex_t * pCex, int fHighEffort, int fVerbose ) +{ + abctime clk = Abc_Clock(); + int n, i, iFirstVar, iLit, status; + Vec_Int_t * vLits = NULL, * vTemp; + sat_solver * pSat; + Cnf_Dat_t * pCnf; + int nFinal, * pFinal; + Abc_Cex_t * pCexBest = NULL; + int CountBest = 0; + Gia_Man_t * pFrames; + + // CEX minimization + clk = Abc_Clock(); + pCexBest = Bmc_CexCareMinimizeAig( p, Gia_ManPiNum(p), pCex, 1, 1, fVerbose ); + for ( i = pCexBest->nRegs; i < pCexBest->nBits; i++ ) + CountBest += Abc_InfoHasBit(pCexBest->pData, i); + if ( fVerbose ) + { + printf( "Care bits = %d. ", CountBest ); + Abc_PrintTime( 1, "Non-SAT-based CEX minimization", Abc_Clock() - clk ); + } + + // SAT instance + clk = Abc_Clock(); + pFrames = Gia_ManFramesForCexMin( p, pCex->iFrame + 1 ); + pCnf = (Cnf_Dat_t*)Mf_ManGenerateCnf( pFrames, 8, 0, 0, 0, 0 ); + iFirstVar = pCnf->nVars - (pCex->iFrame+1) * pCex->nPis; + pSat = (sat_solver*)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + iLit = Abc_Var2Lit( 1, 1 ); + status = sat_solver_addclause( pSat, &iLit, &iLit + 1 ); + assert( status ); + // create literals + vTemp = Vec_IntAlloc( 100 ); + for ( i = pCex->nRegs; i < pCex->nBits; i++ ) + Vec_IntPush( vTemp, Abc_Var2Lit(iFirstVar + i - pCex->nRegs, !Abc_InfoHasBit(pCex->pData, i)) ); + if ( fVerbose ) + Abc_PrintTime( 1, "Constructing SAT solver", Abc_Clock() - clk ); + + for ( n = 0; n < 2; n++ ) + { + Vec_IntFreeP( &vLits ); + + vLits = Vec_IntDup( vTemp ); + if ( n ) Vec_IntReverseOrder( vLits ); + + // SAT-based minimization + clk = Abc_Clock(); + status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits), 0, 0, 0, 0 ); + nFinal = sat_solver_final( pSat, &pFinal ); + if ( fVerbose ) + { + printf( "Status %s Selected %5d assumptions out of %5d. ", status == l_False ? "OK ":"BUG", nFinal, Vec_IntSize(vLits) ); + Abc_PrintTime( 1, "Analyze_final", Abc_Clock() - clk ); + } + if ( CountBest > nFinal ) + { + CountBest = nFinal; + ABC_FREE( pCexBest ); + pCexBest = Bmc_CexCareDeriveCex( pCex, iFirstVar, pFinal, nFinal ); + } + if ( !fHighEffort ) + continue; + + // SAT-based minimization + clk = Abc_Clock(); + nFinal = sat_solver_minimize_assumptions( pSat, Vec_IntArray(vLits), Vec_IntSize(vLits), 0 ); + if ( fVerbose ) + { + printf( "Status %s Selected %5d assumptions out of %5d. ", status == l_False ? "OK ":"BUG", nFinal, Vec_IntSize(vLits) ); + Abc_PrintTime( 1, "LEXUNSAT ", Abc_Clock() - clk ); + } + if ( CountBest > nFinal ) + { + CountBest = nFinal; + ABC_FREE( pCexBest ); + pCexBest = Bmc_CexCareDeriveCex( pCex, iFirstVar, Vec_IntArray(vLits), nFinal ); + } + } + if ( fVerbose ) + { + printf( "Final : " ); + Bmc_CexPrint( pCexBest, pCexBest->nPis, 0 ); + } + // cleanup + Vec_IntFreeP( &vLits ); + Vec_IntFreeP( &vTemp ); + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + Gia_ManStop( pFrames ); + return pCexBest; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaClp.c b/yosys/abc/src/aig/gia/giaClp.c new file mode 100644 index 00000000000..dba81637ee2 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaClp.c @@ -0,0 +1,533 @@ +/**CFile**************************************************************** + + FileName [giaClp.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Collapsing AIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +#ifdef ABC_USE_CUDD +#include "bdd/extrab/extraBdd.h" +#include "bdd/dsd/dsd.h" +#endif + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#ifdef ABC_USE_CUDD + +extern int Abc_ConvertZddToSop( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase ); +extern int Abc_CountZddCubes( DdManager * dd, DdNode * zCover ); +extern int Abc_NtkDeriveFlatGiaSop( Gia_Man_t * pGia, int * gFanins, char * pSop ); +extern int Gia_ManFactorNode( Gia_Man_t * p, char * pSop, Vec_Int_t * vLeaves ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManRebuildIsop( DdManager * dd, DdNode * bLocal, Gia_Man_t * pNew, Vec_Int_t * vFanins, Vec_Str_t * vSop, Vec_Str_t * vCube ) +{ + char * pSop; + DdNode * bCover, * zCover, * zCover0, * zCover1; + int nFanins = Vec_IntSize(vFanins); + int fPhase, nCubes, nCubes0, nCubes1; + + // get the ZDD of the negative polarity + bCover = Cudd_zddIsop( dd, Cudd_Not(bLocal), Cudd_Not(bLocal), &zCover0 ); + Cudd_Ref( zCover0 ); + Cudd_Ref( bCover ); + Cudd_RecursiveDeref( dd, bCover ); + nCubes0 = Abc_CountZddCubes( dd, zCover0 ); + + // get the ZDD of the positive polarity + bCover = Cudd_zddIsop( dd, bLocal, bLocal, &zCover1 ); + Cudd_Ref( zCover1 ); + Cudd_Ref( bCover ); + Cudd_RecursiveDeref( dd, bCover ); + nCubes1 = Abc_CountZddCubes( dd, zCover1 ); + + // compare the number of cubes + if ( nCubes1 <= nCubes0 ) + { // use positive polarity + nCubes = nCubes1; + zCover = zCover1; + Cudd_RecursiveDerefZdd( dd, zCover0 ); + fPhase = 1; + } + else + { // use negative polarity + nCubes = nCubes0; + zCover = zCover0; + Cudd_RecursiveDerefZdd( dd, zCover1 ); + fPhase = 0; + } + if ( nCubes > 1000 ) + { + Cudd_RecursiveDerefZdd( dd, zCover ); + return -1; + } + + // allocate memory for the cover + Vec_StrGrow( vSop, (nFanins + 3) * nCubes + 1 ); + pSop = Vec_StrArray( vSop ); + pSop[(nFanins + 3) * nCubes] = 0; + // create the SOP + Vec_StrFill( vCube, nFanins, '-' ); + Vec_StrPush( vCube, '\0' ); + Abc_ConvertZddToSop( dd, zCover, pSop, nFanins, vCube, fPhase ); + Cudd_RecursiveDerefZdd( dd, zCover ); + + // perform factoring +// return Abc_NtkDeriveFlatGiaSop( pNew, Vec_IntArray(vFanins), pSop ); + return Gia_ManFactorNode( pNew, pSop, vFanins ); +} +int Gia_ManRebuildNode( Dsd_Manager_t * pManDsd, Dsd_Node_t * pNodeDsd, Gia_Man_t * pNew, DdManager * ddNew, Vec_Int_t * vFanins, Vec_Str_t * vSop, Vec_Str_t * vCube ) +{ + DdManager * ddDsd = Dsd_ManagerReadDd( pManDsd ); + DdNode * bLocal, * bTemp; + Dsd_Node_t * pFaninDsd; + Dsd_Type_t Type; + int i, nDecs, iLit = -1; + + // add the fanins + Type = Dsd_NodeReadType( pNodeDsd ); + nDecs = Dsd_NodeReadDecsNum( pNodeDsd ); + assert( nDecs > 1 ); + Vec_IntClear( vFanins ); + for ( i = 0; i < nDecs; i++ ) + { + pFaninDsd = Dsd_NodeReadDec( pNodeDsd, i ); + iLit = Dsd_NodeReadMark( Dsd_Regular(pFaninDsd) ); + iLit = Abc_LitNotCond( iLit, Dsd_IsComplement(pFaninDsd) ); + assert( Type == DSD_NODE_OR || !Dsd_IsComplement(pFaninDsd) ); + Vec_IntPush( vFanins, iLit ); + } + + // create the local function depending on the type of the node + switch ( Type ) + { + case DSD_NODE_CONST1: + { + iLit = 1; + break; + } + case DSD_NODE_OR: + { + iLit = 0; + for ( i = 0; i < nDecs; i++ ) + iLit = Gia_ManHashOr( pNew, iLit, Vec_IntEntry(vFanins, i) ); + break; + } + case DSD_NODE_EXOR: + { + iLit = 0; + for ( i = 0; i < nDecs; i++ ) + iLit = Gia_ManHashXor( pNew, iLit, Vec_IntEntry(vFanins, i) ); + break; + } + case DSD_NODE_PRIME: + { + bLocal = Dsd_TreeGetPrimeFunction( ddDsd, pNodeDsd ); Cudd_Ref( bLocal ); + bLocal = Extra_TransferLevelByLevel( ddDsd, ddNew, bTemp = bLocal ); Cudd_Ref( bLocal ); + Cudd_RecursiveDeref( ddDsd, bTemp ); + // bLocal is now in the new BDD manager + iLit = Gia_ManRebuildIsop( ddNew, bLocal, pNew, vFanins, vSop, vCube ); + Cudd_RecursiveDeref( ddNew, bLocal ); + break; + } + default: + { + assert( 0 ); + break; + } + } + Dsd_NodeSetMark( pNodeDsd, iLit ); + return iLit; +} +Gia_Man_t * Gia_ManRebuild( Gia_Man_t * p, Dsd_Manager_t * pManDsd, DdManager * ddNew ) +{ + Gia_Man_t * pNew; + Dsd_Node_t ** ppNodesDsd; + Dsd_Node_t * pNodeDsd; + int i, nNodesDsd, iLit = -1; + Vec_Str_t * vSop, * vCube; + Vec_Int_t * vFanins; + + vFanins = Vec_IntAlloc( 1000 ); + vSop = Vec_StrAlloc( 10000 ); + vCube = Vec_StrAlloc( 1000 ); + + pNew = Gia_ManStart( 2*Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + + // save the CI nodes in the DSD nodes + Dsd_NodeSetMark( Dsd_ManagerReadConst1(pManDsd), 1 ); + for ( i = 0; i < Gia_ManCiNum(p); i++ ) + { + pNodeDsd = Dsd_ManagerReadInput( pManDsd, i ); + Dsd_NodeSetMark( pNodeDsd, Gia_ManAppendCi( pNew ) ); + } + + // collect DSD nodes in DFS order (leaves and const1 are not collected) + ppNodesDsd = Dsd_TreeCollectNodesDfs( pManDsd, &nNodesDsd ); + for ( i = 0; i < nNodesDsd; i++ ) + { + iLit = Gia_ManRebuildNode( pManDsd, ppNodesDsd[i], pNew, ddNew, vFanins, vSop, vCube ); + if ( iLit == -1 ) + break; + } + ABC_FREE( ppNodesDsd ); + Vec_IntFree( vFanins ); + Vec_StrFree( vSop ); + Vec_StrFree( vCube ); + if ( iLit == -1 ) + { + Gia_ManStop( pNew ); + return Gia_ManDup(p); + } + + // set the pointers to the CO drivers + for ( i = 0; i < Gia_ManCoNum(p); i++ ) + { + pNodeDsd = Dsd_ManagerReadRoot( pManDsd, i ); + iLit = Dsd_NodeReadMark( Dsd_Regular(pNodeDsd) ); + iLit = Abc_LitNotCond( iLit, Dsd_IsComplement(pNodeDsd) ); + Gia_ManAppendCo( pNew, iLit ); + } + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCollapseDeref( DdManager * dd, Vec_Ptr_t * vFuncs ) +{ + DdNode * bFunc; int i; + Vec_PtrForEachEntry( DdNode *, vFuncs, bFunc, i ) + if ( bFunc ) + Cudd_RecursiveDeref( dd, bFunc ); + Vec_PtrFree( vFuncs ); +} +void Gia_ObjCollapseDeref( Gia_Man_t * p, DdManager * dd, Vec_Ptr_t * vFuncs, int Id ) +{ + if ( Gia_ObjRefDecId(p, Id) ) + return; + Cudd_RecursiveDeref( dd, (DdNode *)Vec_PtrEntry(vFuncs, Id) ); + Vec_PtrWriteEntry( vFuncs, Id, NULL ); +} +Vec_Ptr_t * Gia_ManCollapse( Gia_Man_t * p, DdManager * dd, int nBddLimit, int fVerbose ) +{ + Vec_Ptr_t * vFuncs; + DdNode * bFunc0, * bFunc1, * bFunc; + Gia_Obj_t * pObj; + int i, Id; + Gia_ManCreateRefs( p ); + // assign constant node + vFuncs = Vec_PtrStart( Gia_ManObjNum(p) ); + if ( Gia_ObjRefNumId(p, 0) > 0 ) + Vec_PtrWriteEntry( vFuncs, 0, Cudd_ReadLogicZero(dd) ), Cudd_Ref(Cudd_ReadLogicZero(dd)); + // assign elementary variables + Gia_ManForEachCiId( p, Id, i ) + if ( Gia_ObjRefNumId(p, Id) > 0 ) + Vec_PtrWriteEntry( vFuncs, Id, Cudd_bddIthVar(dd,i) ), Cudd_Ref(Cudd_bddIthVar(dd,i)); + // create BDD for AND nodes + Gia_ManForEachAnd( p, pObj, i ) + { + bFunc0 = Cudd_NotCond( (DdNode *)Vec_PtrEntry(vFuncs, Gia_ObjFaninId0(pObj, i)), Gia_ObjFaninC0(pObj) ); + bFunc1 = Cudd_NotCond( (DdNode *)Vec_PtrEntry(vFuncs, Gia_ObjFaninId1(pObj, i)), Gia_ObjFaninC1(pObj) ); + bFunc = Cudd_bddAndLimit( dd, bFunc0, bFunc1, nBddLimit ); + if ( bFunc == NULL ) + { + Gia_ManCollapseDeref( dd, vFuncs ); + return NULL; + } + Cudd_Ref( bFunc ); + Vec_PtrWriteEntry( vFuncs, i, bFunc ); + Gia_ObjCollapseDeref( p, dd, vFuncs, Gia_ObjFaninId0(pObj, i) ); + Gia_ObjCollapseDeref( p, dd, vFuncs, Gia_ObjFaninId1(pObj, i) ); + } + // create BDD for outputs + Gia_ManForEachCoId( p, Id, i ) + { + pObj = Gia_ManCo( p, i ); + bFunc0 = Cudd_NotCond( (DdNode *)Vec_PtrEntry(vFuncs, Gia_ObjFaninId0(pObj, Id)), Gia_ObjFaninC0(pObj) ); + Vec_PtrWriteEntry( vFuncs, Id, bFunc0 ); Cudd_Ref( bFunc0 ); + Gia_ObjCollapseDeref( p, dd, vFuncs, Gia_ObjFaninId0(pObj, Id) ); + } + assert( Vec_PtrSize(vFuncs) == Vec_PtrCountZero(vFuncs) + Gia_ManCoNum(p) ); + // compact + Gia_ManForEachCoId( p, Id, i ) + Vec_PtrWriteEntry( vFuncs, i, Vec_PtrEntry(vFuncs, Id) ); + Vec_PtrShrink( vFuncs, Gia_ManCoNum(p) ); + return vFuncs; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManCollapseTest( Gia_Man_t * p, int fVerbose ) +{ + Gia_Man_t * pNew; + DdManager * dd, * ddNew; + Dsd_Manager_t * pManDsd; + Vec_Ptr_t * vFuncs; + // derive global BDDs + dd = Cudd_Init( Gia_ManCiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + vFuncs = Gia_ManCollapse( p, dd, 10000, 0 ); + Cudd_AutodynDisable( dd ); + if ( vFuncs == NULL ) + { + Extra_StopManager( dd ); + return Gia_ManDup(p); + } + // start ISOP manager + ddNew = Cudd_Init( Gia_ManCiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_zddVarsFromBddVars( ddNew, 2 ); +// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 ); + if ( fVerbose ) + printf( "Ins = %d. Outs = %d. Shared BDD nodes = %d. Peak live nodes = %d. Peak nodes = %d.\n", + Gia_ManCiNum(p), Gia_ManCoNum(p), + Cudd_SharingSize( (DdNode **)Vec_PtrArray(vFuncs), Vec_PtrSize(vFuncs) ), + Cudd_ReadPeakLiveNodeCount(dd), (int)Cudd_ReadNodeCount(dd) ); + // perform decomposition + pManDsd = Dsd_ManagerStart( dd, Gia_ManCiNum(p), 0 ); + Dsd_Decompose( pManDsd, (DdNode **)Vec_PtrArray(vFuncs), Vec_PtrSize(vFuncs) ); + if ( fVerbose ) + { + Vec_Ptr_t * vNamesCi = Gia_GetFakeNames( Gia_ManCiNum(p), 0 ); + Vec_Ptr_t * vNamesCo = Gia_GetFakeNames( Gia_ManCoNum(p), 1 ); + char ** ppNamesCi = (char **)Vec_PtrArray( vNamesCi ); + char ** ppNamesCo = (char **)Vec_PtrArray( vNamesCo ); + Dsd_TreePrint( stdout, pManDsd, ppNamesCi, ppNamesCo, 0, -1, 0 ); + Vec_PtrFreeFree( vNamesCi ); + Vec_PtrFreeFree( vNamesCo ); + } + + pNew = Gia_ManRebuild( p, pManDsd, ddNew ); + Dsd_ManagerStop( pManDsd ); + // return manager + Gia_ManCollapseDeref( dd, vFuncs ); + Extra_StopManager( dd ); + Extra_StopManager( ddNew ); + return pNew; +} +void Gia_ManCollapseTestTest( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + pNew = Gia_ManCollapseTest( p, 0 ); + Gia_ManPrintStats( p, NULL ); + Gia_ManPrintStats( pNew, NULL ); + Gia_ManStop( pNew ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintDsdOne( Dsd_Manager_t * pManDsd, int Output, int OffSet ) +{ + Vec_Str_t * vStr = Vec_StrAlloc( 100 ); + Dsd_TreePrint4( vStr, pManDsd, Output ); + for ( int i = 0; i < OffSet; i++ ) + printf( " " ); + printf( "Supp %2d nDsd %2d %s\n", Dsd_TreeSuppSize(pManDsd, Output), Dsd_TreeNonDsdMax(pManDsd, Output), Vec_StrArray(vStr) ); + Vec_StrFree( vStr ); + fflush( stdout ); +} +void Gia_ManPrintDsd( Dsd_Manager_t * pManDsd, int Output, int nOutputs, int OffSet ) +{ + if ( Output == -1 ) + { + for ( int i = 0; i < nOutputs; i++ ) + Gia_ManPrintDsdOne( pManDsd, i, OffSet ); + } + else + { + assert( Output >= 0 && Output < nOutputs ); + Gia_ManPrintDsdOne( pManDsd, Output, OffSet ); + } +} + +void Gia_ManCheckDsd( Gia_Man_t * p, int OffSet, int fVerbose ) +{ + DdManager * dd; + Dsd_Manager_t * pManDsd; + Vec_Ptr_t * vFuncs; + dd = Cudd_Init( Gia_ManCiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + vFuncs = Gia_ManCollapse( p, dd, 10000, 0 ); + Cudd_AutodynDisable( dd ); + if ( vFuncs == NULL ) + { + Extra_StopManager( dd ); + return; + } + pManDsd = Dsd_ManagerStart( dd, Gia_ManCiNum(p), 0 ); + if ( pManDsd == NULL ) + { + Gia_ManCollapseDeref( dd, vFuncs ); + Cudd_Quit( dd ); + return; + } + Dsd_Decompose( pManDsd, (DdNode **)Vec_PtrArray(vFuncs), Vec_PtrSize(vFuncs) ); + + if ( fVerbose ) + { + Vec_Ptr_t * vNamesCi = Gia_GetFakeNames( Gia_ManCiNum(p), 0 ); + Vec_Ptr_t * vNamesCo = Gia_GetFakeNames( Gia_ManCoNum(p), 1 ); + char ** ppNamesCi = (char **)Vec_PtrArray( vNamesCi ); + char ** ppNamesCo = (char **)Vec_PtrArray( vNamesCo ); + Dsd_TreePrint( stdout, pManDsd, ppNamesCi, ppNamesCo, 0, -1, OffSet ); + Vec_PtrFreeFree( vNamesCi ); + Vec_PtrFreeFree( vNamesCo ); + } + else + Gia_ManPrintDsd( pManDsd, 0, Vec_PtrSize(vFuncs), 0 ); + + Dsd_ManagerStop( pManDsd ); + Gia_ManCollapseDeref( dd, vFuncs ); + Extra_StopManager( dd ); +} + +Vec_Ptr_t * Gia_ManRecurDsdCof( DdManager * dd, Vec_Ptr_t * vFuncs, int iVar ) +{ + Vec_Ptr_t * vNew = Vec_PtrAlloc( 2 * Vec_PtrSize(vFuncs) ); DdNode * bFunc; int i; + Vec_PtrForEachEntry( DdNode *, vFuncs, bFunc, i ) { + DdNode * bCof0 = Cudd_Cofactor( dd, bFunc, Cudd_Not(Cudd_bddIthVar(dd, iVar)) ); Cudd_Ref( bCof0 ); + DdNode * bCof1 = Cudd_Cofactor( dd, bFunc, Cudd_bddIthVar(dd, iVar) ); Cudd_Ref( bCof1 ); + Vec_PtrPush( vNew, bCof0 ); + Vec_PtrPush( vNew, bCof1 ); + } + return vNew; +} +void Gia_ManRecurDsd( Gia_Man_t * p, int fVerbose ) +{ + DdManager * dd; + Dsd_Manager_t * pManDsd; + Vec_Ptr_t * vFuncs, * vAux; + dd = Cudd_Init( Gia_ManCiNum(p), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); + vFuncs = Gia_ManCollapse( p, dd, 10000, 0 ); + Cudd_AutodynDisable( dd ); + if ( vFuncs == NULL ) + { + Extra_StopManager( dd ); + return; + } + pManDsd = Dsd_ManagerStart( dd, Gia_ManCiNum(p), 0 ); + if ( pManDsd == NULL ) + { + Gia_ManCollapseDeref( dd, vFuncs ); + Cudd_Quit( dd ); + return; + } + Dsd_Decompose( pManDsd, (DdNode **)Vec_PtrArray(vFuncs), Vec_PtrSize(vFuncs) ); + + printf( "Function:\n" ); + Gia_ManPrintDsd( pManDsd, 0, Vec_PtrSize(vFuncs), 0 ); + + for ( int i = 0; i < 5 && Dsd_TreeNonDsdMax(pManDsd, -1) > 0; i++ ) + { + int v, iBestV = -1, DsdMin = ABC_INFINITY, SuppMin = ABC_INFINITY; + for ( v = 0; v < Gia_ManCiNum(p); v++ ) + { + Vec_Ptr_t * vTemp = Gia_ManRecurDsdCof( dd, vFuncs, v ); + Dsd_Decompose( pManDsd, (DdNode **)Vec_PtrArray(vTemp), Vec_PtrSize(vTemp) ); + int DsdCur = Dsd_TreeNonDsdMax( pManDsd, -1 ); + int SuppCur = Dsd_TreeSuppSize( pManDsd, -1 ); + if ( DsdMin > DsdCur || (DsdMin == DsdCur && SuppMin > SuppCur) ) + DsdMin = DsdCur, SuppMin = SuppCur, iBestV = v; + Gia_ManCollapseDeref( dd, vTemp ); + } + assert( iBestV >= 0 ); + vFuncs = Gia_ManRecurDsdCof( dd, vAux = vFuncs, iBestV ); + Gia_ManCollapseDeref( dd, vAux ); + printf( "Cofactoring variable %c:\n", (int)(iBestV >= 26 ? 'A' - 26 : 'a') + iBestV ); + Dsd_Decompose( pManDsd, (DdNode **)Vec_PtrArray(vFuncs), Vec_PtrSize(vFuncs) ); + Gia_ManPrintDsd( pManDsd, -1, Vec_PtrSize(vFuncs), (i+1)*2 ); + } + + Dsd_ManagerStop( pManDsd ); + Gia_ManCollapseDeref( dd, vFuncs ); + Extra_StopManager( dd ); +} + +#else + +Gia_Man_t * Gia_ManCollapseTest( Gia_Man_t * p, int fVerbose ) +{ + return NULL; +} + +void Gia_ManCheckDsd( Gia_Man_t * p, int OffSet, int fVerbose ) +{ +} + +void Gia_ManRecurDsd( Gia_Man_t * p, int fVerbose ) +{ +} + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaCof.c b/yosys/abc/src/aig/gia/giaCof.c new file mode 100644 index 00000000000..d89e2586715 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaCof.c @@ -0,0 +1,1093 @@ +/**CFile**************************************************************** + + FileName [giaCof.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Cofactor estimation procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaCof.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Cof_Fan_t_ Cof_Fan_t; +struct Cof_Fan_t_ +{ + unsigned iFan : 31; // ID of the fanin/fanout + unsigned fCompl : 1; // complemented attribute +}; + +typedef struct Cof_Obj_t_ Cof_Obj_t; +struct Cof_Obj_t_ +{ + unsigned fTerm : 1; // terminal node (CI/CO) + unsigned fPhase : 1; // value under 000 pattern + unsigned fMark0 : 1; // first user-controlled mark + unsigned fMark1 : 1; // second user-controlled mark + unsigned nFanins : 4; // the number of fanins + unsigned nFanouts : 24; // total number of fanouts + unsigned nFanoutsM; // total number of MUX ctrl fanouts + unsigned Value; // application specific data + int Id; // ID of the node + int iNext; // next one in the linked list + int iLit; // literal of the node after rehashing + Cof_Fan_t Fanios[0]; // the array of fanins/fanouts +}; + +typedef struct Cof_Man_t_ Cof_Man_t; +struct Cof_Man_t_ +{ + Gia_Man_t * pGia; // the original AIG manager + Vec_Int_t * vCis; // the vector of CIs (PIs + LOs) + Vec_Int_t * vCos; // the vector of COs (POs + LIs) + int nObjs; // the number of objects + int nNodes; // the number of nodes + int nTravIds; // traversal ID of the network + int * pObjData; // the logic network defined for the AIG + int nObjData; // the size of array to store the logic network + int * pLevels; // the linked lists of levels + int nLevels; // the max number of logic levels +}; + +static inline unsigned Gia_ObjHandle( Gia_Obj_t * pObj ) { return pObj->Value; } + +static inline int Cof_ObjLevel( Cof_Man_t * p, Cof_Obj_t * pObj ) { return Gia_ObjLevel(p->pGia, Gia_ManObj(p->pGia,pObj->Id)); } + +static inline unsigned Cof_ObjHandle( Cof_Man_t * p, Cof_Obj_t * pObj ) { return (unsigned)(((int *)pObj) - p->pObjData); } +static inline unsigned Cof_ObjHandleDiff( Cof_Obj_t * pObj, Cof_Obj_t * pFanin ) { return (unsigned)(((int *)pObj) - ((int *)pFanin)); } + +static inline int Cof_ObjIsTerm( Cof_Obj_t * pObj ) { return pObj->fTerm; } +static inline int Cof_ObjIsCi( Cof_Obj_t * pObj ) { return pObj->fTerm && pObj->nFanins == 0; } +static inline int Cof_ObjIsCo( Cof_Obj_t * pObj ) { return pObj->fTerm && pObj->nFanins == 1; } +static inline int Cof_ObjIsNode( Cof_Obj_t * pObj ) { return!pObj->fTerm && pObj->nFanins > 0; } +static inline int Cof_ObjIsConst0( Cof_Obj_t * pObj ) { return!pObj->fTerm && pObj->nFanins == 0; } + +static inline int Cof_ObjFaninNum( Cof_Obj_t * pObj ) { return pObj->nFanins; } +static inline int Cof_ObjFanoutNum( Cof_Obj_t * pObj ) { return pObj->nFanouts; } +static inline int Cof_ObjSize( Cof_Obj_t * pObj ) { return sizeof(Cof_Obj_t) / 4 + pObj->nFanins + pObj->nFanouts; } + +static inline Cof_Obj_t * Cof_ManObj( Cof_Man_t * p, unsigned iHandle ) { return (Cof_Obj_t *)(p->pObjData + iHandle); } +static inline Cof_Obj_t * Cof_ObjFanin( Cof_Obj_t * pObj, int i ) { return (Cof_Obj_t *)(((int *)pObj) - pObj->Fanios[i].iFan); } +static inline Cof_Obj_t * Cof_ObjFanout( Cof_Obj_t * pObj, int i ) { return (Cof_Obj_t *)(((int *)pObj) + pObj->Fanios[pObj->nFanins+i].iFan); } + +static inline int Cof_ManObjNum( Cof_Man_t * p ) { return p->nObjs; } +static inline int Cof_ManNodeNum( Cof_Man_t * p ) { return p->nNodes; } + +static inline void Cof_ManResetTravId( Cof_Man_t * p ) { extern void Cof_ManCleanValue( Cof_Man_t * p ); Cof_ManCleanValue( p ); p->nTravIds = 1; } +static inline void Cof_ManIncrementTravId( Cof_Man_t * p ) { p->nTravIds++; } +static inline void Cof_ObjSetTravId( Cof_Obj_t * pObj, int TravId ) { pObj->Value = TravId; } +static inline void Cof_ObjSetTravIdCurrent( Cof_Man_t * p, Cof_Obj_t * pObj ) { pObj->Value = p->nTravIds; } +static inline void Cof_ObjSetTravIdPrevious( Cof_Man_t * p, Cof_Obj_t * pObj ) { pObj->Value = p->nTravIds - 1; } +static inline int Cof_ObjIsTravIdCurrent( Cof_Man_t * p, Cof_Obj_t * pObj ) { return ((int)pObj->Value == p->nTravIds); } +static inline int Cof_ObjIsTravIdPrevious( Cof_Man_t * p, Cof_Obj_t * pObj ) { return ((int)pObj->Value == p->nTravIds - 1); } + +#define Cof_ManForEachObj( p, pObj, i ) \ + for ( i = 0; (i < p->nObjData) && (pObj = Cof_ManObj(p,i)); i += Cof_ObjSize(pObj) ) +#define Cof_ManForEachNode( p, pObj, i ) \ + for ( i = 0; (i < p->nObjData) && (pObj = Cof_ManObj(p,i)); i += Cof_ObjSize(pObj) ) if ( Cof_ObjIsTerm(pObj) ) {} else +#define Cof_ObjForEachFanin( pObj, pNext, i ) \ + for ( i = 0; (i < (int)pObj->nFanins) && (pNext = Cof_ObjFanin(pObj,i)); i++ ) +#define Cof_ObjForEachFanout( pObj, pNext, i ) \ + for ( i = 0; (i < (int)pObj->nFanouts) && (pNext = Cof_ObjFanout(pObj,i)); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates logic network isomorphic to the given AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cof_Man_t * Cof_ManCreateLogicSimple( Gia_Man_t * pGia ) +{ + Cof_Man_t * p; + Cof_Obj_t * pObjLog, * pFanLog; + Gia_Obj_t * pObj; + int * pMuxRefs; + int i, iHandle = 0; + p = ABC_CALLOC( Cof_Man_t, 1 ); + p->pGia = pGia; + p->vCis = Vec_IntAlloc( Gia_ManCiNum(pGia) ); + p->vCos = Vec_IntAlloc( Gia_ManCoNum(pGia) ); + p->nObjData = (sizeof(Cof_Obj_t) / 4) * Gia_ManObjNum(pGia) + 4 * Gia_ManAndNum(pGia) + 2 * Gia_ManCoNum(pGia); + p->pObjData = ABC_CALLOC( int, p->nObjData ); + ABC_FREE( pGia->pRefs ); + Gia_ManCreateRefs( pGia ); + Gia_ManForEachObj( pGia, pObj, i ) + { + pObj->Value = iHandle; + pObjLog = Cof_ManObj( p, iHandle ); + pObjLog->nFanins = 0; + pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj ); + pObjLog->Id = i; + pObjLog->Value = 0; + if ( Gia_ObjIsAnd(pObj) ) + { + pFanLog = Cof_ManObj( p, Gia_ObjHandle(Gia_ObjFanin0(pObj)) ); + pFanLog->Fanios[pFanLog->nFanins + pFanLog->Value++].iFan = + pObjLog->Fanios[pObjLog->nFanins].iFan = Cof_ObjHandleDiff( pObjLog, pFanLog ); + pObjLog->Fanios[pObjLog->nFanins++].fCompl = Gia_ObjFaninC0(pObj); + + pFanLog = Cof_ManObj( p, Gia_ObjHandle(Gia_ObjFanin1(pObj)) ); + pFanLog->Fanios[pFanLog->nFanins + pFanLog->Value++].iFan = + pObjLog->Fanios[pObjLog->nFanins].iFan = Cof_ObjHandleDiff( pObjLog, pFanLog ); + pObjLog->Fanios[pObjLog->nFanins++].fCompl = Gia_ObjFaninC1(pObj); + p->nNodes++; + } + else if ( Gia_ObjIsCo(pObj) ) + { + pFanLog = Cof_ManObj( p, Gia_ObjHandle(Gia_ObjFanin0(pObj)) ); + pFanLog->Fanios[pFanLog->nFanins + pFanLog->Value++].iFan = + pObjLog->Fanios[pObjLog->nFanins].iFan = Cof_ObjHandleDiff( pObjLog, pFanLog ); + pObjLog->Fanios[pObjLog->nFanins++].fCompl = Gia_ObjFaninC0(pObj); + + pObjLog->fTerm = 1; + Vec_IntPush( p->vCos, iHandle ); + } + else if ( Gia_ObjIsCi(pObj) ) + { + pObjLog->fTerm = 1; + Vec_IntPush( p->vCis, iHandle ); + } + iHandle += Cof_ObjSize( pObjLog ); + p->nObjs++; + } + assert( iHandle == p->nObjData ); + pMuxRefs = Gia_ManCreateMuxRefs( pGia ); + Gia_ManForEachObj( pGia, pObj, i ) + { + pObjLog = Cof_ManObj( p, Gia_ObjHandle(pObj) ); + assert( pObjLog->nFanouts == pObjLog->Value ); + pObjLog->nFanoutsM = pMuxRefs[i]; + } + ABC_FREE( pMuxRefs ); + return p; +} + +/**Function************************************************************* + + Synopsis [Creates logic network isomorphic to the given AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cof_ManStop( Cof_Man_t * p ) +{ + Vec_IntFree( p->vCis ); + Vec_IntFree( p->vCos ); + ABC_FREE( p->pObjData ); + ABC_FREE( p->pLevels ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [Collects support nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cof_ManTfoSize_rec( Cof_Man_t * p, Cof_Obj_t * pObj ) +{ + Cof_Obj_t * pNext; + unsigned i, Counter = 0; + if ( Cof_ObjIsTravIdCurrent(p, pObj) ) + return 0; + Cof_ObjSetTravIdCurrent(p, pObj); + if ( Cof_ObjIsCo(pObj) ) + return 0; + assert( Cof_ObjIsCi(pObj) || Cof_ObjIsNode(pObj) ); + Cof_ObjForEachFanout( pObj, pNext, i ) + Counter += Cof_ManTfoSize_rec( p, pNext ); + return 1 + Counter; +} + +/**Function************************************************************* + + Synopsis [Collects support nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cof_ManTfoSize( Cof_Man_t * p, Cof_Obj_t ** ppObjs, int nObjs ) +{ + int i, Counter = 0; + Cof_ManIncrementTravId( p ); + for ( i = 0; i < nObjs; i++ ) + Counter += Cof_ManTfoSize_rec( p, ppObjs[i] ) - 1; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Collects support nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cof_ManTfiSize_rec( Cof_Man_t * p, Cof_Obj_t * pObj ) +{ + Cof_Obj_t * pNext; + unsigned i, Counter = 0; + if ( Cof_ObjIsTravIdCurrent(p, pObj) ) + return 0; + Cof_ObjSetTravIdCurrent(p, pObj); + if ( Cof_ObjIsCi(pObj) ) + return 0; + assert( Cof_ObjIsNode(pObj) ); + Cof_ObjForEachFanin( pObj, pNext, i ) + Counter += Cof_ManTfiSize_rec( p, pNext ); + return 1 + Counter; +} + +/**Function************************************************************* + + Synopsis [Collects support nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cof_ManTfiSize( Cof_Man_t * p, Cof_Obj_t ** ppObjs, int nObjs ) +{ + int i, Counter = 0; + Cof_ManIncrementTravId( p ); + for ( i = 0; i < nObjs; i++ ) + if ( Cof_ObjIsCo(ppObjs[i]) ) + Counter += Cof_ManTfiSize_rec( p, Cof_ObjFanin(ppObjs[i],0) ); + else + Counter += Cof_ManTfiSize_rec( p, ppObjs[i] ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Collects support nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cof_ManSuppSize_rec( Cof_Man_t * p, Cof_Obj_t * pObj ) +{ + Cof_Obj_t * pNext; + unsigned i, Counter = 0; + if ( Cof_ObjIsTravIdCurrent(p, pObj) ) + return 0; + Cof_ObjSetTravIdCurrent(p, pObj); + if ( Cof_ObjIsCi(pObj) ) + return 1; + assert( Cof_ObjIsNode(pObj) ); + Cof_ObjForEachFanin( pObj, pNext, i ) + Counter += Cof_ManSuppSize_rec( p, pNext ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Collects support nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cof_ManSuppSize( Cof_Man_t * p, Cof_Obj_t ** ppObjs, int nObjs ) +{ + int i, Counter = 0; + Cof_ManIncrementTravId( p ); + for ( i = 0; i < nObjs; i++ ) + if ( Cof_ObjIsCo(ppObjs[i]) ) + Counter += Cof_ManSuppSize_rec( p, Cof_ObjFanin(ppObjs[i],0) ); + else + Counter += Cof_ManSuppSize_rec( p, ppObjs[i] ); + return Counter; +} + + +/**Function************************************************************* + + Synopsis [Cleans the value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cof_ManCleanValue( Cof_Man_t * p ) +{ + Cof_Obj_t * pObj; + int i; + Cof_ManForEachObj( p, pObj, i ) + pObj->Value = 0; +} + +/**Function************************************************************* + + Synopsis [Returns sorted array of node handles with largest fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cof_ManInsertEntry_rec( Vec_Ptr_t * vNodes, Cof_Obj_t * pNode, int nNodeMax ) +{ + Cof_Obj_t * pLast; + if ( Vec_PtrSize(vNodes) == 0 ) + { + Vec_PtrPush(vNodes, pNode); + return; + } + pLast = (Cof_Obj_t *)Vec_PtrPop(vNodes); + if ( Cof_ObjFanoutNum(pLast) < Cof_ObjFanoutNum(pNode) ) + { + Cof_ManInsertEntry_rec( vNodes, pNode, nNodeMax ); + if ( Vec_PtrSize(vNodes) < nNodeMax ) + Vec_PtrPush( vNodes, pLast ); + } + else + { + Vec_PtrPush( vNodes, pLast ); + if ( Vec_PtrSize(vNodes) < nNodeMax ) + Vec_PtrPush( vNodes, pNode ); + } +} + +/**Function************************************************************* + + Synopsis [Returns sorted array of node handles with largest fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Cof_ManCollectHighFanout( Cof_Man_t * p, int nNodes ) +{ + Vec_Ptr_t * vNodes; + Cof_Obj_t * pObj; + int i; + vNodes = Vec_PtrAlloc( nNodes ); + Cof_ManForEachObj( p, pObj, i ) + if ( Cof_ObjIsCi(pObj) || Cof_ObjIsNode(pObj) ) + Cof_ManInsertEntry_rec( vNodes, pObj, nNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Returns sorted array of node handles with largest fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cof_ManCountRemoved( Cof_Man_t * p, Cof_Obj_t * pRoot, int fConst1 ) +{ + Gia_Obj_t * pNextGia; + Cof_Obj_t * pTemp, * pNext, * pFanin0, * pFanin1; + int Counter = 0, LevelStart, LevelNext; + int i, k, iHandle, iLit0, iLit1, iNextNew; + // restart the trav ids + Cof_ManIncrementTravId( p ); + Cof_ObjSetTravIdCurrent( p, pRoot ); + // add the node to the queue + LevelStart = Cof_ObjLevel(p, pRoot); + assert( p->pLevels[LevelStart] == 0 ); + pRoot->iNext = 0; + p->pLevels[LevelStart] = Cof_ObjHandle( p, pRoot ); + // set the new literal + pRoot->iLit = Abc_Var2Lit( 0, fConst1 ); + // process nodes in the levelized order + for ( i = LevelStart; i < p->nLevels; i++ ) + { + for ( iHandle = p->pLevels[i]; + iHandle && (pTemp = Cof_ManObj(p, iHandle)); + iHandle = pTemp->iNext ) + { + assert( pTemp->Id != Abc_Lit2Var(pTemp->iLit) ); + Cof_ObjForEachFanout( pTemp, pNext, k ) + { + if ( Cof_ObjIsCo(pNext) ) + continue; + if ( Cof_ObjIsTravIdCurrent(p, pNext) ) + continue; + pFanin0 = Cof_ObjFanin( pNext, 0 ); + pFanin1 = Cof_ObjFanin( pNext, 1 ); + assert( pFanin0 == pTemp || pFanin1 == pTemp ); + pNextGia = Gia_ManObj( p->pGia, pNext->Id ); + if ( Cof_ObjIsTravIdCurrent(p, pFanin0) ) + iLit0 = Abc_LitNotCond( pFanin0->iLit, Gia_ObjFaninC0(pNextGia) ); + else + iLit0 = Gia_ObjFaninLit0( pNextGia, pNext->Id ); + if ( Cof_ObjIsTravIdCurrent(p, pFanin1) ) + iLit1 = Abc_LitNotCond( pFanin1->iLit, Gia_ObjFaninC1(pNextGia) ); + else + iLit1 = Gia_ObjFaninLit1( pNextGia, pNext->Id ); + iNextNew = Gia_ManHashAndTry( p->pGia, iLit0, iLit1 ); + if ( iNextNew == -1 ) + continue; + Cof_ObjSetTravIdCurrent(p, pNext); + // set the new literal + pNext->iLit = iNextNew; + // add it to be processed + LevelNext = Cof_ObjLevel( p, pNext ); + assert( LevelNext > i && LevelNext < p->nLevels ); + pNext->iNext = p->pLevels[LevelNext]; + p->pLevels[LevelNext] = Cof_ObjHandle( p, pNext ); + Counter++; + } + } + p->pLevels[i] = 0; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns sorted array of node handles with largest fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cof_ManPrintHighFanoutOne( Cof_Man_t * p, Cof_Obj_t * pObj ) +{ + printf( "%7d : ", pObj->Id ); + printf( "i/o/c =%2d %5d %5d ", Cof_ObjFaninNum(pObj), Cof_ObjFanoutNum(pObj), 2*pObj->nFanoutsM ); + printf( "l =%4d ", Cof_ObjLevel(p, pObj) ); + printf( "s =%5d ", Cof_ManSuppSize(p, &pObj, 1) ); + printf( "TFI =%7d ", Cof_ManTfiSize(p, &pObj, 1) ); + printf( "TFO =%7d ", Cof_ManTfoSize(p, &pObj, 1) ); + printf( "C0 =%6d ", Cof_ManCountRemoved(p, pObj, 0) ); + printf( "C1 =%6d", Cof_ManCountRemoved(p, pObj, 1) ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Returns sorted array of node handles with largest fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cof_ManPrintHighFanout( Cof_Man_t * p, int nNodes ) +{ + Vec_Ptr_t * vNodes; + Cof_Obj_t * pObj; + int i; + vNodes = Cof_ManCollectHighFanout( p, nNodes ); + Vec_PtrForEachEntry( Cof_Obj_t *, vNodes, pObj, i ) + Cof_ManPrintHighFanoutOne( p, pObj ); + Vec_PtrFree( vNodes ); +} + + +/**Function************************************************************* + + Synopsis [Compute MFFC size of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cof_NodeDeref_rec( Cof_Obj_t * pNode ) +{ + if ( pNode->nFanins == 0 ) + return 0; + if ( --pNode->nFanouts > 0 ) + return 0; + return 1 + Cof_NodeDeref_rec( Cof_ObjFanin(pNode, 0) ) + + Cof_NodeDeref_rec( Cof_ObjFanin(pNode, 1) ); +} +int Cof_NodeRef_rec( Cof_Obj_t * pNode ) +{ + if ( pNode->nFanins == 0 ) + return 0; + if ( pNode->nFanouts++ > 0 ) + return 0; + return 1 + Cof_NodeRef_rec( Cof_ObjFanin(pNode, 0) ) + + Cof_NodeRef_rec( Cof_ObjFanin(pNode, 1) ); +} +static inline int Cof_ObjMffcSize( Cof_Obj_t * pNode ) +{ + int Count1, Count2, nFanout; + nFanout = pNode->nFanouts; + pNode->nFanouts = 1; + Count1 = Cof_NodeDeref_rec( pNode ); + Count2 = Cof_NodeRef_rec( pNode ); + pNode->nFanouts = nFanout; + assert( Count1 == Count2 ); + return Count1; +} + +/**Function************************************************************* + + Synopsis [Prints the distribution of fanins/fanouts in the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cof_ManPrintFanio( Cof_Man_t * p ) +{ + char Buffer[100]; + Cof_Obj_t * pNode; + Vec_Int_t * vFanins, * vFanouts, * vMffcs; + int nFanins, nFanouts, nMffcs, nFaninsMax, nFanoutsMax, nMffcsMax, nFaninsAll, nFanoutsAll, nMffcsAll; + int i, k, nSizeMax, nMffcNodes = 0; + + // determine the largest fanin and fanout + nFaninsMax = nFanoutsMax = nMffcsMax = 0; + nFaninsAll = nFanoutsAll = nMffcsAll = 0; + Cof_ManForEachNode( p, pNode, i ) + { + if ( i == 0 ) continue; + nFanins = Cof_ObjFaninNum(pNode); + nFanouts = Cof_ObjFanoutNum(pNode); + nMffcs = pNode->nFanouts > 1 ? Cof_ObjMffcSize(pNode) : 0; + nFaninsAll += nFanins; + nFanoutsAll += nFanouts; + nMffcsAll += nMffcs; + nFaninsMax = Abc_MaxInt( nFaninsMax, nFanins ); + nFanoutsMax = Abc_MaxInt( nFanoutsMax, nFanouts ); + nMffcsMax = Abc_MaxInt( nMffcsMax, nMffcs ); + } + + // allocate storage for fanin/fanout numbers + nSizeMax = Abc_MaxInt( 10 * (Abc_Base10Log(nFaninsMax) + 1), 10 * (Abc_Base10Log(nFanoutsMax) + 1) ); + nSizeMax = Abc_MaxInt( 10 * (Abc_Base10Log(nMffcsMax) + 1), nSizeMax ); + vFanins = Vec_IntStart( nSizeMax ); + vFanouts = Vec_IntStart( nSizeMax ); + vMffcs = Vec_IntStart( nSizeMax ); + + // count the number of fanins and fanouts + Cof_ManForEachNode( p, pNode, i ) + { + if ( i == 0 ) continue; + nFanins = Cof_ObjFaninNum(pNode); + nFanouts = Cof_ObjFanoutNum(pNode); + nMffcs = pNode->nFanouts > 1 ? Cof_ObjMffcSize(pNode) : 0; + + if ( nFanins < 10 ) + Vec_IntAddToEntry( vFanins, nFanins, 1 ); + else if ( nFanins < 100 ) + Vec_IntAddToEntry( vFanins, 10 + nFanins/10, 1 ); + else if ( nFanins < 1000 ) + Vec_IntAddToEntry( vFanins, 20 + nFanins/100, 1 ); + else if ( nFanins < 10000 ) + Vec_IntAddToEntry( vFanins, 30 + nFanins/1000, 1 ); + else if ( nFanins < 100000 ) + Vec_IntAddToEntry( vFanins, 40 + nFanins/10000, 1 ); + else if ( nFanins < 1000000 ) + Vec_IntAddToEntry( vFanins, 50 + nFanins/100000, 1 ); + else if ( nFanins < 10000000 ) + Vec_IntAddToEntry( vFanins, 60 + nFanins/1000000, 1 ); + + if ( nFanouts < 10 ) + Vec_IntAddToEntry( vFanouts, nFanouts, 1 ); + else if ( nFanouts < 100 ) + Vec_IntAddToEntry( vFanouts, 10 + nFanouts/10, 1 ); + else if ( nFanouts < 1000 ) + Vec_IntAddToEntry( vFanouts, 20 + nFanouts/100, 1 ); + else if ( nFanouts < 10000 ) + Vec_IntAddToEntry( vFanouts, 30 + nFanouts/1000, 1 ); + else if ( nFanouts < 100000 ) + Vec_IntAddToEntry( vFanouts, 40 + nFanouts/10000, 1 ); + else if ( nFanouts < 1000000 ) + Vec_IntAddToEntry( vFanouts, 50 + nFanouts/100000, 1 ); + else if ( nFanouts < 10000000 ) + Vec_IntAddToEntry( vFanouts, 60 + nFanouts/1000000, 1 ); + + if ( nMffcs == 0 ) + continue; + nMffcNodes++; + + if ( nMffcs < 10 ) + Vec_IntAddToEntry( vMffcs, nMffcs, 1 ); + else if ( nMffcs < 100 ) + Vec_IntAddToEntry( vMffcs, 10 + nMffcs/10, 1 ); + else if ( nMffcs < 1000 ) + Vec_IntAddToEntry( vMffcs, 20 + nMffcs/100, 1 ); + else if ( nMffcs < 10000 ) + Vec_IntAddToEntry( vMffcs, 30 + nMffcs/1000, 1 ); + else if ( nMffcs < 100000 ) + Vec_IntAddToEntry( vMffcs, 40 + nMffcs/10000, 1 ); + else if ( nMffcs < 1000000 ) + Vec_IntAddToEntry( vMffcs, 50 + nMffcs/100000, 1 ); + else if ( nMffcs < 10000000 ) + Vec_IntAddToEntry( vMffcs, 60 + nMffcs/1000000, 1 ); + } + + printf( "The distribution of fanins, fanouts. and MFFCs in the network:\n" ); + printf( " Number Nodes with fanin Nodes with fanout Nodes with MFFC\n" ); + + for ( k = 0; k < nSizeMax; k++ ) + { + if ( vFanins->pArray[k] == 0 && vFanouts->pArray[k] == 0 && vMffcs->pArray[k] == 0 ) + continue; + if ( k < 10 ) + printf( "%15d : ", k ); + else + { + sprintf( Buffer, "%d - %d", (int)pow((double)10, k/10) * (k%10), (int)pow((double)10, k/10) * (k%10+1) - 1 ); + printf( "%15s : ", Buffer ); + } + if ( vFanins->pArray[k] == 0 ) + printf( " " ); + else + printf( "%11d ", vFanins->pArray[k] ); + printf( " " ); + if ( vFanouts->pArray[k] == 0 ) + printf( " " ); + else + printf( "%12d ", vFanouts->pArray[k] ); + printf( " " ); + if ( vMffcs->pArray[k] == 0 ) + printf( " " ); + else + printf( " %12d ", vMffcs->pArray[k] ); + printf( "\n" ); + } + Vec_IntFree( vFanins ); + Vec_IntFree( vFanouts ); + Vec_IntFree( vMffcs ); + + printf( "Fanins: Max = %d. Ave = %.2f. Fanouts: Max = %d. Ave = %.2f. MFFCs: Max = %d. Ave = %.2f.\n", + nFaninsMax, 1.0*nFaninsAll /Cof_ManNodeNum(p), + nFanoutsMax, 1.0*nFanoutsAll/Cof_ManNodeNum(p), + nMffcsMax, 1.0*nMffcsAll /nMffcNodes ); +} + +/**Function************************************************************* + + Synopsis [Returns sorted array of node handles with largest fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintFanio( Gia_Man_t * pGia, int nNodes ) +{ + Cof_Man_t * p; + abctime clk = Abc_Clock(); + p = Cof_ManCreateLogicSimple( pGia ); + p->nLevels = 1 + Gia_ManLevelNum( pGia ); + p->pLevels = ABC_CALLOC( int, p->nLevels ); + Cof_ManPrintFanio( p ); + + if ( nNodes > 0 ) + { + Cof_ManResetTravId( p ); + Gia_ManHashStart( pGia ); + Cof_ManPrintHighFanout( p, nNodes ); + Gia_ManHashStop( pGia ); +ABC_PRMn( "Memory for logic network", 4*p->nObjData ); +ABC_PRT( "Time", Abc_Clock() - clk ); + } + + Cof_ManStop( p ); +} + + +/**Function************************************************************* + + Synopsis [Duplicates AIG in the DFS order while putting CIs first.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupCofInt( Gia_Man_t * p, int iVar ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj, * pPivot; + int i, iCofVar = -1; + if ( !(iVar > 0 && iVar < Gia_ManObjNum(p)) ) + { + printf( "Gia_ManDupCof(): Variable %d is out of range (%d; %d).\n", iVar, 0, Gia_ManObjNum(p) ); + return NULL; + } + // find the cofactoring variable + pPivot = Gia_ManObj( p, iVar ); + if ( !Gia_ObjIsCand(pPivot) ) + { + printf( "Gia_ManDupCof(): Variable %d should be a CI or an AND node.\n", iVar ); + return NULL; + } + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + // compute negative cofactor + Gia_ManForEachCi( p, pObj, i ) + { + pObj->Value = Gia_ManAppendCi(pNew); + if ( pObj == pPivot ) + { + iCofVar = pObj->Value; + pObj->Value = Abc_Var2Lit( 0, 0 ); + } + } + Gia_ManForEachAnd( p, pObj, i ) + { + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( pObj == pPivot ) + { + iCofVar = pObj->Value; + pObj->Value = Abc_Var2Lit( 0, 0 ); + } + } + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + // compute the positive cofactor + Gia_ManForEachCi( p, pObj, i ) + { + pObj->Value = Abc_Var2Lit( Gia_ObjId(pNew, Gia_ManCi(pNew, i)), 0 ); + if ( pObj == pPivot ) + pObj->Value = Abc_Var2Lit( 0, 1 ); + } + Gia_ManForEachAnd( p, pObj, i ) + { + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( pObj == pPivot ) + pObj->Value = Abc_Var2Lit( 0, 1 ); + } + // create MUXes + assert( iCofVar > 0 ); + Gia_ManForEachCo( p, pObj, i ) + { + if ( pObj->Value == (unsigned)Gia_ObjFanin0Copy(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + else + pObj->Value = Gia_ManAppendCo( pNew, Gia_ManHashMux(pNew, iCofVar, Gia_ObjFanin0Copy(pObj), pObj->Value) ); + } + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG in the DFS order while putting CIs first.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupCof( Gia_Man_t * p, int iVar ) +{ + Gia_Man_t * pNew, * pTemp; + pNew = Gia_ManDupCofInt( p, iVar ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Determines variables whose fanout count is higher than this.] + + Description [Variables are returned in a reverse topological order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManCofVars( Gia_Man_t * p, int nFanLim ) +{ + Vec_Int_t * vVars; + Gia_Obj_t * pObj; + int i; + ABC_FREE( p->pRefs ); + Gia_ManCreateRefs( p ); + vVars = Vec_IntAlloc( 100 ); + Gia_ManForEachObj( p, pObj, i ) + if ( Gia_ObjIsCand(pObj) && Gia_ObjRefNum(p, pObj) >= nFanLim ) + Vec_IntPush( vVars, i ); + ABC_FREE( p->pRefs ); + return vVars; +} + +/**Function************************************************************* + + Synopsis [Transfers attributes from the original one to the final one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManTransfer( Gia_Man_t * pAig, Gia_Man_t * pCof, Gia_Man_t * pNew, Vec_Int_t * vSigs ) +{ + Vec_Int_t * vSigsNew; + Gia_Obj_t * pObj, * pObjF; + int i; + vSigsNew = Vec_IntAlloc( 100 ); + Gia_ManForEachObjVec( vSigs, pAig, pObj, i ) + { + assert( Gia_ObjIsCand(pObj) ); + pObjF = Gia_ManObj( pCof, Abc_Lit2Var(pObj->Value) ); + if ( pObjF->Value && ~pObjF->Value ) + Vec_IntPushUnique( vSigsNew, Abc_Lit2Var(pObjF->Value) ); + } + return vSigsNew; +} + +/**Function************************************************************* + + Synopsis [Cofactors selected variables (should be in reverse topo order).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupCofAllInt( Gia_Man_t * p, Vec_Int_t * vSigs, int fVerbose ) +{ + Vec_Int_t * vSigsNew, * vTemp; + Gia_Man_t * pAig, * pCof, * pNew; + int iVar; + if ( fVerbose ) + { + printf( "Cofactoring %d signals.\n", Vec_IntSize(vSigs) ); + Gia_ManPrintStats( p, NULL ); + } + if ( Vec_IntSize( vSigs ) > 200 ) + { + printf( "Too many signals to cofactor.\n" ); + return NULL; + } + pAig = Gia_ManDup( p ); + vSigsNew = Vec_IntDup( vSigs ); + while ( Vec_IntSize(vSigsNew) > 0 ) + { + Vec_IntSort( vSigsNew, 0 ); + iVar = Vec_IntPop( vSigsNew ); +// Gia_ManCreateRefs( pAig ); +// printf( "ref count = %d\n", Gia_ObjRefNum( pAig, Gia_ManObj(pAig, iVar) ) ); +// ABC_FREE( pAig->pRefs ); + pCof = Gia_ManDupCofInt( pAig, iVar ); + pNew = Gia_ManCleanup( pCof ); + vSigsNew = Gia_ManTransfer( pAig, pCof, pNew, vTemp = vSigsNew ); + Vec_IntFree( vTemp ); + Gia_ManStop( pAig ); + Gia_ManStop( pCof ); + pAig = pNew; + if ( fVerbose ) + printf( "Cofactored variable %d.\n", iVar ); + if ( fVerbose ) + Gia_ManPrintStats( pAig, NULL ); + } + Vec_IntFree( vSigsNew ); + return pAig; +} + +/**Function************************************************************* + + Synopsis [Cofactors all variables whose fanout is higher than this.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupCofAll( Gia_Man_t * p, int nFanLim, int fVerbose ) +{ + Gia_Man_t * pNew; + Vec_Int_t * vSigs = Gia_ManCofVars( p, nFanLim ); + pNew = Gia_ManDupCofAllInt( p, vSigs, fVerbose ); + Vec_IntFree( vSigs ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Print the matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDsdMatrix( Gia_Man_t * p, int iIn ) +{ + Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, j; + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); + assert( Gia_ManPoNum(p) == 1 ); + assert( iIn >= 0 && iIn < Gia_ManPiNum(p) ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + for ( i = 0; i < Gia_ManPiNum(p); i++ ) if ( i != iIn ) + for ( j = i+1; j < Gia_ManPiNum(p); j++ ) if ( j != iIn ) + { + int pRes[8], k, n; + int iLit0 = Gia_ManPi(p, iIn)->Value; + int iLit1 = Gia_ManPi(p, i)->Value; + int iLit2 = Gia_ManPi(p, j)->Value; + for ( k = 0; k < 8; k++ ) + { + Gia_ManPi(p, iIn)->Value = k & 1; + Gia_ManPi(p, i)->Value = (k >> 1) & 1; + Gia_ManPi(p, j)->Value = (k >> 2) & 1; + Gia_ManForEachAnd( p, pObj, n ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + pRes[k] = Gia_ObjFanin0Copy(Gia_ManPo(p, 0)); + } + Gia_ManPi(p, iIn)->Value = iLit0; + Gia_ManPi(p, i)->Value = iLit1; + Gia_ManPi(p, j)->Value = iLit2; + for ( k = 0; k < 4; k++ ) + pRes[k] = Gia_ManHashXor( pNew, pRes[2*k], pRes[2*k+1] ); + Vec_IntPush( vRes, Gia_ManHashXor(pNew, Gia_ManHashAnd(pNew, pRes[0], pRes[3]), Gia_ManHashAnd(pNew, pRes[1], pRes[2])) ); + } + Vec_IntForEachEntry( vRes, j, i ) + Gia_ManAppendCo( pNew, j ); + Vec_IntFree( vRes ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} +void Gia_ManPrintDsdMatrix( Gia_Man_t * p, int iIn ) +{ + extern Gia_Man_t * Cec4_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose ); + Gia_Man_t * pNew = Gia_ManDsdMatrix( p, iIn ); int i, j, fFirst = 1, Count = 0; + Gia_Man_t * pSweep = Cec4_ManSimulateTest3( pNew, 0, 0 ); + Gia_ManStop( pNew ); + printf( "%4c : ", ' ' ); + for ( j = 0; j < Gia_ManPiNum(p); j++ ) + printf( "%4d", j ); + printf( "\n" ); + for ( i = 0; i < Gia_ManPiNum(p); i++, printf("\n"), fFirst = 1 ) + for ( j = 0; j < Gia_ManPiNum(p); j++ ) + { + if ( fFirst ) + printf( "%4d : ", i ), fFirst = 0; + if ( i == iIn ) + continue; + if ( j == iIn ) + printf( "%4c", ' ' ); + else + { + if ( j > i ) { + if ( Gia_ObjFaninLit0p(pSweep, Gia_ManPo(pSweep, Count++)) == 0 ) + printf( "%4c", '.' ); + else + printf( "%4c", '+' ); + } + else + printf( "%4c", ' ' ); + } + } + assert( Count == Gia_ManPoNum(pSweep) ); + Gia_ManStop( pSweep ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaCone.c b/yosys/abc/src/aig/gia/giaCone.c new file mode 100644 index 00000000000..cd43a65ece1 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaCone.c @@ -0,0 +1,590 @@ +/**CFile**************************************************************** + + FileName [giaCone.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaCone.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/extra/extra.h" +#include "misc/vec/vecHsh.h" +#include "misc/vec/vecWec.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Opa_Man_t_ Opa_Man_t; +struct Opa_Man_t_ +{ + Gia_Man_t * pGia; + Vec_Int_t * vFront; + Vec_Int_t * pvParts; + int * pId2Part; + int nParts; +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Opa_Man_t * Opa_ManStart( Gia_Man_t * pGia) +{ + Opa_Man_t * p; + Gia_Obj_t * pObj; + int i; + p = ABC_CALLOC( Opa_Man_t, 1 ); + p->pGia = pGia; + p->pvParts = ABC_CALLOC( Vec_Int_t, Gia_ManPoNum(pGia) ); + p->pId2Part = ABC_FALLOC( int, Gia_ManObjNum(pGia) ); + p->vFront = Vec_IntAlloc( 100 ); + Gia_ManForEachPo( pGia, pObj, i ) + { + Vec_IntPush( p->pvParts + i, Gia_ObjId(pGia, pObj) ); + p->pId2Part[Gia_ObjId(pGia, pObj)] = i; + Vec_IntPush( p->vFront, Gia_ObjId(pGia, pObj) ); + } + p->nParts = Gia_ManPoNum(pGia); + return p; +} +static inline void Opa_ManStop( Opa_Man_t * p ) +{ + int i; + Vec_IntFree( p->vFront ); + for ( i = 0; i < Gia_ManPoNum(p->pGia); i++ ) + ABC_FREE( p->pvParts[i].pArray ); + ABC_FREE( p->pvParts ); + ABC_FREE( p->pId2Part ); + ABC_FREE( p ); +} +static inline void Opa_ManPrint( Opa_Man_t * p ) +{ + int i, k; + printf( "Groups:\n" ); + for ( i = 0; i < Gia_ManPoNum(p->pGia); i++ ) + { + if ( p->pvParts[i].nSize == 0 ) + continue; + printf( "%3d : ", i ); + for ( k = 0; k < p->pvParts[i].nSize; k++ ) + printf( "%d ", p->pvParts[i].pArray[k] ); + printf( "\n" ); + } +} +static inline void Opa_ManPrint2( Opa_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, k, Count; + printf( "Groups %d: ", p->nParts ); + for ( i = 0; i < Gia_ManPoNum(p->pGia); i++ ) + { + if ( p->pvParts[i].nSize == 0 ) + continue; + // count POs in this group + Count = 0; + Gia_ManForEachObjVec( p->pvParts + i, p->pGia, pObj, k ) + Count += Gia_ObjIsPo(p->pGia, pObj); + printf( "%d ", Count ); + } + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Opa_ManMoveOne( Opa_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanin ) +{ + int iObj = Gia_ObjId(p->pGia, pObj); + int iFanin = Gia_ObjId(p->pGia, pFanin); + if ( iFanin == 0 ) + return; + assert( p->pId2Part[ iObj ] >= 0 ); + if ( p->pId2Part[ iFanin ] == -1 ) + { + p->pId2Part[ iFanin ] = p->pId2Part[ iObj ]; + Vec_IntPush( p->pvParts + p->pId2Part[ iObj ], iFanin ); + assert( Gia_ObjIsCi(pFanin) || Gia_ObjIsAnd(pFanin) ); + if ( Gia_ObjIsAnd(pFanin) ) + Vec_IntPush( p->vFront, iFanin ); + else if ( Gia_ObjIsRo(p->pGia, pFanin) ) + { + pFanin = Gia_ObjRoToRi(p->pGia, pFanin); + iFanin = Gia_ObjId(p->pGia, pFanin); + assert( p->pId2Part[ iFanin ] == -1 ); + p->pId2Part[ iFanin ] = p->pId2Part[ iObj ]; + Vec_IntPush( p->pvParts + p->pId2Part[ iObj ], iFanin ); + Vec_IntPush( p->vFront, iFanin ); + } + } + else if ( p->pId2Part[ iObj ] != p->pId2Part[ iFanin ] ) + { + Vec_Int_t * vPartObj = p->pvParts + p->pId2Part[ iObj ]; + Vec_Int_t * vPartFan = p->pvParts + p->pId2Part[ iFanin ]; + int iTemp, i; +// printf( "Moving %d to %d (%d -> %d)\n", iObj, iFanin, Vec_IntSize(vPartObj), Vec_IntSize(vPartFan) ); + // add group of iObj to group of iFanin + assert( Vec_IntSize(vPartObj) > 0 ); + Vec_IntForEachEntry( vPartObj, iTemp, i ) + { + Vec_IntPush( vPartFan, iTemp ); + p->pId2Part[ iTemp ] = p->pId2Part[ iFanin ]; + } + Vec_IntShrink( vPartObj, 0 ); + p->nParts--; + } +} +void Opa_ManPerform( Gia_Man_t * pGia ) +{ + Opa_Man_t * p; + Gia_Obj_t * pObj; + int i, Limit, Count = 0; + + p = Opa_ManStart( pGia ); + Limit = Vec_IntSize(p->vFront); +//Opa_ManPrint2( p ); + Gia_ManForEachObjVec( p->vFront, pGia, pObj, i ) + { + if ( i == Limit ) + { + printf( "%6d : %6d -> %6d\n", ++Count, i, p->nParts ); + Limit = Vec_IntSize(p->vFront); + if ( Count > 1 ) + Opa_ManPrint2( p ); + } +// printf( "*** Object %d ", Gia_ObjId(pGia, pObj) ); + if ( Gia_ObjIsAnd(pObj) ) + { + Opa_ManMoveOne( p, pObj, Gia_ObjFanin0(pObj) ); + Opa_ManMoveOne( p, pObj, Gia_ObjFanin1(pObj) ); + } + else if ( Gia_ObjIsCo(pObj) ) + Opa_ManMoveOne( p, pObj, Gia_ObjFanin0(pObj) ); + else assert( 0 ); +// if ( i % 10 == 0 ) +// printf( "%d ", p->nParts ); + if ( p->nParts == 1 ) + break; + if ( Count == 5 ) + break; + } + printf( "\n" ); + Opa_ManStop( p ); +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManConeMark_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vRoots, int nLimit ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return 0; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( Gia_ObjIsAnd(pObj) ) + { + if ( Gia_ManConeMark_rec( p, Gia_ObjFanin0(pObj), vRoots, nLimit ) ) + return 1; + if ( Gia_ManConeMark_rec( p, Gia_ObjFanin1(pObj), vRoots, nLimit ) ) + return 1; + } + else if ( Gia_ObjIsCo(pObj) ) + { + if ( Gia_ManConeMark_rec( p, Gia_ObjFanin0(pObj), vRoots, nLimit ) ) + return 1; + } + else if ( Gia_ObjIsRo(p, pObj) ) + Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)) ); + else if ( Gia_ObjIsPi(p, pObj) ) + {} + else assert( 0 ); + return (int)(Vec_IntSize(vRoots) > nLimit); +} +int Gia_ManConeMark( Gia_Man_t * p, int iOut, int Limit ) +{ + Vec_Int_t * vRoots; + Gia_Obj_t * pObj; + int i, RetValue; + // start the outputs + pObj = Gia_ManPo( p, iOut ); + vRoots = Vec_IntAlloc( 100 ); + Vec_IntPush( vRoots, Gia_ObjId(p, pObj) ); + // mark internal nodes + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); + Gia_ManForEachObjVec( vRoots, p, pObj, i ) + if ( Gia_ManConeMark_rec( p, pObj, vRoots, Limit ) ) + break; + RetValue = Vec_IntSize( vRoots ) - 1; + Vec_IntFree( vRoots ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCountFlops( Gia_Man_t * p, Vec_Int_t * vOuts ) +{ + int Limit = ABC_INFINITY; + Vec_Int_t * vRoots; + Gia_Obj_t * pObj; + int i, RetValue, iOut; + // start the outputs + vRoots = Vec_IntAlloc( 100 ); + Vec_IntForEachEntry( vOuts, iOut, i ) + { + pObj = Gia_ManPo( p, iOut ); + Vec_IntPush( vRoots, Gia_ObjId(p, pObj) ); + } + // mark internal nodes + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); + Gia_ManForEachObjVec( vRoots, p, pObj, i ) + if ( Gia_ManConeMark_rec( p, pObj, vRoots, Limit ) ) + break; + RetValue = Vec_IntSize( vRoots ) - Vec_IntSize(vOuts); + Vec_IntFree( vRoots ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManFindPoPartition3( Gia_Man_t * p, int iOut, int nDelta, int nOutsMin, int nOutsMax, int fVerbose, Vec_Ptr_t ** pvPosEquivs ) +{ +/* + int i, Count = 0; + // mark nodes belonging to output 'iOut' + for ( i = 0; i < Gia_ManPoNum(p); i++ ) + Count += (Gia_ManConeMark(p, i, 10000) < 10000); + // printf( "%d ", Gia_ManConeMark(p, i, 1000) ); + printf( "%d out of %d\n", Count, Gia_ManPoNum(p) ); + + // add other outputs as long as they are nDelta away +*/ +// Opa_ManPerform( p ); + + return NULL; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManFindPivots( Gia_Man_t * p, int SelectShift, int fOnlyCis, int fVerbose ) +{ + Vec_Int_t * vPivots, * vWeights; + Vec_Int_t * vCount, * vResult; + int i, j, Count, * pPerm, Limit; +/* + Gia_Obj_t * pObj; + // count MUX controls + vCount = Vec_IntStart( Gia_ManObjNum(p) ); + Gia_ManForEachAnd( p, pObj, i ) + { + Gia_Obj_t * pNodeC, * pNodeT, * pNodeE; + if ( !Gia_ObjIsMuxType(pObj) ) + continue; + pNodeC = Gia_ObjRecognizeMux( pObj, &pNodeT, &pNodeE ); + Vec_IntAddToEntry( vCount, Gia_ObjId(p, Gia_Regular(pNodeC)), 1 ); + } +*/ + // count references + Gia_ManCreateRefs( p ); + vCount = Vec_IntAllocArray( p->pRefs, Gia_ManObjNum(p) ); p->pRefs = NULL; + + // collect nodes + vPivots = Vec_IntAlloc( 100 ); + vWeights = Vec_IntAlloc( 100 ); + Vec_IntForEachEntry( vCount, Count, i ) + { + if ( Count < 2 ) continue; + if ( fOnlyCis && !Gia_ObjIsCi(Gia_ManObj(p, i)) ) + continue; + Vec_IntPush( vPivots, i ); + Vec_IntPush( vWeights, Count ); + } + Vec_IntFree( vCount ); + + if ( fVerbose ) + printf( "Selected %d pivots with more than one fanout (out of %d CIs and ANDs).\n", Vec_IntSize(vWeights), Gia_ManCiNum(p) + Gia_ManAndNum(p) ); + + // permute + Gia_ManRandom(1); + Gia_ManRandom(0); + for ( i = 0; i < Vec_IntSize(vWeights); i++ ) + { + j = (Gia_ManRandom(0) >> 1) % Vec_IntSize(vWeights); + ABC_SWAP( int, vPivots->pArray[i], vPivots->pArray[j] ); + ABC_SWAP( int, vWeights->pArray[i], vWeights->pArray[j] ); + } + // sort + if ( SelectShift == 0 ) + pPerm = Abc_QuickSortCost( Vec_IntArray(vWeights), Vec_IntSize(vWeights), 1 ); + else + { + Vec_Int_t * vTemp = Vec_IntStartNatural( Vec_IntSize(vWeights) ); + pPerm = Vec_IntReleaseArray( vTemp ); + Vec_IntFree( vTemp ); + } + + // select + Limit = Abc_MinInt( 64, Vec_IntSize(vWeights) ); + vResult = Vec_IntAlloc( Limit ); + for ( i = 0; i < Limit; i++ ) + { + j = (i + SelectShift) % Vec_IntSize(vWeights); + if ( fVerbose ) + printf( "%2d : Pivot =%7d Fanout =%7d\n", j, Vec_IntEntry(vPivots, pPerm[j]), Vec_IntEntry(vWeights, pPerm[j]) ); + Vec_IntPush( vResult, Vec_IntEntry(vPivots, pPerm[j]) ); + } + + Vec_IntFree( vPivots ); + Vec_IntFree( vWeights ); + ABC_FREE( pPerm ); + + return vResult; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wrd_t * Gia_ManDeriveSigns( Gia_Man_t * p, Vec_Int_t * vPivots, int fVerbose ) +{ + Vec_Wrd_t * vSigns; + Gia_Obj_t * pObj, * pObjRi; + int i, fChange = 1, Counter; + + Gia_ManFillValue( p ); + Gia_ManForEachObjVec( vPivots, p, pObj, i ) + pObj->Value = i; + + if ( fVerbose ) + printf( "Signature propagation: " ); + vSigns = Vec_WrdStart( Gia_ManObjNum(p) ); + while ( fChange ) + { + fChange = 0; + Gia_ManForEachObj( p, pObj, i ) + { + if ( ~pObj->Value ) + { + assert( pObj->Value >= 0 && pObj->Value < 64 ); + *Vec_WrdEntryP( vSigns, i ) |= ( (word)1 << pObj->Value ); + } + if ( Gia_ObjIsAnd(pObj) ) + *Vec_WrdEntryP( vSigns, i ) |= Vec_WrdEntry(vSigns, Gia_ObjFaninId0(pObj, i)) | Vec_WrdEntry(vSigns, Gia_ObjFaninId1(pObj, i)); + else if ( Gia_ObjIsCo(pObj) ) + *Vec_WrdEntryP( vSigns, i ) |= Vec_WrdEntry(vSigns, Gia_ObjFaninId0(pObj, i)); + } + Counter = 0; + Gia_ManForEachRiRo( p, pObjRi, pObj, i ) + { + word Value = Vec_WrdEntry(vSigns, Gia_ObjId(p, pObj)); + *Vec_WrdEntryP( vSigns, Gia_ObjId(p, pObj) ) |= Vec_WrdEntry(vSigns, Gia_ObjId(p, pObjRi)); + if ( Value != Vec_WrdEntry(vSigns, Gia_ObjId(p, pObj)) ) + fChange = 1, Counter++; + } + if ( fVerbose ) + printf( "%d ", Counter ); + } + if ( fVerbose ) + printf( "\n" ); + return vSigns; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Gia_ManHashOutputs( Gia_Man_t * p, Vec_Wrd_t * vSigns, int fVerbose ) +{ + Vec_Ptr_t * vBins; + Vec_Wec_t * vClasses; + Vec_Wrd_t * vSignsPo; + Vec_Int_t * vPriority, * vBin; + Gia_Obj_t * pObj; + int i; + // collect PO signatures + vSignsPo = Vec_WrdAlloc( Gia_ManPoNum(p) ); + Gia_ManForEachPo( p, pObj, i ) + Vec_WrdPush( vSignsPo, Vec_WrdEntry(vSigns, Gia_ObjId(p, pObj)) ); + // find equivalence classes + vPriority = Hsh_WrdManHashArray( vSignsPo, 1 ); + Vec_WrdFree( vSignsPo ); + vClasses = Vec_WecCreateClasses( vPriority ); + Vec_IntFree( vPriority ); + vBins = (Vec_Ptr_t *)Vec_WecConvertToVecPtr( vClasses ); + Vec_WecFree( vClasses ); + Vec_VecSort( (Vec_Vec_t *)vBins, 1 ); + + if ( fVerbose ) + printf( "Computed %d partitions:\n", Vec_PtrSize(vBins) ); + if ( !fVerbose ) + printf( "Listing partitions with more than 100 outputs:\n" ); + Vec_PtrForEachEntry( Vec_Int_t *, vBins, vBin, i ) + { + assert( Vec_IntSize(vBin) > 0 ); + if ( fVerbose || Vec_IntSize(vBin) > 100 ) + { + int PoNum = Vec_IntEntry( vBin, 0 ); + Gia_Obj_t * pObj = Gia_ManPo( p, PoNum ); + word Sign = Vec_WrdEntry( vSigns, Gia_ObjId(p, pObj) ); + // print + printf( "%3d ", i ); + Extra_PrintBinary( stdout, (unsigned *)&Sign, 64 ); + printf( " " ); + printf( "PO =%7d ", Vec_IntSize(vBin) ); + printf( "FF =%7d", Gia_ManCountFlops(p, vBin) ); + printf( "\n" ); + } + } + return vBins; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManFindPoPartition2( Gia_Man_t * p, int iStartNum, int nDelta, int nOutsMin, int nOutsMax, int fSetLargest, int fVerbose, Vec_Ptr_t ** pvPosEquivs ) +{ + return NULL; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManFindPoPartition( Gia_Man_t * p, int SelectShift, int fOnlyCis, int fSetLargest, int fVerbose, Vec_Ptr_t ** pvPosEquivs ) +{ + Gia_Man_t * pGia = NULL; + Vec_Int_t * vPivots; + Vec_Wrd_t * vSigns; + Vec_Ptr_t * vParts; + Vec_Int_t * vPart; + abctime clk = Abc_Clock(); + vPivots = Gia_ManFindPivots( p, SelectShift, fOnlyCis, fVerbose ); + vSigns = Gia_ManDeriveSigns( p, vPivots, fVerbose ); + Vec_IntFree( vPivots ); + vParts = Gia_ManHashOutputs( p, vSigns, fVerbose ); + Vec_WrdFree( vSigns ); + if ( fSetLargest ) + { + vPart = Vec_VecEntryInt( (Vec_Vec_t *)vParts, 0 ); + pGia = Gia_ManDupCones( p, Vec_IntArray(vPart), Vec_IntSize(vPart), 1 ); + } + if ( pvPosEquivs ) + { + *pvPosEquivs = vParts; + printf( "The algorithm divided %d POs into %d partitions. ", Gia_ManPoNum(p), Vec_PtrSize(vParts) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + else + Vec_VecFree( (Vec_Vec_t *)vParts ); + return pGia; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaConstr.c b/yosys/abc/src/aig/gia/giaConstr.c new file mode 100644 index 00000000000..60432072d23 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaConstr.c @@ -0,0 +1,52 @@ +/**CFile**************************************************************** + + FileName [giaConstr.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Constraint propagation in CNF-based solver.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaConstr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaCut.c b/yosys/abc/src/aig/gia/giaCut.c new file mode 100644 index 00000000000..19d98c3be29 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaCut.c @@ -0,0 +1,1389 @@ +/**CFile**************************************************************** + + FileName [giaCut.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Stand-alone cut computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/util/utilTruth.h" +#include "misc/vec/vecHsh.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define GIA_MAX_CUTSIZE 8 +#define GIA_MAX_CUTNUM 257 +#define GIA_MAX_TT_WORDS ((GIA_MAX_CUTSIZE > 6) ? 1 << (GIA_MAX_CUTSIZE-6) : 1) + +#define GIA_CUT_NO_LEAF 0xF + +typedef struct Gia_Cut_t_ Gia_Cut_t; +struct Gia_Cut_t_ +{ + word Sign; // signature + int iFunc; // functionality + int Cost; // cut cost + int CostLev; // cut cost + unsigned nTreeLeaves : 28; // tree leaves + unsigned nLeaves : 4; // leaf count + int pLeaves[GIA_MAX_CUTSIZE]; // leaves + float CostF; +}; + +typedef struct Gia_Sto_t_ Gia_Sto_t; +struct Gia_Sto_t_ +{ + int nCutSize; + int nCutNum; + int fCutMin; + int fTruthMin; + int fVerbose; + Gia_Man_t * pGia; // user's AIG manager (will be modified by adding nodes) + Vec_Int_t * vRefs; // refs for each node + Vec_Wec_t * vCuts; // cuts for each node + Vec_Mem_t * vTtMem; // truth tables + Gia_Cut_t pCuts[3][GIA_MAX_CUTNUM]; // temporary cuts + Gia_Cut_t * ppCuts[GIA_MAX_CUTNUM]; // temporary cut pointers + int nCutsR; // the number of cuts + int Pivot; // current object + int iCutBest; // best-delay cut + int nCutsOver; // overflow cuts + double CutCount[4]; // cut counters + abctime clkStart; // starting time +}; + +static inline word * Gia_CutTruth( Gia_Sto_t * p, Gia_Cut_t * pCut ) { return Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut->iFunc)); } + +#define Sdb_ForEachCut( pList, pCut, i ) for ( i = 0, pCut = pList + 1; i < pList[0]; i++, pCut += pCut[0] + 2 ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Check correctness of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline word Gia_CutGetSign( Gia_Cut_t * pCut ) +{ + word Sign = 0; int i; + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + Sign |= ((word)1) << (pCut->pLeaves[i] & 0x3F); + return Sign; +} +static inline int Gia_CutCheck( Gia_Cut_t * pBase, Gia_Cut_t * pCut ) // check if pCut is contained in pBase +{ + int nSizeB = pBase->nLeaves; + int nSizeC = pCut->nLeaves; + int i, * pB = pBase->pLeaves; + int k, * pC = pCut->pLeaves; + for ( i = 0; i < nSizeC; i++ ) + { + for ( k = 0; k < nSizeB; k++ ) + if ( pC[i] == pB[k] ) + break; + if ( k == nSizeB ) + return 0; + } + return 1; +} +static inline int Gia_CutSetCheckArray( Gia_Cut_t ** ppCuts, int nCuts ) +{ + Gia_Cut_t * pCut0, * pCut1; + int i, k, m, n, Value; + assert( nCuts > 0 ); + for ( i = 0; i < nCuts; i++ ) + { + pCut0 = ppCuts[i]; + assert( pCut0->nLeaves <= GIA_MAX_CUTSIZE ); + assert( pCut0->Sign == Gia_CutGetSign(pCut0) ); + // check duplicates + for ( m = 0; m < (int)pCut0->nLeaves; m++ ) + for ( n = m + 1; n < (int)pCut0->nLeaves; n++ ) + assert( pCut0->pLeaves[m] < pCut0->pLeaves[n] ); + // check pairs + for ( k = 0; k < nCuts; k++ ) + { + pCut1 = ppCuts[k]; + if ( pCut0 == pCut1 ) + continue; + // check containments + Value = Gia_CutCheck( pCut0, pCut1 ); + assert( Value == 0 ); + } + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_CutMergeOrder( Gia_Cut_t * pCut0, Gia_Cut_t * pCut1, Gia_Cut_t * pCut, int nCutSize ) +{ + int nSize0 = pCut0->nLeaves; + int nSize1 = pCut1->nLeaves; + int i, * pC0 = pCut0->pLeaves; + int k, * pC1 = pCut1->pLeaves; + int c, * pC = pCut->pLeaves; + // the case of the largest cut sizes + if ( nSize0 == nCutSize && nSize1 == nCutSize ) + { + for ( i = 0; i < nSize0; i++ ) + { + if ( pC0[i] != pC1[i] ) return 0; + pC[i] = pC0[i]; + } + pCut->nLeaves = nCutSize; + pCut->iFunc = -1; + pCut->Sign = pCut0->Sign | pCut1->Sign; + return 1; + } + // compare two cuts with different numbers + i = k = c = 0; + if ( nSize0 == 0 ) goto FlushCut1; + if ( nSize1 == 0 ) goto FlushCut0; + while ( 1 ) + { + if ( c == nCutSize ) return 0; + if ( pC0[i] < pC1[k] ) + { + pC[c++] = pC0[i++]; + if ( i >= nSize0 ) goto FlushCut1; + } + else if ( pC0[i] > pC1[k] ) + { + pC[c++] = pC1[k++]; + if ( k >= nSize1 ) goto FlushCut0; + } + else + { + pC[c++] = pC0[i++]; k++; + if ( i >= nSize0 ) goto FlushCut1; + if ( k >= nSize1 ) goto FlushCut0; + } + } + +FlushCut0: + if ( c + nSize0 > nCutSize + i ) return 0; + while ( i < nSize0 ) + pC[c++] = pC0[i++]; + pCut->nLeaves = c; + pCut->iFunc = -1; + pCut->Sign = pCut0->Sign | pCut1->Sign; + return 1; + +FlushCut1: + if ( c + nSize1 > nCutSize + k ) return 0; + while ( k < nSize1 ) + pC[c++] = pC1[k++]; + pCut->nLeaves = c; + pCut->iFunc = -1; + pCut->Sign = pCut0->Sign | pCut1->Sign; + return 1; +} +static inline int Gia_CutMergeOrder2( Gia_Cut_t * pCut0, Gia_Cut_t * pCut1, Gia_Cut_t * pCut, int nCutSize ) +{ + int x0, i0 = 0, nSize0 = pCut0->nLeaves, * pC0 = pCut0->pLeaves; + int x1, i1 = 0, nSize1 = pCut1->nLeaves, * pC1 = pCut1->pLeaves; + int xMin, c = 0, * pC = pCut->pLeaves; + while ( 1 ) + { + x0 = (i0 == nSize0) ? ABC_INFINITY : pC0[i0]; + x1 = (i1 == nSize1) ? ABC_INFINITY : pC1[i1]; + xMin = Abc_MinInt(x0, x1); + if ( xMin == ABC_INFINITY ) break; + if ( c == nCutSize ) return 0; + pC[c++] = xMin; + if (x0 == xMin) i0++; + if (x1 == xMin) i1++; + } + pCut->nLeaves = c; + pCut->iFunc = -1; + pCut->Sign = pCut0->Sign | pCut1->Sign; + return 1; +} +static inline int Gia_CutSetCutIsContainedOrder( Gia_Cut_t * pBase, Gia_Cut_t * pCut ) // check if pCut is contained in pBase +{ + int i, nSizeB = pBase->nLeaves; + int k, nSizeC = pCut->nLeaves; + if ( nSizeB == nSizeC ) + { + for ( i = 0; i < nSizeB; i++ ) + if ( pBase->pLeaves[i] != pCut->pLeaves[i] ) + return 0; + return 1; + } + assert( nSizeB > nSizeC ); + if ( nSizeC == 0 ) + return 1; + for ( i = k = 0; i < nSizeB; i++ ) + { + if ( pBase->pLeaves[i] > pCut->pLeaves[k] ) + return 0; + if ( pBase->pLeaves[i] == pCut->pLeaves[k] ) + { + if ( ++k == nSizeC ) + return 1; + } + } + return 0; +} +static inline int Gia_CutSetLastCutIsContained( Gia_Cut_t ** pCuts, int nCuts ) +{ + int i; + for ( i = 0; i < nCuts; i++ ) + if ( pCuts[i]->nLeaves <= pCuts[nCuts]->nLeaves && (pCuts[i]->Sign & pCuts[nCuts]->Sign) == pCuts[i]->Sign && Gia_CutSetCutIsContainedOrder(pCuts[nCuts], pCuts[i]) ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_CutCompare2( Gia_Cut_t * pCut0, Gia_Cut_t * pCut1 ) +{ + if ( pCut0->nTreeLeaves < pCut1->nTreeLeaves ) return -1; + if ( pCut0->nTreeLeaves > pCut1->nTreeLeaves ) return 1; + if ( pCut0->nLeaves < pCut1->nLeaves ) return -1; + if ( pCut0->nLeaves > pCut1->nLeaves ) return 1; + return 0; +} +static inline int Gia_CutCompare( Gia_Cut_t * pCut0, Gia_Cut_t * pCut1 ) +{ + if ( pCut0->CostF > pCut1->CostF ) return -1; + if ( pCut0->CostF < pCut1->CostF ) return 1; + if ( pCut0->nLeaves < pCut1->nLeaves ) return -1; + if ( pCut0->nLeaves > pCut1->nLeaves ) return 1; + return 0; +} +static inline int Gia_CutSetLastCutContains( Gia_Cut_t ** pCuts, int nCuts ) +{ + int i, k, fChanges = 0; + for ( i = 0; i < nCuts; i++ ) + if ( pCuts[nCuts]->nLeaves < pCuts[i]->nLeaves && (pCuts[nCuts]->Sign & pCuts[i]->Sign) == pCuts[nCuts]->Sign && Gia_CutSetCutIsContainedOrder(pCuts[i], pCuts[nCuts]) ) + pCuts[i]->nLeaves = GIA_CUT_NO_LEAF, fChanges = 1; + if ( !fChanges ) + return nCuts; + for ( i = k = 0; i <= nCuts; i++ ) + { + if ( pCuts[i]->nLeaves == GIA_CUT_NO_LEAF ) + continue; + if ( k < i ) + ABC_SWAP( Gia_Cut_t *, pCuts[k], pCuts[i] ); + k++; + } + return k - 1; +} +static inline void Gia_CutSetSortByCost( Gia_Cut_t ** pCuts, int nCuts ) +{ + int i; + for ( i = nCuts; i > 0; i-- ) + { + if ( Gia_CutCompare(pCuts[i - 1], pCuts[i]) < 0 )//!= 1 ) + return; + ABC_SWAP( Gia_Cut_t *, pCuts[i - 1], pCuts[i] ); + } +} +static inline int Gia_CutSetAddCut( Gia_Cut_t ** pCuts, int nCuts, int nCutNum ) +{ + if ( nCuts == 0 ) + return 1; + nCuts = Gia_CutSetLastCutContains(pCuts, nCuts); + assert( nCuts >= 0 ); + Gia_CutSetSortByCost( pCuts, nCuts ); + // add new cut if there is room + return Abc_MinInt( nCuts + 1, nCutNum - 1 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_CutComputeTruth6( Gia_Sto_t * p, Gia_Cut_t * pCut0, Gia_Cut_t * pCut1, int fCompl0, int fCompl1, Gia_Cut_t * pCutR, int fIsXor ) +{ + int nOldSupp = pCutR->nLeaves, truthId, fCompl; word t; + word t0 = *Gia_CutTruth(p, pCut0); + word t1 = *Gia_CutTruth(p, pCut1); + if ( Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ) t0 = ~t0; + if ( Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ) t1 = ~t1; + t0 = Abc_Tt6Expand( t0, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + t1 = Abc_Tt6Expand( t1, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + t = fIsXor ? t0 ^ t1 : t0 & t1; + if ( (fCompl = (int)(t & 1)) ) t = ~t; + if ( p->fTruthMin ) + pCutR->nLeaves = Abc_Tt6MinBase( &t, pCutR->pLeaves, pCutR->nLeaves ); + assert( (int)(t & 1) == 0 ); + truthId = Vec_MemHashInsert(p->vTtMem, &t); + pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); + assert( (int)pCutR->nLeaves <= nOldSupp ); + return (int)pCutR->nLeaves < nOldSupp; +} +static inline int Gia_CutComputeTruth( Gia_Sto_t * p, Gia_Cut_t * pCut0, Gia_Cut_t * pCut1, int fCompl0, int fCompl1, Gia_Cut_t * pCutR, int fIsXor ) +{ + if ( p->nCutSize <= 6 ) + return Gia_CutComputeTruth6( p, pCut0, pCut1, fCompl0, fCompl1, pCutR, fIsXor ); + { + word uTruth[GIA_MAX_TT_WORDS], uTruth0[GIA_MAX_TT_WORDS], uTruth1[GIA_MAX_TT_WORDS]; + int nOldSupp = pCutR->nLeaves, truthId; + int nCutSize = p->nCutSize, fCompl; + int nWords = Abc_Truth6WordNum(nCutSize); + word * pTruth0 = Gia_CutTruth(p, pCut0); + word * pTruth1 = Gia_CutTruth(p, pCut1); + Abc_TtCopy( uTruth0, pTruth0, nWords, Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ); + Abc_TtCopy( uTruth1, pTruth1, nWords, Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ); + Abc_TtExpand( uTruth0, nCutSize, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + Abc_TtExpand( uTruth1, nCutSize, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + if ( fIsXor ) + Abc_TtXor( uTruth, uTruth0, uTruth1, nWords, (fCompl = (int)((uTruth0[0] ^ uTruth1[0]) & 1)) ); + else + Abc_TtAnd( uTruth, uTruth0, uTruth1, nWords, (fCompl = (int)((uTruth0[0] & uTruth1[0]) & 1)) ); + if ( p->fTruthMin ) + pCutR->nLeaves = Abc_TtMinBase( uTruth, pCutR->pLeaves, pCutR->nLeaves, nCutSize ); + assert( (uTruth[0] & 1) == 0 ); +//Kit_DsdPrintFromTruth( uTruth, pCutR->nLeaves ), printf("\n" ), printf("\n" ); + truthId = Vec_MemHashInsert(p->vTtMem, uTruth); + pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); + assert( (int)pCutR->nLeaves <= nOldSupp ); + return (int)pCutR->nLeaves < nOldSupp; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_CutCountBits( word i ) +{ + i = i - ((i >> 1) & 0x5555555555555555); + i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333); + i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F); + return (i*(0x0101010101010101))>>56; +} +static inline void Gia_CutAddUnit( Gia_Sto_t * p, int iObj ) +{ + Vec_Int_t * vThis = Vec_WecEntry( p->vCuts, iObj ); + if ( Vec_IntSize(vThis) == 0 ) + Vec_IntPush( vThis, 1 ); + else + Vec_IntAddToEntry( vThis, 0, 1 ); + Vec_IntPush( vThis, 1 ); + Vec_IntPush( vThis, iObj ); + Vec_IntPush( vThis, 2 ); +} +static inline void Gia_CutAddZero( Gia_Sto_t * p, int iObj ) +{ + Vec_Int_t * vThis = Vec_WecEntry( p->vCuts, iObj ); + assert( Vec_IntSize(vThis) == 0 ); + Vec_IntPush( vThis, 1 ); + Vec_IntPush( vThis, 0 ); + Vec_IntPush( vThis, 0 ); +} +static inline int Gia_CutTreeLeaves( Gia_Sto_t * p, Gia_Cut_t * pCut ) +{ + int i, Cost = 0; + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + Cost += Vec_IntEntry( p->vRefs, pCut->pLeaves[i] ) == 1; + return Cost; +} +static inline float Gia_CutGetCost( Gia_Sto_t * p, Gia_Cut_t * pCut ) +{ + int i, Cost = 0; + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + Cost += Vec_IntEntry( p->vRefs, pCut->pLeaves[i] ); + return (float)Cost / Abc_MaxInt(1, pCut->nLeaves); +} +static inline int Gia_StoPrepareSet( Gia_Sto_t * p, int iObj, int Index ) +{ + Vec_Int_t * vThis = Vec_WecEntry( p->vCuts, iObj ); + int i, v, * pCut, * pList = Vec_IntArray( vThis ); + Sdb_ForEachCut( pList, pCut, i ) + { + Gia_Cut_t * pCutTemp = &p->pCuts[Index][i]; + pCutTemp->nLeaves = pCut[0]; + for ( v = 1; v <= pCut[0]; v++ ) + pCutTemp->pLeaves[v-1] = pCut[v]; + pCutTemp->iFunc = pCut[pCut[0]+1]; + pCutTemp->Sign = Gia_CutGetSign( pCutTemp ); + pCutTemp->nTreeLeaves = Gia_CutTreeLeaves( p, pCutTemp ); + pCutTemp->CostF = Gia_CutGetCost( p, pCutTemp ); + } + return pList[0]; +} +static inline void Gia_StoInitResult( Gia_Sto_t * p ) +{ + int i; + for ( i = 0; i < GIA_MAX_CUTNUM; i++ ) + p->ppCuts[i] = &p->pCuts[2][i]; +} +static inline void Gia_StoStoreResult( Gia_Sto_t * p, int iObj, Gia_Cut_t ** pCuts, int nCuts ) +{ + int i, v; + Vec_Int_t * vList = Vec_WecEntry( p->vCuts, iObj ); + Vec_IntPush( vList, nCuts ); + for ( i = 0; i < nCuts; i++ ) + { + Vec_IntPush( vList, pCuts[i]->nLeaves ); + for ( v = 0; v < (int)pCuts[i]->nLeaves; v++ ) + Vec_IntPush( vList, pCuts[i]->pLeaves[v] ); + Vec_IntPush( vList, pCuts[i]->iFunc ); + } +} +static inline void Gia_CutPrint( Gia_Sto_t * p, int iObj, Gia_Cut_t * pCut ) +{ + int i, nDigits = Abc_Base10Log(Gia_ManObjNum(p->pGia)); + if ( pCut == NULL ) { printf( "No cut.\n" ); return; } + printf( "%d {", pCut->nLeaves ); + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + printf( " %*d", nDigits, pCut->pLeaves[i] ); + for ( ; i < (int)p->nCutSize; i++ ) + printf( " %*s", nDigits, " " ); + printf( " } Cost = %3d CostL = %3d Tree = %d ", + pCut->Cost, pCut->CostLev, pCut->nTreeLeaves ); + printf( "\n" ); +} +void Gia_StoMergeCuts( Gia_Sto_t * p, int iObj ) +{ + Gia_Obj_t * pObj = Gia_ManObj(p->pGia, iObj); + int fIsXor = Gia_ObjIsXor(pObj); + int nCutSize = p->nCutSize; + int nCutNum = p->nCutNum; + int fComp0 = Gia_ObjFaninC0(pObj); + int fComp1 = Gia_ObjFaninC1(pObj); + int Fan0 = Gia_ObjFaninId0(pObj, iObj); + int Fan1 = Gia_ObjFaninId1(pObj, iObj); + int nCuts0 = Gia_StoPrepareSet( p, Fan0, 0 ); + int nCuts1 = Gia_StoPrepareSet( p, Fan1, 1 ); + int i, k, nCutsR = 0; + Gia_Cut_t * pCut0, * pCut1, ** pCutsR = p->ppCuts; + assert( !Gia_ObjIsBuf(pObj) ); + assert( !Gia_ObjIsMux(p->pGia, pObj) ); + Gia_StoInitResult( p ); + p->CutCount[0] += nCuts0 * nCuts1; + for ( i = 0, pCut0 = p->pCuts[0]; i < nCuts0; i++, pCut0++ ) + for ( k = 0, pCut1 = p->pCuts[1]; k < nCuts1; k++, pCut1++ ) + { + if ( (int)(pCut0->nLeaves + pCut1->nLeaves) > nCutSize && Gia_CutCountBits(pCut0->Sign | pCut1->Sign) > nCutSize ) + continue; + p->CutCount[1]++; + if ( !Gia_CutMergeOrder(pCut0, pCut1, pCutsR[nCutsR], nCutSize) ) + continue; + if ( Gia_CutSetLastCutIsContained(pCutsR, nCutsR) ) + continue; + p->CutCount[2]++; + if ( p->fCutMin && Gia_CutComputeTruth(p, pCut0, pCut1, fComp0, fComp1, pCutsR[nCutsR], fIsXor) ) + pCutsR[nCutsR]->Sign = Gia_CutGetSign(pCutsR[nCutsR]); + pCutsR[nCutsR]->nTreeLeaves = Gia_CutTreeLeaves( p, pCutsR[nCutsR] ); + pCutsR[nCutsR]->CostF = Gia_CutGetCost( p, pCutsR[nCutsR] ); + nCutsR = Gia_CutSetAddCut( pCutsR, nCutsR, nCutNum ); + } + p->CutCount[3] += nCutsR; + p->nCutsOver += nCutsR == nCutNum-1; + p->nCutsR = nCutsR; + p->Pivot = iObj; + // debug printout + if ( 0 ) + { + printf( "*** Obj = %4d NumCuts = %4d\n", iObj, nCutsR ); + for ( i = 0; i < nCutsR; i++ ) + Gia_CutPrint( p, iObj, pCutsR[i] ); + printf( "\n" ); + } + // verify + assert( nCutsR > 0 && nCutsR < nCutNum ); + assert( Gia_CutSetCheckArray(pCutsR, nCutsR) ); + // store the cutset + Gia_StoStoreResult( p, iObj, pCutsR, nCutsR ); + if ( nCutsR > 1 || pCutsR[0]->nLeaves > 1 ) + Gia_CutAddUnit( p, iObj ); +} + + +/**Function************************************************************* + + Synopsis [Incremental cut computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Sto_t * Gia_StoAlloc( Gia_Man_t * pGia, int nCutSize, int nCutNum, int fCutMin, int fTruthMin, int fVerbose ) +{ + Gia_Sto_t * p; + assert( nCutSize < GIA_CUT_NO_LEAF ); + assert( nCutSize > 1 && nCutSize <= GIA_MAX_CUTSIZE ); + assert( nCutNum > 1 && nCutNum < GIA_MAX_CUTNUM ); + p = ABC_CALLOC( Gia_Sto_t, 1 ); + p->clkStart = Abc_Clock(); + p->nCutSize = nCutSize; + p->nCutNum = nCutNum; + p->fCutMin = fCutMin; + p->fTruthMin = fTruthMin; + p->fVerbose = fVerbose; + p->pGia = pGia; + p->vRefs = Vec_IntAlloc( Gia_ManObjNum(pGia) ); + p->vCuts = Vec_WecStart( Gia_ManObjNum(pGia) ); + p->vTtMem = fCutMin ? Vec_MemAllocForTT( nCutSize, 0 ) : NULL; + return p; +} +void Gia_StoFree( Gia_Sto_t * p ) +{ + Vec_IntFree( p->vRefs ); + Vec_WecFree( p->vCuts ); + if ( p->fCutMin ) + Vec_MemHashFree( p->vTtMem ); + if ( p->fCutMin ) + Vec_MemFree( p->vTtMem ); + ABC_FREE( p ); +} +void Gia_StoComputeCutsConst0( Gia_Sto_t * p, int iObj ) +{ + Gia_CutAddZero( p, iObj ); +} +void Gia_StoComputeCutsCi( Gia_Sto_t * p, int iObj ) +{ + Gia_CutAddUnit( p, iObj ); +} +void Gia_StoComputeCutsNode( Gia_Sto_t * p, int iObj ) +{ + Gia_StoMergeCuts( p, iObj ); +} +void Gia_StoRefObj( Gia_Sto_t * p, int iObj ) +{ + Gia_Obj_t * pObj = Gia_ManObj(p->pGia, iObj); + assert( iObj == Vec_IntSize(p->vRefs) ); + Vec_IntPush( p->vRefs, 0 ); + if ( Gia_ObjIsAnd(pObj) ) + { + Vec_IntAddToEntry( p->vRefs, Gia_ObjFaninId0(pObj, iObj), 1 ); + Vec_IntAddToEntry( p->vRefs, Gia_ObjFaninId1(pObj, iObj), 1 ); + } + else if ( Gia_ObjIsCo(pObj) ) + Vec_IntAddToEntry( p->vRefs, Gia_ObjFaninId0(pObj, iObj), 1 ); +} +void Gia_StoComputeCuts( Gia_Man_t * pGia ) +{ + int nCutSize = 8; + int nCutNum = 6; + int fCutMin = 0; + int fTruthMin = 0; + int fVerbose = 1; + Gia_Sto_t * p = Gia_StoAlloc( pGia, nCutSize, nCutNum, fCutMin, fTruthMin, fVerbose ); + Gia_Obj_t * pObj; int i, iObj; + assert( nCutSize <= GIA_MAX_CUTSIZE ); + assert( nCutNum < GIA_MAX_CUTNUM ); + // prepare references + Gia_ManForEachObj( p->pGia, pObj, iObj ) + Gia_StoRefObj( p, iObj ); + // compute cuts + Gia_StoComputeCutsConst0( p, 0 ); + Gia_ManForEachCiId( p->pGia, iObj, i ) + Gia_StoComputeCutsCi( p, iObj ); + Gia_ManForEachAnd( p->pGia, pObj, iObj ) + Gia_StoComputeCutsNode( p, iObj ); + if ( p->fVerbose ) + { + printf( "Running cut computation with CutSize = %d CutNum = %d CutMin = %s TruthMin = %s\n", + p->nCutSize, p->nCutNum, p->fCutMin ? "yes":"no", p->fTruthMin ? "yes":"no" ); + printf( "CutPair = %.0f ", p->CutCount[0] ); + printf( "Merge = %.0f (%.2f %%) ", p->CutCount[1], 100.0*p->CutCount[1]/p->CutCount[0] ); + printf( "Eval = %.0f (%.2f %%) ", p->CutCount[2], 100.0*p->CutCount[2]/p->CutCount[0] ); + printf( "Cut = %.0f (%.2f %%) ", p->CutCount[3], 100.0*p->CutCount[3]/p->CutCount[0] ); + printf( "Cut/Node = %.2f ", p->CutCount[3] / Gia_ManAndNum(p->pGia) ); + printf( "\n" ); + printf( "The number of nodes with cut count over the limit (%d cuts) = %d nodes (out of %d). ", + p->nCutNum, p->nCutsOver, Gia_ManAndNum(pGia) ); + Abc_PrintTime( 0, "Time", Abc_Clock() - p->clkStart ); + } + Gia_StoFree( p ); +} + + +/**Function************************************************************* + + Synopsis [Extract a given number of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_StoSelectOneCut( Vec_Wec_t * vCuts, int iObj, Vec_Int_t * vCut, int nCutSizeMin ) +{ + Vec_Int_t * vThis = Vec_WecEntry( vCuts, iObj ); + int i, v, * pCut, * pList = Vec_IntArray( vThis ); + if ( pList == NULL ) + return 0; + Vec_IntClear( vCut ); + Sdb_ForEachCut( pList, pCut, i ) + { + if ( pCut[0] < nCutSizeMin ) + continue; + for ( v = 0; v <= pCut[0]; v++ ) + Vec_IntPush( vCut, pCut[v] ); + return 1; + } + return 0; +} +Vec_Wec_t * Gia_ManSelectCuts( Vec_Wec_t * vCuts, int nCuts, int nCutSizeMin ) +{ + Vec_Wec_t * vCutsSel = Vec_WecStart( nCuts ); + int i; srand( time(NULL) ); + for ( i = 0; i < nCuts; i++ ) + while ( !Gia_StoSelectOneCut(vCuts, (rand() | (rand() << 15)) % Vec_WecSize(vCuts), Vec_WecEntry(vCutsSel, i), nCutSizeMin) ); + return vCutsSel; +} +Vec_Wec_t * Gia_ManExtractCuts( Gia_Man_t * pGia, int nCutSize0, int nCuts0, int fVerbose0 ) +{ + int nCutSize = nCutSize0; + int nCutNum = 6; + int fCutMin = 0; + int fTruthMin = 0; + int fVerbose = fVerbose0; + Vec_Wec_t * vCutsSel; + Gia_Sto_t * p = Gia_StoAlloc( pGia, nCutSize, nCutNum, fCutMin, fTruthMin, fVerbose ); + Gia_Obj_t * pObj; int i, iObj; + assert( nCutSize <= GIA_MAX_CUTSIZE ); + assert( nCutNum < GIA_MAX_CUTNUM ); + // prepare references + Gia_ManForEachObj( p->pGia, pObj, iObj ) + Gia_StoRefObj( p, iObj ); + // compute cuts + Gia_StoComputeCutsConst0( p, 0 ); + Gia_ManForEachCiId( p->pGia, iObj, i ) + Gia_StoComputeCutsCi( p, iObj ); + Gia_ManForEachAnd( p->pGia, pObj, iObj ) + Gia_StoComputeCutsNode( p, iObj ); + if ( p->fVerbose ) + { + printf( "Running cut computation with CutSize = %d CutNum = %d CutMin = %s TruthMin = %s\n", + p->nCutSize, p->nCutNum, p->fCutMin ? "yes":"no", p->fTruthMin ? "yes":"no" ); + printf( "CutPair = %.0f ", p->CutCount[0] ); + printf( "Merge = %.0f (%.2f %%) ", p->CutCount[1], 100.0*p->CutCount[1]/p->CutCount[0] ); + printf( "Eval = %.0f (%.2f %%) ", p->CutCount[2], 100.0*p->CutCount[2]/p->CutCount[0] ); + printf( "Cut = %.0f (%.2f %%) ", p->CutCount[3], 100.0*p->CutCount[3]/p->CutCount[0] ); + printf( "Cut/Node = %.2f ", p->CutCount[3] / Gia_ManAndNum(p->pGia) ); + printf( "\n" ); + printf( "The number of nodes with cut count over the limit (%d cuts) = %d nodes (out of %d). ", + p->nCutNum, p->nCutsOver, Gia_ManAndNum(pGia) ); + Abc_PrintTime( 0, "Time", Abc_Clock() - p->clkStart ); + } + vCutsSel = Gia_ManSelectCuts( p->vCuts, nCuts0, nCutSize0-1 ); + Gia_StoFree( p ); + return vCutsSel; +} +void Gia_ManCreateWins( Gia_Man_t * pGia, Vec_Wec_t * vCuts ) +{ + Gia_Obj_t * pObj; + Vec_Wec_t * vWins = Vec_WecStart( Gia_ManObjNum(pGia) ); + Vec_Int_t * vTemp = Vec_IntAlloc( 100 ); + Vec_Int_t * vCut; int i, k, Obj, Cut; + Vec_WecForEachLevel( vCuts, vCut, i ) + Vec_IntForEachEntryStart( vCut, Obj, k, 1 ) + Vec_IntPush( Vec_WecEntry(vWins, Obj), i ); + Gia_ManForEachAnd( pGia, pObj, Obj ) + { + Vec_Int_t * vWin = Vec_WecEntry(vWins, Obj); + Vec_Int_t * vWin0 = Vec_WecEntry(vWins, Gia_ObjFaninId0(pObj, Obj)); + Vec_Int_t * vWin1 = Vec_WecEntry(vWins, Gia_ObjFaninId1(pObj, Obj)); + Vec_IntTwoFindCommon( vWin0, vWin1, vTemp ); + Vec_IntForEachEntry( vTemp, Cut, k ) + { + Vec_IntPushUniqueOrder( vWin, Cut ); + Vec_IntPush( Vec_WecEntry(vCuts, Cut), Obj ); + } + } + Vec_WecFree( vWins ); + Vec_IntFree( vTemp ); +} +void Gia_ManPrintWins( Vec_Wec_t * vCuts ) +{ + Vec_Int_t * vCut; int i, k, Obj; + Vec_WecForEachLevel( vCuts, vCut, i ) + { + int nInputs = Vec_IntEntry(vCut, 0); + printf( "Cut %5d : ", i ); + printf( "Supp = %d ", nInputs ); + printf( "Nodes = %d ", Vec_IntSize(vCut) - 1 - nInputs ); + Vec_IntForEachEntryStartStop( vCut, Obj, k, 1, nInputs+1 ) + printf( "%d ", Obj ); + printf( " " ); + Vec_IntForEachEntryStart( vCut, Obj, k, nInputs+1 ) + printf( "%d ", Obj ); + printf( "\n" ); + } +} +void Gia_ManPrintWinStats( Vec_Wec_t * vCuts ) +{ + Vec_Int_t * vCut; int i, nInputs = 0, nNodes = 0; + Vec_WecForEachLevel( vCuts, vCut, i ) + { + nInputs += Vec_IntEntry(vCut, 0); + nNodes += Vec_IntSize(vCut) - 1 - Vec_IntEntry(vCut, 0); + } + printf( "Computed %d windows with average support %.3f and average volume %.3f.\n", + Vec_WecSize(vCuts), 1.0*nInputs/Vec_WecSize(vCuts), 1.0*nNodes/Vec_WecSize(vCuts) ); +} +void Gia_ManExtractTest( Gia_Man_t * pGia ) +{ + extern Vec_Wec_t * Gia_ManExtractCuts2( Gia_Man_t * p, int nCutSize, int nCuts, int fVerbose ); + Vec_Wec_t * vCutsSel = Gia_ManExtractCuts2( pGia, 8, 10000, 1 ); + //Vec_Wec_t * vCutsSel = Gia_ManExtractCuts( pGia, 8, 10000, 1 ); + abctime clk = Abc_Clock(); + Gia_ManCreateWins( pGia, vCutsSel ); + //Gia_ManPrintWins( vCutsSel ); + Gia_ManPrintWinStats( vCutsSel ); + Vec_WecFree( vCutsSel ); + Abc_PrintTime( 0, "Creating windows", Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [Extract a given number of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_StoCutPrint( int * pCut ) +{ + int v; + printf( "{" ); + for ( v = 1; v <= pCut[0]; v++ ) + printf( " %d", pCut[v] ); + printf( " }\n" ); +} +void Gia_StoPrintCuts( Vec_Int_t * vThis, int iObj, int nCutSize ) +{ + int i, * pCut; + printf( "Cuts of node %d (size = %d):\n", iObj, nCutSize ); + Sdb_ForEachCut( Vec_IntArray(vThis), pCut, i ) + if ( !nCutSize || pCut[0] == nCutSize ) + Gia_StoCutPrint( pCut ); +} +Vec_Wec_t * Gia_ManFilterCuts( Gia_Man_t * pGia, Vec_Wec_t * vStore, int nCutSize, int nCuts ) +{ + abctime clkStart = Abc_Clock(); + Vec_Wec_t * vCutsSel = Vec_WecAlloc( nCuts ); + Vec_Int_t * vLevel, * vCut = Vec_IntAlloc( 10 ); + Vec_Wec_t * vCuts = Vec_WecAlloc( 1000 ); + Hsh_VecMan_t * p = Hsh_VecManStart( 1000 ); int i, s; + Vec_WecForEachLevel( vStore, vLevel, i ) if ( Vec_IntSize(vLevel) ) + { + int v, k, * pCut, Value; + Sdb_ForEachCut( Vec_IntArray(vLevel), pCut, k ) + { + if ( pCut[0] < 2 ) + continue; + + for ( v = 1; v <= pCut[0]; v++ ) + if ( pCut[v] < 9 ) + break; + if ( v <= pCut[0] ) + continue; + + Vec_IntClear( vCut ); + Vec_IntPushArray( vCut, pCut+1, pCut[0] ); + Value = Hsh_VecManAdd( p, vCut ); + if ( Value == Vec_WecSize(vCuts) ) + { + Vec_Int_t * vTemp = Vec_WecPushLevel(vCuts); + Vec_IntPush( vTemp, 0 ); + Vec_IntAppend( vTemp, vCut ); + } + Vec_IntAddToEntry( Vec_WecEntry(vCuts, Value), 0, 1 ); + } + } + printf( "Collected cuts = %d.\n", Vec_WecSize(vCuts) ); + for ( s = 3; s <= nCutSize; s++ ) + Vec_WecForEachLevel( vCuts, vLevel, i ) + if ( Vec_IntSize(vLevel) - 1 == s ) + { + int * pCut = Vec_IntEntryP(vLevel, 1); + int u, v, Value; + for ( u = 0; u < s; u++ ) + { + Vec_IntClear( vCut ); + for ( v = 0; v < s; v++ ) if ( v != u ) + Vec_IntPush( vCut, pCut[v] ); + assert( Vec_IntSize(vCut) == s-1 ); + Value = Hsh_VecManAdd( p, vCut ); + if ( Value < Vec_WecSize(vCuts) ) + Vec_IntAddToEntry( vLevel, 0, Vec_IntEntry(Vec_WecEntry(vCuts, Value), 0) ); + } + } + Hsh_VecManStop( p ); + Vec_IntFree( vCut ); + // collect + Vec_WecSortByFirstInt( vCuts, 1 ); + Vec_WecForEachLevelStop( vCuts, vLevel, i, Abc_MinInt(Vec_WecSize(vCuts), nCuts) ) + Vec_IntAppend( Vec_WecPushLevel(vCutsSel), vLevel ); + Abc_PrintTime( 0, "Cut filtering time", Abc_Clock() - clkStart ); + return vCutsSel; +} +int Gia_ManCountRefs( Gia_Man_t * pGia, Vec_Int_t * vLevel ) +{ + int i, iObj, nRefs = 0; + Vec_IntForEachEntry( vLevel, iObj, i ) + nRefs += Gia_ObjRefNumId(pGia, iObj); + return nRefs; +} +Vec_Wrd_t * Gia_ManGenSims( Gia_Man_t * pGia ) +{ + Vec_Wrd_t * vSims; + Vec_WrdFreeP( &pGia->vSimsPi ); + pGia->vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(pGia) ); + vSims = Gia_ManSimPatSim( pGia ); + return vSims; +} +int Gia_ManFindSatDcs( Gia_Man_t * pGia, Vec_Wrd_t * vSims, Vec_Int_t * vLevel ) +{ + int nWords = Vec_WrdSize(pGia->vSimsPi) / Gia_ManCiNum(pGia); + int i, w, iObj, Res = 0, Pres[256] = {0}, nMints = 1 << Vec_IntSize(vLevel); + for ( w = 0; w < 64*nWords; w++ ) + { + int iInMint = 0; + Vec_IntForEachEntry( vLevel, iObj, i ) + if ( Abc_TtGetBit( Vec_WrdEntryP(vSims, iObj*nWords), w ) ) + iInMint |= 1 << i; + Pres[iInMint]++; + } + for ( i = 0; i < nMints; i++ ) + Res += Pres[i] == 0; + return Res; +} + + +int Gia_ManCollectCutDivs( Gia_Man_t * p, Vec_Int_t * vIns ) +{ + Gia_Obj_t * pObj; int i, Res = 0; + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); + Vec_IntSort( vIns, 0 ); + + Vec_IntPush( vRes, 0 ); + Vec_IntAppend( vRes, vIns ); + + Gia_ManIncrementTravId( p ); + Gia_ManIncrementTravId( p ); + Gia_ManForEachObjVec( vIns, p, pObj, i ) + Gia_ObjSetTravIdCurrent( p, pObj ); + + Gia_ManForEachAnd( p, pObj, i ) + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + continue; + else if ( Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pObj)) && Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pObj)) ) + { + if ( !Gia_ObjIsTravIdPrevious(p, pObj) ) + Vec_IntPush( vRes, i ); + Gia_ObjSetTravIdCurrent( p, pObj ); + } +// printf( "Divisors: " ); +// Vec_IntPrint( vRes ); + Res = Vec_IntSize(vRes); + Vec_IntFree( vRes ); + return Res; +} + +void Gia_ManConsiderCuts( Gia_Man_t * pGia, Vec_Wec_t * vCuts ) +{ + Vec_Wrd_t * vSims = Gia_ManGenSims( pGia ); + Vec_Int_t * vLevel; int i; + Gia_ManCreateRefs( pGia ); + Vec_WecForEachLevel( vCuts, vLevel, i ) + { + printf( "Cut %3d ", i ); + printf( "Ref = %3d : ", Vec_IntEntry(vLevel, 0) ); + + Vec_IntShift( vLevel, 1 ); + printf( "Ref = %3d : ", Gia_ManCountRefs(pGia, vLevel) ); + printf( "SDC = %3d : ", Gia_ManFindSatDcs(pGia, vSims, vLevel) ); + printf( "Div = %3d : ", Gia_ManCollectCutDivs(pGia, vLevel) ); + Vec_IntPrint( vLevel ); + Vec_IntShift( vLevel, -1 ); + } + Vec_WrdFree( vSims ); +} + + +Vec_Wec_t * Gia_ManExploreCuts( Gia_Man_t * pGia, int nCutSize0, int nCuts0, int fVerbose0 ) +{ + int nCutSize = nCutSize0; + int nCutNum = 64; + int fCutMin = 0; + int fTruthMin = 0; + int fVerbose = fVerbose0; + Vec_Wec_t * vCutsSel; + Gia_Sto_t * p = Gia_StoAlloc( pGia, nCutSize, nCutNum, fCutMin, fTruthMin, fVerbose ); + Gia_Obj_t * pObj; int i, iObj; + assert( nCutSize <= GIA_MAX_CUTSIZE ); + assert( nCutNum < GIA_MAX_CUTNUM ); + // prepare references + Gia_ManForEachObj( p->pGia, pObj, iObj ) + Gia_StoRefObj( p, iObj ); + // compute cuts + Gia_StoComputeCutsConst0( p, 0 ); + Gia_ManForEachCiId( p->pGia, iObj, i ) + Gia_StoComputeCutsCi( p, iObj ); + Gia_ManForEachAnd( p->pGia, pObj, iObj ) + Gia_StoComputeCutsNode( p, iObj ); + if ( p->fVerbose ) + { + printf( "Running cut computation with CutSize = %d CutNum = %d CutMin = %s TruthMin = %s\n", + p->nCutSize, p->nCutNum, p->fCutMin ? "yes":"no", p->fTruthMin ? "yes":"no" ); + printf( "CutPair = %.0f ", p->CutCount[0] ); + printf( "Merge = %.0f (%.2f %%) ", p->CutCount[1], 100.0*p->CutCount[1]/p->CutCount[0] ); + printf( "Eval = %.0f (%.2f %%) ", p->CutCount[2], 100.0*p->CutCount[2]/p->CutCount[0] ); + printf( "Cut = %.0f (%.2f %%) ", p->CutCount[3], 100.0*p->CutCount[3]/p->CutCount[0] ); + printf( "Cut/Node = %.2f ", p->CutCount[3] / Gia_ManAndNum(p->pGia) ); + printf( "\n" ); + printf( "The number of nodes with cut count over the limit (%d cuts) = %d nodes (out of %d). ", + p->nCutNum, p->nCutsOver, Gia_ManAndNum(pGia) ); + Abc_PrintTime( 0, "Time", Abc_Clock() - p->clkStart ); + } + vCutsSel = Gia_ManFilterCuts( pGia, p->vCuts, nCutSize0, nCuts0 ); + //Gia_ManConsiderCuts( pGia, vCutsSel ); + Gia_StoFree( p ); + return vCutsSel; +} +void Gia_ManExploreCutsTest( Gia_Man_t * pGia, int nCutSize0, int nCuts0, int fVerbose0 ) +{ + Vec_Wec_t * vCutSel = Gia_ManExploreCuts( pGia, nCutSize0, nCuts0, fVerbose0 ); + Vec_WecPrint( vCutSel, 0 ); + Vec_WecFree( vCutSel ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Sto_t * Gia_ManMatchCutsInt( Gia_Man_t * pGia, int nCutSize0, int nCutNum0, int fVerbose0 ) +{ + int nCutSize = nCutSize0; + int nCutNum = nCutNum0; + int fCutMin = 1; + int fTruthMin = 1; + int fVerbose = fVerbose0; + Gia_Sto_t * p = Gia_StoAlloc( pGia, nCutSize, nCutNum, fCutMin, fTruthMin, fVerbose ); + Gia_Obj_t * pObj; int i, iObj; + assert( nCutSize <= GIA_MAX_CUTSIZE ); + assert( nCutNum < GIA_MAX_CUTNUM ); + // prepare references + Gia_ManForEachObj( p->pGia, pObj, iObj ) + Gia_StoRefObj( p, iObj ); + // compute cuts + Gia_StoComputeCutsConst0( p, 0 ); + Gia_ManForEachCiId( p->pGia, iObj, i ) + Gia_StoComputeCutsCi( p, iObj ); + Gia_ManForEachAnd( p->pGia, pObj, iObj ) + Gia_StoComputeCutsNode( p, iObj ); + if ( p->fVerbose ) + { + printf( "Running cut computation with CutSize = %d CutNum = %d CutMin = %s TruthMin = %s\n", + p->nCutSize, p->nCutNum, p->fCutMin ? "yes":"no", p->fTruthMin ? "yes":"no" ); + printf( "CutPair = %.0f ", p->CutCount[0] ); + printf( "Merge = %.0f (%.2f %%) ", p->CutCount[1], 100.0*p->CutCount[1]/p->CutCount[0] ); + printf( "Eval = %.0f (%.2f %%) ", p->CutCount[2], 100.0*p->CutCount[2]/p->CutCount[0] ); + printf( "Cut = %.0f (%.2f %%) ", p->CutCount[3], 100.0*p->CutCount[3]/p->CutCount[0] ); + printf( "Cut/Node = %.2f ", p->CutCount[3] / Gia_ManAndNum(p->pGia) ); + printf( "\n" ); + printf( "The number of nodes with cut count over the limit (%d cuts) = %d nodes (out of %d). ", + p->nCutNum, p->nCutsOver, Gia_ManAndNum(pGia) ); + Abc_PrintTime( 0, "Time", Abc_Clock() - p->clkStart ); + } + return p; +} +void Gia_ManMatchCuts( Vec_Mem_t * vTtMem, Gia_Man_t * pGia, int nCutSize, int nCutNum, int fVerbose ) +{ + Gia_Sto_t * p = Gia_ManMatchCutsInt( pGia, nCutSize, nCutNum, fVerbose ); + Vec_Int_t * vLevel; int i, j, k, * pCut; + Vec_Int_t * vNodes = Vec_IntAlloc( 100 ); + Vec_Wec_t * vCuts = Vec_WecAlloc( 100 ); + abctime clkStart = Abc_Clock(); + assert( Abc_Truth6WordNum(nCutSize) == Vec_MemEntrySize(vTtMem) ); + Vec_WecForEachLevel( p->vCuts, vLevel, i ) if ( Vec_IntSize(vLevel) ) + { + Sdb_ForEachCut( Vec_IntArray(vLevel), pCut, k ) if ( pCut[0] > 1 ) + { + word * pTruth = Vec_MemReadEntry( p->vTtMem, Abc_Lit2Var(pCut[pCut[0]+1]) ); + int * pSpot = Vec_MemHashLookup( vTtMem, pTruth ); + if ( *pSpot == -1 ) + continue; + Vec_IntPush( vNodes, i ); + vLevel = Vec_WecPushLevel( vCuts ); + Vec_IntPush( vLevel, i ); + for ( j = 1; j <= pCut[0]; j++ ) + Vec_IntPush( vLevel, pCut[j] ); + break; + } + } + printf( "Nodes with matching cuts: " ); + Vec_IntPrint( vNodes ); + if ( Vec_WecSize(vCuts) > 32 ) + Vec_WecShrink(vCuts, 32); + Vec_WecPrint( vCuts, 0 ); + Vec_WecFree( vCuts ); + Vec_IntFree( vNodes ); + Gia_StoFree( p ); + if ( fVerbose ) + Abc_PrintTime( 1, "Cut matching time", Abc_Clock() - clkStart ); +} +Vec_Ptr_t * Gia_ManMatchCutsArray( Vec_Ptr_t * vTtMems, Gia_Man_t * pGia, int nCutSize, int nCutNum, int fVerbose ) +{ + Vec_Ptr_t * vRes = Vec_PtrAlloc( Vec_PtrSize(vTtMems) ); + Gia_Sto_t * p = Gia_ManMatchCutsInt( pGia, nCutSize, nCutNum, fVerbose ); + Vec_Int_t * vLevel, * vTemp; int i, k, c, * pCut; + abctime clkStart = Abc_Clock(); + for ( i = 0; i < Vec_PtrSize(vTtMems); i++ ) + Vec_PtrPush( vRes, Vec_WecAlloc(100) ); + Vec_WecForEachLevel( p->vCuts, vLevel, i ) if ( Vec_IntSize(vLevel) ) + { + Sdb_ForEachCut( Vec_IntArray(vLevel), pCut, k ) if ( pCut[0] > 1 ) + { + Vec_Mem_t * vTtMem; int m; + Vec_PtrForEachEntry( Vec_Mem_t *, vTtMems, vTtMem, m ) + { + word * pTruth = Vec_MemReadEntry( p->vTtMem, Abc_Lit2Var(pCut[pCut[0]+1]) ); + int * pSpot = Vec_MemHashLookup( vTtMem, pTruth ); + if ( *pSpot == -1 ) + continue; + vTemp = Vec_WecPushLevel( (Vec_Wec_t *)Vec_PtrEntry(vRes, m) ); + Vec_IntPush( vTemp, i ); + for ( c = 1; c <= pCut[0]; c++ ) + Vec_IntPush( vTemp, pCut[c] ); + } + } + } + Gia_StoFree( p ); + if ( fVerbose ) { + Vec_Wec_t * vCuts; + printf( "Detected nodes by type: " ); + Vec_PtrForEachEntry( Vec_Wec_t *, vRes, vCuts, i ) + printf( "Type%d = %d ", i, Vec_WecSize(vCuts) ); + Abc_PrintTime( 1, "Cut matching time", Abc_Clock() - clkStart ); + } + return vRes; +} +Vec_Ptr_t * Gia_ManMatchCutsMany( Vec_Mem_t * vTtMem, Vec_Int_t * vMap, int nFuncs, Gia_Man_t * pGia, int nCutSize, int nCutNum, int fVerbose ) +{ + Gia_Sto_t * p = Gia_ManMatchCutsInt( pGia, nCutSize, nCutNum, fVerbose ); + Vec_Int_t * vLevel; int i, j, k, * pCut; + abctime clkStart = Abc_Clock(); + assert( Abc_Truth6WordNum(nCutSize) == Vec_MemEntrySize(vTtMem) ); + Vec_Ptr_t * vRes = Vec_PtrAlloc( nFuncs ); + for ( i = 0; i < nFuncs; i++ ) + Vec_PtrPush( vRes, Vec_WecAlloc(10) ); + Vec_WecForEachLevel( p->vCuts, vLevel, i ) if ( Vec_IntSize(vLevel) ) + { + Sdb_ForEachCut( Vec_IntArray(vLevel), pCut, k ) if ( pCut[0] > 1 ) + { + word * pTruth = Vec_MemReadEntry( p->vTtMem, Abc_Lit2Var(pCut[pCut[0]+1]) ); + assert( (pTruth[0] & 1) == 0 ); + int * pSpot = Vec_MemHashLookup( vTtMem, pTruth ); + if ( *pSpot == -1 ) + continue; + int iFunc = vMap ? Vec_IntEntry( vMap, *pSpot ) : 0; + assert( iFunc < nFuncs ); + Vec_Wec_t * vCuts = (Vec_Wec_t *)Vec_PtrEntry( vRes, iFunc ); + vLevel = Vec_WecPushLevel( vCuts ); + Vec_IntPush( vLevel, i ); + for ( j = 1; j <= pCut[0]; j++ ) + Vec_IntPush( vLevel, pCut[j] ); + break; + } + } + Gia_StoFree( p ); + if ( fVerbose ) + Abc_PrintTime( 1, "Cut matching time", Abc_Clock() - clkStart ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [Function enumeration.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wrd_t * Gia_ManCollectCutFuncs( Gia_Man_t * p, int nCutSize, int nCutNum, int fVerbose ) +{ + Gia_Sto_t * pSto = Gia_ManMatchCutsInt( p, nCutSize, nCutNum, 0 ); + Vec_Wrd_t * vFuncs = Vec_WrdAlloc( 1000 ); Vec_Int_t * vLevel; int i, k, * pCut; + Vec_WecForEachLevel( pSto->vCuts, vLevel, i ) if ( Vec_IntSize(vLevel) ) + Sdb_ForEachCut( Vec_IntArray(vLevel), pCut, k ) if ( pCut[0] == nCutSize ) { + word * pTruth = Vec_MemReadEntry( pSto->vTtMem, Abc_Lit2Var(pCut[pCut[0]+1]) ); + Vec_WrdPush( vFuncs, pTruth[0] ); + } + Gia_StoFree( pSto ); + if ( fVerbose ) + printf( "Collected %d cut functions using the AIG with %d nodes.\n", Vec_WrdSize(vFuncs), Gia_ManAndNum(p) ); + return vFuncs; +} +Vec_Int_t * Gia_ManCountNpnClasses( Vec_Mem_t * vTtMem, Vec_Int_t * vMap, int nClasses, Vec_Wrd_t * vOrig ) +{ + assert( Vec_MemEntryNum(vTtMem) == Vec_IntSize(vMap) ); + Vec_Int_t * vClassCounts = Vec_IntStart( nClasses ); int i; word Func; + Vec_WrdForEachEntry( vOrig, Func, i ) { + int * pSpot = Vec_MemHashLookup( vTtMem, &Func ); + if ( *pSpot == -1 ) + continue; + int iClass = Vec_IntEntry( vMap, *pSpot ); + if ( iClass == -1 ) + continue; + assert( iClass < Vec_IntSize(vClassCounts) ); + Vec_IntAddToEntry( vClassCounts, iClass, 1 ); + } + return vClassCounts; +} +Vec_Wrd_t * Gia_ManMatchFilterClasses( Vec_Mem_t * vTtMem, Vec_Int_t * vMap, Vec_Int_t * vClassCounts, int nNumFuncs, int fVerbose ) +{ + int * pPerm = Abc_MergeSortCost( Vec_IntArray(vClassCounts), Vec_IntSize(vClassCounts) ); + Vec_Wrd_t * vBest = Vec_WrdAlloc( nNumFuncs ); int i, k, Entry; + Vec_Int_t * vMapNew = Vec_IntStartFull( Vec_IntSize(vMap) ); + for ( i = Vec_IntSize(vClassCounts)-1; i >= 0; i-- ) { + word Best = ~(word)0; + Vec_IntForEachEntry( vMap, Entry, k ) { + if ( Entry != pPerm[i] ) + continue; + if ( Best > Vec_MemReadEntry(vTtMem, k)[0] ) + Best = Vec_MemReadEntry(vTtMem, k)[0]; + Vec_IntWriteEntry( vMapNew, k, Vec_WrdSize(vBest) ); + } + Vec_WrdPush( vBest, Best ); + assert( ~Best ); + if ( Vec_WrdSize(vBest) == nNumFuncs ) + break; + } + ABC_SWAP( Vec_Int_t, *vMap, *vMapNew ); + Vec_IntFree( vMapNew ); + ABC_FREE( pPerm ); + if ( fVerbose ) + printf( "Isolated %d (out of %d) most frequently occuring classes.\n", Vec_WrdSize(vBest), Vec_IntSize(vClassCounts) ); + return vBest; +} +void Gia_ManMatchProfileFunctions( Vec_Wrd_t * vBestReprs, Vec_Mem_t * vTtMem, Vec_Int_t * vMap, Vec_Wrd_t * vFuncs, int nCutSize ) +{ + int BarSize = 60; + extern void Dau_DsdPrintFromTruth( word * pTruth, int nVarsInit ); + Vec_Int_t * vCounts = Gia_ManCountNpnClasses( vTtMem, vMap, Vec_WrdSize(vBestReprs), vFuncs ); + word Repr; int c, i, MaxCount = Vec_IntFindMax( vCounts ); + Vec_WrdForEachEntry( vBestReprs, Repr, c ) + { + int nSymb = BarSize*Vec_IntEntry(vCounts, c)/Abc_MaxInt(MaxCount, 1); + printf( "Class%4d : ", c ); + printf( "Count =%6d ", Vec_IntEntry(vCounts, c) ); + for ( i = 0; i < nSymb; i++ ) + printf( "*" ); + for ( i = nSymb; i < BarSize+3; i++ ) + printf( " " ); + Dau_DsdPrintFromTruth( &Repr, nCutSize ); + } + Vec_IntFree( vCounts ); +} +void Gia_ManMatchCones( Gia_Man_t * pBig, Gia_Man_t * pSmall, int nCutSize, int nCutNum, int nNumFuncs, int nNumCones, int fVerbose ) +{ + abctime clkStart = Abc_Clock(); + extern void Dau_CanonicizeArray( Vec_Wrd_t * vFuncs, int nVars, int fVerbose ); + extern Vec_Mem_t * Dau_CollectNpnFunctionsArray( Vec_Wrd_t * vFuncs, int nVars, Vec_Int_t ** pvMap, int fVerbose ); + Vec_Wrd_t * vFuncs = Gia_ManCollectCutFuncs( pSmall, nCutSize, nCutNum, fVerbose ); + Vec_Wrd_t * vOrig = Vec_WrdDup( vFuncs ); + Dau_CanonicizeArray( vFuncs, nCutSize, fVerbose ); + Vec_Int_t * vMap = NULL; int n; + Vec_Mem_t * vTtMem = Dau_CollectNpnFunctionsArray( vFuncs, nCutSize, &vMap, fVerbose ); + Vec_WrdFree( vFuncs ); + Vec_Int_t * vClassCounts = Gia_ManCountNpnClasses( vTtMem, vMap, Vec_IntEntryLast(vMap)+1, vOrig ); + Vec_Wrd_t * vBestReprs = Gia_ManMatchFilterClasses( vTtMem, vMap, vClassCounts, nNumFuncs, fVerbose ); + assert( Vec_WrdSize(vBestReprs) == nNumFuncs ); + Vec_IntFree( vClassCounts ); + printf( "Frequency profile for %d most popular classes in the small AIG:\n", nNumFuncs ); + Gia_ManMatchProfileFunctions( vBestReprs, vTtMem, vMap, vOrig, nCutSize ); + Vec_WrdFree( vOrig ); + Abc_Random( 1 ); + for ( n = 0; n < nNumCones; n++ ) { + int nRand = Abc_Random( 0 ) % Gia_ManCoNum(pBig); + Gia_Man_t * pCone = Gia_ManDupCones( pBig, &nRand, 1, 1 ); + Vec_Wrd_t * vCutFuncs = Gia_ManCollectCutFuncs( pCone, nCutSize, nCutNum, 0 ); + printf( "ITER %d: Considering output cone %d with %d and-nodes. ", n+1, nRand, Gia_ManAndNum(pCone) ); + printf( "Profiling %d functions of %d-cuts:\n", Vec_WrdSize(vCutFuncs), nCutSize ); + Gia_ManMatchProfileFunctions( vBestReprs, vTtMem, vMap, vCutFuncs, nCutSize ); + Vec_WrdFree( vCutFuncs ); + Gia_ManStop( pCone ); + } + Vec_WrdFree( vBestReprs ); + Vec_IntFree( vMap ); + Vec_MemHashFree( vTtMem ); + Vec_MemFree( vTtMem ); + Abc_PrintTime( 1, "Total computation time", Abc_Clock() - clkStart ); +} + +/**Function************************************************************* + + Synopsis [Function enumeration.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManMatchConesMinimizeTts( Vec_Wrd_t * vSims, int nVarsMax ) +{ + int nVars = 0; + int nWordsMax = Abc_Truth6WordNum( nVarsMax ), nWords; + int i, k = 0, nTruths = Vec_WrdSize(vSims) / nWordsMax; + assert( nTruths * nWordsMax == Vec_WrdSize(vSims) ); + // support-minimize and find the largest supp size + for ( i = 0; i < nTruths; i++ ) { + word * pTruth = Vec_WrdEntryP( vSims, i * nWordsMax ); + int nVarsCur = Abc_TtMinBase( pTruth, NULL, nVarsMax, nVarsMax ); + nVars = Abc_MaxInt( nVars, nVarsCur ); + } + // remap truth tables + nWords = Abc_Truth6WordNum( nVars ); + for ( i = 0; i < nTruths; i++ ) { + word * pTruth = Vec_WrdEntryP( vSims, i * nWordsMax ); + word * pTruth2 = Vec_WrdEntryP( vSims, k * nWords ); + if ( Abc_TtSupportSize(pTruth, nVars) < 3 ) + continue; + memmove( pTruth2, pTruth, nWords * sizeof(word) ); + k++; + if ( 0 ) { + extern void Extra_PrintHexadecimal( FILE * pFile, unsigned Sign[], int nVars ); + printf( "Type%d : ", i ); + Extra_PrintHexadecimal( stdout, (unsigned *)pTruth2, nVars ); + printf( "\n" ); + } + } + Vec_WrdShrink ( vSims, k * nWords ); + return nVars; +} +void Gia_ManMatchConesOutputPrint( Vec_Ptr_t * p, int fVerbose ) +{ + Vec_Wec_t * vCuts; int i; + printf( "Nodes with matching cuts:\n" ); + Vec_PtrForEachEntry( Vec_Wec_t *, p, vCuts, i ) { + if ( fVerbose ) { + printf( "Type %d:\n", i ); + Vec_WecPrint( vCuts, 0 ); + } + else + printf( "Type %d present in %d cuts\n", i, Vec_WecSize(vCuts) ); + } +} +void Gia_ManMatchConesOutputFree( Vec_Ptr_t * p ) +{ + Vec_Wec_t * vCuts; int i; + Vec_PtrForEachEntry( Vec_Wec_t *, p, vCuts, i ) + Vec_WecFree( vCuts ); + Vec_PtrFree( p ); +} +void Gia_ManMatchConesOutput( Gia_Man_t * pBig, Gia_Man_t * pSmall, int nCutNum, int fVerbose ) +{ + abctime clkStart = Abc_Clock(); + extern Vec_Mem_t * Dau_CollectNpnFunctionsArray( Vec_Wrd_t * vFuncs, int nVars, Vec_Int_t ** pvMap, int fVerbose ); + Vec_Wrd_t * vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(pSmall) ); + Vec_Wrd_t * vSims = Gia_ManSimPatSimOut( pSmall, vSimsPi, 1 ); + int nVars = Gia_ManMatchConesMinimizeTts( vSims, Gia_ManCiNum(pSmall) ); + Vec_WrdFree( vSimsPi ); + if ( nVars > 10 ) { + printf( "Some output functions have support size more than 10.\n" ); + Vec_WrdFree( vSims ); + return; + } + Vec_Int_t * vMap = NULL; + Vec_Mem_t * vTtMem = Dau_CollectNpnFunctionsArray( vSims, nVars, &vMap, fVerbose ); + int nFuncs = Vec_WrdSize(vSims) / Abc_Truth6WordNum(nVars); + assert( Vec_WrdSize(vSims) == nFuncs * Abc_Truth6WordNum(nVars) ); + Vec_WrdFree( vSims ); + printf( "Using %d output functions with the support size between 3 and %d.\n", nFuncs, nVars ); + Vec_Ptr_t * vRes = Gia_ManMatchCutsMany( vTtMem, vMap, nFuncs, pBig, nVars, nCutNum, fVerbose ); + Vec_MemHashFree( vTtMem ); + Vec_MemFree( vTtMem ); + Vec_IntFree( vMap ); + Gia_ManMatchConesOutputPrint( vRes, fVerbose ); + Gia_ManMatchConesOutputFree( vRes ); + Abc_PrintTime( 1, "Total computation time", Abc_Clock() - clkStart ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaDecs.c b/yosys/abc/src/aig/gia/giaDecs.c new file mode 100644 index 00000000000..343891d5ee4 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaDecs.c @@ -0,0 +1,350 @@ +/**CFile**************************************************************** + + FileName [giaDecs.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Calling various decomposition engines.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaDecs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig/gia/gia.h" +#include "misc/util/utilTruth.h" +#include "misc/extra/extra.h" +#include "bool/bdc/bdc.h" +#include "bool/kit/kit.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern void Extra_BitMatrixTransposeP( Vec_Wrd_t * vSimsIn, int nWordsIn, Vec_Wrd_t * vSimsOut, int nWordsOut ); +extern Vec_Int_t * Gia_ManResubOne( Vec_Ptr_t * vDivs, int nWords, int nLimit, int nDivsMax, int iChoice, int fUseXor, int fDebug, int fVerbose, word * pFunc, int Depth ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ResubVarNum( Vec_Int_t * vResub ) +{ + if ( Vec_IntSize(vResub) == 1 ) + return Vec_IntEntryLast(vResub) >= 2; + return Vec_IntEntryLast(vResub)/2 - Vec_IntSize(vResub)/2 - 1; +} +word Gia_ResubToTruth6_rec( Vec_Int_t * vResub, int iNode, int nVars ) +{ + assert( iNode >= 0 && nVars <= 6 ); + if ( iNode < nVars ) + return s_Truths6[iNode]; + else + { + int iLit0 = Vec_IntEntry( vResub, Abc_Var2Lit(iNode-nVars, 0) ); + int iLit1 = Vec_IntEntry( vResub, Abc_Var2Lit(iNode-nVars, 1) ); + word Res0 = Gia_ResubToTruth6_rec( vResub, Abc_Lit2Var(iLit0)-2, nVars ); + word Res1 = Gia_ResubToTruth6_rec( vResub, Abc_Lit2Var(iLit1)-2, nVars ); + Res0 = Abc_LitIsCompl(iLit0) ? ~Res0 : Res0; + Res1 = Abc_LitIsCompl(iLit1) ? ~Res1 : Res1; + return iLit0 > iLit1 ? Res0 ^ Res1 : Res0 & Res1; + } +} +word Gia_ResubToTruth6( Vec_Int_t * vResub ) +{ + word Res; + int iRoot = Vec_IntEntryLast(vResub); + if ( iRoot < 2 ) + return iRoot ? ~(word)0 : 0; + assert( iRoot != 2 && iRoot != 3 ); + Res = Gia_ResubToTruth6_rec( vResub, Abc_Lit2Var(iRoot)-2, Gia_ResubVarNum(vResub) ); + return Abc_LitIsCompl(iRoot) ? ~Res : Res; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wrd_t * Gia_ManDeriveTruths( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * vSet, int nWords ) +{ + int nTtWords = Abc_Truth6WordNum(Vec_IntSize(vSet)); + int nFuncs = Vec_WrdSize(vIsfs) / 2 / nWords; + Vec_Wrd_t * vRes = Vec_WrdStart( 2 * nFuncs * nTtWords ); + Vec_Wrd_t * vIn = Vec_WrdStart( 64*nWords ), * vOut; + int i, f, m, iObj; word Func; + assert( Vec_IntSize(vSet) <= 64 ); + Vec_IntForEachEntry( vSet, iObj, i ) + Abc_TtCopy( Vec_WrdEntryP(vIn, i*nWords), Vec_WrdEntryP(vSims, Vec_IntEntry(vCands, iObj)*nWords), nWords, 0 ); + vOut = Vec_WrdStart( Vec_WrdSize(vIn) ); + Extra_BitMatrixTransposeP( vIn, nWords, vOut, 1 ); + for ( f = 0; f < nFuncs; f++ ) + { + word * pIsf[2] = { Vec_WrdEntryP(vIsfs, (2*f+0)*nWords), + Vec_WrdEntryP(vIsfs, (2*f+1)*nWords) }; + word * pTruth[2] = { Vec_WrdEntryP(vRes, (2*f+0)*nTtWords), + Vec_WrdEntryP(vRes, (2*f+1)*nTtWords) }; + for ( m = 0; m < 64*nWords; m++ ) + { + int iMint = (int)Vec_WrdEntry(vOut, m); + int Value0 = Abc_TtGetBit( pIsf[0], m ); + int Value1 = Abc_TtGetBit( pIsf[1], m ); + if ( !Value0 && !Value1 ) + continue; + if ( Value0 && Value1 ) + printf( "Internal error: Onset and Offset overlap.\n" ); + assert( !Value0 || !Value1 ); + Abc_TtSetBit( pTruth[Value1], iMint ); + } + if ( Abc_TtCountOnesVecMask(pTruth[0], pTruth[1], nTtWords, 0) ) + printf( "Verification for function %d failed for %d minterm pairs.\n", f, + Abc_TtCountOnesVecMask(pTruth[0], pTruth[1], nTtWords, 0) ); + } + if ( Vec_IntSize(vSet) < 6 ) + Vec_WrdForEachEntry( vRes, Func, i ) + Vec_WrdWriteEntry( vRes, i, Abc_Tt6Stretch(Func, Vec_IntSize(vSet)) ); + Vec_WrdFree( vIn ); + Vec_WrdFree( vOut ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCountResub( Vec_Wrd_t * vTruths, int nVars, int fVerbose ) +{ + Vec_Int_t * vResub; int nNodes; + int nTtWords = Abc_Truth6WordNum(nVars); + int v, nFuncs = Vec_WrdSize(vTruths) / 2 / nTtWords; + Vec_Wrd_t * vElems = Vec_WrdStartTruthTables( nVars ); + Vec_Ptr_t * vDivs = Vec_PtrAlloc( 2 + nVars ); + assert( Vec_WrdSize(vElems) == nTtWords * nVars ); + assert( nFuncs == 1 ); + Vec_PtrPush( vDivs, Vec_WrdEntryP(vTruths, (2*0+0)*nTtWords) ); + Vec_PtrPush( vDivs, Vec_WrdEntryP(vTruths, (2*0+1)*nTtWords) ); + for ( v = 0; v < nVars; v++ ) + Vec_PtrPush( vDivs, Vec_WrdEntryP(vElems, v*nTtWords) ); + vResub = Gia_ManResubOne( vDivs, nTtWords, 30, 100, 0, 0, 0, fVerbose, NULL, 0 ); + Vec_PtrFree( vDivs ); + Vec_WrdFree( vElems ); + nNodes = Vec_IntSize(vResub) ? Vec_IntSize(vResub)/2 : 999; + Vec_IntFree( vResub ); + return nNodes; +} +Vec_Int_t * Gia_ManDeriveResub( Vec_Wrd_t * vTruths, int nVars ) +{ + Vec_Int_t * vResub; + int nTtWords = Abc_Truth6WordNum(nVars); + int v, nFuncs = Vec_WrdSize(vTruths) / 2 / nTtWords; + Vec_Wrd_t * vElems = Vec_WrdStartTruthTables( nVars ); + Vec_Ptr_t * vDivs = Vec_PtrAlloc( 2 + nVars ); + assert( Vec_WrdSize(vElems) == nTtWords * nVars ); + assert( nFuncs == 1 ); + Vec_PtrPush( vDivs, Vec_WrdEntryP(vTruths, (2*0+0)*nTtWords) ); + Vec_PtrPush( vDivs, Vec_WrdEntryP(vTruths, (2*0+1)*nTtWords) ); + for ( v = 0; v < nVars; v++ ) + Vec_PtrPush( vDivs, Vec_WrdEntryP(vElems, v*nTtWords) ); + vResub = Gia_ManResubOne( vDivs, nTtWords, 30, 100, 0, 0, 0, 0, NULL, 0 ); + Vec_PtrFree( vDivs ); + Vec_WrdFree( vElems ); + return vResub; +} + +int Gia_ManCountBidec( Vec_Wrd_t * vTruths, int nVars, int fVerbose ) +{ + int nNodes, nTtWords = Abc_Truth6WordNum(nVars); + word * pTruth[2] = { Vec_WrdEntryP(vTruths, 0*nTtWords), + Vec_WrdEntryP(vTruths, 1*nTtWords) }; + Abc_TtOr( pTruth[0], pTruth[0], pTruth[1], nTtWords ); + nNodes = Bdc_ManBidecNodeNum( pTruth[1], pTruth[0], nVars, fVerbose ); + Abc_TtSharp( pTruth[0], pTruth[0], pTruth[1], nTtWords ); + return nNodes; +} +Vec_Int_t * Gia_ManDeriveBidec( Vec_Wrd_t * vTruths, int nVars ) +{ + Vec_Int_t * vRes = NULL; + int nTtWords = Abc_Truth6WordNum(nVars); + word * pTruth[2] = { Vec_WrdEntryP(vTruths, 0*nTtWords), + Vec_WrdEntryP(vTruths, 1*nTtWords) }; + Abc_TtOr( pTruth[0], pTruth[0], pTruth[1], nTtWords ); + vRes = Bdc_ManBidecResub( pTruth[1], pTruth[0], nVars ); + Abc_TtSharp( pTruth[0], pTruth[0], pTruth[1], nTtWords ); + return vRes; +} + +int Gia_ManCountIsop( Vec_Wrd_t * vTruths, int nVars, int fVerbose ) +{ + int nTtWords = Abc_Truth6WordNum(nVars); + word * pTruth[2] = { Vec_WrdEntryP(vTruths, 0*nTtWords), + Vec_WrdEntryP(vTruths, 1*nTtWords) }; + int nNodes = Kit_IsopNodeNum( (unsigned *)pTruth[0], (unsigned *)pTruth[1], nVars, NULL ); + return nNodes; +} +Vec_Int_t * Gia_ManDeriveIsop( Vec_Wrd_t * vTruths, int nVars ) +{ + Vec_Int_t * vRes = NULL; + int nTtWords = Abc_Truth6WordNum(nVars); + word * pTruth[2] = { Vec_WrdEntryP(vTruths, 0*nTtWords), + Vec_WrdEntryP(vTruths, 1*nTtWords) }; + vRes = Kit_IsopResub( (unsigned *)pTruth[0], (unsigned *)pTruth[1], nVars, NULL ); + return vRes; +} + +int Gia_ManCountBdd( Vec_Wrd_t * vTruths, int nVars, int fVerbose ) +{ + extern Gia_Man_t * Gia_TryPermOptNew( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ); + int nTtWords = Abc_Truth6WordNum(nVars); + word * pTruth[2] = { Vec_WrdEntryP(vTruths, 0*nTtWords), + Vec_WrdEntryP(vTruths, 1*nTtWords) }; + Gia_Man_t * pGia; int nNodes; + + Abc_TtOr( pTruth[1], pTruth[1], pTruth[0], nTtWords ); + Abc_TtNot( pTruth[0], nTtWords ); + pGia = Gia_TryPermOptNew( pTruth[0], nVars, 1, nTtWords, 50, 0 ); + Abc_TtNot( pTruth[0], nTtWords ); + Abc_TtSharp( pTruth[1], pTruth[1], pTruth[0], nTtWords ); + + nNodes = Gia_ManAndNum(pGia); + Gia_ManStop( pGia ); + return nNodes; +} +Vec_Int_t * Gia_ManDeriveBdd( Vec_Wrd_t * vTruths, int nVars ) +{ + extern Vec_Int_t * Gia_ManToGates( Gia_Man_t * p ); + Vec_Int_t * vRes = NULL; + extern Gia_Man_t * Gia_TryPermOptNew( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ); + int nTtWords = Abc_Truth6WordNum(nVars); + word * pTruth[2] = { Vec_WrdEntryP(vTruths, 0*nTtWords), + Vec_WrdEntryP(vTruths, 1*nTtWords) }; + Gia_Man_t * pGia; + + Abc_TtOr( pTruth[1], pTruth[1], pTruth[0], nTtWords ); + Abc_TtNot( pTruth[0], nTtWords ); + pGia = Gia_TryPermOptNew( pTruth[0], nVars, 1, nTtWords, 50, 0 ); + Abc_TtNot( pTruth[0], nTtWords ); + Abc_TtSharp( pTruth[1], pTruth[1], pTruth[0], nTtWords ); + + vRes = Gia_ManToGates( pGia ); + Gia_ManStop( pGia ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManEvalSolutionOne( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * vSet, int nWords, int fVerbose ) +{ + Vec_Wrd_t * vTruths = Gia_ManDeriveTruths( p, vSims, vIsfs, vCands, vSet, nWords ); + int nTtWords = Vec_WrdSize(vTruths)/2, nVars = Vec_IntSize(vSet); + word * pTruth[2] = { Vec_WrdEntryP(vTruths, 0*nTtWords), + Vec_WrdEntryP(vTruths, 1*nTtWords) }; + int nNodesResub = Gia_ManCountResub( vTruths, nVars, 0 ); + int nNodesBidec = nVars > 2 ? Gia_ManCountBidec( vTruths, nVars, 0 ) : 999; + int nNodesIsop = nVars > 2 ? Gia_ManCountIsop( vTruths, nVars, 0 ) : 999; + int nNodesBdd = nVars > 2 ? Gia_ManCountBdd( vTruths, nVars, 0 ) : 999; + int nNodesMin = Abc_MinInt( Abc_MinInt(nNodesResub, nNodesBidec), Abc_MinInt(nNodesIsop, nNodesBdd) ); + if ( fVerbose ) + { + printf( "Size = %2d ", nVars ); + printf( "Resub =%3d ", nNodesResub ); + printf( "Bidec =%3d ", nNodesBidec ); + printf( "Isop =%3d ", nNodesIsop ); + printf( "Bdd =%3d ", nNodesBdd ); + Abc_TtIsfPrint( pTruth[0], pTruth[1], nTtWords ); + if ( nVars <= 6 ) + { + printf( " " ); + Extra_PrintHex( stdout, (unsigned*)pTruth[0], nVars ); + printf( " " ); + Extra_PrintHex( stdout, (unsigned*)pTruth[1], nVars ); + } + printf( "\n" ); + } + Vec_WrdFree( vTruths ); + if ( nNodesMin > 500 ) + return -1; + if ( nNodesMin == nNodesResub ) + return (nNodesMin << 2) | 0; + if ( nNodesMin == nNodesBidec ) + return (nNodesMin << 2) | 1; + if ( nNodesMin == nNodesIsop ) + return (nNodesMin << 2) | 2; + if ( nNodesMin == nNodesBdd ) + return (nNodesMin << 2) | 3; + return -1; +} +Vec_Int_t * Gia_ManDeriveSolutionOne( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * vSet, int nWords, int Type ) +{ + Vec_Int_t * vRes = NULL; + Vec_Wrd_t * vTruths = Gia_ManDeriveTruths( p, vSims, vIsfs, vCands, vSet, nWords ); + int nTtWords = Vec_WrdSize(vTruths)/2, nVars = Vec_IntSize(vSet); + word * pTruth[2] = { Vec_WrdEntryP(vTruths, 0*nTtWords), + Vec_WrdEntryP(vTruths, 1*nTtWords) }; + if ( Type == 0 ) + vRes = Gia_ManDeriveResub( vTruths, nVars ); + else if ( Type == 1 ) + vRes = Gia_ManDeriveBidec( vTruths, nVars ); + else if ( Type == 2 ) + vRes = Gia_ManDeriveIsop( vTruths, nVars ); + else if ( Type == 3 ) + vRes = Gia_ManDeriveBdd( vTruths, nVars ); + if ( vRes && Gia_ResubVarNum(vRes) <= 6 ) + { + word Func = Gia_ResubToTruth6( vRes ); + assert( !(Func & pTruth[0][0]) ); + assert( !(pTruth[1][0] & ~Func) ); + } + Vec_WrdFree( vTruths ); + return vRes; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaDeep.c b/yosys/abc/src/aig/gia/giaDeep.c new file mode 100644 index 00000000000..3698c2cd7a0 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaDeep.c @@ -0,0 +1,230 @@ +/**CFile**************************************************************** + + FileName [giaDeep.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Experiments with synthesis.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaDeep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "base/main/main.h" +#include "base/cmd/cmd.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDeepSynOne( int nNoImpr, int TimeOut, int nAnds, int Seed, int fUseTwo, int fVerbose ) +{ + abctime nTimeToStop = TimeOut ? Abc_Clock() + TimeOut * CLOCKS_PER_SEC : 0; + abctime clkStart = Abc_Clock(); + int s, i, IterMax = 100000, nAndsMin = -1, iIterLast = -1; + Gia_Man_t * pTemp = Abc_FrameReadGia(Abc_FrameGetGlobalFrame()); + Gia_Man_t * pNew = Gia_ManDup( pTemp ); + Abc_Random(1); + for ( s = 0; s < 10+Seed; s++ ) + Abc_Random(0); + for ( i = 0; i < IterMax; i++ ) + { + char * pCompress2rs = "balance -l; resub -K 6 -l; rewrite -l; resub -K 6 -N 2 -l; refactor -l; resub -K 8 -l; balance -l; resub -K 8 -N 2 -l; rewrite -l; resub -K 10 -l; rewrite -z -l; resub -K 10 -N 2 -l; balance -l; resub -K 12 -l; refactor -z -l; resub -K 12 -N 2 -l; rewrite -z -l; balance -l"; + unsigned Rand = Abc_Random(0); + int fDch = Rand & 1; + //int fCom = (Rand >> 1) & 3; + int fCom = (Rand >> 1) & 1; + int fFx = (Rand >> 2) & 1; + int KLut = fUseTwo ? 2 + (i % 5) : 3 + (i % 4); + int fChange = 0; + char Command[2000]; + char pComp[1000]; + if ( fCom == 3 ) + sprintf( pComp, "; &put; %s; %s; %s; &get", pCompress2rs, pCompress2rs, pCompress2rs ); + else if ( fCom == 2 ) + sprintf( pComp, "; &put; %s; %s; &get", pCompress2rs, pCompress2rs ); + else if ( fCom == 1 ) + sprintf( pComp, "; &put; %s; &get", pCompress2rs ); + else if ( fCom == 0 ) + sprintf( pComp, "; &dc2" ); + sprintf( Command, "&dch%s; &if -a -K %d; &mfs -e -W 20 -L 20%s%s", + fDch ? " -f" : "", KLut, fFx ? "; &fx; &st" : "", pComp ); + if ( Abc_FrameIsBatchMode() ) + { + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), Command) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", Command ); + return NULL; + } + } + else + { + Abc_FrameSetBatchMode( 1 ); + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), Command) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", Command ); + return NULL; + } + Abc_FrameSetBatchMode( 0 ); + } + pTemp = Abc_FrameReadGia(Abc_FrameGetGlobalFrame()); + if ( Gia_ManAndNum(pNew) > Gia_ManAndNum(pTemp) ) + { + Gia_ManStop( pNew ); + pNew = Gia_ManDup( pTemp ); + fChange = 1; + iIterLast = i; + } + else if ( Gia_ManAndNum(pNew) + Gia_ManAndNum(pNew)/10 < Gia_ManAndNum(pTemp) ) + { + //printf( "Updating\n" ); + //Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), Gia_ManDup(pNew) ); + } + if ( fChange && fVerbose ) + { + printf( "Iter %6d : ", i ); + printf( "Time %8.2f sec : ", (float)1.0*(Abc_Clock() - clkStart)/CLOCKS_PER_SEC ); + printf( "And = %6d ", Gia_ManAndNum(pNew) ); + printf( "Lev = %3d ", Gia_ManLevelNum(pNew) ); + if ( fChange ) + printf( "<== best : " ); + else if ( fVerbose ) + printf( " " ); + printf( "%s", Command ); + printf( "\n" ); + } + if ( nTimeToStop && Abc_Clock() > nTimeToStop ) + { + if ( !Abc_FrameIsBatchMode() ) + printf( "Runtime limit (%d sec) is reached after %d iterations.\n", TimeOut, i ); + break; + } + if ( i - iIterLast > nNoImpr ) + { + printf( "Completed %d iterations without improvement in %.2f seconds.\n", + nNoImpr, (float)1.0*(Abc_Clock() - clkStart)/CLOCKS_PER_SEC ); + break; + } + } + if ( i == IterMax ) + printf( "Iteration limit (%d iters) is reached after %.2f seconds.\n", IterMax, (float)1.0*(Abc_Clock() - clkStart)/CLOCKS_PER_SEC ); + else if ( nAnds && nAndsMin <= nAnds ) + printf( "Quality goal (%d nodes <= %d nodes) is achieved after %d iterations and %.2f seconds.\n", + nAndsMin, nAnds, i, (float)1.0*(Abc_Clock() - clkStart)/CLOCKS_PER_SEC ); + return pNew; +} +Gia_Man_t * Gia_ManDeepSyn( Gia_Man_t * pGia, int nIters, int nNoImpr, int TimeOut, int nAnds, int Seed, int fUseTwo, int fVerbose ) +{ + Gia_Man_t * pInit = Gia_ManDup(pGia); + Gia_Man_t * pBest = Gia_ManDup(pGia); + Gia_Man_t * pThis; + int i; + for ( i = 0; i < nIters; i++ ) + { + Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), Gia_ManDup(pInit) ); + pThis = Gia_ManDeepSynOne( nNoImpr, TimeOut, nAnds, Seed+i, fUseTwo, fVerbose ); + if ( Gia_ManAndNum(pBest) > Gia_ManAndNum(pThis) ) + { + Gia_ManStop( pBest ); + pBest = pThis; + } + else + Gia_ManStop( pThis ); + + } + Gia_ManStop( pInit ); + return pBest; +} + +/**Function************************************************************* + + Synopsis [Generating one AIG by applying a randomized script.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManRandSyn( Gia_Man_t * p, unsigned random_seed ) +{ + char * pCompress2rs = "balance -l; resub -K 6 -l; rewrite -l; resub -K 6 -N 2 -l; refactor -l; resub -K 8 -l; balance -l; resub -K 8 -N 2 -l; rewrite -l; resub -K 10 -l; rewrite -z -l; resub -K 10 -N 2 -l; balance -l; resub -K 12 -l; refactor -z -l; resub -K 12 -N 2 -l; rewrite -z -l; balance -l"; + unsigned Rand = random_seed; + int fDch = Rand & 1; + //int fCom = (Rand >> 1) & 3; + int fCom = (Rand >> 1) & 1; + int fFx = (Rand >> 2) & 1; + int fUseTwo = 0; + int KLut = fUseTwo ? 2 + (Rand % 5) : 3 + (Rand % 4); + //int fChange = 0; + char Command[2000]; + char pComp[1000]; + if ( fCom == 3 ) + sprintf( pComp, "; &put; %s; %s; %s; &get", pCompress2rs, pCompress2rs, pCompress2rs ); + else if ( fCom == 2 ) + sprintf( pComp, "; &put; %s; %s; &get", pCompress2rs, pCompress2rs ); + else if ( fCom == 1 ) + sprintf( pComp, "; &put; %s; &get", pCompress2rs ); + else if ( fCom == 0 ) + sprintf( pComp, "; &dc2" ); + sprintf( Command, "&dch%s; &if -a -K %d; &mfs -e -W 20 -L 20%s%s", + fDch ? " -f" : "", KLut, fFx ? "; &fx; &st" : "", pComp ); + Gia_Man_t * pOld = Abc_FrameGetGia(Abc_FrameGetGlobalFrame()); + Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), Gia_ManDup(p) ); + if ( Abc_FrameIsBatchMode() ) + { + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), Command) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", Command ); + return NULL; + } + } + else + { + Abc_FrameSetBatchMode( 1 ); + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), Command) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", Command ); + return NULL; + } + Abc_FrameSetBatchMode( 0 ); + } + Gia_Man_t * pRes = Abc_FrameGetGia(Abc_FrameGetGlobalFrame()); + Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pOld ); + return pRes; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaDfs.c b/yosys/abc/src/aig/gia/giaDfs.c new file mode 100644 index 00000000000..7ed59b9a23b --- /dev/null +++ b/yosys/abc/src/aig/gia/giaDfs.c @@ -0,0 +1,630 @@ +/**CFile**************************************************************** + + FileName [giaDfs.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [DFS procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaDfs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Counts the support size of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCollectCis_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( Gia_ObjIsCi(pObj) ) + { + Vec_IntPush( vSupp, Gia_ObjId(p, pObj) ); + return; + } + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManCollectCis_rec( p, Gia_ObjFanin0(pObj), vSupp ); + Gia_ManCollectCis_rec( p, Gia_ObjFanin1(pObj), vSupp ); +} + +/**Function************************************************************* + + Synopsis [Collects support nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCollectCis( Gia_Man_t * p, int * pNodes, int nNodes, Vec_Int_t * vSupp ) +{ + Gia_Obj_t * pObj; + int i; + Vec_IntClear( vSupp ); + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); + for ( i = 0; i < nNodes; i++ ) + { + pObj = Gia_ManObj( p, pNodes[i] ); + if ( Gia_ObjIsCo(pObj) ) + Gia_ManCollectCis_rec( p, Gia_ObjFanin0(pObj), vSupp ); + else + Gia_ManCollectCis_rec( p, pObj, vSupp ); + } +} + +/**Function************************************************************* + + Synopsis [Counts the support size of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCollectAnds_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vNodes ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return; + Gia_ObjSetTravIdCurrentId(p, iObj); + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManCollectAnds_rec( p, Gia_ObjFaninId0(pObj, iObj), vNodes ); + Gia_ManCollectAnds_rec( p, Gia_ObjFaninId1(pObj, iObj), vNodes ); + Vec_IntPush( vNodes, iObj ); +} + +/**Function************************************************************* + + Synopsis [Collects support nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCollectAnds( Gia_Man_t * p, int * pNodes, int nNodes, Vec_Int_t * vNodes, Vec_Int_t * vLeaves ) +{ + int i, iLeaf; +// Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrentId( p, 0 ); + if ( vLeaves ) + Vec_IntForEachEntry( vLeaves, iLeaf, i ) + Gia_ObjSetTravIdCurrentId( p, iLeaf ); + Vec_IntClear( vNodes ); + for ( i = 0; i < nNodes; i++ ) + { + Gia_Obj_t * pObj = Gia_ManObj( p, pNodes[i] ); + if ( Gia_ObjIsCo(pObj) ) + Gia_ManCollectAnds_rec( p, Gia_ObjFaninId0(pObj, pNodes[i]), vNodes ); + else if ( Gia_ObjIsAnd(pObj) ) + Gia_ManCollectAnds_rec( p, pNodes[i], vNodes ); + } +} + +/**Function************************************************************* + + Synopsis [Collects support nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManCollectAndsAll( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; int i; + Vec_Int_t * vNodes = Vec_IntAlloc( Gia_ManAndNum(p) ); + Gia_ManForEachAnd( p, pObj, i ) + Vec_IntPush( vNodes, i ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Counts the support size of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCollectNodesCis_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( Gia_ObjIsCi(pObj) ) + { + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); + return; + } + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManCollectNodesCis_rec( p, Gia_ObjFanin0(pObj), vNodes ); + Gia_ManCollectNodesCis_rec( p, Gia_ObjFanin1(pObj), vNodes ); + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); +} + +/**Function************************************************************* + + Synopsis [Collects support nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManCollectNodesCis( Gia_Man_t * p, int * pNodes, int nNodes ) +{ + Vec_Int_t * vNodes; + Gia_Obj_t * pObj; + int i; + vNodes = Vec_IntAlloc( 10000 ); + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); + for ( i = 0; i < nNodes; i++ ) + { + pObj = Gia_ManObj( p, pNodes[i] ); + if ( Gia_ObjIsCo(pObj) ) + Gia_ManCollectNodesCis_rec( p, Gia_ObjFanin0(pObj), vNodes ); + else + Gia_ManCollectNodesCis_rec( p, pObj, vNodes ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Collects support nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCollectTest( Gia_Man_t * p ) +{ + Vec_Int_t * vNodes; + Gia_Obj_t * pObj; + int i, iNode; + abctime clk = Abc_Clock(); + vNodes = Vec_IntAlloc( 100 ); + Gia_ManIncrementTravId( p ); + Gia_ManForEachCo( p, pObj, i ) + { + iNode = Gia_ObjId(p, pObj); + Gia_ManCollectAnds( p, &iNode, 1, vNodes, NULL ); + } + Vec_IntFree( vNodes ); + ABC_PRT( "DFS from each output", Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [Collects support nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSuppSize_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return 0; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( Gia_ObjIsCi(pObj) ) + return 1; + assert( Gia_ObjIsAnd(pObj) ); + return Gia_ManSuppSize_rec( p, Gia_ObjFanin0(pObj) ) + + Gia_ManSuppSize_rec( p, Gia_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Computes support size of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSuppSizeOne( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + Gia_ManIncrementTravId( p ); + return Gia_ManSuppSize_rec( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Computes support size of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSuppSizeTest( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, Counter = 0; + abctime clk = Abc_Clock(); + Gia_ManForEachObj( p, pObj, i ) + if ( Gia_ObjIsAnd(pObj) ) + Counter += (Gia_ManSuppSizeOne(p, pObj) <= 16); + printf( "Nodes with small support %d (out of %d)\n", Counter, Gia_ManAndNum(p) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Collects support nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSuppSize( Gia_Man_t * p, int * pNodes, int nNodes ) +{ + Gia_Obj_t * pObj; + int i, Counter = 0; + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); + for ( i = 0; i < nNodes; i++ ) + { + pObj = Gia_ManObj( p, pNodes[i] ); + if ( Gia_ObjIsCo(pObj) ) + Counter += Gia_ManSuppSize_rec( p, Gia_ObjFanin0(pObj) ); + else + Counter += Gia_ManSuppSize_rec( p, pObj ); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Collects support nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManConeSize_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return 0; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( Gia_ObjIsCi(pObj) ) + return 0; + assert( Gia_ObjIsAnd(pObj) ); + return 1 + Gia_ManConeSize_rec( p, Gia_ObjFanin0(pObj) ) + + Gia_ManConeSize_rec( p, Gia_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Collects support nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManConeSize( Gia_Man_t * p, int * pNodes, int nNodes ) +{ + Gia_Obj_t * pObj; + int i, Counter = 0; + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); + for ( i = 0; i < nNodes; i++ ) + { + pObj = Gia_ManObj( p, pNodes[i] ); + if ( Gia_ObjIsCo(pObj) ) + Counter += Gia_ManConeSize_rec( p, Gia_ObjFanin0(pObj) ); + else + Counter += Gia_ManConeSize_rec( p, pObj ); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Levelizes the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Vec_t * Gia_ManLevelize( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + Vec_Vec_t * vLevels; + int nLevels, Level, i; + nLevels = Gia_ManLevelNum( p ); + vLevels = Vec_VecStart( nLevels + 1 ); + Gia_ManForEachAnd( p, pObj, i ) + { + Level = Gia_ObjLevel( p, pObj ); + assert( Level <= nLevels ); + Vec_VecPush( vLevels, Level, pObj ); + } + return vLevels; +} + +/**Function************************************************************* + + Synopsis [Levelizes the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Gia_ManLevelizeR( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + Vec_Wec_t * vLevels; + int nLevels, Level, i; + nLevels = Gia_ManLevelRNum( p ); + vLevels = Vec_WecStart( nLevels + 1 ); + Gia_ManForEachObj( p, pObj, i ) + { + if ( i == 0 || (!Gia_ObjIsCo(pObj) && !Gia_ObjLevel(p, pObj)) ) + continue; + Level = Gia_ObjLevel( p, pObj ); + assert( Level <= nLevels ); + Vec_WecPush( vLevels, Level, i ); + } + return vLevels; +} +/**Function************************************************************* + + Synopsis [Computes reverse topological order.] + + Description [Assumes that levels are already assigned. + The levels of CO nodes may not be assigned.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManOrderReverse( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + Vec_Vec_t * vLevels; + Vec_Ptr_t * vLevel; + Vec_Int_t * vResult; + int i, k; + vLevels = Vec_VecStart( 100 ); + // make sure levels are assigned + Gia_ManForEachAnd( p, pObj, i ) + assert( Gia_ObjLevel(p, pObj) > 0 ); + // add CO nodes based on the level of their fanin + Gia_ManForEachCo( p, pObj, i ) + Vec_VecPush( vLevels, Gia_ObjLevel(p, Gia_ObjFanin0(pObj)), pObj ); + // add other nodes based on their level + Gia_ManForEachObj( p, pObj, i ) + if ( !Gia_ObjIsCo(pObj) ) + Vec_VecPush( vLevels, Gia_ObjLevel(p, pObj), pObj ); + // put the nodes in the reverse topological order + vResult = Vec_IntAlloc( Gia_ManObjNum(p) ); + Vec_VecForEachLevelReverse( vLevels, vLevel, i ) + Vec_PtrForEachEntry( Gia_Obj_t *, vLevel, pObj, k ) + Vec_IntPush( vResult, Gia_ObjId(p, pObj) ); + Vec_VecFree( vLevels ); + return vResult; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCollectSeq_rec( Gia_Man_t * p, int Id, Vec_Int_t * vRoots, Vec_Int_t * vObjs ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjIsTravIdCurrentId( p, Id ) ) + return; + Gia_ObjSetTravIdCurrentId( p, Id ); + pObj = Gia_ManObj( p, Id ); + if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ManCollectSeq_rec( p, Gia_ObjFaninId0(pObj, Id), vRoots, vObjs ); + Gia_ManCollectSeq_rec( p, Gia_ObjFaninId1(pObj, Id), vRoots, vObjs ); + } + else if ( Gia_ObjIsCi(pObj) ) + { + if ( Gia_ObjIsRo(p, pObj) ) + Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)) ); + } + else if ( Gia_ObjIsCo(pObj) ) + Gia_ManCollectSeq_rec( p, Gia_ObjFaninId0(pObj, Id), vRoots, vObjs ); + else assert( 0 ); + Vec_IntPush( vObjs, Id ); +} +Vec_Int_t * Gia_ManCollectSeq( Gia_Man_t * p, int * pPos, int nPos ) +{ + Vec_Int_t * vObjs, * vRoots; + int i, iRoot; + // collect roots + vRoots = Vec_IntAlloc( 100 ); + for ( i = 0; i < nPos; i++ ) + Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ManPo(p, pPos[i])) ); + // start trav IDs + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrentId( p, 0 ); + // collect objects + vObjs = Vec_IntAlloc( 1000 ); + Vec_IntPush( vObjs, 0 ); + Vec_IntForEachEntry( vRoots, iRoot, i ) + Gia_ManCollectSeq_rec( p, iRoot, vRoots, vObjs ); + Vec_IntFree( vRoots ); + return vObjs; +} +void Gia_ManCollectSeqTest( Gia_Man_t * p ) +{ + Vec_Int_t * vObjs; + int i; + abctime clk = Abc_Clock(); + for ( i = 0; i < Gia_ManPoNum(p); i++ ) + { + if ( i % 10000 == 0 ) + printf( "%8d finished...\r", i ); + + vObjs = Gia_ManCollectSeq( p, &i, 1 ); +// printf( "%d ", Vec_IntSize(vObjs) ); + Vec_IntFree( vObjs ); + } + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + +} + +/**Function************************************************************* + + Synopsis [Collect TFI nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCollectTfi_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vNodes ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return; + Gia_ObjSetTravIdCurrentId(p, iObj); + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManCollectTfi_rec( p, Gia_ObjFaninId0(pObj, iObj), vNodes ); + Gia_ManCollectTfi_rec( p, Gia_ObjFaninId1(pObj, iObj), vNodes ); + Vec_IntPush( vNodes, iObj ); +} +void Gia_ManCollectTfi( Gia_Man_t * p, Vec_Int_t * vRoots, Vec_Int_t * vNodes ) +{ + int i, iRoot; + Vec_IntClear( vNodes ); + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vRoots, iRoot, i ) + Gia_ManCollectTfi_rec( p, iRoot, vNodes ); +} + +/**Function************************************************************* + + Synopsis [Collect TFI nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCollectTfo_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vNodes ) +{ + Gia_Obj_t * pObj; int i, iFan; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return; + Gia_ObjSetTravIdCurrentId(p, iObj); + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCo(pObj) ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ObjForEachFanoutStaticId( p, iObj, iFan, i ) + Gia_ManCollectTfo_rec( p, iFan, vNodes ); + Vec_IntPush( vNodes, iObj ); +} +void Gia_ManCollectTfo( Gia_Man_t * p, Vec_Int_t * vRoots, Vec_Int_t * vNodes ) +{ + int i, iRoot; + Vec_IntClear( vNodes ); + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vRoots, iRoot, i ) + Gia_ManCollectTfo_rec( p, iRoot, vNodes ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaDup.c b/yosys/abc/src/aig/gia/giaDup.c new file mode 100644 index 00000000000..87f2bb74c56 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaDup.c @@ -0,0 +1,6175 @@ +/**CFile**************************************************************** + + FileName [giaDup.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Duplication procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaDup.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/tim/tim.h" +#include "misc/vec/vecWec.h" +#include "proof/cec/cec.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + + +extern Bnd_Man_t* pBnd; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Removes pointers to the unmarked nodes..] + + Description [Array vLits contains literals of p. At the same time, + each object pObj of p points to a literal of pNew. This procedure + remaps literals in array vLits into literals of pNew.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDupRemapLiterals( Vec_Int_t * vLits, Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, iLit, iLitNew; + Vec_IntForEachEntry( vLits, iLit, i ) + { + if ( iLit < 0 ) + continue; + pObj = Gia_ManObj( p, Abc_Lit2Var(iLit) ); + if ( ~pObj->Value == 0 ) + iLitNew = -1; + else + iLitNew = Abc_LitNotCond( pObj->Value, Abc_LitIsCompl(iLit) ); + Vec_IntWriteEntry( vLits, i, iLitNew ); + } +} + +/**Function************************************************************* + + Synopsis [Removes pointers to the unmarked nodes..] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDupRemapEquiv( Gia_Man_t * pNew, Gia_Man_t * p ) +{ + Vec_Int_t * vClass; + int i, k, iNode, iRepr, iPrev; + if ( p->pReprs == NULL ) + return; + assert( pNew->pReprs == NULL && pNew->pNexts == NULL ); + // start representatives + pNew->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(pNew) ); + for ( i = 0; i < Gia_ManObjNum(pNew); i++ ) + Gia_ObjSetRepr( pNew, i, GIA_VOID ); + // iterate over constant candidates + Gia_ManForEachConst( p, i ) + Gia_ObjSetRepr( pNew, Abc_Lit2Var(Gia_ManObj(p, i)->Value), 0 ); + // iterate over class candidates + vClass = Vec_IntAlloc( 100 ); + Gia_ManForEachClass( p, i ) + { + Vec_IntClear( vClass ); + Gia_ClassForEachObj( p, i, k ) + Vec_IntPushUnique( vClass, Abc_Lit2Var(Gia_ManObj(p, k)->Value) ); + assert( Vec_IntSize( vClass ) > 1 ); + Vec_IntSort( vClass, 0 ); + iRepr = iPrev = Vec_IntEntry( vClass, 0 ); + Vec_IntForEachEntryStart( vClass, iNode, k, 1 ) + { + Gia_ObjSetRepr( pNew, iNode, iRepr ); + assert( iPrev < iNode ); + iPrev = iNode; + } + } + Vec_IntFree( vClass ); + pNew->pNexts = Gia_ManDeriveNexts( pNew ); +} + +/**Function************************************************************* + + Synopsis [Remaps combinational inputs when objects are DFS ordered.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDupRemapCis( Gia_Man_t * pNew, Gia_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjNew; + int i; + assert( Vec_IntSize(p->vCis) == Vec_IntSize(pNew->vCis) ); + Gia_ManForEachCi( p, pObj, i ) + { + assert( Gia_ObjCioId(pObj) == i ); + pObjNew = Gia_ObjFromLit( pNew, pObj->Value ); + assert( !Gia_IsComplement(pObjNew) ); + Vec_IntWriteEntry( pNew->vCis, i, Gia_ObjId(pNew, pObjNew) ); + Gia_ObjSetCioId( pObjNew, i ); + } +} + +/**Function************************************************************* + + Synopsis [Remaps combinational outputs when objects are DFS ordered.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDupRemapCos( Gia_Man_t * pNew, Gia_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjNew; + int i; + assert( Vec_IntSize(p->vCos) == Vec_IntSize(pNew->vCos) ); + Gia_ManForEachCo( p, pObj, i ) + { + assert( Gia_ObjCioId(pObj) == i ); + pObjNew = Gia_ObjFromLit( pNew, pObj->Value ); + assert( !Gia_IsComplement(pObjNew) ); + Vec_IntWriteEntry( pNew->vCos, i, Gia_ObjId(pNew, pObjNew) ); + Gia_ObjSetCioId( pObjNew, i ); + } +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManDupOrderDfs_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return pObj->Value; + if ( Gia_ObjIsCi(pObj) ) + return pObj->Value = Gia_ManAppendCi(pNew); +// if ( p->pNexts && Gia_ObjNext(p, Gia_ObjId(p, pObj)) ) +// Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjNextObj(p, Gia_ObjId(p, pObj)) ); + Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); + if ( Gia_ObjIsCo(pObj) ) + return pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin1(pObj) ); + return pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG while putting objects in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupOrderDfs( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCo( p, pObj, i ) + Gia_ManDupOrderDfs_rec( pNew, p, pObj ); + Gia_ManForEachCi( p, pObj, i ) + if ( !~pObj->Value ) + pObj->Value = Gia_ManAppendCi(pNew); + assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(p) ); + Gia_ManDupRemapCis( pNew, p ); + Gia_ManDupRemapEquiv( pNew, p ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG while putting objects in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupAbs( Gia_Man_t * p, Vec_Int_t * vMapPpi2Ff, Vec_Int_t * vMapFf2Ppi ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int k, Flop, Used; + assert( Vec_IntSize(vMapFf2Ppi) == Vec_IntSize(vMapPpi2Ff) + Vec_IntCountEntry(vMapFf2Ppi, -1) ); + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + // create inputs + Gia_ManForEachPi( p, pObj, k ) + pObj->Value = Gia_ManAppendCi(pNew); + Vec_IntForEachEntry( vMapPpi2Ff, Flop, k ) + { + pObj = Gia_ManCi( p, Gia_ManPiNum(p) + Flop ); + pObj->Value = Gia_ManAppendCi(pNew); + } + Vec_IntForEachEntry( vMapFf2Ppi, Used, Flop ) + { + pObj = Gia_ManCi( p, Gia_ManPiNum(p) + Flop ); + if ( Used >= 0 ) + { + assert( pObj->Value != ~0 ); + continue; + } + assert( pObj->Value == ~0 ); + pObj->Value = Gia_ManAppendCi(pNew); + } + Gia_ManForEachCi( p, pObj, k ) + assert( pObj->Value != ~0 ); + // create nodes + Gia_ManForEachPo( p, pObj, k ) + Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Vec_IntForEachEntry( vMapFf2Ppi, Used, Flop ) + { + if ( Used >= 0 ) + continue; + pObj = Gia_ManCi( p, Gia_ManPiNum(p) + Flop ); + pObj = Gia_ObjRoToRi( p, pObj ); + Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); + } + // create outputs + Gia_ManForEachPo( p, pObj, k ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Vec_IntForEachEntry( vMapFf2Ppi, Used, Flop ) + { + if ( Used >= 0 ) + continue; + pObj = Gia_ManCi( p, Gia_ManPiNum(p) + Flop ); + pObj = Gia_ObjRoToRi( p, pObj ); + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) - Vec_IntSize(vMapPpi2Ff) ); + assert( Gia_ManPiNum(pNew) == Gia_ManPiNum(p) + Vec_IntSize(vMapPpi2Ff) ); + assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(p) ); + assert( Gia_ManPoNum(pNew) == Gia_ManPoNum(p) ); + assert( Gia_ManCoNum(pNew) == Gia_ManCoNum(p) - Vec_IntSize(vMapPpi2Ff) ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Duplicates AIG while putting objects in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupOutputGroup( Gia_Man_t * p, int iOutStart, int iOutStop ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + for ( i = iOutStart; i < iOutStop; i++ ) + { + pObj = Gia_ManCo( p, i ); + Gia_ManDupOrderDfs_rec( pNew, p, pObj ); + } + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG while putting objects in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupOutputVec( Gia_Man_t * p, Vec_Int_t * vOutPres ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + assert( Gia_ManRegNum(p) == 0 ); + assert( Gia_ManPoNum(p) == Vec_IntSize(vOutPres) ); + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachPo( p, pObj, i ) + if ( Vec_IntEntry(vOutPres, i) ) + Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachPo( p, pObj, i ) + if ( Vec_IntEntry(vOutPres, i) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG while putting objects in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupSelectedOutputs( Gia_Man_t * p, Vec_Int_t * vOutsLeft ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i, iOut; + assert( Gia_ManRegNum(p) == 0 ); + assert( Gia_ManPoNum(p) >= Vec_IntSize(vOutsLeft) ); + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Vec_IntForEachEntry( vOutsLeft, iOut, i ) + Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin0(Gia_ManPo(p, iOut)) ); + Vec_IntForEachEntry( vOutsLeft, iOut, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManPo(p, iOut)) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDupOrderDfsChoices_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + Gia_Obj_t * pNext; + if ( ~pObj->Value ) + return; + assert( Gia_ObjIsAnd(pObj) ); + pNext = Gia_ObjNextObj( p, Gia_ObjId(p, pObj) ); + if ( pNext ) + Gia_ManDupOrderDfsChoices_rec( pNew, p, pNext ); + Gia_ManDupOrderDfsChoices_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManDupOrderDfsChoices_rec( pNew, p, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( pNext ) + { + pNew->pNexts[Abc_Lit2Var(pObj->Value)] = Abc_Lit2Var( Abc_Lit2Var(pNext->Value) ); + assert( Abc_Lit2Var(pObj->Value) > Abc_Lit2Var(pNext->Value) ); + } +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG while putting objects in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupOrderDfsChoices( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + assert( p->pReprs && p->pNexts ); + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->pNexts = ABC_CALLOC( int, Gia_ManObjNum(p) ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachCo( p, pObj, i ) + { + Gia_ManDupOrderDfsChoices_rec( pNew, p, Gia_ObjFanin0(pObj) ); + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); +// Gia_ManDeriveReprs( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG while putting objects in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManDupOrderDfs2_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return pObj->Value; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManDupOrderDfs2_rec( pNew, p, Gia_ObjFanin1(pObj) ); + Gia_ManDupOrderDfs2_rec( pNew, p, Gia_ObjFanin0(pObj) ); + return pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManDupOrderDfsReverse( Gia_Man_t * p, int fRevFans, int fRevOuts ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + if ( fRevOuts ) + { + if ( fRevFans ) + Gia_ManForEachCoReverse( p, pObj, i ) + Gia_ManDupOrderDfs2_rec( pNew, p, Gia_ObjFanin0(pObj) ); + else + Gia_ManForEachCoReverse( p, pObj, i ) + Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); + } + else + { + if ( fRevFans ) + Gia_ManForEachCo( p, pObj, i ) + Gia_ManDupOrderDfs2_rec( pNew, p, Gia_ObjFanin0(pObj) ); + else + Gia_ManForEachCo( p, pObj, i ) + Gia_ManDupOrderDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); + } + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManDupRemapCis( pNew, p ); + Gia_ManDupRemapCos( pNew, p ); + Gia_ManDupRemapEquiv( pNew, p ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG while putting first PIs, then nodes, then POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupOrderAiger( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManDupRemapEquiv( pNew, p ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + assert( Gia_ManIsNormalized(pNew) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG while putting first PIs, then nodes, then POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupOnsetOffset( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + { + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + pObj->Value = Gia_ManAppendCo( pNew, Abc_LitNot(Gia_ObjFanin0Copy(pObj)) ); + } + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG while putting first PIs, then nodes, then POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupLastPis( Gia_Man_t * p, int nLastPis ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + assert( Gia_ManRegNum(p) == 0 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = (i < Gia_ManCiNum(p) - nLastPis) ? ~0 : Gia_ManAppendCi(pNew); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG while complementing the flops.] + + Description [The array of initial state contains the init state + for each state bit of the flops in the design.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupFlip( Gia_Man_t * p, int * pInitState ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCi(pObj) ) + { + pObj->Value = Gia_ManAppendCi( pNew ); + if ( Gia_ObjCioId(pObj) >= Gia_ManPiNum(p) ) + pObj->Value = Abc_LitNotCond( pObj->Value, Abc_InfoHasBit((unsigned *)pInitState, Gia_ObjCioId(pObj) - Gia_ManPiNum(p)) ); + } + else if ( Gia_ObjIsCo(pObj) ) + { + pObj->Value = Gia_ObjFanin0Copy(pObj); + if ( Gia_ObjCioId(pObj) >= Gia_ManPoNum(p) ) + pObj->Value = Abc_LitNotCond( pObj->Value, Abc_InfoHasBit((unsigned *)pInitState, Gia_ObjCioId(pObj) - Gia_ManPoNum(p)) ); + pObj->Value = Gia_ManAppendCo( pNew, pObj->Value ); + } + } + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Cycles AIG using random input.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCycle( Gia_Man_t * p, Abc_Cex_t * pCex, int nFrames ) +{ + Gia_Obj_t * pObj, * pObjRi, * pObjRo; + int i, k; + Gia_ManRandom( 1 ); + assert( pCex == NULL || nFrames <= pCex->iFrame ); + // iterate for the given number of frames + for ( i = 0; i < nFrames; i++ ) + { + Gia_ManForEachPi( p, pObj, k ) + pObj->fMark0 = pCex ? Abc_InfoHasBit(pCex->pData, pCex->nRegs+i*pCex->nPis+k) : (1 & Gia_ManRandom(0)); + Gia_ManForEachAnd( p, pObj, k ) + pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & + (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)); + Gia_ManForEachCo( p, pObj, k ) + pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); + Gia_ManForEachRiRo( p, pObjRi, pObjRo, k ) + pObjRo->fMark0 = pObjRi->fMark0; + } +} +Gia_Man_t * Gia_ManDupCycled( Gia_Man_t * p, Abc_Cex_t * pCex, int nFrames ) +{ + Gia_Man_t * pNew; + Vec_Bit_t * vInits; + Gia_Obj_t * pObj; + int i; + Gia_ManCleanMark0(p); + Gia_ManCycle( p, pCex, nFrames ); + vInits = Vec_BitAlloc( Gia_ManRegNum(p) ); + Gia_ManForEachRo( p, pObj, i ) + Vec_BitPush( vInits, pObj->fMark0 ); + pNew = Gia_ManDupFlip( p, Vec_BitArray(vInits) ); + Vec_BitFree( vInits ); + Gia_ManCleanMark0(p); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Duplicates AIG without any changes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDup( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + if ( Gia_ManHasChoices(p) ) + pNew->pSibls = ABC_CALLOC( int, Gia_ManObjNum(p) ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsAnd(pObj) ) + { + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) ) + pNew->pSibls[Abc_Lit2Var(pObj->Value)] = Abc_Lit2Var(Gia_ObjSiblObj(p, Gia_ObjId(p, pObj))->Value); + } + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + if ( p->pCexSeq ) + pNew->pCexSeq = Abc_CexDup( p->pCexSeq, Gia_ManRegNum(p) ); + return pNew; +} +Gia_Man_t * Gia_ManDup2( Gia_Man_t * p1, Gia_Man_t * p2 ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + assert( Gia_ManCiNum(p1) == Gia_ManCiNum(p2) ); + assert( Gia_ManCoNum(p1) == Gia_ManCoNum(p2) ); + pNew = Gia_ManStart( Gia_ManObjNum(p1) + Gia_ManObjNum(p2) ); + Gia_ManHashStart( pNew ); + Gia_ManConst0(p1)->Value = 0; + Gia_ManConst0(p2)->Value = 0; + Gia_ManForEachCi( p1, pObj, i ) + pObj->Value = Gia_ManCi(p2, i)->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p1, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachAnd( p2, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p1, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManForEachCo( p2, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p1) ); + Gia_ManHashStop( pNew ); + return pNew; +} +Gia_Man_t * Gia_ManDupWithAttributes( Gia_Man_t * p ) +{ + Gia_Man_t * pNew = Gia_ManDup(p); + Gia_ManTransferMapping( pNew, p ); + Gia_ManTransferPacking( pNew, p ); + if ( p->pManTime ) + pNew->pManTime = Tim_ManDup( (Tim_Man_t *)p->pManTime, 0 ); + if ( p->pAigExtra ) + pNew->pAigExtra = Gia_ManDup( p->pAigExtra ); + if ( p->nAnd2Delay ) + pNew->nAnd2Delay = p->nAnd2Delay; + if ( p->vRegClasses ) + pNew->vRegClasses = Vec_IntDup( p->vRegClasses ); + if ( p->vRegInits ) + pNew->vRegInits = Vec_IntDup( p->vRegInits ); + if ( p->vConfigs ) + pNew->vConfigs = Vec_IntDup( p->vConfigs ); + if ( p->pCellStr ) + pNew->pCellStr = Abc_UtilStrsav( p->pCellStr ); + // copy names if present + if ( p->vNamesIn ) + pNew->vNamesIn = Vec_PtrDupStr( p->vNamesIn ); + if ( p->vNamesOut ) + pNew->vNamesOut = Vec_PtrDupStr( p->vNamesOut ); + return pNew; +} +Gia_Man_t * Gia_ManDupRemovePis( Gia_Man_t * p, int nRemPis ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCi(pObj) && Gia_ObjCioId(pObj) < Gia_ManCiNum(p)-nRemPis ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} +Gia_Man_t * Gia_ManDupNoBuf( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + else if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} +Gia_Man_t * Gia_ManDupMap( Gia_Man_t * p, Vec_Int_t * vMap ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Vec_IntEntry(vMap, i) >= 0 ) + pObj->Value = Gia_ManObj( p, Vec_IntEntry(vMap, i) )->Value; + else if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} +Gia_Man_t * Gia_ManDupAddBufs( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) + Gia_ManCiNum(p) + Gia_ManCoNum(p) ); + Gia_ManHashStart( pNew ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendBuf( pNew, pObj->Value ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, pObj->Value ); + Gia_ManHashStop( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG without any changes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupZero( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; int i; + pNew = Gia_ManStart( 1 + Gia_ManCiNum(p) + Gia_ManCoNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + for ( i = 0; i < Gia_ManCiNum(p); i++ ) + Gia_ManAppendCi( pNew ); + for ( i = 0; i < Gia_ManCoNum(p); i++ ) + Gia_ManAppendCo( pNew, 0 ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG without any changes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupPerm( Gia_Man_t * p, Vec_Int_t * vPiPerm ) +{ +// Vec_Int_t * vPiPermInv; + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + assert( Vec_IntSize(vPiPerm) == Gia_ManPiNum(p) ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; +// vPiPermInv = Vec_IntInvert( vPiPerm, -1 ); + Gia_ManForEachPi( p, pObj, i ) +// Gia_ManPi(p, Vec_IntEntry(vPiPermInv,i))->Value = Gia_ManAppendCi( pNew ); + Gia_ManPi(p, Vec_IntEntry(vPiPerm,i))->Value = Gia_ManAppendCi( pNew ); +// Vec_IntFree( vPiPermInv ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCi(pObj) ) + { + if ( Gia_ObjIsRo(p, pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + } + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} +Gia_Man_t * Gia_ManDupPermFlop( Gia_Man_t * p, Vec_Int_t * vFfPerm ) +{ + //Vec_Int_t * vPermInv; + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + assert( Vec_IntSize(vFfPerm) == Gia_ManRegNum(p) ); + //vPermInv = Vec_IntInvert( vFfPerm, -1 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachRo( p, pObj, i ) + //Gia_ManRo(p, Vec_IntEntry(vPermInv, i))->Value = Gia_ManAppendCi(pNew); + Gia_ManRo(p, Vec_IntEntry(vFfPerm, i))->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachPo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManForEachRi( p, pObj, i ) + //pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy( Gia_ManRi(p, Vec_IntEntry(vPermInv, i)) ) ); + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy( Gia_ManRi(p, Vec_IntEntry(vFfPerm, i)) ) ); + //Vec_IntFree( vPermInv ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} +Gia_Man_t * Gia_ManDupSpreadFlop( Gia_Man_t * p, Vec_Int_t * vFfMask ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i, k, Entry; + assert( Vec_IntSize(vFfMask) >= Gia_ManRegNum(p) ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + k = 0; + Vec_IntForEachEntry( vFfMask, Entry, i ) + if ( Entry == -1 ) + Gia_ManAppendCi(pNew); + else + Gia_ManRo(p, k++)->Value = Gia_ManAppendCi(pNew); + assert( k == Gia_ManRegNum(p) ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachPo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + k = 0; + Vec_IntForEachEntry( vFfMask, Entry, i ) + if ( Entry == -1 ) + Gia_ManAppendCo( pNew, 0 ); + else + { + pObj = Gia_ManRi( p, k++ ); + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + assert( k == Gia_ManRegNum(p) ); + Gia_ManSetRegNum( pNew, Vec_IntSize(vFfMask) ); + return pNew; +} +Gia_Man_t * Gia_ManDupPermFlopGap( Gia_Man_t * p, Vec_Int_t * vFfMask ) +{ + Vec_Int_t * vPerm = Vec_IntCondense( vFfMask, -1 ); + Gia_Man_t * pPerm = Gia_ManDupPermFlop( p, vPerm ); + Gia_Man_t * pSpread = Gia_ManDupSpreadFlop( pPerm, vFfMask ); + Vec_IntFree( vPerm ); + Gia_ManStop( pPerm ); + return pSpread; +} + +/**Function************************************************************* + + Synopsis [Appends second AIG without any changes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupPiPerm( Gia_Man_t * p ) +{ + Gia_Man_t * pNew, * pOne; + Gia_Obj_t * pObj; + int i; + Gia_ManRandom(1); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + { + int iLit0 = Gia_ObjFanin0Copy(pObj); + int iLit1 = Gia_ObjFanin1Copy(pObj); + int iPlace0 = Gia_ManRandom(0) % Gia_ManCiNum(p); + int iPlace1 = Gia_ManRandom(0) % Gia_ManCiNum(p); + if ( Abc_Lit2Var(iLit0) <= Gia_ManCiNum(p) ) + iLit0 = Abc_Var2Lit( iPlace0+1, Abc_LitIsCompl(iLit0) ); + if ( Abc_Lit2Var(iLit1) <= Gia_ManCiNum(p) ) + iLit1 = Abc_Var2Lit( iPlace1+1, Abc_LitIsCompl(iLit1) ); + pObj->Value = Gia_ManHashAnd( pNew, iLit0, iLit1 ); + } + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pOne = pNew ); + Gia_ManStop( pOne ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManCreatePerm( int n ) +{ + Vec_Int_t * vPerm = Vec_IntStartNatural( n ); + int i, * pPerm = Vec_IntArray( vPerm ); + for ( i = 0; i < n; i++ ) + { + int j = Abc_Random(0) % n; + ABC_SWAP( int, pPerm[i], pPerm[j] ); + + } + return vPerm; +} +Gia_Man_t * Gia_ManDupRandPerm( Gia_Man_t * p ) +{ + Vec_Int_t * vPiPerm = Gia_ManCreatePerm( Gia_ManCiNum(p) ); + Vec_Int_t * vPoPerm = Gia_ManCreatePerm( Gia_ManCoNum(p) ); + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachPi( p, pObj, i ) + Gia_ManPi(p, Vec_IntEntry(vPiPerm,i))->Value = Gia_ManAppendCi(pNew) ^ (Abc_Random(0) & 1); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachPo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManPo(p, Vec_IntEntry(vPoPerm,i))) ^ (Abc_Random(0) & 1) ); + Vec_IntFree( vPiPerm ); + Vec_IntFree( vPoPerm ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Appends second AIG without any changes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDupAppend( Gia_Man_t * pNew, Gia_Man_t * pTwo ) +{ + Gia_Obj_t * pObj; + int i; + if ( pNew->nRegs > 0 ) + pNew->nRegs = 0; + if ( Vec_IntSize(&pNew->vHTable) == 0 ) + Gia_ManHashStart( pNew ); + Gia_ManConst0(pTwo)->Value = 0; + Gia_ManForEachObj1( pTwo, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } +} +void Gia_ManDupAppendShare( Gia_Man_t * pNew, Gia_Man_t * pTwo ) +{ + Gia_Obj_t * pObj; + int i; + assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(pTwo) ); + if ( Vec_IntSize(&pNew->vHTable) == 0 ) + Gia_ManHashStart( pNew ); + Gia_ManConst0(pTwo)->Value = 0; + Gia_ManForEachObj1( pTwo, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_Obj2Lit( pNew, Gia_ManCi( pNew, Gia_ObjCioId(pObj) ) ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } +} +Gia_Man_t * Gia_ManDupAppendNew( Gia_Man_t * pOne, Gia_Man_t * pTwo ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(pOne) + Gia_ManObjNum(pTwo) ); + pNew->pName = Abc_UtilStrsav( pOne->pName ); + pNew->pSpec = Abc_UtilStrsav( pOne->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManConst0(pOne)->Value = 0; + Gia_ManForEachObj1( pOne, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + } + Gia_ManConst0(pTwo)->Value = 0; + Gia_ManForEachObj1( pTwo, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsPi(pTwo, pObj) ) + pObj->Value = Gia_ManPi(pOne, Gia_ObjCioId(pObj))->Value; + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + } + Gia_ManHashStop( pNew ); + // primary outputs + Gia_ManForEachPo( pOne, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManForEachPo( pTwo, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + // flop inputs + Gia_ManForEachRi( pOne, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManForEachRi( pTwo, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(pOne) + Gia_ManRegNum(pTwo) ); + return pNew; +} +void Gia_ManDupRebuild( Gia_Man_t * pNew, Gia_Man_t * p, Vec_Int_t * vLits, int fBufs ) +{ + Gia_Obj_t * pObj; int i; + assert( Vec_IntSize(vLits) == Gia_ManCiNum(p) ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Vec_IntEntry(vLits, i); + Gia_ManForEachAnd( p, pObj, i ) + if ( fBufs && Gia_ObjIsBuf(pObj) ) + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Vec_IntClear( vLits ); + Gia_ManForEachCo( p, pObj, i ) + Vec_IntPush( vLits, Gia_ObjFanin0Copy(pObj) ); + assert( Vec_IntSize(vLits) == Gia_ManCoNum(p) ); +} + +/**Function************************************************************* + + Synopsis [Creates a miter for inductive checking of the invariant.] + + Description [The first GIA (p) is a sequential AIG whose transition + relation is used. The second GIA (pInv) is a combinational AIG representing + the invariant over the register outputs. If the resulting combination miter + is UNSAT, the invariant holds by simple induction.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupInvMiter( Gia_Man_t * p, Gia_Man_t * pInv ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, Node1, Node2, Node; + assert( Gia_ManRegNum(p) > 0 ); + assert( Gia_ManRegNum(pInv) == 0 ); + assert( Gia_ManCoNum(pInv) == 1 ); + assert( Gia_ManRegNum(p) == Gia_ManCiNum(pInv) ); + Gia_ManFillValue(p); + pNew = Gia_ManStart( Gia_ManObjNum(p) + 2*Gia_ManObjNum(pInv) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + } + // build invariant on top of register outputs in the first frame + Gia_ManForEachRo( p, pObj, i ) + Gia_ManCi(pInv, i)->Value = pObj->Value; + Gia_ManForEachAnd( pInv, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + pObj = Gia_ManCo( pInv, 0 ); + Node1 = Gia_ObjFanin0Copy(pObj); + // build invariant on top of register outputs in the second frame + Gia_ManForEachRi( p, pObj, i ) + Gia_ManCi(pInv, i)->Value = pObj->Value; + Gia_ManForEachAnd( pInv, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + pObj = Gia_ManCo( pInv, 0 ); + Node2 = Gia_ObjFanin0Copy(pObj); + // create miter output + Node = Gia_ManHashAnd( pNew, Node1, Abc_LitNot(Node2) ); + Gia_ManAppendCo( pNew, Node ); + // cleanup + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Appends logic cones as additional property outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupAppendCones( Gia_Man_t * p, Gia_Man_t ** ppCones, int nCones, int fOnlyRegs ) +{ + Gia_Man_t * pNew, * pOne; + Gia_Obj_t * pObj; + int i, k; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachPo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + for ( k = 0; k < nCones; k++ ) + { + pOne = ppCones[k]; + assert( Gia_ManPoNum(pOne) == 1 ); + assert( Gia_ManRegNum(pOne) == 0 ); + if ( fOnlyRegs ) + assert( Gia_ManPiNum(pOne) == Gia_ManRegNum(p) ); + else + assert( Gia_ManPiNum(pOne) == Gia_ManCiNum(p) ); + Gia_ManConst0(pOne)->Value = 0; + Gia_ManForEachPi( pOne, pObj, i ) + pObj->Value = Gia_ManCiLit( pNew, fOnlyRegs ? Gia_ManPiNum(p) + i : i ); + Gia_ManForEachAnd( pOne, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachPo( pOne, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManForEachRi( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pOne = pNew ); + Gia_ManStop( pOne ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Duplicates while adding self-loops to the registers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupSelf( Gia_Man_t * p ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, iCtrl; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + iCtrl = Gia_ManAppendCi( pNew ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachPo( p, pObj, i ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + Gia_ManForEachRi( p, pObj, i ) + pObj->Value = Gia_ManHashMux( pNew, iCtrl, Gia_ObjFanin0Copy(pObj), Gia_ObjRiToRo(p, pObj)->Value ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, pObj->Value ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates while adding self-loops to the registers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupFlopClass( Gia_Man_t * p, int iClass ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i, Counter1 = 0, Counter2 = 0; + assert( p->vFlopClasses != NULL ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachRo( p, pObj, i ) + if ( Vec_IntEntry(p->vFlopClasses, i) != iClass ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachRo( p, pObj, i ) + if ( Vec_IntEntry(p->vFlopClasses, i) == iClass ) + pObj->Value = Gia_ManAppendCi( pNew ), Counter1++; + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachPo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManForEachRi( p, pObj, i ) + if ( Vec_IntEntry(p->vFlopClasses, i) != iClass ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManForEachRi( p, pObj, i ) + if ( Vec_IntEntry(p->vFlopClasses, i) == iClass ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ), Counter2++; + assert( Counter1 == Counter2 ); + Gia_ManSetRegNum( pNew, Counter1 ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG without any changes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupMarked( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i, nRos = 0, nRis = 0; + int CountMarked = 0; + Gia_ManForEachObj( p, pObj, i ) + CountMarked += pObj->fMark0; + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) - CountMarked ); + if ( p->pMuxes ) + pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc ); + pNew->nConstrs = p->nConstrs; + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObj1( p, pObj, i ) + { + if ( pObj->fMark0 ) + { + assert( !Gia_ObjIsBuf(pObj) ); + pObj->fMark0 = 0; + continue; + } + if ( Gia_ObjIsBuf(pObj) ) + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsAnd(pObj) ) + { + if ( Gia_ObjIsXor(pObj) ) + pObj->Value = Gia_ManAppendXorReal( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsMux(p, pObj) ) + pObj->Value = Gia_ManAppendMuxReal( pNew, Gia_ObjFanin2Copy(p, pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin0Copy(pObj) ); + else + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + else if ( Gia_ObjIsCi(pObj) ) + { + pObj->Value = Gia_ManAppendCi( pNew ); + nRos += Gia_ObjIsRo(p, pObj); + } + else if ( Gia_ObjIsCo(pObj) ) + { +// Gia_Obj_t * pFanin = Gia_ObjFanin0(pObj); + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + nRis += Gia_ObjIsRi(p, pObj); + } + } + assert( pNew->nObjsAlloc == pNew->nObjs ); + assert( nRos == nRis ); + Gia_ManSetRegNum( pNew, nRos ); + if ( p->pReprs && p->pNexts ) + { + Gia_Obj_t * pRepr; + pNew->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(pNew) ); + for ( i = 0; i < Gia_ManObjNum(pNew); i++ ) + Gia_ObjSetRepr( pNew, i, GIA_VOID ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( !~pObj->Value ) + continue; + pRepr = Gia_ObjReprObj( p, i ); + if ( pRepr == NULL ) + continue; + if ( !~pRepr->Value ) + continue; + assert( !Gia_ObjIsBuf(pObj) ); + if ( Abc_Lit2Var(pObj->Value) != Abc_Lit2Var(pRepr->Value) ) + Gia_ObjSetRepr( pNew, Abc_Lit2Var(pObj->Value), Abc_Lit2Var(pRepr->Value) ); + } + pNew->pNexts = Gia_ManDeriveNexts( pNew ); + } + if ( Gia_ManHasChoices(p) ) + { + Gia_Obj_t * pSibl; + pNew->pSibls = ABC_CALLOC( int, Gia_ManObjNum(pNew) ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( !~pObj->Value ) + continue; + pSibl = Gia_ObjSiblObj( p, i ); + if ( pSibl == NULL ) + continue; + if ( !~pSibl->Value ) + continue; + assert( !Gia_ObjIsBuf(pObj) ); + assert( Abc_Lit2Var(pObj->Value) > Abc_Lit2Var(pSibl->Value) ); + pNew->pSibls[Abc_Lit2Var(pObj->Value)] = Abc_Lit2Var(pSibl->Value); + } + } + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG while creating "parallel" copies.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupTimes( Gia_Man_t * p, int nTimes ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + Vec_Int_t * vPis, * vPos, * vRis, * vRos; + int i, t, Entry; + assert( nTimes > 0 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + vPis = Vec_IntAlloc( Gia_ManPiNum(p) * nTimes ); + vPos = Vec_IntAlloc( Gia_ManPoNum(p) * nTimes ); + vRis = Vec_IntAlloc( Gia_ManRegNum(p) * nTimes ); + vRos = Vec_IntAlloc( Gia_ManRegNum(p) * nTimes ); + for ( t = 0; t < nTimes; t++ ) + { + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCi(pObj) ) + { + pObj->Value = Gia_ManAppendCi( pNew ); + if ( Gia_ObjIsPi(p, pObj) ) + Vec_IntPush( vPis, Abc_Lit2Var(pObj->Value) ); + else + Vec_IntPush( vRos, Abc_Lit2Var(pObj->Value) ); + } + else if ( Gia_ObjIsCo(pObj) ) + { + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + if ( Gia_ObjIsPo(p, pObj) ) + Vec_IntPush( vPos, Abc_Lit2Var(pObj->Value) ); + else + Vec_IntPush( vRis, Abc_Lit2Var(pObj->Value) ); + } + } + } + Vec_IntClear( pNew->vCis ); + Vec_IntForEachEntry( vPis, Entry, i ) + { + Gia_ObjSetCioId( Gia_ManObj(pNew, Entry), Vec_IntSize(pNew->vCis) ); + Vec_IntPush( pNew->vCis, Entry ); + } + Vec_IntForEachEntry( vRos, Entry, i ) + { + Gia_ObjSetCioId( Gia_ManObj(pNew, Entry), Vec_IntSize(pNew->vCis) ); + Vec_IntPush( pNew->vCis, Entry ); + } + Vec_IntClear( pNew->vCos ); + Vec_IntForEachEntry( vPos, Entry, i ) + { + Gia_ObjSetCioId( Gia_ManObj(pNew, Entry), Vec_IntSize(pNew->vCos) ); + Vec_IntPush( pNew->vCos, Entry ); + } + Vec_IntForEachEntry( vRis, Entry, i ) + { + Gia_ObjSetCioId( Gia_ManObj(pNew, Entry), Vec_IntSize(pNew->vCos) ); + Vec_IntPush( pNew->vCos, Entry ); + } + Vec_IntFree( vPis ); + Vec_IntFree( vPos ); + Vec_IntFree( vRis ); + Vec_IntFree( vRos ); + Gia_ManSetRegNum( pNew, nTimes * Gia_ManRegNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates while adding self-loops to the registers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupMiterCones( Gia_Man_t * p, Vec_Int_t * vPairs ) +{ + Vec_Int_t * vTemp = Vec_IntAlloc( 100 ); + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, iLit0, iLit1; + pNew = Gia_ManStart( Gia_ManObjNum(p) + 3 * Vec_IntSize(vPairs) ); + pNew->pName = Abc_UtilStrsav( "miter" ); + Gia_ManHashAlloc( pNew ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Vec_IntForEachEntryDouble( vPairs, iLit0, iLit1, i ) + { + int Lit0 = Abc_LitNotCond( Gia_ManObj(p, Abc_Lit2Var(iLit0))->Value, Abc_LitIsCompl(iLit0) ); + int Lit1 = Abc_LitNotCond( Gia_ManObj(p, Abc_Lit2Var(iLit1))->Value, Abc_LitIsCompl(iLit1) ); + Vec_IntPush( vTemp, Gia_ManHashXor(pNew, Lit0, Lit1) ); + } + Vec_IntForEachEntry( vTemp, iLit0, i ) + Gia_ManAppendCo( pNew, iLit0 ); + Vec_IntFree( vTemp ); + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManDupDfs2_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return pObj->Value; + if ( p->pReprsOld && ~p->pReprsOld[Gia_ObjId(p, pObj)] ) + { + Gia_Obj_t * pRepr = Gia_ManObj( p, p->pReprsOld[Gia_ObjId(p, pObj)] ); + pRepr->Value = Gia_ManDupDfs2_rec( pNew, p, pRepr ); + return pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); + } + if ( Gia_ObjIsCi(pObj) ) + return pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManDupDfs2_rec( pNew, p, Gia_ObjFanin0(pObj) ); + if ( Gia_ObjIsCo(pObj) ) + return pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManDupDfs2_rec( pNew, p, Gia_ObjFanin1(pObj) ); + if ( Vec_IntSize(&pNew->vHTable) ) + return pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + return pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupDfs2( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj, * pObjNew; + int i; + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCo( p, pObj, i ) + Gia_ManDupDfs2_rec( pNew, p, pObj ); + Gia_ManForEachCi( p, pObj, i ) + if ( ~pObj->Value == 0 ) + pObj->Value = Gia_ManAppendCi(pNew); + assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(p) ); + // remap combinational inputs + Gia_ManForEachCi( p, pObj, i ) + { + pObjNew = Gia_ObjFromLit( pNew, pObj->Value ); + assert( !Gia_IsComplement(pObjNew) ); + Vec_IntWriteEntry( pNew->vCis, Gia_ObjCioId(pObj), Gia_ObjId(pNew, pObjNew) ); + Gia_ObjSetCioId( pObjNew, Gia_ObjCioId(pObj) ); + } + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDupDfs_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManDupDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManDupDfs_rec( pNew, p, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManDupDfs( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManDupDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew->nConstrs = p->nConstrs; + if ( p->pCexSeq ) + pNew->pCexSeq = Abc_CexDup( p->pCexSeq, Gia_ManRegNum(p) ); + return pNew; +} +Gia_Man_t * Gia_ManDupDfsOnePo( Gia_Man_t * p, int iPo ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i; + assert( iPo >= 0 && iPo < Gia_ManPoNum(p) ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachCo( p, pObj, i ) + if ( !Gia_ObjIsPo(p, pObj) || i == iPo ) + Gia_ManDupDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + if ( !Gia_ObjIsPo(p, pObj) || i == iPo ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDupDfsRehash_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManDupDfsRehash_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManDupDfsRehash_rec( pNew, p, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManDupDfsRehash( Gia_Man_t * p ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManDupDfsRehash_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew->nConstrs = p->nConstrs; + if ( p->pCexSeq ) + pNew->pCexSeq = Abc_CexDup( p->pCexSeq, Gia_ManRegNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Cofactors w.r.t. a primary input variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDupCofactorVar_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManDupCofactorVar_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManDupCofactorVar_rec( pNew, p, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManDupCofactorVar( Gia_Man_t * p, int iVar, int Value ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i; + assert( iVar >= 0 && iVar < Gia_ManPiNum(p) ); + assert( Value == 0 || Value == 1 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManPi( p, iVar )->Value = Value; // modification! + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManDupCofactorVar_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew->nConstrs = p->nConstrs; + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} +Gia_Man_t * Gia_ManDupMux( int iVar, Gia_Man_t * pCof1, Gia_Man_t * pCof0 ) +{ + Gia_Man_t * pGia[2] = {pCof0, pCof1}; + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, n; + assert( Gia_ManRegNum(pCof0) == 0 ); + assert( Gia_ManRegNum(pCof1) == 0 ); + assert( Gia_ManCoNum(pCof0) == 1 ); + assert( Gia_ManCoNum(pCof1) == 1 ); + assert( Gia_ManCiNum(pCof1) == Gia_ManCiNum(pCof0) ); + assert( iVar >= 0 && iVar < Gia_ManCiNum(pCof1) ); + pNew = Gia_ManStart( Gia_ManObjNum(pCof1) + Gia_ManObjNum(pCof0) ); + pNew->pName = Abc_UtilStrsav( pCof1->pName ); + pNew->pSpec = Abc_UtilStrsav( pCof1->pSpec ); + Gia_ManHashAlloc( pNew ); + for ( n = 0; n < 2; n++ ) + { + Gia_ManFillValue( pGia[n] ); + Gia_ManConst0(pGia[n])->Value = 0; + Gia_ManForEachCi( pGia[n], pObj, i ) + pObj->Value = n ? Gia_ManCi(pGia[0], i)->Value : Gia_ManAppendCi(pNew); + Gia_ManForEachCo( pGia[n], pObj, i ) + Gia_ManDupCofactorVar_rec( pNew, pGia[n], Gia_ObjFanin0(pObj) ); + } + Gia_ManForEachCo( pGia[0], pObj, i ) + { + int Ctrl = Gia_ManCi(pGia[0], iVar)->Value; + int Lit1 = Gia_ObjFanin0Copy(Gia_ManCo(pGia[1], i)); + int Lit0 = Gia_ObjFanin0Copy(pObj); + Gia_ManAppendCo( pNew, Gia_ManHashMux( pNew, Ctrl, Lit1, Lit0 ) ); + } + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Cofactors w.r.t. an internal node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupCofactorObj( Gia_Man_t * p, int iObj, int Value ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, iObjValue = -1; + assert( Gia_ManRegNum(p) == 0 ); + assert( iObj > 0 && iObj < Gia_ManObjNum(p) ); + assert( Gia_ObjIsCand(Gia_ManObj(p, iObj)) ); + assert( Value == 0 || Value == 1 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ManHashAnd(pNew, Gia_ObjFanin0Copy(pObj), iObjValue) ); + if ( i == iObj ) + iObjValue = Abc_LitNotCond(pObj->Value, !Value), pObj->Value = Value; + } + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Reduce bit-width of GIA assuming it is Boolean.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupBlock( Gia_Man_t * p, int nBlock ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; int i; + assert( Gia_ManCiNum(p) % nBlock == 0 ); + assert( Gia_ManCoNum(p) % nBlock == 0 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = (i % nBlock == 0) ? Gia_ManAppendCi(pNew) : 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + if ( i % nBlock == 0 ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p)/nBlock ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Existentially quantified given variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupExist( Gia_Man_t * p, int iVar ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i; + assert( iVar >= 0 && iVar < Gia_ManPiNum(p) ); + assert( Gia_ManPoNum(p) == 1 ); + assert( Gia_ManRegNum(p) == 0 ); + Gia_ManFillValue( p ); + // find the cofactoring variable + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + // compute negative cofactor + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManPi( p, iVar )->Value = Abc_Var2Lit( 0, 0 ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachPo( p, pObj, i ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + // compute the positive cofactor + Gia_ManPi( p, iVar )->Value = Abc_Var2Lit( 0, 1 ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + // create OR gate + Gia_ManForEachPo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ManHashOr(pNew, Gia_ObjFanin0Copy(pObj), pObj->Value) ); + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Existentially quantified given variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupUniv( Gia_Man_t * p, int iVar ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i; + assert( iVar >= 0 && iVar < Gia_ManPiNum(p) ); + assert( Gia_ManRegNum(p) == 0 ); + Gia_ManFillValue( p ); + // find the cofactoring variable + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + // compute negative cofactor + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManPi( p, iVar )->Value = Abc_Var2Lit( 0, 0 ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachPo( p, pObj, i ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + // compute the positive cofactor + Gia_ManPi( p, iVar )->Value = Abc_Var2Lit( 0, 1 ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + // create OR gate + Gia_ManForEachPo( p, pObj, i ) + { + if ( i == 0 ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ManHashAnd(pNew, Gia_ObjFanin0Copy(pObj), pObj->Value) ); + else + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Existentially quantifies the given variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupExist2( Gia_Man_t * p, int iVar ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i; + assert( iVar >= 0 && iVar < Gia_ManPiNum(p) ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue( p ); + Gia_ManHashAlloc( pNew ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + // first part + Gia_ManPi( p, iVar )->Value = 0; // modification! + Gia_ManForEachCo( p, pObj, i ) + Gia_ManDupCofactorVar_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + // second part + Gia_ManPi( p, iVar )->Value = 1; // modification! + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = ~0; + Gia_ManForEachCo( p, pObj, i ) + Gia_ManDupCofactorVar_rec( pNew, p, Gia_ObjFanin0(pObj) ); + // combination + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ManHashOr(pNew, Gia_ObjFanin0Copy(pObj), pObj->Value) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew->nConstrs = p->nConstrs; + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Duplicates AIG in the DFS order while putting CIs first.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupDfsSkip( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachCo( p, pObj, i ) + if ( pObj->fMark1 == 0 ) + Gia_ManDupDfs_rec( pNew, p, pObj ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG in the DFS order while putting CIs first.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupDfsCone( Gia_Man_t * p, Gia_Obj_t * pRoot ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + assert( Gia_ObjIsCo(pRoot) ); + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManDupDfs_rec( pNew, p, Gia_ObjFanin0(pRoot) ); + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pRoot) ); + Gia_ManSetRegNum( pNew, 0 ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates logic cone of the literal and inserts it back.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDupConeSupp_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vObjs ) +{ + int iLit0, iLit1, iObj = Gia_ObjId( p, pObj ); + int iLit = Gia_ObjCopyArray( p, iObj ); + if ( iLit >= 0 ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManDupConeSupp_rec( pNew, p, Gia_ObjFanin0(pObj), vObjs ); + Gia_ManDupConeSupp_rec( pNew, p, Gia_ObjFanin1(pObj), vObjs ); + iLit0 = Gia_ObjCopyArray( p, Gia_ObjFaninId0(pObj, iObj) ); + iLit1 = Gia_ObjCopyArray( p, Gia_ObjFaninId1(pObj, iObj) ); + iLit0 = Abc_LitNotCond( iLit0, Gia_ObjFaninC0(pObj) ); + iLit1 = Abc_LitNotCond( iLit1, Gia_ObjFaninC1(pObj) ); + iLit = Gia_ManAppendAnd( pNew, iLit0, iLit1 ); + Gia_ObjSetCopyArray( p, iObj, iLit ); + Vec_IntPush( vObjs, iObj ); +} +Gia_Man_t * Gia_ManDupConeSupp( Gia_Man_t * p, int iLit, Vec_Int_t * vCiIds ) +{ + Gia_Man_t * pNew; int i, iLit0; + Gia_Obj_t * pObj, * pRoot = Gia_ManObj( p, Abc_Lit2Var(iLit) ); + Vec_Int_t * vObjs = Vec_IntAlloc( 1000 ); + //assert( Gia_ObjIsAnd(pRoot) ); + if ( Vec_IntSize(&p->vCopies) < Gia_ManObjNum(p) ) + Vec_IntFillExtra( &p->vCopies, Gia_ManObjNum(p), -1 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManForEachCiVec( vCiIds, p, pObj, i ) + Gia_ObjSetCopyArray( p, Gia_ObjId(p, pObj), Gia_ManAppendCi(pNew) ); + Gia_ManDupConeSupp_rec( pNew, p, pRoot, vObjs ); + iLit0 = Gia_ObjCopyArray( p, Abc_Lit2Var(iLit) ); + iLit0 = Abc_LitNotCond( iLit0, Abc_LitIsCompl(iLit) ); + Gia_ManAppendCo( pNew, iLit0 ); + Gia_ManForEachCiVec( vCiIds, p, pObj, i ) + Gia_ObjSetCopyArray( p, Gia_ObjId(p, pObj), -1 ); + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + Gia_ObjSetCopyArray( p, Gia_ObjId(p, pObj), -1 ); + Vec_IntFree( vObjs ); + //assert( Vec_IntCountLarger(&p->vCopies, -1) == 0 ); + return pNew; +} +void Gia_ManDupConeBack_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManDupConeBack_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManDupConeBack_rec( pNew, p, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +// pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +int Gia_ManDupConeBack( Gia_Man_t * p, Gia_Man_t * pNew, Vec_Int_t * vCiIds ) +{ + Gia_Obj_t * pObj, * pRoot; int i; + assert( Gia_ManCiNum(pNew) == Vec_IntSize(vCiIds) ); + Gia_ManFillValue(pNew); + Gia_ManConst0(pNew)->Value = 0; + Gia_ManForEachCi( pNew, pObj, i ) + pObj->Value = Gia_Obj2Lit( p, Gia_ManCi(p, Vec_IntEntry(vCiIds, i)) ); + pRoot = Gia_ManCo(pNew, 0); + Gia_ManDupConeBack_rec( p, pNew, Gia_ObjFanin0(pRoot) ); + return Gia_ObjFanin0Copy(pRoot); +} +int Gia_ManDupConeBackObjs( Gia_Man_t * p, Gia_Man_t * pNew, Vec_Int_t * vObjs ) +{ + Gia_Obj_t * pObj, * pRoot; int i; + assert( Gia_ManCiNum(pNew) == Vec_IntSize(vObjs) ); + Gia_ManFillValue(pNew); + Gia_ManConst0(pNew)->Value = 0; + Gia_ManForEachCi( pNew, pObj, i ) + pObj->Value = Abc_Var2Lit( Vec_IntEntry(vObjs, i), 0 ); + pRoot = Gia_ManCo(pNew, 0); + Gia_ManDupConeBack_rec( p, pNew, Gia_ObjFanin0(pRoot) ); + return Gia_ObjFanin0Copy(pRoot); +} + + +/**Function************************************************************* + + Synopsis [Duplicates AIG in the DFS order while putting CIs first.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDupDfs3_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return; + if ( Gia_ObjIsCi(pObj) ) + { + pObj->Value = Gia_ManAppendCi(pNew); + return; + } + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManDupDfs3_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManDupDfs3_rec( pNew, p, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManDupDfsNode( Gia_Man_t * p, Gia_Obj_t * pRoot ) +{ + Gia_Man_t * pNew; + assert( Gia_ObjIsAnd(pRoot) ); + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManDupDfs3_rec( pNew, p, pRoot ); + Gia_ManAppendCo( pNew, pRoot->Value ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG in the DFS order while putting CIs first.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupDfsLitArray( Gia_Man_t * p, Vec_Int_t * vLits ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i, iLit, iLitRes; + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Vec_IntForEachEntry( vLits, iLit, i ) + { + iLitRes = Gia_ManDupDfs2_rec( pNew, p, Gia_ManObj(p, Abc_Lit2Var(iLit)) ); + Gia_ManAppendCo( pNew, Abc_LitNotCond( iLitRes, Abc_LitIsCompl(iLit)) ); + } + Gia_ManSetRegNum( pNew, 0 ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Returns the array of non-const-0 POs of the dual-output miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManDupTrimmedNonZero( Gia_Man_t * p ) +{ + Vec_Int_t * vNonZero; + Gia_Man_t * pTemp, * pNonDual; + Gia_Obj_t * pObj; + int i; + assert( (Gia_ManPoNum(p) & 1) == 0 ); + pNonDual = Gia_ManTransformMiter( p ); + pNonDual = Gia_ManSeqStructSweep( pTemp = pNonDual, 1, 1, 0 ); + Gia_ManStop( pTemp ); + assert( Gia_ManPiNum(pNonDual) > 0 ); + assert( 2 * Gia_ManPoNum(pNonDual) == Gia_ManPoNum(p) ); + // skip PO pairs corresponding to const0 POs of the non-dual miter + vNonZero = Vec_IntAlloc( 100 ); + Gia_ManForEachPo( pNonDual, pObj, i ) + if ( !Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) + Vec_IntPush( vNonZero, i ); + Gia_ManStop( pNonDual ); + return vNonZero; +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if PO can be removed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManPoIsToRemove( Gia_Man_t * p, Gia_Obj_t * pObj, int Value ) +{ + assert( Gia_ObjIsCo(pObj) ); + if ( Value == -1 ) + return Gia_ObjIsConst0(Gia_ObjFanin0(pObj)); + assert( Value == 0 || Value == 1 ); + return Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) && Value == Gia_ObjFaninC0(pObj); +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG in the DFS order while putting CIs first.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupTrimmed( Gia_Man_t * p, int fTrimCis, int fTrimCos, int fDualOut, int OutValue ) +{ + Vec_Int_t * vNonZero = NULL; + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, Entry; + // collect non-zero + if ( fDualOut && fTrimCos ) + vNonZero = Gia_ManDupTrimmedNonZero( p ); + // start new manager + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + // check if there are PIs to be added + Gia_ManCreateRefs( p ); + Gia_ManForEachPi( p, pObj, i ) + if ( !fTrimCis || Gia_ObjRefNum(p, pObj) ) + break; + if ( i == Gia_ManPiNum(p) ) // there is no PIs - add dummy PI + Gia_ManAppendCi(pNew); + // add the ROs + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + if ( !fTrimCis || Gia_ObjRefNum(p, pObj) || Gia_ObjIsRo(p, pObj) ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( fDualOut && fTrimCos ) + { + Vec_IntForEachEntry( vNonZero, Entry, i ) + { + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManPo(p, 2*Entry+0)) ); + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManPo(p, 2*Entry+1)) ); + } + if ( Gia_ManPoNum(pNew) == 0 ) // nothing - add dummy PO + { +// Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManPo(p, 0)) ); +// Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManPo(p, 1)) ); + Gia_ManAppendCo( pNew, 0 ); + Gia_ManAppendCo( pNew, 0 ); + } + Gia_ManForEachRi( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + // cleanup + pNew = Gia_ManSeqStructSweep( pTemp = pNew, 1, 1, 0 ); + Gia_ManStop( pTemp ); + // trim the PIs +// pNew = Gia_ManDupTrimmed( pTemp = pNew, 1, 0, 0 ); +// Gia_ManStop( pTemp ); + } + else + { + // check if there are POs to be added + Gia_ManForEachPo( p, pObj, i ) + if ( !fTrimCos || !Gia_ManPoIsToRemove(p, pObj, OutValue) ) + break; + if ( i == Gia_ManPoNum(p) ) // there is no POs - add dummy PO + Gia_ManAppendCo( pNew, 0 ); + Gia_ManForEachCo( p, pObj, i ) + if ( !fTrimCos || !Gia_ManPoIsToRemove(p, pObj, OutValue) || Gia_ObjIsRi(p, pObj) ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + } + Vec_IntFreeP( &vNonZero ); + assert( !Gia_ManHasDangling( pNew ) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Removes POs driven by PIs and PIs without fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupTrimmed2( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + // start new manager + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + // check if there are PIs to be added + Gia_ManCreateRefs( p ); + // discount references of POs + Gia_ManForEachPo( p, pObj, i ) + Gia_ObjRefFanin0Dec( p, pObj ); + // check if PIs are left + Gia_ManForEachPi( p, pObj, i ) + if ( Gia_ObjRefNum(p, pObj) ) + break; + if ( i == Gia_ManPiNum(p) ) // there is no PIs - add dummy PI + Gia_ManAppendCi(pNew); + // add the ROs + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + if ( Gia_ObjRefNum(p, pObj) || Gia_ObjIsRo(p, pObj) ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + // check if there are POs to be added + Gia_ManForEachPo( p, pObj, i ) + if ( !Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) && !Gia_ObjIsPi(p, Gia_ObjFanin0(pObj)) ) + break; + if ( i == Gia_ManPoNum(p) ) // there is no POs - add dummy PO + Gia_ManAppendCo( pNew, 0 ); + Gia_ManForEachCo( p, pObj, i ) + if ( (!Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) && !Gia_ObjIsPi(p, Gia_ObjFanin0(pObj))) || Gia_ObjIsRi(p, pObj) ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + assert( !Gia_ManHasDangling( pNew ) ); + return pNew; +} +Gia_Man_t * Gia_ManDupTrimmed3( Gia_Man_t * p ) +{ + Vec_Int_t * vMap = Vec_IntStartFull( Gia_ManObjNum(p) ); + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + // mark duplicated POs + Gia_ManForEachPo( p, pObj, i ) + Vec_IntWriteEntry( vMap, Gia_ObjFaninId0p(p, pObj), i ); + Gia_ManForEachPo( p, pObj, i ) + if ( Vec_IntEntry(vMap, Gia_ObjFaninId0p(p, pObj)) == i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Vec_IntFree( vMap ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG in the DFS order while putting CIs first.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupOntop( Gia_Man_t * p, Gia_Man_t * p2 ) +{ + Gia_Man_t * pTemp, * pNew; + Gia_Obj_t * pObj; + int i; + assert( Gia_ManPoNum(p) == Gia_ManPiNum(p2) ); + assert( Gia_ManRegNum(p) == 0 ); + assert( Gia_ManRegNum(p2) == 0 ); + pNew = Gia_ManStart( Gia_ManObjNum(p)+Gia_ManObjNum(p2) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + // dup first AIG + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + // dup second AIG + Gia_ManConst0(p2)->Value = 0; + Gia_ManForEachCo( p, pObj, i ) + Gia_ManPi(p2, i)->Value = Gia_ObjFanin0Copy(pObj); + Gia_ManForEachAnd( p2, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p2, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManHashStop( pNew ); +// Gia_ManPrintStats( pGiaNew, 0 ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates transition relation from p1 and property from p2.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupWithNewPo( Gia_Man_t * p1, Gia_Man_t * p2 ) +{ + Gia_Man_t * pTemp, * pNew; + Gia_Obj_t * pObj; + int i; + // there is no flops in p2 + assert( Gia_ManRegNum(p2) == 0 ); + // there is only one PO in p2 +// assert( Gia_ManPoNum(p2) == 1 ); + // input count of p2 is equal to flop count of p1 + assert( Gia_ManPiNum(p2) == Gia_ManRegNum(p1) ); + + // start new AIG + pNew = Gia_ManStart( Gia_ManObjNum(p1)+Gia_ManObjNum(p2) ); + pNew->pName = Abc_UtilStrsav( p1->pName ); + pNew->pSpec = Abc_UtilStrsav( p1->pSpec ); + Gia_ManHashAlloc( pNew ); + // dup first AIG + Gia_ManConst0(p1)->Value = 0; + Gia_ManForEachCi( p1, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachAnd( p1, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + // dup second AIG + Gia_ManConst0(p2)->Value = 0; + Gia_ManForEachPi( p2, pObj, i ) + pObj->Value = Gia_ManRo(p1, i)->Value; + Gia_ManForEachAnd( p2, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + // add property output + Gia_ManForEachPo( p2, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + // add flop inputs + Gia_ManForEachRi( p1, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p1) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Print representatives.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintRepr( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachObj( p, pObj, i ) + if ( ~p->pReprsOld[i] ) + printf( "%d->%d ", i, p->pReprs[i].iRepr ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupDfsCiMap( Gia_Man_t * p, int * pCi2Lit, Vec_Int_t * vLits ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + { + pObj->Value = Gia_ManAppendCi(pNew); + if ( ~pCi2Lit[i] ) + pObj->Value = Abc_LitNotCond( Gia_ManObj(p, Abc_Lit2Var(pCi2Lit[i]))->Value, Abc_LitIsCompl(pCi2Lit[i]) ); + } + Gia_ManHashAlloc( pNew ); + if ( vLits ) + { + int iLit, iLitRes; + Vec_IntForEachEntry( vLits, iLit, i ) + { + iLitRes = Gia_ManDupDfs2_rec( pNew, p, Gia_ManObj(p, Abc_Lit2Var(iLit)) ); + Gia_ManAppendCo( pNew, Abc_LitNotCond( iLitRes, Abc_LitIsCompl(iLit)) ); + } + } + else + { + Gia_ManForEachCo( p, pObj, i ) + { + Gia_ManDupDfs2_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + } + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Permute inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManPermuteInputs( Gia_Man_t * p, int nPpis, int nExtra ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + for ( i = 0; i < Gia_ManPiNum(p) - nPpis - nExtra; i++ ) // regular PIs + Gia_ManCi(p, i)->Value = Gia_ManAppendCi( pNew ); + for ( i = Gia_ManPiNum(p) - nExtra; i < Gia_ManPiNum(p); i++ ) // extra PIs due to DC values + Gia_ManCi(p, i)->Value = Gia_ManAppendCi( pNew ); + for ( i = Gia_ManPiNum(p) - nPpis - nExtra; i < Gia_ManPiNum(p) - nExtra; i++ ) // pseudo-PIs + Gia_ManCi(p, i)->Value = Gia_ManAppendCi( pNew ); + for ( i = Gia_ManPiNum(p); i < Gia_ManCiNum(p); i++ ) // flop outputs + Gia_ManCi(p, i)->Value = Gia_ManAppendCi( pNew ); + assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(p) ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupDfsClasses( Gia_Man_t * p ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i; + assert( p->pReprsOld != NULL ); + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManDupDfs_rec( pNew, p, pObj ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Detect topmost gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupTopAnd_iter( Gia_Man_t * p, int fVerbose ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + Vec_Int_t * vFront, * vLeaves; + int i, iLit, iObjId, nCiLits, * pCi2Lit; + char * pVar2Val; + // collect the frontier + vFront = Vec_IntAlloc( 1000 ); + vLeaves = Vec_IntAlloc( 1000 ); + Gia_ManForEachCo( p, pObj, i ) + { + if ( Gia_ObjIsConst0( Gia_ObjFanin0(pObj) ) ) + continue; + if ( Gia_ObjFaninC0(pObj) ) + Vec_IntPush( vLeaves, Gia_ObjFaninLit0p(p, pObj) ); + else + Vec_IntPush( vFront, Gia_ObjFaninId0p(p, pObj) ); + } + if ( Vec_IntSize(vFront) == 0 ) + { + if ( fVerbose ) + printf( "The AIG cannot be decomposed using AND-decomposition.\n" ); + Vec_IntFree( vFront ); + Vec_IntFree( vLeaves ); + return Gia_ManDupNormalize( p, 0 ); + } + // expand the frontier + Gia_ManForEachObjVec( vFront, p, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + { + Vec_IntPush( vLeaves, Abc_Var2Lit( Gia_ObjId(p, pObj), 0 ) ); + continue; + } + assert( Gia_ObjIsAnd(pObj) ); + if ( Gia_ObjFaninC0(pObj) ) + Vec_IntPush( vLeaves, Gia_ObjFaninLit0p(p, pObj) ); + else + Vec_IntPush( vFront, Gia_ObjFaninId0p(p, pObj) ); + if ( Gia_ObjFaninC1(pObj) ) + Vec_IntPush( vLeaves, Gia_ObjFaninLit1p(p, pObj) ); + else + Vec_IntPush( vFront, Gia_ObjFaninId1p(p, pObj) ); + } + Vec_IntFree( vFront ); + // sort the literals + nCiLits = 0; + pCi2Lit = ABC_FALLOC( int, Gia_ManObjNum(p) ); + pVar2Val = ABC_FALLOC( char, Gia_ManObjNum(p) ); + Vec_IntForEachEntry( vLeaves, iLit, i ) + { + iObjId = Abc_Lit2Var(iLit); + pObj = Gia_ManObj(p, iObjId); + if ( Gia_ObjIsCi(pObj) ) + { + pCi2Lit[Gia_ObjCioId(pObj)] = !Abc_LitIsCompl(iLit); + nCiLits++; + } + if ( pVar2Val[iObjId] != 0 && pVar2Val[iObjId] != 1 ) + pVar2Val[iObjId] = Abc_LitIsCompl(iLit); + else if ( pVar2Val[iObjId] != Abc_LitIsCompl(iLit) ) + break; + } + if ( i < Vec_IntSize(vLeaves) ) + { + printf( "Problem is trivially UNSAT.\n" ); + ABC_FREE( pCi2Lit ); + ABC_FREE( pVar2Val ); + Vec_IntFree( vLeaves ); + return Gia_ManDupNormalize( p, 0 ); + } + // create array of input literals + Vec_IntClear( vLeaves ); + Gia_ManForEachObj( p, pObj, i ) + if ( !Gia_ObjIsCi(pObj) && (pVar2Val[i] == 0 || pVar2Val[i] == 1) ) + Vec_IntPush( vLeaves, Abc_Var2Lit(i, pVar2Val[i]) ); + if ( fVerbose ) + printf( "Detected %6d AND leaves and %6d CI leaves.\n", Vec_IntSize(vLeaves), nCiLits ); + // create the input map + if ( nCiLits == 0 ) + pNew = Gia_ManDupDfsLitArray( p, vLeaves ); + else + pNew = Gia_ManDupDfsCiMap( p, pCi2Lit, vLeaves ); + ABC_FREE( pCi2Lit ); + ABC_FREE( pVar2Val ); + Vec_IntFree( vLeaves ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Detect topmost gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupTopAnd( Gia_Man_t * p, int fVerbose ) +{ + Gia_Man_t * pNew, * pTemp; + int fContinue, iIter = 0; + pNew = Gia_ManDupNormalize( p, 0 ); + for ( fContinue = 1; fContinue; ) + { + pNew = Gia_ManDupTopAnd_iter( pTemp = pNew, fVerbose ); + if ( Gia_ManCoNum(pNew) == Gia_ManCoNum(pTemp) && Gia_ManAndNum(pNew) == Gia_ManAndNum(pTemp) ) + fContinue = 0; + Gia_ManStop( pTemp ); + if ( fVerbose ) + { + printf( "Iter %2d : ", ++iIter ); + Gia_ManPrintStatsShort( pNew ); + } + } + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManMiter_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return pObj->Value; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManMiter_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManMiter_rec( pNew, p, Gia_ObjFanin1(pObj) ); + return pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Creates miter of two designs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManMiter( Gia_Man_t * p0, Gia_Man_t * p1, int nInsDup, int fDualOut, int fSeq, int fImplic, int fVerbose ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, iLit; + if ( fSeq ) + { + if ( Gia_ManPiNum(p0) != Gia_ManPiNum(p1) ) + { + printf( "Gia_ManMiter(): Designs have different number of PIs.\n" ); + return NULL; + } + if ( Gia_ManPoNum(p0) != Gia_ManPoNum(p1) ) + { + printf( "Gia_ManMiter(): Designs have different number of POs.\n" ); + return NULL; + } + if ( Gia_ManRegNum(p0) == 0 || Gia_ManRegNum(p1) == 0 ) + { + printf( "Gia_ManMiter(): At least one of the designs has no registers.\n" ); + return NULL; + } + } + else + { + if ( Gia_ManCiNum(p0) != Gia_ManCiNum(p1) ) + { + printf( "Gia_ManMiter(): Designs have different number of CIs.\n" ); + return NULL; + } + if ( Gia_ManCoNum(p0) != Gia_ManCoNum(p1) ) + { + printf( "Gia_ManMiter(): Designs have different number of COs.\n" ); + return NULL; + } + } + // start the manager + pNew = Gia_ManStart( Gia_ManObjNum(p0) + Gia_ManObjNum(p1) ); + pNew->pName = Abc_UtilStrsav( "miter" ); + // map combinational inputs + Gia_ManFillValue( p0 ); + Gia_ManFillValue( p1 ); + Gia_ManConst0(p0)->Value = 0; + Gia_ManConst0(p1)->Value = 0; + // map internal nodes and outputs + Gia_ManHashAlloc( pNew ); + if ( fSeq ) + { + // create primary inputs + Gia_ManForEachPi( p0, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachPi( p1, pObj, i ) + if ( i < Gia_ManPiNum(p1) - nInsDup ) + pObj->Value = Gia_ObjToLit( pNew, Gia_ManPi(pNew, i) ); + else + pObj->Value = Gia_ManAppendCi( pNew ); + // create latch outputs + Gia_ManForEachRo( p0, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachRo( p1, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + // create primary outputs + Gia_ManForEachPo( p0, pObj, i ) + { + Gia_ManMiter_rec( pNew, p0, Gia_ObjFanin0(pObj) ); + Gia_ManMiter_rec( pNew, p1, Gia_ObjFanin0(Gia_ManPo(p1,i)) ); + if ( fDualOut ) + { + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManPo(p1,i)) ); + } + else if ( fImplic ) + { + iLit = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Abc_LitNot(Gia_ObjFanin0Copy(Gia_ManPo(p1,i))) ); + Gia_ManAppendCo( pNew, iLit ); + } + else + { + iLit = Gia_ManHashXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin0Copy(Gia_ManPo(p1,i)) ); + Gia_ManAppendCo( pNew, iLit ); + } + } + // create register inputs + Gia_ManForEachRi( p0, pObj, i ) + { + Gia_ManMiter_rec( pNew, p0, Gia_ObjFanin0(pObj) ); + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManForEachRi( p1, pObj, i ) + { + Gia_ManMiter_rec( pNew, p1, Gia_ObjFanin0(pObj) ); + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p0) + Gia_ManRegNum(p1) ); + } + else + { + // create combinational inputs + Gia_ManForEachCi( p0, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachCi( p1, pObj, i ) + if ( i < Gia_ManCiNum(p1) - nInsDup ) + pObj->Value = Gia_ObjToLit( pNew, Gia_ManCi(pNew, i) ); + else + pObj->Value = Gia_ManAppendCi( pNew ); + // create combinational outputs + Gia_ManForEachCo( p0, pObj, i ) + { + Gia_ManMiter_rec( pNew, p0, Gia_ObjFanin0(pObj) ); + Gia_ManMiter_rec( pNew, p1, Gia_ObjFanin0(Gia_ManCo(p1,i)) ); + if ( fDualOut ) + { + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManCo(p1,i)) ); + } + else if ( fImplic ) + { + iLit = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Abc_LitNot(Gia_ObjFanin0Copy(Gia_ManPo(p1,i))) ); + Gia_ManAppendCo( pNew, iLit ); + } + else + { + iLit = Gia_ManHashXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin0Copy(Gia_ManCo(p1,i)) ); + Gia_ManAppendCo( pNew, iLit ); + } + } + } + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + + pNew = Gia_ManDupNormalize( pTemp = pNew, 0 ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Creates miter of two designs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManMiterInverse( Gia_Man_t * pBot, Gia_Man_t * pTop, int fDualOut, int fVerbose ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, iLit; + int nInputs1 = Gia_ManCiNum(pTop) - Gia_ManCoNum(pBot); + int nInputs2 = Gia_ManCiNum(pBot) - Gia_ManCoNum(pTop); + if ( nInputs1 == nInputs2 ) + printf( "Assuming that the circuits have %d shared inputs, ordered first.\n", nInputs1 ); + else + { + printf( "The number of inputs and outputs does not match.\n" ); + return NULL; + } + pNew = Gia_ManStart( Gia_ManObjNum(pBot) + Gia_ManObjNum(pTop) ); + pNew->pName = Abc_UtilStrsav( "miter" ); + Gia_ManFillValue( pBot ); + Gia_ManFillValue( pTop ); + Gia_ManConst0(pBot)->Value = 0; + Gia_ManConst0(pTop)->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCi( pBot, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); +// Gia_ManForEachCo( pBot, pObj, i ) +// Gia_ManMiter_rec( pNew, pBot, Gia_ObjFanin0(pObj) ); + Gia_ManForEachAnd( pBot, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + Gia_ManForEachCo( pBot, pObj, i ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + Gia_ManForEachCi( pTop, pObj, i ) + if ( i < nInputs1 ) + pObj->Value = Gia_ManCi(pBot, i)->Value; + else + pObj->Value = Gia_ManCo(pBot, i-nInputs1)->Value; +// Gia_ManForEachCo( pTop, pObj, i ) +// Gia_ManMiter_rec( pNew, pTop, Gia_ObjFanin0(pObj) ); + Gia_ManForEachAnd( pTop, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + Gia_ManForEachCo( pTop, pObj, i ) + { + if ( fDualOut ) + { + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManAppendCo( pNew, Gia_ManCi(pBot, i+nInputs1)->Value ); + } + else + { + iLit = Gia_ManHashXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ManCi(pBot, i+nInputs1)->Value ); + Gia_ManAppendCo( pNew, iLit ); + } + } + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + assert( (pBot->vBarBufs == NULL) == (pTop->vBarBufs == NULL) ); + if ( pBot->vBarBufs ) + { + pNew->vBarBufs = Vec_IntAlloc( 1000 ); + Vec_IntAppend( pNew->vBarBufs, pBot->vBarBufs ); + Vec_IntAppend( pNew->vBarBufs, pTop->vBarBufs ); + //printf( "Miter has %d buffers (%d groups).\n", pNew->nBufs, Vec_IntSize(pNew->vBarBufs) ); + } + return pNew; +} + +/**Function************************************************************* + + Synopsis [Computes the AND of all POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupAndOr( Gia_Man_t * p, int nOuts, int fUseOr, int fCompl ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, iResult; + assert( Gia_ManRegNum(p) == 0 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( fUseOr ) // construct OR of all POs + { + iResult = 0; + Gia_ManForEachPo( p, pObj, i ) + iResult = Gia_ManHashOr( pNew, iResult, Gia_ObjFanin0Copy(pObj) ); + } + else // construct AND of all POs + { + iResult = 1; + Gia_ManForEachPo( p, pObj, i ) + iResult = Gia_ManHashAnd( pNew, iResult, Gia_ObjFanin0Copy(pObj) ); + } + iResult = Abc_LitNotCond( iResult, (int)(fCompl > 0) ); +// Gia_ManForEachPo( p, pObj, i ) +// pObj->Value = Gia_ManAppendCo( pNew, iResult ); + for ( i = 0; i < nOuts; i++ ) + Gia_ManAppendCo( pNew, iResult ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Transforms output names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Gia_ManMiterNames( Vec_Ptr_t * p, int nOuts ) +{ + char * pName1, * pName2, pBuffer[1000]; int i; + Vec_Ptr_t * pNew = Vec_PtrAlloc( Vec_PtrSize(p) - nOuts/2 ); + assert( nOuts % 2 == 0 ); + assert( nOuts <= Vec_PtrSize(p) ); + Vec_PtrForEachEntryDouble( char *, char *, p, pName1, pName2, i ) + { + if ( i == nOuts ) + break; + sprintf( pBuffer, "%s_xor_%s", pName1, pName2 ); + Vec_PtrPush( pNew, Abc_UtilStrsav(pBuffer) ); + } + Vec_PtrForEachEntryStart( char *, p, pName1, i, i ) + Vec_PtrPush( pNew, Abc_UtilStrsav(pName1) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Pair-wise miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManPairWiseMiter( Gia_Man_t * p ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pObj2; + int i, k, iLit; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachPo( p, pObj, i ) + Gia_ManForEachPo( p, pObj2, k ) + { + if ( i >= k ) + continue; + iLit = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin0Copy(pObj2) ); + Gia_ManAppendCo( pNew, iLit ); + } + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Transforms the circuit into a regular miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManTransformMiter( Gia_Man_t * p ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pObj2; + int i, iLit; + assert( (Gia_ManPoNum(p) & 1) == 0 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachPo( p, pObj, i ) + { + pObj2 = Gia_ManPo( p, ++i ); + iLit = Gia_ManHashXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin0Copy(pObj2) ); + Gia_ManAppendCo( pNew, iLit ); + } + Gia_ManForEachRi( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + if ( p->vNamesIn ) + pNew->vNamesIn = Vec_PtrDupStr(p->vNamesIn); + if ( p->vNamesOut ) + pNew->vNamesOut = Gia_ManMiterNames(p->vNamesOut, Gia_ManPoNum(p)); + return pNew; +} +Gia_Man_t * Gia_ManTransformMiter2( Gia_Man_t * p ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pObj2; + int i, iLit, nPart = Gia_ManPoNum(p)/2; + assert( (Gia_ManPoNum(p) & 1) == 0 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachPo( p, pObj, i ) + { + if ( i == nPart ) + break; + pObj2 = Gia_ManPo( p, nPart + i ); + iLit = Gia_ManHashXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin0Copy(pObj2) ); + Gia_ManAppendCo( pNew, iLit ); + } + Gia_ManForEachRi( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} +Gia_Man_t * Gia_ManTransformToDual( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachPo( p, pObj, i ) + { + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManAppendCo( pNew, 0 ); + } + Gia_ManForEachRi( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} +Gia_Man_t * Gia_ManTransformTwoWord2DualOutput( Gia_Man_t * p ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pObj2; + int i, nPart = Gia_ManPoNum(p)/2; + assert( (Gia_ManPoNum(p) & 1) == 0 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachPo( p, pObj, i ) + { + if ( i == nPart ) + break; + pObj2 = Gia_ManPo( p, nPart + i ); + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj2) ); + } + Gia_ManForEachRi( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +void Gia_ManCollectOneSide_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( !Gia_ObjIsAnd(pObj) ) + return; + Gia_ManCollectOneSide_rec( p, Gia_ObjFanin0(pObj), vNodes ); + Gia_ManCollectOneSide_rec( p, Gia_ObjFanin1(pObj), vNodes ); + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); +} +Vec_Int_t * Gia_ManCollectOneSide( Gia_Man_t * p, int iSide ) +{ + Gia_Obj_t * pObj; int i; + Vec_Int_t * vNodes = Vec_IntAlloc( Gia_ManAndNum(p) ); + Gia_ManIncrementTravId( p ); + Gia_ManForEachPo( p, pObj, i ) + if ( (i & 1) == iSide ) + Gia_ManCollectOneSide_rec( p, Gia_ObjFanin0(pObj), vNodes ); + return vNodes; +} +Gia_Man_t * Gia_ManTransformDualOutput( Gia_Man_t * p ) +{ + Vec_Int_t * vNodes0 = Gia_ManCollectOneSide( p, 0 ); + Vec_Int_t * vNodes1 = Gia_ManCollectOneSide( p, 1 ); + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pObj2; + int i, fSwap = 0; + assert( Gia_ManRegNum(p) == 0 ); + assert( (Gia_ManPoNum(p) & 1) == 0 ); + if ( Vec_IntSize(vNodes0) > Vec_IntSize(vNodes1) ) + { + ABC_SWAP( Vec_Int_t *, vNodes0, vNodes1 ); + fSwap = 1; + } + assert( Vec_IntSize(vNodes0) <= Vec_IntSize(vNodes1) ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachObjVec( vNodes0, p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachObjVec( vNodes1, p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Vec_IntFree( vNodes0 ); + Vec_IntFree( vNodes1 ); + Gia_ManForEachPo( p, pObj, i ) + { + pObj2 = Gia_ManPo( p, i^fSwap ); + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj2) ); + } + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Performs 'zero' and 'undc' operation.] + + Description [The init string specifies 0/1/X for each flop.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupZeroUndc( Gia_Man_t * p, char * pInit, int nNewPis, int fGiaSimple, int fVerbose ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int CountPis = Gia_ManPiNum(p), * pPiLits; + int i, iResetFlop = -1, Count1 = 0; + //printf( "Using %s\n", pInit ); + // map X-valued flops into new PIs + assert( (int)strlen(pInit) == Gia_ManRegNum(p) ); + pPiLits = ABC_FALLOC( int, Gia_ManRegNum(p) ); + for ( i = 0; i < Gia_ManRegNum(p); i++ ) + if ( pInit[i] == 'x' || pInit[i] == 'X' ) + pPiLits[i] = CountPis++; + // create new manager + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->fGiaSimple = fGiaSimple; + Gia_ManConst0(p)->Value = 0; + // create primary inputs + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + // create additional primary inputs + for ( i = Gia_ManPiNum(p); i < CountPis; i++ ) + Gia_ManAppendCi( pNew ); + // create additional primary inputs + for ( i = 0; i < nNewPis; i++ ) + Gia_ManAppendCi( pNew ); + // create flop outputs + Gia_ManForEachRo( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + // create reset flop output + if ( CountPis > Gia_ManPiNum(p) ) + iResetFlop = Gia_ManAppendCi( pNew ); + // update flop outputs + Gia_ManMarkFanoutDrivers( p ); + Gia_ManForEachRo( p, pObj, i ) + { + if ( pInit[i] == '1' ) + pObj->Value = Abc_LitNot(pObj->Value), Count1++; + else if ( pInit[i] == 'x' || pInit[i] == 'X' ) + { + if ( pObj->fMark0 ) // only add MUX if the flop has fanout + pObj->Value = Gia_ManAppendMux( pNew, iResetFlop, pObj->Value, Gia_Obj2Lit(pNew, Gia_ManPi(pNew, pPiLits[i])) ); + } + else if ( pInit[i] != '0' ) + assert( 0 ); + } + Gia_ManCleanMark0( p ); + ABC_FREE( pPiLits ); + // build internal nodes + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + // create POs + Gia_ManForEachPo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + // create flop inputs + Gia_ManForEachRi( p, pObj, i ) + if ( pInit[i] == '1' ) + pObj->Value = Gia_ManAppendCo( pNew, Abc_LitNot(Gia_ObjFanin0Copy(pObj)) ); + else + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + // create reset flop input + if ( CountPis > Gia_ManPiNum(p) ) + Gia_ManAppendCo( pNew, 1 ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) + (int)(CountPis > Gia_ManPiNum(p)) ); + if ( fVerbose ) + printf( "Converted %d 1-valued FFs and %d DC-valued FFs.\n", Count1, CountPis-Gia_ManPiNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Creates miter of two designs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManMiter2( Gia_Man_t * pStart, char * pInit, int fVerbose ) +{ + Vec_Int_t * vCiValues, * vCoValues0, * vCoValues1; + Gia_Man_t * pNew, * pUndc, * pTemp; + Gia_Obj_t * pObj; + char * pInitNew; + int i, k; + // check PI values + for ( i = 0; i < Gia_ManPiNum(pStart); i++ ) + assert( pInit[i] == 'x' || pInit[i] == 'X' ); + // normalize the manager + pUndc = Gia_ManDupZeroUndc( pStart, pInit + Gia_ManPiNum(pStart), 0, 0, fVerbose ); + // create new init string + pInitNew = ABC_ALLOC( char, Gia_ManPiNum(pUndc)+1 ); + for ( i = 0; i < Gia_ManPiNum(pStart); i++ ) + pInitNew[i] = pInit[i]; + for ( i = k = Gia_ManPiNum(pStart); i < Gia_ManCiNum(pStart); i++ ) + if ( pInit[i] == 'x' || pInit[i] == 'X' ) + pInitNew[k++] = pInit[i]; + pInitNew[k] = 0; + assert( k == Gia_ManPiNum(pUndc) ); + // derive miter + pNew = Gia_ManStart( Gia_ManObjNum(pUndc) ); + pNew->pName = Abc_UtilStrsav( pUndc->pName ); + pNew->pSpec = Abc_UtilStrsav( pUndc->pSpec ); + Gia_ManConst0(pUndc)->Value = 0; + Gia_ManHashAlloc( pNew ); + // add PIs of the first side + Gia_ManForEachPi( pUndc, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + // add PIs of the second side + vCiValues = Vec_IntAlloc( Gia_ManPiNum(pUndc) ); + Gia_ManForEachPi( pUndc, pObj, i ) + if ( pInitNew[i] == 'x' ) + Vec_IntPush( vCiValues, Gia_Obj2Lit( pNew, Gia_ManPi(pNew, i) ) ); + else if ( pInitNew[i] == 'X' ) + Vec_IntPush( vCiValues, Gia_ManAppendCi( pNew ) ); + else assert( 0 ); + // build flops and internal nodes + Gia_ManForEachRo( pUndc, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( pUndc, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + // collect CO values + vCoValues0 = Vec_IntAlloc( Gia_ManPoNum(pUndc) ); + Gia_ManForEachCo( pUndc, pObj, i ) + Vec_IntPush( vCoValues0, Gia_ObjFanin0Copy(pObj) ); + // build the other side + Gia_ManForEachPi( pUndc, pObj, i ) + pObj->Value = Vec_IntEntry( vCiValues, i ); + Gia_ManForEachRo( pUndc, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( pUndc, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + // collect CO values + vCoValues1 = Vec_IntAlloc( Gia_ManPoNum(pUndc) ); + Gia_ManForEachCo( pUndc, pObj, i ) + Vec_IntPush( vCoValues1, Gia_ObjFanin0Copy(pObj) ); + // create POs + Gia_ManForEachPo( pUndc, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ManHashXor( pNew, Vec_IntEntry(vCoValues0, i), Vec_IntEntry(vCoValues1, i) ) ); + // create flop inputs + Gia_ManForEachRi( pUndc, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Vec_IntEntry(vCoValues0, Gia_ManPoNum(pUndc)+i) ); + Gia_ManForEachRi( pUndc, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Vec_IntEntry(vCoValues1, Gia_ManPoNum(pUndc)+i) ); + Vec_IntFree( vCoValues0 ); + Vec_IntFree( vCoValues1 ); + Vec_IntFree( vCiValues ); + ABC_FREE( pInitNew ); + // cleanup + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, 2*Gia_ManRegNum(pUndc) ); + Gia_ManStop( pUndc ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManChoiceMiter_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return pObj->Value; + Gia_ManChoiceMiter_rec( pNew, p, Gia_ObjFanin0(pObj) ); + if ( Gia_ObjIsCo(pObj) ) + return pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManChoiceMiter_rec( pNew, p, Gia_ObjFanin1(pObj) ); + return pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Derives the miter of several AIGs for choice computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManChoiceMiter( Vec_Ptr_t * vGias ) +{ + Gia_Man_t * pNew, * pGia, * pGia0; + int i, k, iNode, nNodes; + // make sure they have equal parameters + assert( Vec_PtrSize(vGias) > 0 ); + pGia0 = (Gia_Man_t *)Vec_PtrEntry( vGias, 0 ); + Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) + { + assert( Gia_ManCiNum(pGia) == Gia_ManCiNum(pGia0) ); + assert( Gia_ManCoNum(pGia) == Gia_ManCoNum(pGia0) ); + assert( Gia_ManRegNum(pGia) == Gia_ManRegNum(pGia0) ); + Gia_ManFillValue( pGia ); + Gia_ManConst0(pGia)->Value = 0; + } + // start the new manager + pNew = Gia_ManStart( Vec_PtrSize(vGias) * Gia_ManObjNum(pGia0) ); + pNew->pName = Abc_UtilStrsav( pGia0->pName ); + pNew->pSpec = Abc_UtilStrsav( pGia0->pSpec ); + // create new CIs and assign them to the old manager CIs + for ( k = 0; k < Gia_ManCiNum(pGia0); k++ ) + { + iNode = Gia_ManAppendCi(pNew); + Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) + Gia_ManCi( pGia, k )->Value = iNode; + } + // create internal nodes + Gia_ManHashAlloc( pNew ); + for ( k = 0; k < Gia_ManCoNum(pGia0); k++ ) + { + Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) + Gia_ManChoiceMiter_rec( pNew, pGia, Gia_ManCo( pGia, k ) ); + } + Gia_ManHashStop( pNew ); + // check the presence of dangling nodes + nNodes = Gia_ManHasDangling( pNew ); + //assert( nNodes == 0 ); + // finalize + Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia0) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG while putting first PIs, then nodes, then POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupWithConstraints( Gia_Man_t * p, Vec_Int_t * vPoTypes ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i, nConstr = 0; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachPo( p, pObj, i ) + if ( Vec_IntEntry(vPoTypes, i) == 0 ) // regular PO + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManForEachPo( p, pObj, i ) + if ( Vec_IntEntry(vPoTypes, i) == 1 ) // constraint (should be complemented!) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ^ 1 ), nConstr++; + Gia_ManForEachRi( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); +// Gia_ManDupRemapEquiv( pNew, p ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew->nConstrs = nConstr; + assert( Gia_ManIsNormalized(pNew) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Copy an AIG structure related to the selected POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ObjCompareByCioId( Gia_Obj_t ** pp1, Gia_Obj_t ** pp2 ) +{ + Gia_Obj_t * pObj1 = *pp1; + Gia_Obj_t * pObj2 = *pp2; + return Gia_ObjCioId(pObj1) - Gia_ObjCioId(pObj2); +} +void Gia_ManDupCones_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes, Vec_Ptr_t * vRoots ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ManDupCones_rec( p, Gia_ObjFanin0(pObj), vLeaves, vNodes, vRoots ); + Gia_ManDupCones_rec( p, Gia_ObjFanin1(pObj), vLeaves, vNodes, vRoots ); + Vec_PtrPush( vNodes, pObj ); + } + else if ( Gia_ObjIsCo(pObj) ) + Gia_ManDupCones_rec( p, Gia_ObjFanin0(pObj), vLeaves, vNodes, vRoots ); + else if ( Gia_ObjIsRo(p, pObj) ) + Vec_PtrPush( vRoots, Gia_ObjRoToRi(p, pObj) ); + else if ( Gia_ObjIsPi(p, pObj) ) + Vec_PtrPush( vLeaves, pObj ); + else assert( 0 ); +} +Gia_Man_t * Gia_ManDupCones( Gia_Man_t * p, int * pPos, int nPos, int fTrimPis ) +{ + Gia_Man_t * pNew; + Vec_Ptr_t * vLeaves, * vNodes, * vRoots; + Gia_Obj_t * pObj; + int i; + + // collect initial POs + vLeaves = Vec_PtrAlloc( 100 ); + vNodes = Vec_PtrAlloc( 100 ); + vRoots = Vec_PtrAlloc( 100 ); + for ( i = 0; i < nPos; i++ ) + Vec_PtrPush( vRoots, Gia_ManPo(p, pPos[i]) ); + + // mark internal nodes + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); + Vec_PtrForEachEntry( Gia_Obj_t *, vRoots, pObj, i ) + Gia_ManDupCones_rec( p, pObj, vLeaves, vNodes, vRoots ); + Vec_PtrSort( vLeaves, (int (*)(const void *, const void *))Gia_ObjCompareByCioId ); + + // start the new manager +// Gia_ManFillValue( p ); + pNew = Gia_ManStart( (fTrimPis ? Vec_PtrSize(vLeaves) : Gia_ManCiNum(p)) + Vec_PtrSize(vNodes) + Vec_PtrSize(vRoots) + 1 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + // map the constant node + Gia_ManConst0(p)->Value = 0; + // create PIs + if ( fTrimPis ) + { + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = ~0; + Vec_PtrForEachEntry( Gia_Obj_t *, vLeaves, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + } + else + { + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + } + // create LOs + Vec_PtrForEachEntryStart( Gia_Obj_t *, vRoots, pObj, i, nPos ) + Gia_ObjRiToRo(p, pObj)->Value = Gia_ManAppendCi( pNew ); + // create internal nodes + Vec_PtrForEachEntry( Gia_Obj_t *, vNodes, pObj, i ) + if ( Gia_ObjIsXor(pObj) ) + pObj->Value = Gia_ManAppendXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + // create COs + Vec_PtrForEachEntry( Gia_Obj_t *, vRoots, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + // finalize + Gia_ManSetRegNum( pNew, Vec_PtrSize(vRoots)-nPos ); + Vec_PtrFree( vLeaves ); + Vec_PtrFree( vNodes ); + Vec_PtrFree( vRoots ); + return pNew; + +} +Gia_Man_t * Gia_ManDupAndCones( Gia_Man_t * p, int * pAnds, int nAnds, int fTrimPis ) +{ + Gia_Man_t * pNew; + Vec_Ptr_t * vLeaves, * vNodes, * vRoots; + Gia_Obj_t * pObj; + int i; + + // collect initial POs + vLeaves = Vec_PtrAlloc( 100 ); + vNodes = Vec_PtrAlloc( 100 ); + vRoots = Vec_PtrAlloc( 100 ); + for ( i = 0; i < nAnds; i++ ) +// Vec_PtrPush( vRoots, Gia_ManPo(p, pPos[i]) ); + Vec_PtrPush( vRoots, Gia_ManObj(p, pAnds[i]) ); + + // mark internal nodes + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); + Vec_PtrForEachEntry( Gia_Obj_t *, vRoots, pObj, i ) + Gia_ManDupCones_rec( p, pObj, vLeaves, vNodes, vRoots ); + Vec_PtrSort( vLeaves, (int (*)(const void *, const void *))Gia_ObjCompareByCioId ); + + // start the new manager +// Gia_ManFillValue( p ); + pNew = Gia_ManStart( Vec_PtrSize(vLeaves) + Vec_PtrSize(vNodes) + Vec_PtrSize(vRoots) + 1); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + // map the constant node + Gia_ManConst0(p)->Value = 0; + // create PIs + if ( fTrimPis ) + { + Vec_PtrForEachEntry( Gia_Obj_t *, vLeaves, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + } + else + { + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + } + // create LOs +// Vec_PtrForEachEntryStart( Gia_Obj_t *, vRoots, pObj, i, nPos ) +// Gia_ObjRiToRo(p, pObj)->Value = Gia_ManAppendCi( pNew ); + // create internal nodes + Vec_PtrForEachEntry( Gia_Obj_t *, vNodes, pObj, i ) + if ( Gia_ObjIsMux(p, pObj) ) + pObj->Value = Gia_ManAppendMux( pNew, Gia_ObjFanin2Copy(p, pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsXor(pObj) ) + pObj->Value = Gia_ManAppendXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + // create COs + Vec_PtrForEachEntry( Gia_Obj_t *, vRoots, pObj, i ) +// Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManAppendCo( pNew, pObj->Value ); + // finalize +// Gia_ManSetRegNum( pNew, Vec_PtrSize(vRoots)-nPos ); + Gia_ManSetRegNum( pNew, 0 ); + Vec_PtrFree( vLeaves ); + Vec_PtrFree( vNodes ); + Vec_PtrFree( vRoots ); + return pNew; + +} +void Gia_ManDupAndConesLimit_rec( Gia_Man_t * pNew, Gia_Man_t * p, int iObj, int Level ) +{ + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); + if ( ~pObj->Value ) + return; + if ( !Gia_ObjIsAnd(pObj) || Gia_ObjLevel(p, pObj) < Level ) + { + pObj->Value = Gia_ManAppendCi( pNew ); + //printf( "PI %d for %d.\n", Abc_Lit2Var(pObj->Value), iObj ); + return; + } + Gia_ManDupAndConesLimit_rec( pNew, p, Gia_ObjFaninId0(pObj, iObj), Level ); + Gia_ManDupAndConesLimit_rec( pNew, p, Gia_ObjFaninId1(pObj, iObj), Level ); + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + //printf( "Obj %d for %d.\n", Abc_Lit2Var(pObj->Value), iObj ); +} +Gia_Man_t * Gia_ManDupAndConesLimit( Gia_Man_t * p, int * pAnds, int nAnds, int Level ) +{ + Gia_Man_t * pNew; + int i; + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManLevelNum( p ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + for ( i = 0; i < nAnds; i++ ) + Gia_ManDupAndConesLimit_rec( pNew, p, pAnds[i], Level ); + for ( i = 0; i < nAnds; i++ ) + Gia_ManAppendCo( pNew, Gia_ManObj(p, pAnds[i])->Value ); + return pNew; +} + +void Gia_ManDupAndConesLimit2_rec( Gia_Man_t * pNew, Gia_Man_t * p, int iObj, int Level ) +{ + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); + if ( ~pObj->Value ) + return; + if ( !Gia_ObjIsAnd(pObj) || Level <= 0 ) + { + pObj->Value = Gia_ManAppendCi( pNew ); + //printf( "PI %d for %d.\n", Abc_Lit2Var(pObj->Value), iObj ); + return; + } + Gia_ManDupAndConesLimit2_rec( pNew, p, Gia_ObjFaninId0(pObj, iObj), Level-1 ); + Gia_ManDupAndConesLimit2_rec( pNew, p, Gia_ObjFaninId1(pObj, iObj), Level-1 ); + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + //printf( "Obj %d for %d.\n", Abc_Lit2Var(pObj->Value), iObj ); +} +Gia_Man_t * Gia_ManDupAndConesLimit2( Gia_Man_t * p, int * pAnds, int nAnds, int Level ) +{ + Gia_Man_t * pNew; + int i; + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + for ( i = 0; i < nAnds; i++ ) + Gia_ManDupAndConesLimit2_rec( pNew, p, pAnds[i], Level ); + for ( i = 0; i < nAnds; i++ ) + Gia_ManAppendCo( pNew, Gia_ManObj(p, pAnds[i])->Value ); + return pNew; + +} + +/**Function************************************************************* + + Synopsis [Generates AIG representing 1-hot condition for N inputs.] + + Description [The condition is true of all POs are 0.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManOneHot( int nSkips, int nVars ) +{ + Gia_Man_t * p; + int i, b, Shift, iGiaLit, nLogVars = Abc_Base2Log( nVars ); + int * pTemp = ABC_CALLOC( int, (1 << nLogVars) ); + p = Gia_ManStart( nSkips + 4 * nVars + 1 ); + p->pName = Abc_UtilStrsav( "onehot" ); + for ( i = 0; i < nSkips; i++ ) + Gia_ManAppendCi( p ); + for ( i = 0; i < nVars; i++ ) + pTemp[i] = Gia_ManAppendCi( p ); + Gia_ManHashStart( p ); + for ( b = 0; b < nLogVars; b++ ) + for ( i = 0, Shift = (1<nConstrs += Gia_ManPoNum(pOneHot); + Gia_ManStop( pOneHot ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG with nodes ordered by level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupLevelized( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i, nLevels = Gia_ManLevelNum( p ); + int * pCounts = ABC_CALLOC( int, nLevels + 1 ); + int * pNodes = ABC_ALLOC( int, Gia_ManAndNum(p) ); + Gia_ManForEachAnd( p, pObj, i ) + pCounts[Gia_ObjLevel(p, pObj)]++; + for ( i = 1; i <= nLevels; i++ ) + pCounts[i] += pCounts[i-1]; + Gia_ManForEachAnd( p, pObj, i ) + pNodes[pCounts[Gia_ObjLevel(p, pObj)-1]++] = i; + // duplicate + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + for ( i = 0; i < Gia_ManAndNum(p) && (pObj = Gia_ManObj(p, pNodes[i])); i++ ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + ABC_FREE( pCounts ); + ABC_FREE( pNodes ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupFromVecs( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos, int nRegs ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + // start the new manager + pNew = Gia_ManStart( 5000 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + // create constant + Gia_ManConst0(p)->Value = 0; + // create PIs + Gia_ManForEachObjVec( vCis, p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + // create internal nodes + Gia_ManForEachObjVec( vAnds, p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + // create ROs + Gia_ManForEachObjVec( vCos, p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, nRegs ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupSliced( Gia_Man_t * p, int nSuppMax ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + // start the new manager + pNew = Gia_ManStart( 5000 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + // create constant and PIs + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + // create internal nodes + Gia_ManCleanMark01(p); + Gia_ManForEachAnd( p, pObj, i ) + if ( Gia_ManSuppSize(p, &i, 1) <= nSuppMax ) + { + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + pObj->fMark0 = 1; + } + else + { + Gia_ObjFanin0(pObj)->fMark1 = 1; + Gia_ObjFanin1(pObj)->fMark1 = 1; + } + Gia_ManForEachCo( p, pObj, i ) + Gia_ObjFanin0(pObj)->fMark1 = 1; + // add POs for the nodes pointed to + Gia_ManForEachAnd( p, pObj, i ) + if ( pObj->fMark0 && pObj->fMark1 ) + Gia_ManAppendCo( pNew, pObj->Value ); + // cleanup and leave + Gia_ManCleanMark01(p); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Extract constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDupWithConstrCollectAnd_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper, int fFirst ) +{ + if ( (Gia_IsComplement(pObj) || !Gia_ObjIsAnd(pObj)) && !fFirst ) + { + Vec_IntPushUnique( vSuper, Gia_ObjToLit(p, pObj) ); + return; + } + Gia_ManDupWithConstrCollectAnd_rec( p, Gia_ObjChild0(pObj), vSuper, 0 ); + Gia_ManDupWithConstrCollectAnd_rec( p, Gia_ObjChild1(pObj), vSuper, 0 ); +} +Gia_Man_t * Gia_ManDupWithConstr( Gia_Man_t * p ) +{ + Vec_Int_t * vSuper; + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, iDriver, iLit, iLitBest = -1, LevelBest = -1; + assert( Gia_ManPoNum(p) == 1 ); + assert( Gia_ManRegNum(p) == 0 ); + pObj = Gia_ManPo( p, 0 ); + if ( Gia_ObjFaninC0(pObj) ) + { + printf( "The miter's output is not AND-decomposable.\n" ); + return NULL; + } + if ( Gia_ObjFaninId0p(p, pObj) == 0 ) + { + printf( "The miter's output is a constant.\n" ); + return NULL; + } + vSuper = Vec_IntAlloc( 100 ); + Gia_ManDupWithConstrCollectAnd_rec( p, Gia_ObjChild0(pObj), vSuper, 1 ); + assert( Vec_IntSize(vSuper) > 1 ); + // find the highest level + Gia_ManLevelNum( p ); + Vec_IntForEachEntry( vSuper, iLit, i ) + if ( LevelBest < Gia_ObjLevelId(p, Abc_Lit2Var(iLit)) ) + LevelBest = Gia_ObjLevelId(p, Abc_Lit2Var(iLit)), iLitBest = iLit; + assert( iLitBest != -1 ); + // create new manager + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + } + // create AND of nodes + iDriver = -1; + Vec_IntForEachEntry( vSuper, iLit, i ) + { + if ( iLit == iLitBest ) + continue; + if ( iDriver == -1 ) + iDriver = Gia_ObjLitCopy(p, iLit); + else + iDriver = Gia_ManHashAnd( pNew, iDriver, Gia_ObjLitCopy(p, iLit) ); + } + // create the main PO + Gia_ManAppendCo( pNew, Gia_ObjLitCopy(p, iLitBest) ); + // create the constraint PO + Gia_ManAppendCo( pNew, Abc_LitNot(iDriver) ); + pNew->nConstrs = 1; + // rehash + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Vec_IntFree( vSuper ); + return pNew; + +} + +/**Function************************************************************* + + Synopsis [Compares two objects by their distance.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSortByValue( Gia_Obj_t ** pp1, Gia_Obj_t ** pp2 ) +{ + int Diff = Gia_Regular(*pp1)->Value - Gia_Regular(*pp2)->Value; + if ( Diff < 0 ) + return -1; + if ( Diff > 0 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Decomposes the miter outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupOuts( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachPo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManForEachAnd( p, pObj, i ) + Gia_ManAppendCo( pNew, pObj->Value ); + Gia_ManForEachRi( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + assert( Gia_ManIsNormalized(pNew) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Computes supports for each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Gia_ManCreateNodeSupps( Gia_Man_t * p, Vec_Int_t * vNodes, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Gia_Obj_t * pObj; int i, Id; + Vec_Wec_t * vSuppsNo = Vec_WecStart( Vec_IntSize(vNodes) ); + Vec_Wec_t * vSupps = Vec_WecStart( Gia_ManObjNum(p) ); + Gia_ManForEachCiId( p, Id, i ) + Vec_IntPush( Vec_WecEntry(vSupps, Id), i ); + Gia_ManForEachAnd( p, pObj, Id ) + Vec_IntTwoMerge2( Vec_WecEntry(vSupps, Gia_ObjFaninId0(pObj, Id)), + Vec_WecEntry(vSupps, Gia_ObjFaninId1(pObj, Id)), + Vec_WecEntry(vSupps, Id) ); + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + Vec_IntAppend( Vec_WecEntry(vSuppsNo, i), Vec_WecEntry(vSupps, Gia_ObjId(p, pObj)) ); + Vec_WecFree( vSupps ); + if ( fVerbose ) + Abc_PrintTime( 1, "Support computation", Abc_Clock() - clk ); + return vSuppsNo; +} + +Vec_Wec_t * Gia_ManCreateCoSupps( Gia_Man_t * p, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Gia_Obj_t * pObj; int i, Id; + Vec_Wec_t * vSuppsCo = Vec_WecStart( Gia_ManCoNum(p) ); + Vec_Wec_t * vSupps = Vec_WecStart( Gia_ManObjNum(p) ); + Gia_ManForEachCiId( p, Id, i ) + Vec_IntPush( Vec_WecEntry(vSupps, Id), i ); + Gia_ManForEachAnd( p, pObj, Id ) + Vec_IntTwoMerge2( Vec_WecEntry(vSupps, Gia_ObjFaninId0(pObj, Id)), + Vec_WecEntry(vSupps, Gia_ObjFaninId1(pObj, Id)), + Vec_WecEntry(vSupps, Id) ); + Gia_ManForEachCo( p, pObj, i ) + Vec_IntAppend( Vec_WecEntry(vSuppsCo, i), Vec_WecEntry(vSupps, Gia_ObjFaninId0p(p, pObj)) ); + Vec_WecFree( vSupps ); + if ( fVerbose ) + Abc_PrintTime( 1, "Support computation", Abc_Clock() - clk ); + return vSuppsCo; +} +int Gia_ManCoSuppSizeMax( Gia_Man_t * p, Vec_Wec_t * vSupps ) +{ + Gia_Obj_t * pObj; + Vec_Int_t * vSuppOne; + int i, nSuppMax = 1; + Gia_ManForEachCo( p, pObj, i ) + { + vSuppOne = Vec_WecEntry( vSupps, i ); + nSuppMax = Abc_MaxInt( nSuppMax, Vec_IntSize(vSuppOne) ); + } + return nSuppMax; +} +int Gia_ManCoLargestSupp( Gia_Man_t * p, Vec_Wec_t * vSupps ) +{ + Gia_Obj_t * pObj; + Vec_Int_t * vSuppOne; + int i, iCoMax = -1, nSuppMax = -1; + Gia_ManForEachCo( p, pObj, i ) + { + vSuppOne = Vec_WecEntry( vSupps, i ); + if ( nSuppMax < Vec_IntSize(vSuppOne) ) + { + nSuppMax = Vec_IntSize(vSuppOne); + iCoMax = i; + } + } + return iCoMax; +} +Vec_Int_t * Gia_ManSortCoBySuppSize( Gia_Man_t * p, Vec_Wec_t * vSupps ) +{ + Vec_Int_t * vOrder = Vec_IntAlloc( Gia_ManCoNum(p) ); + Vec_Wrd_t * vSortData = Vec_WrdAlloc( Gia_ManCoNum(p) ); + Vec_Int_t * vSuppOne; word Entry; int i; + Vec_WecForEachLevel( vSupps, vSuppOne, i ) + Vec_WrdPush( vSortData, ((word)i << 32) | Vec_IntSize(vSuppOne) ); + Abc_QuickSort3( Vec_WrdArray(vSortData), Vec_WrdSize(vSortData), 1 ); + Vec_WrdForEachEntry( vSortData, Entry, i ) + Vec_IntPush( vOrder, (int)(Entry >> 32) ); + Vec_WrdFree( vSortData ); + return vOrder; +} + +/**Function************************************************************* + + Synopsis [Remaps each CO cone to depend on the first CI variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManDupHashDfs_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return pObj->Value; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManDupHashDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManDupHashDfs_rec( pNew, p, Gia_ObjFanin1(pObj) ); + return pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +void Gia_ManDupCleanDfs_rec( Gia_Obj_t * pObj ) +{ + if ( !~pObj->Value ) + return; + pObj->Value = ~0; + if ( Gia_ObjIsCi(pObj) ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManDupCleanDfs_rec( Gia_ObjFanin0(pObj) ); + Gia_ManDupCleanDfs_rec( Gia_ObjFanin1(pObj) ); +} +Gia_Man_t * Gia_ManDupStrashReduce( Gia_Man_t * p, Vec_Wec_t * vSupps, Vec_Int_t ** pvCoMap ) +{ + Gia_Obj_t * pObj; + Gia_Man_t * pNew, * pTemp; + Vec_Int_t * vSuppOne, * vCoMapLit; + int i, k, iCi, iLit, nSuppMax; + assert( Gia_ManRegNum(p) == 0 ); + Gia_ManFillValue( p ); + vCoMapLit = Vec_IntAlloc( Gia_ManCoNum(p) ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + nSuppMax = Gia_ManCoSuppSizeMax( p, vSupps ); + for ( i = 0; i < nSuppMax; i++ ) + Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCo( p, pObj, i ) + { + vSuppOne = Vec_WecEntry( vSupps, i ); + if ( Vec_IntSize(vSuppOne) == 0 ) + Vec_IntPush( vCoMapLit, Abc_Var2Lit(0, Gia_ObjFaninC0(pObj)) ); + else if ( Vec_IntSize(vSuppOne) == 1 ) + Vec_IntPush( vCoMapLit, Abc_Var2Lit(1, Gia_ObjFaninC0(pObj)) ); + else + { + Vec_IntForEachEntry( vSuppOne, iCi, k ) + Gia_ManCi(p, iCi)->Value = Gia_Obj2Lit(pNew, Gia_ManCi(pNew, k) ); + Gia_ManDupHashDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); + assert( Gia_ObjFanin0Copy(pObj) < 2 * Gia_ManObjNum(pNew) ); + Vec_IntPush( vCoMapLit, Gia_ObjFanin0Copy(pObj) ); + Gia_ManDupCleanDfs_rec( Gia_ObjFanin0(pObj) ); + } + } + Gia_ManHashStop( pNew ); + assert( Vec_IntSize(vCoMapLit) == Gia_ManCoNum(p) ); + if ( pvCoMap == NULL ) // do not remap + { + Vec_IntForEachEntry( vCoMapLit, iLit, i ) + Gia_ManAppendCo( pNew, iLit ); + } + else // remap + { + Vec_Int_t * vCoMapRes = Vec_IntAlloc( Gia_ManCoNum(p) ); // map old CO into new CO + Vec_Int_t * vMap = Vec_IntStartFull( 2*Gia_ManObjNum(pNew) ); // map new lit into new CO + Vec_IntForEachEntry( vCoMapLit, iLit, i ) + { + if ( Vec_IntEntry(vMap, iLit) == -1 ) + { + Vec_IntWriteEntry( vMap, iLit, Gia_ManCoNum(pNew) ); + Gia_ManAppendCo( pNew, iLit ); + } + Vec_IntPush( vCoMapRes, Vec_IntEntry(vMap, iLit) ); + } + Vec_IntFree( vMap ); + *pvCoMap = vCoMapRes; + } + Vec_IntFree( vCoMapLit ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} +Gia_Man_t * Gia_ManIsoStrashReduce2( Gia_Man_t * p, Vec_Ptr_t ** pvPosEquivs, int fVerbose ) +{ + Vec_Int_t * vCoMap; + Vec_Wec_t * vSupps = Gia_ManCreateCoSupps( p, fVerbose ); + Gia_Man_t * pNew = Gia_ManDupStrashReduce( p, vSupps, &vCoMap ); + Vec_IntFree( vCoMap ); + Vec_WecFree( vSupps ); + *pvPosEquivs = NULL; + return pNew; +} + +int Gia_ManIsoStrashReduceOne( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp ) +{ + int k, iCi, iLit; + assert( Gia_ObjIsCo(pObj) ); + if ( Vec_IntSize(vSupp) == 0 ) + return Abc_Var2Lit(0, Gia_ObjFaninC0(pObj)); + if ( Vec_IntSize(vSupp) == 1 ) + return Abc_Var2Lit(1, Gia_ObjFaninC0(pObj)); + Vec_IntForEachEntry( vSupp, iCi, k ) + Gia_ManCi(p, iCi)->Value = Gia_Obj2Lit(pNew, Gia_ManCi(pNew, k) ); + Gia_ManDupHashDfs_rec( pNew, p, Gia_ObjFanin0(pObj) ); + iLit = Gia_ObjFanin0Copy(pObj); + Gia_ManDupCleanDfs_rec( Gia_ObjFanin0(pObj) ); + return iLit; +} +Vec_Wec_t * Gia_ManIsoStrashReduceInt( Gia_Man_t * p, Vec_Wec_t * vSupps, int fVerbose ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + Vec_Wec_t * vPosEquivs = Vec_WecAlloc( 100 ); + Vec_Int_t * vSuppOne, * vMap = Vec_IntAlloc( 10000 ); + int i, iLit, nSuppMax = Gia_ManCoSuppSizeMax( p, vSupps ); + // count how many times each support size appears + Vec_Int_t * vSizeCount = Vec_IntStart( nSuppMax + 1 ); + Vec_WecForEachLevel( vSupps, vSuppOne, i ) + Vec_IntAddToEntry( vSizeCount, Vec_IntSize(vSuppOne), 1 ); + // create array of unique outputs + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + Gia_ManConst0(p)->Value = 0; + for ( i = 0; i < nSuppMax; i++ ) + Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCo( p, pObj, i ) + { + vSuppOne = Vec_WecEntry( vSupps, i ); + if ( Vec_IntEntry(vSizeCount, Vec_IntSize(vSuppOne)) == 1 ) + { + Vec_IntPush( Vec_WecPushLevel(vPosEquivs), i ); + continue; + } + iLit = Gia_ManIsoStrashReduceOne( pNew, p, pObj, vSuppOne ); + Vec_IntFillExtra( vMap, iLit + 1, -1 ); + if ( Vec_IntEntry(vMap, iLit) == -1 ) + { + Vec_IntWriteEntry( vMap, iLit, Vec_WecSize(vPosEquivs) ); + Vec_IntPush( Vec_WecPushLevel(vPosEquivs), i ); + continue; + } + Vec_IntPush( Vec_WecEntry(vPosEquivs, Vec_IntEntry(vMap, iLit)), i ); + } + Gia_ManHashStop( pNew ); + Gia_ManStop( pNew ); + Vec_IntFree( vSizeCount ); + Vec_IntFree( vMap ); + return vPosEquivs; +} +Gia_Man_t * Gia_ManIsoStrashReduce( Gia_Man_t * p, Vec_Ptr_t ** pvPosEquivs, int fVerbose ) +{ + Vec_Wec_t * vSupps = Gia_ManCreateCoSupps( p, fVerbose ); + Vec_Wec_t * vPosEquivs = Gia_ManIsoStrashReduceInt( p, vSupps, fVerbose ); + // find the first outputs and derive GIA + Vec_Int_t * vFirsts = Vec_WecCollectFirsts( vPosEquivs ); + Gia_Man_t * pNew = Gia_ManDupCones( p, Vec_IntArray(vFirsts), Vec_IntSize(vFirsts), 0 ); + Vec_IntFree( vFirsts ); + Vec_WecFree( vSupps ); + // report and return + if ( fVerbose ) + { + printf( "Nontrivial classes:\n" ); + Vec_WecPrint( vPosEquivs, 1 ); + } + if ( pvPosEquivs ) + *pvPosEquivs = Vec_WecConvertToVecPtr( vPosEquivs ); + Vec_WecFree( vPosEquivs ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Decomposes the miter outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupDemiter( Gia_Man_t * p, int fVerbose ) +{ + Vec_Int_t * vSuper; + Vec_Ptr_t * vSuperPtr; + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pObjPo; + int i, iLit; + assert( Gia_ManPoNum(p) == 1 ); + // decompose + pObjPo = Gia_ManPo( p, 0 ); + vSuper = Vec_IntAlloc( 100 ); + Gia_ManDupWithConstrCollectAnd_rec( p, Gia_ObjFanin0(pObjPo), vSuper, 1 ); + assert( Vec_IntSize(vSuper) > 1 ); + // report the result + printf( "The miter is %s-decomposable into %d parts.\n", Gia_ObjFaninC0(pObjPo) ? "OR":"AND", Vec_IntSize(vSuper) ); + // create levels + Gia_ManLevelNum( p ); + Vec_IntForEachEntry( vSuper, iLit, i ) + Gia_ManObj(p, Abc_Lit2Var(iLit))->Value = Gia_ObjLevelId(p, Abc_Lit2Var(iLit)); + // create pointer array + vSuperPtr = Vec_PtrAlloc( Vec_IntSize(vSuper) ); + Vec_IntForEachEntry( vSuper, iLit, i ) + Vec_PtrPush( vSuperPtr, Gia_Lit2Obj(p, iLit) ); + Vec_PtrSort( vSuperPtr, (int (*)(const void *, const void *))Gia_ManSortByValue ); + // create new manager + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + // create the outputs + Vec_PtrForEachEntry( Gia_Obj_t *, vSuperPtr, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjLitCopy(p, Gia_Obj2Lit(p, pObj)) ^ Gia_ObjFaninC0(pObjPo) ); + Gia_ManForEachRi( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + // rehash + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Vec_IntFree( vSuper ); + Vec_PtrFree( vSuperPtr ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDupDemiterOrderXors2( Gia_Man_t * p, Vec_Int_t * vXors ) +{ + int i, iObj, * pPerm; + Vec_Int_t * vSizes = Vec_IntAlloc( 100 ); + Vec_IntForEachEntry( vXors, iObj, i ) + Vec_IntPush( vSizes, Gia_ManSuppSize(p, &iObj, 1) ); + pPerm = Abc_MergeSortCost( Vec_IntArray(vSizes), Vec_IntSize(vSizes) ); + Vec_IntClear( vSizes ); + for ( i = 0; i < Vec_IntSize(vXors); i++ ) + Vec_IntPush( vSizes, Vec_IntEntry(vXors, pPerm[i]) ); + ABC_FREE( pPerm ); + Vec_IntClear( vXors ); + Vec_IntAppend( vXors, vSizes ); + Vec_IntFree( vSizes ); +} +int Gia_ManDupDemiterFindMin( Vec_Wec_t * vSupps, Vec_Int_t * vTakenIns, Vec_Int_t * vTakenOuts ) +{ + Vec_Int_t * vLevel; + int i, k, iObj, iObjBest = -1; + int Count, CountBest = ABC_INFINITY; + Vec_WecForEachLevel( vSupps, vLevel, i ) + { + if ( Vec_IntEntry(vTakenOuts, i) ) + continue; + Count = 0; + Vec_IntForEachEntry( vLevel, iObj, k ) + Count += !Vec_IntEntry(vTakenIns, iObj); + if ( CountBest > Count ) + { + CountBest = Count; + iObjBest = i; + } + } + return iObjBest; +} +void Gia_ManDupDemiterOrderXors( Gia_Man_t * p, Vec_Int_t * vXors ) +{ + extern Vec_Wec_t * Gia_ManCreateNodeSupps( Gia_Man_t * p, Vec_Int_t * vNodes, int fVerbose ); + Vec_Wec_t * vSupps = Gia_ManCreateNodeSupps( p, vXors, 0 ); + Vec_Int_t * vTakenIns = Vec_IntStart( Gia_ManCiNum(p) ); + Vec_Int_t * vTakenOuts = Vec_IntStart( Vec_IntSize(vXors) ); + Vec_Int_t * vOrder = Vec_IntAlloc( Vec_IntSize(vXors) ); + int i, k, iObj; + // add outputs in the order of increasing supports + for ( i = 0; i < Vec_IntSize(vXors); i++ ) + { + int Index = Gia_ManDupDemiterFindMin( vSupps, vTakenIns, vTakenOuts ); + assert( Index >= 0 && Index < Vec_IntSize(vXors) ); + Vec_IntPush( vOrder, Vec_IntEntry(vXors, Index) ); + assert( !Vec_IntEntry( vTakenOuts, Index ) ); + Vec_IntWriteEntry( vTakenOuts, Index, 1 ); + Vec_IntForEachEntry( Vec_WecEntry(vSupps, Index), iObj, k ) + Vec_IntWriteEntry( vTakenIns, iObj, 1 ); + } + Vec_WecFree( vSupps ); + Vec_IntFree( vTakenIns ); + Vec_IntFree( vTakenOuts ); + // reload + Vec_IntClear( vXors ); + Vec_IntAppend( vXors, vOrder ); + Vec_IntFree( vOrder ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSetMark0Dfs_rec( Gia_Man_t * p, int iObj ) +{ + Gia_Obj_t * pObj; + pObj = Gia_ManObj( p, iObj ); + if ( pObj->fMark0 ) + return; + pObj->fMark0 = 1; + if ( !Gia_ObjIsAnd(pObj) ) + return; + Gia_ManSetMark0Dfs_rec( p, Gia_ObjFaninId0(pObj, iObj) ); + Gia_ManSetMark0Dfs_rec( p, Gia_ObjFaninId1(pObj, iObj) ); +} +void Gia_ManSetMark1Dfs_rec( Gia_Man_t * p, int iObj ) +{ + Gia_Obj_t * pObj; + pObj = Gia_ManObj( p, iObj ); + if ( pObj->fMark1 ) + return; + pObj->fMark1 = 1; + if ( !Gia_ObjIsAnd(pObj) ) + return; + Gia_ManSetMark1Dfs_rec( p, Gia_ObjFaninId0(pObj, iObj) ); + Gia_ManSetMark1Dfs_rec( p, Gia_ObjFaninId1(pObj, iObj) ); +} + +int Gia_ManCountMark0Dfs_rec( Gia_Man_t * p, int iObj ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return 0; + Gia_ObjSetTravIdCurrentId(p, iObj); + pObj = Gia_ManObj( p, iObj ); + if ( !Gia_ObjIsAnd(pObj) ) + return pObj->fMark0; + return Gia_ManCountMark0Dfs_rec( p, Gia_ObjFaninId0(pObj, iObj) ) + + Gia_ManCountMark0Dfs_rec( p, Gia_ObjFaninId1(pObj, iObj) ) + pObj->fMark0; +} +int Gia_ManCountMark0Dfs( Gia_Man_t * p, int iObj ) +{ + Gia_ManIncrementTravId( p ); + return Gia_ManCountMark0Dfs_rec( p, iObj ); +} +int Gia_ManCountMark1Dfs_rec( Gia_Man_t * p, int iObj ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return 0; + Gia_ObjSetTravIdCurrentId(p, iObj); + pObj = Gia_ManObj( p, iObj ); + if ( !Gia_ObjIsAnd(pObj) ) + return pObj->fMark1; + return Gia_ManCountMark1Dfs_rec( p, Gia_ObjFaninId0(pObj, iObj) ) + + Gia_ManCountMark1Dfs_rec( p, Gia_ObjFaninId1(pObj, iObj) ) + pObj->fMark1; +} +int Gia_ManCountMark1Dfs( Gia_Man_t * p, int iObj ) +{ + Gia_ManIncrementTravId( p ); + return Gia_ManCountMark1Dfs_rec( p, iObj ); +} + +int Gia_ManDecideWhereToAdd( Gia_Man_t * p, Vec_Int_t * vPart[2], Gia_Obj_t * pFan[2] ) +{ + int Count0 = 1, Count1 = 0; + assert( Vec_IntSize(vPart[0]) == Vec_IntSize(vPart[1]) ); + if ( Vec_IntSize(vPart[0]) > 0 ) + { + Count0 = Gia_ManCountMark0Dfs(p, Gia_ObjId(p, pFan[0])) + Gia_ManCountMark1Dfs(p, Gia_ObjId(p, pFan[1])); + Count1 = Gia_ManCountMark0Dfs(p, Gia_ObjId(p, pFan[1])) + Gia_ManCountMark1Dfs(p, Gia_ObjId(p, pFan[0])); + } + return Count0 < Count1; +} +void Gia_ManCollectTopXors_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vXors ) +{ + Gia_Obj_t * pFan0, * pFan1; + int iObj = Gia_ObjId( p, pObj ); + if ( Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) || !Gia_ObjIsAnd(pObj) ) + { + Vec_IntPushUnique( vXors, Gia_ObjId(p, pObj) ); + return; + } + if ( Gia_ObjFaninC0(pObj) ) + Vec_IntPushUnique( vXors, Gia_ObjFaninId0(pObj, iObj) ); + else + Gia_ManCollectTopXors_rec( p, Gia_ObjFanin0(pObj), vXors ); + if ( Gia_ObjFaninC1(pObj) ) + Vec_IntPushUnique( vXors, Gia_ObjFaninId1(pObj, iObj) ); + else + Gia_ManCollectTopXors_rec( p, Gia_ObjFanin1(pObj), vXors ); +} +Vec_Int_t * Gia_ManCollectTopXors( Gia_Man_t * p ) +{ + int i, iObj, iObj2, fFlip, Count1 = 0; + Vec_Int_t * vXors, * vPart[2], * vOrder; + Gia_Obj_t * pFan[2], * pObj = Gia_ManCo(p, 0); + vXors = Vec_IntAlloc( 100 ); + if ( Gia_ManCoNum(p) == 1 ) + { + if ( Gia_ObjFaninC0(pObj) ) + Gia_ManCollectTopXors_rec( p, Gia_ObjFanin0(pObj), vXors ); + else + Vec_IntPush( vXors, Gia_ObjId(p, Gia_ObjFanin0(pObj)) ); + } + else + { + Gia_ManForEachCo( p, pObj, i ) + if ( Gia_ObjFaninId0p(p, pObj) > 0 ) + Vec_IntPush( vXors, Gia_ObjFaninId0p(p, pObj) ); + } + // order by support size + Gia_ManDupDemiterOrderXors( p, vXors ); + //Vec_IntPrint( vXors ); + Vec_IntReverseOrder( vXors ); // from MSB to LSB + // divide into groups + Gia_ManCleanMark01(p); + vPart[0] = Vec_IntAlloc( 100 ); + vPart[1] = Vec_IntAlloc( 100 ); + Gia_ManForEachObjVec( vXors, p, pObj, i ) + { + int fCompl = 0; + if ( !Gia_ObjRecognizeExor(pObj, &pFan[0], &pFan[1]) ) + pFan[0] = pObj, pFan[1] = Gia_ManConst0(p), Count1++; + else + { + fCompl ^= Gia_IsComplement(pFan[0]); + fCompl ^= Gia_IsComplement(pFan[1]); + pFan[0] = Gia_Regular(pFan[0]); + pFan[1] = Gia_Regular(pFan[1]); + } + fFlip = Gia_ManDecideWhereToAdd( p, vPart, pFan ); + Vec_IntPush( vPart[0], Gia_ObjId(p, pFan[fFlip]) ); + Vec_IntPush( vPart[1], Gia_ObjId(p, pFan[!fFlip]) ); + Gia_ManSetMark0Dfs_rec( p, Gia_ObjId(p, pFan[fFlip]) ); + Gia_ManSetMark1Dfs_rec( p, Gia_ObjId(p, pFan[!fFlip]) ); + } + //printf( "Detected %d single-output XOR miters and %d other miters.\n", Vec_IntSize(vXors) - Count1, Count1 ); + Vec_IntFree( vXors ); + Gia_ManCleanMark01(p); + // create new order + vOrder = Vec_IntAlloc( 100 ); + Vec_IntForEachEntryTwo( vPart[0], vPart[1], iObj, iObj2, i ) + Vec_IntPushTwo( vOrder, iObj, iObj2 ); + Vec_IntFree( vPart[0] ); + Vec_IntFree( vPart[1] ); + Vec_IntReverseOrder( vOrder ); // from LSB to MSB + //Vec_IntPrint( vOrder ); + return vOrder; +} +Gia_Man_t * Gia_ManDemiterToDual( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; + Vec_Int_t * vNodes; + Vec_Int_t * vOrder = Gia_ManCollectTopXors( p ); + if ( vOrder == NULL ) + { + printf( "Cannot demiter because the top-most gate is an AND-gate.\n" ); + return NULL; + } + assert( Vec_IntSize(vOrder) % 2 == 0 ); + vNodes = Vec_IntAlloc( Gia_ManObjNum(p) ); + Gia_ManIncrementTravId( p ); + Gia_ManCollectAnds( p, Vec_IntArray(vOrder), Vec_IntSize(vOrder), vNodes, NULL ); + pNew = Gia_ManStart( 1 + Gia_ManCiNum(p) + Vec_IntSize(vNodes) + Vec_IntSize(vOrder) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + pObj = Gia_ManCo(p, 0); + if ( Gia_ObjFanin0(pObj) == Gia_ManConst0(p) ) + { + Gia_ManAppendCo( pNew, 0 ); + Gia_ManAppendCo( pNew, Gia_ObjFaninC0(pObj) ); + } + else + { + Gia_ManSetPhase( p ); + Gia_ManForEachObjVec( vOrder, p, pObj, i ) + Gia_ManAppendCo( pNew, Abc_LitNotCond(pObj->Value, pObj->fPhase) ); + } + Vec_IntFree( vNodes ); + Vec_IntFree( vOrder ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Collect nodes reachable from odd/even outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCollectDfs_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vNodes ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return; + Gia_ObjSetTravIdCurrentId(p, iObj); + pObj = Gia_ManObj( p, iObj ); + if ( !Gia_ObjIsAnd(pObj) ) + return; + Gia_ManCollectDfs_rec( p, Gia_ObjFaninId0(pObj, iObj), vNodes ); + Gia_ManCollectDfs_rec( p, Gia_ObjFaninId1(pObj, iObj), vNodes ); + Vec_IntPush( vNodes, iObj ); +} +Vec_Int_t * Gia_ManCollectReach( Gia_Man_t * p, int fOdd ) +{ + int i, iDriver; + Vec_Int_t * vNodes = Vec_IntAlloc( Gia_ManObjNum(p) ); + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); + Gia_ManForEachCoDriverId( p, iDriver, i ) + if ( (i & 1) == fOdd ) + Gia_ManCollectDfs_rec( p, iDriver, vNodes ); + return vNodes; +} +int Gia_ManDemiterDual( Gia_Man_t * p, Gia_Man_t ** pp0, Gia_Man_t ** pp1 ) +{ + Gia_Obj_t * pObj; + int i, fOdd; + assert( Gia_ManRegNum(p) == 0 ); + assert( Gia_ManCoNum(p) % 2 == 0 ); + *pp0 = *pp1 = NULL; + for ( fOdd = 0; fOdd < 2; fOdd++ ) + { + Vec_Int_t * vNodes = Gia_ManCollectReach( p, fOdd ); + Gia_Man_t * pNew = Gia_ManStart( 1 + Gia_ManCiNum(p) + Vec_IntSize(vNodes) + Gia_ManCoNum(p)/2 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + if ( (i & 1) == fOdd ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Vec_IntFree( vNodes ); + if ( fOdd ) + *pp1 = pNew; + else + *pp0 = pNew; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Collect nodes reachable from first/second half of outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManCollectReach2( Gia_Man_t * p, int fSecond ) +{ + int i, iDriver; + Vec_Int_t * vNodes = Vec_IntAlloc( Gia_ManObjNum(p) ); + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); + Gia_ManForEachCoDriverId( p, iDriver, i ) + if ( (i < Gia_ManCoNum(p)/2) ^ fSecond ) + Gia_ManCollectDfs_rec( p, iDriver, vNodes ); + return vNodes; +} +int Gia_ManDemiterTwoWords( Gia_Man_t * p, Gia_Man_t ** pp0, Gia_Man_t ** pp1 ) +{ + Gia_Obj_t * pObj; + int i, fSecond; + assert( Gia_ManRegNum(p) == 0 ); + assert( Gia_ManCoNum(p) % 2 == 0 ); + *pp0 = *pp1 = NULL; + for ( fSecond = 0; fSecond < 2; fSecond++ ) + { + Vec_Int_t * vNodes = Gia_ManCollectReach2( p, fSecond ); + Gia_Man_t * pNew = Gia_ManStart( 1 + Gia_ManCiNum(p) + Vec_IntSize(vNodes) + Gia_ManCoNum(p)/2 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + if ( (i < Gia_ManCoNum(p)/2) ^ fSecond ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Vec_IntFree( vNodes ); + if ( fSecond ) + *pp1 = pNew; + else + *pp0 = pNew; + } + return 1; +} + + + +/**Function************************************************************* + + Synopsis [Extracts "half" of the sequential AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupHalfSeq( Gia_Man_t * p, int fSecond ) +{ + int i; Gia_Obj_t * pObj; + Gia_Man_t * pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = 0; + if ( fSecond ) + { + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachPo( p, pObj, i ) + Gia_ManDupOrderDfs_rec( pNew, p, pObj ); + Gia_ManForEachRi( p, pObj, i ) + if ( i >= Gia_ManRegNum(p)/2 ) + Gia_ManDupOrderDfs_rec( pNew, p, pObj ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p)- Gia_ManRegNum(p)/2 ); + } + else + { + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachRo( p, pObj, i ) + if ( i >= Gia_ManRegNum(p)/2 ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachRo( p, pObj, i ) + if ( i < Gia_ManRegNum(p)/2 ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachPo( p, pObj, i ) + Gia_ManDupOrderDfs_rec( pNew, p, pObj ); + Gia_ManForEachRi( p, pObj, i ) + if ( i < Gia_ManRegNum(p)/2 ) + Gia_ManDupOrderDfs_rec( pNew, p, pObj ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p)/2 ); + } + return pNew; +} + +/**Function************************************************************* + + Synopsis [Merge two sets of sequential equivalences.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSeqEquivMerge( Gia_Man_t * p, Gia_Man_t * pPart[2] ) +{ + int i, iObj, * pClasses = ABC_FALLOC( int, Gia_ManObjNum(p) ); + int n, Repr, * pClass2Repr = ABC_FALLOC( int, Gia_ManObjNum(p) ); + // initialize equiv class representation in the big AIG + assert( p->pReprs == NULL && p->pNexts == NULL ); + p->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + Gia_ObjSetRepr( p, i, GIA_VOID ); + // map equivalences of p into classes + pClasses[0] = 0; + for ( n = 0; n < 2; n++ ) + { + assert( pPart[n]->pReprs != NULL && pPart[n]->pNexts != NULL ); + for ( i = 0; i < Gia_ManObjNum(pPart[n]); i++ ) + if ( Gia_ObjRepr(pPart[n], i) == 0 ) + pClasses[Gia_ManObj(pPart[n], i)->Value] = 0; + Gia_ManForEachClass( pPart[n], i ) + { + Repr = Gia_ManObj(pPart[n], i)->Value; + if ( n == 1 ) + { + Gia_ClassForEachObj( pPart[n], i, iObj ) + if ( pClasses[Gia_ManObj(pPart[n], iObj)->Value] != -1 ) + Repr = pClasses[Gia_ManObj(pPart[n], iObj)->Value]; + } + Gia_ClassForEachObj( pPart[n], i, iObj ) + pClasses[Gia_ManObj(pPart[n], iObj)->Value] = Repr; + } + } + // map representatives of each class + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + if ( pClasses[i] != -1 && pClass2Repr[pClasses[i]] == -1 ) + { + pClass2Repr[pClasses[i]] = i; + pClasses[i] = -1; + } + // remap the remaining classes + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + if ( pClasses[i] != -1 ) + p->pReprs[i].iRepr = pClass2Repr[pClasses[i]]; + ABC_FREE(pClasses); + ABC_FREE(pClass2Repr); + // create next pointers + p->pNexts = Gia_ManDeriveNexts( p ); +} + +/**Function************************************************************* + + Synopsis [Print equivalences.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintEquivs( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; int i, iObj; + printf( "Const0:" ); + Gia_ManForEachAnd( p, pObj, i ) + if ( Gia_ObjRepr(p, i) == 0 ) + printf( " %d", i ); + printf( "\n" ); + Gia_ManForEachClass( p, i ) + { + printf( "%d:", i ); + Gia_ClassForEachObj1( p, i, iObj ) + printf( " %d", iObj ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Computing seq equivs by dividing AIG into two parts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSeqEquivDivide( Gia_Man_t * p, Cec_ParCor_t * pPars ) +{ + Gia_Man_t * pParts[2]; + Gia_Obj_t * pObj; + int n, i; + for ( n = 0; n < 2; n++ ) + { + // derive n-th part of the AIG + pParts[n] = Gia_ManDupHalfSeq( p, n ); + //Gia_ManPrintStats( pParts[n], NULL ); + // compute equivalences (recorded internally using pReprs and pNexts) + Cec_ManLSCorrespondenceClasses( pParts[n], pPars ); + // make the nodes of the part AIG point to their prototypes in the AIG + Gia_ManForEachObj( p, pObj, i ) + if ( ~pObj->Value ) + Gia_ManObj( pParts[n], Abc_Lit2Var(pObj->Value) )->Value = i; + } + Gia_ManSeqEquivMerge( p, pParts ); + Gia_ManStop( pParts[0] ); + Gia_ManStop( pParts[1] ); +} +Gia_Man_t * Gia_ManScorrDivideTest( Gia_Man_t * p, Cec_ParCor_t * pPars ) +{ + extern Gia_Man_t * Gia_ManCorrReduce( Gia_Man_t * p ); + Gia_Man_t * pNew, * pTemp; + ABC_FREE( p->pReprs ); p->pReprs = NULL; + ABC_FREE( p->pNexts ); p->pNexts = NULL; + Gia_ManSeqEquivDivide( p, pPars ); + //Gia_ManPrintEquivs( p ); + pNew = Gia_ManCorrReduce( p ); + pNew = Gia_ManSeqCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicate AIG by creating a cut between logic fed by PIs] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManHighLightFlopLogic( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; int i; + Gia_ManForEachPi( p, pObj, i ) + pObj->fMark0 = 0; + Gia_ManForEachRo( p, pObj, i ) + pObj->fMark0 = 1; + Gia_ManForEachAnd( p, pObj, i ) + pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 | Gia_ObjFanin1(pObj)->fMark0; + Gia_ManForEachCo( p, pObj, i ) + pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0; +} +Gia_Man_t * Gia_ManDupReplaceCut( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; int i; + Gia_Obj_t * pObj, * pFanin; + Gia_ManHighLightFlopLogic( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + // create PIs for nodes pointed to from above the cut + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachAnd( p, pObj, i ) + { + if ( !pObj->fMark0 ) + continue; + pFanin = Gia_ObjFanin0(pObj); + if ( !pFanin->fMark0 && !~pFanin->Value ) + pFanin->Value = Gia_ManAppendCi(pNew); + pFanin = Gia_ObjFanin1(pObj); + if ( !pFanin->fMark0 && !~pFanin->Value ) + pFanin->Value = Gia_ManAppendCi(pNew); + } + // create flop outputs + Gia_ManForEachRo( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + // create internal nodes + Gia_ManForEachCo( p, pObj, i ) + Gia_ManDupOrderDfs_rec( pNew, p, pObj ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + Gia_ManCleanMark0( p ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicate AIG by creating a cut between logic fed by PIs] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupAddPis( Gia_Man_t * p, int nMulti ) +{ + Gia_Man_t * pNew; int i, k; + Gia_Obj_t * pObj; + pNew = Gia_ManStart( Gia_ManObjNum(p) + Gia_ManCiNum(p) * nMulti ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + { + pObj->Value = Gia_ManAppendCi(pNew); + for ( k = 1; k < nMulti; k++ ) + Gia_ManAppendCi(pNew); + } + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + assert( Gia_ManCiNum(pNew) == nMulti * Gia_ManCiNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManDupUifBoxTypes( Vec_Int_t * vBarBufs ) +{ + Vec_Int_t * vTypes = Vec_IntAlloc( 10 ); + int i, Entry; + Vec_IntForEachEntry( vBarBufs, Entry, i ) + if ( Vec_IntFind(vTypes, Entry & 0xFFFE) < 0 ) + Vec_IntPush( vTypes, Entry & 0xFFFE ); + return vTypes; +} +Vec_Wec_t ** Gia_ManDupUifBuildMap( Gia_Man_t * p ) +{ + Vec_Int_t * vTypes = Gia_ManDupUifBoxTypes( p->vBarBufs ); + Vec_Wec_t ** pvMap = ABC_ALLOC( Vec_Wec_t *, 2*Vec_IntSize(vTypes) ); + Vec_Int_t * vBufs = Vec_IntAlloc( p->nBufs ); + Gia_Obj_t * pObj; int i, Item, j, k = 0; + Gia_ManForEachObj1( p, pObj, i ) + if ( Gia_ObjIsBuf(pObj) ) + Vec_IntPush( vBufs, i ); + assert( p->nBufs == Vec_IntSize(vBufs) ); + for ( i = 0; i < 2*Vec_IntSize(vTypes); i++ ) + pvMap[i] = Vec_WecAlloc( 10 ); + Vec_IntForEachEntry( p->vBarBufs, Item, i ) + { + int Type = Vec_IntFind( vTypes, Item & 0xFFFE ); + Vec_Int_t * vVec = Vec_WecPushLevel(pvMap[2*Type + (Item&1)]); + for ( j = 0; j < (Item >> 16); j++ ) + Vec_IntPush( vVec, Vec_IntEntry(vBufs, k++) ); + } + assert( p->nBufs == k ); + for ( i = 0; i < Vec_IntSize(vTypes); i++ ) + assert( Vec_WecSize(pvMap[2*i+0]) == Vec_WecSize(pvMap[2*i+1]) ); + Vec_IntFree( vTypes ); + Vec_IntFree( vBufs ); + return pvMap; +} +int Gia_ManDupUifConstrOne( Gia_Man_t * pNew, Gia_Man_t * p, Vec_Int_t * vVec0, Vec_Int_t * vVec1 ) +{ + Vec_Int_t * vTemp = Vec_IntAlloc( Vec_IntSize(vVec0) ); + int i, o0, o1, iRes; + Vec_IntForEachEntryTwo( vVec0, vVec1, o0, o1, i ) + Vec_IntPush( vTemp, Gia_ManHashXor(pNew, Gia_ManObj(p, o0)->Value, Abc_LitNot(Gia_ManObj(p, o1)->Value)) ); + iRes = Gia_ManHashAndMulti( pNew, vTemp ); + Vec_IntFree( vTemp ); + return iRes; +} +int Gia_ManDupUifConstr( Gia_Man_t * pNew, Gia_Man_t * p, Vec_Wec_t ** pvMap, int nTypes ) +{ + int t, i, k, iUif = 1; + for ( t = 0; t < nTypes; t++ ) + { + assert( Vec_WecSize(pvMap[2*t+0]) == Vec_WecSize(pvMap[2*t+1]) ); + for ( i = 0; i < Vec_WecSize(pvMap[2*t+0]); i++ ) + for ( k = i + 1; k < Vec_WecSize(pvMap[2*t+0]); k++ ) + { + int iCond1 = Gia_ManDupUifConstrOne( pNew, p, Vec_WecEntry(pvMap[2*t+0], i), Vec_WecEntry(pvMap[2*t+0], k) ); + int iCond2 = Gia_ManDupUifConstrOne( pNew, p, Vec_WecEntry(pvMap[2*t+1], i), Vec_WecEntry(pvMap[2*t+1], k) ); + int iRes = Gia_ManHashOr( pNew, Abc_LitNot(iCond1), iCond2 ); + iUif = Gia_ManHashAnd( pNew, iUif, iRes ); + } + } + return iUif; +} +Gia_Man_t * Gia_ManDupUif( Gia_Man_t * p ) +{ + Vec_Int_t * vTypes = Gia_ManDupUifBoxTypes( p->vBarBufs ); + Vec_Wec_t ** pvMap = Gia_ManDupUifBuildMap( p ); + Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; + int i, iUif = 0; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + } + iUif = Gia_ManDupUifConstr( pNew, p, pvMap, Vec_IntSize(vTypes) ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ManHashAnd(pNew, pObj->Value, iUif) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + for ( i = 0; i < 2*Vec_IntSize(vTypes); i++ ) + Vec_WecFree( pvMap[i] ); + ABC_FREE( pvMap ); + if ( p->vBarBufs ) + pNew->vBarBufs = Vec_IntDup( p->vBarBufs ); + printf( "Added UIF constraints for %d type%s of boxes.\n", Vec_IntSize(vTypes), Vec_IntSize(vTypes) > 1 ? "s" :"" ); + Vec_IntFree( vTypes ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManDupBlackBoxBuildMap( Gia_Man_t * p ) +{ + Vec_Int_t * vMap = Vec_IntAlloc( p->nBufs ); int i, Item; + Vec_IntForEachEntry( p->vBarBufs, Item, i ) + Vec_IntFillExtra( vMap, Vec_IntSize(vMap) + (Item >> 16), Item & 1 ); + assert( p->nBufs == Vec_IntSize(vMap) ); + return vMap; +} +Gia_Man_t * Gia_ManDupBlackBox( Gia_Man_t * p ) +{ + Vec_Int_t * vMap = Gia_ManDupBlackBoxBuildMap( p ); + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, k = 0, iCi = 0, nCis = Gia_ManCiNum(p) + Vec_IntSum(vMap); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + for ( i = 0; i < nCis; i++ ) + Gia_ManAppendCi( pNew ); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + { + if ( Vec_IntEntry(vMap, k++) ) // out + pObj->Value = Gia_ManCiLit(pNew, iCi++); + else + pObj->Value = Gia_ObjFanin0Copy(pObj); + } + else if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManCiLit(pNew, iCi++); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + assert( k == p->nBufs && iCi == nCis ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Vec_IntFree( vMap ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates with the care set.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupWithCare( Gia_Man_t * p, Gia_Man_t * pCare ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, iCare = -1; + assert( Gia_ManCiNum(pCare) == Gia_ManCiNum(p) ); + assert( Gia_ManCoNum(pCare) == 1 ); + assert( Gia_ManRegNum(p) == 0 ); + assert( Gia_ManRegNum(pCare) == 0 ); + pNew = Gia_ManStart( 2*Gia_ManObjNum(p) + Gia_ManObjNum(pCare) ); + pNew->pName = Abc_UtilStrsavTwo( pNew->pName ? pNew->pName : (char *)"test", (char *)"_care" ); + Gia_ManHashAlloc( pNew ); + Gia_ManConst0(pCare)->Value = 0; + Gia_ManForEachCi( pCare, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( pCare, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( pCare, pObj, i ) + iCare = Gia_ObjFanin0Copy(pObj); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManCi(pCare, i)->Value; + Gia_ManForEachAnd( p, pObj, i ) + { + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + pObj->Value = Gia_ManHashAnd( pNew, iCare, pObj->Value ); + } + Gia_ManForEachCo( p, pObj, i ) + { + pObj->Value = Gia_ObjFanin0Copy(pObj); + pObj->Value = Gia_ManHashAnd( pNew, iCare, pObj->Value ); + Gia_ManAppendCo( pNew, pObj->Value ); + } + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManProdAdderGen( int nArgA, int nArgB, int Seed, int fSigned, int fCla ) +{ + extern void Wlc_BlastReduceMatrix( Gia_Man_t * pNew, Vec_Wec_t * vProds, Vec_Wec_t * vLevels, Vec_Int_t * vRes, int fSigned, int fCla ); + int i, k, x, fCompl, iLit; char pNameP[32], pNameT[32]; + Vec_Wec_t * vProds = Vec_WecStart( nArgA + nArgB ); + Vec_Wec_t * vLevels = Vec_WecStart( nArgA + nArgB ); + Vec_Int_t * vRes = Vec_IntAlloc( nArgA + nArgB ); + Vec_Int_t * vArgA = Vec_IntAlloc( nArgA ); + Vec_Int_t * vArgB = Vec_IntAlloc( nArgB ), * vLevel; + Gia_Man_t * pProd = Gia_ManStart( 1000 ); + Gia_Man_t * pTree = Gia_ManStart( 1000 ), * pTemp; + Gia_ManHashAlloc( pTree ); + pProd->pName = Abc_UtilStrsav( "prod" ); + pTree->pName = Abc_UtilStrsav( "tree" ); + for ( x = 0; x < nArgA; x++ ) + Vec_IntPush( vArgA, Gia_ManAppendCi(pProd) ); + for ( x = 0; x < nArgB; x++ ) + Vec_IntPush( vArgB, Gia_ManAppendCi(pProd) ); + for ( x = 0; x < nArgA + nArgB; x++ ) + { + for ( i = 0; i < nArgA; i++ ) + for ( k = 0; k < nArgB; k++ ) + { + if ( i + k != x ) + continue; + fCompl = fSigned && ((i == nArgA-1) ^ (k == nArgB-1)); + iLit = Abc_LitNotCond(Gia_ManAppendAnd(pProd, Vec_IntEntry(vArgA, i), Vec_IntEntry(vArgB, k)), fCompl); + Gia_ManAppendCo( pProd, iLit ); + Vec_WecPush( vProds, i+k, Gia_ManAppendCi(pTree) ); + Vec_WecPush( vLevels, i+k, 0 ); + } + } + if ( fSigned ) + { + Vec_WecPush( vProds, nArgA, 1 ); + Vec_WecPush( vLevels, nArgA, 0 ); + + Vec_WecPush( vProds, nArgA+nArgB-1, 1 ); + Vec_WecPush( vLevels, nArgA+nArgB-1, 0 ); + } + if ( Seed ) + { + Abc_Random( 1 ); + for ( x = 0; x < Seed; x++ ) + Abc_Random( 0 ); + Vec_WecForEachLevel( vProds, vLevel, x ) + if ( Vec_IntSize(vLevel) > 1 ) + Vec_IntRandomizeOrder( vLevel ); + } + Wlc_BlastReduceMatrix( pTree, vProds, vLevels, vRes, fSigned, fCla ); + Vec_IntShrink( vRes, nArgA + nArgB ); + assert( Vec_IntSize(vRes) == nArgA + nArgB ); + Vec_IntForEachEntry( vRes, iLit, x ) + Gia_ManAppendCo( pTree, iLit ); + pTree = Gia_ManCleanup( pTemp = pTree ); + Gia_ManStop( pTemp ); + + sprintf( pNameP, "prod%d%d.aig", nArgA, nArgB ); + sprintf( pNameT, "tree%d%d.aig", nArgA, nArgB ); + Gia_AigerWrite( pProd, pNameP, 0, 0, 0 ); + Gia_AigerWrite( pTree, pNameT, 0, 0, 0 ); + Gia_ManStop( pProd ); + Gia_ManStop( pTree ); + printf( "Dumped files \"%s\" and \"%s\".\n", pNameP, pNameT ); + + Vec_WecFree( vProds ); + Vec_WecFree( vLevels ); + Vec_IntFree( vArgA ); + Vec_IntFree( vArgB ); + Vec_IntFree( vRes ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupAddFlop( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) + 2 ); + pNew->pName = Abc_UtilStrsav(p->pName); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManAppendCo( pNew, 0 ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p)+1 ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManBoundaryMiter( Gia_Man_t * p1, Gia_Man_t * p2, int fVerbose ) +{ + // Vec_Int_t * vLits; + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, iLit; + if ( Gia_ManBufNum(p1) == 0 ) { + printf( "The first AIG should have a boundary.\n" ); + return NULL; + } + if ( Gia_ManBufNum(p2) != 0 ) { + printf( "The second AIG should have no boundary.\n" ); + return NULL; + } + assert( Gia_ManBufNum(p1) > 0 ); + assert( Gia_ManBufNum(p2) == 0 ); + assert( Gia_ManRegNum(p1) == 0 ); + assert( Gia_ManRegNum(p2) == 0 ); + assert( Gia_ManCiNum(p1) == Gia_ManCiNum(p2) ); + assert( Gia_ManCoNum(p1) == Gia_ManCoNum(p2) ); + // vLits = Vec_IntAlloc( Gia_ManBufNum(p1) ); + if ( fVerbose ) + printf( "Creating a boundary miter with %d inputs, %d outputs, and %d buffers.\n", + Gia_ManCiNum(p1), Gia_ManCoNum(p1), Gia_ManBufNum(p1) ); + pNew = Gia_ManStart( Gia_ManObjNum(p1) + Gia_ManObjNum(p2) ); + pNew->pName = ABC_ALLOC( char, strlen(p1->pName) + 10 ); + sprintf( pNew->pName, "%s_bmiter", p1->pName ); + Gia_ManHashStart( pNew ); + Gia_ManConst0(p1)->Value = 0; + Gia_ManConst0(p2)->Value = 0; + + + for( int i = 0; i < Gia_ManCiNum(p1); i++ ) + { + int iLit = Gia_ManCi(p1, i)->Value = Gia_ManCi(p2, i) -> Value = Gia_ManAppendCi(pNew); + + pObj = Gia_ManCi(p1, i); + if ( pBnd ) Bnd_ManMap( iLit, Gia_ObjId( p1, pObj ), 1 ); + + pObj = Gia_ManCi(p2, i); + if ( pBnd ) Bnd_ManMap( iLit, Gia_ObjId( p2, pObj) , 0 ); + + } + + // record the corresponding impl node of each lit + Gia_ManForEachAnd( p2, pObj, i ) + { + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( pBnd ) Bnd_ManMap( pObj -> Value, Gia_ObjId(p2, pObj), 0 ); + } + + // record hashed equivalent nodes + Gia_ManForEachAnd( p1, pObj, i ) + { + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( pBnd ) Bnd_ManMap( pObj -> Value, Gia_ObjId(p1, pObj), 1 ); + } + + Gia_ManForEachCo( p2, pObj, i ) + { + iLit = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManForEachCo( p1, pObj, i ) + { + iLit = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + + // Vec_IntForEachEntry( vLits, iLit, i ) + // Gia_ManAppendCo( pNew, iLit ); + // Vec_IntFree( vLits ); + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + Synopsis [Duplicates AIG while putting objects in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManImplFromBMiter( Gia_Man_t * p, int nPo, int nBInput ) +{ + Gia_Man_t * pNew, *pTemp; + Gia_Obj_t * pObj, *pObj2; + int i; + int nBoundI = 0, nBoundO = 0; + int nExtra; + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + // pNew->pName = Abc_UtilStrsav( p->pName ); + // pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + + // add po of impl + Gia_ManForEachCo( p, pObj, i ) + { + if ( i < nPo ) + { + Gia_ManDupOrderDfs_rec( pNew, p, pObj ); + } + } + nExtra = Gia_ManAndNum( pNew ); + + // add boundary as buf + Gia_ManForEachCo( p, pObj, i ) + { + if ( i >= 2 * nPo ) + { + pObj2 = Gia_ObjFanin0(pObj); + if (~pObj2->Value) // visited boundary + { + if ( i >= 2 * nPo + nBInput ) + { + nBoundO ++; + } + else nBoundI ++; + } + + Gia_ManDupOrderDfs_rec( pNew, p, pObj2 ); + Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + } + } + nExtra = Gia_ManAndNum( pNew ) - nExtra - Gia_ManBufNum( pNew ); + + Gia_ManForEachCi( p, pObj, i ) + if ( !~pObj->Value ) + pObj->Value = Gia_ManAppendCi(pNew); + assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(p) ); + + Gia_ManDupRemapCis( pNew, p ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + + + printf( "synthesized implementation:\n" ); + printf( "\t%d / %d input boundary recovered.\n", nBoundI, nBInput ); + printf( "\t%d / %d output boundary recovered.\n", nBoundO, Gia_ManCoNum(p)-2*nPo-nBInput ); + printf( "\t%d / %d unused nodes in the box.\n", nExtra, Gia_ManAndNum(pNew) - Gia_ManBufNum( pNew ) ); + + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupOdc( Gia_Man_t * p, int iObj, int fVerbose ) +{ + Vec_Int_t * vRoots = Vec_IntAlloc( 1 ); + Vec_Int_t * vNodes = Vec_IntAlloc( 100 ); + Vec_Int_t * vSupp = Vec_IntAlloc( 100 ); + Gia_Obj_t * pObj; int i, iRes = 0; + Vec_IntPush( vRoots, iObj ); + Gia_ManStaticFanoutStart( p ); + Gia_ManCollectTfo( p, vRoots, vNodes ); + Gia_ManStaticFanoutStop( p ); + Vec_IntSort(vNodes, 0); + Gia_ManForEachObjVecStart( vNodes, p, pObj, i, 1 ) { + if ( !Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pObj)) ) + Vec_IntPushUnique( vSupp, Gia_ObjFaninId0p(p, pObj) ); + if ( !Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pObj)) ) + Vec_IntPushUnique( vSupp, Gia_ObjFaninId1p(p, pObj) ); + } + Vec_IntSort(vSupp, 0); + if ( fVerbose ) Vec_IntPrint( vSupp ); + if ( fVerbose ) Vec_IntPrint( vNodes ); + Gia_Man_t * pTemp, * pNew = Gia_ManStart( 100 ); + pNew->pName = Abc_UtilStrsav( "care" ); + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObjVec( vSupp, p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManHashStart(pNew); + Gia_ManObj(p, iObj)->Value = 0; + Gia_ManForEachObjVecStart( vNodes, p, pObj, i, 1 ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + Gia_ManObj(p, iObj)->Value = 1; + Gia_ManForEachObjVecStart( vNodes, p, pObj, i, 1 ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + iRes = Gia_ManHashOr( pNew, iRes, Gia_ManHashXor(pNew, pObj->Value, Gia_ObjFanin0Copy(pObj)) ); + Gia_ManAppendCo( pNew, Abc_LitNot(iRes) ); + Vec_IntFree( vRoots ); + Vec_IntFree( vNodes ); + Vec_IntFree( vSupp ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Mark nodes supported by the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManMarkSupported( Gia_Man_t * p, Vec_Int_t * vObjs ) +{ + Gia_Obj_t * pObj; int i; + Vec_Int_t * vInner = Vec_IntAlloc( 100 ); + Gia_ManIncrementTravId(p); + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + Gia_ObjSetTravIdCurrent(p, pObj); + Vec_IntAppend( vInner, vObjs ); + Gia_ManForEachAnd( p, pObj, i ) { + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + continue; + if ( !Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pObj)) || !Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pObj)) ) + continue; + Gia_ObjSetTravIdCurrent(p, pObj); + Vec_IntPush( vInner, Gia_ObjId(p, pObj) ); + } + return vInner; +} +Vec_Int_t * Gia_ManMarkPointed( Gia_Man_t * p, Vec_Int_t * vCut, Vec_Int_t * vInner ) +{ + Gia_Obj_t * pObj; int i; + Vec_Int_t * vOuts = Vec_IntAlloc( 100 ); + Gia_ManForEachObjVec( vCut, p, pObj, i ) + Gia_ObjSetTravIdPrevious(p, pObj); + Gia_ManForEachAnd( p, pObj, i ) { + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + continue; + if ( Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pObj)) ) { + Gia_ObjSetTravIdPrevious(p, Gia_ObjFanin0(pObj)); + Vec_IntPush( vOuts, Gia_ObjFaninId0p(p, pObj) ); + } + if ( Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pObj)) ) { + Gia_ObjSetTravIdPrevious(p, Gia_ObjFanin1(pObj)); + Vec_IntPush( vOuts, Gia_ObjFaninId1p(p, pObj) ); + } + } + Gia_ManForEachCo( p, pObj, i ) { + if ( Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pObj)) ) { + Gia_ObjSetTravIdPrevious(p, Gia_ObjFanin0(pObj)); + Vec_IntPush( vOuts, Gia_ObjFaninId0p(p, pObj) ); + } + } + Vec_IntSort( vOuts, 0 ); + return vOuts; +} +Gia_Man_t * Gia_ManDupWindow( Gia_Man_t * p, Vec_Int_t * vCut ) +{ + Gia_Obj_t * pObj; int i; + Vec_Int_t * vInner = Gia_ManMarkSupported( p, vCut ); + Vec_Int_t * vOuts = Gia_ManMarkPointed( p, vCut, vInner ); + Gia_Man_t * pNew = Gia_ManStart( 100 ); + pNew->pName = Abc_UtilStrsav( "win" ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObjVec( vCut, p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachObjVecStart( vInner, p, pObj, i, Vec_IntSize(vCut) ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachObjVec( vOuts, p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, pObj->Value ); + printf( "Derived window with %d inputs, %d internal nodes, and %d outputs.\n", Vec_IntSize(vCut), Vec_IntSize(vInner), Vec_IntSize(vOuts) ); + printf( "Outputs: " ); + Vec_IntPrint( vOuts ); + Vec_IntFree( vInner ); + Vec_IntFree( vOuts ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Gia_ManCollectIntTfos( Gia_Man_t * p, Vec_Int_t * vVarNums ) +{ + Vec_Wec_t * vTfos = Vec_WecStart( Vec_IntSize(vVarNums) ); + Vec_Int_t * vNodes = Vec_IntAlloc( 100 ); + Gia_Obj_t * pObj; int i, k, Input, iNode; + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vVarNums, Input, i ) + Gia_ObjSetTravIdCurrentId( p, Gia_ManCiIdToId(p, Input) ); + Gia_ManForEachAnd( p, pObj, i ) + if ( Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId0(pObj, i)) || Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId1(pObj, i)) ) + Gia_ObjSetTravIdCurrentId( p, i ), Vec_IntPush( vNodes, i ); + Vec_IntForEachEntry( vVarNums, Input, i ) + { + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrentId( p, Gia_ManCiIdToId(p, Input) ); + Vec_IntForEachEntry( vNodes, iNode, k ) + if ( Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId0(Gia_ManObj(p, iNode), iNode)) || Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId1(Gia_ManObj(p, iNode), iNode)) ) + Gia_ObjSetTravIdCurrentId( p, iNode ), Vec_WecPush( vTfos, i, iNode ); + } + Vec_IntFree( vNodes ); + return vTfos; +} +Gia_Man_t * Gia_ManDupCofs( Gia_Man_t * p, Vec_Int_t * vVarNums ) +{ + Vec_Int_t * vOutLits = Vec_IntStartFull( 1 << Vec_IntSize(vVarNums) ); + Vec_Wec_t * vTfos = Gia_ManCollectIntTfos( p, vVarNums ); + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pRoot = Gia_ManCo(p, 0); int i, iLit; + assert( Gia_ManPoNum(p) == 1 && Gia_ManRegNum(p) == 0 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachCiVec( vVarNums, p, pObj, i ) + pObj->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Vec_IntWriteEntry( vOutLits, 0, Gia_ObjFanin0Copy(pRoot) ); + int m, g, x, b = 0; + for ( m = 1; m < Vec_IntSize(vOutLits); m++ ) + { + g = m ^ (m >> 1); x = (b ^ g) == 1 ? 0 : Abc_Base2Log(b ^ g); b = g; + Vec_Int_t * vNode = Vec_WecEntry( vTfos, x ); + Gia_ManPi(p, Vec_IntEntry(vVarNums, x))->Value ^= 1; + Gia_ManForEachObjVec( vNode, p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Vec_IntWriteEntry( vOutLits, g, Gia_ObjFanin0Copy(pRoot) ); + } + assert( Vec_IntFindMin(vOutLits) >= 0 ); + Vec_IntForEachEntry( vOutLits, iLit, i ) + Gia_ManAppendCo( pNew, iLit ); + Vec_IntFree( vOutLits ); + Vec_WecFree( vTfos ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManCofPattern( Gia_Man_t * p ) +{ + Vec_Int_t * vRes = Vec_IntAlloc( Gia_ManCoNum(p) ); + Vec_Int_t * vMap = Vec_IntStartFull( 2*Gia_ManObjNum(p) ); + Gia_Obj_t * pObj; int i, iLit, iClass = 0; + assert( Gia_ManCoNum(p) == 1 << Abc_Base2Log(Gia_ManCoNum(p)) ); + Gia_ManForEachPo( p, pObj, i ) + { + iLit = Gia_ObjFaninLit0p(p, pObj); + if ( Vec_IntEntry(vMap, iLit) == -1 ) + Vec_IntWriteEntry( vMap, iLit, iClass++ ); + Vec_IntPush( vRes, Vec_IntEntry(vMap, iLit) ); + } + Vec_IntFree( vMap ); + return vRes; +} +Vec_Int_t * Gia_ManCofClassPattern( Gia_Man_t * p, Vec_Int_t * vVarNums, int fVerbose ) +{ + extern Gia_Man_t * Cec4_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose ); + Gia_Man_t * pCofs = Gia_ManDupCofs( p, vVarNums ); + Gia_Man_t * pSweep = Cec4_ManSimulateTest3( pCofs, 0, 0 ); + Vec_Int_t * vRes = Gia_ManCofPattern( pSweep ); + assert( Vec_IntSize(vRes) == 1 << Vec_IntSize(vVarNums) ); + Gia_ManStop( pSweep ); + Gia_ManStop( pCofs ); + if ( fVerbose ) + { + int i, Class, nClasses = Vec_IntFindMax(vRes)+1; + printf( "%d -> %d: ", Vec_IntSize(vVarNums), nClasses ); + if ( nClasses <= 36 ) + Vec_IntForEachEntry( vRes, Class, i ) + printf( "%c", (Class < 10 ? (int)'0' : (int)'A'-10) + Class ); + printf( "\n" ); + } + return vRes; +} +Gia_Man_t * Gia_ManDupEncode( Gia_Man_t * p, Vec_Int_t * vVarNums, int fVerbose ) +{ + extern Vec_Int_t * Gia_GenDecoder( Gia_Man_t * p, int * pLits, int nLits ); + Gia_Man_t * pNew, * pTemp; + Vec_Int_t * vCols = Gia_ManCofClassPattern( p, vVarNums, fVerbose ); + Vec_Int_t * vVars = Vec_IntAlloc( 100 ), * vDec; + int i, k, Limit = Vec_IntSize(vCols), Entry; + int nClasses = Vec_IntFindMax(vCols)+1; + int nExtras = Abc_Base2Log(nClasses); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + for ( i = 0; i < Vec_IntSize(vVarNums) + nExtras; i++ ) + Vec_IntPush( vVars, Gia_ManAppendCi(pNew) ); + Gia_ManHashAlloc( pNew ); + vDec = Gia_GenDecoder( pNew, Vec_IntEntryP(vVars, Vec_IntSize(vVarNums)), nExtras ); + Vec_IntForEachEntry( vCols, Entry, i ) + Vec_IntWriteEntry( vCols, i, Vec_IntEntry(vDec, Entry) ); + Vec_IntFree( vDec ); + for ( i = Vec_IntSize(vVarNums) - 1; i >= 0; i--, Limit /= 2 ) + for ( k = 0; k < Limit; k += 2 ) + Vec_IntWriteEntry( vCols, k/2, Gia_ManHashMux(pNew, Vec_IntEntry(vVars, i), Vec_IntEntry(vCols, k+1), Vec_IntEntry(vCols, k)) ); + Gia_ManAppendCo( pNew, Vec_IntEntry(vCols, 0) ); + Vec_IntFree( vCols ); + Vec_IntFree( vVars ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + if ( fVerbose ) + printf( "Generated AIG with %d inputs and %d nodes representing %d PIs with %d columns.\n", + Gia_ManPiNum(pNew), Gia_ManAndNum(pNew), Vec_IntSize(vVarNums), nClasses ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCofClassRand( Gia_Man_t * p, int nVars, int nRands ) +{ + for ( int n = 0; n < nRands; n++ ) + { + Abc_Random(1); + for ( int i = 0; i < n; i++ ) + Abc_Random(0); + Vec_Int_t * vIns = Vec_IntStartNatural( Gia_ManPiNum(p) ); + Vec_IntRandomizeOrder( vIns ); + Vec_IntShrink( vIns, nVars ); + int k, Entry; + printf( "Vars: " ); + Vec_IntForEachEntry( vIns, Entry, k ) + printf( "%d ", Entry ); + printf( " " ); + Vec_Int_t * vTemp = Gia_ManCofClassPattern( p, vIns, 1 ); + Vec_IntFree( vTemp ); + Vec_IntFree( vIns ); + } +} +void Gia_ManCofClassEnum( Gia_Man_t * p, int nVars ) +{ + Vec_Int_t * vIns = Vec_IntAlloc( nVars ); + int m, k, Entry, Count, nMints = 1 << Gia_ManPiNum(p); + for ( m = 0; m < nMints; m++ ) { + for ( Count = k = 0; k < Gia_ManPiNum(p); k++ ) + Count += (m >> k) & 1; + if ( Count != nVars ) + continue; + Vec_IntClear( vIns ); + for ( k = 0; k < Gia_ManPiNum(p); k++ ) + if ( (m >> k) & 1 ) + Vec_IntPush( vIns, k ); + assert( Vec_IntSize(vIns) == Count ); + printf( "Vars: " ); + Vec_IntForEachEntry( vIns, Entry, k ) + printf( "%d ", Entry ); + printf( " " ); + Vec_Int_t * vTemp = Gia_ManCofClassPattern( p, vIns, 1 ); + Vec_IntFree( vTemp ); + } + Vec_IntFree( vIns ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaEdge.c b/yosys/abc/src/aig/gia/giaEdge.c new file mode 100644 index 00000000000..5ba8006fd38 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaEdge.c @@ -0,0 +1,1000 @@ +/**CFile**************************************************************** + + FileName [giaEdge.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Edge-related procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaEdge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/tim/tim.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Gia_ObjEdgeCount( int iObj, Vec_Int_t * vEdge1, Vec_Int_t * vEdge2 ) +{ + return (Vec_IntEntry(vEdge1, iObj) > 0) + (Vec_IntEntry(vEdge2, iObj) > 0); +} +static inline int Gia_ObjEdgeAdd( int iObj, int iNext, Vec_Int_t * vEdge1, Vec_Int_t * vEdge2 ) +{ + int RetValue = 0; + if ( Vec_IntEntry(vEdge1, iObj) == 0 ) + Vec_IntWriteEntry(vEdge1, iObj, iNext); + else if ( Vec_IntEntry(vEdge2, iObj) == 0 ) + Vec_IntWriteEntry(vEdge2, iObj, iNext); + else RetValue = 1; + return RetValue; +} +static inline void Gia_ObjEdgeRemove( int iObj, int iNext, Vec_Int_t * vEdge1, Vec_Int_t * vEdge2 ) +{ + assert( Vec_IntEntry(vEdge1, iObj) == iNext || Vec_IntEntry(vEdge2, iObj) == iNext ); + if ( Vec_IntEntry(vEdge1, iObj) == iNext ) + Vec_IntWriteEntry( vEdge1, iObj, Vec_IntEntry(vEdge2, iObj) ); + Vec_IntWriteEntry( vEdge2, iObj, 0 ); +} +static inline void Gia_ObjEdgeClean( int iObj, Vec_Int_t * vEdge1, Vec_Int_t * vEdge2 ) +{ + Vec_IntWriteEntry( vEdge1, iObj, 0 ); + Vec_IntWriteEntry( vEdge2, iObj, 0 ); +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Transforms edge assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManEdgeFromArray( Gia_Man_t * p, Vec_Int_t * vArray ) +{ + int i, iObj1, iObj2, Count = 0; + Vec_IntFreeP( &p->vEdge1 ); + Vec_IntFreeP( &p->vEdge2 ); + p->vEdge1 = Vec_IntStart( Gia_ManObjNum(p) ); + p->vEdge2 = Vec_IntStart( Gia_ManObjNum(p) ); + Vec_IntForEachEntryDouble( vArray, iObj1, iObj2, i ) + { + assert( iObj1 < iObj2 ); + Count += Gia_ObjEdgeAdd( iObj1, iObj2, p->vEdge1, p->vEdge2 ); + Count += Gia_ObjEdgeAdd( iObj2, iObj1, p->vEdge1, p->vEdge2 ); + } + if ( Count ) + printf( "Found %d violations during edge conversion.\n", Count ); +} +Vec_Int_t * Gia_ManEdgeToArray( Gia_Man_t * p ) +{ + int iObj, iFanin; + Vec_Int_t * vArray = Vec_IntAlloc( 1000 ); + assert( p->vEdge1 && p->vEdge2 ); + assert( Vec_IntSize(p->vEdge1) == Gia_ManObjNum(p) ); + assert( Vec_IntSize(p->vEdge2) == Gia_ManObjNum(p) ); + for ( iObj = 0; iObj < Gia_ManObjNum(p); iObj++ ) + { + iFanin = Vec_IntEntry( p->vEdge1, iObj ); + if ( iFanin && iFanin < iObj ) + Vec_IntPushTwo( vArray, iFanin, iObj ); + iFanin = Vec_IntEntry( p->vEdge2, iObj ); + if ( iFanin && iFanin < iObj ) + Vec_IntPushTwo( vArray, iFanin, iObj ); + } + return vArray; +} + +/**Function************************************************************* + + Synopsis [Prints mapping statistics.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManConvertPackingToEdges( Gia_Man_t * p ) +{ + int i, k, Entry, nEntries, nEntries2, nNodes[4], Count = 0; + if ( p->vPacking == NULL ) + return; + Vec_IntFreeP( &p->vEdge1 ); + Vec_IntFreeP( &p->vEdge2 ); + p->vEdge1 = Vec_IntStart( Gia_ManObjNum(p) ); + p->vEdge2 = Vec_IntStart( Gia_ManObjNum(p) ); + // iterate through structures + nEntries = Vec_IntEntry( p->vPacking, 0 ); + nEntries2 = 0; + Vec_IntForEachEntryStart( p->vPacking, Entry, i, 1 ) + { + assert( Entry > 0 && Entry < 4 ); + i++; + for ( k = 0; k < Entry; k++, i++ ) + nNodes[k] = Vec_IntEntry(p->vPacking, i); + i--; + nEntries2++; + // create edges + if ( Entry == 2 ) + { + Count += Gia_ObjEdgeAdd( nNodes[0], nNodes[1], p->vEdge1, p->vEdge2 ); + Count += Gia_ObjEdgeAdd( nNodes[1], nNodes[0], p->vEdge1, p->vEdge2 ); + } + else if ( Entry == 3 ) + { + Count += Gia_ObjEdgeAdd( nNodes[0], nNodes[2], p->vEdge1, p->vEdge2 ); + Count += Gia_ObjEdgeAdd( nNodes[2], nNodes[0], p->vEdge1, p->vEdge2 ); + Count += Gia_ObjEdgeAdd( nNodes[1], nNodes[2], p->vEdge1, p->vEdge2 ); + Count += Gia_ObjEdgeAdd( nNodes[2], nNodes[1], p->vEdge1, p->vEdge2 ); + } + } + assert( nEntries == nEntries2 ); + if ( Count ) + printf( "Skipped %d illegal edges.\n", Count ); +} + +/**Function************************************************************* + + Synopsis [Evaluates given edge assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ObjHaveEdge( Gia_Man_t * p, int iObj, int iNext ) +{ + return Vec_IntEntry(p->vEdge1, iObj) == iNext || Vec_IntEntry(p->vEdge2, iObj) == iNext; +} +int Gia_ObjCheckEdge( Gia_Man_t * p, int iObj, int iNext ) +{ + return Gia_ObjHaveEdge( p, iObj, iNext ); +} +static inline int Gia_ObjEvalEdgeDelay( Gia_Man_t * p, int iObj, Vec_Int_t * vDelay ) +{ + int nEdgeDelay = 2; + int i, iFan, Delay, DelayMax = 0; + if ( Gia_ManHasMapping(p) && Gia_ObjIsLut(p, iObj) ) + { + assert( Gia_ObjLutSize(p, iObj) <= 4 ); + Gia_LutForEachFanin( p, iObj, iFan, i ) + { + Delay = Vec_IntEntry(vDelay, iFan) + (Gia_ObjHaveEdge(p, iObj, iFan) ? nEdgeDelay : 10); + DelayMax = Abc_MaxInt( DelayMax, Delay ); + } + } + else if ( Gia_ObjIsLut2(p, iObj) ) + { + assert( Gia_ObjLutSize2(p, iObj) <= 4 ); + Gia_LutForEachFanin2( p, iObj, iFan, i ) + { + Delay = Vec_IntEntry(vDelay, iFan) + (Gia_ObjHaveEdge(p, iObj, iFan) ? nEdgeDelay : 10); + DelayMax = Abc_MaxInt( DelayMax, Delay ); + } + } + else assert( 0 ); + return DelayMax; +} +int Gia_ManEvalEdgeDelay( Gia_Man_t * p ) +{ + int k, iLut, DelayMax = 0; + assert( p->vEdge1 && p->vEdge2 ); + Vec_IntFreeP( &p->vEdgeDelay ); + p->vEdgeDelay = Vec_IntStart( Gia_ManObjNum(p) ); + if ( Gia_ManHasMapping(p) ) + { + if ( p->pManTime != NULL && Tim_ManBoxNum((Tim_Man_t*)p->pManTime) ) + { + Gia_Obj_t * pObj; + Vec_Int_t * vNodes = Gia_ManOrderWithBoxes( p ); + Tim_ManIncrementTravId( (Tim_Man_t*)p->pManTime ); + Gia_ManForEachObjVec( vNodes, p, pObj, k ) + { + iLut = Gia_ObjId( p, pObj ); + if ( Gia_ObjIsAnd(pObj) ) + { + if ( Gia_ObjIsLut(p, iLut) ) + Vec_IntWriteEntry( p->vEdgeDelay, iLut, Gia_ObjEvalEdgeDelay(p, iLut, p->vEdgeDelay) ); + } + else if ( Gia_ObjIsCi(pObj) ) + { + int arrTime = Tim_ManGetCiArrival( (Tim_Man_t*)p->pManTime, Gia_ObjCioId(pObj) ); + Vec_IntWriteEntry( p->vEdgeDelay, iLut, arrTime ); + } + else if ( Gia_ObjIsCo(pObj) ) + { + int arrTime = Vec_IntEntry( p->vEdgeDelay, Gia_ObjFaninId0(pObj, iLut) ); + Tim_ManSetCoArrival( (Tim_Man_t*)p->pManTime, Gia_ObjCioId(pObj), arrTime ); + } + else if ( !Gia_ObjIsConst0(pObj) ) + assert( 0 ); + } + Vec_IntFree( vNodes ); + } + else + { + Gia_ManForEachLut( p, iLut ) + Vec_IntWriteEntry( p->vEdgeDelay, iLut, Gia_ObjEvalEdgeDelay(p, iLut, p->vEdgeDelay) ); + } + } + else if ( Gia_ManHasMapping2(p) ) + { + if ( p->pManTime != NULL && Tim_ManBoxNum((Tim_Man_t*)p->pManTime) ) + { + Gia_Obj_t * pObj; + Vec_Int_t * vNodes = Gia_ManOrderWithBoxes( p ); + Tim_ManIncrementTravId( (Tim_Man_t*)p->pManTime ); + Gia_ManForEachObjVec( vNodes, p, pObj, k ) + { + iLut = Gia_ObjId( p, pObj ); + if ( Gia_ObjIsAnd(pObj) ) + { + if ( Gia_ObjIsLut2(p, iLut) ) + Vec_IntWriteEntry( p->vEdgeDelay, iLut, Gia_ObjEvalEdgeDelay(p, iLut, p->vEdgeDelay) ); + } + else if ( Gia_ObjIsCi(pObj) ) + { + int arrTime = Tim_ManGetCiArrival( (Tim_Man_t*)p->pManTime, Gia_ObjCioId(pObj) ); + Vec_IntWriteEntry( p->vEdgeDelay, iLut, arrTime ); + } + else if ( Gia_ObjIsCo(pObj) ) + { + int arrTime = Vec_IntEntry( p->vEdgeDelay, Gia_ObjFaninId0(pObj, iLut) ); + Tim_ManSetCoArrival( (Tim_Man_t*)p->pManTime, Gia_ObjCioId(pObj), arrTime ); + } + else if ( !Gia_ObjIsConst0(pObj) ) + assert( 0 ); + } + Vec_IntFree( vNodes ); + } + else + { + Gia_ManForEachLut2( p, iLut ) + Vec_IntWriteEntry( p->vEdgeDelay, iLut, Gia_ObjEvalEdgeDelay(p, iLut, p->vEdgeDelay) ); + } + } + else assert( 0 ); + Gia_ManForEachCoDriverId( p, iLut, k ) + DelayMax = Abc_MaxInt( DelayMax, Vec_IntEntry(p->vEdgeDelay, iLut) ); + return DelayMax; +} +int Gia_ManEvalEdgeCount( Gia_Man_t * p ) +{ + return (Vec_IntCountPositive(p->vEdge1) + Vec_IntCountPositive(p->vEdge2))/2; +} + + +/**Function************************************************************* + + Synopsis [Finds edge assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ObjComputeEdgeDelay( Gia_Man_t * p, int iObj, Vec_Int_t * vDelay, Vec_Int_t * vEdge1, Vec_Int_t * vEdge2, int fUseTwo ) +{ + int i, iFan, Delay, Status1, Status2; + int DelayMax = 0, DelayMax2 = 0, nCountMax = 0; + int iFanMax1 = -1, iFanMax2 = -1; + Vec_IntWriteEntry(vEdge1, iObj, 0); + Vec_IntWriteEntry(vEdge2, iObj, 0); + if ( Gia_ManHasMapping(p) && Gia_ObjIsLut(p, iObj) ) + { + assert( Gia_ObjLutSize(p, iObj) <= 4 ); + Gia_LutForEachFanin( p, iObj, iFan, i ) + { + Delay = Vec_IntEntry( vDelay, iFan ) + 10; + if ( DelayMax < Delay ) + { + DelayMax2 = DelayMax; + DelayMax = Delay; + iFanMax1 = iFan; + nCountMax = 1; + } + else if ( DelayMax == Delay ) + { + iFanMax2 = iFan; + nCountMax++; + if ( !fUseTwo ) + DelayMax2 = DelayMax; + } + else + DelayMax2 = Abc_MaxInt( DelayMax2, Delay ); + } + } + else if ( Gia_ObjIsLut2(p, iObj) ) + { + assert( Gia_ObjLutSize2(p, iObj) <= 4 ); + Gia_LutForEachFanin2( p, iObj, iFan, i ) + { + Delay = Vec_IntEntry( vDelay, iFan ) + 10; + if ( DelayMax < Delay ) + { + DelayMax2 = DelayMax; + DelayMax = Delay; + iFanMax1 = iFan; + nCountMax = 1; + } + else if ( DelayMax == Delay ) + { + iFanMax2 = iFan; + nCountMax++; + if ( !fUseTwo ) + DelayMax2 = DelayMax; + } + else + DelayMax2 = Abc_MaxInt( DelayMax2, Delay ); + } + } + else assert( 0 ); + assert( nCountMax > 0 ); + if ( DelayMax <= 10 ) + {} // skip first level + else if ( nCountMax == 1 ) + { + Status1 = Gia_ObjEdgeCount( iFanMax1, vEdge1, vEdge2 ); + if ( Status1 <= 1 ) + { + Gia_ObjEdgeAdd( iFanMax1, iObj, vEdge1, vEdge2 ); + Gia_ObjEdgeAdd( iObj, iFanMax1, vEdge1, vEdge2 ); + DelayMax = Abc_MaxInt( DelayMax2, DelayMax - 8 ); + Vec_IntWriteEntry( vDelay, iObj, DelayMax ); + return DelayMax; + } + } + else if ( fUseTwo && nCountMax == 2 ) + { + Status1 = Gia_ObjEdgeCount( iFanMax1, vEdge1, vEdge2 ); + Status2 = Gia_ObjEdgeCount( iFanMax2, vEdge1, vEdge2 ); + if ( Status1 <= 1 && Status2 <= 1 ) + { + Gia_ObjEdgeAdd( iFanMax1, iObj, vEdge1, vEdge2 ); + Gia_ObjEdgeAdd( iFanMax2, iObj, vEdge1, vEdge2 ); + Gia_ObjEdgeAdd( iObj, iFanMax1, vEdge1, vEdge2 ); + Gia_ObjEdgeAdd( iObj, iFanMax2, vEdge1, vEdge2 ); + DelayMax = Abc_MaxInt( DelayMax2, DelayMax - 8 ); + Vec_IntWriteEntry( vDelay, iObj, DelayMax ); + return DelayMax; + } + } + Vec_IntWriteEntry( vDelay, iObj, DelayMax ); + return DelayMax; +} +int Gia_ManComputeEdgeDelay( Gia_Man_t * p, int fUseTwo ) +{ + int k, iLut, DelayMax = 0; + Vec_IntFreeP( &p->vEdgeDelay ); + Vec_IntFreeP( &p->vEdge1 ); + Vec_IntFreeP( &p->vEdge2 ); + p->vEdge1 = Vec_IntStart( Gia_ManObjNum(p) ); + p->vEdge2 = Vec_IntStart( Gia_ManObjNum(p) ); + p->vEdgeDelay = Vec_IntStart( Gia_ManObjNum(p) ); + if ( Gia_ManHasMapping(p) ) + { + if ( p->pManTime != NULL && Tim_ManBoxNum((Tim_Man_t*)p->pManTime) ) + { + Gia_Obj_t * pObj; + Vec_Int_t * vNodes = Gia_ManOrderWithBoxes( p ); + Tim_ManIncrementTravId( (Tim_Man_t*)p->pManTime ); + Gia_ManForEachObjVec( vNodes, p, pObj, k ) + { + iLut = Gia_ObjId( p, pObj ); + if ( Gia_ObjIsAnd(pObj) ) + { + if ( Gia_ObjIsLut(p, iLut) ) + Gia_ObjComputeEdgeDelay( p, iLut, p->vEdgeDelay, p->vEdge1, p->vEdge2, fUseTwo ); + } + else if ( Gia_ObjIsCi(pObj) ) + { + int arrTime = Tim_ManGetCiArrival( (Tim_Man_t*)p->pManTime, Gia_ObjCioId(pObj) ); + Vec_IntWriteEntry( p->vEdgeDelay, iLut, arrTime ); + } + else if ( Gia_ObjIsCo(pObj) ) + { + int arrTime = Vec_IntEntry( p->vEdgeDelay, Gia_ObjFaninId0(pObj, iLut) ); + Tim_ManSetCoArrival( (Tim_Man_t*)p->pManTime, Gia_ObjCioId(pObj), arrTime ); + } + else if ( !Gia_ObjIsConst0(pObj) ) + assert( 0 ); + } + Vec_IntFree( vNodes ); + } + else + { + Gia_ManForEachLut( p, iLut ) + Gia_ObjComputeEdgeDelay( p, iLut, p->vEdgeDelay, p->vEdge1, p->vEdge2, fUseTwo ); + } + } + else if ( Gia_ManHasMapping2(p) ) + { + if ( p->pManTime != NULL && Tim_ManBoxNum((Tim_Man_t*)p->pManTime) ) + { + Gia_Obj_t * pObj; + Vec_Int_t * vNodes = Gia_ManOrderWithBoxes( p ); + Tim_ManIncrementTravId( (Tim_Man_t*)p->pManTime ); + Gia_ManForEachObjVec( vNodes, p, pObj, k ) + { + iLut = Gia_ObjId( p, pObj ); + if ( Gia_ObjIsAnd(pObj) ) + { + if ( Gia_ObjIsLut2(p, iLut) ) + Gia_ObjComputeEdgeDelay( p, iLut, p->vEdgeDelay, p->vEdge1, p->vEdge2, fUseTwo ); + } + else if ( Gia_ObjIsCi(pObj) ) + { + int arrTime = Tim_ManGetCiArrival( (Tim_Man_t*)p->pManTime, Gia_ObjCioId(pObj) ); + Vec_IntWriteEntry( p->vEdgeDelay, iLut, arrTime ); + } + else if ( Gia_ObjIsCo(pObj) ) + { + int arrTime = Vec_IntEntry( p->vEdgeDelay, Gia_ObjFaninId0(pObj, iLut) ); + Tim_ManSetCoArrival( (Tim_Man_t*)p->pManTime, Gia_ObjCioId(pObj), arrTime ); + } + else if ( !Gia_ObjIsConst0(pObj) ) + assert( 0 ); + } + Vec_IntFree( vNodes ); + } + else + { + Gia_ManForEachLut2( p, iLut ) + Gia_ObjComputeEdgeDelay( p, iLut, p->vEdgeDelay, p->vEdge1, p->vEdge2, fUseTwo ); + } + } + else assert( 0 ); + Gia_ManForEachCoDriverId( p, iLut, k ) + DelayMax = Abc_MaxInt( DelayMax, Vec_IntEntry(p->vEdgeDelay, iLut) ); + //printf( "The number of edges = %d. Delay = %d.\n", Gia_ManEvalEdgeCount(p), DelayMax ); + return DelayMax; +} + +/**Function************************************************************* + + Synopsis [Finds edge assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ObjComputeEdgeDelay2( Gia_Man_t * p, int iObj, Vec_Int_t * vDelay, Vec_Int_t * vEdge1, Vec_Int_t * vEdge2, Vec_Int_t * vFanMax1, Vec_Int_t * vFanMax2, Vec_Int_t * vCountMax ) +{ + int i, iFan, DelayFanin, Status1, Status2; + int DelayMax = 0, nCountMax = 0; + int iFanMax1 = -1, iFanMax2 = -1; + Vec_IntWriteEntry(vEdge1, iObj, 0); + Vec_IntWriteEntry(vEdge2, iObj, 0); + // analyze this node + DelayMax = Vec_IntEntry( vDelay, iObj ); + nCountMax = Vec_IntEntry( vCountMax, iObj ); + if ( DelayMax == 0 ) + {} + else if ( nCountMax == 1 ) + { + iFanMax1 = Vec_IntEntry( vFanMax1, iObj ); + Status1 = Gia_ObjEdgeCount( iFanMax1, vEdge1, vEdge2 ); + if ( Status1 <= 1 ) + { + Gia_ObjEdgeAdd( iFanMax1, iObj, vEdge1, vEdge2 ); + Gia_ObjEdgeAdd( iObj, iFanMax1, vEdge1, vEdge2 ); + DelayMax--; + } + } + else if ( nCountMax == 2 ) + { + iFanMax1 = Vec_IntEntry( vFanMax1, iObj ); + iFanMax2 = Vec_IntEntry( vFanMax2, iObj ); + Status1 = Gia_ObjEdgeCount( iFanMax1, vEdge1, vEdge2 ); + Status2 = Gia_ObjEdgeCount( iFanMax2, vEdge1, vEdge2 ); + if ( Status1 <= 1 && Status2 <= 1 ) + { + Gia_ObjEdgeAdd( iFanMax1, iObj, vEdge1, vEdge2 ); + Gia_ObjEdgeAdd( iFanMax2, iObj, vEdge1, vEdge2 ); + Gia_ObjEdgeAdd( iObj, iFanMax1, vEdge1, vEdge2 ); + Gia_ObjEdgeAdd( iObj, iFanMax2, vEdge1, vEdge2 ); + DelayMax--; + } + } + Vec_IntWriteEntry( vDelay, iObj, DelayMax ); + // computed DelayMax at this point + if ( Gia_ManHasMapping(p) && Gia_ObjIsLut(p, iObj) ) + { + Gia_LutForEachFanin( p, iObj, iFan, i ) + { + DelayFanin = Vec_IntEntry( vDelay, iFan ); + if ( DelayFanin < DelayMax + 1 ) + { + Vec_IntWriteEntry( vDelay, iFan, DelayMax + 1 ); + Vec_IntWriteEntry( vFanMax1, iFan, iObj ); + Vec_IntWriteEntry( vCountMax, iFan, 1 ); + } + else if ( DelayFanin == DelayMax + 1 ) + { + Vec_IntWriteEntry( vFanMax2, iFan, iObj ); + Vec_IntAddToEntry( vCountMax, iFan, 1 ); + } + } + } + else if ( Gia_ObjIsLut2(p, iObj) ) + { + Gia_LutForEachFanin2( p, iObj, iFan, i ) + { + DelayFanin = Vec_IntEntry( vDelay, iFan ); + if ( DelayFanin < DelayMax + 1 ) + { + Vec_IntWriteEntry( vDelay, iFan, DelayMax + 1 ); + Vec_IntWriteEntry( vFanMax1, iFan, iObj ); + Vec_IntWriteEntry( vCountMax, iFan, 1 ); + } + else if ( DelayFanin == DelayMax + 1 ) + { + Vec_IntWriteEntry( vFanMax2, iFan, iObj ); + Vec_IntAddToEntry( vCountMax, iFan, 1 ); + } + } + } + else assert( 0 ); + return DelayMax; +} +int Gia_ManComputeEdgeDelay2( Gia_Man_t * p ) +{ + int k, iLut, DelayMax = 0; + Vec_Int_t * vFanMax1 = Vec_IntStart( Gia_ManObjNum(p) ); + Vec_Int_t * vFanMax2 = Vec_IntStart( Gia_ManObjNum(p) ); + Vec_Int_t * vCountMax = Vec_IntStart( Gia_ManObjNum(p) ); + assert( p->pManTime == NULL ); + Vec_IntFreeP( &p->vEdgeDelay ); + Vec_IntFreeP( &p->vEdge1 ); + Vec_IntFreeP( &p->vEdge2 ); + p->vEdgeDelay = Vec_IntStart( Gia_ManObjNum(p) ); + p->vEdge1 = Vec_IntStart( Gia_ManObjNum(p) ); + p->vEdge2 = Vec_IntStart( Gia_ManObjNum(p) ); +// Gia_ManForEachCoDriverId( p, iLut, k ) +// Vec_IntWriteEntry( p->vEdgeDelay, iLut, 1 ); + if ( Gia_ManHasMapping(p) ) + Gia_ManForEachLutReverse( p, iLut ) + Gia_ObjComputeEdgeDelay2( p, iLut, p->vEdgeDelay, p->vEdge1, p->vEdge2, vFanMax1, vFanMax2, vCountMax ); + else if ( Gia_ManHasMapping2(p) ) + Gia_ManForEachLut2Reverse( p, iLut ) + Gia_ObjComputeEdgeDelay2( p, iLut, p->vEdgeDelay, p->vEdge1, p->vEdge2, vFanMax1, vFanMax2, vCountMax ); + else assert( 0 ); + Gia_ManForEachCiId( p, iLut, k ) + DelayMax = Abc_MaxInt( DelayMax, Vec_IntEntry(p->vEdgeDelay, iLut) ); + Vec_IntFree( vFanMax1 ); + Vec_IntFree( vFanMax2 ); + Vec_IntFree( vCountMax ); + //printf( "The number of edges = %d. Delay = %d.\n", Gia_ManEvalEdgeCount(p), DelayMax ); + return DelayMax; +} + +/**Function************************************************************* + + Synopsis [Finds edge assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManUpdateMapping( Gia_Man_t * p, Vec_Int_t * vNodes, Vec_Wec_t * vWin ) +{ + int i, iNode; + Vec_IntForEachEntry( vNodes, iNode, i ) + ABC_SWAP( Vec_Int_t, *Vec_WecEntry(p->vMapping2, iNode), *Vec_WecEntry(vWin, i) ); +} +int Gia_ManEvalWindowInc( Gia_Man_t * p, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Wec_t * vWin, Vec_Int_t * vTemp, int fUseTwo ) +{ + int i, iLut, Delay, DelayMax = 0; + assert( Vec_IntSize(vNodes) == Vec_WecSize(vWin) ); + Gia_ManUpdateMapping( p, vNodes, vWin ); + Gia_ManCollectTfo( p, vLeaves, vTemp ); + Vec_IntReverseOrder( vTemp ); + Vec_IntForEachEntry( vTemp, iLut, i ) + { + if ( !Gia_ObjIsLut(p, iLut) ) + continue; + Delay = Gia_ObjComputeEdgeDelay( p, iLut, p->vEdgeDelay, p->vEdge1, p->vEdge2, fUseTwo ); + DelayMax = Abc_MaxInt( DelayMax, Delay ); + } + Gia_ManUpdateMapping( p, vNodes, vWin ); + return DelayMax; +} +int Gia_ManEvalWindow( Gia_Man_t * p, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Wec_t * vWin, Vec_Int_t * vTemp, int fUseTwo ) +{ + int DelayMax; + assert( Vec_IntSize(vNodes) == Vec_WecSize(vWin) ); + Gia_ManUpdateMapping( p, vNodes, vWin ); + DelayMax = Gia_ManComputeEdgeDelay( p, fUseTwo ); + Gia_ManUpdateMapping( p, vNodes, vWin ); + return DelayMax; +} + + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Edg_ManToMapping( Gia_Man_t * p ) +{ + int iObj, iFanin, k; + assert( Gia_ManHasMapping(p) ); + Vec_WecFreeP( &p->vMapping2 ); + Vec_WecFreeP( &p->vFanouts2 ); + p->vMapping2 = Vec_WecStart( Gia_ManObjNum(p) ); + p->vFanouts2 = Vec_WecStart( Gia_ManObjNum(p) ); + Gia_ManForEachLut( p, iObj ) + { + assert( Gia_ObjLutSize(p, iObj) <= 4 ); + Gia_LutForEachFanin( p, iObj, iFanin, k ) + { + Vec_WecPush( p->vMapping2, iObj, iFanin ); + Vec_WecPush( p->vFanouts2, iFanin, iObj ); + } + } +} + +/**Function************************************************************* + + Synopsis [Computes delay for the given edge assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Edg_ObjEvalEdgeDelay( Gia_Man_t * p, int iObj, Vec_Int_t * vDelay ) +{ + int DelayEdge = 0; // 2; + int DelayNoEdge = 1; + int i, iFan, Delay, DelayMax = 0; + assert( Gia_ObjIsLut2(p, iObj) ); + Gia_LutForEachFanin2( p, iObj, iFan, i ) + { + Delay = Vec_IntEntry(vDelay, iFan) + (Gia_ObjHaveEdge(p, iObj, iFan) ? DelayEdge : DelayNoEdge); + DelayMax = Abc_MaxInt( DelayMax, Delay ); + } + //printf( "Obj %d - Level %d\n", iObj, DelayMax ); + return DelayMax; +} +int Edg_ManEvalEdgeDelay( Gia_Man_t * p ) +{ + int iLut, Delay, DelayMax = 0; + assert( p->vEdge1 && p->vEdge2 ); + if ( p->vEdgeDelay == NULL ) + p->vEdgeDelay = Vec_IntStart( Gia_ManObjNum(p) ); + else + Vec_IntFill( p->vEdgeDelay, Gia_ManObjNum(p), 0 ); + Gia_ManForEachLut2( p, iLut ) + { + Delay = Edg_ObjEvalEdgeDelay(p, iLut, p->vEdgeDelay); + Vec_IntWriteEntry( p->vEdgeDelay, iLut, Delay ); + DelayMax = Abc_MaxInt( DelayMax, Delay ); + } + return DelayMax; +} + +static inline int Edg_ObjEvalEdgeDelayR( Gia_Man_t * p, int iObj, Vec_Int_t * vDelay ) +{ + int DelayEdge = 0; // 2; + int DelayNoEdge = 1; + int i, iFan, Delay, DelayMax = 0; + assert( Gia_ObjIsLut2(p, iObj) ); + Gia_LutForEachFanout2( p, iObj, iFan, i ) + { + Delay = Vec_IntEntry(vDelay, iFan) + (Gia_ObjHaveEdge(p, iObj, iFan) ? DelayEdge : DelayNoEdge); + DelayMax = Abc_MaxInt( DelayMax, Delay ); + } + //printf( "Obj %d - LevelR %d\n", iObj, DelayMax ); + return DelayMax; +} +int Edg_ManEvalEdgeDelayR( Gia_Man_t * p ) +{ +// int k, DelayNoEdge = 1; + int iLut, Delay, DelayMax = 0; + assert( p->vEdge1 && p->vEdge2 ); + if ( p->vEdgeDelayR == NULL ) + p->vEdgeDelayR = Vec_IntStart( Gia_ManObjNum(p) ); + else + Vec_IntFill( p->vEdgeDelayR, Gia_ManObjNum(p), 0 ); +// Gia_ManForEachCoDriverId( p, iLut, k ) +// Vec_IntWriteEntry( p->vEdgeDelayR, iLut, DelayNoEdge ); + Gia_ManForEachLut2Reverse( p, iLut ) + { + Delay = Edg_ObjEvalEdgeDelayR(p, iLut, p->vEdgeDelayR); + Vec_IntWriteEntry( p->vEdgeDelayR, iLut, Delay ); + DelayMax = Abc_MaxInt( DelayMax, Delay ); + } + return DelayMax; +} + +void Edg_ManCollectCritEdges( Gia_Man_t * p, Vec_Wec_t * vEdges, int DelayMax ) +{ + Vec_Int_t * vLevel; + int k, iLut, Delay1, Delay2; + assert( p->vEdge1 && p->vEdge2 ); + Vec_WecClear( vEdges ); + Vec_WecInit( vEdges, DelayMax + 1 ); + Gia_ManForEachLut2( p, iLut ) + { + Delay1 = Vec_IntEntry( p->vEdgeDelay, iLut ); + Delay2 = Vec_IntEntry( p->vEdgeDelayR, iLut ); + assert( Delay1 + Delay2 <= DelayMax ); + if ( Delay1 + Delay2 == DelayMax ) + Vec_WecPush( vEdges, Delay1, iLut ); + } + // every level should have critical nodes, except the first one + //Vec_WecPrint( vEdges, 0 ); + Vec_WecForEachLevelStart( vEdges, vLevel, k, 1 ) + assert( Vec_IntSize(vLevel) > 0 ); +} + + +/**Function************************************************************* + + Synopsis [Update one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Edg_ObjImprove( Gia_Man_t * p, int iObj, int nEdgeLimit, int DelayMax, int fVerbose ) +{ + int nFaninsC = 0, nFanoutsC = 0; // critical + int nFaninsEC = 0, nFanoutsEC = 0; // edge-critical + int nFaninsENC = 0, nFanoutsENC = 0; // edge-non-critial + int pFanins[4], pFanouts[4]; + int nEdgeDiff, nEdges = 0, Count = 0; + int i, iNext, Delay1, Delay2; + // count how many fanins have critical edge + Delay1 = Vec_IntEntry( p->vEdgeDelayR, iObj ); + //if ( Delay1 > 1 ) + Gia_LutForEachFanin2( p, iObj, iNext, i ) + { + if ( !Gia_ObjIsAnd(Gia_ManObj(p, iNext)) ) + continue; + Delay2 = Vec_IntEntry( p->vEdgeDelay, iNext ); + if ( Gia_ObjHaveEdge(p, iObj, iNext) ) + { + nEdges++; + assert( Delay1 + Delay2 <= DelayMax ); + if ( Delay1 + Delay2 == DelayMax ) + nFaninsEC++; + else + nFaninsENC++; + } + else + { + assert( Delay1 + Delay2 + 1 <= DelayMax ); + if ( Delay1 + Delay2 + 1 == DelayMax ) + pFanins[nFaninsC++] = iNext; + } + } + // count how many fanouts have critical edge + Delay1 = Vec_IntEntry( p->vEdgeDelay, iObj ); + //if ( Delay2 < DelayMax - 1 ) + Gia_LutForEachFanout2( p, iObj, iNext, i ) + { + //if ( !Gia_ObjIsAnd(Gia_ManObj(p, iNext)) ) + // continue; + assert( Gia_ObjIsAnd(Gia_ManObj(p, iNext)) ); + Delay2 = Vec_IntEntry( p->vEdgeDelayR, iNext ); + if ( Gia_ObjHaveEdge(p, iObj, iNext) ) + { + nEdges++; + assert( Delay1 + Delay2 <= DelayMax ); + if ( Delay1 + Delay2 == DelayMax ) + nFanoutsEC++; + else + nFanoutsENC++; + } + else + { + assert( Delay1 + Delay2 + 1 <= DelayMax ); + if ( Delay1 + Delay2 + 1 == DelayMax ) + { + if ( nFanoutsC < nEdgeLimit ) + pFanouts[nFanoutsC] = iNext; + nFanoutsC++; + } + } + } + if ( fVerbose ) + { + printf( "%8d : ", iObj ); + printf( "Edges = %d ", nEdges ); + printf( "Fanins (all %d EC %d ENC %d C %d) ", + Gia_ObjLutSize2(p, iObj), nFaninsEC, nFaninsENC, nFaninsC ); + printf( "Fanouts (all %d EC %d ENC %d C %d) ", + Gia_ObjLutFanoutNum2(p, iObj), nFanoutsEC, nFanoutsENC, nFanoutsC ); + } + // consider simple cases + assert( nEdges <= nEdgeLimit ); + if ( nEdges == nEdgeLimit ) + { + if ( fVerbose ) + printf( "Full\n" ); + return 0; + } + nEdgeDiff = nEdgeLimit - nEdges; + // check if fanins or fanouts could be improved + if ( nFaninsEC == 0 && nFaninsC && nFaninsC <= nEdgeDiff ) + { + for ( i = 0; i < nFaninsC; i++ ) + if ( Gia_ObjEdgeCount(pFanins[i], p->vEdge1, p->vEdge2) == nEdgeLimit ) + break; + if ( i == nFaninsC ) + { + for ( i = 0; i < nFaninsC; i++ ) + { + Count += Gia_ObjEdgeAdd( iObj, pFanins[i], p->vEdge1, p->vEdge2 ); + Count += Gia_ObjEdgeAdd( pFanins[i], iObj, p->vEdge1, p->vEdge2 ); + } + if ( Count ) + printf( "Wrong number of edges.\n" ); + if ( fVerbose ) + printf( "Fixed %d critical fanins\n", nFaninsC ); + return 1; + } + } + if ( nFanoutsEC == 0 && nFanoutsC && nFanoutsC <= nEdgeDiff ) + { + for ( i = 0; i < nFanoutsC; i++ ) + if ( Gia_ObjEdgeCount(pFanouts[i], p->vEdge1, p->vEdge2) == nEdgeLimit ) + break; + if ( i == nFanoutsC ) + { + for ( i = 0; i < nFanoutsC; i++ ) + { + Count += Gia_ObjEdgeAdd( iObj, pFanouts[i], p->vEdge1, p->vEdge2 ); + Count += Gia_ObjEdgeAdd( pFanouts[i], iObj, p->vEdge1, p->vEdge2 ); + } + if ( Count ) + printf( "Wrong number of edges.\n" ); + if ( fVerbose ) + printf( "Fixed %d critical fanouts\n", nFanoutsC ); + return 1; + } + } + if ( fVerbose ) + printf( "Cannot fix\n" ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Finds edge assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Edg_ManAssignEdgeNew( Gia_Man_t * p, int nEdges, int fVerbose ) +{ + int DelayNoEdge = 1; + int fLevelVerbose = 0; + Vec_Int_t * vLevel; + Vec_Wec_t * vEdges = Vec_WecStart(0); + Vec_Int_t * vEdge1 = NULL, * vEdge2 = NULL; + int DelayD = 0, DelayR = 0, DelayPrev = ABC_INFINITY; + int k, j, i, iLast = -1, iObj; + if ( fVerbose ) + printf( "Running edge assignment with E = %d.\n", nEdges ); + // create fanouts + Edg_ManToMapping( p ); + // create empty assignment + Vec_IntFreeP( &p->vEdge1 ); + Vec_IntFreeP( &p->vEdge2 ); + p->vEdge1 = Vec_IntStart( Gia_ManObjNum(p) ); + p->vEdge2 = Vec_IntStart( Gia_ManObjNum(p) ); + // perform optimization + for ( i = 0; i < 10000; i++ ) + { + // if there is no improvement after 10 iterations, quit + if ( i > iLast + 50 ) + break; + // create delay information + DelayD = Edg_ManEvalEdgeDelay( p ); + DelayR = Edg_ManEvalEdgeDelayR( p ); + assert( DelayD == DelayR + DelayNoEdge ); + if ( DelayPrev > DelayD ) + { + //printf( "Saving backup point at %d levels.\n", DelayD ); + Vec_IntFreeP( &vEdge1 ); vEdge1 = Vec_IntDup( p->vEdge1 ); + Vec_IntFreeP( &vEdge2 ); vEdge2 = Vec_IntDup( p->vEdge2 ); + DelayPrev = DelayD; + iLast = i; + } + if ( fVerbose ) + printf( "\nIter %4d : Delay = %4d\n", i, DelayD ); + // collect critical nodes (nodes with critical edges) + Edg_ManCollectCritEdges( p, vEdges, DelayD ); + // sort levels according to the number of critical edges + if ( fLevelVerbose ) + { + Vec_WecForEachLevel( vEdges, vLevel, k ) + Vec_IntPush( vLevel, k ); + } + Vec_WecSort( vEdges, 0 ); + if ( fLevelVerbose ) + { + Vec_WecForEachLevel( vEdges, vLevel, k ) + { + int Level = Vec_IntPop( vLevel ); + printf( "%d: Level %2d : ", k, Level ); + Vec_IntPrint( vLevel ); + } + } + Vec_WecForEachLevel( vEdges, vLevel, k ) + { + Vec_IntForEachEntry( vLevel, iObj, j ) + if ( Edg_ObjImprove(p, iObj, nEdges, DelayD, fVerbose) ) // improved + break; + if ( j < Vec_IntSize(vLevel) ) + break; + } + if ( k == Vec_WecSize(vEdges) ) // if we could not improve anything, quit + break; + } + Vec_WecFree( vEdges ); + // update to the saved version + Vec_IntFreeP( &p->vEdge1 ); p->vEdge1 = vEdge1; + Vec_IntFreeP( &p->vEdge2 ); p->vEdge2 = vEdge2; + return DelayD; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaEmbed.c b/yosys/abc/src/aig/gia/giaEmbed.c new file mode 100644 index 00000000000..28d28483f84 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaEmbed.c @@ -0,0 +1,1876 @@ +/**CFile**************************************************************** + + FileName [giaEmbed.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Logic network derived from AIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaEmbed.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include "gia.h" +#include "aig/ioa/ioa.h" + +ABC_NAMESPACE_IMPL_START + + +/* + The code is based on the paper by D. Harel and Y. Koren, + "Graph drawing by high-dimensional embedding", + J. Graph Algs & Apps, Vol 8(2), pp. 195-217 (2004). + http://www.emis.de/journals/JGAA/accepted/2004/HarelKoren2004.8.2.pdf + + Iterative refinement is described in the paper: F. A. Aloul, I. L. Markov, and K. A. Sakallah. + "FORCE: A Fast and Easy-To-Implement Variable-Ordering Heuristic", Proc. GLSVLSI 03. + http://www.eecs.umich.edu/~imarkov/pubs/conf/glsvlsi03-force.pdf +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define GIA_PLACE_SIZE 0x7fff +// objects will be placed in box [0, GIA_PLACE_SIZE] x [0, GIA_PLACE_SIZE] + +typedef float Emb_Dat_t; + +typedef struct Emb_Obj_t_ Emb_Obj_t; +struct Emb_Obj_t_ +{ + unsigned fCi : 1; // terminal node CI + unsigned fCo : 1; // terminal node CO + unsigned fMark0 : 1; // first user-controlled mark + unsigned fMark1 : 1; // second user-controlled mark + unsigned nFanins : 28; // the number of fanins + unsigned nFanouts; // the number of fanouts + int hHandle; // the handle of the node + union { + unsigned TravId; // user-specified value + unsigned iFanin; + }; + union { + unsigned Value; // user-specified value + unsigned iFanout; + }; + int Fanios[0]; // the array of fanins/fanouts +}; + +typedef struct Emb_Man_t_ Emb_Man_t; +struct Emb_Man_t_ +{ + Gia_Man_t * pGia; // the original AIG manager + Vec_Int_t * vCis; // the vector of CIs (PIs + LOs) + Vec_Int_t * vCos; // the vector of COs (POs + LIs) + int nObjs; // the number of objects + int nRegs; // the number of registers + int nTravIds; // traversal ID of the network + int * pObjData; // the array containing data for objects + int nObjData; // the size of array to store the logic network + int fVerbose; // verbose output flag + Emb_Dat_t * pVecs; // array of vectors of size nObjs * nDims + int nReached; // the number of nodes reachable from the pivot + int nDistMax; // the maximum distance from the node + float ** pMatr; // covariance matrix nDims * nDims + float ** pEigen; // the first several eigen values of the matrix + float * pSols; // solutions to the problem nObjs * nSols; + unsigned short*pPlacement; // (x,y) coordinates for each cell +}; + +static inline int Emb_ManRegNum( Emb_Man_t * p ) { return p->nRegs; } +static inline int Emb_ManCiNum( Emb_Man_t * p ) { return Vec_IntSize(p->vCis); } +static inline int Emb_ManCoNum( Emb_Man_t * p ) { return Vec_IntSize(p->vCos); } +static inline int Emb_ManPiNum( Emb_Man_t * p ) { return Vec_IntSize(p->vCis) - p->nRegs; } +static inline int Emb_ManPoNum( Emb_Man_t * p ) { return Vec_IntSize(p->vCos) - p->nRegs; } +static inline int Emb_ManObjNum( Emb_Man_t * p ) { return p->nObjs; } +static inline int Emb_ManNodeNum( Emb_Man_t * p ) { return p->nObjs - Vec_IntSize(p->vCis) - Vec_IntSize(p->vCos); } + +static inline Emb_Obj_t * Emb_ManObj( Emb_Man_t * p, unsigned hHandle ) { return (Emb_Obj_t *)(p->pObjData + hHandle); } +static inline Emb_Obj_t * Emb_ManCi( Emb_Man_t * p, int i ) { return Emb_ManObj( p, Vec_IntEntry(p->vCis,i) ); } +static inline Emb_Obj_t * Emb_ManCo( Emb_Man_t * p, int i ) { return Emb_ManObj( p, Vec_IntEntry(p->vCos,i) ); } + +static inline int Emb_ObjIsTerm( Emb_Obj_t * pObj ) { return pObj->fCi || pObj->fCo; } +static inline int Emb_ObjIsCi( Emb_Obj_t * pObj ) { return pObj->fCi; } +static inline int Emb_ObjIsCo( Emb_Obj_t * pObj ) { return pObj->fCo; } +//static inline int Emb_ObjIsPi( Emb_Obj_t * pObj ) { return pObj->fCi && pObj->nFanins == 0; } +//static inline int Emb_ObjIsPo( Emb_Obj_t * pObj ) { return pObj->fCo && pObj->nFanouts == 0; } +static inline int Emb_ObjIsNode( Emb_Obj_t * pObj ) { return!Emb_ObjIsTerm(pObj) && pObj->nFanins > 0; } +//static inline int Emb_ObjIsConst0( Emb_Obj_t * pObj ) { return!Emb_ObjIsTerm(pObj) && pObj->nFanins == 0; } + +static inline int Emb_ObjSize( Emb_Obj_t * pObj ) { return sizeof(Emb_Obj_t) / 4 + pObj->nFanins + pObj->nFanouts; } +static inline int Emb_ObjFaninNum( Emb_Obj_t * pObj ) { return pObj->nFanins; } +static inline int Emb_ObjFanoutNum( Emb_Obj_t * pObj ) { return pObj->nFanouts; } +static inline Emb_Obj_t * Emb_ObjFanin( Emb_Obj_t * pObj, int i ) { return (Emb_Obj_t *)(((int *)pObj) - pObj->Fanios[i]); } +static inline Emb_Obj_t * Emb_ObjFanout( Emb_Obj_t * pObj, int i ) { return (Emb_Obj_t *)(((int *)pObj) + pObj->Fanios[pObj->nFanins+i]); } + +static inline void Emb_ManResetTravId( Emb_Man_t * p ) { extern void Emb_ManCleanTravId( Emb_Man_t * p ); Emb_ManCleanTravId( p ); p->nTravIds = 1; } +static inline void Emb_ManIncrementTravId( Emb_Man_t * p ) { p->nTravIds++; } +static inline void Emb_ObjSetTravId( Emb_Obj_t * pObj, int TravId ) { pObj->TravId = TravId; } +static inline void Emb_ObjSetTravIdCurrent( Emb_Man_t * p, Emb_Obj_t * pObj ) { pObj->TravId = p->nTravIds; } +static inline void Emb_ObjSetTravIdPrevious( Emb_Man_t * p, Emb_Obj_t * pObj ) { pObj->TravId = p->nTravIds - 1; } +static inline int Emb_ObjIsTravIdCurrent( Emb_Man_t * p, Emb_Obj_t * pObj ) { return ((int)pObj->TravId == p->nTravIds); } +static inline int Emb_ObjIsTravIdPrevious( Emb_Man_t * p, Emb_Obj_t * pObj ) { return ((int)pObj->TravId == p->nTravIds - 1); } + +static inline Emb_Dat_t * Emb_ManVec( Emb_Man_t * p, int v ) { return p->pVecs + v * p->nObjs; } +static inline float * Emb_ManSol( Emb_Man_t * p, int v ) { return p->pSols + v * p->nObjs; } + +#define Emb_ManForEachObj( p, pObj, i ) \ + for ( i = 0; (i < p->nObjData) && (pObj = Emb_ManObj(p,i)); i += Emb_ObjSize(pObj) ) +#define Emb_ManForEachNode( p, pObj, i ) \ + for ( i = 0; (i < p->nObjData) && (pObj = Emb_ManObj(p,i)); i += Emb_ObjSize(pObj) ) if ( Emb_ObjIsTerm(pObj) ) {} else +#define Emb_ManForEachObjVec( vVec, p, pObj, i ) \ + for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Emb_ManObj(p, Vec_IntEntry(vVec,i))); i++ ) +#define Emb_ObjForEachFanin( pObj, pNext, i ) \ + for ( i = 0; (i < (int)pObj->nFanins) && (pNext = Emb_ObjFanin(pObj,i)); i++ ) +#define Emb_ObjForEachFanout( pObj, pNext, i ) \ + for ( i = 0; (i < (int)pObj->nFanouts) && (pNext = Emb_ObjFanout(pObj,i)); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates fanin/fanout pair.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Emb_ObjAddFanin( Emb_Obj_t * pObj, Emb_Obj_t * pFanin ) +{ + assert( pObj->iFanin < pObj->nFanins ); + assert( pFanin->iFanout < pFanin->nFanouts ); + pFanin->Fanios[pFanin->nFanins + pFanin->iFanout++] = + pObj->Fanios[pObj->iFanin++] = pObj->hHandle - pFanin->hHandle; +} + +/**Function************************************************************* + + Synopsis [Creates logic network isomorphic to the given AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Emb_Man_t * Emb_ManStartSimple( Gia_Man_t * pGia ) +{ + Emb_Man_t * p; + Emb_Obj_t * pObjLog, * pFanLog; + Gia_Obj_t * pObj, * pObjRi, * pObjRo; + int i, nNodes, hHandle = 0; + // prepare the AIG + Gia_ManCreateRefs( pGia ); + // create logic network + p = ABC_CALLOC( Emb_Man_t, 1 ); + p->pGia = pGia; + p->nRegs = Gia_ManRegNum(pGia); + p->vCis = Vec_IntAlloc( Gia_ManCiNum(pGia) ); + p->vCos = Vec_IntAlloc( Gia_ManCoNum(pGia) ); + p->nObjData = (sizeof(Emb_Obj_t) / 4) * Gia_ManObjNum(pGia) + 2 * (2 * Gia_ManAndNum(pGia) + Gia_ManCoNum(pGia) + Gia_ManRegNum(pGia) + Gia_ManCoNum(pGia)); + p->pObjData = ABC_CALLOC( int, p->nObjData ); + // create constant node + Gia_ManConst0(pGia)->Value = hHandle; + pObjLog = Emb_ManObj( p, hHandle ); + pObjLog->hHandle = hHandle; + pObjLog->nFanins = Gia_ManCoNum(pGia); //0; + pObjLog->nFanouts = Gia_ObjRefNum( pGia, Gia_ManConst0(pGia) ); + // count objects + hHandle += Emb_ObjSize( pObjLog ); + nNodes = 1; + p->nObjs++; + // create the PIs + Gia_ManForEachCi( pGia, pObj, i ) + { + // create PI object + pObj->Value = hHandle; + Vec_IntPush( p->vCis, hHandle ); + pObjLog = Emb_ManObj( p, hHandle ); + pObjLog->hHandle = hHandle; + pObjLog->nFanins = Gia_ObjIsRo( pGia, pObj ); + pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj ); + pObjLog->fCi = 1; + // count objects + hHandle += Emb_ObjSize( pObjLog ); + p->nObjs++; + } + // create internal nodes + Gia_ManForEachAnd( pGia, pObj, i ) + { + assert( Gia_ObjRefNum( pGia, pObj ) > 0 ); + // create node object + pObj->Value = hHandle; + pObjLog = Emb_ManObj( p, hHandle ); + pObjLog->hHandle = hHandle; + pObjLog->nFanins = 2; + pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj ); + // add fanins + pFanLog = Emb_ManObj( p, Gia_ObjValue(Gia_ObjFanin0(pObj)) ); + Emb_ObjAddFanin( pObjLog, pFanLog ); + pFanLog = Emb_ManObj( p, Gia_ObjValue(Gia_ObjFanin1(pObj)) ); + Emb_ObjAddFanin( pObjLog, pFanLog ); + // count objects + hHandle += Emb_ObjSize( pObjLog ); + nNodes++; + p->nObjs++; + } + // create the POs + Gia_ManForEachCo( pGia, pObj, i ) + { + // create PO object + pObj->Value = hHandle; + Vec_IntPush( p->vCos, hHandle ); + pObjLog = Emb_ManObj( p, hHandle ); + pObjLog->hHandle = hHandle; + pObjLog->nFanins = 1; + pObjLog->nFanouts = 1 + Gia_ObjIsRi( pGia, pObj ); + pObjLog->fCo = 1; + // add fanins + pFanLog = Emb_ManObj( p, Gia_ObjValue(Gia_ObjFanin0(pObj)) ); + Emb_ObjAddFanin( pObjLog, pFanLog ); + // count objects + hHandle += Emb_ObjSize( pObjLog ); + p->nObjs++; + } + // connect registers + Gia_ManForEachRiRo( pGia, pObjRi, pObjRo, i ) + Emb_ObjAddFanin( Emb_ManObj(p,Gia_ObjValue(pObjRo)), Emb_ManObj(p,Gia_ObjValue(pObjRi)) ); + assert( nNodes == Emb_ManNodeNum(p) ); + assert( hHandle == p->nObjData ); + assert( p->nObjs == Gia_ManObjNum(pGia) ); + if ( hHandle != p->nObjData ) + printf( "Emb_ManStartSimple(): Fatal error in internal representation.\n" ); + // make sure the fanin/fanout counters are correct + Gia_ManForEachObj( pGia, pObj, i ) + { + if ( !~Gia_ObjValue(pObj) ) + continue; + pObjLog = Emb_ManObj( p, Gia_ObjValue(pObj) ); + assert( pObjLog->nFanins == pObjLog->iFanin || Gia_ObjIsConst0(pObj) ); + assert( pObjLog->nFanouts == pObjLog->iFanout || Gia_ObjIsCo(pObj) ); + pObjLog->iFanin = pObjLog->iFanout = 0; + } + ABC_FREE( pGia->pRefs ); + return p; +} + +/**Function************************************************************* + + Synopsis [Collect the fanin IDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Emb_ManCollectSuper_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper, Vec_Int_t * vVisit ) +{ + if ( pObj->fMark1 ) + return; + pObj->fMark1 = 1; + Vec_IntPush( vVisit, Gia_ObjId(p, pObj) ); + if ( pObj->fMark0 ) + { + Vec_IntPush( vSuper, Gia_ObjId(p, pObj) ); + return; + } + assert( Gia_ObjIsAnd(pObj) ); + Emb_ManCollectSuper_rec( p, Gia_ObjFanin0(pObj), vSuper, vVisit ); + Emb_ManCollectSuper_rec( p, Gia_ObjFanin1(pObj), vSuper, vVisit ); + +} + +/**Function************************************************************* + + Synopsis [Collect the fanin IDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Emb_ManCollectSuper( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper, Vec_Int_t * vVisit ) +{ + int Entry, i; + Vec_IntClear( vSuper ); + Vec_IntClear( vVisit ); + assert( pObj->fMark0 == 1 ); + pObj->fMark0 = 0; + Emb_ManCollectSuper_rec( p, pObj, vSuper, vVisit ); + pObj->fMark0 = 1; + Vec_IntForEachEntry( vVisit, Entry, i ) + Gia_ManObj(p, Entry)->fMark1 = 0; +} + +/**Function************************************************************* + + Synopsis [Assigns references while removing the MUX/XOR ones.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Emb_ManCreateRefsSpecial( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj, * pFan0, * pFan1; + Gia_Obj_t * pObjC, * pObjD0, * pObjD1; + int i; + assert( p->pRefs == NULL ); + Gia_ManCleanMark0( p ); + Gia_ManCreateRefs( p ); + Gia_ManForEachAnd( p, pObj, i ) + { + assert( pObj->fMark0 == 0 ); + pFan0 = Gia_ObjFanin0(pObj); + pFan1 = Gia_ObjFanin1(pObj); + // skip nodes whose fanins are PIs or are already marked + if ( Gia_ObjIsCi(pFan0) || pFan0->fMark0 || + Gia_ObjIsCi(pFan1) || pFan1->fMark0 ) + continue; + // skip nodes that are not MUX type + if ( !Gia_ObjIsMuxType(pObj) ) + continue; + // the node is MUX type, mark it and its fanins + pObj->fMark0 = 1; + pFan0->fMark0 = 1; + pFan1->fMark0 = 1; + // deref the control + pObjC = Gia_ObjRecognizeMux( pObj, &pObjD1, &pObjD0 ); + Gia_ObjRefDec( p, Gia_Regular(pObjC) ); + if ( Gia_Regular(pObjD0) == Gia_Regular(pObjD1) ) + Gia_ObjRefDec( p, Gia_Regular(pObjD0) ); + } + Gia_ManForEachAnd( p, pObj, i ) + assert( Gia_ObjRefNum(p, pObj) > 0 ); + Gia_ManCleanMark0( p ); +} + +/**Function************************************************************* + + Synopsis [Assigns references while removing the MUX/XOR ones.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Emb_ManTransformRefs( Gia_Man_t * p, int * pnObjs, int * pnFanios ) +{ + Vec_Int_t * vSuper, * vVisit; + Gia_Obj_t * pObj, * pFanin; + int i, k, Counter; + assert( p->pRefs != NULL ); + + // mark nodes to be used in the logic network + Gia_ManCleanMark0( p ); + Gia_ManConst0(p)->fMark0 = 1; + // mark the inputs + Gia_ManForEachCi( p, pObj, i ) + pObj->fMark0 = 1; + // mark those nodes that have ref count more than 1 + Gia_ManForEachAnd( p, pObj, i ) + pObj->fMark0 = (Gia_ObjRefNum(p, pObj) > 1); + // mark the output drivers + Gia_ManForEachCoDriver( p, pObj, i ) + pObj->fMark0 = 1; + + // count the number of nodes + Counter = 0; + Gia_ManForEachObj( p, pObj, i ) + Counter += pObj->fMark0; + *pnObjs = Counter + Gia_ManCoNum(p); + + // reset the references + ABC_FREE( p->pRefs ); + p->pRefs = ABC_CALLOC( int, Gia_ManObjNum(p) ); + // reference from internal nodes + Counter = 0; + vSuper = Vec_IntAlloc( 100 ); + vVisit = Vec_IntAlloc( 100 ); + Gia_ManCleanMark1( p ); + Gia_ManForEachAnd( p, pObj, i ) + { + if ( pObj->fMark0 == 0 ) + continue; + Emb_ManCollectSuper( p, pObj, vSuper, vVisit ); + Gia_ManForEachObjVec( vSuper, p, pFanin, k ) + { + assert( pFanin->fMark0 ); + Gia_ObjRefInc( p, pFanin ); + } + Counter += Vec_IntSize( vSuper ); + } + Gia_ManCheckMark1( p ); + Vec_IntFree( vSuper ); + Vec_IntFree( vVisit ); + // reference from outputs + Gia_ManForEachCoDriver( p, pObj, i ) + { + assert( pObj->fMark0 ); + Gia_ObjRefInc( p, pObj ); + } + *pnFanios = Counter + Gia_ManCoNum(p); +} + +/**Function************************************************************* + + Synopsis [Cleans the value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Emb_ManCleanTravId( Emb_Man_t * p ) +{ + Emb_Obj_t * pObj; + int i; + Emb_ManForEachObj( p, pObj, i ) + pObj->TravId = 0; +} + +/**Function************************************************************* + + Synopsis [Cleans the value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Emb_ManSetValue( Emb_Man_t * p ) +{ + Emb_Obj_t * pObj; + int i, Counter = 0; + Emb_ManForEachObj( p, pObj, i ) + { + pObj->Value = Counter++; +// if ( pObj->fCi && pObj->nFanins == 0 ) +// printf( "CI: Handle = %8d. Value = %6d. Fanins = %d.\n", pObj->hHandle, pObj->Value, pObj->nFanins ); + } +} + +/**Function************************************************************* + + Synopsis [Creates logic network isomorphic to the given AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Emb_Man_t * Emb_ManStart( Gia_Man_t * pGia ) +{ + Emb_Man_t * p; + Emb_Obj_t * pObjLog, * pFanLog; + Gia_Obj_t * pObj, * pObjRi, * pObjRo, * pFanin; + Vec_Int_t * vSuper, * vVisit; + int nObjs, nFanios, nNodes = 0; + int i, k, hHandle = 0; + // prepare the AIG +// Gia_ManCreateRefs( pGia ); + Emb_ManCreateRefsSpecial( pGia ); + Emb_ManTransformRefs( pGia, &nObjs, &nFanios ); + Gia_ManFillValue( pGia ); + // create logic network + p = ABC_CALLOC( Emb_Man_t, 1 ); + p->pGia = pGia; + p->nRegs = Gia_ManRegNum(pGia); + p->vCis = Vec_IntAlloc( Gia_ManCiNum(pGia) ); + p->vCos = Vec_IntAlloc( Gia_ManCoNum(pGia) ); + p->nObjData = (sizeof(Emb_Obj_t) / 4) * nObjs + 2 * (nFanios + Gia_ManRegNum(pGia) + Gia_ManCoNum(pGia)); + p->pObjData = ABC_CALLOC( int, p->nObjData ); + // create constant node + Gia_ManConst0(pGia)->Value = hHandle; + pObjLog = Emb_ManObj( p, hHandle ); + pObjLog->hHandle = hHandle; + pObjLog->nFanins = Gia_ManCoNum(pGia); //0; + pObjLog->nFanouts = Gia_ObjRefNum( pGia, Gia_ManConst0(pGia) ); + // count objects + hHandle += Emb_ObjSize( pObjLog ); + nNodes++; + p->nObjs++; + // create the PIs + Gia_ManForEachCi( pGia, pObj, i ) + { + // create PI object + pObj->Value = hHandle; + Vec_IntPush( p->vCis, hHandle ); + pObjLog = Emb_ManObj( p, hHandle ); + pObjLog->hHandle = hHandle; + pObjLog->nFanins = Gia_ObjIsRo( pGia, pObj ); + pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj ); + pObjLog->fCi = 1; + // count objects + hHandle += Emb_ObjSize( pObjLog ); + p->nObjs++; + } + // create internal nodes + vSuper = Vec_IntAlloc( 100 ); + vVisit = Vec_IntAlloc( 100 ); + Gia_ManForEachAnd( pGia, pObj, i ) + { + if ( pObj->fMark0 == 0 ) + { + assert( Gia_ObjRefNum( pGia, pObj ) == 0 ); + continue; + } + assert( Gia_ObjRefNum( pGia, pObj ) > 0 ); + Emb_ManCollectSuper( pGia, pObj, vSuper, vVisit ); + // create node object + pObj->Value = hHandle; + pObjLog = Emb_ManObj( p, hHandle ); + pObjLog->hHandle = hHandle; + pObjLog->nFanins = Vec_IntSize( vSuper ); + pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj ); + // add fanins + Gia_ManForEachObjVec( vSuper, pGia, pFanin, k ) + { + pFanLog = Emb_ManObj( p, Gia_ObjValue(pFanin) ); + Emb_ObjAddFanin( pObjLog, pFanLog ); + } + // count objects + hHandle += Emb_ObjSize( pObjLog ); + nNodes++; + p->nObjs++; + } + Vec_IntFree( vSuper ); + Vec_IntFree( vVisit ); + // create the POs + Gia_ManForEachCo( pGia, pObj, i ) + { + // create PO object + pObj->Value = hHandle; + Vec_IntPush( p->vCos, hHandle ); + pObjLog = Emb_ManObj( p, hHandle ); + pObjLog->hHandle = hHandle; + pObjLog->nFanins = 1; + pObjLog->nFanouts = 1 + Gia_ObjIsRi( pGia, pObj ); + pObjLog->fCo = 1; + // add fanins + pFanLog = Emb_ManObj( p, Gia_ObjValue(Gia_ObjFanin0(pObj)) ); + Emb_ObjAddFanin( pObjLog, pFanLog ); + // count objects + hHandle += Emb_ObjSize( pObjLog ); + p->nObjs++; + } + // connect registers + Gia_ManForEachRiRo( pGia, pObjRi, pObjRo, i ) + Emb_ObjAddFanin( Emb_ManObj(p,Gia_ObjValue(pObjRo)), Emb_ManObj(p,Gia_ObjValue(pObjRi)) ); + Gia_ManCleanMark0( pGia ); + assert( nNodes == Emb_ManNodeNum(p) ); + assert( nObjs == p->nObjs ); + assert( hHandle == p->nObjData ); + if ( hHandle != p->nObjData ) + printf( "Emb_ManStart(): Fatal error in internal representation.\n" ); + // make sure the fanin/fanout counters are correct + Gia_ManForEachObj( pGia, pObj, i ) + { + if ( !~Gia_ObjValue(pObj) ) + continue; + pObjLog = Emb_ManObj( p, Gia_ObjValue(pObj) ); + assert( pObjLog->nFanins == pObjLog->iFanin || Gia_ObjIsConst0(pObj) ); + assert( pObjLog->nFanouts == pObjLog->iFanout || Gia_ObjIsCo(pObj) ); + pObjLog->iFanin = pObjLog->iFanout = 0; + } + ABC_FREE( pGia->pRefs ); + return p; +} + +/**Function************************************************************* + + Synopsis [Creates logic network isomorphic to the given AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Emb_ManPrintStats( Emb_Man_t * p ) +{ +// if ( p->pName ) +// printf( "%8s : ", p->pName ); + printf( "i/o =%7d/%7d ", Emb_ManPiNum(p), Emb_ManPoNum(p) ); + if ( Emb_ManRegNum(p) ) + printf( "ff =%7d ", Emb_ManRegNum(p) ); + printf( "node =%8d ", Emb_ManNodeNum(p) ); + printf( "obj =%8d ", Emb_ManObjNum(p) ); +// printf( "lev =%5d ", Emb_ManLevelNum(p) ); +// printf( "cut =%5d ", Emb_ManCrossCut(p) ); + printf( "mem =%5.2f MB", 4.0*p->nObjData/(1<<20) ); +// printf( "obj =%5d ", Emb_ManObjNum(p) ); + printf( "\n" ); + +// Emb_ManSatExperiment( p ); +} + +/**Function************************************************************* + + Synopsis [Creates logic network isomorphic to the given AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Emb_ManStop( Emb_Man_t * p ) +{ + Vec_IntFree( p->vCis ); + Vec_IntFree( p->vCos ); + ABC_FREE( p->pPlacement ); + ABC_FREE( p->pVecs ); + ABC_FREE( p->pSols ); + ABC_FREE( p->pMatr ); + ABC_FREE( p->pEigen ); + ABC_FREE( p->pObjData ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Prints the distribution of fanins/fanouts in the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Emb_ManPrintFanio( Emb_Man_t * p ) +{ + char Buffer[100]; + Emb_Obj_t * pNode; + Vec_Int_t * vFanins, * vFanouts; + int nFanins, nFanouts, nFaninsMax, nFanoutsMax, nFaninsAll, nFanoutsAll; + int i, k, nSizeMax; + + // determine the largest fanin and fanout + nFaninsMax = nFanoutsMax = 0; + nFaninsAll = nFanoutsAll = 0; + Emb_ManForEachNode( p, pNode, i ) + { + if ( i == 0 ) continue; // skip const 0 obj + nFanins = Emb_ObjFaninNum(pNode); + nFanouts = Emb_ObjFanoutNum(pNode); + nFaninsAll += nFanins; + nFanoutsAll += nFanouts; + nFaninsMax = Abc_MaxInt( nFaninsMax, nFanins ); + nFanoutsMax = Abc_MaxInt( nFanoutsMax, nFanouts ); + } + + // allocate storage for fanin/fanout numbers + nSizeMax = Abc_MaxInt( 10 * (Abc_Base10Log(nFaninsMax) + 1), 10 * (Abc_Base10Log(nFanoutsMax) + 1) ); + vFanins = Vec_IntStart( nSizeMax ); + vFanouts = Vec_IntStart( nSizeMax ); + + // count the number of fanins and fanouts + Emb_ManForEachNode( p, pNode, i ) + { + if ( i == 0 ) continue; // skip const 0 obj + nFanins = Emb_ObjFaninNum(pNode); + nFanouts = Emb_ObjFanoutNum(pNode); + + if ( nFanins < 10 ) + Vec_IntAddToEntry( vFanins, nFanins, 1 ); + else if ( nFanins < 100 ) + Vec_IntAddToEntry( vFanins, 10 + nFanins/10, 1 ); + else if ( nFanins < 1000 ) + Vec_IntAddToEntry( vFanins, 20 + nFanins/100, 1 ); + else if ( nFanins < 10000 ) + Vec_IntAddToEntry( vFanins, 30 + nFanins/1000, 1 ); + else if ( nFanins < 100000 ) + Vec_IntAddToEntry( vFanins, 40 + nFanins/10000, 1 ); + else if ( nFanins < 1000000 ) + Vec_IntAddToEntry( vFanins, 50 + nFanins/100000, 1 ); + else if ( nFanins < 10000000 ) + Vec_IntAddToEntry( vFanins, 60 + nFanins/1000000, 1 ); + + if ( nFanouts < 10 ) + Vec_IntAddToEntry( vFanouts, nFanouts, 1 ); + else if ( nFanouts < 100 ) + Vec_IntAddToEntry( vFanouts, 10 + nFanouts/10, 1 ); + else if ( nFanouts < 1000 ) + Vec_IntAddToEntry( vFanouts, 20 + nFanouts/100, 1 ); + else if ( nFanouts < 10000 ) + Vec_IntAddToEntry( vFanouts, 30 + nFanouts/1000, 1 ); + else if ( nFanouts < 100000 ) + Vec_IntAddToEntry( vFanouts, 40 + nFanouts/10000, 1 ); + else if ( nFanouts < 1000000 ) + Vec_IntAddToEntry( vFanouts, 50 + nFanouts/100000, 1 ); + else if ( nFanouts < 10000000 ) + Vec_IntAddToEntry( vFanouts, 60 + nFanouts/1000000, 1 ); + } + + printf( "The distribution of fanins and fanouts in the network:\n" ); + printf( " Number Nodes with fanin Nodes with fanout\n" ); + for ( k = 0; k < nSizeMax; k++ ) + { + if ( vFanins->pArray[k] == 0 && vFanouts->pArray[k] == 0 ) + continue; + if ( k < 10 ) + printf( "%15d : ", k ); + else + { + sprintf( Buffer, "%d - %d", (int)pow((double)10, k/10) * (k%10), (int)pow((double)10, k/10) * (k%10+1) - 1 ); + printf( "%15s : ", Buffer ); + } + if ( vFanins->pArray[k] == 0 ) + printf( " " ); + else + printf( "%12d ", vFanins->pArray[k] ); + printf( " " ); + if ( vFanouts->pArray[k] == 0 ) + printf( " " ); + else + printf( "%12d ", vFanouts->pArray[k] ); + printf( "\n" ); + } + Vec_IntFree( vFanins ); + Vec_IntFree( vFanouts ); + + printf( "Fanins: Max = %d. Ave = %.2f. Fanouts: Max = %d. Ave = %.2f.\n", + nFaninsMax, 1.0*nFaninsAll/Emb_ManNodeNum(p), + nFanoutsMax, 1.0*nFanoutsAll/Emb_ManNodeNum(p) ); +} + +/**Function************************************************************* + + Synopsis [Computes the distance from the given object] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Emb_ManComputeDistance_old( Emb_Man_t * p, Emb_Obj_t * pPivot ) +{ + Vec_Int_t * vThis, * vNext, * vTemp; + Emb_Obj_t * pThis, * pNext; + int i, k, d, nVisited = 0; +// assert( Emb_ObjIsTerm(pPivot) ); + vThis = Vec_IntAlloc( 1000 ); + vNext = Vec_IntAlloc( 1000 ); + Emb_ManIncrementTravId( p ); + Emb_ObjSetTravIdCurrent( p, pPivot ); + Vec_IntPush( vThis, pPivot->hHandle ); + for ( d = 0; Vec_IntSize(vThis) > 0; d++ ) + { + nVisited += Vec_IntSize(vThis); + Vec_IntClear( vNext ); + Emb_ManForEachObjVec( vThis, p, pThis, i ) + { + Emb_ObjForEachFanin( pThis, pNext, k ) + { + if ( Emb_ObjIsTravIdCurrent(p, pNext) ) + continue; + Emb_ObjSetTravIdCurrent(p, pNext); + Vec_IntPush( vNext, pNext->hHandle ); + nVisited += !Emb_ObjIsTerm(pNext); + } + Emb_ObjForEachFanout( pThis, pNext, k ) + { + if ( Emb_ObjIsTravIdCurrent(p, pNext) ) + continue; + Emb_ObjSetTravIdCurrent(p, pNext); + Vec_IntPush( vNext, pNext->hHandle ); + nVisited += !Emb_ObjIsTerm(pNext); + } + } + vTemp = vThis; vThis = vNext; vNext = vTemp; + } + Vec_IntFree( vThis ); + Vec_IntFree( vNext ); + // check if there are several strongly connected components +// if ( nVisited < Emb_ManNodeNum(p) ) +// printf( "Visited less nodes (%d) than present (%d).\n", nVisited, Emb_ManNodeNum(p) ); + return d; +} + +/**Function************************************************************* + + Synopsis [Traverses from the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManTestDistanceInternal( Emb_Man_t * p ) +{ + int nAttempts = 20; + int i, iNode, Dist; + abctime clk; + Emb_Obj_t * pPivot, * pNext; + Gia_ManRandom( 1 ); + Emb_ManResetTravId( p ); + // compute distances from several randomly selected PIs + clk = Abc_Clock(); + printf( "From inputs: " ); + for ( i = 0; i < nAttempts; i++ ) + { + iNode = Gia_ManRandom( 0 ) % Emb_ManCiNum(p); + pPivot = Emb_ManCi( p, iNode ); + if ( Emb_ObjFanoutNum(pPivot) == 0 ) + { i--; continue; } + pNext = Emb_ObjFanout( pPivot, 0 ); + if ( !Emb_ObjIsNode(pNext) ) + { i--; continue; } + Dist = Emb_ManComputeDistance_old( p, pPivot ); + printf( "%d ", Dist ); + } + ABC_PRT( "Time", Abc_Clock() - clk ); + // compute distances from several randomly selected POs + clk = Abc_Clock(); + printf( "From outputs: " ); + for ( i = 0; i < nAttempts; i++ ) + { + iNode = Gia_ManRandom( 0 ) % Emb_ManCoNum(p); + pPivot = Emb_ManCo( p, iNode ); + pNext = Emb_ObjFanin( pPivot, 0 ); + if ( !Emb_ObjIsNode(pNext) ) + { i--; continue; } + Dist = Emb_ManComputeDistance_old( p, pPivot ); + printf( "%d ", Dist ); + } + ABC_PRT( "Time", Abc_Clock() - clk ); + // compute distances from several randomly selected nodes + clk = Abc_Clock(); + printf( "From nodes: " ); + for ( i = 0; i < nAttempts; i++ ) + { + iNode = Gia_ManRandom( 0 ) % Gia_ManObjNum(p->pGia); + if ( !~Gia_ManObj(p->pGia, iNode)->Value ) + { i--; continue; } + pPivot = Emb_ManObj( p, Gia_ManObj(p->pGia, iNode)->Value ); + if ( !Emb_ObjIsNode(pPivot) ) + { i--; continue; } + Dist = Emb_ManComputeDistance_old( p, pPivot ); + printf( "%d ", Dist ); + } + ABC_PRT( "Time", Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [Returns sorted array of node handles with largest fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManTestDistance( Gia_Man_t * pGia ) +{ + Emb_Man_t * p; + abctime clk = Abc_Clock(); + p = Emb_ManStart( pGia ); +// Emb_ManPrintFanio( p ); + Emb_ManPrintStats( p ); +ABC_PRT( "Time", Abc_Clock() - clk ); + Gia_ManTestDistanceInternal( p ); + Emb_ManStop( p ); +} + + + + +/**Function************************************************************* + + Synopsis [Perform BFS from the set of nodes.] + + Description [Returns one of the most distant objects.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Emb_Obj_t * Emb_ManPerformBfs( Emb_Man_t * p, Vec_Int_t * vThis, Vec_Int_t * vNext, Emb_Dat_t * pDist ) +{ + Vec_Int_t * vTemp; + Emb_Obj_t * pThis, * pNext, * pResult; + int i, k; + assert( Vec_IntSize(vThis) > 0 ); + for ( p->nDistMax = 0; Vec_IntSize(vThis) > 0; p->nDistMax++ ) + { + p->nReached += Vec_IntSize(vThis); + Vec_IntClear( vNext ); + Emb_ManForEachObjVec( vThis, p, pThis, i ) + { + if ( pDist ) pDist[pThis->Value] = p->nDistMax; + Emb_ObjForEachFanin( pThis, pNext, k ) + { + if ( Emb_ObjIsTravIdCurrent(p, pNext) ) + continue; + Emb_ObjSetTravIdCurrent(p, pNext); + Vec_IntPush( vNext, pNext->hHandle ); + } + Emb_ObjForEachFanout( pThis, pNext, k ) + { + if ( Emb_ObjIsTravIdCurrent(p, pNext) ) + continue; + Emb_ObjSetTravIdCurrent(p, pNext); + Vec_IntPush( vNext, pNext->hHandle ); + } + } + vTemp = vThis; vThis = vNext; vNext = vTemp; + } + assert( Vec_IntSize(vNext) > 0 ); + pResult = Emb_ManObj( p, Vec_IntEntry(vNext, 0) ); + assert( pDist == NULL || pDist[pResult->Value] == p->nDistMax - 1 ); + return pResult; +} + +/**Function************************************************************* + + Synopsis [Computes the distances from the given set of objects.] + + Description [Returns one of the most distant objects.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Emb_ManConnectedComponents( Emb_Man_t * p ) +{ + Gia_Obj_t * pObj; + Vec_Int_t * vThis, * vNext, * vResult; + Emb_Obj_t * pThis; + int i; + vResult = Vec_IntAlloc( 1000 ); + vThis = Vec_IntAlloc( 1000 ); + vNext = Vec_IntAlloc( 1000 ); + p->nReached = 0; + Emb_ManIncrementTravId( p ); + Gia_ManForEachCo( p->pGia, pObj, i ) + { + pThis = Emb_ManObj( p, Gia_ObjValue(pObj) ); + if ( Emb_ObjIsTravIdCurrent(p, pThis) ) + continue; + Emb_ObjSetTravIdCurrent( p, pThis ); + Vec_IntPush( vResult, pThis->hHandle ); + // perform BFS from this node + Vec_IntClear( vThis ); + Vec_IntPush( vThis, pThis->hHandle ); + Emb_ManPerformBfs( p, vThis, vNext, NULL ); + } + Vec_IntFree( vThis ); + Vec_IntFree( vNext ); + return vResult; +} + +/**Function************************************************************* + + Synopsis [Computes the distances from the given set of objects.] + + Description [Returns one of the most distant objects.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Emb_Obj_t * Emb_ManFindDistances( Emb_Man_t * p, Vec_Int_t * vStart, Emb_Dat_t * pDist ) +{ + Vec_Int_t * vThis, * vNext; + Emb_Obj_t * pThis, * pResult; + int i; + p->nReached = p->nDistMax = 0; + vThis = Vec_IntAlloc( 1000 ); + vNext = Vec_IntAlloc( 1000 ); + Emb_ManIncrementTravId( p ); + Emb_ManForEachObjVec( vStart, p, pThis, i ) + { + Emb_ObjSetTravIdCurrent( p, pThis ); + Vec_IntPush( vThis, pThis->hHandle ); + } + pResult = Emb_ManPerformBfs( p, vThis, vNext, pDist ); + Vec_IntFree( vThis ); + Vec_IntFree( vNext ); + return pResult; +} + +/**Function************************************************************* + + Synopsis [Traverses from the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Emb_Obj_t * Emb_ManRandomVertex( Emb_Man_t * p ) +{ + Emb_Obj_t * pPivot; + do { + int iNode = (911 * Gia_ManRandom(0)) % Gia_ManObjNum(p->pGia); + if ( ~Gia_ManObj(p->pGia, iNode)->Value ) + pPivot = Emb_ManObj( p, Gia_ManObj(p->pGia, iNode)->Value ); + else + pPivot = NULL; + } + while ( pPivot == NULL || !Emb_ObjIsNode(pPivot) ); + return pPivot; +} + +/**Function************************************************************* + + Synopsis [Computes the distances from the given set of objects.] + + Description [Returns one of the most distant objects.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Emb_DumpGraphIntoFile( Emb_Man_t * p ) +{ + FILE * pFile; + Emb_Obj_t * pThis, * pNext; + int i, k; + pFile = fopen( "1.g", "w" ); + Emb_ManForEachObj( p, pThis, i ) + { + if ( !Emb_ObjIsTravIdCurrent(p, pThis) ) + continue; + Emb_ObjForEachFanout( pThis, pNext, k ) + { + assert( Emb_ObjIsTravIdCurrent(p, pNext) ); + fprintf( pFile, "%d %d\n", pThis->Value, pNext->Value ); + } + } + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Computes dimentions of the graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Emb_ManComputeDimensions( Emb_Man_t * p, int nDims ) +{ + Emb_Obj_t * pRandom, * pPivot; + Vec_Int_t * vStart, * vComps; + int d, nReached; + int i;//, Counter; + // connect unconnected components + vComps = Emb_ManConnectedComponents( p ); +// printf( "Components = %d. Considered %d objects (out of %d).\n", Vec_IntSize(vComps), p->nReached, Emb_ManObjNum(p) ); + if ( Vec_IntSize(vComps) > 1 ) + { + Emb_Obj_t * pFanin, * pObj = Emb_ManObj( p, 0 ); + Emb_ManForEachObjVec( vComps, p, pFanin, i ) + { + assert( Emb_ObjIsCo(pFanin) ); + pFanin->Fanios[pFanin->nFanins + pFanin->nFanouts-1] = + pObj->Fanios[i] = pObj->hHandle - pFanin->hHandle; + } + } + Vec_IntFree( vComps ); + // allocate memory for vectors + assert( p->pVecs == NULL ); + p->pVecs = ABC_CALLOC( Emb_Dat_t, p->nObjs * nDims ); +// for ( i = 0; i < p->nObjs * nDims; i++ ) +// p->pVecs[i] = ABC_INFINITY; + vStart = Vec_IntAlloc( nDims ); + // get the pivot vertex + pRandom = Emb_ManRandomVertex( p ); + Vec_IntPush( vStart, pRandom->hHandle ); + // get the most distant vertex from the pivot + pPivot = Emb_ManFindDistances( p, vStart, NULL ); +// Emb_DumpGraphIntoFile( p ); + nReached = p->nReached; + if ( nReached < Emb_ManObjNum(p) ) + { +// printf( "Considering a connected component with %d objects (out of %d).\n", p->nReached, Emb_ManObjNum(p) ); + } + // start dimensions with this vertex + Vec_IntClear( vStart ); + for ( d = 0; d < nDims; d++ ) + { +// printf( "%3d : Adding vertex %7d with distance %3d.\n", d+1, pPivot->Value, p->nDistMax ); + Vec_IntPush( vStart, pPivot->hHandle ); + if ( d+1 == nReached ) + break; + pPivot = Emb_ManFindDistances( p, vStart, Emb_ManVec(p, d) ); + assert( nReached == p->nReached ); + } + Vec_IntFree( vStart ); + // make sure the number of reached objects is correct +// Counter = 0; +// for ( i = 0; i < p->nObjs; i++ ) +// if ( p->pVecs[i] < ABC_INFINITY ) +// Counter++; +// assert( Counter == nReached ); +} + +/**Function************************************************************* + + Synopsis [Allocated square matrix of floats.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float ** Emb_ManMatrAlloc( int nDims ) +{ + int i; + float ** pMatr = (float **)ABC_ALLOC( char, sizeof(float *) * nDims + sizeof(float) * nDims * nDims ); + pMatr[0] = (float *)(pMatr + nDims); + for ( i = 1; i < nDims; i++ ) + pMatr[i] = pMatr[i-1] + nDims; + return pMatr; +} + +/**Function************************************************************* + + Synopsis [Computes covariance matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Emb_ManComputeCovariance( Emb_Man_t * p, int nDims ) +{ + Emb_Dat_t * pOne, * pTwo; + double Ave; + float * pRow; + int d, i, k, v; + // average vectors + for ( d = 0; d < nDims; d++ ) + { + // compute average + Ave = 0.0; + pOne = Emb_ManVec( p, d ); + for ( v = 0; v < p->nObjs; v++ ) + if ( pOne[v] < ABC_INFINITY ) + Ave += pOne[v]; + Ave /= p->nReached; + // update the vector + for ( v = 0; v < p->nObjs; v++ ) + if ( pOne[v] < ABC_INFINITY ) + pOne[v] -= Ave; + else + pOne[v] = 0.0; + } + // compute the matrix + assert( p->pMatr == NULL ); + assert( p->pEigen == NULL ); + p->pMatr = Emb_ManMatrAlloc( nDims ); + p->pEigen = Emb_ManMatrAlloc( nDims ); + for ( i = 0; i < nDims; i++ ) + { + pOne = Emb_ManVec( p, i ); + pRow = p->pMatr[i]; + for ( k = 0; k < nDims; k++ ) + { + pTwo = Emb_ManVec( p, k ); + pRow[k] = 0.0; + for ( v = 0; v < p->nObjs; v++ ) + pRow[k] += pOne[v]*pTwo[v]; + } + } +} + +/**Function************************************************************* + + Synopsis [Returns random vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Emb_ManVecRandom( float * pVec, int nDims ) +{ + int i; + for ( i = 0; i < nDims; i++ ) + pVec[i] = Gia_ManRandom( 0 ); +} + +/**Function************************************************************* + + Synopsis [Returns normalized vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Emb_ManVecNormal( float * pVec, int nDims ) +{ + int i; + double Norm = 0.0; + for ( i = 0; i < nDims; i++ ) + Norm += pVec[i] * pVec[i]; + Norm = pow( Norm, 0.5 ); + for ( i = 0; i < nDims; i++ ) + pVec[i] /= Norm; +} + +/**Function************************************************************* + + Synopsis [Multiplies vector by vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Emb_ManVecMultiplyOne( float * pVec0, float * pVec1, int nDims ) +{ + float Res = 0.0; + int i; + for ( i = 0; i < nDims; i++ ) + Res += pVec0[i] * pVec1[i]; + return Res; +} + +/**Function************************************************************* + + Synopsis [Copies the vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Emb_ManVecCopyOne( float * pVecDest, float * pVecSour, int nDims ) +{ + int i; + for ( i = 0; i < nDims; i++ ) + pVecDest[i] = pVecSour[i]; +} + +/**Function************************************************************* + + Synopsis [Multiplies matrix by vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Emb_ManVecMultiply( float ** pMatr, float * pVec, int nDims, float * pRes ) +{ + int k; + for ( k = 0; k < nDims; k++ ) + pRes[k] = Emb_ManVecMultiplyOne( pMatr[k], pVec, nDims ); +} + +/**Function************************************************************* + + Synopsis [Multiplies vector by matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Emb_ManVecOrthogonolizeOne( float * pEigen, float * pVecI, int nDims, float * pVecRes ) +{ + int k; + for ( k = 0; k < nDims; k++ ) + pVecRes[k] = pVecI[k] - pEigen[k] * Emb_ManVecMultiplyOne( pVecI, pEigen, nDims ); +} + +/**Function************************************************************* + + Synopsis [Computes the first nSols eigen-vectors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Emb_ManComputeEigenvectors( Emb_Man_t * p, int nDims, int nSols ) +{ + float * pVecUiHat, * pVecUi; + int i, j, k; + assert( nSols < nDims ); + pVecUiHat = p->pEigen[nSols]; + for ( i = 0; i < nSols; i++ ) + { + pVecUi = p->pEigen[i]; + Emb_ManVecRandom( pVecUiHat, nDims ); + Emb_ManVecNormal( pVecUiHat, nDims ); + k = 0; + do { + k++; + Emb_ManVecCopyOne( pVecUi, pVecUiHat, nDims ); + for ( j = 0; j < i; j++ ) + { + Emb_ManVecOrthogonolizeOne( p->pEigen[j], pVecUi, nDims, pVecUiHat ); + Emb_ManVecCopyOne( pVecUi, pVecUiHat, nDims ); + } + Emb_ManVecMultiply( p->pMatr, pVecUi, nDims, pVecUiHat ); + Emb_ManVecNormal( pVecUiHat, nDims ); + } while ( Emb_ManVecMultiplyOne( pVecUiHat, pVecUi, nDims ) < 0.999 && k < 100 ); + Emb_ManVecCopyOne( pVecUi, pVecUiHat, nDims ); +// printf( "Converged after %d iterations.\n", k ); + } +} + +/**Function************************************************************* + + Synopsis [Derives solutions from original vectors and eigenvectors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Emb_ManComputeSolutions( Emb_Man_t * p, int nDims, int nSols ) +{ + Emb_Dat_t * pX; + float * pY; + int i, j, k; + assert( p->pSols == NULL ); + p->pSols = ABC_CALLOC( float, p->nObjs * nSols ); + for ( i = 0; i < nDims; i++ ) + { + pX = Emb_ManVec( p, i ); + for ( j = 0; j < nSols; j++ ) + { + pY = Emb_ManSol( p, j ); + for ( k = 0; k < p->nObjs; k++ ) + pY[k] += pX[k] * p->pEigen[j][i]; + } + } +} + +/**Function************************************************************* + + Synopsis [Projects into square of size [0;GIA_PLACE_SIZE] x [0;GIA_PLACE_SIZE].] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Emb_ManDerivePlacement( Emb_Man_t * p, int nSols ) +{ + float * pY0, * pY1, Max0, Max1, Min0, Min1, Str0, Str1; + int * pPerm0, * pPerm1; + int k; + if ( nSols != 2 ) + return; + // compute intervals + Min0 = ABC_INFINITY; + Max0 = -ABC_INFINITY; + pY0 = Emb_ManSol( p, 0 ); + for ( k = 0; k < p->nObjs; k++ ) + { + Min0 = Abc_MinInt( Min0, pY0[k] ); + Max0 = Abc_MaxInt( Max0, pY0[k] ); + } + Str0 = 1.0*GIA_PLACE_SIZE/(Max0 - Min0); + // update the coordinates + for ( k = 0; k < p->nObjs; k++ ) + pY0[k] = (pY0[k] != 0.0) ? ((pY0[k] - Min0) * Str0) : 0.0; + + // compute intervals + Min1 = ABC_INFINITY; + Max1 = -ABC_INFINITY; + pY1 = Emb_ManSol( p, 1 ); + for ( k = 0; k < p->nObjs; k++ ) + { + Min1 = Abc_MinInt( Min1, pY1[k] ); + Max1 = Abc_MaxInt( Max1, pY1[k] ); + } + Str1 = 1.0*GIA_PLACE_SIZE/(Max1 - Min1); + // update the coordinates + for ( k = 0; k < p->nObjs; k++ ) + pY1[k] = (pY1[k] != 0.0) ? ((pY1[k] - Min1) * Str1) : 0.0; + + // derive the order of these numbers + pPerm0 = Gia_SortFloats( pY0, NULL, p->nObjs ); + pPerm1 = Gia_SortFloats( pY1, NULL, p->nObjs ); + + // average solutions and project them into square [0;GIA_PLACE_SIZE] x [0;GIA_PLACE_SIZE] + p->pPlacement = ABC_ALLOC( unsigned short, 2 * p->nObjs ); + for ( k = 0; k < p->nObjs; k++ ) + { + p->pPlacement[2*pPerm0[k]+0] = (unsigned short)(int)(1.0 * k * GIA_PLACE_SIZE / p->nObjs); + p->pPlacement[2*pPerm1[k]+1] = (unsigned short)(int)(1.0 * k * GIA_PLACE_SIZE / p->nObjs); + } + ABC_FREE( pPerm0 ); + ABC_FREE( pPerm1 ); +} + + +/**Function************************************************************* + + Synopsis [Computes wire-length.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +double Emb_ManComputeHPWL( Emb_Man_t * p ) +{ + double Result = 0.0; + Emb_Obj_t * pThis, * pNext; + int i, k, iMinX, iMaxX, iMinY, iMaxY; + if ( p->pPlacement == NULL ) + return 0.0; + Emb_ManForEachObj( p, pThis, i ) + { + iMinX = iMaxX = p->pPlacement[2*pThis->Value+0]; + iMinY = iMaxY = p->pPlacement[2*pThis->Value+1]; + Emb_ObjForEachFanout( pThis, pNext, k ) + { + iMinX = Abc_MinInt( iMinX, p->pPlacement[2*pNext->Value+0] ); + iMaxX = Abc_MaxInt( iMaxX, p->pPlacement[2*pNext->Value+0] ); + iMinY = Abc_MinInt( iMinY, p->pPlacement[2*pNext->Value+1] ); + iMaxY = Abc_MaxInt( iMaxY, p->pPlacement[2*pNext->Value+1] ); + } + Result += (iMaxX - iMinX) + (iMaxY - iMinY); + } + return Result; +} + + +/**Function************************************************************* + + Synopsis [Performs iterative refinement of the given placement.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Emb_ManPlacementRefine( Emb_Man_t * p, int nIters, int fVerbose ) +{ + Emb_Obj_t * pThis, * pNext; + double CostThis, CostPrev; + float * pEdgeX, * pEdgeY; + float * pVertX, * pVertY; + float VertX, VertY; + int * pPermX, * pPermY; + int i, k, Iter, iMinX, iMaxX, iMinY, iMaxY; + abctime clk = Abc_Clock(); + if ( p->pPlacement == NULL ) + return; + pEdgeX = ABC_ALLOC( float, p->nObjs ); + pEdgeY = ABC_ALLOC( float, p->nObjs ); + pVertX = ABC_ALLOC( float, p->nObjs ); + pVertY = ABC_ALLOC( float, p->nObjs ); + // refine placement + CostPrev = 0.0; + for ( Iter = 0; Iter < nIters; Iter++ ) + { + // compute centers of hyperedges + CostThis = 0.0; + Emb_ManForEachObj( p, pThis, i ) + { + iMinX = iMaxX = p->pPlacement[2*pThis->Value+0]; + iMinY = iMaxY = p->pPlacement[2*pThis->Value+1]; + Emb_ObjForEachFanout( pThis, pNext, k ) + { + iMinX = Abc_MinInt( iMinX, p->pPlacement[2*pNext->Value+0] ); + iMaxX = Abc_MaxInt( iMaxX, p->pPlacement[2*pNext->Value+0] ); + iMinY = Abc_MinInt( iMinY, p->pPlacement[2*pNext->Value+1] ); + iMaxY = Abc_MaxInt( iMaxY, p->pPlacement[2*pNext->Value+1] ); + } + pEdgeX[pThis->Value] = 0.5 * (iMaxX + iMinX); + pEdgeY[pThis->Value] = 0.5 * (iMaxY + iMinY); + CostThis += (iMaxX - iMinX) + (iMaxY - iMinY); + } + // compute new centers of objects + Emb_ManForEachObj( p, pThis, i ) + { + VertX = pEdgeX[pThis->Value]; + VertY = pEdgeY[pThis->Value]; + Emb_ObjForEachFanin( pThis, pNext, k ) + { + VertX += pEdgeX[pNext->Value]; + VertY += pEdgeY[pNext->Value]; + } + pVertX[pThis->Value] = VertX / (Emb_ObjFaninNum(pThis) + 1); + pVertY[pThis->Value] = VertY / (Emb_ObjFaninNum(pThis) + 1); + } + // sort these numbers + pPermX = Gia_SortFloats( pVertX, NULL, p->nObjs ); + pPermY = Gia_SortFloats( pVertY, NULL, p->nObjs ); + for ( k = 0; k < p->nObjs; k++ ) + { + p->pPlacement[2*pPermX[k]+0] = (unsigned short)(int)(1.0 * k * GIA_PLACE_SIZE / p->nObjs); + p->pPlacement[2*pPermY[k]+1] = (unsigned short)(int)(1.0 * k * GIA_PLACE_SIZE / p->nObjs); + } + ABC_FREE( pPermX ); + ABC_FREE( pPermY ); + // evaluate cost + if ( fVerbose ) + { + printf( "%2d : HPWL = %e ", Iter+1, CostThis ); + ABC_PRT( "Time", Abc_Clock() - clk ); + } + } + ABC_FREE( pEdgeX ); + ABC_FREE( pEdgeY ); + ABC_FREE( pVertX ); + ABC_FREE( pVertY ); +} + + +/**Function************************************************************* + + Synopsis [Derives solutions from original vectors and eigenvectors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Emb_ManPrintSolutions( Emb_Man_t * p, int nSols ) +{ + float * pSol; + int i, k; + for ( i = 0; i < nSols; i++ ) + { + pSol = Emb_ManSol( p, i ); + for ( k = 0; k < p->nObjs; k++ ) + printf( "%4d ", (int)(100 * pSol[k]) ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Prepares image for dumping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Emb_ManDumpGnuplotPrepare( Emb_Man_t * p ) +{ +// int nRows = 496; +// int nCols = 710; + int nRows = 500; + int nCols = 700; + Vec_Int_t * vLines; + Emb_Obj_t * pThis; + char * pBuffer, ** ppRows; + int i, k, placeX, placeY; + int fStart; + // alloc memory + pBuffer = ABC_CALLOC( char, nRows * (nCols+1) ); + ppRows = ABC_ALLOC( char *, nRows ); + for ( i = 0; i < nRows; i++ ) + ppRows[i] = pBuffer + i*(nCols+1); + // put data into them + Emb_ManForEachObj( p, pThis, i ) + { + placeX = p->pPlacement[2*pThis->Value+0] * nCols / (1<<16); + placeY = p->pPlacement[2*pThis->Value+1] * nRows / (1<<16); + assert( placeX < nCols && placeY < nRows ); + ppRows[placeY][placeX] = 1; + } + // select lines + vLines = Vec_IntAlloc( 1000 ); + for ( i = 0; i < nRows; i++ ) + { + fStart = 0; + for ( k = 0; k <= nCols; k++ ) + { + if ( ppRows[i][k] && !fStart ) + { + Vec_IntPush( vLines, k ); + Vec_IntPush( vLines, i ); + fStart = 1; + } + if ( !ppRows[i][k] && fStart ) + { + Vec_IntPush( vLines, k-1 ); + Vec_IntPush( vLines, i ); + fStart = 0; + } + } + assert( fStart == 0 ); + } + ABC_FREE( pBuffer ); + ABC_FREE( ppRows ); + return vLines; +} + +/**Function************************************************************* + + Synopsis [Derives solutions from original vectors and eigenvectors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Emb_ManDumpGnuplot( Emb_Man_t * p, char * pName, int fDumpLarge, int fShowImage ) +{ + extern void Gia_ManGnuplotShow( char * pPlotFileName ); +// char * pDirectory = "place\\"; + char * pDirectory = ""; +// extern char * Ioa_TimeStamp(); + FILE * pFile; + char Buffer[1000]; + Emb_Obj_t * pThis, * pNext; + int i, k; + if ( p->pPlacement == NULL ) + { + printf( "Emb_ManDumpGnuplot(): Placement is not available.\n" ); + return; + } + sprintf( Buffer, "%s%s", pDirectory, Gia_FileNameGenericAppend(pName, ".plt") ); + pFile = fopen( Buffer, "w" ); + fprintf( pFile, "# This Gnuplot file was produced by ABC on %s\n", Ioa_TimeStamp() ); + fprintf( pFile, "\n" ); + fprintf( pFile, "set nokey\n" ); + fprintf( pFile, "\n" ); + if ( !fShowImage ) + { +// fprintf( pFile, "set terminal postscript\n" ); + fprintf( pFile, "set terminal gif font \'arial\' 10 size 800,600 xffffff x000000 x000000 x000000\n" ); + fprintf( pFile, "set output \'%s\'\n", Gia_FileNameGenericAppend(pName, ".gif") ); + fprintf( pFile, "\n" ); + } + fprintf( pFile, "set title \"%s : PI = %d PO = %d FF = %d Node = %d Obj = %d HPWL = %.2e\\n", + pName, Emb_ManPiNum(p), Emb_ManPoNum(p), Emb_ManRegNum(p), Emb_ManNodeNum(p), Emb_ManObjNum(p), Emb_ManComputeHPWL(p) ); + fprintf( pFile, "(image generated by ABC and Gnuplot on %s)\"", Ioa_TimeStamp() ); + fprintf( pFile, "font \"Times, 12\"\n" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "plot [:] '-' w l\n" ); + fprintf( pFile, "\n" ); + if ( fDumpLarge ) + { + int begX, begY, endX, endY; + Vec_Int_t * vLines = Emb_ManDumpGnuplotPrepare( p ); + Vec_IntForEachEntry( vLines, begX, i ) + { + begY = Vec_IntEntry( vLines, i+1 ); + endX = Vec_IntEntry( vLines, i+2 ); + endY = Vec_IntEntry( vLines, i+3 ); + i += 3; + fprintf( pFile, "%5d %5d\n", begX, begY ); + fprintf( pFile, "%5d %5d\n", endX, endY ); + fprintf( pFile, "\n" ); + } + Vec_IntFree( vLines ); + } + else + { + Emb_ManForEachObj( p, pThis, i ) + { + if ( !Emb_ObjIsTravIdCurrent(p, pThis) ) + continue; + Emb_ObjForEachFanout( pThis, pNext, k ) + { + assert( Emb_ObjIsTravIdCurrent(p, pNext) ); + fprintf( pFile, "%5d %5d\n", p->pPlacement[2*pThis->Value+0], p->pPlacement[2*pThis->Value+1] ); + fprintf( pFile, "%5d %5d\n", p->pPlacement[2*pNext->Value+0], p->pPlacement[2*pNext->Value+1] ); + fprintf( pFile, "\n" ); + } + } + } + fprintf( pFile, "EOF\n" ); + fprintf( pFile, "\n" ); + if ( fShowImage ) + { + fprintf( pFile, "pause -1 \"Close window\"\n" ); // Hit return to continue + fprintf( pFile, "reset\n" ); + fprintf( pFile, "\n" ); + } + else + { + fprintf( pFile, "# pause -1 \"Close window\"\n" ); // Hit return to continue + fprintf( pFile, "# reset\n" ); + fprintf( pFile, "\n" ); + } + fclose( pFile ); + if ( fShowImage ) + Gia_ManGnuplotShow( Buffer ); +} + +/**Function************************************************************* + + Synopsis [Computes dimentions of the graph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSolveProblem( Gia_Man_t * pGia, Emb_Par_t * pPars ) +{ + Emb_Man_t * p; + int i; + abctime clkSetup; + abctime clk; +// Gia_ManTestDistance( pGia ); + + // transform AIG into internal data-structure +clk = Abc_Clock(); + if ( pPars->fCluster ) + { + p = Emb_ManStart( pGia ); + if ( pPars->fVerbose ) + { + printf( "Clustered: " ); + Emb_ManPrintStats( p ); + } + } + else + p = Emb_ManStartSimple( pGia ); + p->fVerbose = pPars->fVerbose; +// Emb_ManPrintFanio( p ); + + // prepare data-structure + Gia_ManRandom( 1 ); // reset random numbers for deterministic behavior + Emb_ManResetTravId( p ); + Emb_ManSetValue( p ); +clkSetup = Abc_Clock() - clk; + +clk = Abc_Clock(); + Emb_ManComputeDimensions( p, pPars->nDims ); +if ( pPars->fVerbose ) +ABC_PRT( "Setup ", clkSetup ); +if ( pPars->fVerbose ) +ABC_PRT( "Dimensions", Abc_Clock() - clk ); + +clk = Abc_Clock(); + Emb_ManComputeCovariance( p, pPars->nDims ); +if ( pPars->fVerbose ) +ABC_PRT( "Matrix ", Abc_Clock() - clk ); + +clk = Abc_Clock(); + Emb_ManComputeEigenvectors( p, pPars->nDims, pPars->nSols ); + Emb_ManComputeSolutions( p, pPars->nDims, pPars->nSols ); + Emb_ManDerivePlacement( p, pPars->nSols ); +if ( pPars->fVerbose ) +ABC_PRT( "Eigenvecs ", Abc_Clock() - clk ); + + if ( pPars->fRefine ) + { +clk = Abc_Clock(); + Emb_ManPlacementRefine( p, pPars->nIters, pPars->fVerbose ); +if ( pPars->fVerbose ) +ABC_PRT( "Refinement", Abc_Clock() - clk ); + } + + if ( (pPars->fDump || pPars->fDumpLarge) && pPars->nSols == 2 ) + { +clk = Abc_Clock(); + Emb_ManDumpGnuplot( p, pGia->pName, pPars->fDumpLarge, pPars->fShowImage ); +if ( pPars->fVerbose ) +ABC_PRT( "Image dump", Abc_Clock() - clk ); + } + + // transfer placement + if ( Gia_ManObjNum(pGia) == p->nObjs ) + { + // assuming normalized ordering of the AIG + pGia->pPlacement = ABC_CALLOC( Gia_Plc_t, p->nObjs ); + for ( i = 0; i < p->nObjs; i++ ) + { + pGia->pPlacement[i].xCoord = p->pPlacement[2*i+0]; + pGia->pPlacement[i].yCoord = p->pPlacement[2*i+1]; + } + } + Emb_ManStop( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaEnable.c b/yosys/abc/src/aig/gia/giaEnable.c new file mode 100644 index 00000000000..3377a49cf4c --- /dev/null +++ b/yosys/abc/src/aig/gia/giaEnable.c @@ -0,0 +1,650 @@ +/**CFile**************************************************************** + + FileName [gia.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Structural detection of enables, sets and resets.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_CollectSuper_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper ) +{ + // if the new node is complemented or a PI, another gate begins + if ( Gia_IsComplement(pObj) || Gia_ObjIsCi(pObj) ) + { + Vec_IntPushUnique( vSuper, Gia_ObjId(p, Gia_Regular(pObj)) ); + return; + } + assert( Gia_ObjIsAnd(pObj) ); + // go through the branches + Gia_CollectSuper_rec( p, Gia_ObjChild0(pObj), vSuper ); + Gia_CollectSuper_rec( p, Gia_ObjChild1(pObj), vSuper ); +} + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_CollectSuper( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper ) +{ + assert( !Gia_IsComplement(pObj) ); + Vec_IntClear( vSuper ); +// Gia_CollectSuper_rec( p, pObj, vSuper ); + if ( Gia_ObjIsAnd(pObj) ) + { + Vec_IntPushUnique( vSuper, Gia_ObjId(p, Gia_ObjFanin0(pObj)) ); + Vec_IntPushUnique( vSuper, Gia_ObjId(p, Gia_ObjFanin1(pObj)) ); + } + else + Vec_IntPushUnique( vSuper, Gia_ObjId(p, Gia_Regular(pObj)) ); + +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintSignals( Gia_Man_t * p, int * pFreq, char * pStr ) +{ + Vec_Int_t * vObjs; + int i, Counter = 0, nTotal = 0; + vObjs = Vec_IntAlloc( 100 ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + if ( pFreq[i] > 1 ) + { + nTotal += pFreq[i]; + Counter++; + } + printf( "%s (total = %d driven = %d)\n", pStr, Counter, nTotal ); + Counter = 0; + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + if ( pFreq[i] > 10 ) + { + printf( "%3d : Obj = %6d Refs = %6d Freq = %6d\n", + ++Counter, i, Gia_ObjRefNum(p, Gia_ManObj(p,i)), pFreq[i] ); + Vec_IntPush( vObjs, i ); + } + Vec_IntFree( vObjs ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDetectSeqSignals( Gia_Man_t * p, int fSetReset, int fVerbose ) +{ + Vec_Int_t * vSuper; + Gia_Obj_t * pFlop, * pObjC, * pObj0, * pObj1, * pNode, * pTemp; + int i, k, Ent, * pSets, * pResets, * pEnables; + int nHaveSetReset = 0, nHaveEnable = 0; + assert( Gia_ManRegNum(p) > 0 ); + pSets = ABC_CALLOC( int, Gia_ManObjNum(p) ); + pResets = ABC_CALLOC( int, Gia_ManObjNum(p) ); + pEnables = ABC_CALLOC( int, Gia_ManObjNum(p) ); + vSuper = Vec_IntAlloc( 100 ); + Gia_ManForEachRi( p, pFlop, i ) + { + pNode = Gia_ObjFanin0(pFlop); + if ( !Gia_ObjIsAnd(pNode) ) + continue; + // detect sets/resets + Gia_CollectSuper( p, pNode, vSuper ); + if ( Gia_ObjFaninC0(pFlop) ) + Vec_IntForEachEntry( vSuper, Ent, k ) + pSets[Ent]++; + else + Vec_IntForEachEntry( vSuper, Ent, k ) + pResets[Ent]++; + // detect enables + if ( !Gia_ObjIsMuxType(pNode) ) + continue; + pObjC = Gia_ObjRecognizeMux( pNode, &pObj0, &pObj1 ); + pTemp = Gia_ObjRiToRo( p, pFlop ); + if ( Gia_Regular(pObj0) != pTemp && Gia_Regular(pObj1) != pTemp ) + continue; + if ( !Gia_ObjFaninC0(pFlop) ) + { + pObj0 = Gia_Not(pObj0); + pObj1 = Gia_Not(pObj1); + } + if ( Gia_IsComplement(pObjC) ) + { + pObjC = Gia_Not(pObjC); + pTemp = pObj0; + pObj0 = pObj1; + pObj1 = pTemp; + } + // detect controls +// Gia_CollectSuper( p, pObjC, vSuper ); +// Vec_IntForEachEntry( vSuper, Ent, k ) +// pEnables[Ent]++; + pEnables[Gia_ObjId(p, pObjC)]++; + nHaveEnable++; + } + Gia_ManForEachRi( p, pFlop, i ) + { + pNode = Gia_ObjFanin0(pFlop); + if ( !Gia_ObjIsAnd(pNode) ) + continue; + // detect sets/resets + Gia_CollectSuper( p, pNode, vSuper ); + Vec_IntForEachEntry( vSuper, Ent, k ) + if ( pSets[Ent] > 1 || pResets[Ent] > 1 ) + { + nHaveSetReset++; + break; + } + } + Vec_IntFree( vSuper ); + ABC_FREE( p->pRefs ); + Gia_ManCreateRefs( p ); + if ( fVerbose ) + { + printf( "Flops with set/reset = %6d. Flops with enable = %6d.\n", nHaveSetReset, nHaveEnable ); + if ( fSetReset ) + { + Gia_ManPrintSignals( p, pSets, "Set signals" ); + Gia_ManPrintSignals( p, pResets, "Reset signals" ); + } + Gia_ManPrintSignals( p, pEnables, "Enable signals" ); + } + ABC_FREE( p->pRefs ); + ABC_FREE( pSets ); + ABC_FREE( pResets ); + ABC_FREE( pEnables ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManDetectSeqSignalsWithFanout( Gia_Man_t * p, int nFanMax, int fVerbose ) +{ + Vec_Int_t * vResult; + Vec_Int_t * vSuper; + Gia_Obj_t * pFlop, * pObjC, * pObj0, * pObj1, * pNode, * pTemp; + int i, k, Ent, * pSets, * pResets, * pEnables; + int nHaveSetReset = 0, nHaveEnable = 0; + assert( Gia_ManRegNum(p) > 0 ); + pSets = ABC_CALLOC( int, Gia_ManObjNum(p) ); + pResets = ABC_CALLOC( int, Gia_ManObjNum(p) ); + pEnables = ABC_CALLOC( int, Gia_ManObjNum(p) ); + vSuper = Vec_IntAlloc( 100 ); + Gia_ManForEachRi( p, pFlop, i ) + { + pNode = Gia_ObjFanin0(pFlop); + if ( !Gia_ObjIsAnd(pNode) ) + continue; + // detect sets/resets + Gia_CollectSuper( p, pNode, vSuper ); + if ( Gia_ObjFaninC0(pFlop) ) + Vec_IntForEachEntry( vSuper, Ent, k ) + pSets[Ent]++; + else + Vec_IntForEachEntry( vSuper, Ent, k ) + pResets[Ent]++; + // detect enables + if ( !Gia_ObjIsMuxType(pNode) ) + continue; + pObjC = Gia_ObjRecognizeMux( pNode, &pObj0, &pObj1 ); + pTemp = Gia_ObjRiToRo( p, pFlop ); + if ( Gia_Regular(pObj0) != pTemp && Gia_Regular(pObj1) != pTemp ) + continue; + if ( !Gia_ObjFaninC0(pFlop) ) + { + pObj0 = Gia_Not(pObj0); + pObj1 = Gia_Not(pObj1); + } + if ( Gia_IsComplement(pObjC) ) + { + pObjC = Gia_Not(pObjC); + pTemp = pObj0; + pObj0 = pObj1; + pObj1 = pTemp; + } + // detect controls +// Gia_CollectSuper( p, pObjC, vSuper ); +// Vec_IntForEachEntry( vSuper, Ent, k ) +// pEnables[Ent]++; + pEnables[Gia_ObjId(p, pObjC)]++; + nHaveEnable++; + } + Gia_ManForEachRi( p, pFlop, i ) + { + pNode = Gia_ObjFanin0(pFlop); + if ( !Gia_ObjIsAnd(pNode) ) + continue; + // detect sets/resets + Gia_CollectSuper( p, pNode, vSuper ); + Vec_IntForEachEntry( vSuper, Ent, k ) + if ( pSets[Ent] > 1 || pResets[Ent] > 1 ) + { + nHaveSetReset++; + break; + } + } + Vec_IntFree( vSuper ); + vResult = Vec_IntAlloc( 100 ); + for ( i = 1; i < Gia_ManObjNum(p); i++ ) + if ( pSets[i] > nFanMax ) + { + if ( fVerbose ) + printf( "Adding set signal %d related to %d flops.\n", i, pSets[i] ); + Vec_IntPushUnique( vResult, i ); + } + for ( i = 1; i < Gia_ManObjNum(p); i++ ) + if ( pResets[i] > nFanMax ) + { + if ( fVerbose ) + printf( "Adding reset signal %d related to %d flops.\n", i, pResets[i] ); + Vec_IntPushUnique( vResult, i ); + } + for ( i = 1; i < Gia_ManObjNum(p); i++ ) + if ( pEnables[i] > nFanMax ) + { + if ( fVerbose ) + printf( "Adding enable signal %d related to %d flops.\n", i, pEnables[i] ); + Vec_IntPushUnique( vResult, i ); + } + ABC_FREE( pSets ); + ABC_FREE( pResets ); + ABC_FREE( pEnables ); + return vResult; +} + + +/**Function************************************************************* + + Synopsis [Transfers attributes from the original one to the final one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManTransferFrames( Gia_Man_t * pAig, Gia_Man_t * pFrames, int nFrames, Gia_Man_t * pNew, Vec_Int_t * vSigs ) +{ + Vec_Int_t * vSigsNew; + Gia_Obj_t * pObj, * pObjF; + int k, f; + vSigsNew = Vec_IntAlloc( 100 ); + Gia_ManForEachObjVec( vSigs, pAig, pObj, k ) + { + assert( Gia_ObjIsCand(pObj) ); + for ( f = 0; f < nFrames; f++ ) + { + pObjF = Gia_ManObj( pFrames, Abc_Lit2Var(Gia_ObjCopyF( pAig, f, pObj )) ); + if ( pObjF->Value && ~pObjF->Value ) + Vec_IntPushUnique( vSigsNew, Abc_Lit2Var(pObjF->Value) ); + } + } + return vSigsNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManUnrollInit( Gia_Man_t * p, int nFrames ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj, * pObjRi, * pObjRo; + int f, i; + Vec_IntFill( &p->vCopies, nFrames * Gia_ManObjNum(p), -1 ); + pNew = Gia_ManStart( nFrames * Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachRo( p, pObj, i ) + Gia_ObjSetCopyF( p, 0, pObj, 0 ); + for ( f = 0; f < nFrames; f++ ) + { + Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 ); + Gia_ManForEachPi( p, pObj, i ) + Gia_ObjSetCopyF( p, f, pObj, Gia_ManAppendCi(pNew) ); + Gia_ManForEachAnd( p, pObj, i ) + Gia_ObjSetCopyF( p, f, pObj, Gia_ManHashAnd(pNew, Gia_ObjFanin0CopyF(p, f, pObj), Gia_ObjFanin1CopyF(p, f, pObj)) ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ObjSetCopyF( p, f, pObj, Gia_ObjFanin0CopyF(p, f, pObj) ); + Gia_ManForEachPo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjCopyF(p, f, pObj) ); + if ( f == nFrames - 1 ) + break; + Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) + Gia_ObjSetCopyF( p, f+1, pObjRo, Gia_ObjCopyF(p, f, pObjRi) ); + } + Gia_ManHashStop( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Unrolls initialized timeframes while cofactoring some vars.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManUnrollAndCofactor( Gia_Man_t * p, int nFrames, int nFanMax, int fVerbose ) +{ + Vec_Int_t * vCofSigs, * vTemp; + Gia_Man_t * pAig, * pFrames, * pNew; + // compute initialized timeframes + pFrames = Gia_ManUnrollInit( p, nFrames ); + pAig = Gia_ManCleanup( pFrames ); + // compute and remap set/reset/enable signals + vCofSigs = Gia_ManDetectSeqSignalsWithFanout( p, nFanMax, fVerbose ); + vCofSigs = Gia_ManTransferFrames( p, pFrames, nFrames, pAig, vTemp = vCofSigs ); + Vec_IntFree( vTemp ); + Gia_ManStop( pFrames ); + Vec_IntErase( &p->vCopies ); + // cofactor all these variables + pNew = Gia_ManDupCofAllInt( pAig, vCofSigs, fVerbose ); + Vec_IntFree( vCofSigs ); + Gia_ManStop( pAig ); + return pNew; +} + + + +/**Function************************************************************* + + Synopsis [Transform seq circuits with enables by removing enables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManRemoveEnables2( Gia_Man_t * p ) +{ + Gia_Man_t * pNew, * pAux; + Gia_Obj_t * pTemp, * pObjC, * pObj0, * pObj1, * pFlopIn, * pFlopOut; + Gia_Obj_t * pThis, * pNode; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pThis, i ) + pThis->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pThis, i ) + pThis->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pThis), Gia_ObjFanin1Copy(pThis) ); + Gia_ManForEachPo( p, pThis, i ) + pThis->Value = Gia_ObjFanin0Copy(pThis); + Gia_ManForEachRi( p, pFlopIn, i ) + { + pNode = Gia_ObjFanin0(pFlopIn); + if ( !Gia_ObjIsMuxType(pNode) ) + { + printf( "Cannot recognize enable of flop %d.\n", i ); + continue; + } + pObjC = Gia_ObjRecognizeMux( pNode, &pObj1, &pObj0 ); + pFlopOut = Gia_ObjRiToRo( p, pFlopIn ); + if ( Gia_Regular(pObj0) != pFlopOut && Gia_Regular(pObj1) != pFlopOut ) + { + printf( "Cannot recognize self-loop of enable flop %d.\n", i ); + continue; + } + if ( !Gia_ObjFaninC0(pFlopIn) ) + { + pObj0 = Gia_Not(pObj0); + pObj1 = Gia_Not(pObj1); + } + if ( Gia_IsComplement(pObjC) ) + { + pObjC = Gia_Not(pObjC); + pTemp = pObj0; + pObj0 = pObj1; + pObj1 = pTemp; + } + if ( Gia_Regular(pObj0) == pFlopOut ) + { +// printf( "FlopIn compl = %d. FlopOut is d0. Complement = %d.\n", +// Gia_ObjFaninC0(pFlopIn), Gia_IsComplement(pObj0) ); + pFlopIn->Value = Abc_LitNotCond(Gia_Regular(pObj1)->Value, !Gia_IsComplement(pObj1)); + } + else if ( Gia_Regular(pObj1) == pFlopOut ) + { +// printf( "FlopIn compl = %d. FlopOut is d1. Complement = %d.\n", +// Gia_ObjFaninC0(pFlopIn), Gia_IsComplement(pObj1) ); + pFlopIn->Value = Abc_LitNotCond(Gia_Regular(pObj0)->Value, !Gia_IsComplement(pObj0)); + } + } + Gia_ManForEachCo( p, pThis, i ) + Gia_ManAppendCo( pNew, pThis->Value ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pAux = pNew ); + Gia_ManStop( pAux ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Transform seq circuits with enables by removing enables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManRemoveEnables( Gia_Man_t * p ) +{ + Vec_Ptr_t * vCtrls, * vDatas; + Vec_Int_t * vFlopClasses; + Gia_Man_t * pNew, * pAux; + Gia_Obj_t * pFlopIn, * pFlopOut, * pDriver, * pFan0, * pFan1, * pCtrl = NULL, * pData, * pObj; + int i, iClass, fCompl, Counter = 0; + vCtrls = Vec_PtrAlloc( 100 ); + Vec_PtrPush( vCtrls, NULL ); + vDatas = Vec_PtrAlloc( Gia_ManRegNum(p) ); + vFlopClasses = Vec_IntAlloc( Gia_ManRegNum(p) ); + Gia_ManForEachRi( p, pFlopIn, i ) + { + fCompl = Gia_ObjFaninC0(pFlopIn); + pDriver = Gia_ObjFanin0(pFlopIn); + if ( !Gia_ObjIsAnd(pDriver) ) + { + printf( "The flop driver %d is not a node.\n", i ); + Vec_PtrPush( vDatas, NULL ); + Vec_IntPush( vFlopClasses, 0 ); + Counter++; + continue; + } + if ( !Gia_ObjFaninC0(pDriver) || !Gia_ObjFaninC1(pDriver) ) + { + printf( "The flop driver %d is not an OR gate.\n", i ); + Vec_PtrPush( vDatas, NULL ); + Vec_IntPush( vFlopClasses, 0 ); + Counter++; + continue; + } + pFan0 = Gia_ObjFanin0(pDriver); + pFan1 = Gia_ObjFanin1(pDriver); + if ( !Gia_ObjIsAnd(pFan0) || !Gia_ObjIsAnd(pFan1) ) + { + printf( "The flop driver fanin %d is not a node.\n", i ); + Vec_PtrPush( vDatas, NULL ); + Vec_IntPush( vFlopClasses, 0 ); + Counter++; + continue; + } + pFlopOut = Gia_ObjRiToRo( p, pFlopIn ); + pFlopOut = Gia_NotCond( pFlopOut, !fCompl ); + if ( Gia_ObjChild0(pFan0) != pFlopOut && Gia_ObjChild1(pFan0) != pFlopOut && + Gia_ObjChild0(pFan1) != pFlopOut && Gia_ObjChild1(pFan1) != pFlopOut ) + { + printf( "The flop %d does not have a self-loop.\n", i ); + Vec_PtrPush( vDatas, NULL ); + Vec_IntPush( vFlopClasses, 0 ); + Counter++; + continue; + } + pData = NULL; + if ( Gia_ObjChild0(pFan0) == pFlopOut ) + { + pCtrl = Gia_Not( Gia_ObjChild1(pFan0) ); + if ( Gia_ObjFanin0(pFan1) == Gia_Regular(pCtrl) ) + pData = Gia_ObjChild1(pFan1); + else + pData = Gia_ObjChild0(pFan1); + } + else if ( Gia_ObjChild1(pFan0) == pFlopOut ) + { + pCtrl = Gia_Not( Gia_ObjChild0(pFan0) ); + if ( Gia_ObjFanin0(pFan1) == Gia_Regular(pCtrl) ) + pData = Gia_ObjChild1(pFan1); + else + pData = Gia_ObjChild0(pFan1); + } + else if ( Gia_ObjChild0(pFan1) == pFlopOut ) + { + pCtrl = Gia_Not( Gia_ObjChild1(pFan1) ); + if ( Gia_ObjFanin0(pFan0) == Gia_Regular(pCtrl) ) + pData = Gia_ObjChild1(pFan0); + else + pData = Gia_ObjChild0(pFan0); + } + else if ( Gia_ObjChild1(pFan1) == pFlopOut ) + { + pCtrl = Gia_Not( Gia_ObjChild0(pFan1) ); + if ( Gia_ObjFanin0(pFan0) == Gia_Regular(pCtrl) ) + pData = Gia_ObjChild1(pFan0); + else + pData = Gia_ObjChild0(pFan0); + } + else assert( 0 ); + if ( Vec_PtrFind( vCtrls, pCtrl ) == -1 ) + Vec_PtrPush( vCtrls, pCtrl ); + iClass = Vec_PtrFind( vCtrls, pCtrl ); + pData = Gia_NotCond( pData, !fCompl ); + Vec_PtrPush( vDatas, pData ); + Vec_IntPush( vFlopClasses, iClass ); + } + assert( Vec_PtrSize( vDatas ) == Gia_ManRegNum(p) ); + assert( Vec_IntSize( vFlopClasses ) == Gia_ManRegNum(p) ); + printf( "Detected %d classes.\n", Vec_PtrSize(vCtrls) - (Counter == 0) ); + Vec_PtrFree( vCtrls ); + + + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsPo(p, pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManForEachRi( p, pObj, i ) + { + pData = (Gia_Obj_t *)Vec_PtrEntry(vDatas, i); + if ( pData == NULL ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + else + pObj->Value = Gia_ManAppendCo( pNew, Abc_LitNotCond(Gia_Regular(pData)->Value, Gia_IsComplement(pData)) ); + } + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + Vec_PtrFree( vDatas ); + + + pNew = Gia_ManCleanup( pAux = pNew ); + Gia_ManStop( pAux ); + pNew->vFlopClasses = vFlopClasses; + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaEquiv.c b/yosys/abc/src/aig/gia/giaEquiv.c new file mode 100644 index 00000000000..36e604153b5 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaEquiv.c @@ -0,0 +1,2995 @@ +/**CFile**************************************************************** + + FileName [giaEquiv.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Manipulation of equivalence classes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaEquiv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "proof/cec/cec.h" +#include "sat/bmc/bmc.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Manipulating original IDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManOrigIdsInit( Gia_Man_t * p ) +{ + Vec_IntFreeP( &p->vIdsOrig ); + p->vIdsOrig = Vec_IntStartNatural( Gia_ManObjNum(p) ); +} +void Gia_ManOrigIdsStart( Gia_Man_t * p ) +{ + Vec_IntFreeP( &p->vIdsOrig ); + p->vIdsOrig = Vec_IntStartFull( Gia_ManObjNum(p) ); +} +void Gia_ManOrigIdsRemap( Gia_Man_t * p, Gia_Man_t * pNew ) +{ + Gia_Obj_t * pObj; int i; + if ( p->vIdsOrig == NULL ) + return; + Gia_ManOrigIdsStart( pNew ); + Vec_IntWriteEntry( pNew->vIdsOrig, 0, 0 ); + Gia_ManForEachObj1( p, pObj, i ) + if ( ~pObj->Value && Abc_Lit2Var(pObj->Value) && Vec_IntEntry(p->vIdsOrig, i) != -1 && Vec_IntEntry(pNew->vIdsOrig, Abc_Lit2Var(pObj->Value)) == -1 ) + Vec_IntWriteEntry( pNew->vIdsOrig, Abc_Lit2Var(pObj->Value), Vec_IntEntry(p->vIdsOrig, i) ); + Gia_ManForEachObj( pNew, pObj, i ) + assert( Vec_IntEntry(pNew->vIdsOrig, i) >= 0 ); +} +// input is a set of equivalent node pairs in any order +// output is the mapping of each node into the equiv node with the smallest ID +void Gia_ManOrigIdsRemapPairsInsert( Vec_Int_t * vMap, int One, int Two ) +{ + int Smo = One < Two ? One : Two; + int Big = One < Two ? Two : One; + assert( Smo != Big ); + if ( Vec_IntEntry(vMap, Big) == -1 ) + Vec_IntWriteEntry( vMap, Big, Smo ); + else + Gia_ManOrigIdsRemapPairsInsert( vMap, Smo, Vec_IntEntry(vMap, Big) ); +} +int Gia_ManOrigIdsRemapPairsExtract( Vec_Int_t * vMap, int One ) +{ + if ( Vec_IntEntry(vMap, One) == -1 ) + return One; + return Gia_ManOrigIdsRemapPairsExtract( vMap, Vec_IntEntry(vMap, One) ); +} +Vec_Int_t * Gia_ManOrigIdsRemapPairs( Vec_Int_t * vEquivPairs, int nObjs ) +{ + Vec_Int_t * vMapResult; + Vec_Int_t * vMap2Smaller; + int i, One, Two; + // map bigger into smaller one + vMap2Smaller = Vec_IntStartFull( nObjs ); + Vec_IntForEachEntryDouble( vEquivPairs, One, Two, i ) + Gia_ManOrigIdsRemapPairsInsert( vMap2Smaller, One, Two ); + // collect results in the topo order + vMapResult = Vec_IntStartFull( nObjs ); + Vec_IntForEachEntry( vMap2Smaller, One, i ) + if ( One >= 0 ) + Vec_IntWriteEntry( vMapResult, i, Gia_ManOrigIdsRemapPairsExtract(vMap2Smaller, One) ); + Vec_IntFree( vMap2Smaller ); + return vMapResult; +} +// remap the AIG using the equivalent pairs proved +// returns the reduced AIG and the equivalence classes of the original AIG +Gia_Man_t * Gia_ManOrigIdsReduce( Gia_Man_t * p, Vec_Int_t * vPairs ) +{ + Gia_Man_t * pNew = NULL; + Gia_Obj_t * pObj, * pRepr; int i; + Vec_Int_t * vMap = Gia_ManOrigIdsRemapPairs( vPairs, Gia_ManObjNum(p) ); + Gia_ManSetPhase( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + { + if ( Vec_IntEntry(vMap, i) == -1 ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else + { + pRepr = Gia_ManObj( p, Vec_IntEntry(vMap, i) ); + pObj->Value = Abc_LitNotCond( pRepr->Value, pRepr->fPhase ^ pObj->fPhase ); + } + } + Gia_ManHashStop( pNew ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Vec_IntFree( vMap ); + // compute equivalences + assert( !p->pReprs && !p->pNexts ); + p->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + Gia_ObjSetRepr( p, i, GIA_VOID ); + Gia_ManFillValue(pNew); + Gia_ManForEachAnd( p, pObj, i ) + { + int iRepr = Abc_Lit2Var(pObj->Value); + if ( iRepr == 0 ) + { + Gia_ObjSetRepr( p, i, 0 ); + continue; + } + pRepr = Gia_ManObj( pNew, iRepr ); + if ( !~pRepr->Value ) // first time + { + pRepr->Value = i; + continue; + } + // add equivalence + Gia_ObjSetRepr( p, i, pRepr->Value ); + } + p->pNexts = Gia_ManDeriveNexts( p ); + return pNew; +} +Gia_Man_t * Gia_ManOrigIdsReduceTest( Gia_Man_t * p, Vec_Int_t * vPairs ) +{ + Gia_Man_t * pTemp, * pNew = Gia_ManOrigIdsReduce( p, vPairs ); + Gia_ManPrintStats( p, NULL ); + Gia_ManPrintStats( pNew, NULL ); + //Gia_ManStop( pNew ); + // cleanup the resulting one + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Compute equivalence classes of nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManComputeGiaEquivs( Gia_Man_t * pGia, int nConfs, int fVerbose ) +{ + Gia_Man_t * pTemp; + Cec_ParFra_t ParsFra, * pPars = &ParsFra; + Cec_ManFraSetDefaultParams( pPars ); + pPars->nItersMax = 100; + pPars->fUseOrigIds = 1; + pPars->fSatSweeping = 1; + pPars->nBTLimit = nConfs; + pPars->fVerbose = fVerbose; + pTemp = Cec_ManSatSweeping( pGia, pPars, 0 ); + Gia_ManStop( pTemp ); + return Gia_ManOrigIdsReduce( pGia, pGia->vIdsEquiv ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if AIG is not in the required topo order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCheckTopoOrder_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + Gia_Obj_t * pRepr; + if ( pObj->Value == 0 ) + return 1; + pObj->Value = 0; + assert( Gia_ObjIsAnd(pObj) ); + if ( !Gia_ManCheckTopoOrder_rec( p, Gia_ObjFanin0(pObj) ) ) + return 0; + if ( !Gia_ManCheckTopoOrder_rec( p, Gia_ObjFanin1(pObj) ) ) + return 0; + pRepr = p->pReprs ? Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ) : NULL; + return pRepr == NULL || pRepr->Value == 0; +} + +/**Function************************************************************* + + Synopsis [Returns 0 if AIG is not in the required topo order.] + + Description [AIG should be in such an order that the representative + is always traversed before the node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCheckTopoOrder( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, RetValue = 1; + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = 0; + Gia_ManForEachCo( p, pObj, i ) + RetValue &= Gia_ManCheckTopoOrder_rec( p, Gia_ObjFanin0(pObj) ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Given representatives, derives pointers to the next objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Gia_ManDeriveNexts( Gia_Man_t * p ) +{ + unsigned * pNexts, * pTails; + int i; + assert( p->pReprs != NULL ); + assert( p->pNexts == NULL ); + pNexts = ABC_CALLOC( unsigned, Gia_ManObjNum(p) ); + pTails = ABC_ALLOC( unsigned, Gia_ManObjNum(p) ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + pTails[i] = i; + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + { + //if ( p->pReprs[i].iRepr == GIA_VOID ) + if ( !p->pReprs[i].iRepr || p->pReprs[i].iRepr == GIA_VOID ) + continue; + pNexts[ pTails[p->pReprs[i].iRepr] ] = i; + pTails[p->pReprs[i].iRepr] = i; + } + ABC_FREE( pTails ); + return (int *)pNexts; +} + +/**Function************************************************************* + + Synopsis [Given points to the next objects, derives representatives.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDeriveReprs( Gia_Man_t * p ) +{ + int i, iObj; + assert( p->pReprs == NULL ); + assert( p->pNexts != NULL ); + p->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + Gia_ObjSetRepr( p, i, GIA_VOID ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + { + if ( p->pNexts[i] == 0 ) + continue; + if ( p->pReprs[i].iRepr != GIA_VOID ) + continue; + // next is set, repr is not set + for ( iObj = p->pNexts[i]; iObj; iObj = p->pNexts[iObj] ) + p->pReprs[iObj].iRepr = i; + } +} + +/**Function************************************************************* + + Synopsis [Given pSibls, derives original representitives and nexts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +void Gia_ManDeriveReprsFromSibls( Gia_Man_t *p ) +{ + + int i, iObj; + assert( !p->pReprs && p->pSibls ); + p->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + Gia_ObjSetRepr( p, i, GIA_VOID ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + { + if ( p->pSibls[i] == 0 ) + continue; + if ( p->pReprs[i].iRepr != GIA_VOID ) + continue; + for ( iObj = p->pSibls[i]; iObj; iObj = p->pSibls[iObj] ) + p->pReprs[iObj].iRepr = i; + } + ABC_FREE( p->pNexts ); + p->pNexts = Gia_ManDeriveNexts( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManEquivCountLitsAll( Gia_Man_t * p ) +{ + int i, nLits = 0; + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + nLits += (Gia_ObjRepr(p, i) != GIA_VOID); + return nLits; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManEquivCountClasses( Gia_Man_t * p ) +{ + int i, Counter = 0; + if ( p->pReprs == NULL ) + return 0; + for ( i = 1; i < Gia_ManObjNum(p); i++ ) + Counter += Gia_ObjIsHead(p, i); + return Counter; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManEquivCheckLits( Gia_Man_t * p, int nLits ) +{ + int nLitsReal = Gia_ManEquivCountLitsAll( p ); + if ( nLitsReal != nLits ) + Abc_Print( 1, "Detected a mismatch in counting equivalence classes (%d).\n", nLitsReal - nLits ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintStatsClasses( Gia_Man_t * p ) +{ + int i, Counter = 0, Counter0 = 0, CounterX = 0, Proved = 0, nLits; + for ( i = 1; i < Gia_ManObjNum(p); i++ ) + { + if ( Gia_ObjIsHead(p, i) ) + Counter++; + else if ( Gia_ObjIsConst(p, i) ) + Counter0++; + else if ( Gia_ObjIsNone(p, i) ) + CounterX++; + if ( Gia_ObjProved(p, i) ) + Proved++; + } + CounterX -= Gia_ManCoNum(p); + nLits = Gia_ManCiNum(p) + Gia_ManAndNum(p) - Counter - CounterX; + +// Abc_Print( 1, "i/o/ff =%5d/%5d/%5d ", Gia_ManPiNum(p), Gia_ManPoNum(p), Gia_ManRegNum(p) ); +// Abc_Print( 1, "and =%5d ", Gia_ManAndNum(p) ); +// Abc_Print( 1, "lev =%3d ", Gia_ManLevelNum(p) ); + Abc_Print( 1, "cst =%3d cls =%6d lit =%8d\n", Counter0, Counter, nLits ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManEquivCountLits( Gia_Man_t * p ) +{ + int i, Counter = 0, Counter0 = 0, CounterX = 0; + if ( p->pReprs == NULL || p->pNexts == NULL ) + return 0; + for ( i = 1; i < Gia_ManObjNum(p); i++ ) + { + if ( Gia_ObjIsHead(p, i) ) + Counter++; + else if ( Gia_ObjIsConst(p, i) ) + Counter0++; + else if ( Gia_ObjIsNone(p, i) ) + CounterX++; + } + CounterX -= Gia_ManCoNum(p); + return Gia_ManCiNum(p) + Gia_ManAndNum(p) - Counter - CounterX; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManEquivCountOne( Gia_Man_t * p, int i ) +{ + int Ent, nLits = 1; + Gia_ClassForEachObj1( p, i, Ent ) + { + assert( Gia_ObjRepr(p, Ent) == i ); + nLits++; + } + return nLits; +} +void Gia_ManEquivPrintOne( Gia_Man_t * p, int i, int Counter ) +{ + int Ent; + Abc_Print( 1, "Class %4d : Num = %2d {", Counter, Gia_ManEquivCountOne(p, i) ); + Gia_ClassForEachObj( p, i, Ent ) + { + Abc_Print( 1," %d", Ent ); + if ( p->pReprs[Ent].fColorA || p->pReprs[Ent].fColorB ) + Abc_Print( 1," <%d%d>", p->pReprs[Ent].fColorA, p->pReprs[Ent].fColorB ); + } + Abc_Print( 1, " }\n" ); +} +void Gia_ManEquivPrintClasses( Gia_Man_t * p, int fVerbose, float Mem ) +{ + int i, Counter = 0, Counter0 = 0, CounterX = 0, Proved = 0, nLits; + for ( i = 1; i < Gia_ManObjNum(p); i++ ) + { + if ( Gia_ObjIsHead(p, i) ) + Counter++; + else if ( Gia_ObjIsConst(p, i) ) + Counter0++; + else if ( Gia_ObjIsNone(p, i) ) + CounterX++; + if ( Gia_ObjProved(p, i) ) + Proved++; + } + CounterX -= Gia_ManCoNum(p); + nLits = Gia_ManCiNum(p) + Gia_ManAndNum(p) - Counter - CounterX; +// Abc_Print( 1, "cst =%8d cls =%7d lit =%8d unused =%8d proof =%6d mem =%5.2f MB\n", +// Counter0, Counter, nLits, CounterX, Proved, (Mem == 0.0) ? 8.0*Gia_ManObjNum(p)/(1<<20) : Mem ); + Abc_Print( 1, "cst =%8d cls =%7d lit =%8d unused =%8d proof =%6d\n", + Counter0, Counter, nLits, CounterX, Proved ); + assert( Gia_ManEquivCheckLits( p, nLits ) ); + if ( fVerbose ) + { +// int Ent; + Abc_Print( 1, "Const0 (%d) = ", Counter0 ); + Gia_ManForEachConst( p, i ) + Abc_Print( 1, "%d ", i ); + Abc_Print( 1, "\n" ); + Counter = 0; + Gia_ManForEachClass( p, i ) + Gia_ManEquivPrintOne( p, i, ++Counter ); +/* + Gia_ManLevelNum( p ); + Gia_ManForEachClass( p, i ) + if ( i % 100 == 0 ) + { +// Abc_Print( 1, "%d ", Gia_ManEquivCountOne(p, i) ); + Gia_ClassForEachObj( p, i, Ent ) + { + Abc_Print( 1, "%d ", Gia_ObjLevel( p, Gia_ManObj(p, Ent) ) ); + } + Abc_Print( 1, "\n" ); + } +*/ + } +} + + +/**Function************************************************************* + + Synopsis [Map representatives into class members with minimum level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManChoiceMinLevel_rec( Gia_Man_t * p, int iPivot, int fDiveIn, Vec_Int_t * vMap ) +{ + int Level0, Level1, LevelMax; + Gia_Obj_t * pPivot = Gia_ManObj( p, iPivot ); + if ( Gia_ObjIsCi(pPivot) || iPivot == 0 ) + return 0; + if ( Gia_ObjLevel(p, pPivot) ) + return Gia_ObjLevel(p, pPivot); + if ( fDiveIn && Gia_ObjIsClass(p, iPivot) ) + { + int iObj, ObjMin = -1, iRepr = Gia_ObjRepr(p, iPivot), LevMin = ABC_INFINITY; + Gia_ClassForEachObj( p, iRepr, iObj ) + { + int LevCur = Gia_ManChoiceMinLevel_rec( p, iObj, 0, vMap ); + if ( LevMin > LevCur ) + { + LevMin = LevCur; + ObjMin = iObj; + } + } + assert( LevMin > 0 ); + Vec_IntWriteEntry( vMap, iRepr, ObjMin ); + Gia_ClassForEachObj( p, iRepr, iObj ) + Gia_ObjSetLevelId( p, iObj, LevMin ); + return LevMin; + } + assert( Gia_ObjIsAnd(pPivot) ); + Level0 = Gia_ManChoiceMinLevel_rec( p, Gia_ObjFaninId0(pPivot, iPivot), 1, vMap ); + Level1 = Gia_ManChoiceMinLevel_rec( p, Gia_ObjFaninId1(pPivot, iPivot), 1, vMap ); + LevelMax = 1 + Abc_MaxInt(Level0, Level1); + Gia_ObjSetLevel( p, pPivot, LevelMax ); + return LevelMax; +} +Vec_Int_t * Gia_ManChoiceMinLevel( Gia_Man_t * p ) +{ + Vec_Int_t * vMap = Vec_IntStartFull( Gia_ManObjNum(p) ); + Gia_Obj_t * pObj; + int i, LevelCur, LevelMax = 0; +// assert( Gia_ManRegNum(p) == 0 ); + Gia_ManCleanLevels( p, Gia_ManObjNum(p) ); + Gia_ManForEachCo( p, pObj, i ) + { + LevelCur = Gia_ManChoiceMinLevel_rec( p, Gia_ObjFaninId0p(p, pObj), 1, vMap ); + LevelMax = Abc_MaxInt(LevelMax, LevelCur); + } + //printf( "Max level %d\n", LevelMax ); + return vMap; +} + +/**Function************************************************************* + + Synopsis [Returns representative node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * Gia_ManEquivRepr( Gia_Man_t * p, Gia_Obj_t * pObj, int fUseAll, int fDualOut ) +{ + if ( fUseAll ) + { + if ( Gia_ObjRepr(p, Gia_ObjId(p,pObj)) == GIA_VOID ) + return NULL; + } + else + { + if ( !Gia_ObjProved(p, Gia_ObjId(p,pObj)) ) + return NULL; + } +// if ( fDualOut && !Gia_ObjDiffColors( p, Gia_ObjId(p, pObj), Gia_ObjRepr(p, Gia_ObjId(p,pObj)) ) ) + if ( fDualOut && !Gia_ObjDiffColors2( p, Gia_ObjId(p, pObj), Gia_ObjRepr(p, Gia_ObjId(p,pObj)) ) ) + return NULL; + return Gia_ManObj( p, Gia_ObjRepr(p, Gia_ObjId(p,pObj)) ); +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManEquivReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int fUseAll, int fDualOut ) +{ + Gia_Obj_t * pRepr; + if ( (pRepr = Gia_ManEquivRepr(p, pObj, fUseAll, fDualOut)) ) + { + Gia_ManEquivReduce_rec( pNew, p, pRepr, fUseAll, fDualOut ); + pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); + return; + } + if ( ~pObj->Value ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManEquivReduce_rec( pNew, p, Gia_ObjFanin0(pObj), fUseAll, fDualOut ); + Gia_ManEquivReduce_rec( pNew, p, Gia_ObjFanin1(pObj), fUseAll, fDualOut ); + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Reduces AIG using equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManEquivReduce( Gia_Man_t * p, int fUseAll, int fDualOut, int fSkipPhase, int fVerbose ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + if ( !p->pReprs && p->pSibls ) + { + int * pMap = ABC_FALLOC( int, Gia_ManObjNum(p) ); + p->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + Gia_ObjSetRepr( p, i, GIA_VOID ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + if ( p->pSibls[i] > 0 ) + { + if ( pMap[p->pSibls[i]] == -1 ) + pMap[p->pSibls[i]] = p->pSibls[i]; + pMap[i] = pMap[p->pSibls[i]]; + } + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + if ( p->pSibls[i] > 0 ) + Gia_ObjSetRepr( p, i, pMap[i] ); + //printf( "Created equivalence classes.\n" ); + ABC_FREE( p->pNexts ); + p->pNexts = Gia_ManDeriveNexts( p ); + ABC_FREE( pMap ); + } + if ( !p->pReprs ) + { + Abc_Print( 1, "Gia_ManEquivReduce(): Equivalence classes are not available.\n" ); + return NULL; + } + if ( fDualOut && (Gia_ManPoNum(p) & 1) ) + { + Abc_Print( 1, "Gia_ManEquivReduce(): Dual-output miter should have even number of POs.\n" ); + return NULL; + } + // check if there are any equivalences defined + Gia_ManForEachObj( p, pObj, i ) + if ( Gia_ObjReprObj(p, i) != NULL ) + break; + if ( i == Gia_ManObjNum(p) ) + { +// Abc_Print( 1, "Gia_ManEquivReduce(): There are no equivalences to reduce.\n" ); +// return NULL; + return Gia_ManDup( p ); + } +/* + if ( !Gia_ManCheckTopoOrder( p ) ) + { + Abc_Print( 1, "Gia_ManEquivReduce(): AIG is not in a correct topological order.\n" ); + return NULL; + } +*/ + if ( !fSkipPhase ) + Gia_ManSetPhase( p ); + if ( fDualOut ) + Gia_ManEquivSetColors( p, fVerbose ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManEquivReduce_rec( pNew, p, Gia_ObjFanin0(pObj), fUseAll, fDualOut ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Obj_t * Gia_MakeRandomChoice( Gia_Man_t * p, int iRepr ) +{ + int iTemp, Rand, Count = 0; + Gia_ClassForEachObj( p, iRepr, iTemp ) + Count++; + Rand = rand() % Count; + Count = 0; + Gia_ClassForEachObj( p, iRepr, iTemp ) + if ( Count++ == Rand ) + break; + return Gia_ManObj(p, iTemp); +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManEquivReduce2_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vMap, int fDiveIn ) +{ + Gia_Obj_t * pRepr; + if ( ~pObj->Value ) + return; + assert( Gia_ObjIsAnd(pObj) ); + if ( fDiveIn && (pRepr = Gia_ManEquivRepr(p, pObj, 1, 0)) ) + { + int iTemp, iRepr = Gia_ObjId(p, pRepr); + Gia_Obj_t * pRepr2 = vMap ? Gia_ManObj( p, Vec_IntEntry(vMap, iRepr) ) : Gia_MakeRandomChoice(p, iRepr); + Gia_ManEquivReduce2_rec( pNew, p, pRepr2, vMap, 0 ); + Gia_ClassForEachObj( p, iRepr, iTemp ) + { + Gia_Obj_t * pTemp = Gia_ManObj(p, iTemp); + pTemp->Value = Abc_LitNotCond( pRepr2->Value, Gia_ObjPhaseReal(pRepr2) ^ Gia_ObjPhaseReal(pTemp) ); + } + assert( ~pObj->Value ); + assert( ~pRepr->Value ); + assert( ~pRepr2->Value ); + return; + } + Gia_ManEquivReduce2_rec( pNew, p, Gia_ObjFanin0(pObj), vMap, 1 ); + Gia_ManEquivReduce2_rec( pNew, p, Gia_ObjFanin1(pObj), vMap, 1 ); + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManEquivReduce2( Gia_Man_t * p, int fRandom ) +{ + Vec_Int_t * vMap; + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + if ( fRandom ) srand(time(NULL)); + if ( !p->pReprs && p->pSibls ) + { + int * pMap = ABC_FALLOC( int, Gia_ManObjNum(p) ); + p->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + Gia_ObjSetRepr( p, i, GIA_VOID ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + if ( p->pSibls[i] > 0 ) + { + if ( pMap[p->pSibls[i]] == -1 ) + pMap[p->pSibls[i]] = p->pSibls[i]; + pMap[i] = pMap[p->pSibls[i]]; + } + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + if ( p->pSibls[i] > 0 ) + Gia_ObjSetRepr( p, i, pMap[i] ); + //printf( "Created equivalence classes.\n" ); + ABC_FREE( p->pNexts ); + p->pNexts = Gia_ManDeriveNexts( p ); + ABC_FREE( pMap ); + } + if ( !p->pReprs ) + { + Abc_Print( 1, "Gia_ManEquivReduce(): Equivalence classes are not available.\n" ); + return NULL; + } + // check if there are any equivalences defined + Gia_ManForEachObj( p, pObj, i ) + if ( Gia_ObjReprObj(p, i) != NULL ) + break; + if ( i == Gia_ManObjNum(p) ) + return Gia_ManDup( p ); + vMap = fRandom ? NULL : Gia_ManChoiceMinLevel( p ); + Gia_ManSetPhase( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManEquivReduce2_rec( pNew, p, Gia_ObjFanin0(pObj), vMap, 1 ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + Vec_IntFreeP( &vMap ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Reduces AIG using equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManEquivFixOutputPairs( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj0, * pObj1; + int i; + assert( (Gia_ManPoNum(p) & 1) == 0 ); + Gia_ManForEachPo( p, pObj0, i ) + { + pObj1 = Gia_ManPo( p, ++i ); + if ( Gia_ObjChild0(pObj0) != Gia_ObjChild0(pObj1) ) + continue; + pObj0->iDiff0 = Gia_ObjId(p, pObj0); + pObj0->fCompl0 = 0; + pObj1->iDiff0 = Gia_ObjId(p, pObj1); + pObj1->fCompl0 = 0; + } +} + +/**Function************************************************************* + + Synopsis [Removes pointers to the unmarked nodes..] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManEquivUpdatePointers( Gia_Man_t * p, Gia_Man_t * pNew ) +{ + Gia_Obj_t * pObj, * pObjNew; + int i; + Gia_ManForEachObj( p, pObj, i ) + { + if ( !~pObj->Value ) + continue; + pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) ); + if ( pObjNew->fMark0 ) + pObj->Value = ~0; + } +} + +/**Function************************************************************* + + Synopsis [Removes pointers to the unmarked nodes..] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManEquivDeriveReprs( Gia_Man_t * p, Gia_Man_t * pNew, Gia_Man_t * pFinal ) +{ + Vec_Int_t * vClass; + Gia_Obj_t * pObj, * pObjNew; + int i, k, iNode, iRepr, iPrev; + // start representatives + pFinal->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(pFinal) ); + for ( i = 0; i < Gia_ManObjNum(pFinal); i++ ) + Gia_ObjSetRepr( pFinal, i, GIA_VOID ); + // iterate over constant candidates + Gia_ManForEachConst( p, i ) + { + pObj = Gia_ManObj( p, i ); + if ( !~pObj->Value ) + continue; + pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) ); + if ( Abc_Lit2Var(pObjNew->Value) == 0 ) + continue; + Gia_ObjSetRepr( pFinal, Abc_Lit2Var(pObjNew->Value), 0 ); + } + // iterate over class candidates + vClass = Vec_IntAlloc( 100 ); + Gia_ManForEachClass( p, i ) + { + Vec_IntClear( vClass ); + Gia_ClassForEachObj( p, i, k ) + { + pObj = Gia_ManObj( p, k ); + if ( !~pObj->Value ) + continue; + pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) ); + Vec_IntPushUnique( vClass, Abc_Lit2Var(pObjNew->Value) ); + } + if ( Vec_IntSize( vClass ) < 2 ) + continue; + Vec_IntSort( vClass, 0 ); + iRepr = iPrev = Vec_IntEntry( vClass, 0 ); + Vec_IntForEachEntryStart( vClass, iNode, k, 1 ) + { + Gia_ObjSetRepr( pFinal, iNode, iRepr ); + assert( iPrev < iNode ); + iPrev = iNode; + } + } + Vec_IntFree( vClass ); + pFinal->pNexts = Gia_ManDeriveNexts( pFinal ); +} + +/**Function************************************************************* + + Synopsis [Removes pointers to the unmarked nodes..] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManEquivRemapDfs( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Vec_Int_t * vClass; + int i, k, iNode, iRepr, iPrev; + pNew = Gia_ManDupDfs( p ); + // start representatives + pNew->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(pNew) ); + for ( i = 0; i < Gia_ManObjNum(pNew); i++ ) + Gia_ObjSetRepr( pNew, i, GIA_VOID ); + // iterate over constant candidates + Gia_ManForEachConst( p, i ) + Gia_ObjSetRepr( pNew, Abc_Lit2Var(Gia_ManObj(p, i)->Value), 0 ); + // iterate over class candidates + vClass = Vec_IntAlloc( 100 ); + Gia_ManForEachClass( p, i ) + { + Vec_IntClear( vClass ); + Gia_ClassForEachObj( p, i, k ) + Vec_IntPushUnique( vClass, Abc_Lit2Var(Gia_ManObj(p, k)->Value) ); + assert( Vec_IntSize( vClass ) > 1 ); + Vec_IntSort( vClass, 0 ); + iRepr = iPrev = Vec_IntEntry( vClass, 0 ); + Vec_IntForEachEntryStart( vClass, iNode, k, 1 ) + { + Gia_ObjSetRepr( pNew, iNode, iRepr ); + assert( iPrev < iNode ); + iPrev = iNode; + } + } + Vec_IntFree( vClass ); + pNew->pNexts = Gia_ManDeriveNexts( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Reduces AIG while remapping equivalence classes.] + + Description [Drops the pairs of outputs if they are proved equivalent.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManEquivReduceAndRemap( Gia_Man_t * p, int fSeq, int fMiterPairs ) +{ + Gia_Man_t * pNew, * pFinal; + pNew = Gia_ManEquivReduce( p, 0, 0, 0, 0 ); + if ( pNew == NULL ) + return NULL; + Gia_ManOrigIdsRemap( p, pNew ); + if ( fMiterPairs ) + Gia_ManEquivFixOutputPairs( pNew ); + if ( fSeq ) + Gia_ManSeqMarkUsed( pNew ); + else + Gia_ManCombMarkUsed( pNew ); + Gia_ManEquivUpdatePointers( p, pNew ); + pFinal = Gia_ManDupMarked( pNew ); + Gia_ManOrigIdsRemap( pNew, pFinal ); + Gia_ManEquivDeriveReprs( p, pNew, pFinal ); + Gia_ManStop( pNew ); + pFinal = Gia_ManEquivRemapDfs( pNew = pFinal ); + Gia_ManOrigIdsRemap( pNew, pFinal ); + Gia_ManStop( pNew ); + return pFinal; +} + +/**Function************************************************************* + + Synopsis [Marks CIs/COs/ANDs unreachable from POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManEquivSetColor_rec( Gia_Man_t * p, Gia_Obj_t * pObj, int fOdds ) +{ + if ( Gia_ObjVisitColor( p, Gia_ObjId(p,pObj), fOdds ) ) + return 0; + if ( Gia_ObjIsRo(p, pObj) ) + return 1 + Gia_ManEquivSetColor_rec( p, Gia_ObjFanin0(Gia_ObjRoToRi(p, pObj)), fOdds ); + assert( Gia_ObjIsAnd(pObj) ); + return 1 + Gia_ManEquivSetColor_rec( p, Gia_ObjFanin0(pObj), fOdds ) + + Gia_ManEquivSetColor_rec( p, Gia_ObjFanin1(pObj), fOdds ); +} + +/**Function************************************************************* + + Synopsis [Marks CIs/COs/ANDs unreachable from POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManEquivSetColors( Gia_Man_t * p, int fVerbose ) +{ + Gia_Obj_t * pObj; + int i, nNodes[2], nDiffs[2]; + assert( (Gia_ManPoNum(p) & 1) == 0 ); + Gia_ObjSetColors( p, 0 ); + Gia_ManForEachPi( p, pObj, i ) + Gia_ObjSetColors( p, Gia_ObjId(p,pObj) ); + nNodes[0] = nNodes[1] = Gia_ManPiNum(p); + Gia_ManForEachPo( p, pObj, i ) + nNodes[i&1] += Gia_ManEquivSetColor_rec( p, Gia_ObjFanin0(pObj), i&1 ); +// Gia_ManForEachObj( p, pObj, i ) +// if ( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) ) +// assert( Gia_ObjColors(p, i) ); + nDiffs[0] = Gia_ManCandNum(p) - nNodes[0]; + nDiffs[1] = Gia_ManCandNum(p) - nNodes[1]; + if ( fVerbose ) + { + Abc_Print( 1, "CI+AND = %7d A = %7d B = %7d Ad = %7d Bd = %7d AB = %7d.\n", + Gia_ManCandNum(p), nNodes[0], nNodes[1], nDiffs[0], nDiffs[1], + Gia_ManCandNum(p) - nDiffs[0] - nDiffs[1] ); + } + return (nDiffs[0] + nDiffs[1]) / 2; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSpecBuild( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vXorLits, int fDualOut, int fSpeculate, Vec_Int_t * vTrace, Vec_Int_t * vGuide, Vec_Int_t * vMap ) +{ + Gia_Obj_t * pRepr; + unsigned iLitNew; + pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); + if ( pRepr == NULL ) + return; +// if ( fDualOut && !Gia_ObjDiffColors( p, Gia_ObjId(p, pObj), Gia_ObjId(p, pRepr) ) ) + if ( fDualOut && !Gia_ObjDiffColors2( p, Gia_ObjId(p, pObj), Gia_ObjId(p, pRepr) ) ) + return; + iLitNew = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); + if ( pObj->Value != iLitNew && !Gia_ObjProved(p, Gia_ObjId(p,pObj)) ) + { + if ( vTrace ) + Vec_IntPush( vTrace, 1 ); + if ( vGuide == NULL || Vec_IntEntry( vGuide, Vec_IntSize(vTrace)-1 ) ) + { + if ( vMap ) + Vec_IntPush( vMap, Gia_ObjId(p, pObj) ); + Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, pObj->Value, iLitNew) ); + } + } + else + { + if ( vTrace ) + Vec_IntPush( vTrace, 0 ); + } + if ( fSpeculate ) + pObj->Value = iLitNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSpecReduce_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vXorLits, int fDualOut, int fSpeculate, Vec_Int_t * vTrace, Vec_Int_t * vGuide, Vec_Int_t * vMap ) +{ + if ( ~pObj->Value ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), vXorLits, fDualOut, fSpeculate, vTrace, vGuide, vMap ); + Gia_ManSpecReduce_rec( pNew, p, Gia_ObjFanin1(pObj), vXorLits, fDualOut, fSpeculate, vTrace, vGuide, vMap ); + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManSpecBuild( pNew, p, pObj, vXorLits, fDualOut, fSpeculate, vTrace, vGuide, vMap ); +} + +/**Function************************************************************* + + Synopsis [Reduces AIG using equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManSpecReduceTrace( Gia_Man_t * p, Vec_Int_t * vTrace, Vec_Int_t * vMap ) +{ + Vec_Int_t * vXorLits; + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, iLitNew; + if ( !p->pReprs ) + { + Abc_Print( 1, "Gia_ManSpecReduce(): Equivalence classes are not available.\n" ); + return NULL; + } + Vec_IntClear( vTrace ); + vXorLits = Vec_IntAlloc( 1000 ); + Gia_ManSetPhase( p ); + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachRo( p, pObj, i ) + Gia_ManSpecBuild( pNew, p, pObj, vXorLits, 0, 1, vTrace, NULL, vMap ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), vXorLits, 0, 1, vTrace, NULL, vMap ); + Gia_ManForEachPo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Vec_IntForEachEntry( vXorLits, iLitNew, i ) + Gia_ManAppendCo( pNew, iLitNew ); + if ( Vec_IntSize(vXorLits) == 0 ) + { + Abc_Print( 1, "Speculatively reduced model has no primary outputs.\n" ); + Gia_ManAppendCo( pNew, 0 ); + } + Gia_ManForEachRi( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManHashStop( pNew ); + Vec_IntFree( vXorLits ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Reduces AIG using equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManSpecReduce( Gia_Man_t * p, int fDualOut, int fSynthesis, int fSpeculate, int fSkipSome, int fVerbose ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + Vec_Int_t * vXorLits; + int i, iLitNew; + Vec_Int_t * vTrace = NULL, * vGuide = NULL; + if ( !p->pReprs ) + { + Abc_Print( 1, "Gia_ManSpecReduce(): Equivalence classes are not available.\n" ); + return NULL; + } + if ( fDualOut && (Gia_ManPoNum(p) & 1) ) + { + Abc_Print( 1, "Gia_ManSpecReduce(): Dual-output miter should have even number of POs.\n" ); + return NULL; + } + if ( fSkipSome ) + { + vGuide = Vec_IntAlloc( 100 ); + pTemp = Gia_ManSpecReduceTrace( p, vGuide, NULL ); + Gia_ManStop( pTemp ); + assert( Vec_IntSize(vGuide) == Gia_ManEquivCountLitsAll(p) ); + vTrace = Vec_IntAlloc( 100 ); + } + vXorLits = Vec_IntAlloc( 1000 ); + Gia_ManSetPhase( p ); + Gia_ManFillValue( p ); + if ( fDualOut ) + Gia_ManEquivSetColors( p, fVerbose ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachRo( p, pObj, i ) + Gia_ManSpecBuild( pNew, p, pObj, vXorLits, fDualOut, fSpeculate, vTrace, vGuide, NULL ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManSpecReduce_rec( pNew, p, Gia_ObjFanin0(pObj), vXorLits, fDualOut, fSpeculate, vTrace, vGuide, NULL ); + if ( !fSynthesis ) + { + Gia_ManForEachPo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Vec_IntForEachEntry( vXorLits, iLitNew, i ) + Gia_ManAppendCo( pNew, iLitNew ); + if ( Vec_IntSize(vXorLits) == 0 ) + { + Abc_Print( 1, "Speculatively reduced model has no primary outputs.\n" ); + Gia_ManAppendCo( pNew, 0 ); + } + Gia_ManForEachRi( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManHashStop( pNew ); + Vec_IntFree( vXorLits ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + + // update using trace + if ( fSkipSome ) + { + // count the number of non-zero entries + int iLit, nAddPos = 0; + Vec_IntForEachEntry( vGuide, iLit, i ) + if ( iLit ) + nAddPos++; + if ( nAddPos ) + assert( Gia_ManPoNum(pNew) == Gia_ManPoNum(p) + nAddPos ); + } + Vec_IntFreeP( &vTrace ); + Vec_IntFreeP( &vGuide ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSpecBuildInit( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vXorLits, int f, int fDualOut ) +{ + Gia_Obj_t * pRepr; + int iLitNew; + pRepr = Gia_ObjReprObj( p, Gia_ObjId(p,pObj) ); + if ( pRepr == NULL ) + return; +// if ( fDualOut && !Gia_ObjDiffColors( p, Gia_ObjId(p, pObj), Gia_ObjId(p, pRepr) ) ) + if ( fDualOut && !Gia_ObjDiffColors2( p, Gia_ObjId(p, pObj), Gia_ObjId(p, pRepr) ) ) + return; + iLitNew = Abc_LitNotCond( Gia_ObjCopyF(p, f, pRepr), Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); + if ( Gia_ObjCopyF(p, f, pObj) != iLitNew && !Gia_ObjProved(p, Gia_ObjId(p,pObj)) ) + Vec_IntPush( vXorLits, Gia_ManHashXor(pNew, Gia_ObjCopyF(p, f, pObj), iLitNew) ); + Gia_ObjSetCopyF( p, f, pObj, iLitNew ); +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSpecReduceInit_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vXorLits, int f, int fDualOut ) +{ + if ( ~Gia_ObjCopyF(p, f, pObj) ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManSpecReduceInit_rec( pNew, p, Gia_ObjFanin0(pObj), vXorLits, f, fDualOut ); + Gia_ManSpecReduceInit_rec( pNew, p, Gia_ObjFanin1(pObj), vXorLits, f, fDualOut ); + Gia_ObjSetCopyF( p, f, pObj, Gia_ManHashAnd(pNew, Gia_ObjFanin0CopyF(p, f, pObj), Gia_ObjFanin1CopyF(p, f, pObj)) ); + Gia_ManSpecBuildInit( pNew, p, pObj, vXorLits, f, fDualOut ); +} + +/**Function************************************************************* + + Synopsis [Creates initialized SRM with the given number of frames.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManSpecReduceInit( Gia_Man_t * p, Abc_Cex_t * pInit, int nFrames, int fDualOut ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pObjRi, * pObjRo; + Vec_Int_t * vXorLits; + int f, i, iLitNew; + if ( !p->pReprs ) + { + Abc_Print( 1, "Gia_ManSpecReduceInit(): Equivalence classes are not available.\n" ); + return NULL; + } + if ( Gia_ManRegNum(p) == 0 ) + { + Abc_Print( 1, "Gia_ManSpecReduceInit(): Circuit is not sequential.\n" ); + return NULL; + } + if ( Gia_ManRegNum(p) != pInit->nRegs ) + { + Abc_Print( 1, "Gia_ManSpecReduceInit(): Mismatch in the number of registers.\n" ); + return NULL; + } + if ( fDualOut && (Gia_ManPoNum(p) & 1) ) + { + Abc_Print( 1, "Gia_ManSpecReduceInit(): Dual-output miter should have even number of POs.\n" ); + return NULL; + } + +/* + if ( !Gia_ManCheckTopoOrder( p ) ) + { + Abc_Print( 1, "Gia_ManSpecReduceInit(): AIG is not in a correct topological order.\n" ); + return NULL; + } +*/ + assert( pInit->nRegs == Gia_ManRegNum(p) && pInit->nPis == 0 ); + Vec_IntFill( &p->vCopies, nFrames * Gia_ManObjNum(p), -1 ); + vXorLits = Vec_IntAlloc( 1000 ); + Gia_ManSetPhase( p ); + if ( fDualOut ) + Gia_ManEquivSetColors( p, 0 ); + pNew = Gia_ManStart( nFrames * Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachRo( p, pObj, i ) + Gia_ObjSetCopyF( p, 0, pObj, Abc_InfoHasBit(pInit->pData, i) ); + for ( f = 0; f < nFrames; f++ ) + { + Gia_ObjSetCopyF( p, f, Gia_ManConst0(p), 0 ); + Gia_ManForEachPi( p, pObj, i ) + Gia_ObjSetCopyF( p, f, pObj, Gia_ManAppendCi(pNew) ); + Gia_ManForEachRo( p, pObj, i ) + Gia_ManSpecBuildInit( pNew, p, pObj, vXorLits, f, fDualOut ); + Gia_ManForEachCo( p, pObj, i ) + { + Gia_ManSpecReduceInit_rec( pNew, p, Gia_ObjFanin0(pObj), vXorLits, f, fDualOut ); + Gia_ObjSetCopyF( p, f, pObj, Gia_ObjFanin0CopyF(p, f, pObj) ); + } + if ( f == nFrames - 1 ) + break; + Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) + Gia_ObjSetCopyF( p, f+1, pObjRo, Gia_ObjCopyF(p, f, pObjRi) ); + } + Vec_IntForEachEntry( vXorLits, iLitNew, i ) + Gia_ManAppendCo( pNew, iLitNew ); + if ( Vec_IntSize(vXorLits) == 0 ) + { +// Abc_Print( 1, "Speculatively reduced model has no primary outputs.\n" ); + Gia_ManAppendCo( pNew, 0 ); + } + Vec_IntErase( &p->vCopies ); + Vec_IntFree( vXorLits ); + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Creates initialized SRM with the given number of frames.] + + Description [Uses as many frames as needed to create the number of + output not less than the number of equivalence literals.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManSpecReduceInitFrames( Gia_Man_t * p, Abc_Cex_t * pInit, int nFramesMax, int * pnFrames, int fDualOut, int nMinOutputs ) +{ + Gia_Man_t * pFrames; + int f, nLits; + nLits = Gia_ManEquivCountLits( p ); + for ( f = 1; ; f++ ) + { + pFrames = Gia_ManSpecReduceInit( p, pInit, f, fDualOut ); + if ( (nMinOutputs == 0 && Gia_ManPoNum(pFrames) >= nLits/2+1) || + (nMinOutputs != 0 && Gia_ManPoNum(pFrames) >= nMinOutputs) ) + break; + if ( f == nFramesMax ) + break; + if ( Gia_ManAndNum(pFrames) > 500000 ) + { + Gia_ManStop( pFrames ); + return NULL; + } + Gia_ManStop( pFrames ); + pFrames = NULL; + } + if ( f == nFramesMax ) + Abc_Print( 1, "Stopped unrolling after %d frames.\n", nFramesMax ); + if ( pnFrames ) + *pnFrames = f; + return pFrames; +} + +/**Function************************************************************* + + Synopsis [Transforms equiv classes by removing the AB nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManEquivTransform( Gia_Man_t * p, int fVerbose ) +{ + extern void Cec_ManSimClassCreate( Gia_Man_t * p, Vec_Int_t * vClass ); + Vec_Int_t * vClass, * vClassNew; + int iRepr, iNode, Ent, k; + int nRemovedLits = 0, nRemovedClas = 0; + int nTotalLits = 0, nTotalClas = 0; + Gia_Obj_t * pObj; + int i; + assert( p->pReprs && p->pNexts ); + vClass = Vec_IntAlloc( 100 ); + vClassNew = Vec_IntAlloc( 100 ); + Gia_ManForEachObj( p, pObj, i ) + if ( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) ) + assert( Gia_ObjColors(p, i) ); + Gia_ManForEachClassReverse( p, iRepr ) + { + nTotalClas++; + Vec_IntClear( vClass ); + Vec_IntClear( vClassNew ); + Gia_ClassForEachObj( p, iRepr, iNode ) + { + nTotalLits++; + Vec_IntPush( vClass, iNode ); + assert( Gia_ObjColors(p, iNode) ); + if ( Gia_ObjColors(p, iNode) != 3 ) + Vec_IntPush( vClassNew, iNode ); + else + nRemovedLits++; + } + Vec_IntForEachEntry( vClass, Ent, k ) + { + p->pReprs[Ent].fFailed = p->pReprs[Ent].fProved = 0; + p->pReprs[Ent].iRepr = GIA_VOID; + p->pNexts[Ent] = 0; + } + if ( Vec_IntSize(vClassNew) < 2 ) + { + nRemovedClas++; + continue; + } + Cec_ManSimClassCreate( p, vClassNew ); + } + Vec_IntFree( vClass ); + Vec_IntFree( vClassNew ); + if ( fVerbose ) + Abc_Print( 1, "Removed classes = %6d (out of %6d). Removed literals = %6d (out of %6d).\n", + nRemovedClas, nTotalClas, nRemovedLits, nTotalLits ); +} + +/**Function************************************************************* + + Synopsis [Marks proved equivalences.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManEquivMark( Gia_Man_t * p, char * pFileName, int fSkipSome, int fVerbose ) +{ + Gia_Man_t * pMiter, * pTemp; + Gia_Obj_t * pObj; + int i, iLit, nAddPos, nLits = 0; + int nLitsAll, Counter = 0; + nLitsAll = Gia_ManEquivCountLitsAll( p ); + if ( nLitsAll == 0 ) + { + Abc_Print( 1, "Gia_ManEquivMark(): Current AIG does not have equivalences.\n" ); + return; + } + // read AIGER file + pMiter = Gia_AigerRead( pFileName, 0, 0, 0 ); + if ( pMiter == NULL ) + { + Abc_Print( 1, "Gia_ManEquivMark(): Input file %s could not be read.\n", pFileName ); + return; + } + if ( fSkipSome ) + { + Vec_Int_t * vTrace = Vec_IntAlloc( 100 ); + pTemp = Gia_ManSpecReduceTrace( p, vTrace, NULL ); + Gia_ManStop( pTemp ); + assert( Vec_IntSize(vTrace) == nLitsAll ); + // count the number of non-zero entries + nAddPos = 0; + Vec_IntForEachEntry( vTrace, iLit, i ) + if ( iLit ) + nAddPos++; + // check the number + if ( Gia_ManPoNum(pMiter) != Gia_ManPoNum(p) + nAddPos ) + { + Abc_Print( 1, "Gia_ManEquivMark(): The number of POs is not correct: MiterPONum(%d) != AIGPONum(%d) + AIGFilteredEquivNum(%d).\n", + Gia_ManPoNum(pMiter), Gia_ManPoNum(p), nAddPos ); + Gia_ManStop( pMiter ); + Vec_IntFreeP( &vTrace ); + return; + } + // mark corresponding POs as solved + nLits = iLit = Counter = 0; + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + { + if ( Gia_ObjRepr(p, i) == GIA_VOID ) + continue; + if ( Vec_IntEntry( vTrace, nLits++ ) == 0 ) + continue; + pObj = Gia_ManPo( pMiter, Gia_ManPoNum(p) + iLit++ ); + if ( Gia_ObjFaninLit0p(pMiter, pObj) == 0 ) // const 0 - proven + { + Gia_ObjSetProved(p, i); + Counter++; + } + } + assert( nLits == nLitsAll ); + assert( iLit == nAddPos ); + Vec_IntFreeP( &vTrace ); + } + else + { + if ( Gia_ManPoNum(pMiter) != Gia_ManPoNum(p) + nLitsAll ) + { + Abc_Print( 1, "Gia_ManEquivMark(): The number of POs is not correct: MiterPONum(%d) != AIGPONum(%d) + AIGEquivNum(%d).\n", + Gia_ManPoNum(pMiter), Gia_ManPoNum(p), nLitsAll ); + Gia_ManStop( pMiter ); + return; + } + // mark corresponding POs as solved + nLits = 0; + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + { + if ( Gia_ObjRepr(p, i) == GIA_VOID ) + continue; + pObj = Gia_ManPo( pMiter, Gia_ManPoNum(p) + nLits++ ); + if ( Gia_ObjFaninLit0p(pMiter, pObj) == 0 ) // const 0 - proven + { + Gia_ObjSetProved(p, i); + Counter++; + } + } + assert( nLits == nLitsAll ); + } + if ( fVerbose ) + Abc_Print( 1, "Set %d equivalences as proved.\n", Counter ); + Gia_ManStop( pMiter ); +} + +/**Function************************************************************* + + Synopsis [Transforms equiv classes by filtering those that correspond to disproved outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManEquivFilter( Gia_Man_t * p, Vec_Int_t * vPoIds, int fVerbose ) +{ + Gia_Man_t * pSrm; + Vec_Int_t * vTrace, * vMap; + int i, iObjId, Entry, Prev = -1; + // check if there are equivalences + if ( p->pReprs == NULL || p->pNexts == NULL ) + { + Abc_Print( 1, "Gia_ManEquivFilter(): Equivalence classes are not defined.\n" ); + return; + } + // check if PO indexes are available + if ( vPoIds == NULL ) + { + Abc_Print( 1, "Gia_ManEquivFilter(): Array of disproved POs is not available.\n" ); + return; + } + if ( Vec_IntSize(vPoIds) == 0 ) + return; + // create SRM with mapping into POs + vMap = Vec_IntAlloc( 1000 ); + vTrace = Vec_IntAlloc( 1000 ); + pSrm = Gia_ManSpecReduceTrace( p, vTrace, vMap ); + Vec_IntFree( vTrace ); + // the resulting array (vMap) maps PO indexes of the SRM into object IDs + assert( Gia_ManPoNum(pSrm) == Gia_ManPoNum(p) + Vec_IntSize(vMap) ); + Gia_ManStop( pSrm ); + if ( fVerbose ) + printf( "Design POs = %d. SRM POs = %d. Spec POs = %d. Disproved POs = %d.\n", + Gia_ManPoNum(p), Gia_ManPoNum(p) + Vec_IntSize(vMap), Vec_IntSize(vMap), Vec_IntSize(vPoIds) ); + // check if disproved POs satisfy the range + Vec_IntSort( vPoIds, 0 ); + Vec_IntForEachEntry( vPoIds, Entry, i ) + { + if ( Entry < 0 || Entry >= Gia_ManPoNum(p) + Vec_IntSize(vMap) ) + { + Abc_Print( 1, "Gia_ManEquivFilter(): Array of disproved POs contains PO index (%d),\n", Entry ); + Abc_Print( 1, "which does not fit into the range of available PO indexes of the SRM: [%d; %d].\n", 0, Gia_ManPoNum(p) + Vec_IntSize(vMap)-1 ); + Vec_IntFree( vMap ); + return; + } + if ( Entry < Gia_ManPoNum(p) ) + Abc_Print( 0, "Gia_ManEquivFilter(): One of the original POs (%d) have failed.\n", Entry ); + if ( Prev == Entry ) + { + Abc_Print( 1, "Gia_ManEquivFilter(): Array of disproved POs contains at least one duplicate entry (%d),\n", Entry ); + Vec_IntFree( vMap ); + return; + } + Prev = Entry; + } + // perform the reduction of the equivalence classes + Vec_IntForEachEntry( vPoIds, Entry, i ) + { + if ( Entry < Gia_ManPoNum(p) ) + continue; + iObjId = Vec_IntEntry( vMap, Entry - Gia_ManPoNum(p) ); + Gia_ObjUnsetRepr( p, iObjId ); +// Gia_ObjSetNext( p, iObjId, 0 ); + } + Vec_IntFree( vMap ); + ABC_FREE( p->pNexts ); + p->pNexts = Gia_ManDeriveNexts( p ); +} + +/**Function************************************************************* + + Synopsis [Transforms equiv classes by filtering those that correspond to disproved outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManEquivFilterTest( Gia_Man_t * p ) +{ + Vec_Int_t * vPoIds; + int i; + vPoIds = Vec_IntAlloc( 1000 ); + for ( i = 0; i < 10; i++ ) + { + Vec_IntPush( vPoIds, Gia_ManPoNum(p) + 2 * i + 2 ); + printf( "%d ", Gia_ManPoNum(p) + 2*i + 2 ); + } + printf( "\n" ); + Gia_ManEquivFilter( p, vPoIds, 1 ); + Vec_IntFree( vPoIds ); +} + +/**Function************************************************************* + + Synopsis [Transforms equiv classes by setting a good representative.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManEquivImprove( Gia_Man_t * p ) +{ + Vec_Int_t * vClass; + int i, k, iNode, iRepr; + int iReprBest, iLevelBest, iLevelCur, iMffcBest, iMffcCur; + assert( p->pReprs != NULL && p->pNexts != NULL ); + Gia_ManLevelNum( p ); + Gia_ManCreateRefs( p ); + // iterate over class candidates + vClass = Vec_IntAlloc( 100 ); + Gia_ManForEachClass( p, i ) + { + Vec_IntClear( vClass ); + iReprBest = -1; + iLevelBest = iMffcBest = ABC_INFINITY; + Gia_ClassForEachObj( p, i, k ) + { + iLevelCur = Gia_ObjLevel( p,Gia_ManObj(p, k) ); + iMffcCur = Gia_NodeMffcSize( p, Gia_ManObj(p, k) ); + if ( iLevelBest > iLevelCur || (iLevelBest == iLevelCur && iMffcBest > iMffcCur) ) + { + iReprBest = k; + iLevelBest = iLevelCur; + iMffcBest = iMffcCur; + } + Vec_IntPush( vClass, k ); + } + assert( Vec_IntSize( vClass ) > 1 ); + assert( iReprBest > 0 ); + if ( i == iReprBest ) + continue; +/* + Abc_Print( 1, "Repr/Best = %6d/%6d. Lev = %3d/%3d. Mffc = %3d/%3d.\n", + i, iReprBest, Gia_ObjLevel( p,Gia_ManObj(p, i) ), Gia_ObjLevel( p,Gia_ManObj(p, iReprBest) ), + Gia_NodeMffcSize( p, Gia_ManObj(p, i) ), Gia_NodeMffcSize( p, Gia_ManObj(p, iReprBest) ) ); +*/ + iRepr = iReprBest; + Gia_ObjSetRepr( p, iRepr, GIA_VOID ); + Gia_ObjSetProved( p, i ); + Gia_ObjUnsetProved( p, iRepr ); + Vec_IntForEachEntry( vClass, iNode, k ) + if ( iNode != iRepr ) + Gia_ObjSetRepr( p, iNode, iRepr ); + } + Vec_IntFree( vClass ); + ABC_FREE( p->pNexts ); +// p->pNexts = Gia_ManDeriveNexts( p ); +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if pOld is in the TFI of pNode.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ObjCheckTfi_rec( Gia_Man_t * p, Gia_Obj_t * pOld, Gia_Obj_t * pNode, Vec_Ptr_t * vVisited ) +{ + // check the trivial cases + if ( pNode == NULL ) + return 0; + if ( Gia_ObjIsCi(pNode) ) + return 0; +// if ( pNode->Id < pOld->Id ) // cannot use because of choices of pNode +// return 0; + if ( pNode == pOld ) + return 1; + // skip the visited node + if ( pNode->fMark0 ) + return 0; + pNode->fMark0 = 1; + Vec_PtrPush( vVisited, pNode ); + // check the children + if ( Gia_ObjCheckTfi_rec( p, pOld, Gia_ObjFanin0(pNode), vVisited ) ) + return 1; + if ( Gia_ObjCheckTfi_rec( p, pOld, Gia_ObjFanin1(pNode), vVisited ) ) + return 1; + // check equivalent nodes + return Gia_ObjCheckTfi_rec( p, pOld, Gia_ObjNextObj(p, Gia_ObjId(p, pNode)), vVisited ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pOld is in the TFI of pNode.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ObjCheckTfi( Gia_Man_t * p, Gia_Obj_t * pOld, Gia_Obj_t * pNode ) +{ + Vec_Ptr_t * vVisited; + Gia_Obj_t * pObj; + int RetValue, i; + assert( !Gia_IsComplement(pOld) ); + assert( !Gia_IsComplement(pNode) ); + vVisited = Vec_PtrAlloc( 100 ); + RetValue = Gia_ObjCheckTfi_rec( p, pOld, pNode, vVisited ); + Vec_PtrForEachEntry( Gia_Obj_t *, vVisited, pObj, i ) + pObj->fMark0 = 0; + Vec_PtrFree( vVisited ); + return RetValue; +} + + +/**Function************************************************************* + + Synopsis [Adds the next entry while making choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManAddNextEntry_rec( Gia_Man_t * p, Gia_Obj_t * pOld, Gia_Obj_t * pNode ) +{ + if ( Gia_ObjNext(p, Gia_ObjId(p, pOld)) == 0 ) + { + Gia_ObjSetNext( p, Gia_ObjId(p, pOld), Gia_ObjId(p, pNode) ); + return; + } + Gia_ManAddNextEntry_rec( p, Gia_ObjNextObj(p, Gia_ObjId(p, pOld)), pNode ); +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManEquivToChoices_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + Gia_Obj_t * pRepr, * pReprNew, * pObjNew; + if ( ~pObj->Value ) + return; + if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) && !Gia_ObjFailed(p,Gia_ObjId(p,pObj)) ) + { + if ( Gia_ObjIsConst0(pRepr) ) + { + pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); + return; + } + Gia_ManEquivToChoices_rec( pNew, p, pRepr ); + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( Abc_LitRegular(pObj->Value) == Abc_LitRegular(pRepr->Value) ) + { + assert( (int)pObj->Value == Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ) ); + return; + } + if ( pRepr->Value > pObj->Value ) // should never happen with high resource limit + return; + assert( pRepr->Value < pObj->Value ); + pReprNew = Gia_ManObj( pNew, Abc_Lit2Var(pRepr->Value) ); + pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) ); + if ( Gia_ObjReprObj( pNew, Gia_ObjId(pNew, pObjNew) ) ) + { +// assert( Gia_ObjReprObj( pNew, Gia_ObjId(pNew, pObjNew) ) == pReprNew ); + if ( Gia_ObjReprObj( pNew, Gia_ObjId(pNew, pObjNew) ) != pReprNew ) + return; + pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); + return; + } + if ( !Gia_ObjCheckTfi( pNew, pReprNew, pObjNew ) ) + { + assert( Gia_ObjNext(pNew, Gia_ObjId(pNew, pObjNew)) == 0 ); + Gia_ObjSetRepr( pNew, Gia_ObjId(pNew, pObjNew), Gia_ObjId(pNew, pReprNew) ); + Gia_ManAddNextEntry_rec( pNew, pReprNew, pObjNew ); + } + pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); + return; + } + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Removes choices, which contain fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManRemoveBadChoices( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, iObj, iPrev, Counter = 0; + // mark nodes with fanout + Gia_ManForEachObj( p, pObj, i ) + { + pObj->fMark0 = 0; + if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ObjFanin0(pObj)->fMark0 = 1; + Gia_ObjFanin1(pObj)->fMark0 = 1; + } + else if ( Gia_ObjIsCo(pObj) ) + Gia_ObjFanin0(pObj)->fMark0 = 1; + } + // go through the classes and remove + Gia_ManForEachClass( p, i ) + { + for ( iPrev = i, iObj = Gia_ObjNext(p, i); iObj; iObj = Gia_ObjNext(p, iPrev) ) + { + if ( !Gia_ManObj(p, iObj)->fMark0 ) + { + iPrev = iObj; + continue; + } + Gia_ObjSetRepr( p, iObj, GIA_VOID ); + Gia_ObjSetNext( p, iPrev, Gia_ObjNext(p, iObj) ); + Gia_ObjSetNext( p, iObj, 0 ); + Counter++; + } + } + // remove the marks + Gia_ManCleanMark0( p ); +// Abc_Print( 1, "Removed %d bad choices.\n", Counter ); +} + +/**Function************************************************************* + + Synopsis [Reduces AIG using equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManEquivToChoices( Gia_Man_t * p, int nSnapshots ) +{ + Vec_Int_t * vNodes; + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pRepr; + int i; +//Gia_ManEquivPrintClasses( p, 0, 0 ); + assert( (Gia_ManCoNum(p) % nSnapshots) == 0 ); + Gia_ManSetPhase( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) ); + pNew->pNexts = ABC_CALLOC( int, Gia_ManObjNum(p) ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + pNew->pReprs[i].iRepr = GIA_VOID; + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachRo( p, pObj, i ) + if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) + { + assert( Gia_ObjIsConst0(pRepr) || Gia_ObjIsRo(p, pRepr) ); + pObj->Value = pRepr->Value; + } + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin0(pObj) ); + vNodes = Gia_ManGetDangling( p ); + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + Gia_ManEquivToChoices_rec( pNew, p, pObj ); + Vec_IntFree( vNodes ); + Gia_ManForEachCo( p, pObj, i ) + if ( i % nSnapshots == 0 ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + Gia_ManRemoveBadChoices( pNew ); +//Gia_ManEquivPrintClasses( pNew, 0, 0 ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); +//Gia_ManEquivPrintClasses( pNew, 0, 0 ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Counts the number of choice nodes] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCountChoiceNodes( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, Counter = 0; + if ( p->pReprs == NULL || p->pNexts == NULL ) + return 0; + Gia_ManForEachObj( p, pObj, i ) + Counter += Gia_ObjIsHead( p, i ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of choices] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCountChoices( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, Counter = 0; + if ( p->pReprs == NULL || p->pNexts == NULL ) + return 0; + Gia_ManForEachObj( p, pObj, i ) + Counter += (int)(Gia_ObjNext( p, i ) > 0); + return Counter; +} + +ABC_NAMESPACE_IMPL_END + +#include "aig/aig/aig.h" +#include "aig/saig/saig.h" +#include "proof/cec/cec.h" +#include "giaAig.h" + +ABC_NAMESPACE_IMPL_START + + +/**Function************************************************************* + + Synopsis [Returns 1 if AIG has dangling nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManHasNoEquivs( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + if ( p->pReprs == NULL ) + return 1; + Gia_ManForEachObj( p, pObj, i ) + if ( Gia_ObjReprObj(p, i) != NULL ) + break; + return i == Gia_ManObjNum(p); +} + +/**Function************************************************************* + + Synopsis [Implements iteration during speculation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_CommandSpecI( Gia_Man_t * pGia, int nFramesInit, int nBTLimitInit, int fStart, int fCheckMiter, int fVerbose ) +{ +// extern int Cec_ManCheckNonTrivialCands( Gia_Man_t * pAig ); + Aig_Man_t * pTemp; + Gia_Man_t * pSrm, * pReduce, * pAux; + int nIter, nStart = 0; + if ( pGia->pReprs == NULL || pGia->pNexts == NULL ) + { + Abc_Print( 1, "Gia_CommandSpecI(): Equivalence classes are not defined.\n" ); + return 0; + } + // (spech)* where spech = &srm; restore save3; bmc2 -F 100 -C 25000; &resim + Gia_ManCleanMark0( pGia ); + Gia_ManPrintStats( pGia, NULL ); + for ( nIter = 0; ; nIter++ ) + { + if ( Gia_ManHasNoEquivs(pGia) ) + { + Abc_Print( 1, "Gia_CommandSpecI: No equivalences left.\n" ); + break; + } + Abc_Print( 1, "ITER %3d : ", nIter ); +// if ( fVerbose ) +// Abc_Print( 1, "Starting BMC from frame %d.\n", nStart ); +// if ( fVerbose ) +// Gia_ManPrintStats( pGia, 0 ); + Gia_ManPrintStatsClasses( pGia ); + // perform speculative reduction +// if ( Gia_ManPoNum(pSrm) <= Gia_ManPoNum(pGia) ) + if ( !Cec_ManCheckNonTrivialCands(pGia) ) + { + Abc_Print( 1, "Gia_CommandSpecI: There are only trivial equiv candidates left (PO drivers). Quitting.\n" ); + break; + } + pSrm = Gia_ManSpecReduce( pGia, 0, 0, 1, 0, 0 ); + // bmc2 -F 100 -C 25000 + { + Abc_Cex_t * pCex; + int nFrames = nFramesInit; // different from default + int nNodeDelta = 2000; + int nBTLimit = nBTLimitInit; // different from default + int nBTLimitAll = 2000000; + pTemp = Gia_ManToAig( pSrm, 0 ); +// Aig_ManPrintStats( pTemp ); + Gia_ManStop( pSrm ); + Saig_BmcPerform( pTemp, nStart, nFrames, nNodeDelta, 0, nBTLimit, nBTLimitAll, fVerbose, 0, NULL, 0, 0 ); + pCex = pTemp->pSeqModel; pTemp->pSeqModel = NULL; + Aig_ManStop( pTemp ); + if ( pCex == NULL ) + { + Abc_Print( 1, "Gia_CommandSpecI(): Internal BMC could not find a counter-example.\n" ); + break; + } + if ( fStart ) + nStart = pCex->iFrame; + // perform simulation + { + Cec_ParSim_t Pars, * pPars = &Pars; + Cec_ManSimSetDefaultParams( pPars ); + pPars->fCheckMiter = fCheckMiter; + if ( Cec_ManSeqResimulateCounter( pGia, pPars, pCex ) ) + { + ABC_FREE( pCex ); + break; + } + ABC_FREE( pCex ); + } + } + // write equivalence classes + Gia_AigerWrite( pGia, "gore.aig", 0, 0, 0 ); + // reduce the model + pReduce = Gia_ManSpecReduce( pGia, 0, 0, 1, 0, 0 ); + if ( pReduce ) + { + pReduce = Gia_ManSeqStructSweep( pAux = pReduce, 1, 1, 0 ); + Gia_ManStop( pAux ); + Gia_AigerWrite( pReduce, "gsrm.aig", 0, 0, 0 ); +// Abc_Print( 1, "Speculatively reduced model was written into file \"%s\".\n", "gsrm.aig" ); +// Gia_ManPrintStatsShort( pReduce ); + Gia_ManStop( pReduce ); + } + } + return 1; +} + + + + +/**Function************************************************************* + + Synopsis [Reduces AIG using equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManFilterEquivsForSpeculation( Gia_Man_t * pGia, char * pName1, char * pName2, int fLatchA, int fLatchB ) +{ + Gia_Man_t * pGia1, * pGia2, * pMiter; + Gia_Obj_t * pObj1, * pObj2, * pObjM, * pObj; + int i, iObj, iNext, Counter = 0; + if ( pGia->pReprs == NULL || pGia->pNexts == NULL ) + { + Abc_Print( 1, "Equivalences are not defined.\n" ); + return 0; + } + pGia1 = Gia_AigerRead( pName1, 0, 0, 0 ); + if ( pGia1 == NULL ) + { + Abc_Print( 1, "Cannot read first file %s.\n", pName1 ); + return 0; + } + pGia2 = Gia_AigerRead( pName2, 0, 0, 0 ); + if ( pGia2 == NULL ) + { + Gia_ManStop( pGia2 ); + Abc_Print( 1, "Cannot read second file %s.\n", pName2 ); + return 0; + } + pMiter = Gia_ManMiter( pGia1, pGia2, 0, 0, 1, 0, 0 ); + if ( pMiter == NULL ) + { + Gia_ManStop( pGia1 ); + Gia_ManStop( pGia2 ); + Abc_Print( 1, "Cannot create sequential miter.\n" ); + return 0; + } + // make sure the miter is isomorphic + if ( Gia_ManObjNum(pGia) != Gia_ManObjNum(pMiter) ) + { + Gia_ManStop( pGia1 ); + Gia_ManStop( pGia2 ); + Gia_ManStop( pMiter ); + Abc_Print( 1, "The number of objects in different.\n" ); + return 0; + } + if ( memcmp( pGia->pObjs, pMiter->pObjs, sizeof(Gia_Obj_t) * Gia_ManObjNum(pGia) ) ) + { + Gia_ManStop( pGia1 ); + Gia_ManStop( pGia2 ); + Gia_ManStop( pMiter ); + Abc_Print( 1, "The AIG structure of the miter does not match.\n" ); + return 0; + } + // transfer copies + Gia_ManCleanMark0( pGia ); + Gia_ManForEachObj( pGia1, pObj1, i ) + { + if ( pObj1->Value == ~0 ) + continue; + pObjM = Gia_ManObj( pMiter, Abc_Lit2Var(pObj1->Value) ); + pObj = Gia_ManObj( pGia, Gia_ObjId(pMiter, pObjM) ); + pObj->fMark0 = 1; + } + Gia_ManCleanMark1( pGia ); + Gia_ManForEachObj( pGia2, pObj2, i ) + { + if ( pObj2->Value == ~0 ) + continue; + pObjM = Gia_ManObj( pMiter, Abc_Lit2Var(pObj2->Value) ); + pObj = Gia_ManObj( pGia, Gia_ObjId(pMiter, pObjM) ); + pObj->fMark1 = 1; + } + + // filter equivalences + Gia_ManForEachConst( pGia, i ) + { + Gia_ObjUnsetRepr( pGia, i ); + assert( pGia->pNexts[i] == 0 ); + } + Gia_ManForEachClass( pGia, i ) + { + // find the first colorA and colorB + int ClassA = -1, ClassB = -1; + Gia_ClassForEachObj( pGia, i, iObj ) + { + pObj = Gia_ManObj( pGia, iObj ); + if ( ClassA == -1 && pObj->fMark0 && !pObj->fMark1 ) + { + if ( fLatchA && !Gia_ObjIsRo(pGia, pObj) ) + continue; + ClassA = iObj; + } + if ( ClassB == -1 && pObj->fMark1 && !pObj->fMark0 ) + { + if ( fLatchB && !Gia_ObjIsRo(pGia, pObj) ) + continue; + ClassB = iObj; + } + } + // undo equivalence classes + for ( iObj = i, iNext = Gia_ObjNext(pGia, iObj); iObj; + iObj = iNext, iNext = Gia_ObjNext(pGia, iObj) ) + { + Gia_ObjUnsetRepr( pGia, iObj ); + Gia_ObjSetNext( pGia, iObj, 0 ); + } + assert( !Gia_ObjIsHead(pGia, i) ); + if ( ClassA > 0 && ClassB > 0 ) + { + if ( ClassA > ClassB ) + { + ClassA ^= ClassB; + ClassB ^= ClassA; + ClassA ^= ClassB; + } + assert( ClassA < ClassB ); + Gia_ObjSetNext( pGia, ClassA, ClassB ); + Gia_ObjSetRepr( pGia, ClassB, ClassA ); + Counter++; + assert( Gia_ObjIsHead(pGia, ClassA) ); + } + } + Abc_Print( 1, "The number of two-node classes after filtering = %d.\n", Counter ); +//Gia_ManEquivPrintClasses( pGia, 1, 0 ); + + Gia_ManCleanMark0( pGia ); + Gia_ManCleanMark1( pGia ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Reduces AIG using equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManFilterEquivsUsingParts( Gia_Man_t * pGia, char * pName1, char * pName2 ) +{ + Vec_Int_t * vNodes; + Gia_Man_t * pGia1, * pGia2, * pMiter; + Gia_Obj_t * pObj1, * pObj2, * pObjM, * pObj = NULL; + int i, k, iObj, iNext, iPrev, iRepr; + int iLitsOld, iLitsNew; + if ( pGia->pReprs == NULL || pGia->pNexts == NULL ) + { + Abc_Print( 1, "Equivalences are not defined.\n" ); + return 0; + } + pGia1 = Gia_AigerRead( pName1, 0, 0, 0 ); + if ( pGia1 == NULL ) + { + Abc_Print( 1, "Cannot read first file %s.\n", pName1 ); + return 0; + } + pGia2 = Gia_AigerRead( pName2, 0, 0, 0 ); + if ( pGia2 == NULL ) + { + Gia_ManStop( pGia2 ); + Abc_Print( 1, "Cannot read second file %s.\n", pName2 ); + return 0; + } + pMiter = Gia_ManMiter( pGia1, pGia2, 0, 0, 1, 0, 0 ); + if ( pMiter == NULL ) + { + Gia_ManStop( pGia1 ); + Gia_ManStop( pGia2 ); + Abc_Print( 1, "Cannot create sequential miter.\n" ); + return 0; + } + // make sure the miter is isomorphic + if ( Gia_ManObjNum(pGia) != Gia_ManObjNum(pMiter) ) + { + Gia_ManStop( pGia1 ); + Gia_ManStop( pGia2 ); + Gia_ManStop( pMiter ); + Abc_Print( 1, "The number of objects in different.\n" ); + return 0; + } + if ( memcmp( pGia->pObjs, pMiter->pObjs, sizeof(Gia_Obj_t) * Gia_ManObjNum(pGia) ) ) + { + Gia_ManStop( pGia1 ); + Gia_ManStop( pGia2 ); + Gia_ManStop( pMiter ); + Abc_Print( 1, "The AIG structure of the miter does not match.\n" ); + return 0; + } + // transfer copies + Gia_ManCleanMark0( pGia ); + Gia_ManForEachObj( pGia1, pObj1, i ) + { + if ( pObj1->Value == ~0 ) + continue; + pObjM = Gia_ManObj( pMiter, Abc_Lit2Var(pObj1->Value) ); + pObj = Gia_ManObj( pGia, Gia_ObjId(pMiter, pObjM) ); + pObj->fMark0 = 1; + } + Gia_ManCleanMark1( pGia ); + Gia_ManForEachObj( pGia2, pObj2, i ) + { + if ( pObj2->Value == ~0 ) + continue; + pObjM = Gia_ManObj( pMiter, Abc_Lit2Var(pObj2->Value) ); + pObj = Gia_ManObj( pGia, Gia_ObjId(pMiter, pObjM) ); + pObj->fMark1 = 1; + } + + // filter equivalences + iLitsOld = iLitsNew = 0; + Gia_ManForEachConst( pGia, i ) + { + iLitsOld++; + pObj = Gia_ManObj( pGia, i ); + assert( pGia->pNexts[i] == 0 ); + assert( pObj->fMark0 || pObj->fMark1 ); + if ( pObj->fMark0 && pObj->fMark1 ) // belongs to both A and B + Gia_ObjUnsetRepr( pGia, i ); + else + iLitsNew++; + } + // filter equivalences + vNodes = Vec_IntAlloc( 100 ); + Gia_ManForEachClass( pGia, i ) + { + int fSeenA = 0, fSeenB = 0; + assert( pObj->fMark0 || pObj->fMark1 ); + Vec_IntClear( vNodes ); + Gia_ClassForEachObj( pGia, i, iObj ) + { + pObj = Gia_ManObj( pGia, iObj ); + if ( pObj->fMark0 && !pObj->fMark1 ) + { + fSeenA = 1; + Vec_IntPush( vNodes, iObj ); + } + if ( !pObj->fMark0 && pObj->fMark1 ) + { + fSeenB = 1; + Vec_IntPush( vNodes, iObj ); + } + iLitsOld++; + } + iLitsOld--; + // undo equivalence classes + for ( iObj = i, iNext = Gia_ObjNext(pGia, iObj); iObj; + iObj = iNext, iNext = Gia_ObjNext(pGia, iObj) ) + { + Gia_ObjUnsetRepr( pGia, iObj ); + Gia_ObjSetNext( pGia, iObj, 0 ); + } + assert( !Gia_ObjIsHead(pGia, i) ); + if ( fSeenA && fSeenB && Vec_IntSize(vNodes) > 1 ) + { + // create new class + iPrev = iRepr = Vec_IntEntry( vNodes, 0 ); + Vec_IntForEachEntryStart( vNodes, iObj, k, 1 ) + { + Gia_ObjSetRepr( pGia, iObj, iRepr ); + Gia_ObjSetNext( pGia, iPrev, iObj ); + iPrev = iObj; + iLitsNew++; + } + assert( Gia_ObjNext(pGia, iPrev) == 0 ); + } + } + Vec_IntFree( vNodes ); + Abc_Print( 1, "The number of literals: Before = %d. After = %d.\n", iLitsOld, iLitsNew ); +//Gia_ManEquivPrintClasses( pGia, 1, 0 ); + + Gia_ManCleanMark0( pGia ); + Gia_ManCleanMark1( pGia ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManFilterEquivsUsingLatches( Gia_Man_t * pGia, int fFlopsOnly, int fFlopsWith, int fUseRiDrivers ) +{ + Gia_Obj_t * pObjR; + Vec_Int_t * vNodes, * vFfIds; + int i, k, iObj, iNext, iPrev, iRepr; + int iLitsOld = 0, iLitsNew = 0; + assert( fFlopsOnly ^ fFlopsWith ); + vNodes = Vec_IntAlloc( 100 ); + // select nodes "flop" node IDs + vFfIds = Vec_IntStart( Gia_ManObjNum(pGia) ); + if ( fUseRiDrivers ) + { + Gia_ManForEachRi( pGia, pObjR, i ) + Vec_IntWriteEntry( vFfIds, Gia_ObjFaninId0p(pGia, pObjR), 1 ); + } + else + { + Gia_ManForEachRo( pGia, pObjR, i ) + Vec_IntWriteEntry( vFfIds, Gia_ObjId(pGia, pObjR), 1 ); + } + // remove all non-flop constants + Gia_ManForEachConst( pGia, i ) + { + iLitsOld++; + assert( pGia->pNexts[i] == 0 ); + if ( !Vec_IntEntry(vFfIds, i) ) + Gia_ObjUnsetRepr( pGia, i ); + else + iLitsNew++; + } + // clear the classes + if ( fFlopsOnly ) + { + Gia_ManForEachClass( pGia, i ) + { + Vec_IntClear( vNodes ); + Gia_ClassForEachObj( pGia, i, iObj ) + { + if ( Vec_IntEntry(vFfIds, iObj) ) + Vec_IntPush( vNodes, iObj ); + iLitsOld++; + } + iLitsOld--; + // undo equivalence classes + for ( iObj = i, iNext = Gia_ObjNext(pGia, iObj); iObj; + iObj = iNext, iNext = Gia_ObjNext(pGia, iObj) ) + { + Gia_ObjUnsetRepr( pGia, iObj ); + Gia_ObjSetNext( pGia, iObj, 0 ); + } + assert( !Gia_ObjIsHead(pGia, i) ); + if ( Vec_IntSize(vNodes) > 1 ) + { + // create new class + iPrev = iRepr = Vec_IntEntry( vNodes, 0 ); + Vec_IntForEachEntryStart( vNodes, iObj, k, 1 ) + { + Gia_ObjSetRepr( pGia, iObj, iRepr ); + Gia_ObjSetNext( pGia, iPrev, iObj ); + iPrev = iObj; + iLitsNew++; + } + assert( Gia_ObjNext(pGia, iPrev) == 0 ); + } + } + } + else + { + Gia_ManForEachClass( pGia, i ) + { + int fSeenFlop = 0; + Gia_ClassForEachObj( pGia, i, iObj ) + { + if ( Vec_IntEntry(vFfIds, iObj) ) + fSeenFlop = 1; + iLitsOld++; + iLitsNew++; + } + iLitsOld--; + iLitsNew--; + if ( fSeenFlop ) + continue; + // undo equivalence classes + for ( iObj = i, iNext = Gia_ObjNext(pGia, iObj); iObj; + iObj = iNext, iNext = Gia_ObjNext(pGia, iObj) ) + { + Gia_ObjUnsetRepr( pGia, iObj ); + Gia_ObjSetNext( pGia, iObj, 0 ); + iLitsNew--; + } + iLitsNew++; + assert( !Gia_ObjIsHead(pGia, i) ); + } + } + Vec_IntFree( vNodes ); + Vec_IntFree( vFfIds ); + Abc_Print( 1, "The number of literals: Before = %d. After = %d.\n", iLitsOld, iLitsNew ); +} + +/**Function************************************************************* + + Synopsis [Changing node order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManChangeOrder_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return pObj->Value; + if ( Gia_ObjIsCi(pObj) ) + return pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManChangeOrder_rec( pNew, p, Gia_ObjFanin0(pObj) ); + if ( Gia_ObjIsCo(pObj) ) + return pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManChangeOrder_rec( pNew, p, Gia_ObjFanin1(pObj) ); + return pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManChangeOrder( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i, k; + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachClass( p, i ) + Gia_ClassForEachObj( p, i, k ) + Gia_ManChangeOrder_rec( pNew, p, Gia_ManObj(p, k) ); + Gia_ManForEachConst( p, k ) + Gia_ManChangeOrder_rec( pNew, p, Gia_ManObj(p, k) ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManChangeOrder_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + assert( Gia_ManObjNum(pNew) == Gia_ManObjNum(p) ); + return pNew; +} +void Gia_ManTransferEquivs( Gia_Man_t * p, Gia_Man_t * pNew ) +{ + Vec_Int_t * vClass; + int i, k, iNode, iRepr; + assert( Gia_ManObjNum(p) == Gia_ManObjNum(pNew) ); + assert( p->pReprs != NULL ); + assert( p->pNexts != NULL ); + assert( pNew->pReprs == NULL ); + assert( pNew->pNexts == NULL ); + // start representatives + pNew->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(pNew) ); + for ( i = 0; i < Gia_ManObjNum(pNew); i++ ) + Gia_ObjSetRepr( pNew, i, GIA_VOID ); + // iterate over constant candidates + Gia_ManForEachConst( p, i ) + Gia_ObjSetRepr( pNew, Abc_Lit2Var(Gia_ManObj(p, i)->Value), 0 ); + // iterate over class candidates + vClass = Vec_IntAlloc( 100 ); + Gia_ManForEachClass( p, i ) + { + Vec_IntClear( vClass ); + Gia_ClassForEachObj( p, i, k ) + Vec_IntPushUnique( vClass, Abc_Lit2Var(Gia_ManObj(p, k)->Value) ); + assert( Vec_IntSize( vClass ) > 1 ); + Vec_IntSort( vClass, 0 ); + iRepr = Vec_IntEntry( vClass, 0 ); + Vec_IntForEachEntryStart( vClass, iNode, k, 1 ) + Gia_ObjSetRepr( pNew, iNode, iRepr ); + } + Vec_IntFree( vClass ); + pNew->pNexts = Gia_ManDeriveNexts( pNew ); +} +void Gia_ManTransferTest( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; int i; + Gia_Rpr_t * pReprs = p->pReprs; // representatives (for CIs and ANDs) + int * pNexts = p->pNexts; // next nodes in the equivalence classes + Gia_Man_t * pNew = Gia_ManChangeOrder(p); + //Gia_ManEquivPrintClasses( p, 1, 0 ); + assert( Gia_ManObjNum(p) == Gia_ManObjNum(pNew) ); + Gia_ManTransferEquivs( p, pNew ); + p->pReprs = NULL; + p->pNexts = NULL; + // make new point to old + Gia_ManForEachObj( p, pObj, i ) + { + assert( !Abc_LitIsCompl(pObj->Value) ); + Gia_ManObj(pNew, Abc_Lit2Var(pObj->Value))->Value = Abc_Var2Lit(i, 0); + } + Gia_ManTransferEquivs( pNew, p ); + //Gia_ManEquivPrintClasses( p, 1, 0 ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + pReprs[i].fProved = 0; + //printf( "%5d : %5d %5d %5d %5d\n", i, *(int*)&p->pReprs[i], *(int*)&pReprs[i], (int)p->pNexts[i], (int)pNexts[i] ); + if ( memcmp(p->pReprs, pReprs, sizeof(int)*Gia_ManObjNum(p)) ) + printf( "Verification of reprs failed.\n" ); + else + printf( "Verification of reprs succeeded.\n" ); + if ( memcmp(p->pNexts, pNexts, sizeof(int)*Gia_ManObjNum(p)) ) + printf( "Verification of nexts failed.\n" ); + else + printf( "Verification of nexts succeeded.\n" ); + ABC_FREE( pNew->pReprs ); + ABC_FREE( pNew->pNexts ); + ABC_FREE( pReprs ); + ABC_FREE( pNexts ); + Gia_ManStop( pNew ); +} + +/**Function************************************************************* + + Synopsis [Transfer from new to old.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManTransferEquivs2( Gia_Man_t * p, Gia_Man_t * pOld ) +{ + Gia_Obj_t * pObj; + Vec_Int_t * vClass; + int i, k, iNode, iRepr; + assert( p->pReprs != NULL ); + assert( p->pNexts != NULL ); + assert( pOld->pReprs == NULL ); + assert( pOld->pNexts == NULL ); + // create map + Gia_ManFillValue( p ); + Gia_ManForEachObj( pOld, pObj, i ) + if ( ~pObj->Value ) + Gia_ManObj(p, Abc_Lit2Var(pObj->Value))->Value = Abc_Var2Lit(i, 0); + // start representatives + pOld->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(pOld) ); + for ( i = 0; i < Gia_ManObjNum(pOld); i++ ) + Gia_ObjSetRepr( pOld, i, GIA_VOID ); + // iterate over constant candidates + Gia_ManForEachConst( p, i ) + Gia_ObjSetRepr( pOld, Abc_Lit2Var(Gia_ManObj(p, i)->Value), 0 ); + // iterate over class candidates + vClass = Vec_IntAlloc( 100 ); + Gia_ManForEachClass( p, i ) + { + Vec_IntClear( vClass ); + Gia_ClassForEachObj( p, i, k ) + if ( (int)Gia_ManObj(p, k)->Value >= 0 ) + Vec_IntPushUnique( vClass, Abc_Lit2Var(Gia_ManObj(p, k)->Value) ); + if ( Vec_IntSize( vClass ) <= 1 ) + continue; + assert( Vec_IntSize( vClass ) > 1 ); + Vec_IntSort( vClass, 0 ); + iRepr = Vec_IntEntry( vClass, 0 ); + Vec_IntForEachEntryStart( vClass, iNode, k, 1 ) + Gia_ObjSetRepr( pOld, iNode, iRepr ); + } + Vec_IntFree( vClass ); + pOld->pNexts = Gia_ManDeriveNexts( pOld ); +} + +/**Function************************************************************* + + Synopsis [Converting AIG after SAT sweeping into AIG with choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Cec4_ManMarkIndependentClasses_rec( Gia_Man_t * p, int iObj ) +{ + Gia_Obj_t * pObj; + assert( iObj > 0 ); + if ( Gia_ObjIsTravIdPreviousId(p, iObj) ) // failed + return 0; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) // passed + return 1; + Gia_ObjSetTravIdCurrentId(p, iObj); + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + return 1; + assert( Gia_ObjIsAnd(pObj) ); + if ( Cec4_ManMarkIndependentClasses_rec( p, Gia_ObjFaninId0(pObj, iObj) ) && + Cec4_ManMarkIndependentClasses_rec( p, Gia_ObjFaninId1(pObj, iObj) ) ) + return 1; + Gia_ObjSetTravIdPreviousId(p, iObj); + return 0; +} +int Cec4_ManMarkIndependentClasses( Gia_Man_t * p, Gia_Man_t * pNew ) +{ + int iObjNew, iRepr, iObj, Res, fHaveChoices = 0; + Gia_ManCleanMark01(p); + Gia_ManForEachClass( p, iRepr ) + { + Gia_ManIncrementTravId( pNew ); + Gia_ManIncrementTravId( pNew ); + iObjNew = Abc_Lit2Var( Gia_ManObj(p, iRepr)->Value ); + Res = Cec4_ManMarkIndependentClasses_rec( pNew, iObjNew ); + assert( Res == 1 ); + Gia_ObjSetTravIdPreviousId( pNew, iObjNew ); + p->pReprs[iRepr].fColorA = 1; + Gia_ClassForEachObj1( p, iRepr, iObj ) + { + assert( p->pReprs[iObj].iRepr == (unsigned)iRepr ); + iObjNew = Abc_Lit2Var( Gia_ManObj(p, iObj)->Value ); + if ( Cec4_ManMarkIndependentClasses_rec( pNew, iObjNew ) ) + { + p->pReprs[iObj].fColorA = 1; + fHaveChoices = 1; + } + Gia_ObjSetTravIdPreviousId( pNew, iObjNew ); + } + } + return fHaveChoices; +} +int Cec4_ManSatSolverAnd_rec( Gia_Man_t * pCho, Gia_Man_t * p, Gia_Man_t * pNew, int iObj ) +{ + return 0; +} +int Cec4_ManSatSolverChoices_rec( Gia_Man_t * pCho, Gia_Man_t * p, Gia_Man_t * pNew, int iObj ) +{ + if ( !Gia_ObjIsClass(p, iObj) ) + return Cec4_ManSatSolverAnd_rec( pCho, p, pNew, iObj ); + else + { + Vec_Int_t * vLits = Vec_IntAlloc( 100 ); + int i, iHead, iNext, iRepr = Gia_ObjIsHead(p, iObj) ? iObj : Gia_ObjRepr(p, iObj); + Gia_ClassForEachObj( p, iRepr, iObj ) + if ( p->pReprs[iObj].fColorA ) + Vec_IntPush( vLits, Cec4_ManSatSolverAnd_rec( pCho, p, pNew, iObj ) ); + Vec_IntSort( vLits, 1 ); + iHead = Abc_Lit2Var( Vec_IntEntry(vLits, 0) ); + if ( Vec_IntSize(vLits) > 1 ) + { + Vec_IntForEachEntryStart( vLits, iNext, i, 1 ) + { + pCho->pSibls[iHead] = Abc_Lit2Var(iNext); + iHead = Abc_Lit2Var(iNext); + } + } + return Abc_LitNotCond( Vec_IntEntry(vLits, 0), Gia_ManObj(p, iHead)->fPhase ); + } +} +Gia_Man_t * Cec4_ManSatSolverChoices( Gia_Man_t * p, Gia_Man_t * pNew ) +{ + Gia_Man_t * pCho; + Gia_Obj_t * pObj; + int i, DriverId; + // mark topologically dependent equivalent nodes + if ( !Cec4_ManMarkIndependentClasses( p, pNew ) ) + return Gia_ManDup( pNew ); + // rebuild AIG in a different order with choices + pCho = Gia_ManStart( Gia_ManObjNum(pNew) ); + pCho->pName = Abc_UtilStrsav( p->pName ); + pCho->pSpec = Abc_UtilStrsav( p->pSpec ); + pCho->pSibls = ABC_CALLOC( int, Gia_ManObjNum(pNew) ); + Gia_ManFillValue(pNew); + Gia_ManConst0(pNew)->Value = 0; + for ( i = 0; i < Gia_ManCiNum(pNew); i++ ) + Gia_ManCi(pNew, i)->Value = Gia_ManAppendCi( pCho ); + Gia_ManForEachCoDriverId( p, DriverId, i ) + Cec4_ManSatSolverChoices_rec( pCho, p, pNew, DriverId ); + Gia_ManForEachCo( pNew, pObj, i ) + pObj->Value = Gia_ManAppendCo( pCho, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pCho, Gia_ManRegNum(p) ); + return pCho; +} + +/**Function************************************************************* + + Synopsis [Converting AIG after SAT sweeping into AIG with choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManCombSpecReduce( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj, * pRepr; int i, iLit; + Vec_Int_t * vXors = Vec_IntAlloc( 100 ); + Gia_Man_t * pTemp, * pNew = Gia_ManStart( Gia_ManObjNum(p) ); + assert( p->pReprs && p->pNexts ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManLevelNum(p); + Gia_ManSetPhase(p); + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + { + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + pRepr = Gia_ObjReprObj( p, i ); + if ( pRepr && Abc_Lit2Var(pObj->Value) != Abc_Lit2Var(pRepr->Value) ) + { + //if ( Gia_ObjLevel(p, pRepr) > Gia_ObjLevel(p, pObj) + 50 ) + //printf( "%d %d ", Gia_ObjLevel(p, pRepr), Gia_ObjLevel(p, pObj) ); + iLit = Abc_LitNotCond( pRepr->Value, pObj->fPhase ^ pRepr->fPhase ); + Vec_IntPush( vXors, Gia_ManHashXor( pNew, pObj->Value, iLit ) ); + pObj->Value = iLit; + } + } + Gia_ManHashStop( pNew ); + if ( Vec_IntSize(vXors) == 0 ) + Vec_IntPush( vXors, 0 ); + Vec_IntForEachEntry( vXors, iLit, i ) + Gia_ManAppendCo( pNew, iLit ); + Vec_IntFree( vXors ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} +void Gia_ManCombSpecReduceTest( Gia_Man_t * p, char * pFileName ) +{ + Gia_Man_t * pSrm = Gia_ManCombSpecReduce( p ); + if ( pFileName == NULL ) + pFileName = "test.aig"; + Gia_AigerWrite( pSrm, pFileName, 0, 0, 0 ); + Abc_Print( 1, "Speculatively reduced model was written into file \"%s\".\n", pFileName ); + Gia_ManStop( pSrm ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END diff --git a/yosys/abc/src/aig/gia/giaEra.c b/yosys/abc/src/aig/gia/giaEra.c new file mode 100644 index 00000000000..b5b94cb5136 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaEra.c @@ -0,0 +1,602 @@ +/**CFile**************************************************************** + + FileName [giaEra.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Explicit reachability analysis.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaEra.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/mem/mem.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// explicit state representation +typedef struct Gia_ObjEra_t_ Gia_ObjEra_t; +struct Gia_ObjEra_t_ +{ + int Num; // ID of this state + int Cond; // input condition + int iPrev; // previous state + int iNext; // next state in the hash table + unsigned pData[0]; // state bits +}; + +// explicit state reachability +typedef struct Gia_ManEra_t_ Gia_ManEra_t; +struct Gia_ManEra_t_ +{ + Gia_Man_t * pAig; // user's AIG manager + int nWordsSim; // 2^(PInum) + int nWordsDat; // Abc_BitWordNum + unsigned * pDataSim; // simulation data + Mem_Fixed_t * pMemory; // memory manager + Vec_Ptr_t * vStates; // reached states + Gia_ObjEra_t * pStateNew; // temporary state + int iCurState; // the current state + Vec_Int_t * vBugTrace; // the sequence of transitions + Vec_Int_t * vStgDump; // STG written into a file + // hash table for states + int nBins; + unsigned * pBins; +}; + +static inline unsigned * Gia_ManEraData( Gia_ManEra_t * p, int i ) { return p->pDataSim + i * p->nWordsSim; } +static inline Gia_ObjEra_t * Gia_ManEraState( Gia_ManEra_t * p, int i ) { return (Gia_ObjEra_t *)Vec_PtrEntry(p->vStates, i); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates reachability manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_ManEra_t * Gia_ManEraCreate( Gia_Man_t * pAig ) +{ + Vec_Ptr_t * vTruths; + Gia_ManEra_t * p; + unsigned * pTruth, * pSimInfo; + int i; + p = ABC_CALLOC( Gia_ManEra_t, 1 ); + p->pAig = pAig; + p->nWordsSim = Abc_TruthWordNum( Gia_ManPiNum(pAig) ); + p->nWordsDat = Abc_BitWordNum( Gia_ManRegNum(pAig) ); + p->pDataSim = ABC_ALLOC( unsigned, p->nWordsSim*Gia_ManObjNum(pAig) ); + p->pMemory = Mem_FixedStart( sizeof(Gia_ObjEra_t) + sizeof(unsigned) * p->nWordsDat ); + p->vStates = Vec_PtrAlloc( 100000 ); + p->nBins = Abc_PrimeCudd( 100000 ); + p->pBins = ABC_CALLOC( unsigned, p->nBins ); + Vec_PtrPush( p->vStates, NULL ); + // assign primary input values + vTruths = Vec_PtrAllocTruthTables( Gia_ManPiNum(pAig) ); + Vec_PtrForEachEntry( unsigned *, vTruths, pTruth, i ) + { + pSimInfo = Gia_ManEraData( p, Gia_ObjId(pAig, Gia_ManPi(pAig, i)) ); + memcpy( pSimInfo, pTruth, sizeof(unsigned) * p->nWordsSim ); + } + Vec_PtrFree( vTruths ); + // assign constant zero node + pSimInfo = Gia_ManEraData( p, 0 ); + memset( pSimInfo, 0, sizeof(unsigned) * p->nWordsSim ); + p->vStgDump = Vec_IntAlloc( 1000 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Deletes reachability manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManEraFree( Gia_ManEra_t * p ) +{ + Mem_FixedStop( p->pMemory, 0 ); + Vec_IntFree( p->vStgDump ); + Vec_PtrFree( p->vStates ); + if ( p->vBugTrace ) Vec_IntFree( p->vBugTrace ); + ABC_FREE( p->pDataSim ); + ABC_FREE( p->pBins ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Creates new state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_ObjEra_t * Gia_ManEraCreateState( Gia_ManEra_t * p ) +{ + Gia_ObjEra_t * pNew; + pNew = (Gia_ObjEra_t *)Mem_FixedEntryFetch( p->pMemory ); + pNew->Num = Vec_PtrSize( p->vStates ); + pNew->iPrev = 0; + Vec_PtrPush( p->vStates, pNew ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Computes hash value of the node using its simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManEraStateHash( unsigned * pState, int nWordsSim, int nTableSize ) +{ + static int s_FPrimes[128] = { + 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, + 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, + 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, + 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, + 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, + 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, + 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, + 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, + 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, + 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, + 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, + 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, + 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 + }; + unsigned uHash; + int i; + uHash = 0; + for ( i = 0; i < nWordsSim; i++ ) + uHash ^= pState[i] * s_FPrimes[i & 0x7F]; + return uHash % nTableSize; +} + +/**Function************************************************************* + + Synopsis [Returns the place of this state in the table or NULL if it exists.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned * Gia_ManEraHashFind( Gia_ManEra_t * p, Gia_ObjEra_t * pState, int * pStateNum ) +{ + Gia_ObjEra_t * pThis; + unsigned * pPlace = p->pBins + Gia_ManEraStateHash( pState->pData, p->nWordsDat, p->nBins ); + for ( pThis = (*pPlace)? Gia_ManEraState(p, *pPlace) : NULL; pThis; + pPlace = (unsigned *)&pThis->iNext, pThis = (*pPlace)? Gia_ManEraState(p, *pPlace) : NULL ) + if ( !memcmp( pState->pData, pThis->pData, sizeof(unsigned) * p->nWordsDat ) ) + { + if ( pStateNum ) + *pStateNum = pThis->Num; + return NULL; + } + if ( pStateNum ) + *pStateNum = -1; + return pPlace; +} + +/**Function************************************************************* + + Synopsis [Resizes the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManEraHashResize( Gia_ManEra_t * p ) +{ + Gia_ObjEra_t * pThis; + unsigned * pBinsOld, * piPlace; + int nBinsOld, iNext, Counter, i; + assert( p->pBins != NULL ); + // replace the table + pBinsOld = p->pBins; + nBinsOld = p->nBins; + p->nBins = Abc_PrimeCudd( 3 * p->nBins ); + p->pBins = ABC_CALLOC( unsigned, p->nBins ); + // rehash the entries from the old table + Counter = 0; + for ( i = 0; i < nBinsOld; i++ ) + for ( pThis = (pBinsOld[i]? Gia_ManEraState(p, pBinsOld[i]) : NULL), + iNext = (pThis? pThis->iNext : 0); + pThis; pThis = (iNext? Gia_ManEraState(p, iNext) : NULL), + iNext = (pThis? pThis->iNext : 0) ) + { + assert( pThis->Num ); + pThis->iNext = 0; + piPlace = Gia_ManEraHashFind( p, pThis, NULL ); + assert( *piPlace == 0 ); // should not be there + *piPlace = pThis->Num; + Counter++; + } + assert( Counter == Vec_PtrSize( p->vStates ) - 1 ); + ABC_FREE( pBinsOld ); +} + +/**Function************************************************************* + + Synopsis [Initialize register output to the given state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManInsertState( Gia_ManEra_t * p, Gia_ObjEra_t * pState ) +{ + Gia_Obj_t * pObj; + unsigned * pSimInfo; + int i; + Gia_ManForEachRo( p->pAig, pObj, i ) + { + pSimInfo = Gia_ManEraData( p, Gia_ObjId(p->pAig, pObj) ); + if ( Abc_InfoHasBit(pState->pData, i) ) + memset( pSimInfo, 0xff, sizeof(unsigned) * p->nWordsSim ); + else + memset( pSimInfo, 0, sizeof(unsigned) * p->nWordsSim ); + } +} + +/**Function************************************************************* + + Synopsis [Returns -1 if outputs are not asserted.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManOutputAsserted( Gia_ManEra_t * p, Gia_Obj_t * pObj ) +{ + unsigned * pInfo = Gia_ManEraData( p, Gia_ObjId(p->pAig, pObj) ); + int w; + for ( w = 0; w < p->nWordsSim; w++ ) + if ( pInfo[w] ) + return 32*w + Gia_WordFindFirstBit( pInfo[w] ); + return -1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSimulateCo( Gia_ManEra_t * p, Gia_Obj_t * pObj ) +{ + int Id = Gia_ObjId(p->pAig, pObj); + unsigned * pInfo = Gia_ManEraData( p, Id ); + unsigned * pInfo0 = Gia_ManEraData( p, Gia_ObjFaninId0(pObj, Id) ); + int w; + if ( Gia_ObjFaninC0(pObj) ) + for ( w = p->nWordsSim-1; w >= 0; w-- ) + pInfo[w] = ~pInfo0[w]; + else + for ( w = p->nWordsSim-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSimulateNode( Gia_ManEra_t * p, Gia_Obj_t * pObj ) +{ + int Id = Gia_ObjId(p->pAig, pObj); + unsigned * pInfo = Gia_ManEraData( p, Id ); + unsigned * pInfo0 = Gia_ManEraData( p, Gia_ObjFaninId0(pObj, Id) ); + unsigned * pInfo1 = Gia_ManEraData( p, Gia_ObjFaninId1(pObj, Id) ); + int w; + if ( Gia_ObjFaninC0(pObj) ) + { + if ( Gia_ObjFaninC1(pObj) ) + for ( w = p->nWordsSim-1; w >= 0; w-- ) + pInfo[w] = ~(pInfo0[w] | pInfo1[w]); + else + for ( w = p->nWordsSim-1; w >= 0; w-- ) + pInfo[w] = ~pInfo0[w] & pInfo1[w]; + } + else + { + if ( Gia_ObjFaninC1(pObj) ) + for ( w = p->nWordsSim-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w] & ~pInfo1[w]; + else + for ( w = p->nWordsSim-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w] & pInfo1[w]; + } +} + +/**Function************************************************************* + + Synopsis [Performs one iteration of reachability analysis.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPerformOneIter( Gia_ManEra_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachObj1( p->pAig, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + Gia_ManSimulateNode( p, pObj ); + else if ( Gia_ObjIsCo(pObj) ) + Gia_ManSimulateCo( p, pObj ); + } +} + +/**Function************************************************************* + + Synopsis [Performs one iteration of reachability analysis.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManCollectBugTrace( Gia_ManEra_t * p, Gia_ObjEra_t * pState, int iCond ) +{ + Vec_Int_t * vTrace; + vTrace = Vec_IntAlloc( 10 ); + Vec_IntPush( vTrace, iCond ); + for ( ; pState; pState = pState->iPrev ? Gia_ManEraState(p, pState->iPrev) : NULL ) + Vec_IntPush( vTrace, pState->Cond ); + Vec_IntReverseOrder( vTrace ); + return vTrace; +} + +/**Function************************************************************* + + Synopsis [Counts the depth of state transitions leading ot this state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCountDepth( Gia_ManEra_t * p ) +{ + Gia_ObjEra_t * pState; + int Counter = 0; + pState = (Gia_ObjEra_t *)Vec_PtrEntryLast( p->vStates ); + if ( pState->iPrev == 0 && Vec_PtrSize(p->vStates) > 3 ) + pState = (Gia_ObjEra_t *)Vec_PtrEntry( p->vStates, Vec_PtrSize(p->vStates) - 2 ); + for ( ; pState; pState = pState->iPrev ? Gia_ManEraState(p, pState->iPrev) : NULL ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Analized reached states.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManAnalyzeResult( Gia_ManEra_t * p, Gia_ObjEra_t * pState, int fMiter, int fStgDump ) +{ + Gia_Obj_t * pObj; + unsigned * pSimInfo, * piPlace, uOutput = 0; + int i, k, iCond, nMints, iNextState; + // check if the miter is asserted + if ( fMiter ) + { + Gia_ManForEachPo( p->pAig, pObj, i ) + { + iCond = Gia_ManOutputAsserted( p, pObj ); + if ( iCond >= 0 ) + { + p->vBugTrace = Gia_ManCollectBugTrace( p, pState, iCond ); + return 1; + } + } + } + // collect reached states + nMints = (1 << Gia_ManPiNum(p->pAig)); + for ( k = 0; k < nMints; k++ ) + { + if ( p->pStateNew == NULL ) + p->pStateNew = Gia_ManEraCreateState( p ); + p->pStateNew->pData[p->nWordsDat-1] = 0; + Gia_ManForEachRi( p->pAig, pObj, i ) + { + pSimInfo = Gia_ManEraData( p, Gia_ObjId(p->pAig, pObj) ); + if ( Abc_InfoHasBit(p->pStateNew->pData, i) != Abc_InfoHasBit(pSimInfo, k) ) + Abc_InfoXorBit( p->pStateNew->pData, i ); + } + if ( fStgDump ) + { + uOutput = 0; + Gia_ManForEachPo( p->pAig, pObj, i ) + { + pSimInfo = Gia_ManEraData( p, Gia_ObjId(p->pAig, pObj) ); + if ( Abc_InfoHasBit(pSimInfo, k) && i < 32 ) + Abc_InfoXorBit( &uOutput, i ); + } + } + piPlace = Gia_ManEraHashFind( p, p->pStateNew, &iNextState ); + if ( fStgDump ) Vec_IntPush( p->vStgDump, k ); + if ( fStgDump ) Vec_IntPush( p->vStgDump, pState->Num ); + if ( piPlace == NULL ) + { + if ( fStgDump ) Vec_IntPush( p->vStgDump, iNextState ); + if ( fStgDump ) Vec_IntPush( p->vStgDump, uOutput ); + continue; + } + if ( fStgDump ) Vec_IntPush( p->vStgDump, p->pStateNew->Num ); + if ( fStgDump ) Vec_IntPush( p->vStgDump, uOutput ); +//printf( "Inserting %d ", Vec_PtrSize(p->vStates) ); +//Extra_PrintBinary( stdout, p->pStateNew->pData, Gia_ManRegNum(p->pAig) ); printf( "\n" ); + assert( *piPlace == 0 ); + *piPlace = p->pStateNew->Num; + p->pStateNew->Cond = k; + p->pStateNew->iPrev = pState->Num; + p->pStateNew->iNext = 0; + p->pStateNew = NULL; + // expand hash table if needed + if ( Vec_PtrSize(p->vStates) > 2 * p->nBins ) + Gia_ManEraHashResize( p ); + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Resizes the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCollectReachable( Gia_Man_t * pAig, int nStatesMax, int fMiter, int fDumpFile, int fVerbose ) +{ + Gia_ManEra_t * p; + Gia_ObjEra_t * pState; + int Hash; + abctime clk = Abc_Clock(); + int RetValue = 1; + assert( Gia_ManPiNum(pAig) <= 12 ); + assert( Gia_ManRegNum(pAig) > 0 ); + p = Gia_ManEraCreate( pAig ); + // create init state + pState = Gia_ManEraCreateState( p ); + pState->Cond = 0; + pState->iPrev = 0; + pState->iNext = 0; + memset( pState->pData, 0, sizeof(unsigned) * p->nWordsDat ); + Hash = Gia_ManEraStateHash(pState->pData, p->nWordsDat, p->nBins); + p->pBins[ Hash ] = pState->Num; + // process reachable states + while ( p->iCurState < Vec_PtrSize( p->vStates ) - 1 ) + { + if ( Vec_PtrSize(p->vStates) >= nStatesMax ) + { + printf( "Reached the limit on states traversed (%d). ", nStatesMax ); + RetValue = -1; + break; + } + pState = Gia_ManEraState( p, ++p->iCurState ); + if ( p->iCurState > 1 && pState->iPrev == 0 ) + continue; +//printf( "Extracting %d ", p->iCurState ); +//Extra_PrintBinary( stdout, p->pStateNew->pData, Gia_ManRegNum(p->pAig) ); printf( "\n" ); + Gia_ManInsertState( p, pState ); + Gia_ManPerformOneIter( p ); + if ( Gia_ManAnalyzeResult( p, pState, fMiter, fDumpFile ) && fMiter ) + { + RetValue = 0; + printf( "Miter failed in state %d after %d transitions. ", + p->iCurState, Vec_IntSize(p->vBugTrace)-1 ); + break; + } + if ( fVerbose && p->iCurState % 5000 == 0 ) + { + printf( "States =%10d. Reached =%10d. R = %5.3f. Depth =%6d. Mem =%9.2f MB. ", + p->iCurState, Vec_PtrSize(p->vStates), 1.0*p->iCurState/Vec_PtrSize(p->vStates), Gia_ManCountDepth(p), + (1.0/(1<<20))*(1.0*Vec_PtrSize(p->vStates)*(sizeof(Gia_ObjEra_t) + sizeof(unsigned) * p->nWordsDat) + + 1.0*p->nBins*sizeof(unsigned) + 1.0*p->vStates->nCap * sizeof(void*)) ); + ABC_PRT( "Time", Abc_Clock() - clk ); + } + } + printf( "Reachability analysis traversed %d states with depth %d. ", p->iCurState-1, Gia_ManCountDepth(p) ); + ABC_PRT( "Time", Abc_Clock() - clk ); + if ( fDumpFile ) + { + char * pFileName = "test.stg"; + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + printf( "Cannot open file \"%s\" for writing.\n", pFileName ); + else + { + Gia_ManStgPrint( pFile, p->vStgDump, Gia_ManPiNum(pAig), Gia_ManPoNum(pAig), p->iCurState-1 ); + fclose( pFile ); + printf( "Extracted STG was written into file \"%s\".\n", pFileName ); + } + } + Gia_ManEraFree( p ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaEra2.c b/yosys/abc/src/aig/gia/giaEra2.c new file mode 100644 index 00000000000..a6165573af7 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaEra2.c @@ -0,0 +1,1963 @@ +/**CFile**************************************************************** + + FileName [gia.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "giaAig.h" + +ABC_NAMESPACE_IMPL_START + +/* + Limitations of this package: + - no more than (1<<31)-1 state cubes and internal nodes + - no more than MAX_VARS_NUM state variables + - no more than MAX_CALL_NUM transitions from a state + - cube list rebalancing happens when cube count reaches MAX_CUBE_NUM +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define MAX_CALL_NUM (1000000) // the max number of recursive calls +#define MAX_ITEM_NUM (1<<20) // the number of items on a page +#define MAX_PAGE_NUM (1<<11) // the max number of memory pages +#define MAX_VARS_NUM (1<<14) // the max number of state vars allowed +#define MAX_CUBE_NUM 63 // the max number of cubes before rebalancing + +// pointer to the tree node or state cube +typedef struct Gia_PtrAre_t_ Gia_PtrAre_t; +struct Gia_PtrAre_t_ +{ + unsigned nItem : 20; // item number (related to MAX_ITEM_NUM) + unsigned nPage : 11; // page number (related to MAX_PAGE_NUM) + unsigned fMark : 1; // user mark +}; + +typedef union Gia_PtrAreInt_t_ Gia_PtrAreInt_t; +union Gia_PtrAreInt_t_ +{ + Gia_PtrAre_t iGia; + unsigned iInt; +}; + +// tree nodes +typedef struct Gia_ObjAre_t_ Gia_ObjAre_t; +struct Gia_ObjAre_t_ +{ + unsigned iVar : 14; // variable (related to MAX_VARS_NUM) + unsigned nStas0 : 6; // cube counter (related to MAX_CUBE_NUM) + unsigned nStas1 : 6; // cube counter (related to MAX_CUBE_NUM) + unsigned nStas2 : 6; // cube counter (related to MAX_CUBE_NUM) + Gia_PtrAre_t F[3]; // branches +}; + +// state cube +typedef struct Gia_StaAre_t_ Gia_StaAre_t; +struct Gia_StaAre_t_ +{ + Gia_PtrAre_t iPrev; // previous state + Gia_PtrAre_t iNext; // next cube in the list + unsigned pData[0]; // state bits +}; + +// explicit state reachability manager +typedef struct Gia_ManAre_t_ Gia_ManAre_t; +struct Gia_ManAre_t_ +{ + Gia_Man_t * pAig; // user's AIG manager + Gia_Man_t * pNew; // temporary AIG manager + unsigned ** ppObjs; // storage for objects (MAX_PAGE_NUM pages) + unsigned ** ppStas; // storage for states (MAX_PAGE_NUM pages) +// unsigned * pfUseless; // to label useless cubes +// int nUselessAlloc; // the number of useless alloced + // internal flags + int fMiter; // stops when a bug is discovered + int fStopped; // set high when reachability is stopped + int fTree; // working in the tree mode + // internal parametesr + int nWords; // the size of bit info in words + int nSize; // the size of state structure in words + int nObjPages; // the number of pages used for objects + int nStaPages; // the number of pages used for states + int nObjs; // the number of objects + int nStas; // the number of states + int iStaCur; // the next state to be explored + Gia_PtrAre_t Root; // root of the tree + Vec_Vec_t * vCiTfos; // storage for nodes in the CI TFOs + Vec_Vec_t * vCiLits; // storage for literals of these nodes + Vec_Int_t * vCubesA; // checked cubes + Vec_Int_t * vCubesB; // unchecked cubes + // deriving counter-example + void * pSat; // SAT solver + Vec_Int_t * vSatNumCis; // SAT variables for CIs + Vec_Int_t * vSatNumCos; // SAT variables for COs + Vec_Int_t * vCofVars; // variables used to cofactor + Vec_Int_t * vAssumps; // temporary storage for assumptions + Gia_StaAre_t * pTarget; // state that needs to be reached + int iOutFail; // the number of the failed output + // statistics + int nChecks; // the number of timea cube was checked + int nEquals; // total number of equal + int nCompares; // the number of compares + int nRecCalls; // the number of rec calls + int nDisjs; // the number of disjoint cube pairs + int nDisjs2; // the number of disjoint cube pairs + int nDisjs3; // the number of disjoint cube pairs + // time + int timeAig; // AIG cofactoring time + int timeCube; // cube checking time +}; + +static inline Gia_PtrAre_t Gia_Int2Ptr( unsigned n ) { Gia_PtrAreInt_t g; g.iInt = n; return g.iGia; } +static inline unsigned Gia_Ptr2Int( Gia_PtrAre_t n ) { Gia_PtrAreInt_t g; g.iGia = n; return g.iInt & 0x7fffffff; } + +static inline int Gia_ObjHasBranch0( Gia_ObjAre_t * q ) { return !q->nStas0 && (q->F[0].nPage || q->F[0].nItem); } +static inline int Gia_ObjHasBranch1( Gia_ObjAre_t * q ) { return !q->nStas1 && (q->F[1].nPage || q->F[1].nItem); } +static inline int Gia_ObjHasBranch2( Gia_ObjAre_t * q ) { return !q->nStas2 && (q->F[2].nPage || q->F[2].nItem); } + +static inline Gia_ObjAre_t * Gia_ManAreObj( Gia_ManAre_t * p, Gia_PtrAre_t n ) { return (Gia_ObjAre_t *)(p->ppObjs[n.nPage] + (n.nItem << 2)); } +static inline Gia_StaAre_t * Gia_ManAreSta( Gia_ManAre_t * p, Gia_PtrAre_t n ) { return (Gia_StaAre_t *)(p->ppStas[n.nPage] + n.nItem * p->nSize); } +static inline Gia_ObjAre_t * Gia_ManAreObjInt( Gia_ManAre_t * p, int n ) { return Gia_ManAreObj( p, Gia_Int2Ptr(n) ); } +static inline Gia_StaAre_t * Gia_ManAreStaInt( Gia_ManAre_t * p, int n ) { return Gia_ManAreSta( p, Gia_Int2Ptr(n) ); } +static inline Gia_ObjAre_t * Gia_ManAreObjLast( Gia_ManAre_t * p ) { return Gia_ManAreObjInt( p, p->nObjs-1 ); } +static inline Gia_StaAre_t * Gia_ManAreStaLast( Gia_ManAre_t * p ) { return Gia_ManAreStaInt( p, p->nStas-1 ); } + +static inline Gia_ObjAre_t * Gia_ObjNextObj0( Gia_ManAre_t * p, Gia_ObjAre_t * q ) { return Gia_ManAreObj( p, q->F[0] ); } +static inline Gia_ObjAre_t * Gia_ObjNextObj1( Gia_ManAre_t * p, Gia_ObjAre_t * q ) { return Gia_ManAreObj( p, q->F[1] ); } +static inline Gia_ObjAre_t * Gia_ObjNextObj2( Gia_ManAre_t * p, Gia_ObjAre_t * q ) { return Gia_ManAreObj( p, q->F[2] ); } + +static inline int Gia_StaHasValue0( Gia_StaAre_t * p, int iReg ) { return Abc_InfoHasBit( p->pData, iReg << 1 ); } +static inline int Gia_StaHasValue1( Gia_StaAre_t * p, int iReg ) { return Abc_InfoHasBit( p->pData, (iReg << 1) + 1 ); } + +static inline void Gia_StaSetValue0( Gia_StaAre_t * p, int iReg ) { Abc_InfoSetBit( p->pData, iReg << 1 ); } +static inline void Gia_StaSetValue1( Gia_StaAre_t * p, int iReg ) { Abc_InfoSetBit( p->pData, (iReg << 1) + 1 ); } + +static inline Gia_StaAre_t * Gia_StaPrev( Gia_ManAre_t * p, Gia_StaAre_t * pS ) { return Gia_ManAreSta(p, pS->iPrev); } +static inline Gia_StaAre_t * Gia_StaNext( Gia_ManAre_t * p, Gia_StaAre_t * pS ) { return Gia_ManAreSta(p, pS->iNext); } +static inline int Gia_StaIsGood( Gia_ManAre_t * p, Gia_StaAre_t * pS ) { return ((unsigned *)pS) != p->ppStas[0]; } + +static inline void Gia_StaSetUnused( Gia_StaAre_t * pS ) { pS->iPrev.fMark = 1; } +static inline int Gia_StaIsUnused( Gia_StaAre_t * pS ) { return pS->iPrev.fMark; } +static inline int Gia_StaIsUsed( Gia_StaAre_t * pS ) { return !pS->iPrev.fMark; } + +#define Gia_ManAreForEachCubeList( p, pList, pCube ) \ + for ( pCube = pList; Gia_StaIsGood(p, pCube); pCube = Gia_StaNext(p, pCube) ) +#define Gia_ManAreForEachCubeList2( p, iList, pCube, iCube ) \ + for ( iCube = Gia_Ptr2Int(iList), pCube = Gia_ManAreSta(p, iList); \ + Gia_StaIsGood(p, pCube); \ + iCube = Gia_Ptr2Int(pCube->iNext), pCube = Gia_StaNext(p, pCube) ) +#define Gia_ManAreForEachCubeStore( p, pCube, i ) \ + for ( i = 1; i < p->nStas && (pCube = Gia_ManAreStaInt(p, i)); i++ ) +#define Gia_ManAreForEachCubeVec( vVec, p, pCube, i ) \ + for ( i = 0; i < Vec_IntSize(vVec) && (pCube = Gia_ManAreStaInt(p, Vec_IntEntry(vVec,i))); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Count state minterms contained in a cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCountMintermsInCube( Gia_StaAre_t * pCube, int nVars, unsigned * pStore ) +{ + unsigned Mint, Mask = 0; + int i, m, nMints, nDashes = 0, Dashes[32]; + // count the number of dashes + for ( i = 0; i < nVars; i++ ) + { + if ( Gia_StaHasValue0( pCube, i ) ) + continue; + if ( Gia_StaHasValue1( pCube, i ) ) + Mask |= (1 << i); + else + Dashes[nDashes++] = i; + } + // fill in the miterms + nMints = (1 << nDashes); + for ( m = 0; m < nMints; m++ ) + { + Mint = Mask; + for ( i = 0; i < nVars; i++ ) + if ( m & (1 << i) ) + Mint |= (1 << Dashes[i]); + Abc_InfoSetBit( pStore, Mint ); + } +} + +/**Function************************************************************* + + Synopsis [Count state minterms contains in the used cubes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCountMinterms( Gia_ManAre_t * p ) +{ + Gia_StaAre_t * pCube; + unsigned * pMemory; + int i, nMemSize, Counter = 0; + if ( Gia_ManRegNum(p->pAig) > 30 ) + return -1; + nMemSize = Abc_BitWordNum( 1 << Gia_ManRegNum(p->pAig) ); + pMemory = ABC_CALLOC( unsigned, nMemSize ); + Gia_ManAreForEachCubeStore( p, pCube, i ) + if ( Gia_StaIsUsed(pCube) ) + Gia_ManCountMintermsInCube( pCube, Gia_ManRegNum(p->pAig), pMemory ); + for ( i = 0; i < nMemSize; i++ ) + Counter += Gia_WordCountOnes( pMemory[i] ); + ABC_FREE( pMemory ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Derives the TFO of one CI.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManDeriveCiTfo_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vRes ) +{ + if ( Gia_ObjIsCi(pObj) ) + return pObj->fMark0; + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return pObj->fMark0; + Gia_ObjSetTravIdCurrent(p, pObj); + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManDeriveCiTfo_rec( p, Gia_ObjFanin0(pObj), vRes ); + Gia_ManDeriveCiTfo_rec( p, Gia_ObjFanin1(pObj), vRes ); + pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 | Gia_ObjFanin1(pObj)->fMark0; + if ( pObj->fMark0 ) + Vec_IntPush( vRes, Gia_ObjId(p, pObj) ); + return pObj->fMark0; +} + + +/**Function************************************************************* + + Synopsis [Derives the TFO of one CI.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManDeriveCiTfoOne( Gia_Man_t * p, Gia_Obj_t * pPivot ) +{ + Vec_Int_t * vRes; + Gia_Obj_t * pObj; + int i; + assert( pPivot->fMark0 == 0 ); + pPivot->fMark0 = 1; + vRes = Vec_IntAlloc( 100 ); + Vec_IntPush( vRes, Gia_ObjId(p, pPivot) ); + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); + Gia_ManForEachCo( p, pObj, i ) + { + Gia_ManDeriveCiTfo_rec( p, Gia_ObjFanin0(pObj), vRes ); + if ( Gia_ObjFanin0(pObj)->fMark0 ) + Vec_IntPush( vRes, Gia_ObjId(p, pObj) ); + } + pPivot->fMark0 = 0; + return vRes; +} + +/**Function************************************************************* + + Synopsis [Derives the TFO of each CI.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Vec_t * Gia_ManDeriveCiTfo( Gia_Man_t * p ) +{ + Vec_Ptr_t * vRes; + Gia_Obj_t * pPivot; + int i; + Gia_ManCleanMark0( p ); + Gia_ManIncrementTravId( p ); + vRes = Vec_PtrAlloc( Gia_ManCiNum(p) ); + Gia_ManForEachCi( p, pPivot, i ) + Vec_PtrPush( vRes, Gia_ManDeriveCiTfoOne(p, pPivot) ); + Gia_ManCleanMark0( p ); + return (Vec_Vec_t *)vRes; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if states are equal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_StaAreEqual( Gia_StaAre_t * p1, Gia_StaAre_t * p2, int nWords ) +{ + int w; + for ( w = 0; w < nWords; w++ ) + if ( p1->pData[w] != p2->pData[w] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if states are disjoint.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_StaAreDisjoint( Gia_StaAre_t * p1, Gia_StaAre_t * p2, int nWords ) +{ + int w; + for ( w = 0; w < nWords; w++ ) + if ( ((p1->pData[w] ^ p2->pData[w]) >> 1) & (p1->pData[w] ^ p2->pData[w]) & 0x55555555 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if cube p1 contains cube p2.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_StaAreContain( Gia_StaAre_t * p1, Gia_StaAre_t * p2, int nWords ) +{ + int w; + for ( w = 0; w < nWords; w++ ) + if ( (p1->pData[w] | p2->pData[w]) != p2->pData[w] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns the number of dashes in p1 that are non-dashes in p2.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_StaAreDashNum( Gia_StaAre_t * p1, Gia_StaAre_t * p2, int nWords ) +{ + int w, Counter = 0; + for ( w = 0; w < nWords; w++ ) + Counter += Gia_WordCountOnes( (~(p1->pData[w] ^ (p1->pData[w] >> 1))) & (p2->pData[w] ^ (p2->pData[w] >> 1)) & 0x55555555 ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns the number of a variable for sharping the cube.] + + Description [Counts the number of variables that have dash in p1 and + non-dash in p2. If there is exactly one such variable, returns its index. + Otherwise returns -1.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_StaAreSharpVar( Gia_StaAre_t * p1, Gia_StaAre_t * p2, int nWords ) +{ + unsigned Word; + int w, iVar = -1; + for ( w = 0; w < nWords; w++ ) + { + Word = (~(p1->pData[w] ^ (p1->pData[w] >> 1))) & (p2->pData[w] ^ (p2->pData[w] >> 1)) & 0x55555555; + if ( Word == 0 ) + continue; + if ( !Gia_WordHasOneBit(Word) ) + return -1; + // has exactly one bit + if ( iVar >= 0 ) + return -1; + // the first variable of this type + iVar = 16 * w + Gia_WordFindFirstBit( Word ) / 2; + } + return iVar; +} + +/**Function************************************************************* + + Synopsis [Returns the number of a variable for merging the cubes.] + + Description [If there is exactly one such variable, returns its index. + Otherwise returns -1.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_StaAreDisjointVar( Gia_StaAre_t * p1, Gia_StaAre_t * p2, int nWords ) +{ + unsigned Word; + int w, iVar = -1; + for ( w = 0; w < nWords; w++ ) + { + Word = (p1->pData[w] ^ p2->pData[w]) & ((p1->pData[w] ^ p2->pData[w]) >> 1) & 0x55555555; + if ( Word == 0 ) + continue; + if ( !Gia_WordHasOneBit(Word) ) + return -1; + // has exactly one bit + if ( iVar >= 0 ) + return -1; + // the first variable of this type + iVar = 16 * w + Gia_WordFindFirstBit( Word ) / 2; + } + return iVar; +} + +/**Function************************************************************* + + Synopsis [Creates reachability manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_ManAre_t * Gia_ManAreCreate( Gia_Man_t * pAig ) +{ + Gia_ManAre_t * p; + assert( sizeof(Gia_ObjAre_t) == 16 ); + p = ABC_CALLOC( Gia_ManAre_t, 1 ); + p->pAig = pAig; + p->nWords = Abc_BitWordNum( 2 * Gia_ManRegNum(pAig) ); + p->nSize = sizeof(Gia_StaAre_t)/4 + p->nWords; + p->ppObjs = ABC_CALLOC( unsigned *, MAX_PAGE_NUM ); + p->ppStas = ABC_CALLOC( unsigned *, MAX_PAGE_NUM ); + p->vCiTfos = Gia_ManDeriveCiTfo( pAig ); + p->vCiLits = Vec_VecDupInt( p->vCiTfos ); + p->vCubesA = Vec_IntAlloc( 100 ); + p->vCubesB = Vec_IntAlloc( 100 ); + p->iOutFail = -1; + return p; +} + +/**Function************************************************************* + + Synopsis [Deletes reachability manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManAreFree( Gia_ManAre_t * p ) +{ + int i; + Gia_ManStop( p->pAig ); + if ( p->pNew ) + Gia_ManStop( p->pNew ); + Vec_IntFree( p->vCubesA ); + Vec_IntFree( p->vCubesB ); + Vec_VecFree( p->vCiTfos ); + Vec_VecFree( p->vCiLits ); + for ( i = 0; i < p->nObjPages; i++ ) + ABC_FREE( p->ppObjs[i] ); + ABC_FREE( p->ppObjs ); + for ( i = 0; i < p->nStaPages; i++ ) + ABC_FREE( p->ppStas[i] ); + ABC_FREE( p->ppStas ); +// ABC_FREE( p->pfUseless ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Returns new object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_ObjAre_t * Gia_ManAreCreateObj( Gia_ManAre_t * p ) +{ + if ( p->nObjs == p->nObjPages * MAX_ITEM_NUM ) + { + if ( p->nObjPages == MAX_PAGE_NUM ) + { + printf( "ERA manager has run out of memory after allocating 2B internal nodes.\n" ); + return NULL; + } + p->ppObjs[p->nObjPages++] = ABC_CALLOC( unsigned, MAX_ITEM_NUM * 4 ); + if ( p->nObjs == 0 ) + p->nObjs = 1; + } + return Gia_ManAreObjInt( p, p->nObjs++ ); +} + +/**Function************************************************************* + + Synopsis [Returns new state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_StaAre_t * Gia_ManAreCreateSta( Gia_ManAre_t * p ) +{ + if ( p->nStas == p->nStaPages * MAX_ITEM_NUM ) + { + if ( p->nStaPages == MAX_PAGE_NUM ) + { + printf( "ERA manager has run out of memory after allocating 2B state cubes.\n" ); + return NULL; + } + if ( p->ppStas[p->nStaPages] == NULL ) + p->ppStas[p->nStaPages] = ABC_CALLOC( unsigned, MAX_ITEM_NUM * p->nSize ); + p->nStaPages++; + if ( p->nStas == 0 ) + { + p->nStas = 1; +// p->nUselessAlloc = (1 << 18); +// p->pfUseless = ABC_CALLOC( unsigned, p->nUselessAlloc ); + } +// if ( p->nStas == p->nUselessAlloc * 32 ) +// { +// p->nUselessAlloc *= 2; +// p->pfUseless = ABC_REALLOC( unsigned, p->pfUseless, p->nUselessAlloc ); +// memset( p->pfUseless + p->nUselessAlloc/2, 0, sizeof(unsigned) * p->nUselessAlloc/2 ); +// } + } + return Gia_ManAreStaInt( p, p->nStas++ ); +} + +/**Function************************************************************* + + Synopsis [Recycles new state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManAreRycycleSta( Gia_ManAre_t * p, Gia_StaAre_t * pSta ) +{ + memset( pSta, 0, p->nSize << 2 ); + if ( pSta == Gia_ManAreStaLast(p) ) + { + p->nStas--; + if ( p->nStas == (p->nStaPages-1) * MAX_ITEM_NUM ) + p->nStaPages--; + } + else + { +// Gia_StaSetUnused( pSta ); + } +} + +/**Function************************************************************* + + Synopsis [Creates new state state from the latch values.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_StaAre_t * Gia_ManAreCreateStaNew( Gia_ManAre_t * p ) +{ + Gia_StaAre_t * pSta; + Gia_Obj_t * pObj; + int i; + pSta = Gia_ManAreCreateSta( p ); + Gia_ManForEachRi( p->pAig, pObj, i ) + { + if ( pObj->Value == 0 ) + Gia_StaSetValue0( pSta, i ); + else if ( pObj->Value == 1 ) + Gia_StaSetValue1( pSta, i ); + } + return pSta; +} + +/**Function************************************************************* + + Synopsis [Creates new state state with latch init values.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_StaAre_t * Gia_ManAreCreateStaInit( Gia_ManAre_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachRi( p->pAig, pObj, i ) + pObj->Value = 0; + return Gia_ManAreCreateStaNew( p ); +} + + +/**Function************************************************************* + + Synopsis [Prints the state cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManArePrintCube( Gia_ManAre_t * p, Gia_StaAre_t * pSta ) +{ + Gia_Obj_t * pObj; + int i, Count0 = 0, Count1 = 0, Count2 = 0; + printf( "%4d %4d : ", p->iStaCur, p->nStas-1 ); + printf( "Prev %4d ", Gia_Ptr2Int(pSta->iPrev) ); + printf( "%p ", pSta ); + Gia_ManForEachRi( p->pAig, pObj, i ) + { + if ( Gia_StaHasValue0(pSta, i) ) + printf( "0" ), Count0++; + else if ( Gia_StaHasValue1(pSta, i) ) + printf( "1" ), Count1++; + else + printf( "-" ), Count2++; + } + printf( " 0 =%3d", Count0 ); + printf( " 1 =%3d", Count1 ); + printf( " - =%3d", Count2 ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Counts the depth of state transitions leading ot this state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManAreDepth( Gia_ManAre_t * p, int iState ) +{ + Gia_StaAre_t * pSta; + int Counter = 0; + for ( pSta = Gia_ManAreStaInt(p, iState); Gia_StaIsGood(p, pSta); pSta = Gia_StaPrev(p, pSta) ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of cubes in the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManAreListCountListUsed( Gia_ManAre_t * p, Gia_PtrAre_t Root ) +{ + Gia_StaAre_t * pCube; + int Counter = 0; + Gia_ManAreForEachCubeList( p, Gia_ManAreSta(p, Root), pCube ) + Counter += Gia_StaIsUsed(pCube); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of used cubes in the tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManAreListCountUsed_rec( Gia_ManAre_t * p, Gia_PtrAre_t Root, int fTree ) +{ + Gia_ObjAre_t * pObj; + if ( !fTree ) + return Gia_ManAreListCountListUsed( p, Root ); + pObj = Gia_ManAreObj(p, Root); + return Gia_ManAreListCountUsed_rec( p, pObj->F[0], Gia_ObjHasBranch0(pObj) ) + + Gia_ManAreListCountUsed_rec( p, pObj->F[1], Gia_ObjHasBranch1(pObj) ) + + Gia_ManAreListCountUsed_rec( p, pObj->F[2], Gia_ObjHasBranch2(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Counts the number of used cubes in the tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManAreListCountUsed( Gia_ManAre_t * p ) +{ + return Gia_ManAreListCountUsed_rec( p, p->Root, p->fTree ); +} + + +/**Function************************************************************* + + Synopsis [Prints used cubes in the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManArePrintListUsed( Gia_ManAre_t * p, Gia_PtrAre_t Root ) +{ + Gia_StaAre_t * pCube; + Gia_ManAreForEachCubeList( p, Gia_ManAreSta(p, Root), pCube ) + if ( Gia_StaIsUsed(pCube) ) + Gia_ManArePrintCube( p, pCube ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Prints used cubes in the tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManArePrintUsed_rec( Gia_ManAre_t * p, Gia_PtrAre_t Root, int fTree ) +{ + Gia_ObjAre_t * pObj; + if ( !fTree ) + return Gia_ManArePrintListUsed( p, Root ); + pObj = Gia_ManAreObj(p, Root); + return Gia_ManArePrintUsed_rec( p, pObj->F[0], Gia_ObjHasBranch0(pObj) ) + + Gia_ManArePrintUsed_rec( p, pObj->F[1], Gia_ObjHasBranch1(pObj) ) + + Gia_ManArePrintUsed_rec( p, pObj->F[2], Gia_ObjHasBranch2(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Prints used cubes in the tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManArePrintUsed( Gia_ManAre_t * p ) +{ + return Gia_ManArePrintUsed_rec( p, p->Root, p->fTree ); +} + + +/**Function************************************************************* + + Synopsis [Best var has max weight.] + + Description [Weight is defined as the number of 0/1-lits minus the + absolute value of the diff between the number of 0-lits and 1-lits.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManAreFindBestVar( Gia_ManAre_t * p, Gia_PtrAre_t List ) +{ + Gia_StaAre_t * pCube; + int Count0, Count1, Count2; + int iVarThis, iVarBest = -1, WeightThis, WeightBest = -1; + for ( iVarThis = 0; iVarThis < Gia_ManRegNum(p->pAig); iVarThis++ ) + { + Count0 = Count1 = Count2 = 0; + Gia_ManAreForEachCubeList( p, Gia_ManAreSta(p, List), pCube ) + { + if ( Gia_StaIsUnused(pCube) ) + continue; + if ( Gia_StaHasValue0(pCube, iVarThis) ) + Count0++; + else if ( Gia_StaHasValue1(pCube, iVarThis) ) + Count1++; + else + Count2++; + } +// printf( "%4d : %5d %5d %5d Weight = %5d\n", iVarThis, Count0, Count1, Count2, +// Count0 + Count1 - (Count0 > Count1 ? Count0 - Count1 : Count1 - Count0) ); + if ( (!Count0 && !Count1) || (!Count0 && !Count2) || (!Count1 && !Count2) ) + continue; + WeightThis = Count0 + Count1 - (Count0 > Count1 ? Count0 - Count1 : Count1 - Count0); + if ( WeightBest < WeightThis ) + { + WeightBest = WeightThis; + iVarBest = iVarThis; + } + } + if ( iVarBest == -1 ) + { + Gia_ManArePrintListUsed( p, List ); + printf( "Error: Best variable not found!!!\n" ); + } + assert( iVarBest != -1 ); + return iVarBest; +} + +/**Function************************************************************* + + Synopsis [Rebalances the tree when cubes exceed the limit.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManAreRebalance( Gia_ManAre_t * p, Gia_PtrAre_t * pRoot ) +{ + Gia_ObjAre_t * pNode; + Gia_StaAre_t * pCube; + Gia_PtrAre_t iCube, iNext; + assert( pRoot->nItem || pRoot->nPage ); + pNode = Gia_ManAreCreateObj( p ); + pNode->iVar = Gia_ManAreFindBestVar( p, *pRoot ); + for ( iCube = *pRoot, pCube = Gia_ManAreSta(p, iCube), iNext = pCube->iNext; + Gia_StaIsGood(p, pCube); + iCube = iNext, pCube = Gia_ManAreSta(p, iCube), iNext = pCube->iNext ) + { + if ( Gia_StaIsUnused(pCube) ) + continue; + if ( Gia_StaHasValue0(pCube, pNode->iVar) ) + pCube->iNext = pNode->F[0], pNode->F[0] = iCube, pNode->nStas0++; + else if ( Gia_StaHasValue1(pCube, pNode->iVar) ) + pCube->iNext = pNode->F[1], pNode->F[1] = iCube, pNode->nStas1++; + else + pCube->iNext = pNode->F[2], pNode->F[2] = iCube, pNode->nStas2++; + } + *pRoot = Gia_Int2Ptr(p->nObjs - 1); + assert( pNode == Gia_ManAreObj(p, *pRoot) ); + p->fTree = 1; +} + +/**Function************************************************************* + + Synopsis [Compresses the list by removing unused cubes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManAreCompress( Gia_ManAre_t * p, Gia_PtrAre_t * pRoot ) +{ + Gia_StaAre_t * pCube; + Gia_PtrAre_t iList = *pRoot; + Gia_PtrAre_t iCube, iNext; + assert( pRoot->nItem || pRoot->nPage ); + pRoot->nItem = 0; + pRoot->nPage = 0; + for ( iCube = iList, pCube = Gia_ManAreSta(p, iCube), iNext = pCube->iNext; + Gia_StaIsGood(p, pCube); + iCube = iNext, pCube = Gia_ManAreSta(p, iCube), iNext = pCube->iNext ) + { + if ( Gia_StaIsUnused(pCube) ) + continue; + pCube->iNext = *pRoot; + *pRoot = iCube; + } +} + + +/**Function************************************************************* + + Synopsis [Checks if the state exists in the list.] + + Description [The state may be sharped.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManAreCubeCheckList( Gia_ManAre_t * p, Gia_PtrAre_t * pRoot, Gia_StaAre_t * pSta ) +{ + int fVerbose = 0; + Gia_StaAre_t * pCube; + int iVar; +if ( fVerbose ) +{ +printf( "Trying cube: " ); +Gia_ManArePrintCube( p, pSta ); +} + Gia_ManAreForEachCubeList( p, Gia_ManAreSta(p, *pRoot), pCube ) + { + p->nChecks++; + if ( Gia_StaIsUnused( pCube ) ) + continue; + if ( Gia_StaAreDisjoint( pSta, pCube, p->nWords ) ) + continue; + if ( Gia_StaAreContain( pCube, pSta, p->nWords ) ) + { +if ( fVerbose ) +{ +printf( "Contained in " ); +Gia_ManArePrintCube( p, pCube ); +} + Gia_ManAreRycycleSta( p, pSta ); + return 0; + } + if ( Gia_StaAreContain( pSta, pCube, p->nWords ) ) + { +if ( fVerbose ) +{ +printf( "Contains " ); +Gia_ManArePrintCube( p, pCube ); +} + Gia_StaSetUnused( pCube ); + continue; + } + iVar = Gia_StaAreSharpVar( pSta, pCube, p->nWords ); + if ( iVar == -1 ) + continue; +if ( fVerbose ) +{ +printf( "Sharped by " ); +Gia_ManArePrintCube( p, pCube ); +Gia_ManArePrintCube( p, pSta ); +} +// printf( "%d %d\n", Gia_StaAreDashNum( pSta, pCube, p->nWords ), Gia_StaAreSharpVar( pSta, pCube, p->nWords ) ); + assert( !Gia_StaHasValue0(pSta, iVar) && !Gia_StaHasValue1(pSta, iVar) ); + assert( Gia_StaHasValue0(pCube, iVar) ^ Gia_StaHasValue1(pCube, iVar) ); + if ( Gia_StaHasValue0(pCube, iVar) ) + Gia_StaSetValue1( pSta, iVar ); + else + Gia_StaSetValue0( pSta, iVar ); +// return Gia_ManAreCubeCheckList( p, pRoot, pSta ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Adds new state to the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManAreCubeAddToList( Gia_ManAre_t * p, Gia_PtrAre_t * pRoot, Gia_StaAre_t * pSta ) +{ + int fVerbose = 0; + pSta->iNext = *pRoot; + *pRoot = Gia_Int2Ptr( p->nStas - 1 ); + assert( pSta == Gia_ManAreSta(p, *pRoot) ); +if ( fVerbose ) +{ +printf( "Adding cube: " ); +Gia_ManArePrintCube( p, pSta ); +//printf( "\n" ); +} +} + +/**Function************************************************************* + + Synopsis [Checks if the cube like this exists in the tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManAreCubeCheckTree_rec( Gia_ManAre_t * p, Gia_ObjAre_t * pObj, Gia_StaAre_t * pSta ) +{ + int RetValue; + if ( Gia_StaHasValue0(pSta, pObj->iVar) ) + { + if ( Gia_ObjHasBranch0(pObj) ) + RetValue = Gia_ManAreCubeCheckTree_rec( p, Gia_ObjNextObj0(p, pObj), pSta ); + else + RetValue = Gia_ManAreCubeCheckList( p, pObj->F, pSta ); + if ( RetValue == 0 ) + return 0; + } + else if ( Gia_StaHasValue1(pSta, pObj->iVar) ) + { + if ( Gia_ObjHasBranch1(pObj) ) + RetValue = Gia_ManAreCubeCheckTree_rec( p, Gia_ObjNextObj1(p, pObj), pSta ); + else + RetValue = Gia_ManAreCubeCheckList( p, pObj->F + 1, pSta ); + if ( RetValue == 0 ) + return 0; + } + if ( Gia_ObjHasBranch2(pObj) ) + return Gia_ManAreCubeCheckTree_rec( p, Gia_ObjNextObj2(p, pObj), pSta ); + return Gia_ManAreCubeCheckList( p, pObj->F + 2, pSta ); +} + +/**Function************************************************************* + + Synopsis [Adds new cube to the tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManAreCubeAddToTree_rec( Gia_ManAre_t * p, Gia_ObjAre_t * pObj, Gia_StaAre_t * pSta ) +{ + if ( Gia_StaHasValue0(pSta, pObj->iVar) ) + { + if ( Gia_ObjHasBranch0(pObj) ) + Gia_ManAreCubeAddToTree_rec( p, Gia_ObjNextObj0(p, pObj), pSta ); + else + { + Gia_ManAreCubeAddToList( p, pObj->F, pSta ); + if ( ++pObj->nStas0 == MAX_CUBE_NUM ) + { + pObj->nStas0 = Gia_ManAreListCountListUsed( p, pObj->F[0] ); + if ( pObj->nStas0 < MAX_CUBE_NUM/2 ) + Gia_ManAreCompress( p, pObj->F ); + else + { + Gia_ManAreRebalance( p, pObj->F ); + pObj->nStas0 = 0; + } + } + } + } + else if ( Gia_StaHasValue1(pSta, pObj->iVar) ) + { + if ( Gia_ObjHasBranch1(pObj) ) + Gia_ManAreCubeAddToTree_rec( p, Gia_ObjNextObj1(p, pObj), pSta ); + else + { + Gia_ManAreCubeAddToList( p, pObj->F+1, pSta ); + if ( ++pObj->nStas1 == MAX_CUBE_NUM ) + { + pObj->nStas1 = Gia_ManAreListCountListUsed( p, pObj->F[1] ); + if ( pObj->nStas1 < MAX_CUBE_NUM/2 ) + Gia_ManAreCompress( p, pObj->F+1 ); + else + { + Gia_ManAreRebalance( p, pObj->F+1 ); + pObj->nStas1 = 0; + } + } + } + } + else + { + if ( Gia_ObjHasBranch2(pObj) ) + Gia_ManAreCubeAddToTree_rec( p, Gia_ObjNextObj2(p, pObj), pSta ); + else + { + Gia_ManAreCubeAddToList( p, pObj->F+2, pSta ); + if ( ++pObj->nStas2 == MAX_CUBE_NUM ) + { + pObj->nStas2 = Gia_ManAreListCountListUsed( p, pObj->F[2] ); + if ( pObj->nStas2 < MAX_CUBE_NUM/2 ) + Gia_ManAreCompress( p, pObj->F+2 ); + else + { + Gia_ManAreRebalance( p, pObj->F+2 ); + pObj->nStas2 = 0; + } + } + } + } +} + + + +/**Function************************************************************* + + Synopsis [Collects overlapping cubes in the list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManAreCubeCollectList( Gia_ManAre_t * p, Gia_PtrAre_t * pRoot, Gia_StaAre_t * pSta ) +{ + Gia_StaAre_t * pCube; + int iCube; + Gia_ManAreForEachCubeList2( p, *pRoot, pCube, iCube ) + { + if ( Gia_StaIsUnused( pCube ) ) + continue; + if ( Gia_StaAreDisjoint( pSta, pCube, p->nWords ) ) + { +/* + int iVar; + p->nDisjs++; + iVar = Gia_StaAreDisjointVar( pSta, pCube, p->nWords ); + if ( iVar >= 0 ) + { + p->nDisjs2++; + if ( iCube > p->iStaCur ) + p->nDisjs3++; + } +*/ + continue; + } +// p->nCompares++; +// p->nEquals += Gia_StaAreEqual( pSta, pCube, p->nWords ); + if ( iCube <= p->iStaCur ) + Vec_IntPush( p->vCubesA, iCube ); + else + Vec_IntPush( p->vCubesB, iCube ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Collects overlapping cubes in the tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManAreCubeCollectTree_rec( Gia_ManAre_t * p, Gia_ObjAre_t * pObj, Gia_StaAre_t * pSta ) +{ + int RetValue; + if ( Gia_StaHasValue0(pSta, pObj->iVar) ) + { + if ( Gia_ObjHasBranch0(pObj) ) + RetValue = Gia_ManAreCubeCollectTree_rec( p, Gia_ObjNextObj0(p, pObj), pSta ); + else + RetValue = Gia_ManAreCubeCollectList( p, pObj->F, pSta ); + if ( RetValue == 0 ) + return 0; + } + else if ( Gia_StaHasValue1(pSta, pObj->iVar) ) + { + if ( Gia_ObjHasBranch1(pObj) ) + RetValue = Gia_ManAreCubeCollectTree_rec( p, Gia_ObjNextObj1(p, pObj), pSta ); + else + RetValue = Gia_ManAreCubeCollectList( p, pObj->F + 1, pSta ); + if ( RetValue == 0 ) + return 0; + } + if ( Gia_ObjHasBranch2(pObj) ) + return Gia_ManAreCubeCollectTree_rec( p, Gia_ObjNextObj2(p, pObj), pSta ); + return Gia_ManAreCubeCollectList( p, pObj->F + 2, pSta ); +} + +/**Function************************************************************* + + Synopsis [Checks if the cube like this exists in the tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManAreCubeCheckTree( Gia_ManAre_t * p, Gia_StaAre_t * pSta ) +{ + Gia_StaAre_t * pCube; + int i, iVar; + assert( p->fTree ); + Vec_IntClear( p->vCubesA ); + Vec_IntClear( p->vCubesB ); + Gia_ManAreCubeCollectTree_rec( p, Gia_ManAreObj(p, p->Root), pSta ); +// if ( p->nStas > 3000 ) +// printf( "%d %d \n", Vec_IntSize(p->vCubesA), Vec_IntSize(p->vCubesB) ); +// Vec_IntSort( p->vCubesA, 0 ); +// Vec_IntSort( p->vCubesB, 0 ); + Gia_ManAreForEachCubeVec( p->vCubesA, p, pCube, i ) + { + if ( Gia_StaIsUnused( pCube ) ) + continue; + if ( Gia_StaAreDisjoint( pSta, pCube, p->nWords ) ) + continue; + if ( Gia_StaAreContain( pCube, pSta, p->nWords ) ) + { + Gia_ManAreRycycleSta( p, pSta ); + return 0; + } + if ( Gia_StaAreContain( pSta, pCube, p->nWords ) ) + { + Gia_StaSetUnused( pCube ); + continue; + } + iVar = Gia_StaAreSharpVar( pSta, pCube, p->nWords ); + if ( iVar == -1 ) + continue; + assert( !Gia_StaHasValue0(pSta, iVar) && !Gia_StaHasValue1(pSta, iVar) ); + assert( Gia_StaHasValue0(pCube, iVar) ^ Gia_StaHasValue1(pCube, iVar) ); + if ( Gia_StaHasValue0(pCube, iVar) ) + Gia_StaSetValue1( pSta, iVar ); + else + Gia_StaSetValue0( pSta, iVar ); + return Gia_ManAreCubeCheckTree( p, pSta ); + } + Gia_ManAreForEachCubeVec( p->vCubesB, p, pCube, i ) + { + if ( Gia_StaIsUnused( pCube ) ) + continue; + if ( Gia_StaAreDisjoint( pSta, pCube, p->nWords ) ) + continue; + if ( Gia_StaAreContain( pCube, pSta, p->nWords ) ) + { + Gia_ManAreRycycleSta( p, pSta ); + return 0; + } + if ( Gia_StaAreContain( pSta, pCube, p->nWords ) ) + { + Gia_StaSetUnused( pCube ); + continue; + } + iVar = Gia_StaAreSharpVar( pSta, pCube, p->nWords ); + if ( iVar == -1 ) + continue; + assert( !Gia_StaHasValue0(pSta, iVar) && !Gia_StaHasValue1(pSta, iVar) ); + assert( Gia_StaHasValue0(pCube, iVar) ^ Gia_StaHasValue1(pCube, iVar) ); + if ( Gia_StaHasValue0(pCube, iVar) ) + Gia_StaSetValue1( pSta, iVar ); + else + Gia_StaSetValue0( pSta, iVar ); + return Gia_ManAreCubeCheckTree( p, pSta ); + } +/* + if ( p->nStas > 3000 ) + { +printf( "Trying cube: " ); +Gia_ManArePrintCube( p, pSta ); + Gia_ManAreForEachCubeVec( p->vCubesA, p, pCube, i ) + { +printf( "aaaaaaaaaaaa %5d ", Vec_IntEntry(p->vCubesA,i) ); +Gia_ManArePrintCube( p, pCube ); + } + Gia_ManAreForEachCubeVec( p->vCubesB, p, pCube, i ) + { +printf( "bbbbbbbbbbbb %5d ", Vec_IntEntry(p->vCubesB,i) ); +Gia_ManArePrintCube( p, pCube ); + } + } +*/ + return 1; +} + +/**Function************************************************************* + + Synopsis [Processes the new cube.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManAreCubeProcess( Gia_ManAre_t * p, Gia_StaAre_t * pSta ) +{ + int RetValue; + p->nChecks = 0; + if ( !p->fTree && p->nStas == MAX_CUBE_NUM ) + Gia_ManAreRebalance( p, &p->Root ); + if ( p->fTree ) + { +// RetValue = Gia_ManAreCubeCheckTree_rec( p, Gia_ManAreObj(p, p->Root), pSta ); + RetValue = Gia_ManAreCubeCheckTree( p, pSta ); + if ( RetValue ) + Gia_ManAreCubeAddToTree_rec( p, Gia_ManAreObj(p, p->Root), pSta ); + } + else + { + RetValue = Gia_ManAreCubeCheckList( p, &p->Root, pSta ); + if ( RetValue ) + Gia_ManAreCubeAddToList( p, &p->Root, pSta ); + } +// printf( "%d ", p->nChecks ); + return RetValue; +} + + +/**Function************************************************************* + + Synopsis [Returns the most used CI, or NULL if condition is met.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManAreMostUsedPi_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( Gia_ObjIsCi(pObj) ) + { + pObj->Value++; + return; + } + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManAreMostUsedPi_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ManAreMostUsedPi_rec( p, Gia_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Returns the most used CI, or NULL if condition is met.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * Gia_ManAreMostUsedPi( Gia_ManAre_t * p ) +{ + Gia_Obj_t * pObj, * pObjMax = NULL; + int i; + // clean CI counters + Gia_ManForEachCi( p->pNew, pObj, i ) + pObj->Value = 0; + // traverse from each register output + Gia_ManForEachRi( p->pAig, pObj, i ) + { + if ( pObj->Value <= 1 ) + continue; + Gia_ManIncrementTravId( p->pNew ); + Gia_ManAreMostUsedPi_rec( p->pNew, Gia_ManObj(p->pNew, Abc_Lit2Var(pObj->Value)) ); + } + // check the CI counters + Gia_ManForEachCi( p->pNew, pObj, i ) + if ( pObjMax == NULL || pObjMax->Value < pObj->Value ) + pObjMax = pObj; + // return the result + return pObjMax->Value > 1 ? pObjMax : NULL; +} + +/**Function************************************************************* + + Synopsis [Counts maximum support of primary outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCheckPOs_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return 0; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( Gia_ObjIsCi(pObj) ) + return 1; + assert( Gia_ObjIsAnd(pObj) ); + return Gia_ManCheckPOs_rec( p, Gia_ObjFanin0(pObj) ) + + Gia_ManCheckPOs_rec( p, Gia_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Counts maximum support of primary outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManCheckPOs( Gia_ManAre_t * p ) +{ + Gia_Obj_t * pObj, * pObjNew; + int i, CountCur, CountMax = 0; + Gia_ManForEachPo( p->pAig, pObj, i ) + { + pObjNew = Gia_ManObj( p->pNew, Abc_Lit2Var(pObj->Value) ); + if ( Gia_ObjIsConst0(pObjNew) ) + CountCur = 0; + else + { + Gia_ManIncrementTravId( p->pNew ); + CountCur = Gia_ManCheckPOs_rec( p->pNew, pObjNew ); + } + CountMax = Abc_MaxInt( CountMax, CountCur ); + } + return CountMax; +} + +/**Function************************************************************* + + Synopsis [Returns the status of the primary outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManCheckPOstatus( Gia_ManAre_t * p ) +{ + Gia_Obj_t * pObj, * pObjNew; + int i; + Gia_ManForEachPo( p->pAig, pObj, i ) + { + pObjNew = Gia_ManObj( p->pNew, Abc_Lit2Var(pObj->Value) ); + if ( Gia_ObjIsConst0(pObjNew) ) + { + if ( Abc_LitIsCompl(pObj->Value) ) + { + p->iOutFail = i; + return 1; + } + } + else + { + p->iOutFail = i; +// printf( "To fix later: PO may be assertable.\n" ); + return 1; + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Derives next state cubes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManAreDeriveNexts_rec( Gia_ManAre_t * p, Gia_PtrAre_t Sta ) +{ + Gia_Obj_t * pPivot; + Vec_Int_t * vLits, * vTfos; + Gia_Obj_t * pObj; + int i; + abctime clk; + if ( ++p->nRecCalls == MAX_CALL_NUM ) + return 0; + if ( (pPivot = Gia_ManAreMostUsedPi(p)) == NULL ) + { + Gia_StaAre_t * pNew; + clk = Abc_Clock(); + pNew = Gia_ManAreCreateStaNew( p ); + pNew->iPrev = Sta; + p->fStopped = (p->fMiter && (Gia_ManCheckPOstatus(p) & 1)); + if ( p->fStopped ) + { + assert( p->pTarget == NULL ); + p->pTarget = pNew; + return 1; + } + Gia_ManAreCubeProcess( p, pNew ); + p->timeCube += Abc_Clock() - clk; + return p->fStopped; + } + // remember values in the cone and perform update + vTfos = Vec_VecEntryInt( p->vCiTfos, Gia_ObjCioId(pPivot) ); + vLits = Vec_VecEntryInt( p->vCiLits, Gia_ObjCioId(pPivot) ); + assert( Vec_IntSize(vTfos) == Vec_IntSize(vLits) ); + Gia_ManForEachObjVec( vTfos, p->pAig, pObj, i ) + { + Vec_IntWriteEntry( vLits, i, pObj->Value ); + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( p->pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + else + { + assert( Gia_ObjIsCi(pObj) ); + pObj->Value = 0; + } + } + if ( Gia_ManAreDeriveNexts_rec( p, Sta ) ) + return 1; + // compute different values + Gia_ManForEachObjVec( vTfos, p->pAig, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( p->pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + else + { + assert( Gia_ObjIsCi(pObj) ); + pObj->Value = 1; + } + } + if ( Gia_ManAreDeriveNexts_rec( p, Sta ) ) + return 1; + // reset the original values + Gia_ManForEachObjVec( vTfos, p->pAig, pObj, i ) + pObj->Value = Vec_IntEntry( vLits, i ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Derives next state cubes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManAreDeriveNexts( Gia_ManAre_t * p, Gia_PtrAre_t Sta ) +{ + Gia_StaAre_t * pSta; + Gia_Obj_t * pObj; + int i, RetValue; + abctime clk = Abc_Clock(); + pSta = Gia_ManAreSta( p, Sta ); + if ( Gia_StaIsUnused(pSta) ) + return 0; + // recycle the manager + if ( p->pNew && Gia_ManObjNum(p->pNew) > 1000000 ) + { + Gia_ManStop( p->pNew ); + p->pNew = NULL; + } + // allocate the manager + if ( p->pNew == NULL ) + { + p->pNew = Gia_ManStart( 10 * Gia_ManObjNum(p->pAig) ); + Gia_ManIncrementTravId( p->pNew ); + Gia_ManHashAlloc( p->pNew ); + Gia_ManConst0(p->pAig)->Value = 0; + Gia_ManForEachCi( p->pAig, pObj, i ) + pObj->Value = Gia_ManAppendCi(p->pNew); + } + Gia_ManForEachRo( p->pAig, pObj, i ) + { + if ( Gia_StaHasValue0( pSta, i ) ) + pObj->Value = 0; + else if ( Gia_StaHasValue1( pSta, i ) ) + pObj->Value = 1; + else // don't-care literal + pObj->Value = Abc_Var2Lit( Gia_ObjId( p->pNew, Gia_ManCi(p->pNew, Gia_ObjCioId(pObj)) ), 0 ); + } + Gia_ManForEachAnd( p->pAig, pObj, i ) + pObj->Value = Gia_ManHashAnd( p->pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p->pAig, pObj, i ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + + // perform case-splitting + p->nRecCalls = 0; + RetValue = Gia_ManAreDeriveNexts_rec( p, Sta ); + if ( p->nRecCalls >= MAX_CALL_NUM ) + { + printf( "Exceeded the limit on the number of transitions from a state cube (%d).\n", MAX_CALL_NUM ); + p->fStopped = 1; + } +// printf( "%d ", p->nRecCalls ); +//printf( "%d ", Gia_ManObjNum(p->pNew) ); + p->timeAig += Abc_Clock() - clk; + return RetValue; +} + + +/**Function************************************************************* + + Synopsis [Prints the report] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManArePrintReport( Gia_ManAre_t * p, abctime Time, int fFinal ) +{ + printf( "States =%10d. Reached =%10d. R = %5.3f. Depth =%6d. Mem =%9.2f MB. ", + p->iStaCur, p->nStas, 1.0*p->iStaCur/p->nStas, Gia_ManAreDepth(p, p->iStaCur), + (sizeof(Gia_ManAre_t) + 4.0*Gia_ManRegNum(p->pAig) + 8.0*MAX_PAGE_NUM + + 4.0*p->nStaPages*p->nSize*MAX_ITEM_NUM + 16.0*p->nObjPages*MAX_ITEM_NUM)/(1<<20) ); + if ( fFinal ) + { + ABC_PRT( "Time", Abc_Clock() - Time ); + } + else + { + ABC_PRTr( "Time", Abc_Clock() - Time ); + } +} + +/**Function************************************************************* + + Synopsis [Performs explicit reachability.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManArePerform( Gia_Man_t * pAig, int nStatesMax, int fMiter, int fVerbose ) +{ +// extern Gia_Man_t * Gia_ManCompress2( Gia_Man_t * p, int fUpdateLevel, int fVerbose ); + extern Abc_Cex_t * Gia_ManAreDeriveCex( Gia_ManAre_t * p, Gia_StaAre_t * pLast ); + Gia_ManAre_t * p; + abctime clk = Abc_Clock(); + int RetValue = 1; + if ( Gia_ManRegNum(pAig) > MAX_VARS_NUM ) + { + printf( "Currently can only handle circuit with up to %d registers.\n", MAX_VARS_NUM ); + return -1; + } + ABC_FREE( pAig->pCexSeq ); +// p = Gia_ManAreCreate( Gia_ManCompress2(pAig, 0, 0) ); + p = Gia_ManAreCreate( Gia_ManDup(pAig) ); + p->fMiter = fMiter; + Gia_ManAreCubeProcess( p, Gia_ManAreCreateStaInit(p) ); + for ( p->iStaCur = 1; p->iStaCur < p->nStas; p->iStaCur++ ) + { +// printf( "Explored state %d. Total cubes %d.\n", p->iStaCur, p->nStas-1 ); + if ( Gia_ManAreDeriveNexts( p, Gia_Int2Ptr(p->iStaCur) ) || p->nStas > nStatesMax ) + pAig->pCexSeq = Gia_ManAreDeriveCex( p, p->pTarget ); + if ( p->fStopped ) + { + RetValue = -1; + break; + } + if ( fVerbose )//&& p->iStaCur % 5000 == 0 ) + Gia_ManArePrintReport( p, clk, 0 ); + } + Gia_ManArePrintReport( p, clk, 1 ); + printf( "%s after finding %d state cubes (%d not contained) with depth %d. ", + p->fStopped ? "Stopped" : "Completed", + p->nStas, Gia_ManAreListCountUsed(p), + Gia_ManAreDepth(p, p->iStaCur-1) ); + ABC_PRT( "Time", Abc_Clock() - clk ); + if ( pAig->pCexSeq != NULL ) + Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d.\n", + p->iStaCur, pAig->pName, Gia_ManAreDepth(p, p->iStaCur)-1 ); + if ( fVerbose ) + { + ABC_PRTP( "Cofactoring", p->timeAig - p->timeCube, Abc_Clock() - clk ); + ABC_PRTP( "Containment", p->timeCube, Abc_Clock() - clk ); + ABC_PRTP( "Other ", Abc_Clock() - clk - p->timeAig, Abc_Clock() - clk ); + ABC_PRTP( "TOTAL ", Abc_Clock() - clk, Abc_Clock() - clk ); + } + if ( Gia_ManRegNum(pAig) <= 30 ) + { + clk = Abc_Clock(); + printf( "The number of unique state minterms in computed state cubes is %d. ", Gia_ManCountMinterms(p) ); + ABC_PRT( "Time", Abc_Clock() - clk ); + } +// printf( "Compares = %d. Equals = %d. Disj = %d. Disj2 = %d. Disj3 = %d.\n", +// p->nCompares, p->nEquals, p->nDisjs, p->nDisjs2, p->nDisjs3 ); +// Gia_ManAreFindBestVar( p, Gia_ManAreSta(p, p->Root) ); +// Gia_ManArePrintUsed( p ); + Gia_ManAreFree( p ); + // verify + if ( pAig->pCexSeq ) + { + if ( !Gia_ManVerifyCex( pAig, pAig->pCexSeq, 0 ) ) + printf( "Generated counter-example is INVALID. \n" ); + else + printf( "Generated counter-example verified correctly. \n" ); + return 0; + } + return RetValue; +} + +ABC_NAMESPACE_IMPL_END + +#include "giaAig.h" +#include "sat/cnf/cnf.h" +#include "sat/bsat/satSolver.h" + +ABC_NAMESPACE_IMPL_START + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManAreDeriveCexSatStart( Gia_ManAre_t * p ) +{ + Aig_Man_t * pAig2; + Cnf_Dat_t * pCnf; + assert( p->pSat == NULL ); + pAig2 = Gia_ManToAig( p->pAig, 0 ); + Aig_ManSetRegNum( pAig2, 0 ); + pCnf = Cnf_Derive( pAig2, Gia_ManCoNum(p->pAig) ); + p->pSat = Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + p->vSatNumCis = Cnf_DataCollectCiSatNums( pCnf, pAig2 ); + p->vSatNumCos = Cnf_DataCollectCoSatNums( pCnf, pAig2 ); + Cnf_DataFree( pCnf ); + Aig_ManStop( pAig2 ); + p->vAssumps = Vec_IntAlloc( 100 ); + p->vCofVars = Vec_IntAlloc( 100 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManAreDeriveCexSatStop( Gia_ManAre_t * p ) +{ + assert( p->pSat != NULL ); + assert( p->pTarget != NULL ); + sat_solver_delete( (sat_solver *)p->pSat ); + Vec_IntFree( p->vSatNumCis ); + Vec_IntFree( p->vSatNumCos ); + Vec_IntFree( p->vAssumps ); + Vec_IntFree( p->vCofVars ); + p->pTarget = NULL; + p->pSat = NULL; +} + +/**Function************************************************************* + + Synopsis [Computes satisfying assignment in one timeframe.] + + Description [Returns the vector of integers represeting PIO ids + of the primary inputs that should be 1 in the counter-example.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManAreDeriveCexSat( Gia_ManAre_t * p, Gia_StaAre_t * pCur, Gia_StaAre_t * pNext, int iOutFailed ) +{ + int i, status; + // make assuptions + Vec_IntClear( p->vAssumps ); + for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) + { + if ( Gia_StaHasValue0(pCur, i) ) + Vec_IntPush( p->vAssumps, Abc_Var2Lit( Vec_IntEntry(p->vSatNumCis, Gia_ManPiNum(p->pAig)+i), 1 ) ); + else if ( Gia_StaHasValue1(pCur, i) ) + Vec_IntPush( p->vAssumps, Abc_Var2Lit( Vec_IntEntry(p->vSatNumCis, Gia_ManPiNum(p->pAig)+i), 0 ) ); + } + if ( pNext ) + for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) + { + if ( Gia_StaHasValue0(pNext, i) ) + Vec_IntPush( p->vAssumps, Abc_Var2Lit( Vec_IntEntry(p->vSatNumCos, Gia_ManPoNum(p->pAig)+i), 1 ) ); + else if ( Gia_StaHasValue1(pNext, i) ) + Vec_IntPush( p->vAssumps, Abc_Var2Lit( Vec_IntEntry(p->vSatNumCos, Gia_ManPoNum(p->pAig)+i), 0 ) ); + } + if ( iOutFailed >= 0 ) + { + assert( iOutFailed < Gia_ManPoNum(p->pAig) ); + Vec_IntPush( p->vAssumps, Abc_Var2Lit( Vec_IntEntry(p->vSatNumCos, iOutFailed), 0 ) ); + } + // solve SAT + status = sat_solver_solve( (sat_solver *)p->pSat, (int *)Vec_IntArray(p->vAssumps), (int *)Vec_IntArray(p->vAssumps) + Vec_IntSize(p->vAssumps), + (ABC_INT64_T)1000000, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + if ( status != l_True ) + { + printf( "SAT problem is not satisfiable. Failure...\n" ); + return; + } + assert( status == l_True ); + // check the model + Vec_IntClear( p->vCofVars ); + for ( i = 0; i < Gia_ManPiNum(p->pAig); i++ ) + { + if ( sat_solver_var_value( (sat_solver *)p->pSat, Vec_IntEntry(p->vSatNumCis, i) ) ) + Vec_IntPush( p->vCofVars, i ); + } + // write the current state + for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) + { + if ( Gia_StaHasValue0(pCur, i) ) + assert( sat_solver_var_value( (sat_solver *)p->pSat, Vec_IntEntry(p->vSatNumCis, Gia_ManPiNum(p->pAig)+i) ) == 0 ); + else if ( Gia_StaHasValue1(pCur, i) ) + assert( sat_solver_var_value( (sat_solver *)p->pSat, Vec_IntEntry(p->vSatNumCis, Gia_ManPiNum(p->pAig)+i) ) == 1 ); + // set don't-care value + if ( sat_solver_var_value( (sat_solver *)p->pSat, Vec_IntEntry(p->vSatNumCis, Gia_ManPiNum(p->pAig)+i) ) == 0 ) + Gia_StaSetValue0( pCur, i ); + else + Gia_StaSetValue1( pCur, i ); + } +} + +/**Function************************************************************* + + Synopsis [Returns the status of the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Gia_ManAreDeriveCex( Gia_ManAre_t * p, Gia_StaAre_t * pLast ) +{ + Abc_Cex_t * pCex; + Vec_Ptr_t * vStates; + Gia_StaAre_t * pSta, * pPrev; + int Var, i, v; + assert( p->iOutFail >= 0 ); + Gia_ManAreDeriveCexSatStart( p ); + // compute the trace + vStates = Vec_PtrAlloc( 1000 ); + for ( pSta = pLast; Gia_StaIsGood(p, pSta); pSta = Gia_StaPrev(p, pSta) ) + if ( pSta != pLast ) + Vec_PtrPush( vStates, pSta ); + assert( Vec_PtrSize(vStates) >= 1 ); + // start the counter-example + pCex = Abc_CexAlloc( Gia_ManRegNum(p->pAig), Gia_ManPiNum(p->pAig), Vec_PtrSize(vStates) ); + pCex->iFrame = Vec_PtrSize(vStates)-1; + pCex->iPo = p->iOutFail; + // compute states + pPrev = NULL; + Vec_PtrForEachEntry( Gia_StaAre_t *, vStates, pSta, i ) + { + Gia_ManAreDeriveCexSat( p, pSta, pPrev, (i == 0) ? p->iOutFail : -1 ); + pPrev = pSta; + // create the counter-example + Vec_IntForEachEntry( p->vCofVars, Var, v ) + { + assert( Var < Gia_ManPiNum(p->pAig) ); + Abc_InfoSetBit( pCex->pData, Gia_ManRegNum(p->pAig) + (Vec_PtrSize(vStates)-1-i) * Gia_ManPiNum(p->pAig) + Var ); + } + } + // free temporary things + Vec_PtrFree( vStates ); + Gia_ManAreDeriveCexSatStop( p ); + return pCex; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaEsop.c b/yosys/abc/src/aig/gia/giaEsop.c new file mode 100644 index 00000000000..a819bc20ab5 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaEsop.c @@ -0,0 +1,541 @@ +/**CFile**************************************************************** + + FileName [giaEsop.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [ESOP computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaEsop.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/extra/extra.h" +#include "misc/vec/vecHsh.h" +#include "misc/vec/vecWec.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Eso_Man_t_ Eso_Man_t; +struct Eso_Man_t_ +{ + Gia_Man_t * pGia; // user's AIG + int nVars; // number of variables + int Cube1; // ID of const1 cube + Vec_Wec_t * vEsops; // ESOP for each node + Hsh_VecMan_t * pHash; // hash table for cubes + Vec_Wec_t * vCubes; // cover during minimization + // internal + Vec_Int_t * vCube1; // first cube + Vec_Int_t * vCube2; // second cube + Vec_Int_t * vCube; // resulting cube +}; + +static inline Vec_Int_t * Eso_ManCube( Eso_Man_t * p, int iCube ) { assert( iCube >= 0 ); return Hsh_VecReadEntry(p->pHash, iCube); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Eso_Man_t * Eso_ManAlloc( Gia_Man_t * pGia ) +{ + int i, n, Id; + Eso_Man_t * p = ABC_CALLOC( Eso_Man_t, 1 ); + p->pGia = pGia; + p->nVars = Gia_ManCiNum(pGia); + p->Cube1 = ABC_INFINITY; + p->vEsops = Vec_WecStart( Gia_ManObjNum(pGia) ); + p->pHash = Hsh_VecManStart( 1000 ); + p->vCubes = Vec_WecStart(Gia_ManCiNum(pGia)+1); + p->vCube1 = Vec_IntAlloc(Gia_ManCiNum(pGia)); + p->vCube2 = Vec_IntAlloc(Gia_ManCiNum(pGia)); + p->vCube = Vec_IntAlloc(Gia_ManCiNum(pGia)); + Gia_ManForEachCiId( pGia, Id, i ) + { + for ( n = 0; n < 2; n++ ) + { + Vec_IntFill( p->vCube, 1, Abc_Var2Lit(i, n) ); + Hsh_VecManAdd( p->pHash, p->vCube ); + } + Vec_IntPush( Vec_WecEntry(p->vEsops, Id), Abc_Var2Lit(i, 0) ); + } + return p; +} +void Eso_ManStop( Eso_Man_t * p ) +{ + Vec_WecFree( p->vEsops ); + Hsh_VecManStop( p->pHash ); + Vec_WecFree( p->vCubes ); + Vec_IntFree( p->vCube1 ); + Vec_IntFree( p->vCube2 ); + Vec_IntFree( p->vCube ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [Printing/transforming the cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Eso_ManCoverPrint( Eso_Man_t * p, Vec_Int_t * vEsop ) +{ + Vec_Str_t * vStr; + Vec_Int_t * vCube; + int i, k, Lit, Cube; + if ( Vec_IntSize(vEsop) == 0 ) + { + printf( "Const 0\n" ); + return; + } + vStr = Vec_StrAlloc( p->nVars + 4 ); + Vec_StrFill( vStr, p->nVars, '-' ); + Vec_StrPush( vStr, ' ' ); + Vec_StrPush( vStr, '1' ); + Vec_StrPush( vStr, '\n' ); + Vec_StrPush( vStr, '\0' ); + assert( Vec_IntSize(vEsop) > 0 ); + Vec_IntForEachEntry( vEsop, Cube, i ) + { + if ( Cube == p->Cube1 ) + printf( "%s", Vec_StrArray(vStr) ); + else + { + vCube = Eso_ManCube( p, Cube ); + Vec_IntForEachEntry( vCube, Lit, k ) + Vec_StrWriteEntry( vStr, Abc_Lit2Var(Lit), (char)(Abc_LitIsCompl(Lit)?'0':'1') ); + printf( "%s", Vec_StrArray(vStr) ); + Vec_IntForEachEntry( vCube, Lit, k ) + Vec_StrWriteEntry( vStr, Abc_Lit2Var(Lit), '-' ); + } + } + printf( "\n" ); + Vec_StrFree( vStr ); +} +Vec_Wec_t * Eso_ManCoverDerive( Eso_Man_t * p, Vec_Ptr_t * vCover ) +{ + Vec_Wec_t * vRes; + Vec_Int_t * vEsop, * vLevel; int i; + vRes = Vec_WecAlloc( Vec_VecSizeSize((Vec_Vec_t *)vCover) ); + Vec_PtrForEachEntry( Vec_Int_t *, vCover, vEsop, i ) + { + if ( Vec_IntSize(vEsop) > 0 ) + { + int c, Cube; + Vec_IntForEachEntry( vEsop, Cube, c ) + { + vLevel = Vec_WecPushLevel( vRes ); + if ( Cube != p->Cube1 ) + { + int k, Lit; + Vec_Int_t * vCube = Eso_ManCube( p, Cube ); + Vec_IntForEachEntry( vCube, Lit, k ) + Vec_IntPush( vLevel, Lit ); + } + Vec_IntPush( vLevel, -i-1 ); + } + } + } + //assert( Abc_MaxInt(Vec_WecSize(vRes), 8) == Vec_WecCap(vRes) ); + return vRes; +} +Gia_Man_t * Eso_ManCoverConvert( Eso_Man_t * p, Vec_Ptr_t * vCover ) +{ + Vec_Int_t * vEsop; + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; int i; + pNew = Gia_ManStart( Gia_ManObjNum(p->pGia) ); + pNew->pName = Abc_UtilStrsav( p->pGia->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pGia->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManConst0(p->pGia)->Value = 0; + Gia_ManForEachCi( p->pGia, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Vec_PtrForEachEntry( Vec_Int_t *, vCover, vEsop, i ) + { + if ( Vec_IntSize(vEsop) > 0 ) + { + int c, Cube, iRoot = 0; + Vec_IntForEachEntry( vEsop, Cube, c ) + { + int k, Lit, iAnd = 1; + if ( Cube != p->Cube1 ) + { + Vec_Int_t * vCube = Eso_ManCube( p, Cube ); + Vec_IntForEachEntry( vCube, Lit, k ) + iAnd = Gia_ManHashAnd( pNew, iAnd, Lit + 2 ); + } + iRoot = Gia_ManHashXor( pNew, iRoot, iAnd ); + } + Gia_ManAppendCo( pNew, iRoot ); + } + else + Gia_ManAppendCo( pNew, 0 ); + } + // cleanup + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Minimization.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Eso_ManFindDistOneLitEqual( int * pCube1, int * pCube2, int nLits ) // pCube1 and pCube2 both have nLits +{ + int i, iDiff = -1; + for ( i = 0; i < nLits; i++ ) + if ( pCube1[i] != pCube2[i] ) + { + if ( iDiff != -1 ) + return -1; + if ( Abc_Lit2Var(pCube1[i]) != Abc_Lit2Var(pCube2[i]) ) + return -1; + iDiff = i; + } + return iDiff; +} +int Eso_ManFindDistOneLitNotEqual( int * pCube1, int * pCube2, int nLits ) // pCube1 has nLits; pCube2 has nLits + 1 +{ + int i, k, iDiff = -1; + for ( i = k = 0; i < nLits; i++, k++ ) + if ( pCube1[i] != pCube2[k] ) + { + if ( iDiff != -1 ) + return -1; + iDiff = i; + i--; + } + if ( iDiff == -1 ) + iDiff = nLits; + return iDiff; +} +void Eso_ManMinimizeAdd( Eso_Man_t * p, int Cube ) +{ + int fMimimize = 1; + Vec_Int_t * vCube = (Cube == p->Cube1) ? NULL : Eso_ManCube(p, Cube); + int * pCube2, * pCube = (Cube == p->Cube1) ? NULL : Vec_IntArray(vCube); + int Cube2, nLits = (Cube == p->Cube1) ? 0 : Vec_IntSize(vCube); + Vec_Int_t * vLevel = Vec_WecEntry( p->vCubes, nLits ); + int c, k, iLit, iPlace = Vec_IntFind( vLevel, Cube ); + if ( iPlace >= 0 ) // identical found + { + Vec_IntDrop( vLevel, iPlace ); + return; + } + if ( Cube == p->Cube1 ) // simple case + { + assert( Vec_IntSize(vLevel) == 0 ); + Vec_IntPush( vLevel, Cube ); + return; + } + // look for distance-1 in next bin + if ( fMimimize && nLits < p->nVars - 1 ) + { + Vec_Int_t * vLevel = Vec_WecEntry( p->vCubes, nLits+1 ); + Vec_IntForEachEntry( vLevel, Cube2, c ) + { + pCube2 = Hsh_VecReadArray( p->pHash, Cube2 ); + iLit = Eso_ManFindDistOneLitNotEqual( pCube, pCube2, nLits ); + if ( iLit == -1 ) + continue; + // remove this cube + Vec_IntDrop( vLevel, c ); + // create new cube + Vec_IntClear( p->vCube ); + for ( k = 0; k <= nLits; k++ ) + Vec_IntPush( p->vCube, Abc_LitNotCond(pCube2[k], k == iLit) ); + Cube = Hsh_VecManAdd( p->pHash, p->vCube ); + // try to add new cube + Eso_ManMinimizeAdd( p, Cube ); + return; + } + } + // look for distance-1 in the same bin + if ( fMimimize ) + { + Vec_IntForEachEntry( vLevel, Cube2, c ) + { + pCube2 = Hsh_VecReadArray( p->pHash, Cube2 ); + iLit = Eso_ManFindDistOneLitEqual( pCube2, pCube, nLits ); + if ( iLit == -1 ) + continue; + // remove this cube + Vec_IntDrop( vLevel, c ); + // create new cube + Vec_IntClear( p->vCube ); + for ( k = 0; k < nLits; k++ ) + if ( k != iLit ) + Vec_IntPush( p->vCube, pCube[k] ); + if ( Vec_IntSize(p->vCube) == 0 ) + Cube = p->Cube1; + else + Cube = Hsh_VecManAdd( p->pHash, p->vCube ); + // try to add new cube + Eso_ManMinimizeAdd( p, Cube ); + return; + } + } + assert( nLits > 0 ); + if ( fMimimize && nLits > 0 ) + { + // look for distance-1 in the previous bin + Vec_Int_t * vLevel = Vec_WecEntry( p->vCubes, nLits-1 ); + // check for the case of one-literal cube + if ( nLits == 1 && Vec_IntSize(vLevel) == 1 ) + { + Vec_IntDrop( vLevel, 0 ); + Cube = Abc_LitNot( Cube ); + } + else + Vec_IntForEachEntry( vLevel, Cube2, c ) + { + pCube2 = Hsh_VecReadArray( p->pHash, Cube2 ); + iLit = Eso_ManFindDistOneLitNotEqual( pCube2, pCube, nLits-1 ); + if ( iLit == -1 ) + continue; + // remove this cube + Vec_IntDrop( vLevel, c ); + // create new cube + Vec_IntClear( p->vCube ); + for ( k = 0; k < nLits; k++ ) + Vec_IntPush( p->vCube, Abc_LitNotCond(pCube[k], k == iLit) ); + Cube = Hsh_VecManAdd( p->pHash, p->vCube ); + // try to add new cube + Eso_ManMinimizeAdd( p, Cube ); + return; + } + } + // could not find - simply add this cube + Vec_IntPush( vLevel, Cube ); +} + +void Eso_ManMinimizeCopy( Eso_Man_t * p, Vec_Int_t * vEsop ) +{ + Vec_Int_t * vLevel; + int i; + Vec_IntClear( vEsop ); + Vec_WecForEachLevel( p->vCubes, vLevel, i ) + { + Vec_IntAppend( vEsop, vLevel ); + if ( i > 0 ) + { + int k, Cube; + Vec_IntForEachEntry( vLevel, Cube, k ) + assert( Vec_IntSize(Eso_ManCube(p, Cube)) == i ); + } + Vec_IntClear( vLevel ); + } +} + +/**Function************************************************************* + + Synopsis [Compute the produce of two covers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Eso_ManComputeAnd( Eso_Man_t * p, Vec_Int_t * vCube1, Vec_Int_t * vCube2, Vec_Int_t * vCube ) +{ + int * pBeg = vCube->pArray; + int * pBeg1 = vCube1->pArray; + int * pBeg2 = vCube2->pArray; + int * pEnd1 = vCube1->pArray + vCube1->nSize; + int * pEnd2 = vCube2->pArray + vCube2->nSize; + while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) + { + if ( *pBeg1 == *pBeg2 ) + *pBeg++ = *pBeg1++, pBeg2++; + else if ( Abc_Lit2Var(*pBeg1) == Abc_Lit2Var(*pBeg2) ) + return -1; + else if ( *pBeg1 < *pBeg2 ) + *pBeg++ = *pBeg1++; + else + *pBeg++ = *pBeg2++; + } + while ( pBeg1 < pEnd1 ) + *pBeg++ = *pBeg1++; + while ( pBeg2 < pEnd2 ) + *pBeg++ = *pBeg2++; + vCube->nSize = pBeg - vCube->pArray; + assert( vCube->nSize <= vCube->nCap ); + assert( vCube->nSize >= vCube1->nSize ); + assert( vCube->nSize >= vCube2->nSize ); + return Hsh_VecManAdd( p->pHash, vCube ); +} +void Eso_ManComputeOne( Eso_Man_t * p, Vec_Int_t * vEsop1, Vec_Int_t * vEsop2, Vec_Int_t * vEsop ) +{ + Vec_Int_t vCube1, vCube2; + int i, k, Cube1, Cube2, Cube; + Vec_IntClear( vEsop ); + if ( Vec_IntSize(vEsop1) == 0 || Vec_IntSize(vEsop2) == 0 ) + return; + Cube1 = Vec_IntEntry(vEsop1, 0); + Cube2 = Vec_IntEntry(vEsop2, 0); + Vec_IntForEachEntry( vEsop1, Cube1, i ) + { + if ( Cube1 == p->Cube1 ) + { + Vec_IntForEachEntry( vEsop2, Cube2, k ) + Eso_ManMinimizeAdd( p, Cube2 ); + continue; + } + Vec_IntForEachEntry( vEsop2, Cube2, k ) + { + if ( Cube2 == p->Cube1 ) + { + Eso_ManMinimizeAdd( p, Cube1 ); + continue; + } + vCube1 = *Hsh_VecReadEntry( p->pHash, Cube1 ); + vCube2 = *Hsh_VecReadEntry( p->pHash, Cube2 ); + Cube = Eso_ManComputeAnd( p, &vCube1, &vCube2, p->vCube ); + if ( Cube >= 0 ) + Eso_ManMinimizeAdd( p, Cube ); + } + } + Eso_ManMinimizeCopy( p, vEsop ); +} + +/**Function************************************************************* + + Synopsis [Complements the cover if needed, or just copy it.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Eso_ManTransformOne( Eso_Man_t * p, Vec_Int_t * vEsop, int fCompl, Vec_Int_t * vRes ) +{ + int i, Cube, Start = 0; + Vec_IntClear( vRes ); + if ( fCompl ) + { + if ( Vec_IntSize(vEsop) == 0 ) + Vec_IntPush( vRes, p->Cube1 ); + else + { + Cube = Vec_IntEntry(vEsop, 0); + if ( Cube == p->Cube1 ) + Start = 1; + else if ( Cube < 2 * p->nVars ) + Vec_IntPush( vRes, Abc_LitNot(Cube) ), Start = 1; + else + Vec_IntPush( vRes, p->Cube1 ); + } + } + Vec_IntForEachEntryStart( vEsop, Cube, i, Start ) + Vec_IntPush( vRes, Cube ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [Computes ESOP from AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Eso_ManCompute( Gia_Man_t * pGia, int fVerbose, Vec_Wec_t ** pvRes ) +{ + abctime clk = Abc_Clock(); + Vec_Ptr_t * vCover; + Gia_Man_t * pNew = NULL; + Gia_Obj_t * pObj; + int i, nCubes = 0, nCubesUsed = 0; + Vec_Int_t * vEsop1, * vEsop2, * vEsop; + Eso_Man_t * p = Eso_ManAlloc( pGia ); + Gia_ManForEachAnd( pGia, pObj, i ) + { + vEsop1 = Vec_WecEntry( p->vEsops, Gia_ObjFaninId0(pObj, i) ); + vEsop2 = Vec_WecEntry( p->vEsops, Gia_ObjFaninId1(pObj, i) ); + vEsop1 = Eso_ManTransformOne( p, vEsop1, Gia_ObjFaninC0(pObj), p->vCube1 ); + vEsop2 = Eso_ManTransformOne( p, vEsop2, Gia_ObjFaninC1(pObj), p->vCube2 ); + vEsop = Vec_WecEntry( p->vEsops, i ); + Eso_ManComputeOne( p, vEsop1, vEsop2, vEsop ); + nCubes += Vec_IntSize(vEsop); + } + vCover = Vec_PtrAlloc( Gia_ManCoNum(pGia) ); + Gia_ManForEachCo( pGia, pObj, i ) + { + vEsop1 = Vec_WecEntry( p->vEsops, Gia_ObjFaninId0p(pGia, pObj) ); + vEsop1 = Eso_ManTransformOne( p, vEsop1, Gia_ObjFaninC0(pObj), p->vCube1 ); + if ( fVerbose ) + printf( "Output %3d: ESOP has %5d cubes\n", i, Vec_IntSize(vEsop1) ); +// if ( fVerbose ) +// Eso_ManCoverPrint( p, vEsop1 ); + Vec_PtrPush( vCover, Vec_IntDup(vEsop1) ); + nCubesUsed += Vec_IntSize(vEsop1); + } + if ( fVerbose ) + { + printf( "Outs = %d. Cubes = %d. Used = %d. Hashed = %d. ", + Gia_ManCoNum(pGia), nCubes, nCubesUsed, Hsh_VecSize(p->pHash) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + if ( pvRes ) + *pvRes = Eso_ManCoverDerive( p, vCover ); + else + pNew = Eso_ManCoverConvert( p, vCover ); + Vec_VecFree( (Vec_Vec_t *)vCover ); + Eso_ManStop( p ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaExist.c b/yosys/abc/src/aig/gia/giaExist.c new file mode 100644 index 00000000000..9cffe12fe51 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaExist.c @@ -0,0 +1,526 @@ +/**CFile**************************************************************** + + FileName [giaExist.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Existential quantification.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaExist.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/util/utilTruth.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Existentially quantified several variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +static inline word * Gia_ManQuantInfoId( Gia_Man_t * p, int iObj ) { return Vec_WrdEntryP( p->vSuppWords, p->nSuppWords * iObj ); } +static inline word * Gia_ManQuantInfo( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ManQuantInfoId( p, Gia_ObjId(p, pObj) ); } + +static inline void Gia_ObjCopyGetTwoArray( Gia_Man_t * p, int iObj, int LitsOut[2] ) +{ + int * pLits = Vec_IntEntryP( &p->vCopiesTwo, 2*iObj ); + LitsOut[0] = pLits[0]; + LitsOut[1] = pLits[1]; +} +static inline void Gia_ObjCopySetTwoArray( Gia_Man_t * p, int iObj, int LitsIn[2] ) +{ + int * pLits = Vec_IntEntryP( &p->vCopiesTwo, 2*iObj ); + pLits[0] = LitsIn[0]; + pLits[1] = LitsIn[1]; +} + + +/**Function************************************************************* + + Synopsis [Existentially quantified several variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManQuantVerify_rec( Gia_Man_t * p, int iObj, int CiId ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjIsTravIdCurrentId( p, iObj ) ) + return 0; + Gia_ObjSetTravIdCurrentId( p, iObj ); + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + return Gia_ObjCioId(pObj) == CiId; + return Gia_ManQuantVerify_rec( p, Gia_ObjFaninId0(pObj, iObj), CiId ) || + Gia_ManQuantVerify_rec( p, Gia_ObjFaninId1(pObj, iObj), CiId ); +} +void Gia_ManQuantVerify( Gia_Man_t * p, int iObj ) +{ + word * pInfo = Gia_ManQuantInfoId( p, iObj ); int i, CiId; + assert( Gia_ObjIsAnd(Gia_ManObj(p, iObj)) ); + Vec_IntForEachEntry( &p->vSuppVars, CiId, i ) + { + Gia_ManIncrementTravId( p ); + if ( Abc_TtGetBit(pInfo, i) != Gia_ManQuantVerify_rec(p, iObj, CiId) ) + printf( "Mismatch at node %d related to CI %d (%d).\n", iObj, CiId, Abc_TtGetBit(pInfo, i) ); + } +} + + + +void Gia_ManQuantSetSuppStart( Gia_Man_t * p ) +{ + assert( Gia_ManObjNum(p) == 1 ); + assert( p->vSuppWords == NULL ); + assert( Vec_IntSize(&p->vSuppVars) == 0 ); + p->iSuppPi = 0; + p->nSuppWords = 1; + p->vSuppWords = Vec_WrdAlloc( 1000 ); + Vec_WrdPush( p->vSuppWords, 0 ); +} +void Gia_ManQuantSetSuppZero( Gia_Man_t * p ) +{ + int w; + for ( w = 0; w < p->nSuppWords; w++ ) + Vec_WrdPush( p->vSuppWords, 0 ); + assert( Vec_WrdSize(p->vSuppWords) == p->nSuppWords * Gia_ManObjNum(p) ); +} +void Gia_ManQuantSetSuppCi( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + assert( Gia_ObjIsCi(pObj) ); + assert( p->vSuppWords != NULL ); + if ( p->iSuppPi == 64 * p->nSuppWords ) + { + word Data; int w, Count = 0, Size = Vec_WrdSize(p->vSuppWords); + Vec_Wrd_t * vTemp = Vec_WrdAlloc( Size ? 2 * Size : 1000 ); + Vec_WrdForEachEntry( p->vSuppWords, Data, w ) + { + Vec_WrdPush( vTemp, Data ); + if ( ++Count == p->nSuppWords ) + { + Vec_WrdPush( vTemp, 0 ); + Count = 0; + } + } + Vec_WrdFree( p->vSuppWords ); + p->vSuppWords = vTemp; + p->nSuppWords++; + assert( Vec_WrdSize(p->vSuppWords) == p->nSuppWords * Gia_ManObjNum(p) ); + //printf( "Resizing to %d words.\n", p->nSuppWords ); + } + assert( p->iSuppPi == Vec_IntSize(&p->vSuppVars) ); + Vec_IntPush( &p->vSuppVars, Gia_ObjCioId(pObj) ); + Abc_TtSetBit( Gia_ManQuantInfo(p, pObj), p->iSuppPi++ ); +} +void Gia_ManQuantSetSuppAnd( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + int iObj = Gia_ObjId(p, pObj); + int iFan0 = Gia_ObjFaninId0(pObj, iObj); + int iFan1 = Gia_ObjFaninId1(pObj, iObj); + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManQuantSetSuppZero( p ); + Abc_TtOr( Gia_ManQuantInfo(p, pObj), Gia_ManQuantInfoId(p, iFan0), Gia_ManQuantInfoId(p, iFan1), p->nSuppWords ); +} +int Gia_ManQuantCheckSupp( Gia_Man_t * p, int iObj, int iSupp ) +{ + return Abc_TtGetBit( Gia_ManQuantInfoId(p, iObj), iSupp ); +} +void Gia_ManQuantUpdateCiSupp( Gia_Man_t * p, int iObj ) +{ + if ( Abc_TtIsConst0( Gia_ManQuantInfoId(p, iObj), p->nSuppWords ) ) + Gia_ManQuantSetSuppCi( p, Gia_ManObj(p, iObj) ); + assert( !Abc_TtIsConst0( Gia_ManQuantInfoId(p, iObj), p->nSuppWords ) ); +} +int Gia_ManQuantCheckOverlap( Gia_Man_t * p, int iObj ) +{ + return Abc_TtIntersect( Gia_ManQuantInfoId(p, iObj), Gia_ManQuantInfoId(p, 0), p->nSuppWords, 0 ); +} +void Gia_ManQuantMarkUsedCis( Gia_Man_t * p, int(*pFuncCiToKeep)(void *, int), void * pData ) +{ + int i, CiId; + word * pInfo = Gia_ManQuantInfoId( p, 0 ); + Abc_TtClear( pInfo, p->nSuppWords ); + assert( Abc_TtIsConst0(pInfo, p->nSuppWords) ); + Vec_IntForEachEntry( &p->vSuppVars, CiId, i ) + if ( !pFuncCiToKeep( pData, CiId ) ) // quant var + Abc_TtSetBit( pInfo, i ); +} + +int Gia_ManQuantCountUsed_rec( Gia_Man_t * p, int iObj ) +{ + Gia_Obj_t * pObj; int Count = 1; + if ( Gia_ObjIsTravIdCurrentId( p, iObj ) ) + return 0; + Gia_ObjSetTravIdCurrentId( p, iObj ); + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + return 0; + if ( Gia_ManQuantCheckSupp(p, Gia_ObjFaninId0(pObj, iObj), p->iSuppPi) ) + Count += Gia_ManQuantCountUsed_rec( p, Gia_ObjFaninId0(pObj, iObj) ); + if ( Gia_ManQuantCheckSupp(p, Gia_ObjFaninId1(pObj, iObj), p->iSuppPi) ) + Count += Gia_ManQuantCountUsed_rec( p, Gia_ObjFaninId1(pObj, iObj) ); + return Count; +} +int Gia_ManQuantCountUsed( Gia_Man_t * p, int iObj ) +{ + Gia_ManIncrementTravId( p ); + return Gia_ManQuantCountUsed_rec( p, iObj ); +} + +void Gia_ManQuantDupConeSupp_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vCis, Vec_Int_t * vObjs, int(*pFuncCiToKeep)(void *, int), void * pData ) +{ + int iLit0, iLit1, iObj = Gia_ObjId( p, pObj ); + int iLit = Gia_ObjCopyArray( p, iObj ); + if ( iLit >= 0 ) + return; + if ( Gia_ObjIsCi(pObj) ) + { + int iLit = Gia_ManAppendCi( pNew ); + Gia_Obj_t * pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(iLit) ); + Gia_ManQuantSetSuppZero( pNew ); + if ( !pFuncCiToKeep( pData, Gia_ObjCioId(pObj) ) ) + { + //printf( "Collecting CI %d\n", Gia_ObjCioId(pObj)+1 ); + Gia_ManQuantSetSuppCi( pNew, pObjNew ); + } + Gia_ObjSetCopyArray( p, iObj, iLit ); + Vec_IntPush( vCis, iObj ); + return; + } + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManQuantDupConeSupp_rec( pNew, p, Gia_ObjFanin0(pObj), vCis, vObjs, pFuncCiToKeep, pData ); + Gia_ManQuantDupConeSupp_rec( pNew, p, Gia_ObjFanin1(pObj), vCis, vObjs, pFuncCiToKeep, pData ); + iLit0 = Gia_ObjCopyArray( p, Gia_ObjFaninId0(pObj, iObj) ); + iLit1 = Gia_ObjCopyArray( p, Gia_ObjFaninId1(pObj, iObj) ); + iLit0 = Abc_LitNotCond( iLit0, Gia_ObjFaninC0(pObj) ); + iLit1 = Abc_LitNotCond( iLit1, Gia_ObjFaninC1(pObj) ); + iLit = Gia_ManHashAnd( pNew, iLit0, iLit1 ); + Gia_ObjSetCopyArray( p, iObj, iLit ); + Vec_IntPush( vObjs, iObj ); +} +Gia_Man_t * Gia_ManQuantDupConeSupp( Gia_Man_t * p, int iLit, int(*pFuncCiToKeep)(void *, int), void * pData, Vec_Int_t ** pvCis, int * pOutLit ) +{ + Gia_Man_t * pNew; int i, iLit0, iObj; + Gia_Obj_t * pObj, * pRoot = Gia_ManObj( p, Abc_Lit2Var(iLit) ); + Vec_Int_t * vCis = Vec_IntAlloc( 1000 ); + Vec_Int_t * vObjs = Vec_IntAlloc( 1000 ); + assert( Gia_ObjIsAnd(pRoot) ); + if ( Vec_IntSize(&p->vCopies) < Gia_ManObjNum(p) ) + Vec_IntFillExtra( &p->vCopies, Gia_ManObjNum(p), -1 ); + pNew = Gia_ManStart( 1000 ); + Gia_ManHashStart( pNew ); + Gia_ManQuantSetSuppStart( pNew ); + Gia_ManQuantDupConeSupp_rec( pNew, p, pRoot, vCis, vObjs, pFuncCiToKeep, pData ); + iLit0 = Gia_ObjCopyArray( p, Abc_Lit2Var(iLit) ); + iLit0 = Abc_LitNotCond( iLit0, Abc_LitIsCompl(iLit) ); + if ( pOutLit ) *pOutLit = iLit0; + Gia_ManForEachObjVec( vCis, p, pObj, i ) + Gia_ObjSetCopyArray( p, Gia_ObjId(p, pObj), -1 ); + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + Gia_ObjSetCopyArray( p, Gia_ObjId(p, pObj), -1 ); + //assert( Vec_IntCountLarger(&p->vCopies, -1) == 0 ); + Vec_IntFree( vObjs ); + // remap into CI Ids + Vec_IntForEachEntry( vCis, iObj, i ) + Vec_IntWriteEntry( vCis, i, Gia_ManIdToCioId(p, iObj) ); + if ( pvCis ) *pvCis = vCis; + return pNew; +} +void Gia_ManQuantExist_rec( Gia_Man_t * p, int iObj, int pRes[2] ) +{ + Gia_Obj_t * pObj; + int Lits0[2], Lits1[2], pFans[2], fCompl[2]; + if ( Gia_ObjIsTravIdCurrentId( p, iObj ) ) + { + Gia_ObjCopyGetTwoArray( p, iObj, pRes ); + return; + } + Gia_ObjSetTravIdCurrentId( p, iObj ); + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + { + pRes[0] = 0; pRes[1] = 1; + Gia_ObjCopySetTwoArray( p, iObj, pRes ); + return; + } + pFans[0] = Gia_ObjFaninId0( pObj, iObj ); + pFans[1] = Gia_ObjFaninId1( pObj, iObj ); + fCompl[0] = Gia_ObjFaninC0( pObj ); + fCompl[1] = Gia_ObjFaninC1( pObj ); + if ( Gia_ManQuantCheckSupp(p, pFans[0], p->iSuppPi) ) + Gia_ManQuantExist_rec( p, pFans[0], Lits0 ); + else + Lits0[0] = Lits0[1] = Abc_Var2Lit( pFans[0], 0 ); + if ( Gia_ManQuantCheckSupp(p, pFans[1], p->iSuppPi) ) + Gia_ManQuantExist_rec( p, pFans[1], Lits1 ); + else + Lits1[0] = Lits1[1] = Abc_Var2Lit( pFans[1], 0 ); + pRes[0] = Gia_ManHashAnd( p, Abc_LitNotCond(Lits0[0], fCompl[0]), Abc_LitNotCond(Lits1[0], fCompl[1]) ); + pRes[1] = Gia_ManHashAnd( p, Abc_LitNotCond(Lits0[1], fCompl[0]), Abc_LitNotCond(Lits1[1], fCompl[1]) ); + Gia_ObjCopySetTwoArray( p, iObj, pRes ); +} +int Gia_ManQuantExist2( Gia_Man_t * p0, int iLit, int(*pFuncCiToKeep)(void *, int), void * pData ) +{ +// abctime clk = Abc_Clock(); + Gia_Man_t * pNew; + Vec_Int_t * vOuts, * vOuts2, * vCis; + Gia_Obj_t * pObj = Gia_ManObj( p0, Abc_Lit2Var(iLit) ); + int i, n, Entry, Lit, OutLit = -1, pLits[2], nVarsQua, nAndsOld, nAndsNew; + if ( iLit < 2 ) return iLit; + if ( Gia_ObjIsCi(pObj) ) return pFuncCiToKeep(pData, Gia_ObjCioId(pObj)) ? iLit : 1; + assert( Gia_ObjIsAnd(pObj) ); + pNew = Gia_ManQuantDupConeSupp( p0, iLit, pFuncCiToKeep, pData, &vCis, &OutLit ); + if ( pNew->iSuppPi == 0 ) + { + Gia_ManStop( pNew ); + Vec_IntFree( vCis ); + return iLit; + } + assert( pNew->iSuppPi > 0 && pNew->iSuppPi <= 64 * pNew->nSuppWords ); + vOuts = Vec_IntAlloc( 100 ); + vOuts2 = Vec_IntAlloc( 100 ); + assert( OutLit > 1 ); + Vec_IntPush( vOuts, OutLit ); + nVarsQua = pNew->iSuppPi; + nAndsOld = Gia_ManAndNum(pNew); + while ( --pNew->iSuppPi >= 0 ) + { + Entry = Abc_Lit2Var( Vec_IntEntry(vOuts, 0) ); +// printf( "Quantifying input %d with %d affected nodes (out of %d):\n", +// pNew->iSuppPi, Gia_ManQuantCountUsed(pNew,Entry), Gia_ManAndNum(pNew) ); + if ( Vec_IntSize(&pNew->vCopiesTwo) < 2*Gia_ManObjNum(pNew) ) + Vec_IntFillExtra( &pNew->vCopiesTwo, 2*Gia_ManObjNum(pNew), -1 ); + assert( Vec_IntSize(vOuts) > 0 ); + Vec_IntClear( vOuts2 ); + Gia_ManIncrementTravId( pNew ); + Vec_IntForEachEntry( vOuts, Entry, i ) + { + Gia_ManQuantExist_rec( pNew, Abc_Lit2Var(Entry), pLits ); + for ( n = 0; n < 2; n++ ) + { + Lit = Abc_LitNotCond( pLits[n], Abc_LitIsCompl(Entry) ); + if ( Lit == 0 ) + continue; + if ( Lit == 1 ) + { + Vec_IntFree( vOuts ); + Vec_IntFree( vOuts2 ); + Gia_ManStop( pNew ); + Vec_IntFree( vCis ); + return 1; + } + Vec_IntPushUnique( vOuts2, Lit ); + } + } + Vec_IntClear( vOuts ); + ABC_SWAP( Vec_Int_t *, vOuts, vOuts2 ); + } +// printf( "\n" ); + //printf( "The number of diff cofactors = %d.\n", Vec_IntSize(vOuts) ); + assert( Vec_IntSize(vOuts) > 0 ); + Vec_IntForEachEntry( vOuts, Entry, i ) + Vec_IntWriteEntry( vOuts, i, Abc_LitNot(Entry) ); + OutLit = Gia_ManHashAndMulti( pNew, vOuts ); + OutLit = Abc_LitNot( OutLit ); + Vec_IntFree( vOuts ); + Vec_IntFree( vOuts2 ); + // transfer back + Gia_ManAppendCo( pNew, OutLit ); + nAndsNew = Gia_ManAndNum(p0); + Lit = Gia_ManDupConeBack( p0, pNew, vCis ); + nAndsNew = Gia_ManAndNum(p0) - nAndsNew; + Gia_ManStop( pNew ); + // report the result +// printf( "Performed quantification with %6d nodes, %3d keep-vars, %3d quant-vars, resulting in %5d new nodes. \n", +// nAndsOld, Vec_IntSize(vCis) - nVarsQua, nVarsQua, nAndsNew ); +// Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + Vec_IntFree( vCis ); + return Lit; +} + + +/**Function************************************************************* + + Synopsis [Existentially quantified several variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManQuantCollect_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vQuantCis, Vec_Int_t * vQuantSide, Vec_Int_t * vQuantAnds ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjIsTravIdCurrentId( p, iObj ) ) + return; + Gia_ObjSetTravIdCurrentId( p, iObj ); + if ( !Gia_ManQuantCheckOverlap(p, iObj) ) + { + Vec_IntPush( vQuantSide, iObj ); + return; + } + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + { + Vec_IntPush( vQuantCis, iObj ); + return; + } + Gia_ManQuantCollect_rec( p, Gia_ObjFaninId0(pObj, iObj), vQuantCis, vQuantSide, vQuantAnds ); + Gia_ManQuantCollect_rec( p, Gia_ObjFaninId1(pObj, iObj), vQuantCis, vQuantSide, vQuantAnds ); + Vec_IntPush( vQuantAnds, iObj ); +} +void Gia_ManQuantCollect( Gia_Man_t * p, int iObj, int(*pFuncCiToKeep)(void *, int), void * pData, Vec_Int_t * vQuantCis, Vec_Int_t * vQuantSide, Vec_Int_t * vQuantAnds ) +{ + Gia_ManQuantMarkUsedCis( p, pFuncCiToKeep, pData ); + Gia_ManIncrementTravId( p ); + Gia_ManQuantCollect_rec( p, iObj, vQuantCis, vQuantSide, vQuantAnds ); +// printf( "\nCreated cone with %d quant-vars, %d side-inputs, and %d internal nodes.\n", +// Vec_IntSize(p->vQuantCis), Vec_IntSize(p->vQuantSide), Vec_IntSize(p->vQuantAnds) ); +} + +Gia_Man_t * Gia_ManQuantExist2Dup( Gia_Man_t * p, int iLit, Vec_Int_t * vCis, Vec_Int_t * vSide, Vec_Int_t * vAnds, int * pOutLit ) +{ + int i, iObj, iLit0, iLit1, iLitR; + Gia_Man_t * pNew = Gia_ManStart( Vec_IntSize(vSide) + Vec_IntSize(vCis) + 10*Vec_IntSize(vAnds) ); + Gia_ManQuantSetSuppStart( pNew ); + Gia_ManHashStart( pNew ); + if ( Vec_IntSize(&p->vCopies) < Gia_ManObjNum(p) ) + Vec_IntFillExtra( &p->vCopies, Gia_ManObjNum(p), -1 ); + Vec_IntForEachEntry( vSide, iObj, i ) + { + Gia_ObjSetCopyArray( p, iObj, Gia_ManAppendCi(pNew) ); + Gia_ManQuantSetSuppZero( pNew ); + } + Vec_IntForEachEntry( vCis, iObj, i ) + { + Gia_ObjSetCopyArray( p, iObj, (iLit0 = Gia_ManAppendCi(pNew)) ); + Gia_ManQuantSetSuppZero( pNew ); + Gia_ManQuantSetSuppCi( pNew, Gia_ManObj(pNew, Abc_Lit2Var(iLit0)) ); + } + Vec_IntForEachEntry( vAnds, iObj, i ) + { + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + iLit0 = Gia_ObjCopyArray( p, Gia_ObjFaninId0(pObj, iObj) ); + iLit1 = Gia_ObjCopyArray( p, Gia_ObjFaninId1(pObj, iObj) ); + iLit0 = Abc_LitNotCond( iLit0, Gia_ObjFaninC0(pObj) ); + iLit1 = Abc_LitNotCond( iLit1, Gia_ObjFaninC1(pObj) ); + iLitR = Gia_ManHashAnd( pNew, iLit0, iLit1 ); + Gia_ObjSetCopyArray( p, iObj, iLitR ); + } + iLit0 = Gia_ObjCopyArray( p, Abc_Lit2Var(iLit) ); + iLit0 = Abc_LitNotCond( iLit0, Abc_LitIsCompl(iLit) ); + if ( pOutLit ) *pOutLit = iLit0; + Vec_IntForEachEntry( vSide, iObj, i ) + Gia_ObjSetCopyArray( p, iObj, -1 ); + Vec_IntForEachEntry( vCis, iObj, i ) + Gia_ObjSetCopyArray( p, iObj, -1 ); + Vec_IntForEachEntry( vAnds, iObj, i ) + Gia_ObjSetCopyArray( p, iObj, -1 ); + return pNew; +} +int Gia_ManQuantExistInt( Gia_Man_t * p0, int iLit, Vec_Int_t * vCis, Vec_Int_t * vSide, Vec_Int_t * vAnds ) +{ + int i, Lit, iOutLit, nAndsNew, pLits[2], pRes[2] = {0}; + Gia_Man_t * pNew; + if ( iLit < 2 ) + return 0; + if ( Vec_IntSize(vCis) == 0 ) + return iLit; + if ( Vec_IntSize(vAnds) == 0 ) + { + assert( Gia_ObjIsCi( Gia_ManObj(p0, Abc_Lit2Var(iLit)) ) ); + return Vec_IntFind(vCis, Abc_Lit2Var(iLit)) == -1 ? iLit : 1; + } + pNew = Gia_ManQuantExist2Dup( p0, iLit, vCis, vSide, vAnds, &iOutLit ); + if ( Vec_IntSize(&pNew->vCopiesTwo) < 2*Gia_ManObjNum(pNew) ) + Vec_IntFillExtra( &pNew->vCopiesTwo, 2*Gia_ManObjNum(pNew), -1 ); + Gia_ObjCopySetTwoArray( pNew, 0, pRes ); + for ( i = 0; i < Gia_ManCiNum(pNew); i++ ) + { + pRes[0] = pRes[1] = Abc_Var2Lit( i+1, 0 ); + Gia_ObjCopySetTwoArray( pNew, i+1, pRes ); + } + assert( pNew->iSuppPi == Gia_ManCiNum(pNew) - Vec_IntSize(vSide) ); + for ( i = Gia_ManCiNum(pNew) - 1; i >= Vec_IntSize(vSide); i-- ) + { + pRes[0] = 0; pRes[1] = 1; + Gia_ObjCopySetTwoArray( pNew, i+1, pRes ); + + pNew->iSuppPi--; + if ( Vec_IntSize(&pNew->vCopiesTwo) < 2*Gia_ManObjNum(pNew) ) + Vec_IntFillExtra( &pNew->vCopiesTwo, 2*Gia_ManObjNum(pNew), -1 ); + Gia_ManIncrementTravId( pNew ); + Gia_ManQuantExist_rec( pNew, Abc_Lit2Var(iOutLit), pLits ); + pLits[0] = Abc_LitNotCond( pLits[0], Abc_LitIsCompl(iOutLit) ); + pLits[1] = Abc_LitNotCond( pLits[1], Abc_LitIsCompl(iOutLit) ); + iOutLit = Gia_ManHashOr( pNew, pLits[0], pLits[1] ); + + pRes[0] = pRes[1] = Abc_Var2Lit( i+1, 0 ); + Gia_ObjCopySetTwoArray( pNew, i+1, pRes ); + } + assert( pNew->iSuppPi == 0 ); + Vec_IntAppend( vSide, vCis ); + // transfer back + Gia_ManAppendCo( pNew, iOutLit ); + nAndsNew = Gia_ManAndNum(p0); + Lit = Gia_ManDupConeBackObjs( p0, pNew, vSide ); + nAndsNew = Gia_ManAndNum(p0) - nAndsNew; + Vec_IntShrink( vSide, Vec_IntSize(vSide) - Vec_IntSize(vCis) ); +// printf( "Performed quantification with %6d -> %6d nodes, %3d side-vars, %3d quant-vars, resulting in %5d new nodes. \n", +// Vec_IntSize(vAnds), Gia_ManAndNum(pNew), Vec_IntSize(vSide), Vec_IntSize(vCis), nAndsNew ); + Gia_ManStop( pNew ); + return Lit; +} +int Gia_ManQuantExist( Gia_Man_t * p0, int iLit, int(*pFuncCiToKeep)(void *, int), void * pData ) +{ + int Res; + Vec_Int_t * vQuantCis = Vec_IntAlloc( 100 ); + Vec_Int_t * vQuantSide = Vec_IntAlloc( 100 ); + Vec_Int_t * vQuantAnds = Vec_IntAlloc( 100 ); + Gia_ManQuantCollect( p0, Abc_Lit2Var(iLit), pFuncCiToKeep, pData, vQuantCis, vQuantSide, vQuantAnds ); + Res = Gia_ManQuantExistInt( p0, iLit, vQuantCis, vQuantSide, vQuantAnds ); + Vec_IntFree( vQuantCis ); + Vec_IntFree( vQuantSide ); + Vec_IntFree( vQuantAnds ); + return Res; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaFalse.c b/yosys/abc/src/aig/gia/giaFalse.c new file mode 100644 index 00000000000..50cb8ea72f0 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaFalse.c @@ -0,0 +1,552 @@ +/**CFile**************************************************************** + + FileName [giaFalse.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Detection and elimination of false paths.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaFalse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/vec/vecQue.h" +#include "misc/vec/vecWec.h" +#include "sat/bsat/satStore.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Reconstruct the AIG after detecting false paths.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManFalseRebuildOne( Gia_Man_t * pNew, Gia_Man_t * p, Vec_Int_t * vHook, int fVerbose, int fVeryVerbose ) +{ + Gia_Obj_t * pObj, * pObj1, * pPrev = NULL; + int i, CtrlValue = 0, iPrevValue = -1; + pObj = Gia_ManObj( p, Vec_IntEntry(vHook, 0) ); + if ( Vec_IntSize(vHook) == 1 ) + { + pObj->Value = 0; // what if stuck at 1??? + return; + } + assert( Vec_IntSize(vHook) >= 2 ); + // find controlling value + pObj1 = Gia_ManObj( p, Vec_IntEntry(vHook, 1) ); + if ( Gia_ObjFanin0(pObj1) == pObj ) + CtrlValue = Gia_ObjFaninC0(pObj1); + else if ( Gia_ObjFanin1(pObj1) == pObj ) + CtrlValue = Gia_ObjFaninC1(pObj1); + else assert( 0 ); +// printf( "%d ", CtrlValue ); + // rewrite the path + Gia_ManForEachObjVec( vHook, p, pObj, i ) + { + int iObjValue = pObj->Value; + pObj->Value = i ? Gia_ManHashAnd(pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj)) : CtrlValue; + if ( pPrev ) + pPrev->Value = iPrevValue; + iPrevValue = iObjValue; + pPrev = pObj; + } + if ( fVeryVerbose ) + { + printf( "Eliminated path: " ); + Vec_IntPrint( vHook ); + Gia_ManForEachObjVec( vHook, p, pObj, i ) + { + printf( "Level %3d : ", Gia_ObjLevel(p, pObj) ); + Gia_ObjPrint( p, pObj ); + } + } +} +Gia_Man_t * Gia_ManFalseRebuild( Gia_Man_t * p, Vec_Wec_t * vHooks, int fVerbose, int fVeryVerbose ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, Counter = 0; + pNew = Gia_ManStart( 4 * Gia_ManObjNum(p) / 3 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + { + if ( Vec_WecLevelSize(vHooks, i) > 0 ) + { + if ( fVeryVerbose ) + printf( "Path %d : ", Counter++ ); + Gia_ManFalseRebuildOne( pNew, p, Vec_WecEntry(vHooks, i), fVerbose, fVeryVerbose ); + } + else + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Derive critical path by following minimum slacks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCollectPath_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vPath ) +{ + if ( Gia_ObjIsAnd(pObj) ) + { + if ( Gia_ObjLevel(p, Gia_ObjFanin0(pObj)) > Gia_ObjLevel(p, Gia_ObjFanin1(pObj)) ) + Gia_ManCollectPath_rec( p, Gia_ObjFanin0(pObj), vPath ); + else if ( Gia_ObjLevel(p, Gia_ObjFanin0(pObj)) < Gia_ObjLevel(p, Gia_ObjFanin1(pObj)) ) + Gia_ManCollectPath_rec( p, Gia_ObjFanin1(pObj), vPath ); +// else if ( rand() & 1 ) +// Gia_ManCollectPath_rec( p, Gia_ObjFanin0(pObj), vPath ); + else + Gia_ManCollectPath_rec( p, Gia_ObjFanin1(pObj), vPath ); + } + Vec_IntPush( vPath, Gia_ObjId(p, pObj) ); +} +Vec_Int_t * Gia_ManCollectPath( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + Vec_Int_t * vPath = Vec_IntAlloc( p->nLevels ); + Gia_ManCollectPath_rec( p, Gia_ObjIsCo(pObj) ? Gia_ObjFanin0(pObj) : pObj, vPath ); + return vPath; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCheckFalseOne( Gia_Man_t * p, int iOut, int nTimeOut, Vec_Wec_t * vHooks, int fVerbose, int fVeryVerbose ) +{ + sat_solver * pSat; + Gia_Obj_t * pObj, * pFanin; + Gia_Obj_t * pPivot = Gia_ManCo( p, iOut ); + Vec_Int_t * vLits = Vec_IntAlloc( p->nLevels ); + Vec_Int_t * vPath = Gia_ManCollectPath( p, pPivot ); + int nLits = 0, * pLits = NULL; + int i, Shift[2], status; + abctime clkStart = Abc_Clock(); + // collect objects and assign SAT variables + int iFanin = Gia_ObjFaninId0p( p, pPivot ); + Vec_Int_t * vObjs = Gia_ManCollectNodesCis( p, &iFanin, 1 ); + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + pObj->Value = Vec_IntSize(vObjs) - 1 - i; + assert( Gia_ObjIsCo(pPivot) ); + // create SAT solver + pSat = sat_solver_new(); + sat_solver_set_runtime_limit( pSat, nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 ); + sat_solver_setnvars( pSat, 3 * Vec_IntSize(vPath) + 2 * Vec_IntSize(vObjs) ); + Shift[0] = 3 * Vec_IntSize(vPath); + Shift[1] = 3 * Vec_IntSize(vPath) + Vec_IntSize(vObjs); + // add CNF for the cone + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + { + if ( !Gia_ObjIsAnd(pObj) ) + continue; + sat_solver_add_and( pSat, pObj->Value + Shift[0], + Gia_ObjFanin0(pObj)->Value + Shift[0], Gia_ObjFanin1(pObj)->Value + Shift[0], + Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); + sat_solver_add_and( pSat, pObj->Value + Shift[1], + Gia_ObjFanin0(pObj)->Value + Shift[1], Gia_ObjFanin1(pObj)->Value + Shift[1], + Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); + } + // add CNF for the path + Gia_ManForEachObjVec( vPath, p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + { + assert( i > 0 ); + pFanin = Gia_ManObj( p, Vec_IntEntry(vPath, i-1) ); + if ( pFanin == Gia_ObjFanin0(pObj) ) + { + sat_solver_add_and( pSat, i + 1*Vec_IntSize(vPath), + i-1 + 1*Vec_IntSize(vPath), Gia_ObjFanin1(pObj)->Value + Shift[0], + Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); + sat_solver_add_and( pSat, i + 2*Vec_IntSize(vPath), + i-1 + 2*Vec_IntSize(vPath), Gia_ObjFanin1(pObj)->Value + Shift[1], + Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); + } + else if ( pFanin == Gia_ObjFanin1(pObj) ) + { + sat_solver_add_and( pSat, i + 1*Vec_IntSize(vPath), + Gia_ObjFanin0(pObj)->Value + Shift[0], i-1 + 1*Vec_IntSize(vPath), + Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); + sat_solver_add_and( pSat, i + 2*Vec_IntSize(vPath), + Gia_ObjFanin0(pObj)->Value + Shift[1], i-1 + 2*Vec_IntSize(vPath), + Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); + } + else assert( 0 ); + sat_solver_add_xor( pSat, i, i + 1*Vec_IntSize(vPath), i + 2*Vec_IntSize(vPath), 0 ); + } + else if ( Gia_ObjIsCi(pObj) ) + sat_solver_add_xor( pSat, i, pObj->Value + Shift[0], pObj->Value + Shift[1], 0 ); + else assert( 0 ); + Vec_IntPush( vLits, Abc_Var2Lit(i, 0) ); + } + // call the SAT solver + status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), (ABC_INT64_T)nTimeOut, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + if ( status == l_False ) + { + int iBeg, iEnd; + nLits = sat_solver_final( pSat, &pLits ); + iBeg = Abc_Lit2Var(pLits[nLits-1]); + iEnd = Abc_Lit2Var(pLits[0]); + if ( iEnd - iBeg < 20 ) + { + // check if nodes on the path are already used + for ( i = Abc_MaxInt(iBeg-1, 0); i <= iEnd; i++ ) + if ( Vec_WecLevelSize(vHooks, Vec_IntEntry(vPath, i)) > 0 ) + break; + if ( i > iEnd ) + { + Vec_Int_t * vHook = Vec_WecEntry(vHooks, Vec_IntEntry(vPath, iEnd)); + for ( i = Abc_MaxInt(iBeg-1, 0); i <= iEnd; i++ ) + Vec_IntPush( vHook, Vec_IntEntry(vPath, i) ); + } + } + } + if ( fVerbose ) + { + printf( "PO %6d : Level = %3d ", iOut, Gia_ObjLevel(p, pPivot) ); + if ( status == l_Undef ) + printf( "Timeout reached after %d seconds. ", nTimeOut ); + else if ( status == l_True ) + printf( "There is no false path. " ); + else + { + printf( "False path contains %d nodes (out of %d): ", nLits, Vec_IntSize(vPath) ); + printf( "top = %d ", Vec_IntEntry(vPath, Abc_Lit2Var(pLits[0])) ); + if ( fVeryVerbose ) + for ( i = 0; i < nLits; i++ ) + printf( "%d ", Abc_Lit2Var(pLits[i]) ); + printf( " " ); + } + Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); + } + sat_solver_delete( pSat ); + Vec_IntFree( vObjs ); + Vec_IntFree( vPath ); + Vec_IntFree( vLits ); +} +Gia_Man_t * Gia_ManCheckFalse2( Gia_Man_t * p, int nSlackMax, int nTimeOut, int fVerbose, int fVeryVerbose ) +{ + Gia_Man_t * pNew; + Vec_Wec_t * vHooks; + Vec_Que_t * vPrio; + Vec_Flt_t * vWeights; + Gia_Obj_t * pObj; + int i; +// srand( 111 ); + Gia_ManLevelNum( p ); + // create PO weights + vWeights = Vec_FltAlloc( Gia_ManCoNum(p) ); + Gia_ManForEachCo( p, pObj, i ) + Vec_FltPush( vWeights, Gia_ObjLevel(p, pObj) ); + // put POs into the queue + vPrio = Vec_QueAlloc( Gia_ManCoNum(p) ); + Vec_QueSetPriority( vPrio, Vec_FltArrayP(vWeights) ); + Gia_ManForEachCo( p, pObj, i ) + Vec_QuePush( vPrio, i ); + // work on each PO in the queue + vHooks = Vec_WecStart( Gia_ManObjNum(p) ); + while ( Vec_QueTopPriority(vPrio) >= p->nLevels - nSlackMax ) + Gia_ManCheckFalseOne( p, Vec_QuePop(vPrio), nTimeOut, vHooks, fVerbose, fVeryVerbose ); + if ( fVerbose ) + printf( "Collected %d non-overlapping false paths.\n", Vec_WecSizeUsed(vHooks) ); + // reconstruct the AIG + pNew = Gia_ManFalseRebuild( p, vHooks, fVerbose, fVeryVerbose ); + // cleanup + Vec_WecFree( vHooks ); + Vec_FltFree( vWeights ); + Vec_QueFree( vPrio ); + return pNew; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManFalseRebuildPath( Gia_Man_t * p, Vec_Int_t * vHooks, int fVerbose, int fVeryVerbose ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, iPathEnd = Vec_IntEntryLast(vHooks); + pNew = Gia_ManStart( 4 * Gia_ManObjNum(p) / 3 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + { + if ( iPathEnd == i ) + Gia_ManFalseRebuildOne( pNew, p, vHooks, fVerbose, fVeryVerbose ); + else + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} +Gia_Man_t * Gia_ManCheckOne( Gia_Man_t * p, int iOut, int iObj, int nTimeOut, int fVerbose, int fVeryVerbose ) +{ + sat_solver * pSat; + Gia_Man_t * pNew; + Gia_Obj_t * pObj, * pFanin; + Vec_Int_t * vLits = Vec_IntAlloc( p->nLevels ); + Vec_Int_t * vPath = Gia_ManCollectPath( p, Gia_ManObj(p, iObj) ); + int nLits = 0, * pLits = NULL; + int i, Shift[2], status; + abctime clkStart = Abc_Clock(); + // collect objects and assign SAT variables + Vec_Int_t * vObjs = Gia_ManCollectNodesCis( p, &iObj, 1 ); + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + pObj->Value = Vec_IntSize(vObjs) - 1 - i; + // create SAT solver + pSat = sat_solver_new(); + sat_solver_set_runtime_limit( pSat, nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 ); + sat_solver_setnvars( pSat, 3 * Vec_IntSize(vPath) + 2 * Vec_IntSize(vObjs) ); + Shift[0] = 3 * Vec_IntSize(vPath); + Shift[1] = 3 * Vec_IntSize(vPath) + Vec_IntSize(vObjs); + // add CNF for the cone + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + { + if ( !Gia_ObjIsAnd(pObj) ) + continue; + sat_solver_add_and( pSat, pObj->Value + Shift[0], + Gia_ObjFanin0(pObj)->Value + Shift[0], Gia_ObjFanin1(pObj)->Value + Shift[0], + Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); + sat_solver_add_and( pSat, pObj->Value + Shift[1], + Gia_ObjFanin0(pObj)->Value + Shift[1], Gia_ObjFanin1(pObj)->Value + Shift[1], + Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); + } + // add CNF for the path + Gia_ManForEachObjVec( vPath, p, pObj, i ) + { + if ( !Gia_ObjIsAnd(pObj) ) + continue; + assert( i > 0 ); + pFanin = Gia_ManObj( p, Vec_IntEntry(vPath, i-1) ); + if ( pFanin == Gia_ObjFanin0(pObj) ) + { + sat_solver_add_and( pSat, i + 1*Vec_IntSize(vPath), + i-1 + 1*Vec_IntSize(vPath), Gia_ObjFanin1(pObj)->Value + Shift[0], + Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); + sat_solver_add_and( pSat, i + 2*Vec_IntSize(vPath), + i-1 + 2*Vec_IntSize(vPath), Gia_ObjFanin1(pObj)->Value + Shift[1], + Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); + } + else if ( pFanin == Gia_ObjFanin1(pObj) ) + { + sat_solver_add_and( pSat, i + 1*Vec_IntSize(vPath), + Gia_ObjFanin0(pObj)->Value + Shift[0], i-1 + 1*Vec_IntSize(vPath), + Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); + sat_solver_add_and( pSat, i + 2*Vec_IntSize(vPath), + Gia_ObjFanin0(pObj)->Value + Shift[1], i-1 + 2*Vec_IntSize(vPath), + Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); + } + else assert( 0 ); + sat_solver_add_xor( pSat, i, i + 1*Vec_IntSize(vPath), i + 2*Vec_IntSize(vPath), 0 ); + Vec_IntPush( vLits, Abc_Var2Lit(i, 0) ); + } + // call the SAT solver + status = sat_solver_solve( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits), (ABC_INT64_T)nTimeOut, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + Vec_IntClear( vLits ); + if ( status == l_False ) + { + int iBeg, iEnd; + nLits = sat_solver_final( pSat, &pLits ); + iBeg = Abc_Lit2Var(pLits[nLits-1]); + iEnd = Abc_Lit2Var(pLits[0]); + assert( iBeg <= iEnd ); + // collect path + for ( i = Abc_MaxInt(iBeg-1, 0); i <= iEnd; i++ ) +// for ( i = 0; i < Vec_IntSize(vPath); i++ ) + Vec_IntPush( vLits, Vec_IntEntry(vPath, i) ); + } + if ( fVerbose ) + { + printf( "PO %6d : Level = %3d ", iOut, Gia_ObjLevelId(p, iObj) ); + if ( status == l_Undef ) + printf( "Timeout reached after %d seconds. ", nTimeOut ); + else if ( status == l_True ) + printf( "There is no false path. " ); + else + { + printf( "False path contains %d nodes (out of %d): ", Vec_IntSize(vLits), Vec_IntSize(vPath) ); + if ( fVeryVerbose ) + for ( i = nLits-1; i >= 0; i-- ) + printf( "%d ", Vec_IntEntry(vPath, Abc_Lit2Var(pLits[i])) ); + printf( " " ); + } + Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); + } + sat_solver_delete( pSat ); + Vec_IntFree( vObjs ); + Vec_IntFree( vPath ); + // update the AIG + pNew = Vec_IntSize(vLits) ? Gia_ManFalseRebuildPath( p, vLits, fVerbose, fVeryVerbose ) : NULL; + Vec_IntFree( vLits ); +/* + if ( pNew ) + { + Gia_Man_t * pTemp = Gia_ManDupDfsNode( p, Gia_ManObj(p, iObj) ); + Gia_AigerWrite( pTemp, "false.aig", 0, 0, 0 ); + Abc_Print( 1, "Dumping cone with %d nodes into file \"%s\".\n", Gia_ManAndNum(pTemp), "false.aig" ); + Gia_ManStop( pTemp ); + } +*/ + return pNew; +} +Gia_Man_t * Gia_ManCheckFalseAll( Gia_Man_t * p, int nSlackMax, int nTimeOut, int fVerbose, int fVeryVerbose ) +{ + int Tried = 0, Changed = 0; + p = Gia_ManDup( p ); + while ( 1 ) + { + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i, LevelMax, Changed0 = Changed; + LevelMax = Gia_ManLevelNum( p ); + Gia_ManForEachAnd( p, pObj, i ) + { + if ( Gia_ObjLevel(p, pObj) > nSlackMax ) + continue; + Tried++; + pNew = Gia_ManCheckOne( p, -1, i, nTimeOut, fVerbose, fVeryVerbose ); + if ( pNew == NULL ) + continue; + Changed++; + Gia_ManStop( p ); + p = pNew; + LevelMax = Gia_ManLevelNum( p ); + } + if ( Changed0 == Changed ) + break; + } +// if ( fVerbose ) + printf( "Performed %d attempts and %d changes.\n", Tried, Changed ); + return p; +} +Gia_Man_t * Gia_ManCheckFalse( Gia_Man_t * p, int nSlackMax, int nTimeOut, int fVerbose, int fVeryVerbose ) +{ + int Tried = 0, Changed = 0; + Vec_Int_t * vTried; +// srand( 111 ); + p = Gia_ManDup( p ); + vTried = Vec_IntStart( Gia_ManCoNum(p) ); + while ( 1 ) + { + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i, LevelMax, Changed0 = Changed; + LevelMax = Gia_ManLevelNum( p ); + Gia_ManForEachCo( p, pObj, i ) + { + if ( !Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) ) + continue; + if ( Gia_ObjLevel(p, Gia_ObjFanin0(pObj)) < LevelMax - nSlackMax ) + continue; + if ( Vec_IntEntry( vTried, i ) ) + continue; + Tried++; + pNew = Gia_ManCheckOne( p, i, Gia_ObjFaninId0p(p, pObj), nTimeOut, fVerbose, fVeryVerbose ); +/* + if ( i != 126 && pNew ) + { + Gia_ManStop( pNew ); + pNew = NULL; + } +*/ + if ( pNew == NULL ) + { + Vec_IntWriteEntry( vTried, i, 1 ); + continue; + } + Changed++; + Gia_ManStop( p ); + p = pNew; + LevelMax = Gia_ManLevelNum( p ); + } + if ( Changed0 == Changed ) + break; + } +// if ( fVerbose ) + printf( "Performed %d attempts and %d changes.\n", Tried, Changed ); + Vec_IntFree( vTried ); + return p; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaFanout.c b/yosys/abc/src/aig/gia/giaFanout.c new file mode 100644 index 00000000000..fd58bfeb85b --- /dev/null +++ b/yosys/abc/src/aig/gia/giaFanout.c @@ -0,0 +1,433 @@ +/**CFile**************************************************************** + + FileName [giaFanout.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaFanout.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// 0: first iFan +// 1: prev iFan0 +// 2: prev iFan1 +// 3: next iFan0 +// 4: next iFan1 + +static inline int Gia_FanoutCreate( int FanId, int Num ) { assert( Num < 2 ); return (FanId << 1) | Num; } +static inline int * Gia_FanoutObj( int * pData, int ObjId ) { return pData + 5*ObjId; } +static inline int * Gia_FanoutPrev( int * pData, int iFan ) { return pData + 5*(iFan >> 1) + 1 + (iFan & 1); } +static inline int * Gia_FanoutNext( int * pData, int iFan ) { return pData + 5*(iFan >> 1) + 3 + (iFan & 1); } + +// these two procedures are only here for the use inside the iterator +static inline int Gia_ObjFanout0Int( Gia_Man_t * p, int ObjId ) { assert(ObjId < p->nFansAlloc); return p->pFanData[5*ObjId]; } +static inline int Gia_ObjFanoutNext( Gia_Man_t * p, int iFan ) { assert(iFan/2 < p->nFansAlloc); return p->pFanData[5*(iFan >> 1) + 3 + (iFan & 1)]; } + +// iterator over the fanouts +#define Gia_ObjForEachFanout( p, pObj, pFanout, iFan, i ) \ + for ( assert(p->pFanData), i = 0; (i < (int)(pObj)->nRefs) && \ + (((iFan) = i? Gia_ObjFanoutNext(p, iFan) : Gia_ObjFanout0Int(p, Gia_ObjId(p, pObj))), 1) && \ + (((pFanout) = Gia_ManObj(p, iFan>>1)), 1); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Create fanout for all objects in the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManFanoutStart( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + // allocate fanout datastructure + assert( p->pFanData == NULL ); + p->nFansAlloc = 2 * Gia_ManObjNum(p); + if ( p->nFansAlloc < (1<<12) ) + p->nFansAlloc = (1<<12); + p->pFanData = ABC_ALLOC( int, 5 * p->nFansAlloc ); + memset( p->pFanData, 0, sizeof(int) * 5 * p->nFansAlloc ); + // add fanouts for all objects + Gia_ManForEachObj( p, pObj, i ) + { + if ( Gia_ObjChild0(pObj) ) + Gia_ObjAddFanout( p, Gia_ObjFanin0(pObj), pObj ); + if ( Gia_ObjChild1(pObj) ) + Gia_ObjAddFanout( p, Gia_ObjFanin1(pObj), pObj ); + } +} + +/**Function************************************************************* + + Synopsis [Deletes fanout for all objects in the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManFanoutStop( Gia_Man_t * p ) +{ + assert( p->pFanData != NULL ); + ABC_FREE( p->pFanData ); + p->nFansAlloc = 0; +} + +/**Function************************************************************* + + Synopsis [Adds fanout (pFanout) of node (pObj).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ObjAddFanout( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanout ) +{ + int iFan, * pFirst, * pPrevC, * pNextC, * pPrev, * pNext; + assert( p->pFanData ); + assert( !Gia_IsComplement(pObj) && !Gia_IsComplement(pFanout) ); + assert( Gia_ObjId(p, pFanout) > 0 ); + if ( Gia_ObjId(p, pObj) >= p->nFansAlloc || Gia_ObjId(p, pFanout) >= p->nFansAlloc ) + { + int nFansAlloc = 2 * Abc_MaxInt( Gia_ObjId(p, pObj), Gia_ObjId(p, pFanout) ); + p->pFanData = ABC_REALLOC( int, p->pFanData, 5 * nFansAlloc ); + memset( p->pFanData + 5 * p->nFansAlloc, 0, sizeof(int) * 5 * (nFansAlloc - p->nFansAlloc) ); + p->nFansAlloc = nFansAlloc; + } + assert( Gia_ObjId(p, pObj) < p->nFansAlloc && Gia_ObjId(p, pFanout) < p->nFansAlloc ); + iFan = Gia_FanoutCreate( Gia_ObjId(p, pFanout), Gia_ObjWhatFanin(p, pFanout, pObj) ); + pPrevC = Gia_FanoutPrev( p->pFanData, iFan ); + pNextC = Gia_FanoutNext( p->pFanData, iFan ); + pFirst = Gia_FanoutObj( p->pFanData, Gia_ObjId(p, pObj) ); + if ( *pFirst == 0 ) + { + *pFirst = iFan; + *pPrevC = iFan; + *pNextC = iFan; + } + else + { + pPrev = Gia_FanoutPrev( p->pFanData, *pFirst ); + pNext = Gia_FanoutNext( p->pFanData, *pPrev ); + assert( *pNext == *pFirst ); + *pPrevC = *pPrev; + *pNextC = *pFirst; + *pPrev = iFan; + *pNext = iFan; + } +} + +/**Function************************************************************* + + Synopsis [Removes fanout (pFanout) of node (pObj).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ObjRemoveFanout( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanout ) +{ + int iFan, * pFirst, * pPrevC, * pNextC, * pPrev, * pNext; + assert( p->pFanData && Gia_ObjId(p, pObj) < p->nFansAlloc && Gia_ObjId(p, pFanout) < p->nFansAlloc ); + assert( !Gia_IsComplement(pObj) && !Gia_IsComplement(pFanout) ); + assert( Gia_ObjId(p, pFanout) > 0 ); + iFan = Gia_FanoutCreate( Gia_ObjId(p, pFanout), Gia_ObjWhatFanin(p, pFanout, pObj) ); + pPrevC = Gia_FanoutPrev( p->pFanData, iFan ); + pNextC = Gia_FanoutNext( p->pFanData, iFan ); + pPrev = Gia_FanoutPrev( p->pFanData, *pNextC ); + pNext = Gia_FanoutNext( p->pFanData, *pPrevC ); + assert( *pPrev == iFan ); + assert( *pNext == iFan ); + pFirst = Gia_FanoutObj( p->pFanData, Gia_ObjId(p, pObj) ); + assert( *pFirst > 0 ); + if ( *pFirst == iFan ) + { + if ( *pNextC == iFan ) + { + *pFirst = 0; + *pPrev = 0; + *pNext = 0; + *pPrevC = 0; + *pNextC = 0; + return; + } + *pFirst = *pNextC; + } + *pPrev = *pPrevC; + *pNext = *pNextC; + *pPrevC = 0; + *pNextC = 0; +} + + + + +/**Function************************************************************* + + Synopsis [Compute the map of all edges.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManStartFanoutMap( Gia_Man_t * p, Vec_Int_t * vFanoutNums ) +{ + Vec_Int_t * vEdgeMap; + Gia_Obj_t * pObj; + int i, iOffset; + iOffset = Gia_ManObjNum(p); + vEdgeMap = Vec_IntStart( iOffset + Gia_ManMuxNum(p) + 2 * Gia_ManAndNum(p) + Gia_ManCoNum(p) - Gia_ManBufNum(p) ); + Gia_ManForEachObj( p, pObj, i ) + { + Vec_IntWriteEntry( vEdgeMap, i, iOffset ); + iOffset += Vec_IntEntry( vFanoutNums, Gia_ObjId(p, pObj) ); + } + assert( iOffset <= Vec_IntSize(vEdgeMap) ); + return vEdgeMap; +} + +/**Function************************************************************* + + Synopsis [Allocates static fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManStaticFanoutStart( Gia_Man_t * p ) +{ + Vec_Int_t * vCounts; + int * pRefsOld; + Gia_Obj_t * pObj, * pFanin; + int i, iFanout; + assert( p->vFanoutNums == NULL ); + assert( p->vFanout == NULL ); + // recompute reference counters + pRefsOld = p->pRefs; p->pRefs = NULL; + Gia_ManCreateRefs(p); + p->vFanoutNums = Vec_IntAllocArray( p->pRefs, Gia_ManObjNum(p) ); + p->pRefs = pRefsOld; + // start the fanout maps + p->vFanout = Gia_ManStartFanoutMap( p, p->vFanoutNums ); + // incrementally add fanouts + vCounts = Vec_IntStart( Gia_ManObjNum(p) ); + Gia_ManForEachObj( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) || Gia_ObjIsCo(pObj) ) + { + pFanin = Gia_ObjFanin0(pObj); + iFanout = Vec_IntEntry( vCounts, Gia_ObjId(p, pFanin) ); + Gia_ObjSetFanout( p, pFanin, iFanout, pObj ); + Vec_IntAddToEntry( vCounts, Gia_ObjId(p, pFanin), 1 ); + } + if ( Gia_ObjIsAnd(pObj) && !Gia_ObjIsBuf(pObj) ) + { + pFanin = Gia_ObjFanin1(pObj); + iFanout = Vec_IntEntry( vCounts, Gia_ObjId(p, pFanin) ); + Gia_ObjSetFanout( p, pFanin, iFanout, pObj ); + Vec_IntAddToEntry( vCounts, Gia_ObjId(p, pFanin), 1 ); + } + if ( Gia_ObjIsMux(p, pObj) ) + { + + pFanin = Gia_ObjFanin2(p, pObj); + iFanout = Vec_IntEntry( vCounts, Gia_ObjId(p, pFanin) ); + Gia_ObjSetFanout( p, pFanin, iFanout, pObj ); + Vec_IntAddToEntry( vCounts, Gia_ObjId(p, pFanin), 1 ); + } + } + // double-check the current number of fanouts added + Gia_ManForEachObj( p, pObj, i ) + assert( Vec_IntEntry(vCounts, i) == Gia_ObjFanoutNum(p, pObj) ); + Vec_IntFree( vCounts ); +} + + +/**Function************************************************************* + + Synopsis [Compute the map of all edges.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManStartMappingFanoutMap( Gia_Man_t * p, Vec_Int_t * vFanoutNums ) +{ + Gia_Obj_t * pObj; + int i, iOffset = Gia_ManObjNum(p); + Vec_Int_t * vEdgeMap = Vec_IntAlloc( 2 * iOffset ); + Vec_IntFill( vEdgeMap, iOffset, 0 ); + Gia_ManForEachObj( p, pObj, i ) + { + if ( Vec_IntEntry(vFanoutNums, i) == 0 ) + continue; + Vec_IntWriteEntry( vEdgeMap, i, iOffset ); + iOffset += Vec_IntEntry( vFanoutNums, i ); + Vec_IntFillExtra( vEdgeMap, iOffset, 0 ); + } + //printf( "Fanout map is %.2fx larger than AIG manager.\n", 1.0*Vec_IntSize(vEdgeMap)/Gia_ManObjNum(p) ); + return vEdgeMap; +} + +/**Function************************************************************* + + Synopsis [Allocates static fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ObjCheckDupMappingFanins( Gia_Man_t * p, int iObj ) +{ + int * pFanins = Gia_ObjLutFanins( p, iObj ); + int i, k, nFanins = Gia_ObjLutSize( p, iObj ); + for ( i = 0; i < nFanins; i++ ) + for ( k = i + 1; k < nFanins; k++ ) + assert( pFanins[i] != pFanins[k] ); +} +void Gia_ManStaticMappingFanoutStart( Gia_Man_t * p, Vec_Int_t ** pvIndex ) +{ + Vec_Int_t * vCounts; + int * pRefsOld; + Gia_Obj_t * pObj, * pFanin; + int i, k, iFan, iFanout, Index; + assert( p->vFanoutNums == NULL ); + assert( p->vFanout == NULL ); + // recompute reference counters + pRefsOld = p->pLutRefs; p->pLutRefs = NULL; + Gia_ManSetLutRefs(p); + p->vFanoutNums = Vec_IntAllocArray( p->pLutRefs, Gia_ManObjNum(p) ); + p->pLutRefs = pRefsOld; + // start the fanout maps + p->vFanout = Gia_ManStartMappingFanoutMap( p, p->vFanoutNums ); + if ( pvIndex ) + *pvIndex = Vec_IntStart( Vec_IntSize(p->vFanout) ); + // incrementally add fanouts + vCounts = Vec_IntStart( Gia_ManObjNum(p) ); + Gia_ManForEachLut( p, i ) + { + Gia_ObjCheckDupMappingFanins( p, i ); + pObj = Gia_ManObj( p, i ); + Gia_LutForEachFaninIndex( p, i, iFan, k, Index ) + { + pFanin = Gia_ManObj( p, iFan ); + iFanout = Vec_IntEntry( vCounts, iFan ); + Gia_ObjSetFanout( p, pFanin, iFanout, pObj ); + Vec_IntAddToEntry( vCounts, iFan, 1 ); + if ( pvIndex ) + Vec_IntWriteEntry( *pvIndex, Vec_IntEntry(p->vFanout, iFan) + iFanout, Index ); + } + } + Gia_ManForEachCo( p, pObj, i ) + { + iFan = Gia_ObjFaninId0p(p, pObj); + pFanin = Gia_ManObj( p, iFan ); + iFanout = Vec_IntEntry( vCounts, iFan ); + Gia_ObjSetFanout( p, pFanin, iFanout, pObj ); + Vec_IntAddToEntry( vCounts, iFan, 1 ); + } + // double-check the current number of fanouts added + Gia_ManForEachObj( p, pObj, i ) + assert( Vec_IntEntry(vCounts, i) == Gia_ObjFanoutNum(p, pObj) ); + Vec_IntFree( vCounts ); +} + +/**Function************************************************************* + + Synopsis [Deallocates static fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManStaticFanoutStop( Gia_Man_t * p ) +{ + Vec_IntFreeP( &p->vFanoutNums ); + Vec_IntFreeP( &p->vFanout ); +} + + +/**Function************************************************************* + + Synopsis [Tests static fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManStaticFanoutTest( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj, * pFanout; + int i, k; + Gia_ManStaticFanoutStart( p ); + Gia_ManForEachObj( p, pObj, i ) + { + Gia_ObjPrint( p, pObj ); + printf( " Fanouts : " ); + Gia_ObjForEachFanoutStatic( p, pObj, pFanout, k ) + printf( "%5d ", Gia_ObjId(p, pFanout) ); + printf( "\n" ); + } + Gia_ManStaticFanoutStop( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaForce.c b/yosys/abc/src/aig/gia/giaForce.c new file mode 100644 index 00000000000..0b3003a82ea --- /dev/null +++ b/yosys/abc/src/aig/gia/giaForce.c @@ -0,0 +1,1106 @@ +/**CFile**************************************************************** + + FileName [gia.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +/* + The code is based on the paper by F. A. Aloul, I. L. Markov, and K. A. Sakallah. + "FORCE: A Fast and Easy-To-Implement Variable-Ordering Heuristic", Proc. GLSVLSI�03. + http://www.eecs.umich.edu/~imarkov/pubs/conf/glsvlsi03-force.pdf +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Frc_Obj_t_ Frc_Obj_t; +struct Frc_Obj_t_ +{ + unsigned fCi : 1; // terminal node CI + unsigned fCo : 1; // terminal node CO + unsigned fMark0 : 1; // first user-controlled mark + unsigned fMark1 : 1; // second user-controlled mark + unsigned nFanins : 28; // the number of fanins + unsigned nFanouts; // the number of fanouts + unsigned iFanout; // the current number of fanouts + int hHandle; // the handle of the node + int pPlace; // the placement of each node + union { + float fEdgeCenter; // center-of-gravity of the edge + unsigned iFanin; + }; + int Fanios[0]; // the array of fanins/fanouts +}; + +typedef struct Frc_Man_t_ Frc_Man_t; +struct Frc_Man_t_ +{ + Gia_Man_t * pGia; // the original AIG manager + Vec_Int_t * vCis; // the vector of CIs (PIs + LOs) + Vec_Int_t * vCos; // the vector of COs (POs + LIs) + int nObjs; // the number of objects + int nRegs; // the number of registers + int * pObjData; // the array containing data for objects + int nObjData; // the size of array to store the logic network + int fVerbose; // verbose output flag + int nCutCur; // current cut + int nCutMax; // max cut seen +}; + +static inline int Frc_ManRegNum( Frc_Man_t * p ) { return p->nRegs; } +static inline int Frc_ManCiNum( Frc_Man_t * p ) { return Vec_IntSize(p->vCis); } +static inline int Frc_ManCoNum( Frc_Man_t * p ) { return Vec_IntSize(p->vCos); } +static inline int Frc_ManPiNum( Frc_Man_t * p ) { return Vec_IntSize(p->vCis) - p->nRegs; } +static inline int Frc_ManPoNum( Frc_Man_t * p ) { return Vec_IntSize(p->vCos) - p->nRegs; } +static inline int Frc_ManObjNum( Frc_Man_t * p ) { return p->nObjs; } +static inline int Frc_ManNodeNum( Frc_Man_t * p ) { return p->nObjs - Vec_IntSize(p->vCis) - Vec_IntSize(p->vCos); } + +static inline Frc_Obj_t * Frc_ManObj( Frc_Man_t * p, int hHandle ) { return (Frc_Obj_t *)(p->pObjData + hHandle); } +static inline Frc_Obj_t * Frc_ManCi( Frc_Man_t * p, int i ) { return Frc_ManObj( p, Vec_IntEntry(p->vCis,i) ); } +static inline Frc_Obj_t * Frc_ManCo( Frc_Man_t * p, int i ) { return Frc_ManObj( p, Vec_IntEntry(p->vCos,i) ); } + +static inline int Frc_ObjIsTerm( Frc_Obj_t * pObj ) { return pObj->fCi || pObj->fCo; } +static inline int Frc_ObjIsCi( Frc_Obj_t * pObj ) { return pObj->fCi; } +static inline int Frc_ObjIsCo( Frc_Obj_t * pObj ) { return pObj->fCo; } +static inline int Frc_ObjIsPi( Frc_Obj_t * pObj ) { return pObj->fCi && pObj->nFanins == 0; } +static inline int Frc_ObjIsPo( Frc_Obj_t * pObj ) { return pObj->fCo && pObj->nFanouts == 0; } +static inline int Frc_ObjIsNode( Frc_Obj_t * pObj ) { return!Frc_ObjIsTerm(pObj) && pObj->nFanins > 0; } +static inline int Frc_ObjIsConst0( Frc_Obj_t * pObj ) { return!Frc_ObjIsTerm(pObj) && pObj->nFanins == 0; } + +static inline int Frc_ObjSize( Frc_Obj_t * pObj ) { return sizeof(Frc_Obj_t) / 4 + pObj->nFanins + pObj->nFanouts; } +static inline int Frc_ObjFaninNum( Frc_Obj_t * pObj ) { return pObj->nFanins; } +static inline int Frc_ObjFanoutNum( Frc_Obj_t * pObj ) { return pObj->nFanouts; } +static inline Frc_Obj_t * Frc_ObjFanin( Frc_Obj_t * pObj, int i ) { return (Frc_Obj_t *)(((int *)pObj) - pObj->Fanios[i]); } +static inline Frc_Obj_t * Frc_ObjFanout( Frc_Obj_t * pObj, int i ) { return (Frc_Obj_t *)(((int *)pObj) + pObj->Fanios[pObj->nFanins+i]); } + +#define Frc_ManForEachObj( p, pObj, i ) \ + for ( i = 0; (i < p->nObjData) && (pObj = Frc_ManObj(p,i)); i += Frc_ObjSize(pObj) ) +#define Frc_ManForEachObjVec( vVec, p, pObj, i ) \ + for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Frc_ManObj(p, Vec_IntEntry(vVec,i))); i++ ) + +#define Frc_ManForEachNode( p, pObj, i ) \ + for ( i = 0; (i < p->nObjData) && (pObj = Frc_ManObj(p,i)); i += Frc_ObjSize(pObj) ) if ( Frc_ObjIsTerm(pObj) ) {} else +#define Frc_ManForEachCi( p, pObj, i ) \ + for ( i = 0; (i < Vec_IntSize(p->vCis)) && (pObj = Frc_ManObj(p,Vec_IntEntry(p->vCis,i))); i++ ) +#define Frc_ManForEachCo( p, pObj, i ) \ + for ( i = 0; (i < Vec_IntSize(p->vCos)) && (pObj = Frc_ManObj(p,Vec_IntEntry(p->vCos,i))); i++ ) + +#define Frc_ObjForEachFanin( pObj, pNext, i ) \ + for ( i = 0; (i < (int)pObj->nFanins) && (pNext = Frc_ObjFanin(pObj,i)); i++ ) +#define Frc_ObjForEachFaninReverse( pObj, pNext, i ) \ + for ( i = (int)pObj->nFanins - 1; (i >= 0) && (pNext = Frc_ObjFanin(pObj,i)); i-- ) +#define Frc_ObjForEachFanout( pObj, pNext, i ) \ + for ( i = 0; (i < (int)pObj->nFanouts) && (pNext = Frc_ObjFanout(pObj,i)); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +/**Function************************************************************* + + Synopsis [Creates fanin/fanout pair.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Frc_ObjAddFanin( Frc_Obj_t * pObj, Frc_Obj_t * pFanin ) +{ + assert( pObj->iFanin < pObj->nFanins ); + assert( pFanin->iFanout < pFanin->nFanouts ); + pFanin->Fanios[pFanin->nFanins + pFanin->iFanout++] = + pObj->Fanios[pObj->iFanin++] = pObj->hHandle - pFanin->hHandle; +} + +/**Function************************************************************* + + Synopsis [Creates logic network isomorphic to the given AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Frc_Man_t * Frc_ManStartSimple( Gia_Man_t * pGia ) +{ + Frc_Man_t * p; + Frc_Obj_t * pObjLog, * pFanLog; + Gia_Obj_t * pObj;//, * pObjRi, * pObjRo; + int i, nNodes, hHandle = 0; + // prepare the AIG + Gia_ManCreateRefs( pGia ); + // create logic network + p = ABC_CALLOC( Frc_Man_t, 1 ); + p->pGia = pGia; + p->nRegs = Gia_ManRegNum(pGia); + p->vCis = Vec_IntAlloc( Gia_ManCiNum(pGia) ); + p->vCos = Vec_IntAlloc( Gia_ManCoNum(pGia) ); + p->nObjData = (sizeof(Frc_Obj_t) / 4) * Gia_ManObjNum(pGia) + 2 * (2 * Gia_ManAndNum(pGia) + Gia_ManCoNum(pGia)); + p->pObjData = ABC_CALLOC( int, p->nObjData ); + // create constant node + Gia_ManConst0(pGia)->Value = hHandle; + pObjLog = Frc_ManObj( p, hHandle ); + pObjLog->hHandle = hHandle; + pObjLog->nFanins = 0; + pObjLog->nFanouts = Gia_ObjRefNum( pGia, Gia_ManConst0(pGia) ); + // count objects + hHandle += Frc_ObjSize( pObjLog ); + nNodes = 1; + p->nObjs++; + // create the PIs + Gia_ManForEachCi( pGia, pObj, i ) + { + // create PI object + pObj->Value = hHandle; + Vec_IntPush( p->vCis, hHandle ); + pObjLog = Frc_ManObj( p, hHandle ); + pObjLog->hHandle = hHandle; + pObjLog->nFanins = 0; + pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj ); + pObjLog->fCi = 0; + // count objects + hHandle += Frc_ObjSize( pObjLog ); + p->nObjs++; + } + // create internal nodes + Gia_ManForEachAnd( pGia, pObj, i ) + { + assert( Gia_ObjRefNum( pGia, pObj ) > 0 ); + // create node object + pObj->Value = hHandle; + pObjLog = Frc_ManObj( p, hHandle ); + pObjLog->hHandle = hHandle; + pObjLog->nFanins = 2; + pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj ); + // add fanins + pFanLog = Frc_ManObj( p, Gia_ObjValue(Gia_ObjFanin0(pObj)) ); + Frc_ObjAddFanin( pObjLog, pFanLog ); + pFanLog = Frc_ManObj( p, Gia_ObjValue(Gia_ObjFanin1(pObj)) ); + Frc_ObjAddFanin( pObjLog, pFanLog ); + // count objects + hHandle += Frc_ObjSize( pObjLog ); + nNodes++; + p->nObjs++; + } + // create the POs + Gia_ManForEachCo( pGia, pObj, i ) + { + // create PO object + pObj->Value = hHandle; + Vec_IntPush( p->vCos, hHandle ); + pObjLog = Frc_ManObj( p, hHandle ); + pObjLog->hHandle = hHandle; + pObjLog->nFanins = 1; + pObjLog->nFanouts = 0; + pObjLog->fCo = 1; + // add fanins + pFanLog = Frc_ManObj( p, Gia_ObjValue(Gia_ObjFanin0(pObj)) ); + Frc_ObjAddFanin( pObjLog, pFanLog ); + // count objects + hHandle += Frc_ObjSize( pObjLog ); + p->nObjs++; + } + // connect registers +// Gia_ManForEachRiRo( pGia, pObjRi, pObjRo, i ) +// Frc_ObjAddFanin( Frc_ManObj(p,Gia_ObjValue(pObjRo)), Frc_ManObj(p,Gia_ObjValue(pObjRi)) ); + assert( nNodes == Frc_ManNodeNum(p) ); + assert( hHandle == p->nObjData ); + if ( hHandle != p->nObjData ) + printf( "Frc_ManStartSimple(): Fatal error in internal representation.\n" ); + // make sure the fanin/fanout counters are correct + Gia_ManForEachObj( pGia, pObj, i ) + { + if ( !~Gia_ObjValue(pObj) ) + continue; + pObjLog = Frc_ManObj( p, Gia_ObjValue(pObj) ); + assert( pObjLog->nFanins == pObjLog->iFanin ); + assert( pObjLog->nFanouts == pObjLog->iFanout ); + pObjLog->iFanin = pObjLog->iFanout = 0; + } + ABC_FREE( pGia->pRefs ); + return p; +} + +/**Function************************************************************* + + Synopsis [Collect the fanin IDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Frc_ManCollectSuper_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper, Vec_Int_t * vVisit ) +{ + if ( pObj->fMark1 ) + return; + pObj->fMark1 = 1; + Vec_IntPush( vVisit, Gia_ObjId(p, pObj) ); + if ( pObj->fMark0 ) + { + Vec_IntPush( vSuper, Gia_ObjId(p, pObj) ); + return; + } + assert( Gia_ObjIsAnd(pObj) ); + Frc_ManCollectSuper_rec( p, Gia_ObjFanin0(pObj), vSuper, vVisit ); + Frc_ManCollectSuper_rec( p, Gia_ObjFanin1(pObj), vSuper, vVisit ); + +} + +/**Function************************************************************* + + Synopsis [Collect the fanin IDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Frc_ManCollectSuper( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper, Vec_Int_t * vVisit ) +{ + int Entry, i; + Vec_IntClear( vSuper ); + Vec_IntClear( vVisit ); + assert( pObj->fMark0 == 1 ); + pObj->fMark0 = 0; + Frc_ManCollectSuper_rec( p, pObj, vSuper, vVisit ); + pObj->fMark0 = 1; + Vec_IntForEachEntry( vVisit, Entry, i ) + Gia_ManObj(p, Entry)->fMark1 = 0; +} + +/**Function************************************************************* + + Synopsis [Assigns references while removing the MUX/XOR ones.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Frc_ManCreateRefsSpecial( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj, * pFan0, * pFan1; + Gia_Obj_t * pObjC, * pObjD0, * pObjD1; + int i; + assert( p->pRefs == NULL ); + Gia_ManCleanMark0( p ); + Gia_ManCreateRefs( p ); + Gia_ManForEachAnd( p, pObj, i ) + { + assert( pObj->fMark0 == 0 ); + pFan0 = Gia_ObjFanin0(pObj); + pFan1 = Gia_ObjFanin1(pObj); + // skip nodes whose fanins are PIs or are already marked + if ( Gia_ObjIsCi(pFan0) || pFan0->fMark0 || + Gia_ObjIsCi(pFan1) || pFan1->fMark0 ) + continue; + // skip nodes that are not MUX type + if ( !Gia_ObjIsMuxType(pObj) ) + continue; + // the node is MUX type, mark it and its fanins + pObj->fMark0 = 1; + pFan0->fMark0 = 1; + pFan1->fMark0 = 1; + // deref the control + pObjC = Gia_ObjRecognizeMux( pObj, &pObjD1, &pObjD0 ); + Gia_ObjRefDec( p, Gia_Regular(pObjC) ); + if ( Gia_Regular(pObjD0) == Gia_Regular(pObjD1) ) + Gia_ObjRefDec( p, Gia_Regular(pObjD0) ); + } + Gia_ManForEachAnd( p, pObj, i ) + assert( Gia_ObjRefNum(p, pObj) > 0 ); + Gia_ManCleanMark0( p ); +} + +/**Function************************************************************* + + Synopsis [Assigns references while removing the MUX/XOR ones.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Frc_ManTransformRefs( Gia_Man_t * p, int * pnObjs, int * pnFanios ) +{ + Vec_Int_t * vSuper, * vVisit; + Gia_Obj_t * pObj, * pFanin; + int i, k, Counter; + assert( p->pRefs != NULL ); + + // mark nodes to be used in the logic network + Gia_ManCleanMark0( p ); + Gia_ManConst0(p)->fMark0 = 1; + // mark the inputs + Gia_ManForEachCi( p, pObj, i ) + pObj->fMark0 = 1; + // mark those nodes that have ref count more than 1 + Gia_ManForEachAnd( p, pObj, i ) + pObj->fMark0 = (Gia_ObjRefNum(p, pObj) > 1); + // mark the output drivers + Gia_ManForEachCoDriver( p, pObj, i ) + pObj->fMark0 = 1; + + // count the number of nodes + Counter = 0; + Gia_ManForEachObj( p, pObj, i ) + Counter += pObj->fMark0; + *pnObjs = Counter + Gia_ManCoNum(p); + + // reset the references + ABC_FREE( p->pRefs ); + p->pRefs = ABC_CALLOC( int, Gia_ManObjNum(p) ); + // reference from internal nodes + Counter = 0; + vSuper = Vec_IntAlloc( 100 ); + vVisit = Vec_IntAlloc( 100 ); + Gia_ManCleanMark1( p ); + Gia_ManForEachAnd( p, pObj, i ) + { + if ( pObj->fMark0 == 0 ) + continue; + Frc_ManCollectSuper( p, pObj, vSuper, vVisit ); + Gia_ManForEachObjVec( vSuper, p, pFanin, k ) + { + assert( pFanin->fMark0 ); + Gia_ObjRefInc( p, pFanin ); + } + Counter += Vec_IntSize( vSuper ); + } + Gia_ManCheckMark1( p ); + Vec_IntFree( vSuper ); + Vec_IntFree( vVisit ); + // reference from outputs + Gia_ManForEachCoDriver( p, pObj, i ) + { + assert( pObj->fMark0 ); + Gia_ObjRefInc( p, pObj ); + } + *pnFanios = Counter + Gia_ManCoNum(p); +} + +/**Function************************************************************* + + Synopsis [Creates logic network isomorphic to the given AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Frc_Man_t * Frc_ManStart( Gia_Man_t * pGia ) +{ + Frc_Man_t * p; + Frc_Obj_t * pObjLog, * pFanLog; + Gia_Obj_t * pObj, * pFanin;//, * pObjRi, * pObjRo; + Vec_Int_t * vSuper, * vVisit; + int nObjs, nFanios, nNodes = 0; + int i, k, hHandle = 0; + // prepare the AIG +// Gia_ManCreateRefs( pGia ); + Frc_ManCreateRefsSpecial( pGia ); + Frc_ManTransformRefs( pGia, &nObjs, &nFanios ); + Gia_ManFillValue( pGia ); + // create logic network + p = ABC_CALLOC( Frc_Man_t, 1 ); + p->pGia = pGia; + p->nRegs = Gia_ManRegNum(pGia); + p->vCis = Vec_IntAlloc( Gia_ManCiNum(pGia) ); + p->vCos = Vec_IntAlloc( Gia_ManCoNum(pGia) ); + p->nObjData = (sizeof(Frc_Obj_t) / 4) * nObjs + 2 * nFanios; + p->pObjData = ABC_CALLOC( int, p->nObjData ); + // create constant node + Gia_ManConst0(pGia)->Value = hHandle; + pObjLog = Frc_ManObj( p, hHandle ); + pObjLog->hHandle = hHandle; + pObjLog->nFanins = 0; + pObjLog->nFanouts = Gia_ObjRefNum( pGia, Gia_ManConst0(pGia) ); + // count objects + hHandle += Frc_ObjSize( pObjLog ); + nNodes++; + p->nObjs++; + // create the PIs + Gia_ManForEachCi( pGia, pObj, i ) + { + // create PI object + pObj->Value = hHandle; + Vec_IntPush( p->vCis, hHandle ); + pObjLog = Frc_ManObj( p, hHandle ); + pObjLog->hHandle = hHandle; + pObjLog->nFanins = 0; + pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj ); + pObjLog->fCi = 1; + // count objects + hHandle += Frc_ObjSize( pObjLog ); + p->nObjs++; + } + // create internal nodes + vSuper = Vec_IntAlloc( 100 ); + vVisit = Vec_IntAlloc( 100 ); + Gia_ManForEachAnd( pGia, pObj, i ) + { + if ( pObj->fMark0 == 0 ) + { + assert( Gia_ObjRefNum( pGia, pObj ) == 0 ); + continue; + } + assert( Gia_ObjRefNum( pGia, pObj ) > 0 ); + Frc_ManCollectSuper( pGia, pObj, vSuper, vVisit ); + // create node object + pObj->Value = hHandle; + pObjLog = Frc_ManObj( p, hHandle ); + pObjLog->hHandle = hHandle; + pObjLog->nFanins = Vec_IntSize( vSuper ); + pObjLog->nFanouts = Gia_ObjRefNum( pGia, pObj ); + // add fanins + Gia_ManForEachObjVec( vSuper, pGia, pFanin, k ) + { + pFanLog = Frc_ManObj( p, Gia_ObjValue(pFanin) ); + Frc_ObjAddFanin( pObjLog, pFanLog ); + } + // count objects + hHandle += Frc_ObjSize( pObjLog ); + nNodes++; + p->nObjs++; + } + Vec_IntFree( vSuper ); + Vec_IntFree( vVisit ); + // create the POs + Gia_ManForEachCo( pGia, pObj, i ) + { + // create PO object + pObj->Value = hHandle; + Vec_IntPush( p->vCos, hHandle ); + pObjLog = Frc_ManObj( p, hHandle ); + pObjLog->hHandle = hHandle; + pObjLog->nFanins = 1; + pObjLog->nFanouts = 0; + pObjLog->fCo = 1; + // add fanins + pFanLog = Frc_ManObj( p, Gia_ObjValue(Gia_ObjFanin0(pObj)) ); + Frc_ObjAddFanin( pObjLog, pFanLog ); + // count objects + hHandle += Frc_ObjSize( pObjLog ); + p->nObjs++; + } + // connect registers +// Gia_ManForEachRiRo( pGia, pObjRi, pObjRo, i ) +// Frc_ObjAddFanin( Frc_ManObj(p,Gia_ObjValue(pObjRo)), Frc_ManObj(p,Gia_ObjValue(pObjRi)) ); + Gia_ManCleanMark0( pGia ); + assert( nNodes == Frc_ManNodeNum(p) ); + assert( nObjs == p->nObjs ); + assert( hHandle == p->nObjData ); + if ( hHandle != p->nObjData ) + printf( "Frc_ManStart(): Fatal error in internal representation.\n" ); + // make sure the fanin/fanout counters are correct + Gia_ManForEachObj( pGia, pObj, i ) + { + if ( !~Gia_ObjValue(pObj) ) + continue; + pObjLog = Frc_ManObj( p, Gia_ObjValue(pObj) ); + assert( pObjLog->nFanins == pObjLog->iFanin ); + assert( pObjLog->nFanouts == pObjLog->iFanout ); + pObjLog->iFanin = pObjLog->iFanout = 0; + } + ABC_FREE( pGia->pRefs ); + return p; +} + +/**Function************************************************************* + + Synopsis [Creates logic network isomorphic to the given AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Frc_ManPrintStats( Frc_Man_t * p ) +{ +// if ( p->pName ) +// printf( "%8s : ", p->pName ); + printf( "i/o =%7d/%7d ", Frc_ManPiNum(p), Frc_ManPoNum(p) ); + if ( Frc_ManRegNum(p) ) + printf( "ff =%7d ", Frc_ManRegNum(p) ); + printf( "node =%8d ", Frc_ManNodeNum(p) ); + printf( "obj =%8d ", Frc_ManObjNum(p) ); +// printf( "lev =%5d ", Frc_ManLevelNum(p) ); +// printf( "cut =%5d ", Frc_ManCrossCut(p) ); + printf( "mem =%5.2f MB", 4.0*p->nObjData/(1<<20) ); +// printf( "obj =%5d ", Frc_ManObjNum(p) ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Creates logic network isomorphic to the given AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Frc_ManStop( Frc_Man_t * p ) +{ + Vec_IntFree( p->vCis ); + Vec_IntFree( p->vCos ); + ABC_FREE( p->pObjData ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [Computes cross cut size for the given order of POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Frc_ManCrossCut_rec( Frc_Man_t * p, Frc_Obj_t * pObj ) +{ + assert( pObj->iFanout > 0 ); + if ( pObj->iFanout-- == pObj->nFanouts ) + { + Frc_Obj_t * pFanin; + int i; + p->nCutCur++; + p->nCutMax = Abc_MaxInt( p->nCutMax, p->nCutCur ); + if ( !Frc_ObjIsCi(pObj) ) + Frc_ObjForEachFanin( pObj, pFanin, i ) + p->nCutCur -= Frc_ManCrossCut_rec( p, pFanin ); + } + return pObj->iFanout == 0; +} + +/**Function************************************************************* + + Synopsis [Computes cross cut size for the given order of POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Frc_ManCrossCut2_rec( Frc_Man_t * p, Frc_Obj_t * pObj ) +{ + assert( pObj->iFanout > 0 ); + if ( pObj->iFanout-- == pObj->nFanouts ) + { + Frc_Obj_t * pFanin; + int i; + p->nCutCur++; + p->nCutMax = Abc_MaxInt( p->nCutMax, p->nCutCur ); + if ( !Frc_ObjIsCi(pObj) ) + Frc_ObjForEachFaninReverse( pObj, pFanin, i ) + p->nCutCur -= Frc_ManCrossCut2_rec( p, pFanin ); + } + return pObj->iFanout == 0; +} + +/**Function************************************************************* + + Synopsis [Computes cross cut size for the given order of POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Frc_ManCrossCut( Frc_Man_t * p, Vec_Int_t * vOrder, int fReverse ) +{ + Frc_Obj_t * pObj; + int i; + assert( Vec_IntSize(vOrder) == Frc_ManCoNum(p) ); + p->nCutCur = 0; + p->nCutMax = 0; + Frc_ManForEachObj( p, pObj, i ) + pObj->iFanout = pObj->nFanouts; + Frc_ManForEachObjVec( vOrder, p, pObj, i ) + { + assert( Frc_ObjIsCo(pObj) ); + if ( fReverse ) + p->nCutCur -= Frc_ManCrossCut2_rec( p, Frc_ObjFanin(pObj,0) ); + else + p->nCutCur -= Frc_ManCrossCut_rec( p, Frc_ObjFanin(pObj,0) ); + } + assert( p->nCutCur == 0 ); +// Frc_ManForEachObj( p, pObj, i ) +// assert( pObj->iFanout == 0 ); + return p->nCutMax; +} + +/**Function************************************************************* + + Synopsis [Collects CO handles.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Frc_ManCollectCos( Frc_Man_t * p ) +{ + Vec_Int_t * vCoOrder; + Frc_Obj_t * pObj; + int i; + vCoOrder = Vec_IntAlloc( Frc_ManCoNum(p) ); + Frc_ManForEachCo( p, pObj, i ) + Vec_IntPush( vCoOrder, pObj->hHandle ); + return vCoOrder; +} + +/**Function************************************************************* + + Synopsis [Computes cross cut size for the given order of POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Frc_ManCrossCutTest( Frc_Man_t * p, Vec_Int_t * vOrderInit ) +{ + Vec_Int_t * vOrder; +// abctime clk = Abc_Clock(); + vOrder = vOrderInit? vOrderInit : Frc_ManCollectCos( p ); + printf( "CrossCut = %6d\n", Frc_ManCrossCut( p, vOrder, 0 ) ); + printf( "CrossCut = %6d\n", Frc_ManCrossCut( p, vOrder, 1 ) ); + Vec_IntReverseOrder( vOrder ); + printf( "CrossCut = %6d\n", Frc_ManCrossCut( p, vOrder, 0 ) ); + printf( "CrossCut = %6d\n", Frc_ManCrossCut( p, vOrder, 1 ) ); + Vec_IntReverseOrder( vOrder ); + if ( vOrder != vOrderInit ) + Vec_IntFree( vOrder ); +// ABC_PRT( "Time", Abc_Clock() - clk ); +} + + + +/**Function************************************************************* + + Synopsis [Generates random placement.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Frc_ManPlaceRandom( Frc_Man_t * p ) +{ + Frc_Obj_t * pThis; + int * pPlacement; + int i, h, Temp, iNext, Counter; + pPlacement = ABC_ALLOC( int, p->nObjs ); + for ( i = 0; i < p->nObjs; i++ ) + pPlacement[i] = i; + for ( i = 0; i < p->nObjs; i++ ) + { + iNext = Gia_ManRandom( 0 ) % p->nObjs; + Temp = pPlacement[i]; + pPlacement[i] = pPlacement[iNext]; + pPlacement[iNext] = Temp; + } + Counter = 0; + Frc_ManForEachObj( p, pThis, h ) + pThis->pPlace = pPlacement[Counter++]; + ABC_FREE( pPlacement ); +} + +/**Function************************************************************* + + Synopsis [Shuffles array of random integers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Frc_ManArrayShuffle( Vec_Int_t * vArray ) +{ + int i, iNext, Temp; + for ( i = 0; i < vArray->nSize; i++ ) + { + iNext = Gia_ManRandom( 0 ) % vArray->nSize; + Temp = vArray->pArray[i]; + vArray->pArray[i] = vArray->pArray[iNext]; + vArray->pArray[iNext] = Temp; + } +} + +/**Function************************************************************* + + Synopsis [Computes cross cut size for the given order of POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Frc_ManPlaceDfs_rec( Frc_Man_t * p, Frc_Obj_t * pObj, int * piPlace ) +{ + assert( pObj->iFanout > 0 ); + if ( pObj->iFanout-- == pObj->nFanouts ) + { + Frc_Obj_t * pFanin; + int i; + if ( !Frc_ObjIsCi(pObj) ) + Frc_ObjForEachFanin( pObj, pFanin, i ) + Frc_ManPlaceDfs_rec( p, pFanin, piPlace ); + pObj->pPlace = (*piPlace)++; + } +} + +/**Function************************************************************* + + Synopsis [Generates DFS placement.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Frc_ManPlaceDfs( Frc_Man_t * p, Vec_Int_t * vCoOrder ) +{ + Frc_Obj_t * pObj; + int i, nPlaces = 0; + Frc_ManForEachObj( p, pObj, i ) + { + pObj->iFanout = pObj->nFanouts; + if ( pObj->nFanouts == 0 && !Frc_ObjIsCo(pObj) ) + pObj->pPlace = nPlaces++; + } + Frc_ManForEachObjVec( vCoOrder, p, pObj, i ) + { + assert( Frc_ObjIsCo(pObj) ); + Frc_ManPlaceDfs_rec( p, Frc_ObjFanin(pObj,0), &nPlaces ); + pObj->pPlace = nPlaces++; + } + assert( nPlaces == p->nObjs ); +} + +/**Function************************************************************* + + Synopsis [Generates DFS placement by trying both orders.] + + Description [Returns the cross cut size of the best order. ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Frc_ManPlaceDfsBoth( Frc_Man_t * p, Vec_Int_t * vCoOrder, int * piCutSize2 ) +{ + int nCutStart1, nCutStart2; + nCutStart1 = Frc_ManCrossCut( p, vCoOrder, 0 ); + Vec_IntReverseOrder( vCoOrder ); + nCutStart2 = Frc_ManCrossCut( p, vCoOrder, 0 ); + if ( nCutStart1 <= nCutStart2 ) + { + Vec_IntReverseOrder( vCoOrder ); // undo + Frc_ManPlaceDfs( p, vCoOrder ); + *piCutSize2 = nCutStart2; + return nCutStart1; + } + else + { + Frc_ManPlaceDfs( p, vCoOrder ); + Vec_IntReverseOrder( vCoOrder ); // undo + *piCutSize2 = nCutStart1; + return nCutStart2; + } +} + +/**Function************************************************************* + + Synopsis [Performs iterative refinement of the given placement.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Frc_ManPlacementRefine( Frc_Man_t * p, int nIters, int fVerbose ) +{ + int fRandomize = 0; + Vec_Int_t * vCoOrder; + Frc_Obj_t * pThis, * pNext; + double CostThis, CostPrev; + float * pVertX, VertX; + int * pPermX, * pHandles; + int k, h, Iter, iMinX, iMaxX, Counter, nCutStart, nCutCur, nCutCur2, nCutPrev; + abctime clk = Abc_Clock(), clk2, clk2Total = 0; + // create starting one-dimensional placement + vCoOrder = Frc_ManCollectCos( p ); + if ( fRandomize ) + Frc_ManArrayShuffle( vCoOrder ); + nCutStart = Frc_ManPlaceDfsBoth( p, vCoOrder, &nCutCur2 ); + // refine placement + CostPrev = 0.0; + nCutPrev = nCutStart; + pHandles = ABC_ALLOC( int, p->nObjs ); + pVertX = ABC_ALLOC( float, p->nObjs ); + for ( Iter = 0; Iter < nIters; Iter++ ) + { + // compute centers of hyperedges + CostThis = 0.0; + Frc_ManForEachObj( p, pThis, h ) + { + iMinX = iMaxX = pThis->pPlace; + Frc_ObjForEachFanout( pThis, pNext, k ) + { + iMinX = Abc_MinInt( iMinX, pNext->pPlace ); + iMaxX = Abc_MaxInt( iMaxX, pNext->pPlace ); + } + pThis->fEdgeCenter = 0.5 * (iMaxX + iMinX); + CostThis += (iMaxX - iMinX); + } + // compute new centers of objects + Counter = 0; + Frc_ManForEachObj( p, pThis, h ) + { + VertX = pThis->fEdgeCenter; + Frc_ObjForEachFanin( pThis, pNext, k ) + VertX += pNext->fEdgeCenter; + pVertX[Counter] = VertX / (Frc_ObjFaninNum(pThis) + 1); + pHandles[Counter++] = h; + } + assert( Counter == Frc_ManObjNum(p) ); + // sort these numbers + clk2 = Abc_Clock(); + pPermX = Gia_SortFloats( pVertX, pHandles, p->nObjs ); + clk2Total += Abc_Clock() - clk2; + assert( pPermX == pHandles ); + Vec_IntClear( vCoOrder ); + for ( k = 0; k < p->nObjs; k++ ) + { + pThis = Frc_ManObj( p, pPermX[k] ); + pThis->pPlace = k; + if ( Frc_ObjIsCo(pThis) ) + Vec_IntPush( vCoOrder, pThis->hHandle ); + } +/* + printf( "Ordering of PIs:\n" ); + Frc_ManForEachCi( p, pThis, k ) + printf( "PI number = %7d. Object handle = %7d, Coordinate = %7d.\n", + k, pThis->hHandle, pThis->pPlace ); +*/ + nCutCur = Frc_ManPlaceDfsBoth( p, vCoOrder, &nCutCur2 ); + // evaluate cost + if ( fVerbose ) + { + printf( "%2d : Span = %e ", Iter+1, CostThis ); + printf( "Cut = %6d (%5.2f %%) CutR = %6d ", nCutCur, 100.0*(nCutStart-nCutCur)/nCutStart, nCutCur2 ); + ABC_PRTn( "Total", Abc_Clock() - clk ); + ABC_PRT( "Sort", clk2Total ); +// Frc_ManCrossCutTest( p, vCoOrder ); + } +// if ( 1.0 * nCutPrev / nCutCur < 1.001 ) +// break; + nCutPrev = nCutCur; + } + ABC_FREE( pHandles ); + ABC_FREE( pVertX ); + Vec_IntFree( vCoOrder ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if all fanouts are COsw.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Frc_ObjFanoutsAreCos( Frc_Obj_t * pThis ) +{ + Frc_Obj_t * pNext; + int i; + Frc_ObjForEachFanout( pThis, pNext, i ) + if ( !Frc_ObjIsCo(pNext) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes the distances from the given set of objects.] + + Description [Returns one of the most distant objects.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Frc_DumpGraphIntoFile( Frc_Man_t * p ) +{ + FILE * pFile; + Frc_Obj_t * pThis, * pNext; + int i, k, Counter = 0; + // assign numbers to CIs and internal nodes + Frc_ManForEachObj( p, pThis, i ) + { + if ( i && ((Frc_ObjIsCi(pThis) && !Frc_ObjFanoutsAreCos(pThis)) || Frc_ObjIsNode(pThis)) ) + pThis->iFanin = Counter++; + else + pThis->iFanin = ~0; + } + // assign numbers to all other nodes + pFile = fopen( "x\\large\\aig\\dg1.g", "w" ); + Frc_ManForEachObj( p, pThis, i ) + { + Frc_ObjForEachFanout( pThis, pNext, k ) + { + if ( ~pThis->iFanin && ~pNext->iFanin ) + fprintf( pFile, "%d %d\n", pThis->iFanin, pNext->iFanin ); + } + } + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Experiment with the FORCE algorithm.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void For_ManExperiment( Gia_Man_t * pGia, int nIters, int fClustered, int fVerbose ) +{ + Frc_Man_t * p; + Gia_ManRandom( 1 ); + if ( fClustered ) + p = Frc_ManStart( pGia ); + else + p = Frc_ManStartSimple( pGia ); +// Frc_DumpGraphIntoFile( p ); + if ( fVerbose ) + Frc_ManPrintStats( p ); +// Frc_ManCrossCutTest( p, NULL ); + Frc_ManPlacementRefine( p, nIters, fVerbose ); + Frc_ManStop( p ); +} + +/**Function************************************************************* + + Synopsis [Experiment with the FORCE algorithm.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void For_ManFileExperiment() +{ + FILE * pFile; + int * pBuffer; + int i, Size, Exp = 25; + abctime clk = Abc_Clock(); + int RetValue; + + Size = (1 << Exp); + printf( "2^%d machine words (%d bytes).\n", Exp, (int)sizeof(int) * Size ); + + pBuffer = ABC_ALLOC( int, Size ); + for ( i = 0; i < Size; i++ ) + pBuffer[i] = i; +ABC_PRT( "Fillup", Abc_Clock() - clk ); + +clk = Abc_Clock(); + pFile = fopen( "test.txt", "rb" ); + RetValue = fread( pBuffer, 1, sizeof(int) * Size, pFile ); + fclose( pFile ); +ABC_PRT( "Read ", Abc_Clock() - clk ); + +clk = Abc_Clock(); + pFile = fopen( "test.txt", "wb" ); + fwrite( pBuffer, 1, sizeof(int) * Size, pFile ); + fclose( pFile ); +ABC_PRT( "Write ", Abc_Clock() - clk ); +/* +2^25 machine words (134217728 bytes). +Fillup = 0.06 sec +Read = 0.08 sec +Write = 1.81 sec +*/ +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaFrames.c b/yosys/abc/src/aig/gia/giaFrames.c new file mode 100644 index 00000000000..39493be8fd9 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaFrames.c @@ -0,0 +1,996 @@ +/**CFile**************************************************************** + + FileName [giaFrames.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Timeframe unrolling.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaFrames.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Gia_ManFra_t_ Gia_ManFra_t; +struct Gia_ManFra_t_ +{ + Gia_ParFra_t * pPars; // parameters + Gia_Man_t * pAig; // AIG to unroll + Vec_Ptr_t * vIns; // inputs of each timeframe + Vec_Ptr_t * vAnds; // nodes of each timeframe + Vec_Ptr_t * vOuts; // outputs of each timeframe +}; + + +typedef struct Gia_ManUnr_t_ Gia_ManUnr_t; +struct Gia_ManUnr_t_ +{ + Gia_ParFra_t * pPars; // parameters + Gia_Man_t * pAig; // AIG to unroll (points to pOrder) + // internal data + Gia_Man_t * pOrder; // AIG reordered (points to pAig) + Vec_Int_t * vLimit; // limits of each timeframe + // data for each ordered node + Vec_Int_t * vRank; // rank of each node + Vec_Int_t * vDegree; // degree of each node + Vec_Int_t * vDegDiff; // degree of each node + Vec_Int_t * vFirst; // first entry in the store + Vec_Int_t * vStore; // store for saved data + // the resulting AIG + Gia_Man_t * pNew; // the resulting AIG + int LastLit; // the place to store the last literal +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Duplicates AIG for unrolling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManUnrollDup_rec( Gia_Man_t * pNew, Gia_Obj_t * pObj, int Id ) +{ + if ( ~pObj->Value ) + return; + if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi(pNew); + else if ( Gia_ObjIsCo(pObj) ) + { + Gia_ManUnrollDup_rec( pNew, Gia_ObjFanin0(pObj), Gia_ObjFaninId0(pObj, Id) ); + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + else if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ManUnrollDup_rec( pNew, Gia_ObjFanin0(pObj), Gia_ObjFaninId0(pObj, Id) ); + Gia_ManUnrollDup_rec( pNew, Gia_ObjFanin1(pObj), Gia_ObjFaninId1(pObj, Id) ); + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + else assert( 0 ); + Gia_ManObj(pNew, Abc_Lit2Var(pObj->Value))->Value = Id; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG for unrolling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManUnrollDup( Gia_Man_t * p, Vec_Int_t * vLimit ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + assert( Vec_IntSize(vLimit) == 0 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + + // save constant class + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Vec_IntPush( vLimit, Gia_ManObjNum(pNew) ); + + // create first class + Gia_ManForEachPo( p, pObj, i ) + Gia_ManUnrollDup_rec( pNew, pObj, Gia_ObjId(p, pObj) ); + Vec_IntPush( vLimit, Gia_ManObjNum(pNew) ); + + // create next classes + for ( i = 1; i < Gia_ManObjNum(pNew); i++ ) + { + if ( i == Vec_IntEntryLast(vLimit) ) + Vec_IntPush( vLimit, Gia_ManObjNum(pNew) ); + pObj = Gia_ManObj( p, Gia_ManObj(pNew, i)->Value ); + if ( Gia_ObjIsRo(p, pObj) ) + { + pObj = Gia_ObjRoToRi(p, pObj); + assert( !~pObj->Value ); + Gia_ManUnrollDup_rec( pNew, pObj, Gia_ObjId(p, pObj) ); + } + } + Gia_ManSetRegNum( pNew, 0 ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG for unrolling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Gia_ManUnrollAbs( Gia_Man_t * p, int nFrames ) +{ + int fVerbose = 0; + Vec_Ptr_t * vFrames; + Vec_Int_t * vLimit, * vOne; + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int nObjBits, nObjMask; + int f, fMax, k, Entry, Prev, iStart, iStop, Size; + // get the bitmasks + nObjBits = Abc_Base2Log( Gia_ManObjNum(p) ); + nObjMask = (1 << nObjBits) - 1; + assert( Gia_ManObjNum(p) <= nObjMask ); + // derive the tents + vLimit = Vec_IntAlloc( 1000 ); + pNew = Gia_ManUnrollDup( p, vLimit ); + // debug printout + if ( fVerbose ) + { + Prev = 1; + printf( "Tents: " ); + Vec_IntForEachEntryStart( vLimit, Entry, k, 1 ) + printf( "%d=%d ", k, Entry-Prev ), Prev = Entry; + printf( " Unused=%d", Gia_ManObjNum(p) - Gia_ManObjNum(pNew) ); + printf( "\n" ); + } + // create abstraction + vFrames = Vec_PtrAlloc( Vec_IntSize(vLimit) ); + for ( fMax = 0; fMax < nFrames; fMax++ ) + { + Size = (fMax+1 < Vec_IntSize(vLimit)) ? Vec_IntEntry(vLimit, fMax+1) : Gia_ManObjNum(pNew); + vOne = Vec_IntAlloc( Size ); + for ( f = 0; f <= fMax; f++ ) + { + iStart = (f < Vec_IntSize(vLimit)) ? Vec_IntEntry(vLimit, f ) : 0; + iStop = (f+1 < Vec_IntSize(vLimit)) ? Vec_IntEntry(vLimit, f+1) : 0; + for ( k = iStop - 1; k >= iStart; k-- ) + { + assert( Gia_ManObj(pNew, k)->Value > 0 ); + pObj = Gia_ManObj(p, Gia_ManObj(pNew, k)->Value); + if ( Gia_ObjIsCo(pObj) || Gia_ObjIsPi(p, pObj) ) + continue; + assert( Gia_ObjIsRo(p, pObj) || Gia_ObjIsAnd(pObj) ); + Entry = ((fMax-f) << nObjBits) | Gia_ObjId(p, pObj); + Vec_IntPush( vOne, Entry ); +// printf( "%d ", Gia_ManObj(pNew, k)->Value ); + } +// printf( "\n" ); + } + // add in reverse topological order + Vec_IntSort( vOne, 1 ); + Vec_PtrPush( vFrames, vOne ); + assert( Vec_IntSize(vOne) <= Size - 1 ); + } + Vec_IntFree( vLimit ); + Gia_ManStop( pNew ); + return vFrames; +} + +/**Function************************************************************* + + Synopsis [Creates manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_ManUnr_t * Gia_ManUnrStart( Gia_Man_t * pAig, Gia_ParFra_t * pPars ) +{ + Gia_ManUnr_t * p; + Gia_Obj_t * pObj; + int i, k, iRank, iFanin, Degree, Shift; + abctime clk = Abc_Clock(); + + p = ABC_CALLOC( Gia_ManUnr_t, 1 ); + p->pAig = pAig; + p->pPars = pPars; + // create order + p->vLimit = Vec_IntAlloc( 0 ); + p->pOrder = Gia_ManUnrollDup( pAig, p->vLimit ); +/* + Vec_IntForEachEntryStart( p->vLimit, Shift, i, 1 ) + printf( "%d=%d ", i, Shift-Vec_IntEntry(p->vLimit, i-1) ); + printf( "\n" ); +*/ + // assign rank + p->vRank = Vec_IntAlloc( Gia_ManObjNum(p->pOrder) ); + for ( iRank = i = 0; i < Gia_ManObjNum(p->pOrder); Vec_IntPush(p->vRank, iRank), i++ ) + if ( Vec_IntEntry(p->vLimit, iRank) == i ) + iRank++; + assert( iRank == Vec_IntSize(p->vLimit)-1 ); + assert( Vec_IntSize(p->vRank) == Gia_ManObjNum(p->pOrder) ); + // assign degree + p->vDegree = Vec_IntStart( Gia_ManObjNum(p->pOrder) ); + p->vDegDiff= Vec_IntStart( 2* Gia_ManObjNum(p->pOrder) ); + Gia_ManForEachAnd( p->pOrder, pObj, i ) + { + for ( k = 0; k < 2; k++ ) + { + iFanin = k ? Gia_ObjFaninId1(pObj, i) : Gia_ObjFaninId0(pObj, i); + Degree = Vec_IntEntry(p->vRank, i) - Vec_IntEntry(p->vRank, iFanin); + Vec_IntWriteEntry( p->vDegDiff, 2*i + k, Degree ); + if ( Vec_IntEntry(p->vDegree, iFanin) < Degree ) + Vec_IntWriteEntry( p->vDegree, iFanin, Degree ); + } + } + Gia_ManForEachCo( p->pOrder, pObj, k ) + { + i = Gia_ObjId( p->pOrder, pObj ); + iFanin = Gia_ObjFaninId0(pObj, i); + Degree = Vec_IntEntry(p->vRank, i) - Vec_IntEntry(p->vRank, iFanin); + Vec_IntWriteEntry( p->vDegDiff, 2*i, Degree ); + if ( Vec_IntEntry(p->vDegree, iFanin) < Degree ) + Vec_IntWriteEntry( p->vDegree, iFanin, Degree ); + } + // assign first + p->vFirst = Vec_IntAlloc( Gia_ManObjNum(p->pOrder) ); + p->vStore = Vec_IntStartFull( 2* Gia_ManObjNum(p->pOrder) + Vec_IntSum(p->vDegree) ); + for ( Shift = i = 0; i < Gia_ManObjNum(p->pOrder); i++ ) + { + Vec_IntPush( p->vFirst, Shift ); + Vec_IntWriteEntry( p->vStore, Shift, 1 + Vec_IntEntry(p->vDegree, i) ); + Shift += 2 + Vec_IntEntry(p->vDegree, i); + } + assert( Shift == Vec_IntSize(p->vStore) ); + // cleanup + Vec_IntFreeP( &p->vRank ); + Vec_IntFreeP( &p->vDegree ); + + // print verbose output + if ( pPars->fVerbose ) + { + printf( "Convergence = %d. Dangling objects = %d. Average degree = %.3f ", + Vec_IntSize(p->vLimit) - 1, + Gia_ManObjNum(pAig) - Gia_ManObjNum(p->pOrder), + 1.0*Vec_IntSize(p->vStore)/Gia_ManObjNum(p->pOrder) - 1.0 ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + return p; +} + +/**Function************************************************************* + + Synopsis [Deletes manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManUnrollStop( void * pMan ) +{ + Gia_ManUnr_t * p = (Gia_ManUnr_t *)pMan; + Gia_ManStopP( &p->pOrder ); + Vec_IntFreeP( &p->vLimit ); + Vec_IntFreeP( &p->vRank ); + Vec_IntFreeP( &p->vDegree ); + Vec_IntFreeP( &p->vDegDiff ); + Vec_IntFreeP( &p->vFirst ); + Vec_IntFreeP( &p->vStore ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [Reading/writing entry from storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ObjUnrWrite( Gia_ManUnr_t * p, int Id, int Entry ) +{ + int i, * pArray = Vec_IntEntryP( p->vStore, Vec_IntEntry(p->vFirst, Id) ); + for ( i = pArray[0]; i > 1; i-- ) + pArray[i] = pArray[i-1]; + pArray[1] = Entry; +} +static inline int Gia_ObjUnrRead( Gia_ManUnr_t * p, int Id, int Degree ) +{ + int * pArray = Vec_IntEntryP( p->vStore, Vec_IntEntry(p->vFirst, Id) ); + if ( Id == 0 ) + return 0; + assert( Degree >= 0 && Degree < pArray[0] ); + if ( Degree ) + Degree--; + return pArray[Degree + 1]; +} +static inline int Gia_ObjUnrReadCopy0( Gia_ManUnr_t * p, Gia_Obj_t * pObj, int Id ) +{ + int Lit = Gia_ObjUnrRead(p, Gia_ObjFaninId0(pObj, Id), Vec_IntEntry(p->vDegDiff, 2*Id)); + return Abc_LitNotCond( Lit, Gia_ObjFaninC0(pObj) ); +} +static inline int Gia_ObjUnrReadCopy1( Gia_ManUnr_t * p, Gia_Obj_t * pObj, int Id ) +{ + int Lit = Gia_ObjUnrRead(p, Gia_ObjFaninId1(pObj, Id), Vec_IntEntry(p->vDegDiff, 2*Id+1)); + return Abc_LitNotCond( Lit, Gia_ObjFaninC1(pObj) ); +} +static inline int Gia_ObjUnrReadCi( Gia_ManUnr_t * p, int Id, int f, Gia_Man_t * pNew ) +{ + Gia_Obj_t * pObj = Gia_ManObj( p->pOrder, Id ); + Gia_Obj_t * pObjReal = Gia_ManObj( p->pAig, pObj->Value ); + assert( Gia_ObjIsCi(pObjReal) ); + if ( Gia_ObjIsPi(p->pAig, pObjReal) ) + { + if ( !p->pPars->fSaveLastLit ) + pObj = Gia_ManPi( pNew, Gia_ManPiNum(p->pAig) * f + Gia_ObjCioId(pObjReal) ); + else + pObj = Gia_ManPi( pNew, Gia_ManRegNum(p->pAig) + Gia_ManPiNum(p->pAig) * f + Gia_ObjCioId(pObjReal) ); + return Abc_Var2Lit( Gia_ObjId(pNew, pObj), 0 ); + } + if ( f == 0 ) // initialize! + { + if ( p->pPars->fInit ) + return 0; + assert( Gia_ObjCioId(pObjReal) >= Gia_ManPiNum(p->pAig) ); + if ( !p->pPars->fSaveLastLit ) + pObj = Gia_ManPi( pNew, Gia_ManPiNum(p->pAig) * p->pPars->nFrames + Gia_ObjCioId(pObjReal)-Gia_ManPiNum(p->pAig) ); + else + pObj = Gia_ManPi( pNew, Gia_ObjCioId(pObjReal)-Gia_ManPiNum(p->pAig) ); + return Abc_Var2Lit( Gia_ObjId(pNew, pObj), 0 ); + } + pObj = Gia_ManObj( p->pOrder, Abc_Lit2Var(Gia_ObjRoToRi(p->pAig, pObjReal)->Value) ); + assert( Gia_ObjIsCo(pObj) ); + return Gia_ObjUnrRead( p, Gia_ObjId(p->pOrder, pObj), 0 ); +} + +/**Function************************************************************* + + Synopsis [Computes init/non-init unrolling without flops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Gia_ManUnrollStart( Gia_Man_t * pAig, Gia_ParFra_t * pPars ) +{ + Gia_ManUnr_t * p; + int f, i; + // start + p = Gia_ManUnrStart( pAig, pPars ); + // start timeframes + assert( p->pNew == NULL ); + p->pNew = Gia_ManStart( 10000 ); + p->pNew->pName = Abc_UtilStrsav( p->pAig->pName ); + p->pNew->pSpec = Abc_UtilStrsav( p->pAig->pSpec ); + Gia_ManHashAlloc( p->pNew ); + // create combinational inputs + if ( !p->pPars->fSaveLastLit ) // only in the case when unrolling depth is known + for ( f = 0; f < p->pPars->nFrames; f++ ) + for ( i = 0; i < Gia_ManPiNum(p->pAig); i++ ) + Gia_ManAppendCi(p->pNew); + // create flop outputs + if ( !p->pPars->fInit ) // only in the case when initialization is not performed + for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) + Gia_ManAppendCi(p->pNew); + return p; +} + +/**Function************************************************************* + + Synopsis [Computes init/non-init unrolling without flops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Gia_ManUnrollAdd( void * pMan, int fMax ) +{ + Gia_ManUnr_t * p = (Gia_ManUnr_t *)pMan; + Gia_Obj_t * pObj; + int f, i, Lit = 0, Beg, End; + // create PIs on demand + if ( p->pPars->fSaveLastLit ) + for ( i = 0; i < Gia_ManPiNum(p->pAig); i++ ) + Gia_ManAppendCi(p->pNew); + // unroll another timeframe + for ( f = 0; f < fMax; f++ ) + { + if ( Vec_IntSize(p->vLimit) <= fMax-f ) + continue; + Beg = Vec_IntEntry( p->vLimit, fMax-f-1 ); + End = Vec_IntEntry( p->vLimit, fMax-f ); + for ( i = Beg; i < End; i++ ) + { + pObj = Gia_ManObj( p->pOrder, i ); + if ( Gia_ObjIsAnd(pObj) ) + Lit = Gia_ManHashAnd( p->pNew, Gia_ObjUnrReadCopy0(p, pObj, i), Gia_ObjUnrReadCopy1(p, pObj, i) ); + else if ( Gia_ObjIsCo(pObj) ) + { + Lit = Gia_ObjUnrReadCopy0(p, pObj, i); + if ( f == fMax-1 ) + { + if ( p->pPars->fSaveLastLit ) + p->LastLit = Lit; + else + Gia_ManAppendCo( p->pNew, Lit ); + } + } + else if ( Gia_ObjIsCi(pObj) ) + Lit = Gia_ObjUnrReadCi( p, i, f, p->pNew ); + else assert( 0 ); + assert( Lit >= 0 ); + Gia_ObjUnrWrite( p, i, Lit ); // should be exactly one call for each obj! + } + } + return p->pNew; +} + +/**Function************************************************************* + + Synopsis [Read the last literal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManUnrollLastLit( void * pMan ) +{ + Gia_ManUnr_t * p = (Gia_ManUnr_t *)pMan; + return p->LastLit; +} + +/**Function************************************************************* + + Synopsis [Computes init/non-init unrolling without flops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManUnroll( Gia_Man_t * pAig, Gia_ParFra_t * pPars ) +{ + Gia_ManUnr_t * p; + Gia_Man_t * pNew, * pTemp; + int fMax; + p = (Gia_ManUnr_t *)Gia_ManUnrollStart( pAig, pPars ); + for ( fMax = 1; fMax <= p->pPars->nFrames; fMax++ ) + Gia_ManUnrollAdd( p, fMax ); + assert( Gia_ManPoNum(p->pNew) == p->pPars->nFrames * Gia_ManPoNum(p->pAig) ); + Gia_ManHashStop( p->pNew ); + Gia_ManSetRegNum( p->pNew, 0 ); +// Gia_ManPrintStats( pNew, 0 ); + // cleanup + p->pNew = Gia_ManCleanup( pTemp = p->pNew ); + Gia_ManStop( pTemp ); +// Gia_ManPrintStats( pNew, 0 ); + pNew = p->pNew; p->pNew = NULL; + Gia_ManUnrollStop( p ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Computes init/non-init unrolling without flops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +/* +Gia_Man_t * Gia_ManUnroll( Gia_ManUnr_t * p ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int fMax, f, i, Lit, Beg, End; + // start timeframes + pNew = Gia_ManStart( 10000 ); + pNew->pName = Abc_UtilStrsav( p->pAig->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pAig->pSpec ); + Gia_ManHashAlloc( pNew ); + // create combinational inputs + for ( f = 0; f < p->pPars->nFrames; f++ ) + for ( i = 0; i < Gia_ManPiNum(p->pAig); i++ ) + Gia_ManAppendCi(pNew); + if ( !p->pPars->fInit ) + for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) + Gia_ManAppendCi(pNew); + // add nodes to each time-frame +// Gia_ObjUnrWrite( p, 0, 0 ); + for ( fMax = 1; fMax <= p->pPars->nFrames; fMax++ ) + for ( f = 0; f < fMax; f++ ) + { + if ( Vec_IntSize(p->vLimit) <= fMax-f ) + continue; + Beg = Vec_IntEntry( p->vLimit, fMax-f-1 ); + End = Vec_IntEntry( p->vLimit, fMax-f ); + for ( i = Beg; i < End; i++ ) + { + pObj = Gia_ManObj( p->pOrder, i ); + if ( Gia_ObjIsAnd(pObj) ) + Lit = Gia_ManHashAnd( pNew, Gia_ObjUnrReadCopy0(p, pObj, i), Gia_ObjUnrReadCopy1(p, pObj, i) ); + else if ( Gia_ObjIsCo(pObj) ) + { + Lit = Gia_ObjUnrReadCopy0(p, pObj, i); + if ( f == fMax-1 ) + Gia_ManAppendCo( pNew, Lit ); + } + else if ( Gia_ObjIsCi(pObj) ) + Lit = Gia_ObjUnrReadCi( p, i, f, pNew ); + else assert( 0 ); + assert( Lit >= 0 ); + Gia_ObjUnrWrite( p, i, Lit ); // should be exactly one call for each obj! + } + } + assert( Gia_ManPoNum(pNew) == p->pPars->nFrames * Gia_ManPoNum(p->pAig) ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, 0 ); +// Gia_ManPrintStats( pNew, 0 ); + // cleanup + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); +// Gia_ManPrintStats( pNew, 0 ); + return pNew; +} +*/ + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManFrames2( Gia_Man_t * pAig, Gia_ParFra_t * pPars ) +{ + Gia_Man_t * pNew; + abctime clk = Abc_Clock(); + pNew = Gia_ManUnroll( pAig, pPars ); + if ( pPars->fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return pNew; +} + + + +/**Function************************************************************* + + Synopsis [This procedure sets default parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManFraSetDefaultParams( Gia_ParFra_t * p ) +{ + memset( p, 0, sizeof(Gia_ParFra_t) ); + p->nFrames = 32; // the number of frames to unroll + p->fInit = 0; // initialize the timeframes + p->fVerbose = 0; // enables verbose output +} + +/**Function************************************************************* + + Synopsis [Creates manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_ManFra_t * Gia_ManFraStart( Gia_Man_t * pAig, Gia_ParFra_t * pPars ) +{ + Gia_ManFra_t * p; + p = ABC_ALLOC( Gia_ManFra_t, 1 ); + memset( p, 0, sizeof(Gia_ManFra_t) ); + p->pAig = pAig; + p->pPars = pPars; + return p; +} + +/**Function************************************************************* + + Synopsis [Deletes manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManFraStop( Gia_ManFra_t * p ) +{ + Vec_VecFree( (Vec_Vec_t *)p->vIns ); + Vec_VecFree( (Vec_Vec_t *)p->vAnds ); + Vec_VecFree( (Vec_Vec_t *)p->vOuts ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Computes supports of all timeframes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManFraSupports( Gia_ManFra_t * p ) +{ + Vec_Int_t * vIns = NULL, * vAnds, * vOuts; + Gia_Obj_t * pObj; + int f, i; + p->vIns = Vec_PtrStart( p->pPars->nFrames ); + p->vAnds = Vec_PtrStart( p->pPars->nFrames ); + p->vOuts = Vec_PtrStart( p->pPars->nFrames ); + Gia_ManIncrementTravId( p->pAig ); + for ( f = p->pPars->nFrames - 1; f >= 0; f-- ) + { + vOuts = Gia_ManCollectPoIds( p->pAig ); + if ( vIns ) + Gia_ManForEachObjVec( vIns, p->pAig, pObj, i ) + if ( Gia_ObjIsRo(p->pAig, pObj) ) + Vec_IntPush( vOuts, Gia_ObjId( p->pAig, Gia_ObjRoToRi(p->pAig, pObj) ) ); + vIns = Vec_IntAlloc( 100 ); + Gia_ManCollectCis( p->pAig, Vec_IntArray(vOuts), Vec_IntSize(vOuts), vIns ); + vAnds = Vec_IntAlloc( 100 ); + Gia_ManCollectAnds( p->pAig, Vec_IntArray(vOuts), Vec_IntSize(vOuts), vAnds, NULL ); + Vec_PtrWriteEntry( p->vIns, f, vIns ); + Vec_PtrWriteEntry( p->vAnds, f, vAnds ); + Vec_PtrWriteEntry( p->vOuts, f, vOuts ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManFramesInit( Gia_Man_t * pAig, Gia_ParFra_t * pPars ) +{ + int fUseAllPis = 1; + Gia_Man_t * pFrames, * pTemp; + Gia_ManFra_t * p; + Gia_Obj_t * pObj; + Vec_Int_t * vIns, * vAnds, * vOuts; + int i, f; + p = Gia_ManFraStart( pAig, pPars ); + Gia_ManFraSupports( p ); + pFrames = Gia_ManStart( Vec_VecSizeSize((Vec_Vec_t*)p->vIns)+ + Vec_VecSizeSize((Vec_Vec_t*)p->vAnds)+Vec_VecSizeSize((Vec_Vec_t*)p->vOuts) ); + pFrames->pName = Abc_UtilStrsav( pAig->pName ); + pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); + Gia_ManHashAlloc( pFrames ); + Gia_ManConst0(pAig)->Value = 0; + for ( f = 0; f < pPars->nFrames; f++ ) + { + vIns = (Vec_Int_t *)Vec_PtrEntry( p->vIns, f ); + vAnds = (Vec_Int_t *)Vec_PtrEntry( p->vAnds, f ); + vOuts = (Vec_Int_t *)Vec_PtrEntry( p->vOuts, f ); + if ( pPars->fVerbose ) + printf( "Frame %3d : CI = %6d. AND = %6d. CO = %6d.\n", + f, Vec_IntSize(vIns), Vec_IntSize(vAnds), Vec_IntSize(vOuts) ); + if ( fUseAllPis ) + { + Gia_ManForEachPi( pAig, pObj, i ) + pObj->Value = Gia_ManAppendCi( pFrames ); + if ( f == 0 ) + { + Gia_ManForEachObjVec( vIns, pAig, pObj, i ) + { + assert( Gia_ObjIsCi(pObj) ); + if ( !Gia_ObjIsPi(pAig, pObj) ) + pObj->Value = 0; + } + } + else + { + Gia_ManForEachObjVec( vIns, pAig, pObj, i ) + { + assert( Gia_ObjIsCi(pObj) ); + if ( !Gia_ObjIsPi(pAig, pObj) ) + pObj->Value = Gia_ObjRoToRi(pAig, pObj)->Value; + } + } + } + else + { + if ( f == 0 ) + { + Gia_ManForEachObjVec( vIns, pAig, pObj, i ) + { + assert( Gia_ObjIsCi(pObj) ); + if ( Gia_ObjIsPi(pAig, pObj) ) + pObj->Value = Gia_ManAppendCi( pFrames ); + else + pObj->Value = 0; + } + } + else + { + Gia_ManForEachObjVec( vIns, pAig, pObj, i ) + { + assert( Gia_ObjIsCi(pObj) ); + if ( Gia_ObjIsPi(pAig, pObj) ) + pObj->Value = Gia_ManAppendCi( pFrames ); + else + pObj->Value = Gia_ObjRoToRi(pAig, pObj)->Value; + } + } + } + Gia_ManForEachObjVec( vAnds, pAig, pObj, i ) + { + assert( Gia_ObjIsAnd(pObj) ); + pObj->Value = Gia_ManHashAnd( pFrames, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + Gia_ManForEachObjVec( vOuts, pAig, pObj, i ) + { + assert( Gia_ObjIsCo(pObj) ); + if ( Gia_ObjIsPo(pAig, pObj) ) + pObj->Value = Gia_ManAppendCo( pFrames, Gia_ObjFanin0Copy(pObj) ); + else + pObj->Value = Gia_ObjFanin0Copy(pObj); + } + } + Gia_ManFraStop( p ); + Gia_ManHashStop( pFrames ); + if ( Gia_ManCombMarkUsed(pFrames) < Gia_ManAndNum(pFrames) ) + { + pFrames = Gia_ManDupMarked( pTemp = pFrames ); + if ( pPars->fVerbose ) + printf( "Before cleanup = %d nodes. After cleanup = %d nodes.\n", + Gia_ManAndNum(pTemp), Gia_ManAndNum(pFrames) ); + Gia_ManStop( pTemp ); + } + else if ( pPars->fVerbose ) + printf( "Before cleanup = %d nodes. After cleanup = %d nodes.\n", + Gia_ManAndNum(pFrames), Gia_ManAndNum(pFrames) ); + return pFrames; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManFrames( Gia_Man_t * pAig, Gia_ParFra_t * pPars ) +{ + Gia_Man_t * pFrames, * pTemp; + Gia_Obj_t * pObj; + Vec_Int_t * vPoLits = NULL; + int i, f; + assert( Gia_ManRegNum(pAig) > 0 ); + assert( pPars->nFrames > 0 ); + if ( pPars->fInit ) + return Gia_ManFramesInit( pAig, pPars ); + if ( pPars->fOrPos ) + vPoLits = Vec_IntStart( Gia_ManPoNum(pAig) ); + pFrames = Gia_ManStart( pPars->nFrames * Gia_ManObjNum(pAig) ); + pFrames->pName = Abc_UtilStrsav( pAig->pName ); + pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); + if ( !pPars->fDisableSt ) + Gia_ManHashAlloc( pFrames ); + Gia_ManConst0(pAig)->Value = 0; + // create primary inputs + for ( f = 0; f < pPars->nFrames; f++ ) + Gia_ManForEachPi( pAig, pObj, i ) + pObj->Value = Gia_ManAppendCi( pFrames ); + // add internal nodes for each timeframe + for ( f = 0; f < pPars->nFrames; f++ ) + { + if ( f == 0 ) + { + Gia_ManForEachRo( pAig, pObj, i ) + pObj->Value = Gia_ManAppendCi( pFrames ); + } + else + { + Gia_ManForEachRo( pAig, pObj, i ) + pObj->Value = Gia_ObjRoToRi( pAig, pObj )->Value; + } + Gia_ManForEachPi( pAig, pObj, i ) + pObj->Value = Gia_Obj2Lit( pFrames, Gia_ManPi(pFrames, f * Gia_ManPiNum(pAig) + i) ); + if ( !pPars->fDisableSt ) + Gia_ManForEachAnd( pAig, pObj, i ) + pObj->Value = Gia_ManHashAnd( pFrames, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else + Gia_ManForEachAnd( pAig, pObj, i ) + pObj->Value = Gia_ManAppendAnd2( pFrames, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( vPoLits ) + { + if ( !pPars->fDisableSt ) + Gia_ManForEachPo( pAig, pObj, i ) + Vec_IntWriteEntry( vPoLits, i, Gia_ManHashOr(pFrames, Vec_IntEntry(vPoLits, i), Gia_ObjFanin0Copy(pObj)) ); + else + Gia_ManForEachPo( pAig, pObj, i ) + Vec_IntWriteEntry( vPoLits, i, Abc_LitNot(Gia_ManAppendAnd2(pFrames, Abc_LitNot(Vec_IntEntry(vPoLits, i)), Abc_LitNot(Gia_ObjFanin0Copy(pObj)))) ); + } + else + { + Gia_ManForEachPo( pAig, pObj, i ) + pObj->Value = Gia_ManAppendCo( pFrames, Gia_ObjFanin0Copy(pObj) ); + } + if ( f == pPars->nFrames - 1 ) + { + if ( vPoLits ) + Gia_ManForEachPo( pAig, pObj, i ) + pObj->Value = Gia_ManAppendCo( pFrames, Vec_IntEntry(vPoLits, i) ); + Gia_ManForEachRi( pAig, pObj, i ) + pObj->Value = Gia_ManAppendCo( pFrames, Gia_ObjFanin0Copy(pObj) ); + } + else + { + Gia_ManForEachRi( pAig, pObj, i ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + } + } + Vec_IntFreeP( &vPoLits ); + if ( !pPars->fDisableSt ) + Gia_ManHashStop( pFrames ); + Gia_ManSetRegNum( pFrames, Gia_ManRegNum(pAig) ); + if ( Gia_ManCombMarkUsed(pFrames) < Gia_ManAndNum(pFrames) ) + { + pFrames = Gia_ManDupMarked( pTemp = pFrames ); + if ( pPars->fVerbose ) + printf( "Before cleanup = %d nodes. After cleanup = %d nodes.\n", + Gia_ManAndNum(pTemp), Gia_ManAndNum(pFrames) ); + Gia_ManStop( pTemp ); + } + else if ( pPars->fVerbose ) + printf( "Before cleanup = %d nodes. After cleanup = %d nodes.\n", + Gia_ManAndNum(pFrames), Gia_ManAndNum(pFrames) ); + return pFrames; +} + + +/**Function************************************************************* + + Synopsis [Perform init unrolling as long as PO(s) are constant 0.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManFramesInitSpecial( Gia_Man_t * pAig, int nFrames, int fVerbose ) +{ + Gia_Man_t * pFrames, * pTemp; + Gia_Obj_t * pObj; + int i, f; + assert( Gia_ManRegNum(pAig) > 0 ); + if ( nFrames > 0 ) + printf( "Computing specialized unrolling with %d frames...\n", nFrames ); + pFrames = Gia_ManStart( Gia_ManObjNum(pAig) ); + pFrames->pName = Abc_UtilStrsav( pAig->pName ); + pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); + Gia_ManHashAlloc( pFrames ); + Gia_ManConst0(pAig)->Value = 0; + for ( f = 0; nFrames == 0 || f < nFrames; f++ ) + { + if ( fVerbose && (f % 100 == 0) ) + { + printf( "%6d : ", f ); + Gia_ManPrintStats( pFrames, NULL ); + } + Gia_ManForEachRo( pAig, pObj, i ) + pObj->Value = f ? Gia_ObjRoToRi( pAig, pObj )->Value : 0; + Gia_ManForEachPi( pAig, pObj, i ) + pObj->Value = Gia_ManAppendCi( pFrames ); + Gia_ManForEachAnd( pAig, pObj, i ) + pObj->Value = Gia_ManHashAnd( pFrames, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachPo( pAig, pObj, i ) + if ( Gia_ObjFanin0Copy(pObj) != 0 ) + break; + if ( i < Gia_ManPoNum(pAig) ) + break; + Gia_ManForEachRi( pAig, pObj, i ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + } + if ( fVerbose ) + printf( "Computed prefix of %d frames.\n", f ); + Gia_ManForEachRi( pAig, pObj, i ) + Gia_ManAppendCo( pFrames, pObj->Value ); + Gia_ManHashStop( pFrames ); + pFrames = Gia_ManCleanup( pTemp = pFrames ); + if ( fVerbose ) + printf( "Before cleanup = %d nodes. After cleanup = %d nodes.\n", + Gia_ManAndNum(pTemp), Gia_ManAndNum(pFrames) ); + Gia_ManStop( pTemp ); + return pFrames; +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaFront.c b/yosys/abc/src/aig/gia/giaFront.c new file mode 100644 index 00000000000..8c7e06e507f --- /dev/null +++ b/yosys/abc/src/aig/gia/giaFront.c @@ -0,0 +1,295 @@ +/**CFile**************************************************************** + + FileName [giaFront.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Frontier representation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaFront.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Find the next place on the frontier.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManFrontFindNext( char * pFront, int nFront, int iFront ) +{ + assert( iFront < nFront ); + for ( ; pFront[iFront]; iFront = (iFront + 1) % nFront ); + assert( pFront[iFront] == 0 ); + pFront[iFront] = 1; + return iFront; +} + +/**Function************************************************************* + + Synopsis [Transforms the frontier manager to its initial state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManFrontTransform( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, * pFrontToId; // mapping of nodes into frontier variables + assert( p->nFront > 0 ); + pFrontToId = ABC_FALLOC( int, p->nFront ); + Gia_ManForEachObj( p, pObj, i ) + { + if ( Gia_ObjIsCo(pObj) ) + { + assert( pObj->Value == GIA_NONE ); + pObj->iDiff0 = i - pFrontToId[Gia_ObjDiff0(pObj)]; + } + else if ( Gia_ObjIsAnd(pObj) ) + { + assert( (int)pObj->Value < p->nFront ); + pObj->iDiff0 = i - pFrontToId[Gia_ObjDiff0(pObj)]; + pObj->iDiff1 = i - pFrontToId[Gia_ObjDiff1(pObj)]; + pFrontToId[pObj->Value] = i; + } + else + { + assert( (int)pObj->Value < p->nFront ); + pFrontToId[pObj->Value] = i; + } + pObj->Value = 0; + } + ABC_FREE( pFrontToId ); +} + +/**Function************************************************************* + + Synopsis [Determine the frontier.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCrossCutSimple( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, nCutCur = 0, nCutMax = 0; + Gia_ManCreateValueRefs( p ); + Gia_ManForEachObj( p, pObj, i ) + { + if ( pObj->Value ) + nCutCur++; + if ( nCutMax < nCutCur ) + nCutMax = nCutCur; + if ( Gia_ObjIsAnd(pObj) ) + { + if ( --Gia_ObjFanin0(pObj)->Value == 0 ) + nCutCur--; + if ( --Gia_ObjFanin1(pObj)->Value == 0 ) + nCutCur--; + } + else if ( Gia_ObjIsCo(pObj) ) + { + if ( --Gia_ObjFanin0(pObj)->Value == 0 ) + nCutCur--; + } + } +// Gia_ManForEachObj( p, pObj, i ) +// assert( pObj->Value == 0 ); + return nCutMax; +} + + +/**Function************************************************************* + + Synopsis [Determine the frontier.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManFront( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj, * pFanin0New, * pFanin1New, * pObjNew; + char * pFront; // places used for the frontier + int i, iLit, nCrossCut = 0, nCrossCutMax = 0; + int nCrossCutMaxInit = Gia_ManCrossCutSimple( p ); + int iFront = 0;//, clk = Abc_Clock(); + // set references for all objects + Gia_ManCreateValueRefs( p ); + // start the new manager + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nFront = 1 + (int)((float)1.1 * nCrossCutMaxInit); + // start the frontier + pFront = ABC_CALLOC( char, pNew->nFront ); + // add constant node + Gia_ManConst0(pNew)->Value = iFront = Gia_ManFrontFindNext( pFront, pNew->nFront, iFront ); + if ( Gia_ObjValue(Gia_ManConst0(p)) == 0 ) + pFront[iFront] = 0; + else + nCrossCut = 1; + // iterate through the objects + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + { + if ( Gia_ObjValue(pObj) && nCrossCutMax < ++nCrossCut ) + nCrossCutMax = nCrossCut; + // create new node + iLit = Gia_ManAppendCi( pNew ); + pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(iLit) ); + assert( Gia_ObjId(pNew, pObjNew) == Gia_ObjId(p, pObj) ); + pObjNew->Value = iFront = Gia_ManFrontFindNext( pFront, pNew->nFront, iFront ); + // handle CIs without fanout + if ( Gia_ObjValue(pObj) == 0 ) + pFront[iFront] = 0; + continue; + } + if ( Gia_ObjIsCo(pObj) ) + { + assert( Gia_ObjValue(pObj) == 0 ); + // create new node + iLit = Gia_ManAppendCo( pNew, 0 ); + pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(iLit) ); + assert( Gia_ObjId(pNew, pObjNew) == Gia_ObjId(p, pObj) ); + // get the fanin + pFanin0New = Gia_ManObj( pNew, Gia_ObjFaninId0(pObj, i) ); + assert( pFanin0New->Value != GIA_NONE ); + pObjNew->Value = GIA_NONE; + pObjNew->iDiff0 = pFanin0New->Value; + pObjNew->fCompl0 = Gia_ObjFaninC0(pObj); + // deref the fanin + if ( --Gia_ObjFanin0(pObj)->Value == 0 ) + { + pFront[pFanin0New->Value] = 0; + nCrossCut--; + } + continue; + } + if ( Gia_ObjValue(pObj) && nCrossCutMax < ++nCrossCut ) + nCrossCutMax = nCrossCut; + // create new node + pObjNew = Gia_ManAppendObj( pNew ); + assert( Gia_ObjId(pNew, pObjNew) == Gia_ObjId(p, pObj) ); + // assign the first fanin + pFanin0New = Gia_ManObj( pNew, Gia_ObjFaninId0(pObj, i) ); + assert( pFanin0New->Value != GIA_NONE ); + pObjNew->iDiff0 = pFanin0New->Value; + pObjNew->fCompl0 = Gia_ObjFaninC0(pObj); + // assign the second fanin + pFanin1New = Gia_ManObj( pNew, Gia_ObjFaninId1(pObj, i) ); + assert( pFanin1New->Value != GIA_NONE ); + pObjNew->iDiff1 = pFanin1New->Value; + pObjNew->fCompl1 = Gia_ObjFaninC1(pObj); + // assign the frontier number + pObjNew->Value = iFront = Gia_ManFrontFindNext( pFront, pNew->nFront, iFront ); + // deref the fanins + if ( --Gia_ObjFanin0(pObj)->Value == 0 ) + { + pFront[pFanin0New->Value] = 0; + nCrossCut--; + } + if ( --Gia_ObjFanin1(pObj)->Value == 0 ) + { + pFront[pFanin1New->Value] = 0; + nCrossCut--; + } + // handle nodes without fanout (choice nodes) + if ( Gia_ObjValue(pObj) == 0 ) + pFront[iFront] = 0; + } + assert( pNew->nObjs == p->nObjs ); + assert( nCrossCut == 0 || nCrossCutMax == nCrossCutMaxInit ); + for ( i = 0; i < pNew->nFront; i++ ) + assert( pFront[i] == 0 ); + ABC_FREE( pFront ); +//printf( "Crosscut = %6d. Frontier = %6d. ", nCrossCutMaxInit, pNew->nFront ); +//ABC_PRT( "Time", Abc_Clock() - clk ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManFrontTest( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + pNew = Gia_ManFront( p ); + Gia_ManFrontTransform( pNew ); +// Gia_ManCleanValue( p ); +// Gia_ManCleanValue( pNew ); + if ( memcmp( pNew->pObjs, p->pObjs, sizeof(Gia_Obj_t) * p->nObjs ) ) + { +/* + Gia_Obj_t * pObj, * pObjNew; + int i; + Gia_ManForEachObj( p, pObj, i ) + { + pObjNew = Gia_ManObj( pNew, i ); + printf( "%5d %5d %5d %5d\n", + pObj->iDiff0, pObjNew->iDiff0, + pObj->iDiff1, pObjNew->iDiff1 ); + } +*/ + printf( "Verification failed.\n" ); + } + else + printf( "Verification successful.\n" ); + Gia_ManStop( pNew ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaFx.c b/yosys/abc/src/aig/gia/giaFx.c new file mode 100644 index 00000000000..7517072e7ac --- /dev/null +++ b/yosys/abc/src/aig/gia/giaFx.c @@ -0,0 +1,500 @@ +/**CFile**************************************************************** + + FileName [giaFx.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Interface to fast_extract package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaFx.c,v 1.00 2013/09/29 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "bool/kit/kit.h" +#include "misc/vec/vecWec.h" +#include "bool/dec/dec.h" +#include "opt/dau/dau.h" +#include "misc/util/utilTruth.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Create GIA for SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManGraphToAig( Gia_Man_t * p, Dec_Graph_t * pGraph ) +{ + Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized" + int i, iAnd0, iAnd1; + // check for constant function + if ( Dec_GraphIsConst(pGraph) ) + return Abc_LitNotCond( 1, Dec_GraphIsComplement(pGraph) ); + // check for a literal + if ( Dec_GraphIsVar(pGraph) ) + return Abc_LitNotCond( Dec_GraphVar(pGraph)->iFunc, Dec_GraphIsComplement(pGraph) ); + // build the AIG nodes corresponding to the AND gates of the graph + Dec_GraphForEachNode( pGraph, pNode, i ) + { + iAnd0 = Abc_LitNotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->iFunc, pNode->eEdge0.fCompl ); + iAnd1 = Abc_LitNotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->iFunc, pNode->eEdge1.fCompl ); + pNode->iFunc = Gia_ManHashAnd( p, iAnd0, iAnd1 ); + } + // complement the result if necessary + return Abc_LitNotCond( pNode->iFunc, Dec_GraphIsComplement(pGraph) ); +} +int Gia_ManSopToAig( Gia_Man_t * p, char * pSop, Vec_Int_t * vLeaves ) +{ + int i, iAnd, iSum, Value, nFanins; + char * pCube; + // get the number of variables + nFanins = Kit_PlaGetVarNum(pSop); + // go through the cubes of the node's SOP + iSum = 0; + Kit_PlaForEachCube( pSop, nFanins, pCube ) + { + // create the AND of literals + iAnd = 1; + Kit_PlaCubeForEachVar( pCube, Value, i ) + { + assert( Vec_IntEntry(vLeaves, i) >= 0 ); + if ( Value == '1' ) + iAnd = Gia_ManHashAnd( p, iAnd, Vec_IntEntry(vLeaves, i) ); + else if ( Value == '0' ) + iAnd = Gia_ManHashAnd( p, iAnd, Abc_LitNot(Vec_IntEntry(vLeaves, i)) ); + else assert( Value == '-' ); + } + // add to the sum of cubes + iSum = Gia_ManHashOr( p, iSum, iAnd ); + } + // decide whether to complement the result + if ( Kit_PlaIsComplement(pSop) ) + iSum = Abc_LitNot(iSum); + return iSum; +} +int Gia_ManFactorGraph( Gia_Man_t * p, Dec_Graph_t * pFForm, Vec_Int_t * vLeaves ) +{ + Dec_Node_t * pFFNode; + int i, Lit; + // assign fanins + Dec_GraphForEachLeaf( pFForm, pFFNode, i ) + { + assert( Vec_IntEntry(vLeaves, i) >= 0 ); + pFFNode->iFunc = Vec_IntEntry(vLeaves, i); + } + // perform strashing + Lit = Gia_ManGraphToAig( p, pFForm ); + return Lit; +} +int Gia_ManFactorNode( Gia_Man_t * p, char * pSop, Vec_Int_t * vLeaves ) +{ + if ( Kit_PlaGetVarNum(pSop) == 0 ) + return Abc_LitNotCond( 1, Kit_PlaIsConst0(pSop) ); + assert( Kit_PlaGetVarNum(pSop) == Vec_IntSize(vLeaves) ); + if ( Kit_PlaGetVarNum(pSop) > 2 && Kit_PlaGetCubeNum(pSop) > 1 ) + { + Dec_Graph_t * pFForm = Dec_Factor( pSop ); + int Lit = Gia_ManFactorGraph( p, pFForm, vLeaves ); + Dec_GraphFree( pFForm ); + return Lit; + } + return Gia_ManSopToAig( p, pSop, vLeaves ); +} + +/**Function************************************************************* + + Synopsis [Computing truth tables for the mapped network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wrd_t * Gia_ManComputeTruths( Gia_Man_t * p, int nCutSize, int nLutNum, int fReverse ) +{ + Vec_Wrd_t * vTruths; + Vec_Int_t vLeaves; + word * pTruth; + int i, k, nWords; + nWords = Abc_Truth6WordNum( nCutSize ); + vTruths = Vec_WrdAlloc( nWords * nLutNum ); + Gia_ObjComputeTruthTableStart( p, nCutSize ); + Gia_ManForEachLut( p, i ) + { + // collect and sort fanins + vLeaves.nCap = vLeaves.nSize = Gia_ObjLutSize( p, i ); + vLeaves.pArray = Gia_ObjLutFanins( p, i ); + if( !Vec_IntCheckUniqueSmall(&vLeaves) ) + { + Vec_IntUniqify(&vLeaves); + Vec_IntWriteEntry(p->vMapping, Vec_IntEntry(p->vMapping, i), vLeaves.nSize); + for ( k = 0; k < vLeaves.nSize; k++ ) + Vec_IntWriteEntry(p->vMapping, Vec_IntEntry(p->vMapping, i) + 1 + k, vLeaves.pArray[k]); + } + assert( Vec_IntCheckUniqueSmall(&vLeaves) ); + Vec_IntSelectSort( Vec_IntArray(&vLeaves), Vec_IntSize(&vLeaves) ); + if ( !fReverse ) + Vec_IntReverseOrder( &vLeaves ); + // compute truth table + pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ManObj(p, i), &vLeaves ); + for ( k = 0; k < nWords; k++ ) + Vec_WrdPush( vTruths, pTruth[k] ); +// Kit_DsdPrintFromTruth( (unsigned *)pTruth, 6 ); printf( "\n" ); + } + Gia_ObjComputeTruthTableStop( p ); + assert( Vec_WrdCap(vTruths) == 16 || Vec_WrdSize(vTruths) == Vec_WrdCap(vTruths) ); + return vTruths; +} + +/**Function************************************************************* + + Synopsis [Extracts information about the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManAssignNumbers( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, Counter = 0; + Gia_ManFillValue( p ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Counter++; + Gia_ManForEachLut( p, i ) + Gia_ManObj(p, i)->Value = Counter++; + return Counter; +} +Vec_Wec_t * Gia_ManFxRetrieve( Gia_Man_t * p, Vec_Str_t ** pvCompl, int fReverse ) +{ + Vec_Wec_t * vCubes; + Vec_Wrd_t * vTruths; + Vec_Int_t * vCube, * vCover; + int nItems, nCutSize, nWords; + int i, c, v, Lit, Cube, Counter = 0; +// abctime clk = Abc_Clock(); + nItems = Gia_ManAssignNumbers( p ); + // compute truth tables + nCutSize = Gia_ManLutSizeMax( p ); + nWords = Abc_Truth6WordNum( nCutSize ); + vTruths = Gia_ManComputeTruths( p, nCutSize, nItems - Gia_ManCiNum(p), fReverse ); + vCover = Vec_IntAlloc( 1 << 16 ); + // collect cubes + vCubes = Vec_WecAlloc( 1000 ); + *pvCompl = Vec_StrStart( nItems ); + Gia_ManForEachLut( p, i ) + { + Gia_Obj_t * pObj = Gia_ManObj( p, i ); + int nVars = Gia_ObjLutSize( p, i ); + int * pVars = Gia_ObjLutFanins( p, i ); + word * pTruth = Vec_WrdEntryP( vTruths, Counter++ * nWords ); + Abc_TtFlipVar5( pTruth, nVars ); + int Status = Kit_TruthIsop( (unsigned *)pTruth, nVars, vCover, 1 ); + Abc_TtFlipVar5( pTruth, nVars ); + if ( Vec_IntSize(vCover) == 0 || (Vec_IntSize(vCover) == 1 && Vec_IntEntry(vCover,0) == 0) ) + { + Vec_StrWriteEntry( *pvCompl, pObj->Value, (char)(Vec_IntSize(vCover) == 0) ); + vCube = Vec_WecPushLevel( vCubes ); + Vec_IntPush( vCube, pObj->Value ); + continue; + } + Vec_StrWriteEntry( *pvCompl, pObj->Value, (char)Status ); + Vec_IntForEachEntry( vCover, Cube, c ) + { + vCube = Vec_WecPushLevel( vCubes ); + Vec_IntPush( vCube, pObj->Value ); + for ( v = 0; v < nVars; v++ ) + { + Lit = 3 & (Cube >> (v << 1)); + if ( Lit == 1 ) + Vec_IntPush( vCube, Abc_Var2Lit(Gia_ManObj(p, pVars[v])->Value, 1) ); + else if ( Lit == 2 ) + Vec_IntPush( vCube, Abc_Var2Lit(Gia_ManObj(p, pVars[v])->Value, 0) ); + else if ( Lit != 0 ) + assert( 0 ); + } + Vec_IntSelectSort( Vec_IntArray(vCube) + 1, Vec_IntSize(vCube) - 1 ); + } + } + assert( Counter * nWords == Vec_WrdSize(vTruths) ); + Vec_WrdFree( vTruths ); + Vec_IntFree( vCover ); +// Abc_PrintTime( 1, "Setup time", Abc_Clock() - clk ); + return vCubes; +} + +/**Function************************************************************* + + Synopsis [Generates GIA after factoring the resulting SOPs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManFxTopoOrder_rec( Vec_Wec_t * vCubes, Vec_Int_t * vFirst, Vec_Int_t * vCount, Vec_Int_t * vVisit, Vec_Int_t * vOrder, int iObj ) +{ + int c, v, Lit; + int iFirst = Vec_IntEntry( vFirst, iObj ); + int nCubes = Vec_IntEntry( vCount, iObj ); + assert( !Vec_IntEntry( vVisit, iObj ) ); + Vec_IntWriteEntry( vVisit, iObj, 1 ); + for ( c = 0; c < nCubes; c++ ) + { + Vec_Int_t * vCube = Vec_WecEntry( vCubes, iFirst + c ); + assert( Vec_IntEntry(vCube, 0) == iObj ); + Vec_IntForEachEntryStart( vCube, Lit, v, 1 ) + if ( !Vec_IntEntry( vVisit, Abc_Lit2Var(Lit) ) ) + Gia_ManFxTopoOrder_rec( vCubes, vFirst, vCount, vVisit, vOrder, Abc_Lit2Var(Lit) ); + } + Vec_IntPush( vOrder, iObj ); +} +Vec_Int_t * Gia_ManFxTopoOrder( Vec_Wec_t * vCubes, int nInputs, int nStart, Vec_Int_t ** pvFirst, Vec_Int_t ** pvCount ) +{ + Vec_Int_t * vOrder, * vFirst, * vCount, * vVisit, * vCube; + int i, iFanin, nNodeMax = -1; + // find the largest index + Vec_WecForEachLevel( vCubes, vCube, i ) + nNodeMax = Abc_MaxInt( nNodeMax, Vec_IntEntry(vCube, 0) ); + nNodeMax++; + // quit if there is no new nodes + if ( nNodeMax == nStart ) + { + //printf( "The network is unchanged by fast extract.\n" ); + return NULL; + } + // find first cube and how many cubes + vFirst = Vec_IntStart( nNodeMax ); + vCount = Vec_IntStart( nNodeMax ); + Vec_WecForEachLevel( vCubes, vCube, i ) + { + iFanin = Vec_IntEntry( vCube, 0 ); + assert( iFanin >= nInputs ); + if ( Vec_IntEntry(vCount, iFanin) == 0 ) + Vec_IntWriteEntry( vFirst, iFanin, i ); + Vec_IntAddToEntry( vCount, iFanin, 1 ); + } + // put all of them in a topo order + vOrder = Vec_IntStart( nInputs ); + vVisit = Vec_IntStart( nNodeMax ); + for ( i = 0; i < nInputs; i++ ) + Vec_IntWriteEntry( vVisit, i, 1 ); + for ( i = nInputs; i < nNodeMax; i++ ) + if ( !Vec_IntEntry( vVisit, i ) ) + Gia_ManFxTopoOrder_rec( vCubes, vFirst, vCount, vVisit, vOrder, i ); + assert( Vec_IntSize(vOrder) == nNodeMax ); + Vec_IntFree( vVisit ); + // return topological order of new nodes + *pvFirst = vFirst; + *pvCount = vCount; + return vOrder; +} +Gia_Man_t * Gia_ManFxInsert( Gia_Man_t * p, Vec_Wec_t * vCubes, Vec_Str_t * vCompls ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; Vec_Str_t * vSop; + Vec_Int_t * vOrder, * vFirst, * vCount, * vFanins, * vCover; + Vec_Int_t * vCopies, * vCube, * vMap; + int k, c, v, Lit, Var, iItem; +// abctime clk = Abc_Clock(); + // prepare the cubes + vOrder = Gia_ManFxTopoOrder( vCubes, Gia_ManCiNum(p), Vec_StrSize(vCompls), &vFirst, &vCount ); + if ( vOrder == NULL ) + return Gia_ManDup( p ); + assert( Vec_IntSize(vOrder) > Vec_StrSize(vCompls) ); + // create new manager + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->vLevels = Vec_IntStart( 6*Gia_ManObjNum(p)/5 + 100 ); + Gia_ManHashStart( pNew ); + // create primary inputs + vMap = Vec_IntStartFull( Vec_IntSize(vOrder) ); + vCopies = Vec_IntAlloc( Vec_IntSize(vOrder) ); + Gia_ManForEachCi( p, pObj, k ) + Vec_IntPush( vCopies, Gia_ManAppendCi(pNew) ); + Vec_IntFillExtra( vCopies, Vec_IntSize(vOrder), -1 ); + // add AIG nodes in the topological order + vSop = Vec_StrAlloc( 1000 ); + vCover = Vec_IntAlloc( 1 << 16 ); + vFanins = Vec_IntAlloc( 100 ); + Vec_IntForEachEntryStart( vOrder, iItem, k, Gia_ManCiNum(p) ) + { + int iFirst = Vec_IntEntry( vFirst, iItem ); + int nCubes = Vec_IntEntry( vCount, iItem ); + // collect fanins + Vec_IntClear( vFanins ); + for ( c = 0; c < nCubes; c++ ) + { + vCube = Vec_WecEntry( vCubes, iFirst + c ); + Vec_IntForEachEntryStart( vCube, Lit, v, 1 ) + if ( Vec_IntEntry(vMap, Abc_Lit2Var(Lit)) == -1 ) + { + Vec_IntWriteEntry( vMap, Abc_Lit2Var(Lit), Vec_IntSize(vFanins) ); + Vec_IntPush( vFanins, Abc_Lit2Var(Lit) ); + } + } + if ( Vec_IntSize(vFanins) > 6 ) + { + // create SOP + Vec_StrClear( vSop ); + for ( c = 0; c < nCubes; c++ ) + { + for ( v = 0; v < Vec_IntSize(vFanins); v++ ) + Vec_StrPush( vSop, '-' ); + vCube = Vec_WecEntry( vCubes, iFirst + c ); + Vec_IntForEachEntryStart( vCube, Lit, v, 1 ) + { + Lit = Abc_Lit2LitV( Vec_IntArray(vMap), Lit ); + assert( Lit >= 0 && Abc_Lit2Var(Lit) < Vec_IntSize(vFanins) ); + Vec_StrWriteEntry( vSop, Vec_StrSize(vSop) - Vec_IntSize(vFanins) + Abc_Lit2Var(Lit), (char)(Abc_LitIsCompl(Lit)? '0' : '1') ); + } + Vec_StrPush( vSop, ' ' ); + Vec_StrPush( vSop, '1' ); + Vec_StrPush( vSop, '\n' ); + } + Vec_StrPush( vSop, '\0' ); + // collect fanins + Vec_IntForEachEntry( vFanins, Var, v ) + { + Vec_IntWriteEntry( vMap, Var, -1 ); + Vec_IntWriteEntry( vFanins, v, Vec_IntEntry(vCopies, Var) ); + } + // derive new AIG + Lit = Gia_ManFactorNode( pNew, Vec_StrArray(vSop), vFanins ); + } + else + { + word uTruth = 0, uCube; + for ( c = 0; c < nCubes; c++ ) + { + uCube = ~(word)0; + vCube = Vec_WecEntry( vCubes, iFirst + c ); + Vec_IntForEachEntryStart( vCube, Lit, v, 1 ) + { + Lit = Abc_Lit2LitV( Vec_IntArray(vMap), Lit ); + assert( Lit >= 0 && Abc_Lit2Var(Lit) < Vec_IntSize(vFanins) ); + uCube &= Abc_LitIsCompl(Lit) ? ~s_Truths6[Abc_Lit2Var(Lit)] : s_Truths6[Abc_Lit2Var(Lit)]; + } + uTruth |= uCube; + } + // complement constant + if ( uTruth == 0 ) + uTruth = ~uTruth; + // collect fanins + Vec_IntForEachEntry( vFanins, Var, v ) + { + Vec_IntWriteEntry( vMap, Var, -1 ); + Vec_IntWriteEntry( vFanins, v, Vec_IntEntry(vCopies, Var) ); + } + // create truth table + Lit = Dsm_ManTruthToGia( pNew, &uTruth, vFanins, vCover ); + } + // complement if the original SOP was complemented + Lit = Abc_LitNotCond( Lit, (iItem < Vec_StrSize(vCompls)) && (Vec_StrEntry(vCompls, iItem) > 0) ); + // remeber this literal + assert( Vec_IntEntry(vCopies, iItem) == -1 ); + Vec_IntWriteEntry( vCopies, iItem, Lit ); + } + Gia_ManHashStop( pNew ); + // create primary outputs + Gia_ManForEachCo( p, pObj, k ) + { + Lit = Gia_ObjFaninId0p(p, pObj) ? Vec_IntEntry(vCopies, Gia_ObjFanin0(pObj)->Value) : 0; + Gia_ManAppendCo( pNew, Abc_LitNotCond( Lit, Gia_ObjFaninC0(pObj) ) ); + } + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + // cleanup + Vec_IntFree( vOrder ); + Vec_IntFree( vFirst ); + Vec_IntFree( vCount ); + Vec_IntFree( vFanins ); + Vec_IntFree( vCopies ); + Vec_IntFree( vMap ); + Vec_StrFree( vSop ); + Vec_IntFree( vCover ); + // remove dangling nodes + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); +// Abc_PrintTime( 1, "Setdn time", Abc_Clock() - clk ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Performs classical fast_extract on logic functions.] + + Description [] + + SideEffects [Sorts the fanins of each cut in the increasing order.] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManPerformFx( Gia_Man_t * p, int nNewNodesMax, int LitCountMax, int fReverse, int fVerbose, int fVeryVerbose ) +{ + extern int Fx_FastExtract( Vec_Wec_t * vCubes, int ObjIdMax, int nNewNodesMax, int LitCountMax, int fCanonDivs, int fVerbose, int fVeryVerbose ); + Gia_Man_t * pNew = NULL; + Vec_Wec_t * vCubes; + Vec_Str_t * vCompl; + if ( Gia_ManAndNum(p) == 0 ) + { + pNew = Gia_ManDup(p); + Gia_ManTransferTiming( pNew, p ); + return pNew; + } +// abctime clk; + assert( Gia_ManHasMapping(p) ); + // collect information + vCubes = Gia_ManFxRetrieve( p, &vCompl, fReverse ); + // call the fast extract procedure +// clk = Abc_Clock(); + Fx_FastExtract( vCubes, Vec_StrSize(vCompl), nNewNodesMax, LitCountMax, 0, fVerbose, fVeryVerbose ); +// Abc_PrintTime( 1, "Fx runtime", Abc_Clock() - clk ); + // insert information + pNew = Gia_ManFxInsert( p, vCubes, vCompl ); + Gia_ManTransferTiming( pNew, p ); + // cleanup + Vec_WecFree( vCubes ); + Vec_StrFree( vCompl ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaGen.c b/yosys/abc/src/aig/gia/giaGen.c new file mode 100644 index 00000000000..a807fe60f75 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaGen.c @@ -0,0 +1,1370 @@ +/**CFile**************************************************************** + + FileName [giaGen.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaGen.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/util/utilTruth.h" +#include "misc/extra/extra.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_DeriveAig( Vec_Wrd_t * vSims, Vec_Str_t * vSimsOut ) +{ + int nInputs = 32*32*24; + int nWords = nInputs/64; + int nExamps = 64; + int i, e, iLitOut[10] = {0}; + Gia_Man_t * pNew; + assert( Vec_WrdSize(vSims) % nInputs == 0 ); + pNew = Gia_ManStart( nInputs * nExamps + 10000 ); + for ( i = 0; i < nInputs; i++ ) + Gia_ManAppendCi( pNew ); + Gia_ManHashStart( pNew ); + for ( e = 0; e < nExamps; e++ ) + { + int Class = Vec_StrEntry( vSimsOut, e ); + int This = 1; + word * pSim = Vec_WrdEntryP( vSims, e*nWords ); + for ( i = 0; i < nInputs; i++ ) + This = Gia_ManHashAnd( pNew, This, Abc_Var2Lit(i+1, !Abc_TtGetBit(pSim, i)) ); + assert( Class >= 0 && Class <= 9 ); + iLitOut[Class] = Gia_ManHashOr( pNew, iLitOut[Class], This ); + //printf( "Finished example %d\n", e ); + } + for ( i = 0; i < 10; i++ ) + Gia_ManAppendCo( pNew, iLitOut[i] ); + //pNew = Gia_ManCleanup( pTemp = pNew ); + //Gia_ManStop( pTemp ); + return pNew; +} +void Gia_DeriveAigTest() +{ + extern int Gia_ManReadCifar10File( char * pFileName, Vec_Wrd_t ** pvSimsIn, Vec_Str_t ** pvSimsOut, int * pnExamples ); + char pFileName[100] = "test"; + Vec_Wrd_t * vSimsIn; + Vec_Str_t * vSimsOut; + int nExamples = 0; + int nInputs = Gia_ManReadCifar10File( pFileName, &vSimsIn, &vSimsOut, &nExamples ); + Gia_Man_t * pThis = Gia_DeriveAig( vSimsIn, vSimsOut ); + Gia_AigerWrite( pThis, "examples64.aig", 0, 0, 0 ); + printf( "Dumped file \"%s\".\n", "examples64.aig" ); + Gia_ManStop( pThis ); + Vec_WrdFree( vSimsIn ); + Vec_StrFree( vSimsOut ); + nInputs = 0; +} + + +/**Function************************************************************* + + Synopsis [Populate internal simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline word * Gia_ManObjSim( Gia_Man_t * p, int iObj ) +{ + return Vec_WrdEntryP( p->vSims, p->nSimWords * iObj ); +} +static inline void Gia_ManObjSimPi( Gia_Man_t * p, int iObj ) +{ + int w; + word * pSim = Gia_ManObjSim( p, iObj ); + for ( w = 0; w < p->nSimWords; w++ ) + pSim[w] = Gia_ManRandomW( 0 ); +// pSim[0] <<= 1; +} +static inline void Gia_ManObjSimPo( Gia_Man_t * p, int iObj ) +{ + int w; + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + word * pSimCo = Gia_ManObjSim( p, iObj ); + word * pSimDri = Gia_ManObjSim( p, Gia_ObjFaninId0(pObj, iObj) ); + if ( Gia_ObjFaninC0(pObj) ) + for ( w = 0; w < p->nSimWords; w++ ) + pSimCo[w] = ~pSimDri[w]; + else + for ( w = 0; w < p->nSimWords; w++ ) + pSimCo[w] = pSimDri[w]; +} +static inline void Gia_ManObjSimAnd( Gia_Man_t * p, int iObj ) +{ + int w; + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + word * pSim = Gia_ManObjSim( p, iObj ); + word * pSim0 = Gia_ManObjSim( p, Gia_ObjFaninId0(pObj, iObj) ); + word * pSim1 = Gia_ManObjSim( p, Gia_ObjFaninId1(pObj, iObj) ); + if ( Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ) + for ( w = 0; w < p->nSimWords; w++ ) + pSim[w] = ~pSim0[w] & ~pSim1[w]; + else if ( Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ) + for ( w = 0; w < p->nSimWords; w++ ) + pSim[w] = ~pSim0[w] & pSim1[w]; + else if ( !Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ) + for ( w = 0; w < p->nSimWords; w++ ) + pSim[w] = pSim0[w] & ~pSim1[w]; + else + for ( w = 0; w < p->nSimWords; w++ ) + pSim[w] = pSim0[w] & pSim1[w]; +} +int Gia_ManSimulateWords( Gia_Man_t * p, int nWords ) +{ + Gia_Obj_t * pObj; int i; + // allocate simulation info for one timeframe + Vec_WrdFreeP( &p->vSims ); + p->vSims = Vec_WrdStart( Gia_ManObjNum(p) * nWords ); + p->nSimWords = nWords; + // perform simulation + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + Gia_ManObjSimAnd( p, i ); + else if ( Gia_ObjIsCi(pObj) ) + Gia_ManObjSimPi( p, i ); + else if ( Gia_ObjIsCo(pObj) ) + Gia_ManObjSimPo( p, i ); + else assert( 0 ); + } + return 1; +} + +int Gia_ManSimulateWordsInit( Gia_Man_t * p, Vec_Wrd_t * vSimsIn ) +{ + Gia_Obj_t * pObj; int i, Id; + int nWords = Vec_WrdSize(vSimsIn) / Gia_ManCiNum(p); + assert( Vec_WrdSize(vSimsIn) == nWords * Gia_ManCiNum(p) ); + // allocate simulation info for one timeframe + Vec_WrdFreeP( &p->vSims ); + p->vSims = Vec_WrdStart( Gia_ManObjNum(p) * nWords ); + p->nSimWords = nWords; + // set input sim info + Gia_ManForEachCiId( p, Id, i ) + memcpy( Vec_WrdEntryP(p->vSims, Id*nWords), Vec_WrdEntryP(vSimsIn, i*nWords), sizeof(word)*nWords ); + // perform simulation + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + Gia_ManObjSimAnd( p, i ); + else if ( Gia_ObjIsCi(pObj) ) + continue; + else if ( Gia_ObjIsCo(pObj) ) + Gia_ManObjSimPo( p, i ); + else assert( 0 ); + } + return 1; +} + +Vec_Wrd_t * Gia_ManSimulateWordsOut( Gia_Man_t * p, Vec_Wrd_t * vSimsIn ) +{ + Gia_Obj_t * pObj; int i, Id; + int nWords = Vec_WrdSize(vSimsIn) / Gia_ManCiNum(p); + Vec_Wrd_t * vSimsOut = Vec_WrdStart( nWords * Gia_ManCoNum(p) ); + assert( Vec_WrdSize(vSimsIn) == nWords * Gia_ManCiNum(p) ); + // allocate simulation info for one timeframe + Vec_WrdFreeP( &p->vSims ); + p->vSims = Vec_WrdStart( Gia_ManObjNum(p) * nWords ); + p->nSimWords = nWords; + // set input sim info + Gia_ManForEachCiId( p, Id, i ) + memcpy( Vec_WrdEntryP(p->vSims, Id*nWords), Vec_WrdEntryP(vSimsIn, i*nWords), sizeof(word)*nWords ); + // perform simulation + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + Gia_ManObjSimAnd( p, i ); + else if ( Gia_ObjIsCi(pObj) ) + continue; + else if ( Gia_ObjIsCo(pObj) ) + Gia_ManObjSimPo( p, i ); + else assert( 0 ); + } + // set output sim info + Gia_ManForEachCoId( p, Id, i ) + memcpy( Vec_WrdEntryP(vSimsOut, i*nWords), Vec_WrdEntryP(p->vSims, Id*nWords), sizeof(word)*nWords ); + Vec_WrdFreeP( &p->vSims ); + p->nSimWords = -1; + return vSimsOut; +} + +/**Function************************************************************* + + Synopsis [Dump data files.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDumpFiles( Gia_Man_t * p, int nCexesT, int nCexesV, int Seed, char * pFileName ) +{ + int n, nSize[2] = {nCexesT*64, nCexesV*64}; + + char pFileNameOutTX[100]; + char pFileNameOutTY[100]; + char pFileNameOutVX[100]; + char pFileNameOutVY[100]; + char pFileNameOut[100]; + + //sprintf( pFileNameOutTX, "train_%s_%d_%d.data", pFileName ? pFileName : Gia_ManName(p), nSize[0], Gia_ManCiNum(p) ); + //sprintf( pFileNameOutTY, "train_%s_%d_%d.data", pFileName ? pFileName : Gia_ManName(p), nSize[0], Gia_ManCoNum(p) ); + //sprintf( pFileNameOutVX, "test_%s_%d_%d.data", pFileName ? pFileName : Gia_ManName(p), nSize[1], Gia_ManCiNum(p) ); + //sprintf( pFileNameOutVY, "test_%s_%d_%d.data", pFileName ? pFileName : Gia_ManName(p), nSize[1], Gia_ManCoNum(p) ); + + sprintf( pFileNameOutTX, "%s_x.train.data", pFileName ? pFileName : Gia_ManName(p) ); + sprintf( pFileNameOutTY, "%s_y.train.data", pFileName ? pFileName : Gia_ManName(p) ); + sprintf( pFileNameOutVX, "%s_x.test.data", pFileName ? pFileName : Gia_ManName(p) ); + sprintf( pFileNameOutVY, "%s_y.test.data", pFileName ? pFileName : Gia_ManName(p) ); + + Gia_ManRandomW( 1 ); + for ( n = 0; n < Seed; n++ ) + Gia_ManRandomW( 0 ); + for ( n = 0; n < 2; n++ ) + { + int Res = Gia_ManSimulateWords( p, nSize[n] ); + + Vec_Bit_t * vBitX = Vec_BitAlloc( nSize[n] * Gia_ManCiNum(p) ); + Vec_Bit_t * vBitY = Vec_BitAlloc( nSize[n] * Gia_ManCoNum(p) ); + + FILE * pFileOutX = fopen( n ? pFileNameOutVX : pFileNameOutTX, "wb" ); + FILE * pFileOutY = fopen( n ? pFileNameOutVY : pFileNameOutTY, "wb" ); + + int i, k, Id, Num, Value, nBytes; + for ( k = 0; k < nSize[n]; k++ ) + { + Gia_ManForEachCiId( p, Id, i ) + { + Vec_BitPush( vBitX, Abc_TtGetBit(Gia_ManObjSim(p, Id), k) ); + //printf( "%d", Abc_TtGetBit(Gia_ManObjSim(p, Id), k) ); + } + //printf( " " ); + Gia_ManForEachCoId( p, Id, i ) + { + Vec_BitPush( vBitY, Abc_TtGetBit(Gia_ManObjSim(p, Id), k) ); + //printf( "%d", Abc_TtGetBit(Gia_ManObjSim(p, Id), k) ); + } + //printf( "\n" ); + } + assert( Vec_BitSize(vBitX) <= Vec_BitCap(vBitX) ); + assert( Vec_BitSize(vBitY) <= Vec_BitCap(vBitY) ); + + Num = 2; Value = fwrite( &Num, 1, 4, pFileOutX ); assert( Value == 4 ); + Num = nSize[n]; Value = fwrite( &Num, 1, 4, pFileOutX ); assert( Value == 4 ); + Num = Gia_ManCiNum(p); Value = fwrite( &Num, 1, 4, pFileOutX ); assert( Value == 4 ); + + nBytes = nSize[n] * Gia_ManCiNum(p) / 8; + assert( nSize[n] * Gia_ManCiNum(p) % 8 == 0 ); + Value = fwrite( Vec_BitArray(vBitX), 1, nBytes, pFileOutX ); + assert( Value == nBytes ); + + Num = 2; Value = fwrite( &Num, 1, 4, pFileOutY ); assert( Value == 4 ); + Num = nSize[n]; Value = fwrite( &Num, 1, 4, pFileOutY ); assert( Value == 4 ); + Num = Gia_ManCoNum(p); Value = fwrite( &Num, 1, 4, pFileOutY ); assert( Value == 4 ); + + nBytes = nSize[n] * Gia_ManCoNum(p) / 8; + assert( nSize[n] * Gia_ManCoNum(p) % 8 == 0 ); + Value = fwrite( Vec_BitArray(vBitY), 1, nBytes, pFileOutY ); + assert( Value == nBytes ); + + fclose( pFileOutX ); + fclose( pFileOutY ); + + Vec_BitFree( vBitX ); + Vec_BitFree( vBitY ); + + Res = 0; + } + printf( "Finished dumping files \"%s\" and \"%s\".\n", pFileNameOutTX, pFileNameOutTY ); + printf( "Finished dumping files \"%s\" and \"%s\".\n", pFileNameOutVX, pFileNameOutVY ); + + sprintf( pFileNameOut, "%s.flist", pFileName ? pFileName : Gia_ManName(p) ); + { + FILE * pFile = fopen( pFileNameOut, "wb" ); + fprintf( pFile, "%s\n", pFileNameOutTX ); + fprintf( pFile, "%s\n", pFileNameOutTY ); + fprintf( pFile, "%s\n", pFileNameOutVX ); + fprintf( pFile, "%s\n", pFileNameOutVY ); + fclose( pFile ); + printf( "Finished dumping file list \"%s\".\n", pFileNameOut ); + } +} + +/**Function************************************************************* + + Synopsis [Dump data files.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDumpPlaFiles( Gia_Man_t * p, int nCexesT, int nCexesV, int Seed, char * pFileName ) +{ + int n, nSize[3] = {nCexesT, nCexesV, nCexesV}; + + char pFileNameOut[3][100]; + + sprintf( pFileNameOut[0], "%s.train.pla", pFileName ? pFileName : Gia_ManName(p) ); + sprintf( pFileNameOut[1], "%s.valid.pla", pFileName ? pFileName : Gia_ManName(p) ); + sprintf( pFileNameOut[2], "%s.test.pla", pFileName ? pFileName : Gia_ManName(p) ); + + Gia_ManRandomW( 1 ); + for ( n = 0; n < Seed; n++ ) + Gia_ManRandomW( 0 ); + for ( n = 0; n < 3; n++ ) + { + int Res = Gia_ManSimulateWords( p, nSize[n] ); + int i, k, Id; + + FILE * pFileOut = fopen( pFileNameOut[n], "wb" ); + + fprintf( pFileOut, ".i %d\n", Gia_ManCiNum(p) ); + fprintf( pFileOut, ".o %d\n", Gia_ManCoNum(p) ); + fprintf( pFileOut, ".p %d\n", nSize[n]*64 ); + fprintf( pFileOut, ".type fr\n" ); + for ( k = 0; k < nSize[n]*64; k++ ) + { + Gia_ManForEachCiId( p, Id, i ) + { + //Vec_BitPush( vBitX, Abc_TtGetBit(Gia_ManObjSim(p, Id), k) ); + fprintf( pFileOut, "%d", Abc_TtGetBit(Gia_ManObjSim(p, Id), k) ); + } + fprintf( pFileOut, " " ); + Gia_ManForEachCoId( p, Id, i ) + { + //Vec_BitPush( vBitY, Abc_TtGetBit(Gia_ManObjSim(p, Id), k) ); + fprintf( pFileOut, "%d", Abc_TtGetBit(Gia_ManObjSim(p, Id), k) ); + } + fprintf( pFileOut, "\n" ); + } + fprintf( pFileOut, ".e\n" ); + + fclose( pFileOut ); + + Res = 0; + } + printf( "Finished dumping files: \"%s.{train, valid, test}.pla\".\n", pFileName ? pFileName : Gia_ManName(p) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimLogStats( Gia_Man_t * p, char * pDumpFile, int Total, int Correct, int Guess ) +{ + FILE * pTable = fopen( pDumpFile, "wb" ); + fprintf( pTable, "{\n" ); + fprintf( pTable, " \"name\" : \"%s\",\n", p->pName ); + fprintf( pTable, " \"input\" : %d,\n", Gia_ManCiNum(p) ); + fprintf( pTable, " \"output\" : %d,\n", Gia_ManCoNum(p) ); + fprintf( pTable, " \"and\" : %d,\n", Gia_ManAndNum(p) ); + fprintf( pTable, " \"level\" : %d,\n", Gia_ManLevelNum(p) ); + fprintf( pTable, " \"total\" : %d,\n", Total ); + fprintf( pTable, " \"correct\" : %d,\n", Correct ); + fprintf( pTable, " \"guess\" : %d\n", Guess ); + fprintf( pTable, "}\n" ); + fclose( pTable ); +} +int Gia_ManSimParamRead( char * pFileName, int * pnIns, int * pnWords ) +{ + int c, nIns = -1, nLines = 0, Count = 0, fReadDot = 0; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return 0; + } + while ( (c = fgetc(pFile)) != EOF ) + { + if ( c == '.' ) + fReadDot = 1; + if ( c == '\n' ) + { + if ( !fReadDot ) + { + if ( nIns == -1 ) + nIns = Count; + else if ( nIns != Count ) + { + printf( "The number of symbols (%d) does not match other lines (%d).\n", Count, nIns ); + fclose( pFile ); + return 0; + } + Count = 0; + nLines++; + } + fReadDot = 0; + } + if ( fReadDot ) + continue; + if ( c != '0' && c != '1' ) + continue; + Count++; + } + if ( nLines % 64 > 0 ) + { + printf( "The number of lines (%d) is not divisible by 64.\n", nLines ); + fclose( pFile ); + return 0; + } + *pnIns = nIns - 1; + *pnWords = nLines / 64; + //printf( "Expecting %d inputs and %d words of simulation data.\n", *pnIns, *pnWords ); + fclose( pFile ); + return 1; +} +void Gia_ManSimFileRead( char * pFileName, int nIns, int nWords, Vec_Wrd_t * vSimsIn, Vec_Int_t * vValues ) +{ + int c, nPats = 0, Count = 0, fReadDot = 0; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return; + } + assert( Vec_WrdSize(vSimsIn) % nWords == 0 ); + while ( (c = fgetc(pFile)) != EOF ) + { + if ( c == '.' ) + fReadDot = 1; + if ( c == '\n' ) + fReadDot = 0; + if ( fReadDot ) + continue; + if ( c != '0' && c != '1' ) + continue; + if ( Count == nIns ) + { + Vec_IntPush( vValues, c - '0' ); + Count = 0; + nPats++; + } + else + { + if ( c == '1' ) + Abc_TtSetBit( Vec_WrdEntryP(vSimsIn, Count * nWords), nPats ); + Count++; + } + } + assert( nPats == 64*nWords ); + fclose( pFile ); + printf( "Finished reading %d simulation patterns for %d inputs. Probability of 1 at the output is %6.2f %%.\n", 64*nWords, nIns, 100.0*Vec_IntSum(vValues)/nPats ); +} +void Gia_ManCompareValues( Gia_Man_t * p, Vec_Wrd_t * vSimsIn, Vec_Int_t * vValues, char * pDumpFile ) +{ + int i, Value, Guess, Count = 0, nWords = Vec_WrdSize(vSimsIn) / Gia_ManCiNum(p); + word * pSims; + assert( Vec_IntSize(vValues) == nWords * 64 ); + Gia_ManSimulateWordsInit( p, vSimsIn ); + assert( p->nSimWords == nWords ); + pSims = Gia_ManObjSim( p, Gia_ObjId(p, Gia_ManCo(p, 0)) ); + Vec_IntForEachEntry( vValues, Value, i ) + if ( Abc_TtGetBit(pSims, i) == Value ) + Count++; + Guess = (Vec_IntSum(vValues) > nWords * 32) ? Vec_IntSum(vValues) : nWords * 64 - Vec_IntSum(vValues); + printf( "Total = %6d. Errors = %6d. Correct = %6d. (%6.2f %%) Naive guess = %6d. (%6.2f %%)\n", + Vec_IntSize(vValues), Vec_IntSize(vValues) - Count, + Count, 100.0*Count/Vec_IntSize(vValues), + Guess, 100.0*Guess/Vec_IntSize(vValues)); + if ( pDumpFile == NULL ) + return; + Gia_ManSimLogStats( p, pDumpFile, Vec_IntSize(vValues), Count, Guess ); + printf( "Finished dumping statistics into file \"%s\".\n", pDumpFile ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManReadSimFile( char * pFileName, int * pnIns, int * pnOuts, int * pnPats, Vec_Wrd_t ** pvSimsIn, Vec_Wrd_t ** pvSimsOut ) +{ + char * pTemp, pBuffer[1000]; + Vec_Wrd_t * vSimsIn = NULL, * vSimsOut = NULL; + int i, iPat = 0, nWordsI, nWordsO, nIns = -1, nOuts = -1, nPats = -1; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return; + } + while ( fgets( pBuffer, 1000, pFile ) != NULL ) + { + pTemp = pBuffer; + if ( pTemp[0] == '\0' || pTemp[0] == '#' || pTemp[0] == ' ' ) + continue; + if ( pTemp[0] != '.' ) + break; + if ( pTemp[1] == 'i' ) + nIns = atoi(pTemp+2); + else if ( pTemp[1] == 'o' ) + nOuts = atoi(pTemp+2); + else if ( pTemp[1] == 'p' ) + { + if ( atoi(pTemp+2) % 64 == 0 ) + printf( "Expecting the number of patterns divisible by 64.\n" ); + nPats = atoi(pTemp+2) / 64; + } + } + if ( nIns == -1 || nOuts == -1 || nPats == -1 ) + { + printf( "Some of the parameters (inputs, outputs, patterns) is not specified.\n" ); + fclose( pFile ); + return; + } + nWordsI = (nIns + 63) / 64; + nWordsO = (nOuts + 63) / 64; + + vSimsIn = Vec_WrdStart( nPats * nWordsI ); + vSimsOut = Vec_WrdStart( nPats * nWordsO ); + rewind(pFile); + while ( fgets( pBuffer, 1000, pFile ) != NULL ) + { + if ( pTemp[0] == '\0' || pTemp[0] == '.' ) + continue; + for ( i = 0, pTemp = pBuffer; *pTemp != '\n'; pTemp++ ) + if ( *pTemp == '0' || *pTemp == '1' ) + { + if ( *pTemp == '1' ) + { + if ( i < nIns ) + Abc_TtSetBit( Vec_WrdEntryP(vSimsIn, nWordsI*iPat), i ); + else + Abc_TtSetBit( Vec_WrdEntryP(vSimsOut, nWordsO*iPat), i-nIns ); + } + i++; + } + iPat++; + } + if ( iPat != nPats ) + printf( "The number of patterns does not match.\n" ); + fclose( pFile ); + *pnIns = nIns; + *pnOuts = nOuts; + *pnPats = nPats; + *pvSimsIn = vSimsIn; + *pvSimsOut = vSimsOut; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManReadBinaryFile( char * pFileName, Vec_Wrd_t ** pvSimsIn, Vec_Str_t ** pvSimsOut ) +{ + extern void Extra_BitMatrixTransposeP( Vec_Wrd_t * vSimsIn, int nWordsIn, Vec_Wrd_t * vSimsOut, int nWordsOut ); + int nFileSize = Extra_FileSize( pFileName ); + int nExamples = 1 << 16; + int nInputs = nFileSize / nExamples - 1; + int nWords = (8*nInputs + 63)/64, i; + char * pContents = Extra_FileReadContents( pFileName ); + Vec_Wrd_t * vSimsIn = Vec_WrdStart( nExamples * nWords ); + Vec_Wrd_t * vSimsIn2 = Vec_WrdStart( nExamples * nWords ); + Vec_Str_t * vSimsOut = Vec_StrAlloc( nExamples ); + assert( nFileSize % nExamples == 0 ); + for ( i = 0; i < nExamples; i++ ) + { + memcpy( (void *)Vec_WrdEntryP(vSimsIn, i*nWords), (void *)(pContents + i*(nInputs+1)), nInputs ); + Vec_StrPush( vSimsOut, pContents[i*(nInputs+1) + nInputs] ); + } + Extra_BitMatrixTransposeP( vSimsIn, nWords, vSimsIn2, nExamples/64 ); + Vec_WrdShrink( vSimsIn2, 8*nInputs * nExamples/64 ); + Vec_WrdFree( vSimsIn ); + *pvSimsIn = vSimsIn2; + *pvSimsOut = vSimsOut; + ABC_FREE( pContents ); + return nInputs; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimLogStats2( Gia_Man_t * p, char * pDumpFile, int Total, int nPositives, float ErrorTotal, float GuessTotal ) +{ + FILE * pTable = fopen( pDumpFile, "wb" ); + fprintf( pTable, "{\n" ); + fprintf( pTable, " \"name\" : \"%s\",\n", p->pName ); + fprintf( pTable, " \"input\" : %d,\n", Gia_ManCiNum(p) ); + fprintf( pTable, " \"output\" : %d,\n", Gia_ManCoNum(p) ); + fprintf( pTable, " \"and\" : %d,\n", Gia_ManAndNum(p) ); + fprintf( pTable, " \"level\" : %d,\n", Gia_ManLevelNum(p) ); + fprintf( pTable, " \"total\" : %d,\n", Total ); + fprintf( pTable, " \"positive\" : %d,\n", nPositives ); + fprintf( pTable, " \"error\" : %e,\n", ErrorTotal ); + fprintf( pTable, " \"guess\" : %e\n", GuessTotal ); + fprintf( pTable, "}\n" ); + fclose( pTable ); +} +int Gia_ManGetExampleValue( word ** ppSims, int nSims, int iExample ) +{ + int o, Sign = 0, ValueSim = 0; + for ( o = 0; o < nSims; o++ ) + if ( (Sign = Abc_TtGetBit(ppSims[o], iExample)) ) + ValueSim |= (1 << o); + if ( Sign ) + ValueSim |= ~0 << nSims; + return ValueSim; +} +void Gia_ManCompareValues2( int nInputs, Gia_Man_t * p, Vec_Wrd_t * vSimsIn, Vec_Str_t * vValues, char * pDumpFile ) +{ + float Error1, ErrorTotal = 0, Guess1, GuessTotal = 0; + int i, o, nPositives = 0, nWords = Vec_WrdSize(vSimsIn) / Gia_ManCiNum(p); + word ** ppSims = ABC_CALLOC( word *, Gia_ManCoNum(p) ); + Gia_Obj_t * pObj; + assert( nWords == (1<<10) ); + assert( Vec_WrdSize(vSimsIn) % Gia_ManCiNum(p) == 0 ); + assert( Vec_StrSize(vValues) == (1 << 16) ); + assert( nWords*64 == (1 << 16) ); + // simulate examples given in vSimsIn + Gia_ManSimulateWordsInit( p, vSimsIn ); + // collect simulation info for the outputs + assert( p->nSimWords == nWords ); + Gia_ManForEachCo( p, pObj, o ) + ppSims[o] = Gia_ManObjSim( p, Gia_ObjId(p, pObj) ); + // compare the output for each example + for ( i = 0; i < nWords*64; i++ ) + { + int ValueGold = (int)Vec_StrEntry( vValues, i ); + int ValueImpl = Gia_ManGetExampleValue( ppSims, Gia_ManCoNum(p), i ); + // compute error for this example + Error1 = (float)(ValueGold - ValueImpl)/256; + ErrorTotal += Error1 * Error1; + // compute error of zero-output + Guess1 = ValueGold > 0 ? Abc_AbsInt(ValueImpl) : 0; + GuessTotal += Guess1 * Guess1; + // count positive values (disregard negative values due to Leaky ReLU) + nPositives += (int)(ValueGold > 0); + } + ABC_FREE( ppSims ); + printf( "Total = %6d. Positive = %6d. (%6.2f %%) Errors = %e. Guess = %e. (%6.2f %%)\n", + Vec_StrSize(vValues), nPositives, 100.0*nPositives/Vec_StrSize(vValues), + ErrorTotal, GuessTotal, 100.0*ErrorTotal/GuessTotal ); + if ( pDumpFile == NULL ) + return; + Gia_ManSimLogStats2( p, pDumpFile, Vec_StrSize(vValues), nPositives, ErrorTotal, GuessTotal ); + printf( "Finished dumping statistics into file \"%s\".\n", pDumpFile ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManTestWordFileUnused( Gia_Man_t * p, char * pFileName, char * pDumpFile ) +{ + Vec_Wrd_t * vSimsIn; + Vec_Str_t * vSimsOut; + int nInputs = Gia_ManReadBinaryFile( pFileName, &vSimsIn, &vSimsOut ); + if ( Gia_ManCiNum(p) == 8*nInputs ) + Gia_ManCompareValues2( nInputs, p, vSimsIn, vSimsOut, pDumpFile ); + else + printf( "The number of inputs in the AIG (%d) and in the file (%d) does not match.\n", Gia_ManCiNum(p), 8*nInputs ); + Vec_WrdFree( vSimsIn ); + Vec_StrFree( vSimsOut ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManTestOneFile( Gia_Man_t * p, char * pFileName, char * pDumpFile ) +{ + Vec_Wrd_t * vSimsIn; + Vec_Int_t * vValues; + int nIns, nWords; + if ( !Gia_ManSimParamRead( pFileName, &nIns, &nWords ) ) + return; + if ( nIns != Gia_ManCiNum(p) ) + { + printf( "The number of inputs in the file \"%s\" (%d) does not match the AIG (%d).\n", pFileName, nIns, Gia_ManCiNum(p) ); + return; + } + vSimsIn = Vec_WrdStart( nIns * nWords ); + vValues = Vec_IntAlloc( nWords * 64 ); + Gia_ManSimFileRead( pFileName, nIns, nWords, vSimsIn, vValues ); + Gia_ManCompareValues( p, vSimsIn, vValues, pDumpFile ); + Vec_WrdFree( vSimsIn ); + Vec_IntFree( vValues ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManReadCifar10File( char * pFileName, Vec_Wrd_t ** pvSimsIn, Vec_Str_t ** pvSimsOut, int * pnExamples ) +{ + int nPixels = 32*32*3; + int nFileSize = Extra_FileSize( pFileName ); + int nExamples = nFileSize / (nPixels + 1); + int nWordsIn = nPixels / 8; + int nWordsOut = (nExamples + 63) / 64; int e; + if ( nFileSize % (nPixels + 1) ) + { + printf( "The input file \"%s\" with image data does not appear to be in CIFAR10 format.\n", pFileName ); + return 0; + } + else + { + Vec_Wrd_t * vSimsIn = Vec_WrdStart( 64 * nWordsOut * nWordsIn ); + Vec_Str_t * vSimsOut = Vec_StrAlloc( 64 * nWordsOut ); + unsigned char * pBuffer = ABC_ALLOC( unsigned char, nFileSize ); + FILE * pFile = fopen( pFileName, "rb" ); + int Value = fread( pBuffer, 1, nFileSize, pFile ); + fclose( pFile ); + assert( Value == nFileSize ); + printf( "Successfully read %5.2f MB (%d images) from file \"%s\".\n", (float)nFileSize/(1<<20), nExamples, pFileName ); + for ( e = 0; e < nExamples; e++ ) + { + Vec_StrPush( vSimsOut, (char)pBuffer[e*(nPixels + 1)] ); + memcpy( Vec_WrdEntryP(vSimsIn, e*nWordsIn), pBuffer + e*(nPixels + 1) + 1, nPixels ); + } + ABC_FREE( pBuffer ); + for ( ; e < 64 * nWordsOut; e++ ) + Vec_StrPush( vSimsOut, (char)0 ); + memset( Vec_WrdEntryP(vSimsIn, nExamples*nWordsIn), 0, (64*nWordsOut - nExamples)*nWordsIn ); + *pvSimsIn = vSimsIn; + *pvSimsOut = vSimsOut; + *pnExamples = nExamples; + return 8*nPixels; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSimulateBatch( Gia_Man_t * p, Vec_Wrd_t * vSimsIn, Vec_Str_t * vSimsOut, Vec_Str_t * vSimsOut2, int b, int Limit ) +{ + Gia_Obj_t * pObj; + word * ppSims[10]; + int i, o, Count = 0; + assert( Gia_ManCiNum(p) == Vec_WrdSize(vSimsIn) ); + assert( Gia_ManCoNum(p) == 10 ); + Gia_ManSimulateWordsInit( p, vSimsIn ); + Gia_ManForEachCo( p, pObj, o ) + ppSims[o] = Gia_ManObjSim( p, Gia_ObjId(p, pObj) ); + for ( i = 0; i < Limit; i++ ) + { + int Value = 0; + for ( o = 0; o < 10; o++ ) + if ( Abc_TtGetBit(ppSims[o], i) ) + { + Value = o; + break; + } + Vec_StrPush( vSimsOut, (char)Value ); + Count += Value == (int)Vec_StrEntry( vSimsOut2, 64*b+i ); + } + return Count; +} +Vec_Str_t * Gia_ManSimulateAll( Gia_Man_t * p, Vec_Wrd_t * vSimsIn, Vec_Str_t * vSimsOut, int nExamples, int fVerbose ) +{ + extern void Extra_BitMatrixTransposeP( Vec_Wrd_t * vSimsIn, int nWordsIn, Vec_Wrd_t * vSimsOut, int nWordsOut ); + Vec_Str_t * vRes = Vec_StrAlloc( 100 ); int b, Count; + int nWordsIn = 32*32*24/64; // one image + int nWordsOut = Vec_WrdSize(vSimsIn)/(nWordsIn*64); + assert( Vec_WrdSize(vSimsIn) % nWordsIn == 0 ); + for ( b = 0; b < nWordsOut; b++ ) + { + int Limit = b == nWordsOut-1 ? nExamples-b*64 : 64; + Vec_Wrd_t * vSimsIn1 = Vec_WrdStart( nWordsIn*64 ); + Vec_Wrd_t * vSimsIn2 = Vec_WrdStart( nWordsIn*64 ); + memcpy( Vec_WrdArray(vSimsIn1), Vec_WrdEntryP(vSimsIn, b*nWordsIn*64), sizeof(word)*nWordsIn*64 ); + Extra_BitMatrixTransposeP( vSimsIn1, nWordsIn, vSimsIn2, 1 ); + Vec_WrdFree( vSimsIn1 ); + Count = Gia_ManSimulateBatch( p, vSimsIn2, vRes, vSimsOut, b, Limit ); + Vec_WrdFree( vSimsIn2 ); + if ( fVerbose ) + printf( "Finished simulating word %4d (out of %4d). Correct = %2d. (Limit = %2d.)\n", b, nWordsOut, Count, Limit ); + } + assert( Vec_StrSize(vRes) == nExamples ); + return vRes; +} +void Gia_ManCompareCifar10Values( Gia_Man_t * p, Vec_Str_t * vRes, Vec_Str_t * vSimsOut, char * pDumpFile, int nExamples ) +{ + int i, Guess = (nExamples+9)/10, Count = 0; + for ( i = 0; i < nExamples; i++ ) + { + char ValueReal = Vec_StrEntry(vRes, i); + char ValueGold = Vec_StrEntry(vSimsOut, i); + if ( ValueReal == ValueGold ) + Count++; + } + printf( "Summary: Total = %6d. Errors = %6d. Correct = %6d. (%6.2f %%) Naive guess = %6d. (%6.2f %%)\n", + nExamples, nExamples - Count, + Count, 100.0*Count/nExamples, + Guess, 100.0*Guess/nExamples); + if ( pDumpFile == NULL ) + return; + Gia_ManSimLogStats( p, pDumpFile, nExamples, Count, Guess ); + printf( "Finished dumping statistics into file \"%s\".\n", pDumpFile ); +} +void Gia_ManTestWordFile( Gia_Man_t * p, char * pFileName, char * pDumpFile, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Vec_Wrd_t * vSimsIn; + Vec_Str_t * vSimsOut; + int i, nExamples = 0; + int nInputs = Gia_ManReadCifar10File( pFileName, &vSimsIn, &vSimsOut, &nExamples ); + char * pKnownFileNames[3] = {"small.aig", "medium.aig", "large.aig"}; + int pLimitFileSizes[3] = {10000, 100000, 1000000}; + for ( i = 0; i < 3; i++ ) + if ( p->pSpec && !strncmp(p->pSpec, pKnownFileNames[i], 5) && Gia_ManAndNum(p) > pLimitFileSizes[i] ) + printf( "Warning: The input file \"%s\" contains more than %d internal and-nodes.\n", pKnownFileNames[i], pLimitFileSizes[i] ); + if ( nInputs == Gia_ManCiNum(p) ) + { + Vec_Str_t * vRes = Gia_ManSimulateAll( p, vSimsIn, vSimsOut, nExamples, fVerbose ); + Gia_ManCompareCifar10Values( p, vRes, vSimsOut, pDumpFile, nExamples ); + Vec_StrFree( vRes ); + } + else + printf( "The primary input counts in the AIG (%d) and in the image data (%d) do not match.\n", Gia_ManCiNum(p), nInputs ); + Vec_WrdFree( vSimsIn ); + Vec_StrFree( vSimsOut ); + Abc_PrintTime( 1, "Total checking time", Abc_Clock() - clk ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSumCount( char * p, Vec_Int_t * vDec, int b ) +{ + int i, Ent, Count = 0, Sum = 0; + for ( i = 0; p[i]; i++ ) { + Ent = (p[i] >= '0' && p[i] <= '9') ? p[i]-'0' : p[i]-'A'+10; + Count += Vec_IntEntry(vDec, Ent) + b * (1 << (Sum += Ent)); + } + return Count + b * ((1 << Sum) - 1); +} +Vec_Str_t * Gia_ManSumEnum_rec( int Num ) +{ + if ( Num == 1 ) { + Vec_Str_t * vRes = Vec_StrAlloc(2); + Vec_StrPush( vRes, '1' ); + Vec_StrPush( vRes, '\0' ); + return vRes; + } + Vec_Str_t * vRes = Vec_StrAlloc( 16 ); + for ( int i = 1; i < Num; i++ ) { + Vec_Str_t * vRes0 = Gia_ManSumEnum_rec(i); + Vec_Str_t * vRes1 = Gia_ManSumEnum_rec(Num-i); + for ( int c0 = 0; c0 < Vec_StrSize(vRes0); c0 += strlen(Vec_StrEntryP(vRes0,c0))+1 ) + for ( int c1 = 0; c1 < Vec_StrSize(vRes1); c1 += strlen(Vec_StrEntryP(vRes1,c1))+1 ) + Vec_StrPrintF( vRes, "%s%s%c", Vec_StrEntryP(vRes0,c0), Vec_StrEntryP(vRes1,c1), '\0' ); + Vec_StrPrintF( vRes, "%c%c", Num < 10 ? '0'+Num : 'A'+Num-10, '\0' ); + Vec_StrFree( vRes0 ); + Vec_StrFree( vRes1 ); + } + return vRes; +} +void Gia_ManSumEnum( int n, Vec_Int_t * vDec ) +{ + Vec_Str_t * vRes = Gia_ManSumEnum_rec( n ); + for ( int b = 1; b <= 256; b <<= 1 ) { + int iBest = -1, CountCur, CountBest = ABC_INFINITY; + for ( int c0 = 0; c0 < Vec_StrSize(vRes); c0 += strlen(Vec_StrEntryP(vRes,c0))+1 ) { + CountCur = Gia_ManSumCount( Vec_StrEntryP(vRes,c0), vDec, b ); + if ( CountBest > CountCur ) + CountBest = CountCur, iBest = c0; + } + printf( " %8d", CountBest ); + //printf( " %8s", Vec_StrEntryP(vRes,iBest) ); + //printf( " %.3f", (float)CountBest/(3*b*((1<> b) & 1 ) + Vec_IntWriteEntry( vLev, b, 1 ); + Vec_WrdForEachEntryStop( vData, Data, i, Vec_WrdSize(vData)-1 ) { + for ( n = 0; n < nIBits; n++, nLits += 2 ) { + Vec_Int_t * vLev = Vec_WecPushLevel( vArgs ); + Vec_IntFill( vLev, nOBits, 0 ); + for ( b = 0; b < nOBits; b++ ) + if ( ((Data >> b) & 1) && b+n < nOBits ) + Vec_IntWriteEntry( vLev, b+n, nLits ); + } + } + return vArgs; +} +Vec_Wec_t * Gia_ManGenNeuronTransformArgs( Gia_Man_t * pNew, Vec_Wec_t * vArgs, int nLutSize, int nOBits ) +{ + int i, nParts = (Vec_WecSize(vArgs) + nLutSize - 2) / nLutSize; + while ( Vec_WecSize(vArgs) < nLutSize*nParts+1 ) + Vec_IntFill( Vec_WecPushLevel(vArgs), nOBits, 0 ); + assert( Vec_WecSize(vArgs) == nLutSize*nParts+1 ); + Vec_Wec_t * vNew = Vec_WecAlloc( nParts ); + Vec_Int_t * vRes = Vec_WecPushLevel( vNew ), * vArg; + Vec_IntAppend( vRes, Vec_WecEntry(vArgs, 0) ); + Vec_WecForEachLevelStart( vArgs, vArg, i, 1 ) { + Gia_ManGenNeuronAdder( pNew, nOBits, Vec_IntArray(vArg), Vec_IntArray(vRes), 0, vRes ); + if ( (i-1) % nLutSize == nLutSize-1 && i < Vec_WecSize(vArgs)-1 ) { + vRes = Vec_WecPushLevel( vNew ); + Vec_IntFill( vRes, nOBits, 0 ); + } + } + assert( Vec_WecSize(vNew) == nParts ); + return vNew; +} +Vec_Wec_t * Gia_ManGenNeuronCompactArgs( Gia_Man_t * pNew, Vec_Wec_t * vArgs, int nLutSize, int nOBits ) +{ + int i, nParts = Vec_WecSize(vArgs) / 3; + Vec_Wec_t * vNew = Vec_WecAlloc( 2 * nParts + Vec_WecSize(vArgs) % 3 ); + for ( i = 0; i < nParts; i++ ) { + Vec_Int_t * vIn0 = Vec_WecEntry(vArgs, 3*i+0); + Vec_Int_t * vIn1 = Vec_WecEntry(vArgs, 3*i+1); + Vec_Int_t * vIn2 = Vec_WecEntry(vArgs, 3*i+2); + Vec_Int_t * vOut0 = Vec_WecPushLevel(vNew); + Vec_Int_t * vOut1 = Vec_WecPushLevel(vNew); + Gia_ManGenCompact( pNew, vIn0, vIn1, vIn2, vOut0, vOut1 ); + } + for ( i = 3*nParts; i < Vec_WecSize(vArgs); i++ ) + Vec_IntAppend( Vec_WecPushLevel(vNew), Vec_WecEntry(vArgs, i) ); + assert( Vec_WecSize(vNew) == 2 * nParts + Vec_WecSize(vArgs) % 3 ); + return vNew; +} +Vec_Int_t * Gia_ManGenNeuronFinal( Gia_Man_t * pNew, Vec_Wec_t * vArgs, int nOBits ) +{ + Vec_Int_t * vRes = Vec_IntAlloc( nOBits ), * vArg; int i; + Vec_IntAppend( vRes, Vec_WecEntry(vArgs, 0) ); + Vec_WecForEachLevelStart( vArgs, vArg, i, 1 ) + Gia_ManGenNeuronAdder( pNew, nOBits, Vec_IntArray(vArg), Vec_IntArray(vRes), 0, vRes ); + return vRes; +} +int Gia_ManGenNeuronBitWidth( Vec_Wrd_t * vData, int nIBits ) +{ + int i, InMask = (1<pName = Abc_UtilStrsav( "neuron" ); + for ( i = 0; i < nIBits * (Vec_WrdSize(vData)-1); i++ ) + Gia_ManAppendCi( pNew ); + Gia_ManHashAlloc( pNew ); + + Vec_Wec_t * vTemp, * vArgs = Gia_ManGenNeuronCreateArgs( vData, nIBits, nOBits ); + Vec_WrdFree( vData ); + + if ( nLutSize ) { + vArgs = Gia_ManGenNeuronTransformArgs( pNew, vTemp = vArgs, nLutSize, nOBits ); + Vec_WecFree( vTemp ); + while ( Vec_WecSize(vArgs) > 2 ) { + vArgs = Gia_ManGenNeuronCompactArgs( pNew, vTemp = vArgs, nLutSize, nOBits ); + Vec_WecFree( vTemp ); + } + } + + Vec_Int_t * vRes = Gia_ManGenNeuronFinal( pNew, vArgs, nOBits ); + Vec_IntForEachEntry( vRes, Lit, i ) + Gia_ManAppendCo( pNew, Lit ); + Vec_IntFree( vRes ); + Vec_WecFree( vArgs ); + + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Generates minimum-node AIG for n-bit comparator (a > b).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupGenComp( int nBits, int fInterleave ) +{ + Gia_Man_t * pNew, * pTemp; int i, iLit = 1; + Vec_Int_t * vBitsA = Vec_IntAlloc( nBits + 1 ); + Vec_Int_t * vBitsB = Vec_IntAlloc( nBits + 1 ); + pNew = Gia_ManStart( 6*nBits+10 ); + pNew->pName = Abc_UtilStrsav( "comp" ); + Gia_ManHashAlloc( pNew ); + if ( fInterleave ) { + for ( i = 0; i < nBits; i++ ) + Vec_IntPush( vBitsA, Gia_ManAppendCi(pNew) ), + Vec_IntPush( vBitsB, Gia_ManAppendCi(pNew) ); + } + else { + for ( i = 0; i < nBits; i++ ) + Vec_IntPush( vBitsA, Gia_ManAppendCi(pNew) ); + for ( i = 0; i < nBits; i++ ) + Vec_IntPush( vBitsB, Gia_ManAppendCi(pNew) ); + } + Vec_IntPush( vBitsA, 0 ); + Vec_IntPush( vBitsB, 0 ); + for ( i = 0; i < nBits; i++ ) { + int iLitA0 = Vec_IntEntry(vBitsA, i); + int iLitA1 = Vec_IntEntry(vBitsA, i+1); + int iLitB0 = Vec_IntEntry(vBitsB, i); + int iLitB1 = Vec_IntEntry(vBitsB, i+1); + int iOrLit0; + if ( i == 0 ) + iOrLit0 = Gia_ManHashOr(pNew, Abc_LitNotCond(iLitA0, !(i&1)), Abc_LitNotCond(iLitB0, i&1)); + else + iOrLit0 = Gia_ManHashAnd(pNew, Abc_LitNotCond(iLitA0, !(i&1)), Abc_LitNotCond(iLitB0, i&1)); + int iOrLit1 = Gia_ManHashAnd(pNew, Abc_LitNotCond(iLitA1, !(i&1)), Abc_LitNotCond(iLitB1, i&1)); + int iOrLit = Gia_ManHashOr(pNew, iOrLit0, iOrLit1 ); + iLit = Gia_ManHashOr(pNew, Abc_LitNot(iLit), iOrLit ); + } + Gia_ManAppendCo( pNew, Abc_LitNotCond(iLit, nBits&1) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Vec_IntFree( vBitsA ); + Vec_IntFree( vBitsB ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Generates optimized AIG for the decoder and the multiplexer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_GenDecoder( Gia_Man_t * p, int * pLits, int nLits ) +{ + if ( nLits == 1 ) + { + Vec_Int_t * vRes = Vec_IntAlloc( 2 ); + Vec_IntPush( vRes, Abc_LitNot(pLits[0]) ); + Vec_IntPush( vRes, pLits[0] ); + return vRes; + } + assert( nLits > 1 ); + int nPart1 = nLits / 2; + int nPart2 = nLits - nPart1; + Vec_Int_t * vRes1 = Gia_GenDecoder( p, pLits, nPart1 ); + Vec_Int_t * vRes2 = Gia_GenDecoder( p, pLits+nPart1, nPart2 ); + Vec_Int_t * vRes = Vec_IntAlloc( Vec_IntSize(vRes1) * Vec_IntSize(vRes2) ); + int i, k, Lit1, Lit2; + Vec_IntForEachEntry( vRes2, Lit2, k ) + Vec_IntForEachEntry( vRes1, Lit1, i ) + Vec_IntPush( vRes, Gia_ManHashAnd(p, Lit1, Lit2) ); + Vec_IntFree( vRes1 ); + Vec_IntFree( vRes2 ); + return vRes; +} +Gia_Man_t * Gia_ManGenMux( int nIns, char * pNums ) +{ + Vec_Int_t * vIns = Vec_IntAlloc( nIns ); + Vec_Int_t * vData = Vec_IntAlloc( 1 << nIns ); + Gia_Man_t * p = Gia_ManStart( 4*(1 << nIns) + nIns ), * pTemp; + int i, iStart = 0, nSize = 1 << nIns; + p->pName = Abc_UtilStrsav( "mux" ); + for ( i = 0; i < nIns; i++ ) + Vec_IntPush( vIns, Gia_ManAppendCi(p) ); + for ( i = 0; i < nSize; i++ ) + Vec_IntPush( vData, Gia_ManAppendCi(p) ); + Gia_ManHashAlloc( p ); + for ( i = (int)strlen(pNums)-1; i >= 0; i-- ) + { + int k, b, nBits = (int)(pNums[i] - '0'); + Vec_Int_t * vDec = Gia_GenDecoder( p, Vec_IntEntryP(vIns, iStart), nBits ); + for ( k = 0; k < nSize; k++ ) + Vec_IntWriteEntry( vData, k, Gia_ManHashAnd(p, Vec_IntEntry(vData, k), Vec_IntEntry(vDec, k%Vec_IntSize(vDec))) ); + for ( b = 0; b < nBits; b++, nSize /= 2 ) + for ( k = 0; k < nSize/2; k++ ) + Vec_IntWriteEntry( vData, k, Gia_ManHashOr(p, Vec_IntEntry(vData, 2*k), Vec_IntEntry(vData, 2*k+1)) ); + Vec_IntFree( vDec ); + iStart += nBits; + } + assert( nSize == 1 ); + Gia_ManAppendCo( p, Vec_IntEntry(vData, 0) ); + Vec_IntFree( vIns ); + Vec_IntFree( vData ); + p = Gia_ManCleanup( pTemp = p ); + Gia_ManStop( pTemp ); + return p; +} + + +/**Function************************************************************* + + Synopsis [Generates N-bit sorter using pair-wise sorting algorithm.] + + Description [https://en.wikipedia.org/wiki/Pairwise_sorting_network] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManGenSorterOne( Gia_Man_t * p, int * pLits, int i, int k ) +{ + int Lit1 = Gia_ManAppendAnd( p, pLits[i], pLits[k] ); + int Lit2 = Gia_ManAppendOr ( p, pLits[i], pLits[k] ); + pLits[i] = Lit1; + pLits[k] = Lit2; +} +static inline void Gia_ManGenSorterConstrMerge( Gia_Man_t * p, int * pLits, int lo, int hi, int r ) +{ + int i, step = r * 2; + if ( step < hi - lo ) + { + Gia_ManGenSorterConstrMerge( p, pLits, lo, hi-r, step ); + Gia_ManGenSorterConstrMerge( p, pLits, lo+r, hi, step ); + for ( i = lo+r; i < hi-r; i += step ) + Gia_ManGenSorterOne( p, pLits, i, i+r ); + } +} +static inline void Gia_ManGenSorterConstrRange( Gia_Man_t * p, int * pLits, int lo, int hi ) +{ + if ( hi - lo >= 1 ) + { + int i, mid = lo + (hi - lo) / 2; + for ( i = lo; i <= mid; i++ ) + Gia_ManGenSorterOne( p, pLits, i, i + (hi - lo + 1) / 2 ); + Gia_ManGenSorterConstrRange( p, pLits, lo, mid ); + Gia_ManGenSorterConstrRange( p, pLits, mid+1, hi ); + Gia_ManGenSorterConstrMerge( p, pLits, lo, hi, 1 ); + } +} +Gia_Man_t * Gia_ManGenSorter( int LogN ) +{ + int i, nVars = 1 << LogN; + int nVarsAlloc = nVars + 2 * (nVars * LogN * (LogN-1) / 4 + nVars - 1); + Vec_Int_t * vLits = Vec_IntAlloc( nVars ); + Gia_Man_t * p = Gia_ManStart( 1 + 2*nVars + nVarsAlloc ); + p->pName = Abc_UtilStrsav( "sorter" ); + for ( i = 0; i < nVars; i++ ) + Vec_IntPush( vLits, Gia_ManAppendCi(p) ); + Gia_ManGenSorterConstrRange( p, Vec_IntArray(vLits), 0, nVars - 1 ); + for ( i = 0; i < nVars; i++ ) + Gia_ManAppendCo( p, Vec_IntEntry(vLits, i) ); + Vec_IntFree( vLits ); + return p; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaGiarf.c b/yosys/abc/src/aig/gia/giaGiarf.c new file mode 100644 index 00000000000..fce7e4d7426 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaGiarf.c @@ -0,0 +1,1079 @@ +/**CFile**************************************************************** + + FileName [gia.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// combinational simulation manager +typedef struct Hcd_Man_t_ Hcd_Man_t; +struct Hcd_Man_t_ +{ + // parameters + Gia_Man_t * pGia; // the AIG to be used for simulation + int nBTLimit; // internal backtrack limit + int fVerbose; // internal verbose flag + // internal variables + unsigned * pSimInfo; // simulation info for each object + Vec_Ptr_t * vSimInfo; // pointers to the CI simulation info + Vec_Ptr_t * vSimPres; // pointers to the presense of simulation info + // temporaries + Vec_Int_t * vClassOld; // old class numbers + Vec_Int_t * vClassNew; // new class numbers + Vec_Int_t * vClassTemp; // temporary storage + Vec_Int_t * vRefinedC; // refined const reprs +}; + +static inline unsigned Hcd_ObjSim( Hcd_Man_t * p, int Id ) { return p->pSimInfo[Id]; } +static inline unsigned * Hcd_ObjSimP( Hcd_Man_t * p, int Id ) { return p->pSimInfo + Id; } +static inline unsigned Hcd_ObjSetSim( Hcd_Man_t * p, int Id, unsigned n ) { return p->pSimInfo[Id] = n; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the fraiging manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hcd_Man_t * Gia_ManEquivStart( Gia_Man_t * pGia, int nBTLimit, int fVerbose ) +{ + Hcd_Man_t * p; + Gia_Obj_t * pObj; + int i; + p = ABC_CALLOC( Hcd_Man_t, 1 ); + p->pGia = pGia; + p->nBTLimit = nBTLimit; + p->fVerbose = fVerbose; + p->pSimInfo = ABC_ALLOC( unsigned, Gia_ManObjNum(pGia) ); + p->vClassOld = Vec_IntAlloc( 100 ); + p->vClassNew = Vec_IntAlloc( 100 ); + p->vClassTemp = Vec_IntAlloc( 100 ); + p->vRefinedC = Vec_IntAlloc( 100 ); + // collect simulation info + p->vSimInfo = Vec_PtrAlloc( 1000 ); + Gia_ManForEachCi( pGia, pObj, i ) + Vec_PtrPush( p->vSimInfo, Hcd_ObjSimP(p, Gia_ObjId(pGia,pObj)) ); + p->vSimPres = Vec_PtrAllocSimInfo( Gia_ManCiNum(pGia), 1 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Starts the fraiging manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManEquivStop( Hcd_Man_t * p ) +{ + Vec_PtrFree( p->vSimInfo ); + Vec_PtrFree( p->vSimPres ); + Vec_IntFree( p->vClassOld ); + Vec_IntFree( p->vClassNew ); + Vec_IntFree( p->vClassTemp ); + Vec_IntFree( p->vRefinedC ); + ABC_FREE( p->pSimInfo ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [Compared two simulation infos.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Hcd_ManCompareEqual( unsigned s0, unsigned s1 ) +{ + if ( (s0 & 1) == (s1 & 1) ) + return s0 == s1; + else + return s0 ==~s1; +} + +/**Function************************************************************* + + Synopsis [Compares one simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Hcd_ManCompareConst( unsigned s ) +{ + if ( s & 1 ) + return s ==~0; + else + return s == 0; +} + +/**Function************************************************************* + + Synopsis [Creates one equivalence class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hcd_ManClassCreate( Gia_Man_t * pGia, Vec_Int_t * vClass ) +{ + int Repr = -1, EntPrev = -1, Ent, i; + assert( Vec_IntSize(vClass) > 0 ); + Vec_IntForEachEntry( vClass, Ent, i ) + { + if ( i == 0 ) + { + Repr = Ent; + Gia_ObjSetRepr( pGia, Ent, -1 ); + EntPrev = Ent; + } + else + { + Gia_ObjSetRepr( pGia, Ent, Repr ); + Gia_ObjSetNext( pGia, EntPrev, Ent ); + EntPrev = Ent; + } + } + Gia_ObjSetNext( pGia, EntPrev, 0 ); +} + +/**Function************************************************************* + + Synopsis [Refines one equivalence class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hcd_ManClassClassRemoveOne( Hcd_Man_t * p, int i ) +{ + int iRepr, Ent; + if ( Gia_ObjIsConst(p->pGia, i) ) + { + Gia_ObjSetRepr( p->pGia, i, GIA_VOID ); + return 1; + } + if ( !Gia_ObjIsClass(p->pGia, i) ) + return 0; + assert( Gia_ObjIsClass(p->pGia, i) ); + iRepr = Gia_ObjRepr( p->pGia, i ); + if ( iRepr == GIA_VOID ) + iRepr = i; + // collect nodes + Vec_IntClear( p->vClassOld ); + Vec_IntClear( p->vClassNew ); + Gia_ClassForEachObj( p->pGia, iRepr, Ent ) + { + if ( Ent == i ) + Vec_IntPush( p->vClassNew, Ent ); + else + Vec_IntPush( p->vClassOld, Ent ); + } + assert( Vec_IntSize( p->vClassNew ) == 1 ); + Hcd_ManClassCreate( p->pGia, p->vClassOld ); + Hcd_ManClassCreate( p->pGia, p->vClassNew ); + assert( !Gia_ObjIsClass(p->pGia, i) ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Refines one equivalence class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hcd_ManClassRefineOne( Hcd_Man_t * p, int i ) +{ + unsigned Sim0, Sim1; + int Ent; + Vec_IntClear( p->vClassOld ); + Vec_IntClear( p->vClassNew ); + Vec_IntPush( p->vClassOld, i ); + Sim0 = Hcd_ObjSim(p, i); + Gia_ClassForEachObj1( p->pGia, i, Ent ) + { + Sim1 = Hcd_ObjSim(p, Ent); + if ( Hcd_ManCompareEqual( Sim0, Sim1 ) ) + Vec_IntPush( p->vClassOld, Ent ); + else + Vec_IntPush( p->vClassNew, Ent ); + } + if ( Vec_IntSize( p->vClassNew ) == 0 ) + return 0; + Hcd_ManClassCreate( p->pGia, p->vClassOld ); + Hcd_ManClassCreate( p->pGia, p->vClassNew ); + if ( Vec_IntSize(p->vClassNew) > 1 ) + return 1 + Hcd_ManClassRefineOne( p, Vec_IntEntry(p->vClassNew,0) ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes hash key of the simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hcd_ManHashKey( unsigned * pSim, int nWords, int nTableSize ) +{ + static int s_Primes[16] = { + 1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177, + 4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 }; + unsigned uHash = 0; + int i; + if ( pSim[0] & 1 ) + for ( i = 0; i < nWords; i++ ) + uHash ^= ~pSim[i] * s_Primes[i & 0xf]; + else + for ( i = 0; i < nWords; i++ ) + uHash ^= pSim[i] * s_Primes[i & 0xf]; + return (int)(uHash % nTableSize); + +} + +/**Function************************************************************* + + Synopsis [Rehashes the refined classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hcd_ManClassesRehash( Hcd_Man_t * p, Vec_Int_t * vRefined ) +{ + int * pTable, nTableSize, Key, i, k; + nTableSize = Abc_PrimeCudd( 100 + Vec_IntSize(vRefined) / 5 ); + pTable = ABC_CALLOC( int, nTableSize ); + Vec_IntForEachEntry( vRefined, i, k ) + { + assert( !Hcd_ManCompareConst( Hcd_ObjSim(p, i) ) ); + Key = Hcd_ManHashKey( Hcd_ObjSimP(p, i), 1, nTableSize ); + if ( pTable[Key] == 0 ) + Gia_ObjSetRepr( p->pGia, i, GIA_VOID ); + else + { + Gia_ObjSetNext( p->pGia, pTable[Key], i ); + Gia_ObjSetRepr( p->pGia, i, Gia_ObjRepr(p->pGia, pTable[Key]) ); + if ( Gia_ObjRepr(p->pGia, i) == GIA_VOID ) + Gia_ObjSetRepr( p->pGia, i, pTable[Key] ); + } + pTable[Key] = i; + } + ABC_FREE( pTable ); +// Gia_ManEquivPrintClasses( p->pGia, 0, 0.0 ); + // refine classes in the table + Vec_IntForEachEntry( vRefined, i, k ) + { + if ( Gia_ObjIsHead( p->pGia, i ) ) + Hcd_ManClassRefineOne( p, i ); + } + Gia_ManEquivPrintClasses( p->pGia, 0, 0.0 ); +} + +/**Function************************************************************* + + Synopsis [Refines equivalence classes after simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hcd_ManClassesRefine( Hcd_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Vec_IntClear( p->vRefinedC ); + Gia_ManForEachAnd( p->pGia, pObj, i ) + { + if ( Gia_ObjIsTail(p->pGia, i) ) // add check for the class level + { + Hcd_ManClassRefineOne( p, Gia_ObjRepr(p->pGia, i) ); + } + else if ( Gia_ObjIsConst(p->pGia, i) ) + { + if ( !Hcd_ManCompareConst( Hcd_ObjSim(p, i) ) ) + Vec_IntPush( p->vRefinedC, i ); + } + } + Hcd_ManClassesRehash( p, p->vRefinedC ); +} + +/**Function************************************************************* + + Synopsis [Creates equivalence classes for the first time.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hcd_ManClassesCreate( Hcd_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + assert( p->pGia->pReprs == NULL ); + p->pGia->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p->pGia) ); + p->pGia->pNexts = ABC_CALLOC( int, Gia_ManObjNum(p->pGia) ); + Gia_ManForEachObj( p->pGia, pObj, i ) + Gia_ObjSetRepr( p->pGia, i, Gia_ObjIsAnd(pObj) ? 0 : GIA_VOID ); +} + +/**Function************************************************************* + + Synopsis [Initializes simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hcd_ManSimulationInit( Hcd_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachCi( p->pGia, pObj, i ) + Hcd_ObjSetSim( p, i, (Gia_ManRandom(0) << 1) ); +} + +/**Function************************************************************* + + Synopsis [Performs one round of simple combinational simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hcd_ManSimulateSimple( Hcd_Man_t * p ) +{ + Gia_Obj_t * pObj; + unsigned Res0, Res1; + int i; + Gia_ManForEachAnd( p->pGia, pObj, i ) + { + Res0 = Hcd_ObjSim( p, Gia_ObjFaninId0(pObj, i) ); + Res1 = Hcd_ObjSim( p, Gia_ObjFaninId1(pObj, i) ); + Hcd_ObjSetSim( p, i, (Gia_ObjFaninC0(pObj)? ~Res0: Res0) & + (Gia_ObjFaninC1(pObj)? ~Res1: Res1) ); + } +} + + +/**Function************************************************************* + + Synopsis [Resimulate and refine one equivalence class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Gia_Resimulate_rec( Hcd_Man_t * p, int iObj ) +{ + Gia_Obj_t * pObj; + unsigned Res0, Res1; + if ( Gia_ObjIsTravIdCurrentId( p->pGia, iObj ) ) + return Hcd_ObjSim( p, iObj ); + Gia_ObjSetTravIdCurrentId( p->pGia, iObj ); + pObj = Gia_ManObj(p->pGia, iObj); + if ( Gia_ObjIsCi(pObj) ) + return Hcd_ObjSim( p, iObj ); + assert( Gia_ObjIsAnd(pObj) ); + Res0 = Gia_Resimulate_rec( p, Gia_ObjFaninId0(pObj, iObj) ); + Res1 = Gia_Resimulate_rec( p, Gia_ObjFaninId1(pObj, iObj) ); + return Hcd_ObjSetSim( p, iObj, (Gia_ObjFaninC0(pObj)? ~Res0: Res0) & + (Gia_ObjFaninC1(pObj)? ~Res1: Res1) ); +} + +/**Function************************************************************* + + Synopsis [Resimulate and refine one equivalence class.] + + Description [Assumes that the counter-example is assigned at the PIs. + The counter-example should have the first bit set to 0 at each PI.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ResimulateAndRefine( Hcd_Man_t * p, int i ) +{ + int RetValue, iObj; + Gia_ManIncrementTravId( p->pGia ); + Gia_ClassForEachObj( p->pGia, i, iObj ) + Gia_Resimulate_rec( p, iObj ); + RetValue = Hcd_ManClassRefineOne( p, i ); + if ( RetValue == 0 ) + printf( "!!! no refinement !!!\n" ); +// assert( RetValue ); +} + +/**Function************************************************************* + + Synopsis [Returns temporary representative of the node.] + + Description [The temp repr is the first node among the nodes in the class that + (a) precedes the given node, and (b) whose level is lower than the given node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * Gia_ObjTempRepr( Gia_Man_t * p, int i, int Level ) +{ + int iRepr, iMember; + iRepr = Gia_ObjRepr( p, i ); + if ( !Gia_ObjProved(p, i) ) + return NULL; + if ( Gia_ObjFailed(p, i) ) + return NULL; + if ( iRepr == GIA_VOID ) + return NULL; + if ( iRepr == 0 ) + return Gia_ManConst0( p ); +// if ( p->pLevels[iRepr] < Level ) +// return Gia_ManObj( p, iRepr ); + Gia_ClassForEachObj( p, iRepr, iMember ) + { + if ( Gia_ObjFailed(p, iMember) ) + continue; + if ( iMember >= i ) + return NULL; + if ( Gia_ObjLevelId(p, iMember) < Level ) + return Gia_ManObj( p, iMember ); + } + assert( 0 ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Generates reduced AIG for the given level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_GenerateReducedLevel( Gia_Man_t * p, int Level, Vec_Ptr_t ** pvRoots ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj, * pRepr; + Vec_Ptr_t * vRoots; + int i; + vRoots = Vec_PtrAlloc( 100 ); + // copy unmarked nodes + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + { + if ( Gia_ObjLevelId(p, i) > Level ) + continue; + if ( Gia_ObjLevelId(p, i) == Level ) + Vec_PtrPush( vRoots, pObj ); + if ( Gia_ObjLevelId(p, i) < Level && (pRepr = Gia_ObjTempRepr(p, i, Level)) ) + { +// printf( "Substituting %d <--- %d\n", Gia_ObjId(p, pRepr), Gia_ObjId(p, pObj) ); + assert( pRepr < pObj ); + pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhase(pRepr) ^ Gia_ObjPhase(pObj) ); + continue; + } + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + *pvRoots = vRoots; + // required by SAT solving + Gia_ManCreateRefs( pNew ); + Gia_ManFillValue( pNew ); + Gia_ManIncrementTravId( pNew ); // needed for MiniSat to record cexes +// Gia_ManSetPhase( pNew ); // needed if MiniSat is using polarity -- should not be enabled for TAS because fPhase is used to label + return pNew; +} + +/**Function************************************************************* + + Synopsis [Collects relevant classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Gia_CollectRelatedClasses( Gia_Man_t * pGia, Vec_Ptr_t * vRoots ) +{ + Vec_Ptr_t * vClasses; + Gia_Obj_t * pRoot, * pRepr; + int i; + vClasses = Vec_PtrAlloc( 100 ); + Gia_ManConst0( pGia )->fMark0 = 1; + Vec_PtrForEachEntry( Gia_Obj_t *, vRoots, pRoot, i ) + { + pRepr = Gia_ObjReprObj( pGia, Gia_ObjId(pGia, pRoot) ); + if ( pRepr == NULL || pRepr->fMark0 ) + continue; + pRepr->fMark0 = 1; + Vec_PtrPush( vClasses, pRepr ); + } + Gia_ManConst0( pGia )->fMark0 = 0; + Vec_PtrForEachEntry( Gia_Obj_t *, vClasses, pRepr, i ) + pRepr->fMark0 = 0; + return vClasses; +} + +/**Function************************************************************* + + Synopsis [Collects class members.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Obj_t * Gia_CollectClassMembers( Gia_Man_t * p, Gia_Obj_t * pRepr, Vec_Ptr_t * vMembers, int Level ) +{ + Gia_Obj_t * pTempRepr = NULL; + int iRepr, iMember; + iRepr = Gia_ObjId( p, pRepr ); + Vec_PtrClear( vMembers ); + Gia_ClassForEachObj( p, iRepr, iMember ) + { + if ( Gia_ObjLevelId(p, iMember) == Level ) + Vec_PtrPush( vMembers, Gia_ManObj( p, iMember ) ); + if ( pTempRepr == NULL && Gia_ObjLevelId(p, iMember) < Level ) + pTempRepr = Gia_ManObj( p, iMember ); + } + return pTempRepr; +} + + +/**Function************************************************************* + + Synopsis [Packs patterns into array of simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +*************************************`**********************************/ +int Gia_GiarfStorePatternTry( Vec_Ptr_t * vInfo, Vec_Ptr_t * vPres, int iBit, int * pLits, int nLits ) +{ + unsigned * pInfo, * pPres; + int i; + for ( i = 0; i < nLits; i++ ) + { + pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i])); + pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i])); + if ( Abc_InfoHasBit( pPres, iBit ) && + Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) ) + return 0; + } + for ( i = 0; i < nLits; i++ ) + { + pInfo = (unsigned *)Vec_PtrEntry(vInfo, Abc_Lit2Var(pLits[i])); + pPres = (unsigned *)Vec_PtrEntry(vPres, Abc_Lit2Var(pLits[i])); + Abc_InfoSetBit( pPres, iBit ); + if ( Abc_InfoHasBit( pInfo, iBit ) == Abc_LitIsCompl(pLits[i]) ) + Abc_InfoXorBit( pInfo, iBit ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Procedure to test the new SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_GiarfStorePattern( Vec_Ptr_t * vSimInfo, Vec_Ptr_t * vPres, Vec_Int_t * vCex ) +{ + int k; + for ( k = 1; k < 32; k++ ) + if ( Gia_GiarfStorePatternTry( vSimInfo, vPres, k, (int *)Vec_IntArray(vCex), Vec_IntSize(vCex) ) ) + break; + return (int)(k < 32); +} + +/**Function************************************************************* + + Synopsis [Inserts pattern into simulation info for the PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_GiarfInsertPattern( Hcd_Man_t * p, Vec_Int_t * vCex, int k ) +{ + Gia_Obj_t * pObj; + unsigned * pInfo; + int Lit, i; + Vec_IntForEachEntry( vCex, Lit, i ) + { + pObj = Gia_ManCi( p->pGia, Abc_Lit2Var(Lit) ); + pInfo = Hcd_ObjSimP( p, Gia_ObjId( p->pGia, pObj ) ); + if ( Abc_InfoHasBit( pInfo, k ) == Abc_LitIsCompl(Lit) ) + Abc_InfoXorBit( pInfo, k ); + } +} + +/**Function************************************************************* + + Synopsis [Inserts pattern into simulation info for the PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_GiarfPrintClasses( Gia_Man_t * pGia ) +{ + int nFails = 0; + int nProves = 0; + int nTotal = 0; + int nBoth = 0; + int i; + for ( i = 0; i < Gia_ManObjNum(pGia); i++ ) + { + nFails += Gia_ObjFailed(pGia, i); + nProves += Gia_ObjProved(pGia, i); + nTotal += Gia_ObjReprObj(pGia, i) != NULL; + nBoth += Gia_ObjFailed(pGia, i) && Gia_ObjProved(pGia, i); + } + printf( "nFails = %7d. nProves = %7d. nBoth = %7d. nTotal = %7d.\n", + nFails, nProves, nBoth, nTotal ); +} + +ABC_NAMESPACE_IMPL_END + +#include "proof/cec/cecInt.h" + +ABC_NAMESPACE_IMPL_START + + +/**Function************************************************************* + + Synopsis [Performs computation of AIGs with choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ComputeEquivalencesLevel( Hcd_Man_t * p, Gia_Man_t * pGiaLev, Vec_Ptr_t * vOldRoots, int Level, int fUseMiniSat ) +{ + int fUse2Solver = 0; + Cec_ManSat_t * pSat; + Cec_ParSat_t Pars; + Tas_Man_t * pTas; + Vec_Int_t * vCex; + Vec_Ptr_t * vClasses, * vMembers, * vOldRootsNew; + Gia_Obj_t * pRoot, * pMember, * pMemberPrev, * pRepr, * pTempRepr; + int i, k, nIter, iRoot, iRootNew, iMember, iMemberPrev, status, fOneFailed;//, iRepr;//, fTwoMember; + int nSaved = 0, nRecords = 0, nUndec = 0, nClassRefs = 0, nTsat = 0, nMiniSat = 0; + clock_t clk, timeTsat = 0, timeMiniSat = 0, timeSim = 0, timeTotal = clock(); + if ( Vec_PtrSize(vOldRoots) == 0 ) + return 0; + // start SAT solvers + Cec_ManSatSetDefaultParams( &Pars ); + Pars.fPolarFlip = 0; + Pars.nBTLimit = p->nBTLimit; + pSat = Cec_ManSatCreate( pGiaLev, &Pars ); + pTas = Tas_ManAlloc( pGiaLev, p->nBTLimit ); + if ( fUseMiniSat ) + vCex = Cec_ManSatReadCex( pSat ); + else + vCex = Tas_ReadModel( pTas ); + vMembers = Vec_PtrAlloc( 100 ); + Vec_PtrCleanSimInfo( p->vSimPres, 0, 1 ); + // resolve constants + Vec_PtrForEachEntry( Gia_Obj_t *, vOldRoots, pRoot, i ) + { + iRoot = Gia_ObjId( p->pGia, pRoot ); + if ( !Gia_ObjIsConst( p->pGia, iRoot ) ) + continue; + iRootNew = Abc_LitNotCond( pRoot->Value, pRoot->fPhase ); + assert( iRootNew != 1 ); + if ( fUse2Solver ) + { + nTsat++; + clk = clock(); + status = Tas_ManSolve( pTas, Gia_ObjFromLit(pGiaLev, iRootNew), NULL ); + timeTsat += clock() - clk; + if ( status == -1 ) + { + nMiniSat++; + clk = clock(); + status = Cec_ManSatCheckNode( pSat, Gia_ObjFromLit(pGiaLev, iRootNew) ); + timeMiniSat += clock() - clk; + if ( status == 0 ) + { + Cec_ManSavePattern( pSat, Gia_ObjFromLit(pGiaLev, iRootNew), NULL ); + vCex = Cec_ManSatReadCex( pSat ); + } + } + else if ( status == 0 ) + vCex = Tas_ReadModel( pTas ); + } + else if ( fUseMiniSat ) + { + nMiniSat++; + clk = clock(); + status = Cec_ManSatCheckNode( pSat, Gia_ObjFromLit(pGiaLev, iRootNew) ); + timeMiniSat += clock() - clk; + if ( status == 0 ) + Cec_ManSavePattern( pSat, Gia_ObjFromLit(pGiaLev, iRootNew), NULL ); + } + else + { + nTsat++; + clk = clock(); + status = Tas_ManSolve( pTas, Gia_ObjFromLit(pGiaLev, iRootNew), NULL ); + timeTsat += clock() - clk; + } + if ( status == -1 ) // undec + { +// Gia_ObjSetFailed( p->pGia, iRoot ); + nUndec++; +// Hcd_ManClassClassRemoveOne( p, iRoot ); + Gia_ObjSetFailed( p->pGia, iRoot ); + } + else if ( status == 1 ) // unsat + { + Gia_ObjSetProved( p->pGia, iRoot ); +// printf( "proved constant %d\n", iRoot ); + } + else // sat + { +// printf( "Disproved constant %d\n", iRoot ); + Gia_ObjUnsetRepr( p->pGia, iRoot ); // do we need this? + nRecords++; + nSaved += Gia_GiarfStorePattern( p->vSimInfo, p->vSimPres, vCex ); + } + } + + vClasses = Vec_PtrAlloc( 100 ); + vOldRootsNew = Vec_PtrAlloc( 100 ); + for ( nIter = 0; Vec_PtrSize(vOldRoots) > 0; nIter++ ) + { +// printf( "Iter = %d (Size = %d)\n", nIter, Vec_PtrSize(vOldRoots) ); + // resolve equivalences + Vec_PtrClear( vClasses ); + Vec_PtrClear( vOldRootsNew ); + Gia_ManConst0( p->pGia )->fMark0 = 1; + Vec_PtrForEachEntry( Gia_Obj_t *, vOldRoots, pRoot, i ) + { + iRoot = Gia_ObjId( p->pGia, pRoot ); + if ( Gia_ObjIsHead( p->pGia, iRoot ) ) + pRepr = pRoot; + else if ( Gia_ObjIsClass( p->pGia, iRoot ) ) + pRepr = Gia_ObjReprObj( p->pGia, iRoot ); + else + continue; + if ( pRepr->fMark0 ) + continue; + pRepr->fMark0 = 1; + Vec_PtrPush( vClasses, pRepr ); +// iRepr = Gia_ObjId( p->pGia, pRepr ); +// fTwoMember = Gia_ClassIsPair(p->pGia, iRepr) + // derive temp repr and members on this level + pTempRepr = Gia_CollectClassMembers( p->pGia, pRepr, vMembers, Level ); + if ( pTempRepr ) + Vec_PtrPush( vMembers, pTempRepr ); + if ( Vec_PtrSize(vMembers) < 2 ) + continue; + // try proving the members + fOneFailed = 0; + pMemberPrev = (Gia_Obj_t *)Vec_PtrEntryLast( vMembers ); + Vec_PtrForEachEntry( Gia_Obj_t *, vMembers, pMember, k ) + { + iMemberPrev = Abc_LitNotCond( pMemberPrev->Value, pMemberPrev->fPhase ); + iMember = Abc_LitNotCond( pMember->Value, !pMember->fPhase ); + assert( iMemberPrev != iMember ); + if ( fUse2Solver ) + { + nTsat++; + clk = clock(); + status = Tas_ManSolve( pTas, Gia_ObjFromLit(pGiaLev, iMemberPrev), Gia_ObjFromLit(pGiaLev, iMember) ); + timeTsat += clock() - clk; + if ( status == -1 ) + { + nMiniSat++; + clk = clock(); + status = Cec_ManSatCheckNodeTwo( pSat, Gia_ObjFromLit(pGiaLev, iMemberPrev), Gia_ObjFromLit(pGiaLev, iMember) ); + timeMiniSat += clock() - clk; + if ( status == 0 ) + { + Cec_ManSavePattern( pSat, Gia_ObjFromLit(pGiaLev, iMemberPrev), Gia_ObjFromLit(pGiaLev, iMember) ); + vCex = Cec_ManSatReadCex( pSat ); + } + } + else if ( status == 0 ) + vCex = Tas_ReadModel( pTas ); + } + else if ( fUseMiniSat ) + { + nMiniSat++; + clk = clock(); + status = Cec_ManSatCheckNodeTwo( pSat, Gia_ObjFromLit(pGiaLev, iMemberPrev), Gia_ObjFromLit(pGiaLev, iMember) ); + timeMiniSat += clock() - clk; + if ( status == 0 ) + Cec_ManSavePattern( pSat, Gia_ObjFromLit(pGiaLev, iMemberPrev), Gia_ObjFromLit(pGiaLev, iMember) ); + } + else + { + nTsat++; + clk = clock(); + status = Tas_ManSolve( pTas, Gia_ObjFromLit(pGiaLev, iMemberPrev), Gia_ObjFromLit(pGiaLev, iMember) ); + timeTsat += clock() - clk; + } + if ( status == -1 ) // undec + { +// Gia_ObjSetFailed( p->pGia, iRoot ); + nUndec++; + if ( Gia_ObjLevel(p->pGia, pMemberPrev) > Gia_ObjLevel(p->pGia, pMember) ) + { +// Hcd_ManClassClassRemoveOne( p, Gia_ObjId(p->pGia, pMemberPrev) ); + Gia_ObjSetFailed( p->pGia, Gia_ObjId(p->pGia, pMemberPrev) ); + Gia_ObjSetFailed( p->pGia, Gia_ObjId(p->pGia, pMember) ); + } + else + { +// Hcd_ManClassClassRemoveOne( p, Gia_ObjId(p->pGia, pMember) ); + Gia_ObjSetFailed( p->pGia, Gia_ObjId(p->pGia, pMemberPrev) ); + Gia_ObjSetFailed( p->pGia, Gia_ObjId(p->pGia, pMember) ); + } + } + else if ( status == 1 ) // unsat + { +// Gia_ObjSetProved( p->pGia, iRoot ); + } + else // sat + { +// iRepr = Gia_ObjId( p->pGia, pRepr ); +// if ( Gia_ClassIsPair(p->pGia, iRepr) ) +// Gia_ClassUndoPair(p->pGia, iRepr); +// else + { + fOneFailed = 1; + nRecords++; + nSaved += Gia_GiarfStorePattern( p->vSimInfo, p->vSimPres, vCex ); + Gia_GiarfInsertPattern( p, vCex, (k % 31) + 1 ); + } + } + pMemberPrev = pMember; +// if ( fOneFailed ) +// k += Vec_PtrSize(vMembers) / 4; + } + // if fail, quit this class + if ( fOneFailed ) + { + nClassRefs++; + Vec_PtrForEachEntry( Gia_Obj_t *, vMembers, pMember, k ) + if ( pMember != pTempRepr && !Gia_ObjFailed(p->pGia, Gia_ObjId(p->pGia, pMember)) ) + Vec_PtrPush( vOldRootsNew, pMember ); + clk = clock(); + Gia_ResimulateAndRefine( p, Gia_ObjId(p->pGia, pRepr) ); + timeSim += clock() - clk; + } + else + { + Vec_PtrForEachEntry( Gia_Obj_t *, vMembers, pMember, k ) + Gia_ObjSetProved( p->pGia, Gia_ObjId(p->pGia, pMember) ); +/* +// } +// else +// { + printf( "Proved equivalent: " ); + Vec_PtrForEachEntry( Gia_Obj_t *, vMembers, pMember, k ) + printf( "%d(L=%d) ", Gia_ObjId(p->pGia, pMember), p->pGia->pLevels[Gia_ObjId(p->pGia, pMember)] ); + printf( "\n" ); +*/ + } + + } + Vec_PtrClear( vOldRoots ); + Vec_PtrForEachEntry( Gia_Obj_t *, vOldRootsNew, pMember, i ) + Vec_PtrPush( vOldRoots, pMember ); + // clean up + Gia_ManConst0( p->pGia )->fMark0 = 0; + Vec_PtrForEachEntry( Gia_Obj_t *, vClasses, pRepr, i ) + pRepr->fMark0 = 0; + } + Vec_PtrFree( vClasses ); + Vec_PtrFree( vOldRootsNew ); + printf( "nSaved = %d nRecords = %d nUndec = %d nClassRefs = %d nMiniSat = %d nTas = %d\n", + nSaved, nRecords, nUndec, nClassRefs, nMiniSat, nTsat ); + ABC_PRT( "Tas ", timeTsat ); + ABC_PRT( "MiniSat", timeMiniSat ); + ABC_PRT( "Sim ", timeSim ); + ABC_PRT( "Total ", clock() - timeTotal ); + + // resimulate +// clk = clock(); + Hcd_ManSimulateSimple( p ); + Hcd_ManClassesRefine( p ); +// ABC_PRT( "Simulate/refine", clock() - clk ); + + // verify the results + Vec_PtrFree( vMembers ); + Tas_ManStop( pTas ); + Cec_ManSatStop( pSat ); + return nIter; +} + +/**Function************************************************************* + + Synopsis [Performs computation of AIGs with choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ComputeEquivalences( Gia_Man_t * pGia, int nBTLimit, int fUseMiniSat, int fVerbose ) +{ + Hcd_Man_t * p; + Vec_Ptr_t * vRoots; + Gia_Man_t * pGiaLev; + int i, Lev, nLevels, nIters; + clock_t clk; + Gia_ManRandom( 1 ); + Gia_ManSetPhase( pGia ); + nLevels = Gia_ManLevelNum( pGia ); + Gia_ManIncrementTravId( pGia ); + // start the manager + p = Gia_ManEquivStart( pGia, nBTLimit, fVerbose ); + // create trivial classes + Hcd_ManClassesCreate( p ); + // refine + for ( i = 0; i < 3; i++ ) + { + clk = clock(); + Hcd_ManSimulationInit( p ); + Hcd_ManSimulateSimple( p ); + ABC_PRT( "Sim", clock() - clk ); + clk = clock(); + Hcd_ManClassesRefine( p ); + ABC_PRT( "Ref", clock() - clk ); + } + // process in the levelized order + for ( Lev = 1; Lev < nLevels; Lev++ ) + { + clk = clock(); + printf( "LEVEL %3d (out of %3d) ", Lev, nLevels ); + pGiaLev = Gia_GenerateReducedLevel( pGia, Lev, &vRoots ); + nIters = Gia_ComputeEquivalencesLevel( p, pGiaLev, vRoots, Lev, fUseMiniSat ); + Gia_ManStop( pGiaLev ); + Vec_PtrFree( vRoots ); + printf( "Iters = %3d " ); + ABC_PRT( "Time", clock() - clk ); + } + Gia_GiarfPrintClasses( pGia ); + // clean up + Gia_ManEquivStop( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaGig.c b/yosys/abc/src/aig/gia/giaGig.c new file mode 100644 index 00000000000..b1696b09d39 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaGig.c @@ -0,0 +1,506 @@ +/**CFile**************************************************************** + + FileName [giaGig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Parser for Gate-Inverter Graph by Niklas Een.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaGig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/extra/extra.h" +#include "misc/util/utilTruth.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define MAX_LINE 1000000 + +// network types +enum { + GLS_NONE = -1, // not used + GLS_ZERO = 0, // zero + GLS_ONE = 1, // one + GLS_PI = 2, // primary input + GLS_PO = 3, // primary output + GLS_BAR = 4, // barrier + GLS_SEQ = 5, // sequential + GLS_SEL = 6, // fan + GLS_LUT4 = 7, // LUT4 + GLS_LUT6 = 8, // LUT6 + GLS_BOX = 9, // sequential box + GLS_DEL = 10, // delay box + GLS_FINAL +}; + +static char * s_Strs[GLS_FINAL] = +{ + "0", // GLS_ZERO = 0, // zero + "1", // GLS_ONE = 1, // one + "PI", // GLS_PI = 2, // primary input + "PO", // GLS_PO = 3, // primary output + "Bar", // GLS_BAR = 4, // barrier + "Seq", // GLS_SEQ = 5, // sequential + "Sel", // GLS_SEL = 6, // fan + "Lut4", // GLS_LUT4 = 7, // LUT4 + "Lut6", // GLS_LUT6 = 8, // LUT6 + "Box", // GLS_BOX = 9, // sequential box + "Del" // GLS_DEL = 10, // delay box +}; + +typedef struct Gls_Man_t_ Gls_Man_t; +struct Gls_Man_t_ +{ + // general + Vec_Str_t * vLines; // line types + Vec_Str_t * vTypes; // gate types + Vec_Int_t * vIndexes; // gate indexes + // specific types + Vec_Int_t * vLut4s; // 4-LUTs (4-tuples) + Vec_Int_t * vLut4TTs; // truth tables + Vec_Int_t * vLut6s; // 6-LUTs (6-tuples) + Vec_Wrd_t * vLut6TTs; // truth tables + Vec_Int_t * vBoxes; // boxes (5-tuples) + Vec_Wec_t * vDelayIns; // delay fanins + Vec_Wec_t * vDelayOuts; // delay fanouts + Vec_Int_t * vDelays; // delay values + // ordering + Vec_Int_t * vOrderPis; + Vec_Int_t * vOrderPos; + Vec_Int_t * vOrderBoxes; + Vec_Int_t * vOrderDelays; + Vec_Int_t * vOrderLuts; + Vec_Int_t * vOrderSeqs; +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gls_Man_t * Gls_ManAlloc( Vec_Str_t * vLines, int * pCounts ) +{ + Gls_Man_t * p = ABC_CALLOC( Gls_Man_t, 1 ); + p->vLines = vLines; + p->vTypes = Vec_StrStart( Vec_StrSize(vLines)+100 ); + p->vIndexes = Vec_IntStart( Vec_StrSize(vLines)+100 ); + p->vLut4s = Vec_IntAlloc( 4 * pCounts[GLS_LUT4] ); + p->vLut4TTs = Vec_IntAlloc( pCounts[GLS_LUT4] ); + p->vLut6s = Vec_IntAlloc( 6 * pCounts[GLS_LUT6] ); + p->vLut6TTs = Vec_WrdAlloc( pCounts[GLS_LUT6] ); + p->vBoxes = Vec_IntAlloc( 5 * pCounts[GLS_BOX] ); + p->vDelays = Vec_IntAlloc( pCounts[GLS_DEL] ); + p->vDelayIns = Vec_WecAlloc( pCounts[GLS_DEL] ); + p->vDelayOuts = Vec_WecAlloc( pCounts[GLS_DEL] ); + // ordering + p->vOrderPis = Vec_IntAlloc( pCounts[GLS_PI] ); + p->vOrderPos = Vec_IntAlloc( pCounts[GLS_PO] ); + p->vOrderBoxes = Vec_IntAlloc( pCounts[GLS_BOX] ); + p->vOrderDelays = Vec_IntAlloc( pCounts[GLS_DEL] ); + p->vOrderLuts = Vec_IntAlloc( pCounts[GLS_LUT4] + pCounts[GLS_LUT6] + 2*pCounts[GLS_BAR] ); + p->vOrderSeqs = Vec_IntAlloc( pCounts[GLS_SEQ] ); + return p; +} +void Gls_ManStop( Gls_Man_t * p ) +{ + Vec_StrFree( p->vLines ); + Vec_StrFree( p->vTypes ); + Vec_IntFree( p->vIndexes ); + Vec_IntFree( p->vLut4s ); + Vec_IntFree( p->vLut4TTs ); + Vec_IntFree( p->vLut6s ); + Vec_WrdFree( p->vLut6TTs ); + Vec_IntFree( p->vBoxes ); + Vec_IntFree( p->vDelays ); + Vec_WecFree( p->vDelayIns ); + Vec_WecFree( p->vDelayOuts ); + // ordering + Vec_IntFree( p->vOrderPis ); + Vec_IntFree( p->vOrderPos ); + Vec_IntFree( p->vOrderBoxes ); + Vec_IntFree( p->vOrderDelays ); + Vec_IntFree( p->vOrderLuts ); + Vec_IntFree( p->vOrderSeqs ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Str_t * Gls_ManCount( FILE * pFile, int pCounts[GLS_FINAL] ) +{ + char * pLine, * pBuffer = ABC_ALLOC(char, MAX_LINE); int Type; + Vec_Str_t * vLines = Vec_StrAlloc( 10000 ); + memset( pCounts, 0, sizeof(int)*GLS_FINAL ); + while ( fgets( pBuffer, MAX_LINE, pFile ) != NULL ) + { + pLine = pBuffer; + while ( *pLine ) + if ( *pLine++ == '=' ) + break; + while ( *pLine == ' ' ) + pLine++; + if ( *pLine == 'L' ) + { + if ( pLine[3] == '4' ) + Type = GLS_LUT4; + else if ( pLine[3] == '6' ) + Type = GLS_LUT6; + else assert( 0 ); + } + else if ( *pLine == 'P' ) + { + if ( pLine[1] == 'I' ) + Type = GLS_PI; + else if ( pLine[1] == 'O' ) + Type = GLS_PO; + else assert( 0 ); + } + else if ( *pLine == 'B' ) + { + if ( pLine[1] == 'o' ) + Type = GLS_BOX; + else if ( pLine[1] == 'a' ) + Type = GLS_BAR; + else assert( 0 ); + } + else if ( *pLine == 'S' ) + { + if ( pLine[2] == 'l' ) + Type = GLS_SEL; + else if ( pLine[2] == 'q' ) + Type = GLS_SEQ; + else assert( 0 ); + } + else if ( *pLine == 'D' ) + Type = GLS_DEL; + else assert( 0 ); + Vec_StrPush( vLines, (char)Type ); + pCounts[Type]++; + } + ABC_FREE( pBuffer ); + return vLines; +} +int Gls_ManParseOne( char ** ppLine ) +{ + int Entry; + char * pLine = *ppLine; + while ( *pLine == ' ' ) pLine++; + if ( *pLine == '-' ) + Entry = GLS_NONE; + else if ( *pLine == '0' ) + Entry = 0; + else if ( *pLine == '1' ) + Entry = 1; + else if ( *pLine == 'w' ) + Entry = atoi(++pLine); + else assert( 0 ); + while ( *pLine == '-' || (*pLine >= '0' && *pLine <= '9') ) pLine++; + while ( *pLine == ' ' ) pLine++; + *ppLine = pLine; + return Entry; +} +int Gls_ManParse( FILE * pFile, Gls_Man_t * p ) +{ + char * pLine, * pBuffer = ABC_ALLOC(char, MAX_LINE); + int i, k, Type, iObj, Entry, iItem; word Truth; + for ( i = 0; fgets( pBuffer, MAX_LINE, pFile ) != NULL; i++ ) + { + pLine = pBuffer; + Type = Vec_StrEntry( p->vLines, i ); + iObj = Gls_ManParseOne( &pLine ); + Vec_StrWriteEntry( p->vTypes, iObj, (char)Type ); + if ( Type == GLS_PI ) + { + Vec_IntPush( p->vOrderPis, iObj ); + Vec_IntWriteEntry( p->vIndexes, iObj, -1 ); + continue; + } + while ( *pLine ) + if ( *pLine++ == '(' ) + break; + Entry = Gls_ManParseOne( &pLine ); + if ( Type == GLS_PO || Type == GLS_BAR || Type == GLS_SEQ || Type == GLS_SEL ) + { + if ( Type == GLS_PO ) + Vec_IntPush( p->vOrderPos, iObj ); + else if ( Type == GLS_BAR ) + Vec_IntPush( p->vOrderLuts, iObj ); + else if ( Type == GLS_SEQ ) + Vec_IntPush( p->vOrderSeqs, iObj ); + else if ( Type == GLS_SEL ) + { + if ( (int)Vec_StrEntry(p->vTypes, Entry) == GLS_DEL ) + { + Vec_Int_t * vOuts = Vec_WecEntry( p->vDelayOuts, Vec_IntEntry(p->vIndexes, Entry) ); + Vec_IntPush( vOuts, iObj ); + } + else if ( (int)Vec_StrEntry(p->vTypes, Entry) == GLS_BAR ) + Vec_IntPush( p->vOrderLuts, iObj ); + else assert( 0 ); + } + Vec_IntWriteEntry( p->vIndexes, iObj, Entry ); + continue; + } + if ( Type == GLS_LUT4 ) + { + Vec_IntWriteEntry( p->vIndexes, iObj, Vec_IntSize(p->vLut4TTs) ); + Vec_IntPush( p->vLut4s, Entry ); + for ( k = 1; ; k++ ) + { + if ( *pLine != ',' ) break; + pLine++; + Entry = Gls_ManParseOne( &pLine ); + Vec_IntPush( p->vLut4s, Entry ); + } + assert( *pLine == ')' ); + assert( k == 4 ); + pLine++; + while ( *pLine ) + if ( *pLine++ == '[' ) + break; + Abc_TtReadHex( &Truth, pLine ); + Vec_IntPush( p->vLut4TTs, (unsigned)Truth ); + Vec_IntPush( p->vOrderLuts, iObj ); + } + else if ( Type == GLS_LUT6 ) + { + Vec_IntWriteEntry( p->vIndexes, iObj, Vec_WrdSize(p->vLut6TTs) ); + Vec_IntPush( p->vLut6s, Entry ); + for ( k = 1; ; k++ ) + { + if ( *pLine != ',' ) break; + pLine++; + Entry = Gls_ManParseOne( &pLine ); + Vec_IntPush( p->vLut6s, Entry ); + } + assert( *pLine == ')' ); + assert( k == 4 ); + pLine++; + while ( *pLine ) + if ( *pLine++ == '[' ) + break; + Abc_TtReadHex( &Truth, pLine ); + Vec_WrdPush( p->vLut6TTs, Truth ); + Vec_IntPush( p->vOrderLuts, iObj ); + } + else if ( Type == GLS_BOX ) + { + Vec_IntWriteEntry( p->vIndexes, iObj, Vec_IntSize(p->vBoxes)/5 ); + Vec_IntPush( p->vBoxes, Entry ); + for ( k = 1; ; k++ ) + { + if ( *pLine != ',' ) break; + pLine++; + Entry = Gls_ManParseOne( &pLine ); + Vec_IntPush( p->vBoxes, Entry ); + } + assert( *pLine == ')' ); + assert( k == 4 || k == 5 ); + if ( k == 4 ) + Vec_IntPush( p->vBoxes, GLS_NONE ); + Vec_IntPush( p->vOrderBoxes, iObj ); + } + else if ( Type == GLS_DEL ) + { + Vec_Int_t * vIns = Vec_WecPushLevel( p->vDelayIns ); + Vec_Int_t * vOuts = Vec_WecPushLevel( p->vDelayOuts ); + Vec_IntWriteEntry( p->vIndexes, iObj, Vec_IntSize(p->vDelays) ); + Vec_IntPush( vIns, Entry ); + if ( *pLine != ')' ) + { + for ( k = 1; ; k++ ) + { + if ( *pLine != ',' ) break; + pLine++; + Entry = Gls_ManParseOne( &pLine ); + Vec_IntPush( vIns, Entry ); + } + } + assert( *pLine == ')' ); + pLine++; + while ( *pLine ) + if ( *pLine++ == '[' ) + break; + iItem = atoi(pLine); + Vec_IntPush( p->vDelays, iItem ); + Vec_IntPush( p->vOrderDelays, iObj ); + vOuts = vIns; // harmless use to prevent a compiler warning + } + else assert( 0 ); + } + ABC_FREE( pBuffer ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gls_ManConstruct( Gls_Man_t * p, char * pFileName ) +{ + extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); + Gia_Man_t * pGia = NULL; + Vec_Int_t * vMap, * vArray; + Vec_Int_t * vCover = Vec_IntAlloc(0); + Vec_Int_t * vLeaves = Vec_IntAlloc(6); + int k, iObj, iLit, Index; char Type; + // create new manager + pGia = Gia_ManStart( Vec_StrSize(p->vTypes) ); + pGia->pName = Abc_UtilStrsav( pFileName ); + pGia->pSpec = Abc_UtilStrsav( pFileName ); + // create constants + vMap = Vec_IntStartFull( Vec_StrSize(p->vTypes) ); + Vec_IntWriteEntry( vMap, 0, 0 ); + Vec_IntWriteEntry( vMap, 1, 1 ); + // create primary inputs + Vec_IntForEachEntry( p->vOrderPis, iObj, k ) + Vec_IntWriteEntry( vMap, iObj, Gia_ManAppendCi(pGia) ); + // create box outputs + Vec_IntForEachEntry( p->vOrderBoxes, iObj, k ) + Vec_IntWriteEntry( vMap, iObj, Gia_ManAppendCi(pGia) ); + // create delay outputs + Vec_IntForEachEntry( p->vOrderDelays, iObj, Index ) + { + assert( Index == Vec_IntEntry(p->vIndexes, iObj) ); + vArray = Vec_WecEntry(p->vDelayOuts, Index); + if ( Vec_IntSize(vArray) == 0 ) + Vec_IntWriteEntry( vMap, iObj, Gia_ManAppendCi(pGia) ); + else + Vec_IntForEachEntry( vArray, iObj, k ) + Vec_IntWriteEntry( vMap, iObj, Gia_ManAppendCi(pGia) ); + } + // construct LUTs + Vec_IntForEachEntry( p->vOrderLuts, iObj, Index ) + { + Type = Vec_StrEntry( p->vTypes, iObj ); + if ( Type == GLS_LUT4 || Type == GLS_LUT6 ) + { + int Limit = Type == GLS_LUT4 ? 4 : 6; + int Index = Vec_IntEntry(p->vIndexes, iObj); + int * pFanins = Type == GLS_LUT4 ? Vec_IntEntryP(p->vLut4s, 4*Index) : Vec_IntEntryP(p->vLut6s, 6*Index); + word Truth = Type == GLS_LUT4 ? (word)Vec_IntEntry(p->vLut4TTs, Index) : Vec_WrdEntry(p->vLut6TTs, Index); + Vec_IntClear( vLeaves ); + for ( k = 0; k < Limit; k++ ) + Vec_IntPush( vLeaves, pFanins[k] == GLS_NONE ? 0 : Vec_IntEntry(vMap, pFanins[k]) ); + iLit = Kit_TruthToGia( pGia, (unsigned *)&Truth, Vec_IntSize(vLeaves), vCover, vLeaves, 0 ); + Vec_IntWriteEntry( vMap, iObj, iLit ); + } + else if ( Type == GLS_BAR || Type == GLS_SEL ) + { + iLit = Vec_IntEntry( vMap, Vec_IntEntry(p->vIndexes, iObj) ); + Vec_IntWriteEntry( vMap, iObj, iLit ); + } + } + // delay inputs + Vec_IntForEachEntry( p->vOrderDelays, iObj, Index ) + { + vArray = Vec_WecEntry(p->vDelayIns, Index); + assert( Vec_IntSize(vArray) > 0 ); + Vec_IntForEachEntry( vArray, iObj, k ) + Gia_ManAppendCo( pGia, Vec_IntEntry(vMap, iObj) ); + } + // create primary outputs + Vec_IntForEachEntry( p->vOrderPos, iObj, k ) + Gia_ManAppendCo( pGia, Vec_IntEntry(vMap, Vec_IntEntry(p->vIndexes, iObj)) ); + // create sequential nodes + Vec_IntForEachEntry( p->vOrderSeqs, iObj, k ) + Gia_ManAppendCo( pGia, Vec_IntEntry(vMap, Vec_IntEntry(p->vIndexes, iObj)) ); + Vec_IntFree( vMap ); + Vec_IntFree( vCover ); + Vec_IntFree( vLeaves ); + // print delay boxes +// for ( k = 0; k < Vec_IntSize(p->vDelays); k++ ) +// printf( "%d:%d ", Vec_IntSize(Vec_WecEntry(p->vDelayIns, k)), Vec_IntSize(Vec_WecEntry(p->vDelayOuts, k)) ); +// printf( "\n" ); + return pGia; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManReadGig( char * pFileName ) +{ + abctime clk = Abc_Clock(); + Gls_Man_t * p = NULL; + Gia_Man_t * pGia = NULL; + Vec_Str_t * vLines; + int i, pCounts[GLS_FINAL]; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot read file \"%s\".\n", pFileName ); + return NULL; + } + vLines = Gls_ManCount( pFile, pCounts ); + rewind( pFile ); + // statistics + for ( i = 0; i < GLS_FINAL; i++ ) + if ( pCounts[i] ) + printf( "%s=%d ", s_Strs[i], pCounts[i] ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + // collect data and derive AIG + p = Gls_ManAlloc( vLines, pCounts ); + if ( Gls_ManParse( pFile, p ) ) + pGia = Gls_ManConstruct( p, pFileName ); + Gls_ManStop( p ); + fclose( pFile ); + //printf( "\n" ); + return pGia; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaGlitch.c b/yosys/abc/src/aig/gia/giaGlitch.c new file mode 100644 index 00000000000..8c0cc1613c4 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaGlitch.c @@ -0,0 +1,786 @@ +/**CFile**************************************************************** + + FileName [giaGlitch.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Glitch simulation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaGlitch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Gli_Obj_t_ Gli_Obj_t; +struct Gli_Obj_t_ +{ + unsigned fTerm : 1; // terminal node + unsigned fPhase : 1; // value under 000 pattern + unsigned fPhase2 : 1; // value under 000 pattern + unsigned fMark : 1; // user-controlled mark + unsigned nFanins : 3; // the number of fanins + unsigned nFanouts : 25; // total number of fanouts + unsigned Handle; // ID of the node + word * pTruth; // truth table of the node + unsigned uSimInfo; // simulation info of the node + union + { + int iFanin; // the number of fanins added + int nSwitches; // the number of switches + }; + union + { + int iFanout; // the number of fanouts added + int nGlitches; // the number of glitches ( nGlitches >= nSwitches ) + }; + int Fanios[0]; // the array of fanins/fanouts +}; + +typedef struct Gli_Man_t_ Gli_Man_t; +struct Gli_Man_t_ +{ + Vec_Int_t * vCis; // the vector of CIs (PIs + LOs) + Vec_Int_t * vCos; // the vector of COs (POs + LIs) + Vec_Int_t * vCisChanged; // the changed CIs + Vec_Int_t * vAffected; // the affected nodes + Vec_Int_t * vFrontier; // the fanouts of these nodes + int nObjs; // the number of objects + int nRegs; // the number of registers + int nTravIds; // traversal ID of the network + int iObjData; // pointer to the current data + int nObjData; // the size of array to store the logic network + int * pObjData; // the internal nodes + unsigned * pSimInfoPrev; // previous values of the CIs +}; + + +static inline int Gli_ManCiNum( Gli_Man_t * p ) { return Vec_IntSize(p->vCis); } +static inline int Gli_ManCoNum( Gli_Man_t * p ) { return Vec_IntSize(p->vCos); } +static inline int Gli_ManPiNum( Gli_Man_t * p ) { return Vec_IntSize(p->vCis) - p->nRegs; } +static inline int Gli_ManPoNum( Gli_Man_t * p ) { return Vec_IntSize(p->vCos) - p->nRegs; } +static inline int Gli_ManRegNum( Gli_Man_t * p ) { return p->nRegs; } +static inline int Gli_ManObjNum( Gli_Man_t * p ) { return p->nObjs; } +static inline int Gli_ManNodeNum( Gli_Man_t * p ) { return p->nObjs - Vec_IntSize(p->vCis) - Vec_IntSize(p->vCos); } + +static inline Gli_Obj_t * Gli_ManObj( Gli_Man_t * p, int v ) { return (Gli_Obj_t *)(p->pObjData + v); } +static inline Gli_Obj_t * Gli_ManCi( Gli_Man_t * p, int v ) { return Gli_ManObj( p, Vec_IntEntry(p->vCis,v) ); } +static inline Gli_Obj_t * Gli_ManCo( Gli_Man_t * p, int v ) { return Gli_ManObj( p, Vec_IntEntry(p->vCos,v) ); } +static inline Gli_Obj_t * Gli_ManPi( Gli_Man_t * p, int v ) { assert( v < Gli_ManPiNum(p) ); return Gli_ManCi( p, v ); } +static inline Gli_Obj_t * Gli_ManPo( Gli_Man_t * p, int v ) { assert( v < Gli_ManPoNum(p) ); return Gli_ManCo( p, v ); } +static inline Gli_Obj_t * Gli_ManRo( Gli_Man_t * p, int v ) { assert( v < Gli_ManRegNum(p) ); return Gli_ManCi( p, Gli_ManRegNum(p)+v ); } +static inline Gli_Obj_t * Gli_ManRi( Gli_Man_t * p, int v ) { assert( v < Gli_ManRegNum(p) ); return Gli_ManCo( p, Gli_ManRegNum(p)+v ); } + +static inline int Gli_ObjIsTerm( Gli_Obj_t * pObj ) { return pObj->fTerm; } +static inline int Gli_ObjIsCi( Gli_Obj_t * pObj ) { return pObj->fTerm && pObj->nFanins == 0; } +static inline int Gli_ObjIsCo( Gli_Obj_t * pObj ) { return pObj->fTerm && pObj->nFanins == 1; } +static inline int Gli_ObjIsNode( Gli_Obj_t * pObj ) { return!pObj->fTerm; } + +static inline int Gli_ObjFaninNum( Gli_Obj_t * pObj ) { return pObj->nFanins; } +static inline int Gli_ObjFanoutNum( Gli_Obj_t * pObj ) { return pObj->nFanouts; } +static inline int Gli_ObjSize( Gli_Obj_t * pObj ) { return sizeof(Gli_Obj_t) / 4 + pObj->nFanins + pObj->nFanouts; } + +static inline Gli_Obj_t * Gli_ObjFanin( Gli_Obj_t * pObj, int i ) { return (Gli_Obj_t *)(((int *)pObj) - pObj->Fanios[i]); } +static inline Gli_Obj_t * Gli_ObjFanout( Gli_Obj_t * pObj, int i ) { return (Gli_Obj_t *)(((int *)pObj) + pObj->Fanios[pObj->nFanins+i]); } + +#define Gli_ManForEachObj( p, pObj, i ) \ + for ( i = 0; (i < p->nObjData) && (pObj = Gli_ManObj(p,i)); i += Gli_ObjSize(pObj) ) +#define Gli_ManForEachNode( p, pObj, i ) \ + for ( i = 0; (i < p->nObjData) && (pObj = Gli_ManObj(p,i)); i += Gli_ObjSize(pObj) ) if ( Gli_ObjIsTerm(pObj) ) {} else + +#define Gli_ManForEachEntry( vVec, p, pObj, i ) \ + for ( i = 0; (i < Vec_IntSize(vVec)) && (pObj = Gli_ManObj(p,Vec_IntEntry(vVec,i))); i++ ) +#define Gli_ManForEachCi( p, pObj, i ) \ + for ( i = 0; (i < Vec_IntSize(p->vCis)) && (pObj = Gli_ManObj(p,Vec_IntEntry(p->vCis,i))); i++ ) +#define Gli_ManForEachCo( p, pObj, i ) \ + for ( i = 0; (i < Vec_IntSize(p->vCos)) && (pObj = Gli_ManObj(p,Vec_IntEntry(p->vCos,i))); i++ ) + +#define Gli_ManForEachPi( p, pObj, i ) \ + for ( i = 0; (i < Gli_ManPiNum(p)) && ((pObj) = Gli_ManCi(p, i)); i++ ) +#define Gli_ManForEachPo( p, pObj, i ) \ + for ( i = 0; (i < Gli_ManPoNum(p)) && ((pObj) = Gli_ManCo(p, i)); i++ ) +#define Gli_ManForEachRo( p, pObj, i ) \ + for ( i = 0; (i < Gli_ManRegNum(p)) && ((pObj) = Gli_ManCi(p, Gli_ManPiNum(p)+i)); i++ ) +#define Gli_ManForEachRi( p, pObj, i ) \ + for ( i = 0; (i < Gli_ManRegNum(p)) && ((pObj) = Gli_ManCo(p, Gli_ManPoNum(p)+i)); i++ ) +#define Gli_ManForEachRiRo( p, pObjRi, pObjRo, i ) \ + for ( i = 0; (i < Gli_ManRegNum(p)) && ((pObjRi) = Gli_ManCo(p, Gli_ManPoNum(p)+i)) && ((pObjRo) = Gli_ManCi(p, Gli_ManPiNum(p)+i)); i++ ) + +#define Gli_ObjForEachFanin( pObj, pNext, i ) \ + for ( i = 0; (i < (int)pObj->nFanins) && (pNext = Gli_ObjFanin(pObj,i)); i++ ) +#define Gli_ObjForEachFanout( pObj, pNext, i ) \ + for ( i = 0; (i < (int)pObj->nFanouts) && (pNext = Gli_ObjFanout(pObj,i)); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates logic network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gli_Man_t * Gli_ManAlloc( int nObjs, int nRegs, int nFanioPairs ) +{ + Gli_Man_t * p; + p = (Gli_Man_t *)ABC_CALLOC( int, (sizeof(Gli_Man_t) / 4) + (sizeof(Gli_Obj_t) / 4) * nObjs + 2 * nFanioPairs ); + p->nRegs = nRegs; + p->vCis = Vec_IntAlloc( 1000 ); + p->vCos = Vec_IntAlloc( 1000 ); + p->vCisChanged = Vec_IntAlloc( 1000 ); + p->vAffected = Vec_IntAlloc( 1000 ); + p->vFrontier = Vec_IntAlloc( 1000 ); + p->nObjData = (sizeof(Gli_Obj_t) / 4) * nObjs + 2 * nFanioPairs; + p->pObjData = (int *)(p + 1); + return p; +} + +/**Function************************************************************* + + Synopsis [Deletes logic network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gli_ManStop( Gli_Man_t * p ) +{ + Vec_IntFree( p->vCis ); + Vec_IntFree( p->vCos ); + Vec_IntFree( p->vCisChanged ); + Vec_IntFree( p->vAffected ); + Vec_IntFree( p->vFrontier ); + ABC_FREE( p->pSimInfoPrev ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Checks logic network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gli_ManPrintObjects( Gli_Man_t * p ) +{ + Gli_Obj_t * pObj, * pNext; + int i, k; + Gli_ManForEachObj( p, pObj, i ) + { + printf( "Node %d \n", pObj->Handle ); + printf( "Fanins: " ); + Gli_ObjForEachFanin( pObj, pNext, k ) + printf( "%d ", pNext->Handle ); + printf( "\n" ); + printf( "Fanouts: " ); + Gli_ObjForEachFanout( pObj, pNext, k ) + printf( "%d ", pNext->Handle ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Checks logic network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gli_ManFinalize( Gli_Man_t * p ) +{ + Gli_Obj_t * pObj; + int i; + assert( p->iObjData == p->nObjData ); + Gli_ManForEachObj( p, pObj, i ) + { + assert( pObj->iFanin == (int)pObj->nFanins ); + assert( pObj->iFanout == (int)pObj->nFanouts ); + pObj->iFanin = 0; + pObj->iFanout = 0; + } +} + +/**Function************************************************************* + + Synopsis [Creates fanin/fanout pair.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gli_ObjAddFanin( Gli_Obj_t * pObj, Gli_Obj_t * pFanin ) +{ + assert( pObj->iFanin < (int)pObj->nFanins ); + assert( pFanin->iFanout < (int)pFanin->nFanouts ); + pFanin->Fanios[pFanin->nFanins + pFanin->iFanout++] = + pObj->Fanios[pObj->iFanin++] = pObj->Handle - pFanin->Handle; +} + +/**Function************************************************************* + + Synopsis [Allocates object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gli_Obj_t * Gli_ObjAlloc( Gli_Man_t * p, int nFanins, int nFanouts ) +{ + Gli_Obj_t * pObj; + pObj = Gli_ManObj( p, p->iObjData ); + pObj->Handle = p->iObjData; + pObj->nFanins = nFanins; + pObj->nFanouts = nFanouts; + p->iObjData += Gli_ObjSize( pObj ); + p->nObjs++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Creates CI.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gli_ManCreateCi( Gli_Man_t * p, int nFanouts ) +{ + Gli_Obj_t * pObj; + pObj = Gli_ObjAlloc( p, 0, nFanouts ); + pObj->fTerm = 1; + Vec_IntPush( p->vCis, pObj->Handle ); + return pObj->Handle; +} + +/**Function************************************************************* + + Synopsis [Creates CO.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gli_ManCreateCo( Gli_Man_t * p, int iFanin ) +{ + Gli_Obj_t * pObj, * pFanin; + pObj = Gli_ObjAlloc( p, 1, 0 ); + pObj->fTerm = 1; + pFanin = Gli_ManObj( p, iFanin ); + Gli_ObjAddFanin( pObj, pFanin ); + pObj->fPhase = pObj->fPhase2 = pFanin->fPhase; + Vec_IntPush( p->vCos, pObj->Handle ); + return pObj->Handle; +} + +/**Function************************************************************* + + Synopsis [Creates node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gli_NodeComputeValue( Gli_Obj_t * pNode ) +{ + int i, Phase = 0; + for ( i = 0; i < (int)pNode->nFanins; i++ ) + Phase |= (Gli_ObjFanin(pNode, i)->fPhase << i); + return Abc_InfoHasBit( (unsigned *)pNode->pTruth, Phase ); +} + +/**Function************************************************************* + + Synopsis [Creates node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gli_NodeComputeValue2( Gli_Obj_t * pNode ) +{ + int i, Phase = 0; + for ( i = 0; i < (int)pNode->nFanins; i++ ) + Phase |= (Gli_ObjFanin(pNode, i)->fPhase2 << i); + return Abc_InfoHasBit( (unsigned *)pNode->pTruth, Phase ); +} + +/**Function************************************************************* + + Synopsis [Creates node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gli_ManCreateNode( Gli_Man_t * p, Vec_Int_t * vFanins, int nFanouts, word * pGateTruth ) +{ + Gli_Obj_t * pObj, * pFanin; + int i; + assert( Vec_IntSize(vFanins) <= 16 ); + pObj = Gli_ObjAlloc( p, Vec_IntSize(vFanins), nFanouts ); + Gli_ManForEachEntry( vFanins, p, pFanin, i ) + Gli_ObjAddFanin( pObj, pFanin ); + pObj->pTruth = pGateTruth; + pObj->fPhase = pObj->fPhase2 = Gli_NodeComputeValue( pObj ); + return pObj->Handle; +} + +/**Function************************************************************* + + Synopsis [Returns the number of switches of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gli_ObjNumSwitches( Gli_Man_t * p, int iNode ) +{ + return Gli_ManObj( p, iNode )->nSwitches; +} + +/**Function************************************************************* + + Synopsis [Returns the number of glitches of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gli_ObjNumGlitches( Gli_Man_t * p, int iNode ) +{ + return Gli_ManObj( p, iNode )->nGlitches; +} + + +/**Function************************************************************* + + Synopsis [Sets random info at the PIs and collects changed PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gli_ManSetPiRandom( Gli_Man_t * p, float PiTransProb ) +{ + Gli_Obj_t * pObj; + float Multi = 1.0 / (1 << 16); + int i; + assert( 0.0 < PiTransProb && PiTransProb < 1.0 ); + Vec_IntClear( p->vCisChanged ); + Gli_ManForEachCi( p, pObj, i ) + if ( Multi * (Gia_ManRandom(0) & 0xffff) < PiTransProb ) + { + Vec_IntPush( p->vCisChanged, pObj->Handle ); + pObj->fPhase ^= 1; + pObj->fPhase2 ^= 1; + pObj->nSwitches++; + pObj->nGlitches++; + } +} + +/**Function************************************************************* + + Synopsis [Sets random info at the PIs and collects changed PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gli_ManSetPiFromSaved( Gli_Man_t * p, int iBit ) +{ + Gli_Obj_t * pObj; + int i; + Vec_IntClear( p->vCisChanged ); + Gli_ManForEachCi( p, pObj, i ) + if ( (p->pSimInfoPrev[i] ^ pObj->uSimInfo) & (1 << iBit) ) + { + Vec_IntPush( p->vCisChanged, pObj->Handle ); + pObj->fPhase ^= 1; + pObj->fPhase2 ^= 1; + pObj->nSwitches++; + pObj->nGlitches++; + } +} + +/**Function************************************************************* + + Synopsis [Computes switching activity of each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gli_ManSwitching( Gli_Man_t * p ) +{ + Gli_Obj_t * pThis; + int i; + Gli_ManForEachNode( p, pThis, i ) + { + if ( ((int)pThis->fPhase) == Gli_NodeComputeValue(pThis) ) + continue; + pThis->fPhase ^= 1; + pThis->nSwitches++; + } +} + +/**Function************************************************************* + + Synopsis [Computes glitching activity of each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gli_ManGlitching( Gli_Man_t * p ) +{ + Gli_Obj_t * pThis, * pFanout;//, * pOther = Gli_ManObj(p, 41); + int i, k, Handle; +// Gli_ManForEachObj( p, pThis, i ) +// assert( pThis->fMark == 0 ); + // start the array of affected nodes + Vec_IntClear( p->vAffected ); + Vec_IntForEachEntry( p->vCisChanged, Handle, i ) + Vec_IntPush( p->vAffected, Handle ); + // iteration propagation + while ( Vec_IntSize(p->vAffected) > 0 ) + { + // compute the frontier + Vec_IntClear( p->vFrontier ); + Gli_ManForEachEntry( p->vAffected, p, pThis, i ) + { + Gli_ObjForEachFanout( pThis, pFanout, k ) + { + if ( Gli_ObjIsCo(pFanout) ) + continue; + if ( pFanout->fMark ) + continue; + pFanout->fMark = 1; + Vec_IntPush( p->vFrontier, pFanout->Handle ); + } + } + // compute the next set of affected nodes + Vec_IntClear( p->vAffected ); + Gli_ManForEachEntry( p->vFrontier, p, pThis, i ) + { + pThis->fMark = 0; + if ( ((int)pThis->fPhase2) == Gli_NodeComputeValue2(pThis) ) + continue; + pThis->fPhase2 ^= 1; + pThis->nGlitches++; + Vec_IntPush( p->vAffected, pThis->Handle ); + } + } +} + +/**Function************************************************************* + + Synopsis [Checks that the resulting values are the same.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gli_ManVerify( Gli_Man_t * p ) +{ + Gli_Obj_t * pObj; + int i; + Gli_ManForEachObj( p, pObj, i ) + { + assert( pObj->fPhase == pObj->fPhase2 ); + assert( pObj->nGlitches >= pObj->nSwitches ); + } +} + +/**Function************************************************************* + + Synopsis [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Gli_ManSimulateSeqNode( Gli_Man_t * p, Gli_Obj_t * pNode ) +{ + unsigned pSimInfos[6], Result = 0; + int nFanins = Gli_ObjFaninNum(pNode); + int i, k, Phase; + Gli_Obj_t * pFanin; + assert( nFanins <= 16 ); + Gli_ObjForEachFanin( pNode, pFanin, i ) + pSimInfos[i] = pFanin->uSimInfo; + for ( i = 0; i < 32; i++ ) + { + Phase = 0; + for ( k = 0; k < nFanins; k++ ) + if ( (pSimInfos[k] >> i) & 1 ) + Phase |= (1 << k); + if ( Abc_InfoHasBit( (unsigned *)pNode->pTruth, Phase ) ) + Result |= (1 << i); + } + return Result; +} + +/**Function************************************************************* + + Synopsis [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Gli_ManUpdateRandomInput( unsigned uInfo, float PiTransProb ) +{ + float Multi = 1.0 / (1 << 16); + int i; + if ( PiTransProb == 0.5 ) + return Gia_ManRandom(0); + for ( i = 0; i < 32; i++ ) + if ( Multi * (Gia_ManRandom(0) & 0xffff) < PiTransProb ) + uInfo ^= (1 << i); + return uInfo; +} + +/**Function************************************************************* + + Synopsis [Simulates sequential network randomly for the given number of frames.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gli_ManSimulateSeqPref( Gli_Man_t * p, int nPref ) +{ + Gli_Obj_t * pObj, * pObjRi, * pObjRo; + int i, f; + // initialize simulation data + Gli_ManForEachPi( p, pObj, i ) + pObj->uSimInfo = Gli_ManUpdateRandomInput( pObj->uSimInfo, 0.5 ); + Gli_ManForEachRo( p, pObj, i ) + pObj->uSimInfo = 0; + for ( f = 0; f < nPref; f++ ) + { + // simulate one frame + Gli_ManForEachNode( p, pObj, i ) + pObj->uSimInfo = Gli_ManSimulateSeqNode( p, pObj ); + Gli_ManForEachRi( p, pObj, i ) + pObj->uSimInfo = Gli_ObjFanin(pObj, 0)->uSimInfo; + // initialize the next frame + Gli_ManForEachPi( p, pObj, i ) + pObj->uSimInfo = Gli_ManUpdateRandomInput( pObj->uSimInfo, 0.5 ); + Gli_ManForEachRiRo( p, pObjRi, pObjRo, i ) + pObjRo->uSimInfo = pObjRi->uSimInfo; + } + // save simulation data after nPref timeframes + if ( p->pSimInfoPrev == NULL ) + p->pSimInfoPrev = ABC_ALLOC( unsigned, Gli_ManCiNum(p) ); + Gli_ManForEachCi( p, pObj, i ) + p->pSimInfoPrev[i] = pObj->uSimInfo; +} + +/**Function************************************************************* + + Synopsis [Initialized object values to be one pattern in the saved data.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gli_ManSetDataSaved( Gli_Man_t * p, int iBit ) +{ + Gli_Obj_t * pObj; + int i; + Gli_ManForEachCi( p, pObj, i ) + pObj->fPhase = pObj->fPhase2 = ((p->pSimInfoPrev[i] >> iBit) & 1); + Gli_ManForEachNode( p, pObj, i ) + pObj->fPhase = pObj->fPhase2 = Gli_NodeComputeValue( pObj ); +} + +/**Function************************************************************* + + Synopsis [Sets random info at the PIs and collects changed PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gli_ManSetPiRandomSeq( Gli_Man_t * p, float PiTransProb ) +{ + Gli_Obj_t * pObj, * pObjRi; + float Multi = 1.0 / (1 << 16); + int i; + assert( 0.0 < PiTransProb && PiTransProb < 1.0 ); + // transfer data to the COs + Gli_ManForEachCo( p, pObj, i ) + pObj->fPhase = pObj->fPhase2 = Gli_ObjFanin(pObj, 0)->fPhase; + // set changed PIs + Vec_IntClear( p->vCisChanged ); + Gli_ManForEachPi( p, pObj, i ) + if ( Multi * (Gia_ManRandom(0) & 0xffff) < PiTransProb ) + { + Vec_IntPush( p->vCisChanged, pObj->Handle ); + pObj->fPhase ^= 1; + pObj->fPhase2 ^= 1; + pObj->nSwitches++; + pObj->nGlitches++; + } + // set changed ROs + Gli_ManForEachRiRo( p, pObjRi, pObj, i ) + if ( pObjRi->fPhase != pObj->fPhase ) + { + Vec_IntPush( p->vCisChanged, pObj->Handle ); + pObj->fPhase ^= 1; + pObj->fPhase2 ^= 1; + pObj->nSwitches++; + pObj->nGlitches++; + } + +} + +/**Function************************************************************* + + Synopsis [Computes glitching activity of each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gli_ManSwitchesAndGlitches( Gli_Man_t * p, int nPatterns, float PiTransProb, int fVerbose ) +{ + int i, k; + abctime clk = Abc_Clock(); + Gia_ManRandom( 1 ); + Gli_ManFinalize( p ); + if ( p->nRegs == 0 ) + { + for ( i = 0; i < nPatterns; i++ ) + { + Gli_ManSetPiRandom( p, PiTransProb ); + Gli_ManSwitching( p ); + Gli_ManGlitching( p ); +// Gli_ManVerify( p ); + } + } + else + { + int nIters = Abc_BitWordNum(nPatterns); + Gli_ManSimulateSeqPref( p, 16 ); + for ( i = 0; i < 32; i++ ) + { + Gli_ManSetDataSaved( p, i ); + for ( k = 0; k < nIters; k++ ) + { + Gli_ManSetPiRandomSeq( p, PiTransProb ); + Gli_ManSwitching( p ); + Gli_ManGlitching( p ); +// Gli_ManVerify( p ); + } + } + } + if ( fVerbose ) + { + printf( "Simulated %d patterns. Input transition probability %.2f. ", nPatterns, PiTransProb ); + ABC_PRMn( "Memory", 4*p->nObjData ); + ABC_PRT( "Time", Abc_Clock() - clk ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaHash.c b/yosys/abc/src/aig/gia/giaHash.c new file mode 100644 index 00000000000..063cfd31ab1 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaHash.c @@ -0,0 +1,1145 @@ +/**CFile**************************************************************** + + FileName [giaHash.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Structural hashing.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaHash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the place where this node is stored (or should be stored).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManHashOne( int iLit0, int iLit1, int iLitC, int TableSize ) +{ + unsigned Key = iLitC * 2011; + Key += Abc_Lit2Var(iLit0) * 7937; + Key += Abc_Lit2Var(iLit1) * 2971; + Key += Abc_LitIsCompl(iLit0) * 911; + Key += Abc_LitIsCompl(iLit1) * 353; + return (int)(Key % TableSize); +} +static inline int * Gia_ManHashFind( Gia_Man_t * p, int iLit0, int iLit1, int iLitC ) +{ + int iThis, * pPlace = Vec_IntEntryP( &p->vHTable, Gia_ManHashOne( iLit0, iLit1, iLitC, Vec_IntSize(&p->vHTable) ) ); + assert( Vec_IntSize(&p->vHash) == Gia_ManObjNum(p) ); + assert( p->pMuxes || iLit0 < iLit1 ); + assert( iLit0 < iLit1 || (!Abc_LitIsCompl(iLit0) && !Abc_LitIsCompl(iLit1)) ); + assert( iLitC == -1 || !Abc_LitIsCompl(iLit1) ); + for ( ; (iThis = *pPlace); pPlace = Vec_IntEntryP(&p->vHash, iThis) ) + { + Gia_Obj_t * pThis = Gia_ManObj( p, iThis ); + if ( Gia_ObjFaninLit0(pThis, iThis) == iLit0 && Gia_ObjFaninLit1(pThis, iThis) == iLit1 && (p->pMuxes == NULL || Gia_ObjFaninLit2p(p, pThis) == iLitC) ) + break; + } + return pPlace; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManHashLookupInt( Gia_Man_t * p, int iLit0, int iLit1 ) +{ + if ( iLit0 > iLit1 ) + iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1; + return Abc_Var2Lit( *Gia_ManHashFind( p, iLit0, iLit1, -1 ), 0 ); +} +int Gia_ManHashLookup( Gia_Man_t * p, Gia_Obj_t * p0, Gia_Obj_t * p1 ) +{ + int iLit0 = Gia_ObjToLit( p, p0 ); + int iLit1 = Gia_ObjToLit( p, p1 ); + return Gia_ManHashLookupInt( p, iLit0, iLit1 ); +} + +/**Function************************************************************* + + Synopsis [Starts the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManHashAlloc( Gia_Man_t * p ) +{ + assert( Vec_IntSize(&p->vHTable) == 0 ); + Vec_IntFill( &p->vHTable, Abc_PrimeCudd( Gia_ManAndNum(p) ? Gia_ManAndNum(p) + 1000 : p->nObjsAlloc ), 0 ); + Vec_IntGrow( &p->vHash, Abc_MaxInt(Vec_IntSize(&p->vHTable), Gia_ManObjNum(p)) ); + Vec_IntFill( &p->vHash, Gia_ManObjNum(p), 0 ); +//printf( "Alloced table with %d entries.\n", Vec_IntSize(&p->vHTable) ); +} + +/**Function************************************************************* + + Synopsis [Starts the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManHashStart( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int * pPlace, i; + Gia_ManHashAlloc( p ); + Gia_ManForEachAnd( p, pObj, i ) + { + pPlace = Gia_ManHashFind( p, Gia_ObjFaninLit0(pObj, i), Gia_ObjFaninLit1(pObj, i), Gia_ObjFaninLit2(p, i) ); + assert( *pPlace == 0 ); + *pPlace = i; + } +} + +/**Function************************************************************* + + Synopsis [Stops the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManHashStop( Gia_Man_t * p ) +{ + Vec_IntErase( &p->vHTable ); + Vec_IntErase( &p->vHash ); +} + +/**Function************************************************************* + + Synopsis [Resizes the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManHashResize( Gia_Man_t * p ) +{ + int i, iThis, iNext, Counter, Counter2, * pPlace; + Vec_Int_t vOld = p->vHTable; + assert( Vec_IntSize(&vOld) > 0 ); + // replace the table + Vec_IntZero( &p->vHTable ); + Vec_IntFill( &p->vHTable, Abc_PrimeCudd( 2 * Gia_ManAndNum(p) ), 0 ); + // rehash the entries from the old table + Counter = 0; + Vec_IntForEachEntry( &vOld, iThis, i ) + for ( iNext = Vec_IntEntry(&p->vHash, iThis); + iThis; iThis = iNext, + iNext = Vec_IntEntry(&p->vHash, iThis) ) + { + Gia_Obj_t * pThis0 = Gia_ManObj( p, iThis ); + Vec_IntWriteEntry( &p->vHash, iThis, 0 ); + pPlace = Gia_ManHashFind( p, Gia_ObjFaninLit0(pThis0, iThis), Gia_ObjFaninLit1(pThis0, iThis), Gia_ObjFaninLit2p(p, pThis0) ); + assert( *pPlace == 0 ); // should not be there + *pPlace = iThis; + assert( *pPlace != 0 ); + Counter++; + } + Counter2 = Gia_ManAndNum(p) - Gia_ManBufNum(p); + assert( Counter == Counter2 ); +// if ( p->fVerbose ) +// printf( "Resizing GIA hash table: %d -> %d.\n", Vec_IntSize(&vOld), Vec_IntSize(&p->vHTable) ); + Vec_IntErase( &vOld ); +} + +/**Function******************************************************************** + + Synopsis [Profiles the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Gia_ManHashProfile( Gia_Man_t * p ) +{ + int iEntry; + int i, Counter, Limit; + printf( "Table size = %d. Entries = %d. ", Vec_IntSize(&p->vHTable), Gia_ManAndNum(p) ); + printf( "Hits = %d. Misses = %d.\n", (int)p->nHashHit, (int)p->nHashMiss ); + Limit = Abc_MinInt( 1000, Vec_IntSize(&p->vHTable) ); + for ( i = 0; i < Limit; i++ ) + { + Counter = 0; + for ( iEntry = Vec_IntEntry(&p->vHTable, i); + iEntry; + iEntry = iEntry? Vec_IntEntry(&p->vHash, iEntry) : 0 ) + Counter++; + if ( Counter ) + printf( "%d ", Counter ); + } + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Recognizes what nodes are control and data inputs of a MUX.] + + Description [If the node is a MUX, returns the control variable C. + Assigns nodes T and E to be the then and else variables of the MUX. + Node C is never complemented. Nodes T and E can be complemented. + This function also recognizes EXOR/NEXOR gates as MUXes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * Gia_ObjRecognizeMuxTwo( Gia_Obj_t * pNode0, Gia_Obj_t * pNode1, Gia_Obj_t ** ppNodeT, Gia_Obj_t ** ppNodeE ) +{ + assert( !Gia_IsComplement(pNode0) ); + assert( !Gia_IsComplement(pNode1) ); + // find the control variable + if ( Gia_ObjFanin1(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC1(pNode1)) ) + { +// if ( FrGia_IsComplement(pNode1->p2) ) + if ( Gia_ObjFaninC1(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1); + return Gia_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1); + return Gia_ObjChild1(pNode0);//pNode1->p2; + } + } + else if ( Gia_ObjFanin0(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC0(pNode1)) ) + { +// if ( FrGia_IsComplement(pNode1->p1) ) + if ( Gia_ObjFaninC0(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2); + return Gia_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2); + return Gia_ObjChild0(pNode0);//pNode1->p1; + } + } + else if ( Gia_ObjFanin0(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC1(pNode1)) ) + { +// if ( FrGia_IsComplement(pNode1->p1) ) + if ( Gia_ObjFaninC0(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2); + return Gia_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1); + return Gia_ObjChild0(pNode0);//pNode1->p1; + } + } + else if ( Gia_ObjFanin1(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC0(pNode1)) ) + { +// if ( FrGia_IsComplement(pNode1->p2) ) + if ( Gia_ObjFaninC1(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1); + return Gia_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2); + return Gia_ObjChild1(pNode0);//pNode1->p2; + } + } + assert( 0 ); // this is not MUX + return NULL; +} + + +/**Function************************************************************* + + Synopsis [Rehashes AIG with mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * Gia_ManHashAndP( Gia_Man_t * p, Gia_Obj_t * p0, Gia_Obj_t * p1 ) +{ + return Gia_ObjFromLit( p, Gia_ManHashAnd( p, Gia_ObjToLit(p, p0), Gia_ObjToLit(p, p1) ) ); +} + +/**Function************************************************************* + + Synopsis [Rehashes AIG with mapping.] + + Description [http://fmv.jku.at/papers/BrummayerBiere-MEMICS06.pdf] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Gia_Obj_t * Gia_ManAddStrash( Gia_Man_t * p, Gia_Obj_t * p0, Gia_Obj_t * p1 ) +{ + Gia_Obj_t * pNode0, * pNode1, * pFanA, * pFanB, * pFanC, * pFanD; + assert( p->fAddStrash ); + pNode0 = Gia_Regular(p0); + pNode1 = Gia_Regular(p1); + if ( !Gia_ObjIsAnd(pNode0) && !Gia_ObjIsAnd(pNode1) ) + return NULL; + pFanA = Gia_ObjIsAnd(pNode0) ? Gia_ObjChild0(pNode0) : NULL; + pFanB = Gia_ObjIsAnd(pNode0) ? Gia_ObjChild1(pNode0) : NULL; + pFanC = Gia_ObjIsAnd(pNode1) ? Gia_ObjChild0(pNode1) : NULL; + pFanD = Gia_ObjIsAnd(pNode1) ? Gia_ObjChild1(pNode1) : NULL; + if ( Gia_IsComplement(p0) ) + { + if ( pFanA == Gia_Not(p1) || pFanB == Gia_Not(p1) ) + return p1; + if ( pFanB == p1 ) + return Gia_ManHashAndP( p, Gia_Not(pFanA), pFanB ); + if ( pFanA == p1 ) + return Gia_ManHashAndP( p, Gia_Not(pFanB), pFanA ); + } + else + { + if ( pFanA == Gia_Not(p1) || pFanB == Gia_Not(p1) ) + return Gia_ManConst0(p); + if ( pFanA == p1 || pFanB == p1 ) + return p0; + } + if ( Gia_IsComplement(p1) ) + { + if ( pFanC == Gia_Not(p0) || pFanD == Gia_Not(p0) ) + return p0; + if ( pFanD == p0 ) + return Gia_ManHashAndP( p, Gia_Not(pFanC), pFanD ); + if ( pFanC == p0 ) + return Gia_ManHashAndP( p, Gia_Not(pFanD), pFanC ); + } + else + { + if ( pFanC == Gia_Not(p0) || pFanD == Gia_Not(p0) ) + return Gia_ManConst0(p); + if ( pFanC == p0 || pFanD == p0 ) + return p1; + } + if ( !Gia_IsComplement(p0) && !Gia_IsComplement(p1) ) + { + if ( pFanA == Gia_Not(pFanC) || pFanA == Gia_Not(pFanD) || pFanB == Gia_Not(pFanC) || pFanB == Gia_Not(pFanD) ) + return Gia_ManConst0(p); + if ( pFanA == pFanC || pFanB == pFanC ) + return Gia_ManHashAndP( p, p0, pFanD ); + if ( pFanB == pFanC || pFanB == pFanD ) + return Gia_ManHashAndP( p, pFanA, p1 ); + if ( pFanA == pFanD || pFanB == pFanD ) + return Gia_ManHashAndP( p, p0, pFanC ); + if ( pFanA == pFanC || pFanA == pFanD ) + return Gia_ManHashAndP( p, pFanB, p1 ); + } + else if ( Gia_IsComplement(p0) && !Gia_IsComplement(p1) ) + { + if ( pFanA == Gia_Not(pFanC) || pFanA == Gia_Not(pFanD) || pFanB == Gia_Not(pFanC) || pFanB == Gia_Not(pFanD) ) + return p1; + if ( pFanB == pFanC || pFanB == pFanD ) + return Gia_ManHashAndP( p, Gia_Not(pFanA), p1 ); + if ( pFanA == pFanC || pFanA == pFanD ) + return Gia_ManHashAndP( p, Gia_Not(pFanB), p1 ); + } + else if ( !Gia_IsComplement(p0) && Gia_IsComplement(p1) ) + { + if ( pFanC == Gia_Not(pFanA) || pFanC == Gia_Not(pFanB) || pFanD == Gia_Not(pFanA) || pFanD == Gia_Not(pFanB) ) + return p0; + if ( pFanD == pFanA || pFanD == pFanB ) + return Gia_ManHashAndP( p, Gia_Not(pFanC), p0 ); + if ( pFanC == pFanA || pFanC == pFanB ) + return Gia_ManHashAndP( p, Gia_Not(pFanD), p0 ); + } + else // if ( Gia_IsComplement(p0) && Gia_IsComplement(p1) ) + { + if ( pFanA == pFanD && pFanB == Gia_Not(pFanC) ) + return Gia_Not(pFanA); + if ( pFanB == pFanC && pFanA == Gia_Not(pFanD) ) + return Gia_Not(pFanB); + if ( pFanA == pFanC && pFanB == Gia_Not(pFanD) ) + return Gia_Not(pFanA); + if ( pFanB == pFanD && pFanA == Gia_Not(pFanC) ) + return Gia_Not(pFanB); + } +/* + if ( !Gia_IsComplement(p0) || !Gia_IsComplement(p1) ) + return NULL; + if ( !Gia_ObjIsAnd(pNode0) || !Gia_ObjIsAnd(pNode1) ) + return NULL; + if ( (Gia_ObjFanin0(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC0(pNode1))) || + (Gia_ObjFanin0(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC1(pNode1))) || + (Gia_ObjFanin1(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC0(pNode1))) || + (Gia_ObjFanin1(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC1(pNode1))) ) + { + Gia_Obj_t * pNodeC, * pNodeT, * pNodeE; + int fCompl; + pNodeC = Gia_ObjRecognizeMuxTwo( pNode0, pNode1, &pNodeT, &pNodeE ); + // using non-standard canonical rule for MUX (d0 is not compl; d1 may be compl) + if ( (fCompl = Gia_IsComplement(pNodeE)) ) + { + pNodeE = Gia_Not(pNodeE); + pNodeT = Gia_Not(pNodeT); + } + pNode0 = Gia_ManHashAndP( p, Gia_Not(pNodeC), pNodeE ); + pNode1 = Gia_ManHashAndP( p, pNodeC, pNodeT ); + p->fAddStrash = 0; + pNodeC = Gia_NotCond( Gia_ManHashAndP( p, Gia_Not(pNode0), Gia_Not(pNode1) ), !fCompl ); + p->fAddStrash = 1; + return pNodeC; + } +*/ + return NULL; +} + +/**Function************************************************************* + + Synopsis [Hashes XOR gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManHashXorReal( Gia_Man_t * p, int iLit0, int iLit1 ) +{ + int fCompl = 0; + assert( p->fAddStrash == 0 ); + if ( iLit0 < 2 ) + return iLit0 ? Abc_LitNot(iLit1) : iLit1; + if ( iLit1 < 2 ) + return iLit1 ? Abc_LitNot(iLit0) : iLit0; + if ( iLit0 == iLit1 ) + return 0; + if ( iLit0 == Abc_LitNot(iLit1) ) + return 1; + if ( (p->nObjs & 0xFF) == 0 && 2 * Vec_IntSize(&p->vHTable) < Gia_ManAndNum(p) ) + Gia_ManHashResize( p ); + if ( iLit0 < iLit1 ) + iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1; + if ( Abc_LitIsCompl(iLit0) ) + iLit0 = Abc_LitNot(iLit0), fCompl ^= 1; + if ( Abc_LitIsCompl(iLit1) ) + iLit1 = Abc_LitNot(iLit1), fCompl ^= 1; + { + int *pPlace = Gia_ManHashFind( p, iLit0, iLit1, -1 ); + if ( *pPlace ) + { + p->nHashHit++; + return Abc_Var2Lit( *pPlace, fCompl ); + } + p->nHashMiss++; + if ( Vec_IntSize(&p->vHash) < Vec_IntCap(&p->vHash) ) + *pPlace = Abc_Lit2Var( Gia_ManAppendXorReal( p, iLit0, iLit1 ) ); + else + { + int iNode = Gia_ManAppendXorReal( p, iLit0, iLit1 ); + pPlace = Gia_ManHashFind( p, iLit0, iLit1, -1 ); + assert( *pPlace == 0 ); + *pPlace = Abc_Lit2Var( iNode ); + } + return Abc_Var2Lit( *pPlace, fCompl ); + } +} + +/**Function************************************************************* + + Synopsis [Hashes MUX gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManHashMuxReal( Gia_Man_t * p, int iLitC, int iLit1, int iLit0 ) +{ + int fCompl = 0; + assert( p->fAddStrash == 0 ); + if ( iLitC < 2 ) + return iLitC ? iLit1 : iLit0; + if ( iLit0 < 2 ) + return iLit0 ? Gia_ManHashOr(p, Abc_LitNot(iLitC), iLit1) : Gia_ManHashAnd(p, iLitC, iLit1); + if ( iLit1 < 2 ) + return iLit1 ? Gia_ManHashOr(p, iLitC, iLit0) : Gia_ManHashAnd(p, Abc_LitNot(iLitC), iLit0); + assert( iLit0 > 1 && iLit1 > 1 && iLitC > 1 ); + if ( iLit0 == iLit1 ) + return iLit0; + if ( iLitC == iLit0 || iLitC == Abc_LitNot(iLit1) ) + return Gia_ManHashAnd(p, iLit0, iLit1); + if ( iLitC == iLit1 || iLitC == Abc_LitNot(iLit0) ) + return Gia_ManHashOr(p, iLit0, iLit1); + if ( Abc_Lit2Var(iLit0) == Abc_Lit2Var(iLit1) ) + return Gia_ManHashXorReal( p, iLitC, iLit0 ); + if ( iLit0 > iLit1 ) + iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1, iLitC = Abc_LitNot(iLitC); + if ( Abc_LitIsCompl(iLit1) ) + iLit0 = Abc_LitNot(iLit0), iLit1 = Abc_LitNot(iLit1), fCompl = 1; + { + int *pPlace = Gia_ManHashFind( p, iLit0, iLit1, iLitC ); + if ( *pPlace ) + { + p->nHashHit++; + return Abc_Var2Lit( *pPlace, fCompl ); + } + p->nHashMiss++; + if ( Vec_IntSize(&p->vHash) < Vec_IntCap(&p->vHash) ) + *pPlace = Abc_Lit2Var( Gia_ManAppendMuxReal( p, iLitC, iLit1, iLit0 ) ); + else + { + int iNode = Gia_ManAppendMuxReal( p, iLitC, iLit1, iLit0 ); + pPlace = Gia_ManHashFind( p, iLit0, iLit1, iLitC ); + assert( *pPlace == 0 ); + *pPlace = Abc_Lit2Var( iNode ); + } + return Abc_Var2Lit( *pPlace, fCompl ); + } +} + +/**Function************************************************************* + + Synopsis [Hashes AND gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManHashAnd( Gia_Man_t * p, int iLit0, int iLit1 ) +{ + if ( iLit0 < 2 ) + return iLit0 ? iLit1 : 0; + if ( iLit1 < 2 ) + return iLit1 ? iLit0 : 0; + if ( iLit0 == iLit1 ) + return iLit1; + if ( iLit0 == Abc_LitNot(iLit1) ) + return 0; + if ( p->fGiaSimple ) + { + assert( Vec_IntSize(&p->vHTable) == 0 ); + return Gia_ManAppendAnd( p, iLit0, iLit1 ); + } + if ( (p->nObjs & 0xFF) == 0 && 2 * Vec_IntSize(&p->vHTable) < Gia_ManAndNum(p) ) + Gia_ManHashResize( p ); + if ( p->fAddStrash ) + { + Gia_Obj_t * pObj = Gia_ManAddStrash( p, Gia_ObjFromLit(p, iLit0), Gia_ObjFromLit(p, iLit1) ); + if ( pObj != NULL ) + return Gia_ObjToLit( p, pObj ); + } + if ( iLit0 > iLit1 ) + iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1; + { + int * pPlace = Gia_ManHashFind( p, iLit0, iLit1, -1 ); + if ( *pPlace ) + { + p->nHashHit++; + return Abc_Var2Lit( *pPlace, 0 ); + } + p->nHashMiss++; + if ( Vec_IntSize(&p->vHash) < Vec_IntCap(&p->vHash) ) + *pPlace = Abc_Lit2Var( Gia_ManAppendAnd( p, iLit0, iLit1 ) ); + else + { + int iNode = Gia_ManAppendAnd( p, iLit0, iLit1 ); + pPlace = Gia_ManHashFind( p, iLit0, iLit1, -1 ); + assert( *pPlace == 0 ); + *pPlace = Abc_Lit2Var( iNode ); + } + return Abc_Var2Lit( *pPlace, 0 ); + } +} +int Gia_ManHashOr( Gia_Man_t * p, int iLit0, int iLit1 ) +{ + return Abc_LitNot(Gia_ManHashAnd( p, Abc_LitNot(iLit0), Abc_LitNot(iLit1) )); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManHashAndTry( Gia_Man_t * p, int iLit0, int iLit1 ) +{ + if ( iLit0 < 2 ) + return iLit0 ? iLit1 : 0; + if ( iLit1 < 2 ) + return iLit1 ? iLit0 : 0; + if ( iLit0 == iLit1 ) + return iLit1; + if ( iLit0 == Abc_LitNot(iLit1) ) + return 0; + if ( iLit0 > iLit1 ) + iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1; + { + int * pPlace = Gia_ManHashFind( p, iLit0, iLit1, -1 ); + if ( *pPlace ) + return Abc_Var2Lit( *pPlace, 0 ); + return -1; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManHashXor( Gia_Man_t * p, int iLit0, int iLit1 ) +{ + if ( p->fGiaSimple ) + return Gia_ManHashOr(p, Gia_ManHashAnd(p, iLit0, Abc_LitNot(iLit1)), Gia_ManHashAnd(p, Abc_LitNot(iLit0), iLit1) ); + else + { + int fCompl = Abc_LitIsCompl(iLit0) ^ Abc_LitIsCompl(iLit1); + int iTemp0 = Gia_ManHashAnd( p, Abc_LitRegular(iLit0), Abc_LitNot(Abc_LitRegular(iLit1)) ); + int iTemp1 = Gia_ManHashAnd( p, Abc_LitRegular(iLit1), Abc_LitNot(Abc_LitRegular(iLit0)) ); + return Abc_LitNotCond( Gia_ManHashAnd( p, Abc_LitNot(iTemp0), Abc_LitNot(iTemp1) ), !fCompl ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManHashMux( Gia_Man_t * p, int iCtrl, int iData1, int iData0 ) +{ + if ( p->fGiaSimple ) + return Gia_ManHashOr(p, Gia_ManHashAnd(p, iCtrl, iData1), Gia_ManHashAnd(p, Abc_LitNot(iCtrl), iData0) ); + else + { + int iTemp0, iTemp1, fCompl = 0; + if ( iData0 > iData1 ) + iData0 ^= iData1, iData1 ^= iData0, iData0 ^= iData1, iCtrl = Abc_LitNot(iCtrl); + if ( Abc_LitIsCompl(iData1) ) + iData0 = Abc_LitNot(iData0), iData1 = Abc_LitNot(iData1), fCompl = 1; + iTemp0 = Gia_ManHashAnd( p, Abc_LitNot(iCtrl), iData0 ); + iTemp1 = Gia_ManHashAnd( p, iCtrl, iData1 ); + return Abc_LitNotCond( Gia_ManHashAnd( p, Abc_LitNot(iTemp0), Abc_LitNot(iTemp1) ), !fCompl ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManHashMaj( Gia_Man_t * p, int iData0, int iData1, int iData2 ) +{ + int iTemp0 = Gia_ManHashOr( p, iData1, iData2 ); + int iTemp1 = Gia_ManHashAnd( p, iData0, iTemp0 ); + int iTemp2 = Gia_ManHashAnd( p, iData1, iData2 ); + return Gia_ManHashOr( p, iTemp1, iTemp2 ); +} + +/**Function************************************************************* + + Synopsis [Rehashes AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManRehash( Gia_Man_t * p, int fAddStrash ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->fAddStrash = fAddStrash; + Gia_ManHashAlloc( pNew ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObj( p, pObj, i ) + { + //if ( Gia_ObjIsBuf(pObj) ) + // pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + //else + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManHashStop( pNew ); + pNew->fAddStrash = 0; + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); +// printf( "Top gate is %s\n", Gia_ObjFaninC0(Gia_ManCo(pNew, 0))? "OR" : "AND" ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Creates well-balanced AND gate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManHashAndMulti( Gia_Man_t * p, Vec_Int_t * vLits ) +{ + if ( Vec_IntSize(vLits) == 0 ) + return 0; + while ( Vec_IntSize(vLits) > 1 ) + { + int i, k = 0, Lit1, Lit2, LitRes; + Vec_IntForEachEntryDouble( vLits, Lit1, Lit2, i ) + { + LitRes = Gia_ManHashAnd( p, Lit1, Lit2 ); + Vec_IntWriteEntry( vLits, k++, LitRes ); + } + if ( Vec_IntSize(vLits) & 1 ) + Vec_IntWriteEntry( vLits, k++, Vec_IntEntryLast(vLits) ); + Vec_IntShrink( vLits, k ); + } + assert( Vec_IntSize(vLits) == 1 ); + return Vec_IntEntry(vLits, 0); +} +int Gia_ManHashAndMulti2( Gia_Man_t * p, Vec_Int_t * vLits ) +{ + int i, iLit, iRes = 1; + Vec_IntForEachEntry( vLits, iLit, i ) + iRes = Gia_ManHashAnd( p, iRes, iLit ); + return iRes; +} +int Gia_ManHashDualMiter( Gia_Man_t * p, Vec_Int_t * vOuts ) +{ + int i, iLit0, iLit1, iRes = 0; + Vec_IntForEachEntryDouble( vOuts, iLit0, iLit1, i ) + iRes = Gia_ManHashOr( p, iRes, Gia_ManHashXor(p, iLit0, iLit1) ); + return iRes; +} + + + +/**Function************************************************************* + + Synopsis [Create multi-input tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Gia_ManCollectLiterals( int nVars ) +{ + int i, * pRes = ABC_CALLOC( int, nVars ); + for ( i = 0; i < nVars; i++ ) + pRes[i] = Abc_Var2Lit( i+1, 0 ); + return pRes; +} +int * Gia_ManGenZero( int nBits ) +{ + return ABC_CALLOC( int, nBits ); +} +int * Gia_ManGenPerm( int nBits ) +{ + int i, * pRes = ABC_CALLOC( int, nBits ); + srand( time(NULL) ); + for ( i = 0; i < nBits; i++ ) + pRes[i] = i; + for ( i = 0; i < nBits; i++ ) + { + int iPerm = rand() % nBits; + ABC_SWAP( int, pRes[i], pRes[iPerm] ); + } + return pRes; +} +int * Gia_ManGenPerm2( int nBits ) +{ + int i, * pRes = ABC_CALLOC( int, nBits ); + srand( time(NULL) ); + for ( i = 0; i < nBits; i++ ) + pRes[i] = rand() % nBits; + return pRes; +} +int Gia_ManMultiCheck( int * pPerm, int nPerm ) +{ + int i; + for ( i = 1; i < nPerm; i++ ) + if ( pPerm[i-1] <= pPerm[i] ) + return 0; + return 1; +} +int Gia_ManMultiInputPerm( Gia_Man_t * pNew, int * pVars, int nVars, int * pPerm, int fOr, int fXor ) +{ + int fPrint = 1; + int i, iLit; + if ( fPrint ) + { + for ( i = 0; i < nVars; i++ ) + printf( "%d ", pPerm[i] ); + printf( "\n" ); + } + while ( 1 ) + { + for ( i = 1; i < nVars; i++ ) + if ( pPerm[i-1] >= pPerm[i] ) + break; + if ( i == nVars ) + break; + assert( pPerm[i-1] >= pPerm[i] ); + if ( pPerm[i-1] > pPerm[i] ) + { + ABC_SWAP( int, pPerm[i-1], pPerm[i] ); + ABC_SWAP( int, pVars[i-1], pVars[i] ); + } + else + { + assert( pPerm[i-1] == pPerm[i] ); + pPerm[i-1]++; + if ( fXor ) + pVars[i-1] = Gia_ManHashXor( pNew, pVars[i-1], pVars[i] ); + else if ( fOr ) + pVars[i-1] = Gia_ManHashOr( pNew, pVars[i-1], pVars[i] ); + else + pVars[i-1] = Gia_ManHashAnd( pNew, pVars[i-1], pVars[i] ); + for ( i = i+1; i < nVars; i++ ) + { + pPerm[i-1] = pPerm[i]; + pVars[i-1] = pVars[i]; + } + nVars--; + } + if ( fPrint ) + { + for ( i = 0; i < nVars; i++ ) + printf( "%d ", pPerm[i] ); + printf( "\n" ); + } + } + iLit = pVars[0]; + for ( i = 1; i < nVars; i++ ) + if ( fXor ) + iLit = Gia_ManHashXor( pNew, iLit, pVars[i] ); + else if ( fOr ) + iLit = Gia_ManHashOr( pNew, iLit, pVars[i] ); + else + iLit = Gia_ManHashAnd( pNew, iLit, pVars[i] ); + return iLit; +} +Gia_Man_t * Gia_ManMultiInputTest( int nBits ) +{ + Gia_Man_t * pNew; + int i, iRes, * pPerm; + int * pMulti = Gia_ManCollectLiterals( nBits ); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "multi" ); + for ( i = 0; i < nBits; i++ ) + Gia_ManAppendCi( pNew ); + Gia_ManHashAlloc( pNew ); + pPerm = Gia_ManGenPerm2( nBits ); + //pPerm = Gia_ManGenZero( nBits ); + iRes = Gia_ManMultiInputPerm( pNew, pMulti, nBits, pPerm, 0, 0 ); + Gia_ManAppendCo( pNew, iRes ); + ABC_FREE( pPerm ); + ABC_FREE( pMulti ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Create MUX tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCube( Gia_Man_t * pNew, int Vars, int nVars, int * pLits ) +{ + int i, iLit = 1; + for ( i = 0; i < nVars; i++ ) + iLit = Gia_ManHashAnd( pNew, iLit, Abc_LitNotCond(pLits[i], !((Vars >> i) & 1)) ); + return iLit; +} +int Gia_ManMuxTree_rec( Gia_Man_t * pNew, int * pCtrl, int nCtrl, int * pData ) +{ + int iLit0, iLit1; + if ( nCtrl == 0 ) + return pData[0]; + iLit0 = Gia_ManMuxTree_rec( pNew, pCtrl, nCtrl-1, pData ); + iLit1 = Gia_ManMuxTree_rec( pNew, pCtrl, nCtrl-1, pData + (1<<(nCtrl-1)) ); + return Gia_ManHashMux( pNew, pCtrl[nCtrl-1], iLit1, iLit0 ); +} +void Gia_ManUsePerm( int * pTree, int nBits, int * pPerm ) +{ + int fPrint = 0; + int i, k, m, nVars = nBits + (1 << nBits); + if ( fPrint ) + { + for ( i = 0; i < nVars; i++ ) + printf( "%d ", pPerm[i] ); + printf( "\n" ); + } + for ( i = 0; i < nBits; i++ ) + { + for ( k = i+1; k < nBits; k++ ) + if ( pPerm[i] > pPerm[k] ) + break; + if ( k == nBits ) + break; + assert( pPerm[i] > pPerm[k] ); + ABC_SWAP( int, pPerm[i], pPerm[k] ); + ABC_SWAP( int, pTree[i], pTree[k] ); + for ( m = 0; m < (1 << nBits); m++ ) + if ( ((m >> i) & 1) && !((m >> k) & 1) ) + { + ABC_SWAP( int, pTree[nBits+m], pTree[nBits+(m^(1<> i) & 1) ) + return Abc_LitNotCond( pLits[i], (iLate1 >> i) & 1 ); + return -1; +} +int Gia_ManLatest( int * pPerm, int nVars, int iPrev1, int iPrev2, int iPrev3 ) +{ + int i, Value = -1, iLate = -1; + for ( i = 0; i < nVars; i++ ) + if ( Value < pPerm[i] && i != iPrev1 && i != iPrev2 && i != iPrev3 ) + { + Value = pPerm[i]; + iLate = i; + } + return iLate; +} +int Gia_ManEarliest( int * pPerm, int nVars ) +{ + int i, Value = ABC_INFINITY, iLate = -1; + for ( i = 0; i < nVars; i++ ) + if ( Value > pPerm[i] ) + { + Value = pPerm[i]; + iLate = i; + } + return iLate; +} +int Gia_ManDecompOne( Gia_Man_t * pNew, int * pTree, int nBits, int * pPerm, int iLate ) +{ + int iRes, iData; + assert( iLate >= 0 && iLate < (1<= 0 && iLate1 < (1<= 0 && iLate2 < (1<= 0 && iLate1 < (1<= 0 && iLate2 < (1<= 0 && iLate3 < (1< BaseValue && pPerm[nBits+iLate2] > BaseValue && pPerm[nBits+iLate3] > BaseValue && pPerm[nBits+iLate4] == BaseValue ) + return Gia_ManDecompThree( pNew, pTree, nBits, pPerm, iLate1, iLate2, iLate3 ); + if ( pPerm[nBits+iLate1] > BaseValue && pPerm[nBits+iLate2] > BaseValue && pPerm[nBits+iLate3] == BaseValue ) + return Gia_ManDecompTwo( pNew, pTree, nBits, pPerm, iLate1, iLate2 ); + if ( pPerm[nBits+iLate1] > BaseValue && pPerm[nBits+iLate2] == BaseValue ) + return Gia_ManDecompOne( pNew, pTree, nBits, pPerm, iLate1 ); + return Gia_ManMuxTree_rec( pNew, pTree, nBits, pTree+nBits ); + } +} +Gia_Man_t * Gia_ManMuxTreeTest( int nBits ) +{ + Gia_Man_t * pNew; + int i, iLit, nVars = nBits + (1 << nBits); + int * pPerm, * pTree = Gia_ManCollectLiterals( nVars ); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "mux_tree" ); + for ( i = 0; i < nVars; i++ ) + Gia_ManAppendCi( pNew ); + Gia_ManHashAlloc( pNew ); + pPerm = Gia_ManGenPerm( nVars ); + //pPerm = Gia_ManGenZero( nVars ); + pPerm[nBits+1] = 100; + pPerm[nBits+5] = 100; + pPerm[nBits+4] = 100; + Gia_ManUsePerm( pTree, nBits, pPerm ); + iLit = Gia_ManDecomp( pNew, pTree, nBits, pPerm ); + Gia_ManAppendCo( pNew, iLit ); + ABC_FREE( pPerm ); + ABC_FREE( pTree ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaHcd.c b/yosys/abc/src/aig/gia/giaHcd.c new file mode 100644 index 00000000000..8e8461e12c2 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaHcd.c @@ -0,0 +1,689 @@ +/**CFile**************************************************************** + + FileName [giaHcd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [New choice computation package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaHcd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "giaAig.h" +#include "aig/aig/aig.h" +#include "opt/dar/dar.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// choicing parameters +typedef struct Hcd_Pars_t_ Hcd_Pars_t; +struct Hcd_Pars_t_ +{ + int nWords; // the number of simulation words + int nBTLimit; // conflict limit at a node + int nSatVarMax; // the max number of SAT variables + int fSynthesis; // set to 1 to perform synthesis + int fPolarFlip; // uses polarity adjustment + int fSimulateTfo; // uses simulation of TFO classes + int fPower; // uses power-aware rewriting + int fUseGia; // uses GIA package + int fUseCSat; // uses circuit-based solver + int fVerbose; // verbose stats + clock_t timeSynth; // synthesis runtime + int nNodesAhead; // the lookahead in terms of nodes + int nCallsRecycle; // calls to perform before recycling SAT solver +}; + +extern void Gia_ComputeEquivalences( Gia_Man_t * pMiter, int nBTLimit, int fUseMiniSat, int fVerbose ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [This procedure sets default parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hcd_ManSetDefaultParams( Hcd_Pars_t * p ) +{ + memset( p, 0, sizeof(Hcd_Pars_t) ); + p->nWords = 8; // the number of simulation words + p->nBTLimit = 1000; // conflict limit at a node + p->nSatVarMax = 5000; // the max number of SAT variables + p->fSynthesis = 1; // derives three snapshots + p->fPolarFlip = 1; // uses polarity adjustment + p->fSimulateTfo = 1; // simulate TFO + p->fPower = 0; // power-aware rewriting + p->fVerbose = 0; // verbose stats + p->nNodesAhead = 1000; // the lookahead in terms of nodes + p->nCallsRecycle = 100; // calls to perform before recycling SAT solver +} + + +/**Function************************************************************* + + Synopsis [Reproduces script "compress".] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Hcd_Compress( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fVerbose ) +//alias compress2 "b -l; rw -l; rwz -l; b -l; rwz -l; b -l" +{ + Aig_Man_t * pTemp; + + Dar_RwrPar_t ParsRwr, * pParsRwr = &ParsRwr; + Dar_RefPar_t ParsRef, * pParsRef = &ParsRef; + + Dar_ManDefaultRwrParams( pParsRwr ); + Dar_ManDefaultRefParams( pParsRef ); + + pParsRwr->fUpdateLevel = fUpdateLevel; + pParsRef->fUpdateLevel = fUpdateLevel; + + pParsRwr->fPower = fPower; + + pParsRwr->fVerbose = 0;//fVerbose; + pParsRef->fVerbose = 0;//fVerbose; + +// pAig = Aig_ManDupDfs( pAig ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + + // refactor + Dar_ManRefactor( pAig, pParsRef ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + + // balance + if ( fBalance ) + { + pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + } + + pParsRwr->fUseZeros = 1; + pParsRef->fUseZeros = 1; + + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + + return pAig; +} + +/**Function************************************************************* + + Synopsis [Reproduces script "compress2".] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Hcd_Compress2( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fVerbose ) +//alias compress2 "b -l; rw -l; rf -l; b -l; rw -l; rwz -l; b -l; rfz -l; rwz -l; b -l" +{ + Aig_Man_t * pTemp; + + Dar_RwrPar_t ParsRwr, * pParsRwr = &ParsRwr; + Dar_RefPar_t ParsRef, * pParsRef = &ParsRef; + + Dar_ManDefaultRwrParams( pParsRwr ); + Dar_ManDefaultRefParams( pParsRef ); + + pParsRwr->fUpdateLevel = fUpdateLevel; + pParsRef->fUpdateLevel = fUpdateLevel; + pParsRwr->fFanout = fFanout; + pParsRwr->fPower = fPower; + + pParsRwr->fVerbose = 0;//fVerbose; + pParsRef->fVerbose = 0;//fVerbose; + +// pAig = Aig_ManDupDfs( pAig ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + + // refactor + Dar_ManRefactor( pAig, pParsRef ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + + // balance +// if ( fBalance ) + { + pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + } + + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + + pParsRwr->fUseZeros = 1; + pParsRef->fUseZeros = 1; + + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + + // balance + if ( fBalance ) + { + pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + } + + // refactor + Dar_ManRefactor( pAig, pParsRef ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + + // rewrite + Dar_ManRewrite( pAig, pParsRwr ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + + // balance + if ( fBalance ) + { + pAig = Dar_ManBalance( pTemp = pAig, fUpdateLevel ); + Aig_ManStop( pTemp ); + if ( fVerbose ) Aig_ManPrintStats( pAig ); + } + return pAig; +} + +/**Function************************************************************* + + Synopsis [Reproduces script "compress2".] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Hcd_ChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fVerbose ) +//alias resyn "b; rw; rwz; b; rwz; b" +//alias resyn2 "b; rw; rf; b; rw; rwz; b; rfz; rwz; b" +{ + Vec_Ptr_t * vGias; + Gia_Man_t * pGia; + + vGias = Vec_PtrAlloc( 3 ); + pGia = Gia_ManFromAig(pAig); + Vec_PtrPush( vGias, pGia ); + + pAig = Hcd_Compress( pAig, fBalance, fUpdateLevel, fPower, fVerbose ); + pGia = Gia_ManFromAig(pAig); + Vec_PtrPush( vGias, pGia ); +//Aig_ManPrintStats( pAig ); + + pAig = Hcd_Compress2( pAig, fBalance, fUpdateLevel, 1, fPower, fVerbose ); + pGia = Gia_ManFromAig(pAig); + Vec_PtrPush( vGias, pGia ); +//Aig_ManPrintStats( pAig ); + + Aig_ManStop( pAig ); + return vGias; +} + + +/**Function************************************************************* + + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hcd_ManChoiceMiter_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return pObj->Value; + Hcd_ManChoiceMiter_rec( pNew, p, Gia_ObjFanin0(pObj) ); + if ( Gia_ObjIsCo(pObj) ) + return pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Hcd_ManChoiceMiter_rec( pNew, p, Gia_ObjFanin1(pObj) ); + return pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Derives the miter of several AIGs for choice computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Hcd_ManChoiceMiter( Vec_Ptr_t * vGias ) +{ + Gia_Man_t * pNew, * pGia, * pGia0; + int i, k, iNode, nNodes; + // make sure they have equal parameters + assert( Vec_PtrSize(vGias) > 0 ); + pGia0 = (Gia_Man_t *)Vec_PtrEntry( vGias, 0 ); + Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) + { + assert( Gia_ManCiNum(pGia) == Gia_ManCiNum(pGia0) ); + assert( Gia_ManCoNum(pGia) == Gia_ManCoNum(pGia0) ); + assert( Gia_ManRegNum(pGia) == Gia_ManRegNum(pGia0) ); + Gia_ManFillValue( pGia ); + Gia_ManConst0(pGia)->Value = 0; + } + // start the new manager + pNew = Gia_ManStart( Vec_PtrSize(vGias) * Gia_ManObjNum(pGia0) ); + pNew->pName = Abc_UtilStrsav( pGia0->pName ); + pNew->pSpec = Abc_UtilStrsav( pGia0->pSpec ); + // create new CIs and assign them to the old manager CIs + for ( k = 0; k < Gia_ManCiNum(pGia0); k++ ) + { + iNode = Gia_ManAppendCi(pNew); + Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) + Gia_ManCi( pGia, k )->Value = iNode; + } + // create internal nodes + Gia_ManHashAlloc( pNew ); + for ( k = 0; k < Gia_ManCoNum(pGia0); k++ ) + { + Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) + Hcd_ManChoiceMiter_rec( pNew, pGia, Gia_ManCo( pGia, k ) ); + } + Gia_ManHashStop( pNew ); + // check the presence of dangling nodes + nNodes = Gia_ManHasDangling( pNew ); + assert( nNodes == 0 ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pOld is in the TFI of pNode.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hcd_ObjCheckTfi_rec( Gia_Man_t * p, Gia_Obj_t * pOld, Gia_Obj_t * pNode, Vec_Ptr_t * vVisited ) +{ + // check the trivial cases + if ( pNode == NULL ) + return 0; + if ( Gia_ObjIsCi(pNode) ) + return 0; +// if ( pNode->Id < pOld->Id ) // cannot use because of choices of pNode +// return 0; + if ( pNode == pOld ) + return 1; + // skip the visited node + if ( pNode->fMark0 ) + return 0; + pNode->fMark0 = 1; + Vec_PtrPush( vVisited, pNode ); + // check the children + if ( Hcd_ObjCheckTfi_rec( p, pOld, Gia_ObjFanin0(pNode), vVisited ) ) + return 1; + if ( Hcd_ObjCheckTfi_rec( p, pOld, Gia_ObjFanin1(pNode), vVisited ) ) + return 1; + // check equivalent nodes + return Hcd_ObjCheckTfi_rec( p, pOld, Gia_ObjNextObj(p, Gia_ObjId(p, pNode)), vVisited ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pOld is in the TFI of pNode.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hcd_ObjCheckTfi( Gia_Man_t * p, Gia_Obj_t * pOld, Gia_Obj_t * pNode ) +{ + Vec_Ptr_t * vVisited; + Gia_Obj_t * pObj; + int RetValue, i; + assert( !Gia_IsComplement(pOld) ); + assert( !Gia_IsComplement(pNode) ); + vVisited = Vec_PtrAlloc( 100 ); + RetValue = Hcd_ObjCheckTfi_rec( p, pOld, pNode, vVisited ); + Vec_PtrForEachEntry( Gia_Obj_t *, vVisited, pObj, i ) + pObj->fMark0 = 0; + Vec_PtrFree( vVisited ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Adds the next entry while making choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hcd_ManAddNextEntry_rec( Gia_Man_t * p, Gia_Obj_t * pOld, Gia_Obj_t * pNode ) +{ + if ( Gia_ObjNext(p, Gia_ObjId(p, pOld)) == 0 ) + { + Gia_ObjSetNext( p, Gia_ObjId(p, pOld), Gia_ObjId(p, pNode) ); + return; + } + Hcd_ManAddNextEntry_rec( p, Gia_ObjNextObj(p, Gia_ObjId(p, pOld)), pNode ); +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hcd_ManEquivToChoices_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + Gia_Obj_t * pRepr, * pReprNew, * pObjNew; + if ( ~pObj->Value ) + return; + if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) + { + if ( Gia_ObjIsConst0(pRepr) ) + { + pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); + return; + } + Hcd_ManEquivToChoices_rec( pNew, p, pRepr ); + assert( Gia_ObjIsAnd(pObj) ); + Hcd_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Hcd_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( Abc_LitRegular(pObj->Value) == Abc_LitRegular(pRepr->Value) ) + { + assert( (int)pObj->Value == Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ) ); + return; + } + if ( pRepr->Value > pObj->Value ) // should never happen with high resource limit + return; + assert( pRepr->Value < pObj->Value ); + pReprNew = Gia_ManObj( pNew, Abc_Lit2Var(pRepr->Value) ); + pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) ); + if ( Gia_ObjReprObj( pNew, Gia_ObjId(pNew, pObjNew) ) ) + { + assert( Gia_ObjReprObj( pNew, Gia_ObjId(pNew, pObjNew) ) == pReprNew ); + pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); + return; + } + if ( !Hcd_ObjCheckTfi( pNew, pReprNew, pObjNew ) ) + { + assert( Gia_ObjNext(pNew, Gia_ObjId(pNew, pObjNew)) == 0 ); + Gia_ObjSetRepr( pNew, Gia_ObjId(pNew, pObjNew), Gia_ObjId(pNew, pReprNew) ); + Hcd_ManAddNextEntry_rec( pNew, pReprNew, pObjNew ); + } + pObj->Value = Abc_LitNotCond( pRepr->Value, Gia_ObjPhaseReal(pRepr) ^ Gia_ObjPhaseReal(pObj) ); + return; + } + assert( Gia_ObjIsAnd(pObj) ); + Hcd_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Hcd_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Removes choices, which contain fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hcd_ManRemoveBadChoices( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, iObj, iPrev, Counter = 0; + // mark nodes with fanout + Gia_ManForEachObj( p, pObj, i ) + { + pObj->fMark0 = 0; + if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ObjFanin0(pObj)->fMark0 = 1; + Gia_ObjFanin1(pObj)->fMark0 = 1; + } + else if ( Gia_ObjIsCo(pObj) ) + Gia_ObjFanin0(pObj)->fMark0 = 1; + } + // go through the classes and remove + Gia_ManForEachClass( p, i ) + { + for ( iPrev = i, iObj = Gia_ObjNext(p, i); iObj; iObj = Gia_ObjNext(p, iPrev) ) + { + if ( !Gia_ManObj(p, iObj)->fMark0 ) + { + iPrev = iObj; + continue; + } + Gia_ObjSetRepr( p, iObj, GIA_VOID ); + Gia_ObjSetNext( p, iPrev, Gia_ObjNext(p, iObj) ); + Gia_ObjSetNext( p, iObj, 0 ); + Counter++; + } + } + // remove the marks + Gia_ManCleanMark0( p ); +// printf( "Removed %d bad choices.\n", Counter ); +} + +/**Function************************************************************* + + Synopsis [Reduces AIG using equivalence classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Hcd_ManEquivToChoices( Gia_Man_t * p, int nSnapshots ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pRepr; + int i; + assert( (Gia_ManCoNum(p) % nSnapshots) == 0 ); + Gia_ManSetPhase( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) ); + pNew->pNexts = ABC_CALLOC( int, Gia_ManObjNum(p) ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + Gia_ObjSetRepr( pNew, i, GIA_VOID ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachRo( p, pObj, i ) + if ( (pRepr = Gia_ObjReprObj(p, Gia_ObjId(p, pObj))) ) + { + assert( Gia_ObjIsConst0(pRepr) || Gia_ObjIsRo(p, pRepr) ); + pObj->Value = pRepr->Value; + } + Gia_ManHashAlloc( pNew ); + Gia_ManForEachCo( p, pObj, i ) + Hcd_ManEquivToChoices_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + if ( i % nSnapshots == 0 ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + Hcd_ManRemoveBadChoices( pNew ); +// Gia_ManEquivPrintClasses( pNew, 0, 0 ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); +// Gia_ManEquivPrintClasses( pNew, 0, 0 ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Performs computation of AIGs with choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Hcd_ComputeChoices( Aig_Man_t * pAig, int nBTLimit, int fSynthesis, int fUseMiniSat, int fVerbose ) +{ + Vec_Ptr_t * vGias; + Gia_Man_t * pGia, * pMiter; + Aig_Man_t * pAigNew; + int i; + clock_t clk = clock(); + // perform synthesis + if ( fSynthesis ) + { + vGias = Hcd_ChoiceSynthesis( Aig_ManDupDfs(pAig), 1, 1, 0, 0 ); + if ( fVerbose ) + ABC_PRT( "Synthesis time", clock() - clk ); + // create choices + clk = clock(); + pMiter = Hcd_ManChoiceMiter( vGias ); + Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) + Gia_ManStop( pGia ); + + Gia_AigerWrite( pMiter, "m3.aig", 0, 0, 0 ); + } + else + { + vGias = Vec_PtrStart( 3 ); + pMiter = Gia_ManFromAig(pAig); + } + // perform choicing + Gia_ComputeEquivalences( pMiter, nBTLimit, fUseMiniSat, fVerbose ); + // derive AIG with choices + pGia = Hcd_ManEquivToChoices( pMiter, Vec_PtrSize(vGias) ); + Gia_ManSetRegNum( pGia, Aig_ManRegNum(pAig) ); + Gia_ManStop( pMiter ); + Vec_PtrFree( vGias ); + if ( fVerbose ) + ABC_PRT( "Choicing time", clock() - clk ); +// Gia_ManHasChoices_very_old( pGia ); + // transform back + pAigNew = Gia_ManToAig( pGia, 1 ); + Gia_ManStop( pGia ); + + if ( fVerbose ) + { + extern int Dch_DeriveChoiceCountReprs( Aig_Man_t * pAig ); + extern int Dch_DeriveChoiceCountEquivs( Aig_Man_t * pAig ); + printf( "Choices : Reprs = %5d. Equivs = %5d. Choices = %5d.\n", + Dch_DeriveChoiceCountReprs( pAigNew ), + Dch_DeriveChoiceCountEquivs( pAigNew ), + Aig_ManChoiceNum( pAigNew ) ); + } + + return pAigNew; +} + +/**Function************************************************************* + + Synopsis [Performs computation of AIGs with choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hcd_ComputeChoicesTest( Gia_Man_t * pGia, int nBTLimit, int fSynthesis, int fUseMiniSat, int fVerbose ) +{ + Aig_Man_t * pAig, * pAigNew; + pAig = Gia_ManToAig( pGia, 0 ); + pAigNew = Hcd_ComputeChoices( pAig, nBTLimit, fSynthesis, fUseMiniSat, fVerbose ); + Aig_ManStop( pAigNew ); + Aig_ManStop( pAig ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaIf.c b/yosys/abc/src/aig/gia/giaIf.c new file mode 100644 index 00000000000..c08a91ecd15 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaIf.c @@ -0,0 +1,2758 @@ +/**CFile**************************************************************** + + FileName [giaMap.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Manipulation of mapping associated with the AIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaMap.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "aig/aig/aig.h" +#include "map/if/if.h" +#include "bool/kit/kit.h" +#include "base/main/main.h" +#include "sat/bsat/satSolver.h" + +#ifdef WIN32 +#include +#endif + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); +extern int Abc_RecToGia3( Gia_Man_t * pMan, If_Man_t * pIfMan, If_Cut_t * pCut, Vec_Int_t * vLeaves, int fHash ); + +extern void Gia_ManPrintGetMuxFanins( Gia_Man_t * p, Gia_Obj_t * pObj, int * pFanins ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Load the network into FPGA manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSetIfParsDefault( void * pp ) +{ + If_Par_t * pPars = (If_Par_t *)pp; +// extern void * Abc_FrameReadLibLut(); + If_Par_t * p = (If_Par_t *)pPars; + // set defaults + memset( p, 0, sizeof(If_Par_t) ); + // user-controlable paramters + p->nLutSize = -1; +// p->nLutSize = 6; + p->nCutsMax = 8; + p->nFlowIters = 1; + p->nAreaIters = 2; + p->DelayTarget = -1; + p->Epsilon = (float)0.005; + p->fPreprocess = 1; + p->fArea = 0; + p->fFancy = 0; + p->fExpRed = 1; //// + p->fLatchPaths = 0; + p->fEdge = 1; + p->fPower = 0; + p->fCutMin = 0; + p->fVerbose = 0; + p->pLutStruct = NULL; + // internal parameters + p->fTruth = 0; + p->nLatchesCi = 0; + p->nLatchesCo = 0; + p->fLiftLeaves = 0; + p->fUseCoAttrs = 1; // use CO attributes + p->pLutLib = NULL; + p->pTimesArr = NULL; + p->pTimesReq = NULL; + p->pFuncCost = NULL; +} + + +/**Function************************************************************* + + Synopsis [Prints mapping statistics.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManLutFaninCount( Gia_Man_t * p ) +{ + int i, Counter = 0; + Gia_ManForEachLut( p, i ) + Counter += Gia_ObjLutSize(p, i); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Prints mapping statistics.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManLutSizeMax( Gia_Man_t * p ) +{ + int i, nSizeMax = -1; + Gia_ManForEachLut( p, i ) + nSizeMax = Abc_MaxInt( nSizeMax, Gia_ObjLutSize(p, i) ); + return nSizeMax; +} + +/**Function************************************************************* + + Synopsis [Prints mapping statistics.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManLutNum( Gia_Man_t * p ) +{ + int i, Counter = 0; + Gia_ManForEachLut( p, i ) + Counter ++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Prints mapping statistics.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManLutLevel( Gia_Man_t * p, int ** ppLevels ) +{ + Gia_Obj_t * pObj; + int i, k, iFan, Level; + int * pLevels = ABC_CALLOC( int, Gia_ManObjNum(p) ); + Gia_ManForEachLut( p, i ) + { + Level = 0; + Gia_LutForEachFanin( p, i, iFan, k ) + if ( Level < pLevels[iFan] ) + Level = pLevels[iFan]; + pLevels[i] = Level + 1; + } + Level = 0; + Gia_ManForEachCo( p, pObj, k ) + { + int LevelFan = pLevels[Gia_ObjFaninId0p(p, pObj)]; + Level = Abc_MaxInt( Level, LevelFan ); + pLevels[Gia_ObjId(p, pObj)] = LevelFan; + } + if ( ppLevels ) + *ppLevels = pLevels; + else + ABC_FREE( pLevels ); + return Level; +} + +/**Function************************************************************* + + Synopsis [Prints mapping statistics.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManLutParams( Gia_Man_t * p, int * pnCurLuts, int * pnCurEdges, int * pnCurLevels ) +{ + int fDisable2Lut = 1; + if ( p->pManTime && Tim_ManBoxNum((Tim_Man_t *)p->pManTime) ) + { + int i; + *pnCurLuts = 0; + *pnCurEdges = 0; + Gia_ManForEachLut( p, i ) + { + (*pnCurLuts)++; + (*pnCurEdges) += Gia_ObjLutSize(p, i); + } + *pnCurLevels = Gia_ManLutLevelWithBoxes( p ); + } + else + { + Gia_Obj_t * pObj; + int i, k, iFan; + int * pLevels = ABC_CALLOC( int, Gia_ManObjNum(p) ); + *pnCurLuts = 0; + *pnCurEdges = 0; + *pnCurLevels = 0; + Gia_ManForEachLut( p, i ) + { + if ( Gia_ObjLutIsMux(p, i) && !(fDisable2Lut && Gia_ObjLutSize(p, i) == 2) ) + { + int pFanins[3]; + if ( Gia_ObjLutSize(p, i) == 3 ) + { + Gia_ManPrintGetMuxFanins( p, Gia_ManObj(p, i), pFanins ); + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[pFanins[0]]+1 ); + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[pFanins[1]] ); + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[pFanins[2]] ); + } + else if ( Gia_ObjLutSize(p, i) == 2 ) + { + pObj = Gia_ManObj( p, i ); + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[Gia_ObjFaninId0(pObj, i)] ); + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[Gia_ObjFaninId1(pObj, i)] ); + } + *pnCurLevels = Abc_MaxInt( *pnCurLevels, pLevels[i] ); + (*pnCurEdges)++; + //nMuxF++; + continue; + } + (*pnCurLuts)++; + (*pnCurEdges) += Gia_ObjLutSize(p, i); + Gia_LutForEachFanin( p, i, iFan, k ) + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[iFan] ); + pLevels[i]++; + *pnCurLevels = Abc_MaxInt( *pnCurLevels, pLevels[i] ); + } + ABC_FREE( pLevels ); + } +} + +/**Function************************************************************* + + Synopsis [Assigns levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSetRefsMapped( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, k, iFan; + ABC_FREE( p->pRefs ); + p->pRefs = ABC_CALLOC( int, Gia_ManObjNum(p) ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ObjRefIncId( p, Gia_ObjFaninId0p(p, pObj) ); + Gia_ManForEachLut( p, i ) + Gia_LutForEachFanin( p, i, iFan, k ) + Gia_ObjRefIncId( p, iFan ); +} + +/**Function************************************************************* + + Synopsis [Assigns levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSetLutRefs( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, k, iFan; + ABC_FREE( p->pLutRefs ); + p->pLutRefs = ABC_CALLOC( int, Gia_ManObjNum(p) ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ObjLutRefIncId( p, Gia_ObjFaninId0p(p, pObj) ); + Gia_ManForEachLut( p, i ) + Gia_LutForEachFanin( p, i, iFan, k ) + Gia_ObjLutRefIncId( p, iFan ); +} + +/**Function************************************************************* + + Synopsis [Calculate mapping overlap.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManComputeOverlap2One_rec( Gia_Man_t * p, int iObj, Vec_Str_t * vLabel, Vec_Int_t * vVisit ) +{ + Gia_Obj_t * pObj; + int Counter; + if ( Vec_StrEntry(vLabel, iObj) ) + return 0; + Vec_StrWriteEntry( vLabel, iObj, 1 ); + pObj = Gia_ManObj( p, iObj ); + assert( Gia_ObjIsAnd(pObj) ); + Counter = Gia_ManComputeOverlap2One_rec( p, Gia_ObjFaninId0(pObj, iObj), vLabel, vVisit ); + Counter += Gia_ManComputeOverlap2One_rec( p, Gia_ObjFaninId1(pObj, iObj), vLabel, vVisit ); + Vec_IntPush( vVisit, iObj ); + return Counter + 1; +} +int Gia_ManComputeOverlap2One( Gia_Man_t * p, int iObj, Vec_Str_t * vLabel, Vec_Int_t * vVisit ) +{ + int iFan, k, Counter; + Vec_IntClear( vVisit ); + Gia_LutForEachFanin( p, iObj, iFan, k ) + Vec_StrWriteEntry( vLabel, iFan, 1 ); + Counter = Gia_ManComputeOverlap2One_rec( p, iObj, vLabel, vVisit ); + Gia_LutForEachFanin( p, iObj, iFan, k ) + Vec_StrWriteEntry( vLabel, iFan, 0 ); + Vec_IntForEachEntry( vVisit, iFan, k ) + Vec_StrWriteEntry( vLabel, iFan, 0 ); + return Counter; +} +int Gia_ManComputeOverlap2( Gia_Man_t * p ) +{ + Vec_Int_t * vVisit; + Vec_Str_t * vLabel; + int i, Count = -Gia_ManAndNum(p); + assert( Gia_ManHasMapping(p) ); + vVisit = Vec_IntAlloc( 100 ); + vLabel = Vec_StrStart( Gia_ManObjNum(p) ); + Gia_ManForEachLut( p, i ) + Count += Gia_ManComputeOverlap2One( p, i, vLabel, vVisit ); + Vec_StrFree( vLabel ); + Vec_IntFree( vVisit ); + return Count; +} + +/**Function************************************************************* + + Synopsis [Calculate mapping overlap.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManComputeOverlapOne_rec( Gia_Man_t * p, int iObj ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return 0; + Gia_ObjSetTravIdCurrentId( p, iObj ); + pObj = Gia_ManObj( p, iObj ); + assert( Gia_ObjIsAnd(pObj) ); + return 1 + Gia_ManComputeOverlapOne_rec( p, Gia_ObjFaninId0(pObj, iObj) ) + + Gia_ManComputeOverlapOne_rec( p, Gia_ObjFaninId1(pObj, iObj) ); +} +int Gia_ManComputeOverlapOne( Gia_Man_t * p, int iObj ) +{ + int iFan, k; + Gia_ManIncrementTravId(p); + Gia_LutForEachFanin( p, iObj, iFan, k ) + Gia_ObjSetTravIdCurrentId( p, iFan ); + return Gia_ManComputeOverlapOne_rec( p, iObj ); +} +int Gia_ManComputeOverlap( Gia_Man_t * p ) +{ + int i, Count = -Gia_ManAndNum(p); + assert( Gia_ManHasMapping(p) ); + Gia_ManForEachLut( p, i ) + Count += Gia_ManComputeOverlapOne( p, i ); + return Count; +} + +/**Function************************************************************* + + Synopsis [Prints mapping statistics.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintGetMuxFanins( Gia_Man_t * p, Gia_Obj_t * pObj, int * pFanins ) +{ + Gia_Obj_t * pData0, * pData1; + Gia_Obj_t * pCtrl = Gia_ObjRecognizeMux( pObj, &pData1, &pData0 ); + pFanins[0] = Gia_ObjId(p, Gia_Regular(pCtrl)); + pFanins[1] = Gia_ObjId(p, Gia_Regular(pData1)); + pFanins[2] = Gia_ObjId(p, Gia_Regular(pData0)); +} +int Gia_ManCountDupLut( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj, * pFanin; + int i, pFanins[3], nCountDup = 0, nCountPis = 0, nCountMux = 0; + Gia_ManCleanMark01( p ); + Gia_ManForEachLut( p, i ) + if ( Gia_ObjLutIsMux(p, i) ) + { + pObj = Gia_ManObj( p, i ); + pObj->fMark1 = 1; + if ( Gia_ObjLutSize(p, i) == 3 ) + { + Gia_ManPrintGetMuxFanins( p, pObj, pFanins ); + + pFanin = Gia_ManObj(p, pFanins[1]); + nCountPis += Gia_ObjIsCi(pFanin); + nCountDup += pFanin->fMark0; + nCountMux += pFanin->fMark1; + pFanin->fMark0 = 1; + + pFanin = Gia_ManObj(p, pFanins[2]); + nCountPis += Gia_ObjIsCi(pFanin); + nCountDup += pFanin->fMark0; + nCountMux += pFanin->fMark1; + pFanin->fMark0 = 1; + } + else if ( Gia_ObjLutSize(p, i) == 2 ) + { + pFanin = Gia_ObjFanin0(pObj); + if ( pFanin->fMark0 || pFanin->fMark1 ) + { + pFanin = Gia_ObjFanin1(pObj); + nCountPis += Gia_ObjIsCi(pFanin); + nCountDup += pFanin->fMark0; + nCountMux += pFanin->fMark1; + pFanin->fMark0 = 1; + } + else + { + nCountPis += Gia_ObjIsCi(pFanin); + nCountDup += pFanin->fMark0; + nCountMux += pFanin->fMark1; + pFanin->fMark0 = 1; + } + } + else assert( 0 ); + } + Gia_ManCleanMark01( p ); + if ( nCountDup + nCountPis + nCountMux ) + printf( "Dup fanins = %d. CI fanins = %d. MUX fanins = %d. Total = %d. (%.2f %%)\n", + nCountDup, nCountPis, nCountMux, nCountDup + nCountPis, 100.0 * (nCountDup + nCountPis + nCountMux) / Gia_ManLutNum(p) ); + return nCountDup + nCountPis; +} + +void Gia_ManPrintMappingStats( Gia_Man_t * p, char * pDumpFile ) +{ + int fDisable2Lut = 1; + Gia_Obj_t * pObj; + int * pLevels; + int i, k, iFan, nLutSize = 0, nLuts = 0, nFanins = 0, LevelMax = 0, Ave = 0, nMuxF = 0; + if ( !Gia_ManHasMapping(p) ) + return; + pLevels = ABC_CALLOC( int, Gia_ManObjNum(p) ); + Gia_ManForEachLut( p, i ) + { + if ( Gia_ObjLutIsMux(p, i) && !(fDisable2Lut && Gia_ObjLutSize(p, i) == 2) ) + { + int pFanins[3]; + if ( Gia_ObjLutSize(p, i) == 3 ) + { + Gia_ManPrintGetMuxFanins( p, Gia_ManObj(p, i), pFanins ); + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[pFanins[0]]+1 ); + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[pFanins[1]] ); + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[pFanins[2]] ); + } + else if ( Gia_ObjLutSize(p, i) == 2 ) + { + pObj = Gia_ManObj( p, i ); + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[Gia_ObjFaninId0(pObj, i)] ); + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[Gia_ObjFaninId1(pObj, i)] ); + } + LevelMax = Abc_MaxInt( LevelMax, pLevels[i] ); + nFanins++; + nMuxF++; + continue; + } + nLuts++; + nFanins += Gia_ObjLutSize(p, i); + nLutSize = Abc_MaxInt( nLutSize, Gia_ObjLutSize(p, i) ); + Gia_LutForEachFanin( p, i, iFan, k ) + pLevels[i] = Abc_MaxInt( pLevels[i], pLevels[iFan] ); + pLevels[i]++; + LevelMax = Abc_MaxInt( LevelMax, pLevels[i] ); + } + Gia_ManForEachCo( p, pObj, i ) + Ave += pLevels[Gia_ObjFaninId0p(p, pObj)]; + ABC_FREE( pLevels ); + +#ifdef WIN32 + { + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + Abc_Print( 1, "Mapping (K=%d) : ", nLutSize ); + SetConsoleTextAttribute( hConsole, 14 ); // yellow + Abc_Print( 1, "lut =%7d ", nLuts ); + if ( nMuxF ) + Abc_Print( 1, "muxF =%7d ", nMuxF ); + SetConsoleTextAttribute( hConsole, 10 ); // green + Abc_Print( 1, "edge =%8d ", nFanins ); + SetConsoleTextAttribute( hConsole, 12 ); // red + Abc_Print( 1, "lev =%5d ", LevelMax ); + Abc_Print( 1, "(%.2f) ", (float)Ave / Gia_ManCoNum(p) ); +// Abc_Print( 1, "over =%5.1f %% ", 100.0 * Gia_ManComputeOverlap(p) / Gia_ManAndNum(p) ); + if ( p->pManTime && Tim_ManBoxNum((Tim_Man_t *)p->pManTime) ) + Abc_Print( 1, "levB =%5d ", Gia_ManLutLevelWithBoxes(p) ); + SetConsoleTextAttribute( hConsole, 7 ); // normal + Abc_Print( 1, "mem =%5.2f MB", 4.0*(Gia_ManObjNum(p) + 2*nLuts + nFanins)/(1<<20) ); + Abc_Print( 1, "\n" ); + } +#else + Abc_Print( 1, "Mapping (K=%d) : ", nLutSize ); + Abc_Print( 1, "%slut =%7d%s ", "\033[1;33m", nLuts, "\033[0m" ); // yellow + Abc_Print( 1, "%sedge =%8d%s ", "\033[1;32m", nFanins, "\033[0m" ); // green + Abc_Print( 1, "%slev =%5d%s ", "\033[1;31m", LevelMax, "\033[0m" ); // red + Abc_Print( 1, "%s(%.2f)%s ", "\033[1;31m", (float)Ave / Gia_ManCoNum(p), "\033[0m" ); +// Abc_Print( 1, "over =%5.1f %% ", 100.0 * Gia_ManComputeOverlap(p) / Gia_ManAndNum(p) ); + if ( p->pManTime && Tim_ManBoxNum((Tim_Man_t *)p->pManTime) ) + Abc_Print( 1, "%slevB =%5d%s ", "\033[1;31m", Gia_ManLutLevelWithBoxes(p), "\033[0m" ); + Abc_Print( 1, "mem =%5.2f MB", 4.0*(Gia_ManObjNum(p) + 2*nLuts + nFanins)/(1<<20) ); + Abc_Print( 1, "\n" ); +#endif + + if ( nMuxF ) + Gia_ManCountDupLut( p ); + + //return; + if ( pDumpFile ) + { + static char FileNameOld[1000] = {0}; + static abctime clk = 0; + FILE * pTable = fopen( pDumpFile, "a+" ); + if ( strcmp( FileNameOld, p->pName ) ) + { + sprintf( FileNameOld, "%s_out", p->pName ); + fprintf( pTable, "\n" ); + fprintf( pTable, "%s ", p->pName ); + fprintf( pTable, " " ); + //fprintf( pTable, "%d ", Gia_ManAndNum(p) ); + fprintf( pTable, "%d ", Gia_ManRegNum(p) ); + fprintf( pTable, "%d ", nLuts ); + fprintf( pTable, "%d ", Gia_ManLutLevelWithBoxes(p) ); + //fprintf( pTable, "%d ", Gia_ManRegBoxNum(p) ); + //fprintf( pTable, "%d ", Gia_ManNonRegBoxNum(p) ); + //fprintf( pTable, "%.2f", 1.0*(Abc_Clock() - clk)/CLOCKS_PER_SEC ); + clk = Abc_Clock(); + } + else + { + //printf( "This part of the code is currently not used.\n" ); + //assert( 0 ); + fprintf( pTable, " " ); + fprintf( pTable, " " ); + fprintf( pTable, "%d ", Gia_ManRegNum(p) ); + fprintf( pTable, "%d ", nLuts ); + fprintf( pTable, "%d ", Gia_ManLutLevelWithBoxes(p) ); + //fprintf( pTable, "%d ", Gia_ManRegBoxNum(p) ); + //fprintf( pTable, "%d ", Gia_ManNonRegBoxNum(p) ); +// fprintf( pTable, "%.2f", 1.0*(Abc_Clock() - clk)/CLOCKS_PER_SEC ); + clk = Abc_Clock(); + } + fclose( pTable ); + } + +} + +/**Function************************************************************* + + Synopsis [Prints mapping statistics.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintPackingStats( Gia_Man_t * p ) +{ + int fVerbose = 0; + int nObjToShow = 200; + int nNumStr[5] = {0}; + int i, k, Entry, nEntries, nEntries2, MaxSize = -1, Count = 0; + if ( p->vPacking == NULL ) + return; + nEntries = Vec_IntEntry( p->vPacking, 0 ); + nEntries2 = 0; + Vec_IntForEachEntryStart( p->vPacking, Entry, i, 1 ) + { + assert( Entry > 0 && Entry < 4 ); + nNumStr[Entry]++; + i++; + if ( fVerbose && nEntries2 < nObjToShow ) Abc_Print( 1, "{ " ); + for ( k = 0; k < Entry; k++, i++ ) + if ( fVerbose && nEntries2 < nObjToShow ) Abc_Print( 1, "%d ", Vec_IntEntry(p->vPacking, i) ); + if ( fVerbose && nEntries2 < nObjToShow ) Abc_Print( 1, "}\n" ); + i--; + nEntries2++; + } + assert( nEntries == nEntries2 ); + if ( nNumStr[3] > 0 ) + MaxSize = 3; + else if ( nNumStr[2] > 0 ) + MaxSize = 2; + else if ( nNumStr[1] > 0 ) + MaxSize = 1; + Abc_Print( 1, "Packing (N=%d) : ", MaxSize ); + for ( i = 1; i <= MaxSize; i++ ) + { + Abc_Print( 1, "%d x LUT = %d ", i, nNumStr[i] ); + Count += i * nNumStr[i]; + } + Abc_Print( 1, "Total = %d ", nEntries2 ); + Abc_Print( 1, "Total LUT = %d", Count ); + Abc_Print( 1, "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintNodeProfile( int * pCounts, int nSizeMax ) +{ + int i, SizeAll = 0, NodeAll = 0; + for ( i = 0; i <= nSizeMax; i++ ) + { + SizeAll += i * pCounts[i]; + NodeAll += pCounts[i]; + } + Abc_Print( 1, "LUT = %d : ", NodeAll ); + for ( i = 2; i <= nSizeMax; i++ ) + Abc_Print( 1, "%d=%d %.1f %% ", i, pCounts[i], 100.0*pCounts[i]/NodeAll ); + Abc_Print( 1, "Ave = %.2f\n", 1.0*SizeAll/(NodeAll ? NodeAll : 1) ); +} +void Gia_ManPrintLutStats( Gia_Man_t * p ) +{ + int i, nSizeMax, pCounts[33] = {0}; + nSizeMax = Gia_ManLutSizeMax( p ); + if ( nSizeMax > 32 ) + { + Abc_Print( 1, "The max LUT size (%d) is too large.\n", nSizeMax ); + return; + } + Gia_ManForEachLut( p, i ) + pCounts[ Gia_ObjLutSize(p, i) ]++; + Gia_ManPrintNodeProfile( pCounts, nSizeMax ); +} + +/**Function************************************************************* + + Synopsis [Computes levels for AIG with choices and white boxes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManChoiceLevel_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; + Gia_Obj_t * pNext; + int i, iBox, iTerm1, nTerms, LevelMax = 0; + if ( Gia_ObjIsTravIdCurrent( p, pObj ) ) + return; + Gia_ObjSetTravIdCurrent( p, pObj ); + if ( Gia_ObjIsCi(pObj) ) + { + if ( pManTime ) + { + iBox = Tim_ManBoxForCi( pManTime, Gia_ObjCioId(pObj) ); + if ( iBox >= 0 ) // this is not a true PI + { + iTerm1 = Tim_ManBoxInputFirst( pManTime, iBox ); + nTerms = Tim_ManBoxInputNum( pManTime, iBox ); + for ( i = 0; i < nTerms; i++ ) + { + pNext = Gia_ManCo( p, iTerm1 + i ); + Gia_ManChoiceLevel_rec( p, pNext ); + if ( LevelMax < Gia_ObjLevel(p, pNext) ) + LevelMax = Gia_ObjLevel(p, pNext); + } + LevelMax++; + } + } +// Abc_Print( 1, "%d ", pObj->Level ); + } + else if ( Gia_ObjIsCo(pObj) ) + { + pNext = Gia_ObjFanin0(pObj); + Gia_ManChoiceLevel_rec( p, pNext ); + if ( LevelMax < Gia_ObjLevel(p, pNext) ) + LevelMax = Gia_ObjLevel(p, pNext); + } + else if ( Gia_ObjIsAnd(pObj) ) + { + // get the maximum level of the two fanins + pNext = Gia_ObjFanin0(pObj); + Gia_ManChoiceLevel_rec( p, pNext ); + if ( LevelMax < Gia_ObjLevel(p, pNext) ) + LevelMax = Gia_ObjLevel(p, pNext); + pNext = Gia_ObjFanin1(pObj); + Gia_ManChoiceLevel_rec( p, pNext ); + if ( LevelMax < Gia_ObjLevel(p, pNext) ) + LevelMax = Gia_ObjLevel(p, pNext); + LevelMax++; + + // get the level of the nodes in the choice node + if ( (pNext = Gia_ObjSiblObj(p, Gia_ObjId(p, pObj))) ) + { + Gia_ManChoiceLevel_rec( p, pNext ); + if ( LevelMax < Gia_ObjLevel(p, pNext) ) + LevelMax = Gia_ObjLevel(p, pNext); + } + } + else if ( !Gia_ObjIsConst0(pObj) ) + assert( 0 ); + Gia_ObjSetLevel( p, pObj, LevelMax ); +} +int Gia_ManChoiceLevel( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, LevelMax = 0; +// assert( Gia_ManRegNum(p) == 0 ); + Gia_ManCleanLevels( p, Gia_ManObjNum(p) ); + Gia_ManIncrementTravId( p ); + Gia_ManForEachCo( p, pObj, i ) + { + Gia_ManChoiceLevel_rec( p, pObj ); + if ( LevelMax < Gia_ObjLevel(p, pObj) ) + LevelMax = Gia_ObjLevel(p, pObj); + } + // account for dangling boxes + Gia_ManForEachCi( p, pObj, i ) + { + Gia_ManChoiceLevel_rec( p, pObj ); + if ( LevelMax < Gia_ObjLevel(p, pObj) ) + LevelMax = Gia_ObjLevel(p, pObj); +// Abc_Print( 1, "%d ", Gia_ObjLevel(p, pObj) ); + } +// Abc_Print( 1, "\n" ); + Gia_ManForEachAnd( p, pObj, i ) + assert( Gia_ObjLevel(p, pObj) > 0 ); +// printf( "Max level %d\n", LevelMax ); + return LevelMax; +} + + +/**Function************************************************************* + + Synopsis [Checks integrity of choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void If_ManCheckChoices_rec( If_Man_t * pIfMan, If_Obj_t * pIfObj ) +{ + if ( !pIfObj || pIfObj->Type != IF_AND || pIfObj->fDriver ) + return; + pIfObj->fDriver = 1; + If_ManCheckChoices_rec( pIfMan, If_ObjFanin0(pIfObj) ); + If_ManCheckChoices_rec( pIfMan, If_ObjFanin1(pIfObj) ); + If_ManCheckChoices_rec( pIfMan, pIfObj->pEquiv ); +} +void If_ManCheckChoices( If_Man_t * pIfMan ) +{ + If_Obj_t * pIfObj; + int i, fFound = 0; + If_ManForEachObj( pIfMan, pIfObj, i ) + pIfObj->fDriver = 0; + If_ManForEachCo( pIfMan, pIfObj, i ) + If_ManCheckChoices_rec( pIfMan, If_ObjFanin0(pIfObj) ); + If_ManForEachNode( pIfMan, pIfObj, i ) + if ( !pIfObj->fDriver ) + printf( "Object %d is dangling.\n", i ), fFound = 1; + if ( !fFound ) + printf( "There are no dangling objects.\n" ); + If_ManForEachObj( pIfMan, pIfObj, i ) + pIfObj->fDriver = 0; +} + + +/**Function************************************************************* + + Synopsis [Converts GIA into IF manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline If_Obj_t * If_ManFanin0Copy( If_Man_t * pIfMan, Gia_Obj_t * pObj ) { return If_NotCond( If_ManObj(pIfMan, Gia_ObjValue(Gia_ObjFanin0(pObj))), Gia_ObjFaninC0(pObj) ); } +static inline If_Obj_t * If_ManFanin1Copy( If_Man_t * pIfMan, Gia_Obj_t * pObj ) { return If_NotCond( If_ManObj(pIfMan, Gia_ObjValue(Gia_ObjFanin1(pObj))), Gia_ObjFaninC1(pObj) ); } +If_Man_t * Gia_ManToIf( Gia_Man_t * p, If_Par_t * pPars ) +{ + If_Man_t * pIfMan; + If_Obj_t * pIfObj = NULL; + Gia_Obj_t * pObj; + int i; + // create levels with choices + Gia_ManChoiceLevel( p ); + // mark representative nodes + if ( Gia_ManHasChoices(p) ) + Gia_ManMarkFanoutDrivers( p ); + // start the mapping manager and set its parameters + pIfMan = If_ManStart( pPars ); + pIfMan->pName = Abc_UtilStrsav( Gia_ManName(p) ); + // print warning about excessive memory usage + if ( 1.0 * Gia_ManObjNum(p) * pIfMan->nObjBytes / (1<<30) > 1.0 ) + printf( "Warning: The mapper will allocate %.1f GB for to represent the subject graph with %d AIG nodes.\n", + 1.0 * Gia_ManObjNum(p) * pIfMan->nObjBytes / (1<<30), Gia_ManObjNum(p) ); + // load the AIG into the mapper + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = If_ObjId( If_ManConst1(pIfMan) ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + pIfObj = If_ManCreateAnd( pIfMan, If_ManFanin0Copy(pIfMan, pObj), If_ManFanin1Copy(pIfMan, pObj) ); + else if ( Gia_ObjIsCi(pObj) ) + { + pIfObj = If_ManCreateCi( pIfMan ); + If_ObjSetLevel( pIfObj, Gia_ObjLevel(p, pObj) ); +// Abc_Print( 1, "pi%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) ); + if ( pIfMan->nLevelMax < (int)pIfObj->Level ) + pIfMan->nLevelMax = (int)pIfObj->Level; + } + else if ( Gia_ObjIsCo(pObj) ) + { + pIfObj = If_ManCreateCo( pIfMan, If_NotCond( If_ManFanin0Copy(pIfMan, pObj), Gia_ObjIsConst0(Gia_ObjFanin0(pObj))) ); +// Abc_Print( 1, "po%d=%d\n ", If_ObjId(pIfObj), If_ObjLevel(pIfObj) ); + } + else assert( 0 ); + assert( i == If_ObjId(pIfObj) ); + Gia_ObjSetValue( pObj, If_ObjId(pIfObj) ); + // set up the choice node + if ( Gia_ObjSibl(p, i) && pObj->fMark0 ) + { + Gia_Obj_t * pSibl, * pPrev; + for ( pPrev = pObj, pSibl = Gia_ObjSiblObj(p, i); pSibl; pPrev = pSibl, pSibl = Gia_ObjSiblObj(p, Gia_ObjId(p, pSibl)) ) + If_ObjSetChoice( If_ManObj(pIfMan, Gia_ObjValue(pPrev)), If_ManObj(pIfMan, Gia_ObjValue(pSibl)) ); + If_ManCreateChoice( pIfMan, If_ManObj(pIfMan, Gia_ObjValue(pObj)) ); + pPars->fExpRed = 0; + } +// assert( If_ObjLevel(pIfObj) == Gia_ObjLevel(pNode) ); + } + if ( Gia_ManHasChoices(p) ) + Gia_ManCleanMark0( p ); + //If_ManCheckChoices( pIfMan ); + return pIfMan; +} + +/**Function************************************************************* + + Synopsis [Rebuilds GIA from mini AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManBuildFromMiniInt( Gia_Man_t * pNew, Vec_Int_t * vLeaves, Vec_Int_t * vAig, int fHash ) +{ + assert( Vec_IntSize(vAig) > 0 ); + assert( Vec_IntEntryLast(vAig) < 2 ); + if ( Vec_IntSize(vAig) == 1 ) // const + return Vec_IntEntry(vAig, 0); + if ( Vec_IntSize(vAig) == 2 ) // variable + { + assert( Vec_IntEntry(vAig, 0) == 0 ); + assert( Vec_IntSize(vLeaves) == 1 ); + return Abc_LitNotCond( Vec_IntEntry(vLeaves, 0), Vec_IntEntry(vAig, 1) ); + } + else + { + int nLeaves = Vec_IntSize(vLeaves); + int i, iVar0, iVar1, iLit0, iLit1, iLit = 0; + assert( Vec_IntSize(vAig) & 1 ); + Vec_IntForEachEntryDouble( vAig, iLit0, iLit1, i ) + { + iVar0 = Abc_Lit2Var( iLit0 ); + iVar1 = Abc_Lit2Var( iLit1 ); + iLit0 = Abc_LitNotCond( iVar0 < nLeaves ? Vec_IntEntry(vLeaves, iVar0) : Vec_IntEntry(vAig, iVar0 - nLeaves), Abc_LitIsCompl(iLit0) ); + iLit1 = Abc_LitNotCond( iVar1 < nLeaves ? Vec_IntEntry(vLeaves, iVar1) : Vec_IntEntry(vAig, iVar1 - nLeaves), Abc_LitIsCompl(iLit1) ); + if ( fHash ) + iLit = Gia_ManHashAnd( pNew, iLit0, iLit1 ); + else if ( iLit0 == iLit1 ) + iLit = iLit0; + else + iLit = Gia_ManAppendAnd( pNew, iLit0, iLit1 ); + assert( (i & 1) == 0 ); + Vec_IntWriteEntry( vAig, Abc_Lit2Var(i), iLit ); // overwriting entries + } + assert( i == Vec_IntSize(vAig) - 1 ); + iLit = Abc_LitNotCond( iLit, Vec_IntEntry(vAig, i) ); + Vec_IntClear( vAig ); // useless + return iLit; + } +} +int Gia_ManBuildFromMini( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Cut_t * pCut, Vec_Int_t * vLeaves, Vec_Int_t * vAig, int fHash, int fUseDsd ) +{ + if ( fUseDsd ) + If_CutDsdBalanceEval( pIfMan, pCut, vAig ); + else + If_CutSopBalanceEval( pIfMan, pCut, vAig ); + return Gia_ManBuildFromMiniInt( pNew, vLeaves, vAig, fHash ); +} + +/**Function************************************************************* + + Synopsis [Converts IF into GIA manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManFromIfAig_rec( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Obj_t * pIfObj ) +{ + int iLit0, iLit1; + if ( pIfObj->iCopy ) + return pIfObj->iCopy; + iLit0 = Gia_ManFromIfAig_rec( pNew, pIfMan, pIfObj->pFanin0 ); + iLit1 = Gia_ManFromIfAig_rec( pNew, pIfMan, pIfObj->pFanin1 ); + iLit0 = Abc_LitNotCond( iLit0, pIfObj->fCompl0 ); + iLit1 = Abc_LitNotCond( iLit1, pIfObj->fCompl1 ); + pIfObj->iCopy = Gia_ManHashAnd( pNew, iLit0, iLit1 ); + return pIfObj->iCopy; +} +Gia_Man_t * Gia_ManFromIfAig( If_Man_t * pIfMan ) +{ + int fHash = 0; + Gia_Man_t * pNew, * pTemp; + If_Obj_t * pIfObj, * pIfLeaf; + If_Cut_t * pCutBest; + Vec_Int_t * vLeaves; + Vec_Int_t * vAig; + int i, k; + assert( pIfMan->pPars->pLutStruct == NULL ); + assert( pIfMan->pPars->fDelayOpt || pIfMan->pPars->fDsdBalance || pIfMan->pPars->fUserRecLib || pIfMan->pPars->fUserSesLib ); + // create new manager + pNew = Gia_ManStart( If_ManObjNum(pIfMan) ); + Gia_ManHashAlloc( pNew ); + // iterate through nodes used in the mapping + vAig = Vec_IntAlloc( 1 << 16 ); + vLeaves = Vec_IntAlloc( 16 ); +// If_ManForEachObj( pIfMan, pIfObj, i ) +// pIfObj->iCopy = 0; + If_ManForEachObj( pIfMan, pIfObj, i ) + { + if ( pIfObj->nRefs == 0 && !If_ObjIsTerm(pIfObj) ) + continue; + if ( If_ObjIsAnd(pIfObj) ) + { + pCutBest = If_ObjCutBest( pIfObj ); + // if the cut does not offer delay improvement +// if ( (int)pIfObj->Level <= (int)pCutBest->Delay ) +// { +// Gia_ManFromIfAig_rec( pNew, pIfMan, pIfObj ); +// continue; +// } + // collect leaves of the best cut + Vec_IntClear( vLeaves ); + If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, k ) + Vec_IntPush( vLeaves, pIfLeaf->iCopy ); + // get the functionality + if ( pIfMan->pPars->fDelayOpt ) + pIfObj->iCopy = Gia_ManBuildFromMini( pNew, pIfMan, pCutBest, vLeaves, vAig, fHash, 0 ); + else if ( pIfMan->pPars->fDsdBalance ) + pIfObj->iCopy = Gia_ManBuildFromMini( pNew, pIfMan, pCutBest, vLeaves, vAig, fHash, 1 ); + else if ( pIfMan->pPars->fUserRecLib ) + pIfObj->iCopy = Abc_RecToGia3( pNew, pIfMan, pCutBest, vLeaves, fHash ); + else assert( 0 ); + } + else if ( If_ObjIsCi(pIfObj) ) + pIfObj->iCopy = Gia_ManAppendCi(pNew); + else if ( If_ObjIsCo(pIfObj) ) + pIfObj->iCopy = Gia_ManAppendCo( pNew, Abc_LitNotCond(If_ObjFanin0(pIfObj)->iCopy, If_ObjFaninC0(pIfObj)) ); + else if ( If_ObjIsConst1(pIfObj) ) + pIfObj->iCopy = 1; + else assert( 0 ); + } + Vec_IntFree( vAig ); + Vec_IntFree( vLeaves ); + pNew = Gia_ManRehash( pTemp = pNew, 0 ); + Gia_ManStop( pTemp ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Write mapping for LUT with given fanins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManFromIfLogicCreateLut( Gia_Man_t * pNew, word * pRes, Vec_Int_t * vLeaves, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2 ) +{ + int i, iLit, iObjLit1; + iObjLit1 = Kit_TruthToGia( pNew, (unsigned *)pRes, Vec_IntSize(vLeaves), vCover, vLeaves, 0 ); + // do not create LUT in the simple case + if ( Abc_Lit2Var(iObjLit1) == 0 ) + return iObjLit1; + Vec_IntForEachEntry( vLeaves, iLit, i ) + if ( Abc_Lit2Var(iObjLit1) == Abc_Lit2Var(iLit) ) + return iObjLit1; + // write mapping + Vec_IntSetEntry( vMapping, Abc_Lit2Var(iObjLit1), Vec_IntSize(vMapping2) ); + Vec_IntPush( vMapping2, Vec_IntSize(vLeaves) ); +// Vec_IntForEachEntry( vLeaves, iLit, i ) +// assert( Abc_Lit2Var(iLit) < Abc_Lit2Var(iObjLit1) ); + Vec_IntForEachEntry( vLeaves, iLit, i ) + Vec_IntPush( vMapping2, Abc_Lit2Var(iLit) ); + Vec_IntPush( vMapping2, Abc_Lit2Var(iObjLit1) ); + return iObjLit1; +} + +/**Function************************************************************* + + Synopsis [Write mapping for LUT with given fanins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManFromIfLogicCreateLutSpecial( Gia_Man_t * pNew, word * pRes, Vec_Int_t * vLeaves, Vec_Int_t * vLeavesTemp, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2, Vec_Int_t * vPacking ) +{ + word z = If_CutPerformDerive07( NULL, (unsigned *)pRes, Vec_IntSize(vLeaves), Vec_IntSize(vLeaves), NULL ); + word Truth; + int i, iObjLit1, iObjLit2; + // create first LUT + Vec_IntClear( vLeavesTemp ); + for ( i = 0; i < 4; i++ ) + { + int v = (int)((z >> (16+(i<<2))) & 7); + if ( v == 6 && Vec_IntSize(vLeaves) == 5 ) + continue; + Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, v) ); + } + Truth = (z & 0xffff); + Truth |= (Truth << 16); + Truth |= (Truth << 32); + iObjLit1 = Gia_ManFromIfLogicCreateLut( pNew, &Truth, vLeavesTemp, vCover, vMapping, vMapping2 ); + // create second LUT + Vec_IntClear( vLeavesTemp ); + for ( i = 0; i < 4; i++ ) + { + int v = (int)((z >> (48+(i<<2))) & 7); + if ( v == 6 && Vec_IntSize(vLeaves) == 5 ) + continue; + if ( v == 7 ) + Vec_IntPush( vLeavesTemp, iObjLit1 ); + else + Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, v) ); + } + Truth = ((z >> 32) & 0xffff); + Truth |= (Truth << 16); + Truth |= (Truth << 32); + iObjLit2 = Gia_ManFromIfLogicCreateLut( pNew, &Truth, vLeavesTemp, vCover, vMapping, vMapping2 ); + // write packing + Vec_IntPush( vPacking, 2 ); + Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit1) ); + Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit2) ); + Vec_IntAddToEntry( vPacking, 0, 1 ); + return iObjLit2; +} + +/**Function************************************************************* + + Synopsis [Write the node into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManFromIfLogicNode( void * pIfMan, Gia_Man_t * pNew, int iObj, Vec_Int_t * vLeaves, Vec_Int_t * vLeavesTemp, + word * pRes, char * pStr, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2, Vec_Int_t * vPacking, int fCheck75, int fCheck44e ) +{ + int nLeaves = Vec_IntSize(vLeaves); + int i, Length, nLutLeaf, nLutLeaf2, nLutRoot, iObjLit1, iObjLit2, iObjLit3; + // workaround for the special case + if ( fCheck75 ) + pStr = "54"; + // perform special case matching for 44 + if ( fCheck44e ) + { + if ( Vec_IntSize(vLeaves) <= 4 ) + { + // create mapping + iObjLit1 = Gia_ManFromIfLogicCreateLut( pNew, pRes, vLeaves, vCover, vMapping, vMapping2 ); + // write packing + if ( !Gia_ObjIsCi(Gia_ManObj(pNew, Abc_Lit2Var(iObjLit1))) && iObjLit1 > 1 ) + { + Vec_IntPush( vPacking, 1 ); + Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit1) ); + Vec_IntAddToEntry( vPacking, 0, 1 ); + } + return iObjLit1; + } + return Gia_ManFromIfLogicCreateLutSpecial( pNew, pRes, vLeaves, vLeavesTemp, vCover, vMapping, vMapping2, vPacking ); + } + if ( ((If_Man_t *)pIfMan)->pPars->fLut6Filter && Vec_IntSize(vLeaves) == 6 ) + { + extern word If_Dec6Perform( word t, int fDerive ); + extern void If_Dec6Verify( word t, word z ); + Vec_Int_t * vLeaves2 = Vec_IntAlloc( 4 ); + word t = pRes[0]; + word z = If_Dec6Perform( t, 1 ); + //If_DecPrintConfig( z ); + If_Dec6Verify( t, z ); + + t = Abc_Tt6Stretch( z & 0xffff, 4 ); + Vec_IntClear( vLeaves2 ); + for ( i = 0; i < 4; i++ ) + Vec_IntPush( vLeaves2, Vec_IntEntry( vLeaves, (int)((z >> (16+i*4)) & 7) ) ); + iObjLit1 = Gia_ManFromIfLogicCreateLut( pNew, &t, vLeaves2, vCover, vMapping, vMapping2 ); + + t = Abc_Tt6Stretch( (z >> 32) & 0xffff, 4 ); + Vec_IntClear( vLeaves2 ); + for ( i = 0; i < 4; i++ ) + if ( ((z >> (48+i*4)) & 7) == 7 ) + Vec_IntPush( vLeaves2, iObjLit1 ); + else + Vec_IntPush( vLeaves2, Vec_IntEntry( vLeaves, (int)((z >> (48+i*4)) & 7) ) ); + iObjLit1 = Gia_ManFromIfLogicCreateLut( pNew, &t, vLeaves2, vCover, vMapping, vMapping2 ); + + Vec_IntFree( vLeaves2 ); + return iObjLit1; + } + // check if there is no LUT structures + if ( pStr == NULL ) + return Gia_ManFromIfLogicCreateLut( pNew, pRes, vLeaves, vCover, vMapping, vMapping2 ); + // quit if parameters are wrong + Length = strlen(pStr); + if ( Length != 2 && Length != 3 ) + { + printf( "Wrong LUT struct (%s)\n", pStr ); + return -1; + } + for ( i = 0; i < Length; i++ ) + if ( pStr[i] - '0' < 3 || pStr[i] - '0' > 6 ) + { + printf( "The LUT size (%d) should belong to {3,4,5,6}.\n", pStr[i] - '0' ); + return -1; + } + + nLutLeaf = pStr[0] - '0'; + nLutLeaf2 = ( Length == 3 ) ? pStr[1] - '0' : 0; + nLutRoot = pStr[Length-1] - '0'; + if ( nLeaves > nLutLeaf - 1 + (nLutLeaf2 ? nLutLeaf2 - 1 : 0) + nLutRoot ) + { + printf( "The node size (%d) is too large for the LUT structure %s.\n", nLeaves, pStr ); + return -1; + } + + // consider easy case + if ( nLeaves <= Abc_MaxInt( nLutLeaf2, Abc_MaxInt(nLutLeaf, nLutRoot) ) ) + { + // create mapping + iObjLit1 = Gia_ManFromIfLogicCreateLut( pNew, pRes, vLeaves, vCover, vMapping, vMapping2 ); + // write packing + if ( !Gia_ObjIsCi(Gia_ManObj(pNew, Abc_Lit2Var(iObjLit1))) && iObjLit1 > 1 ) + { + Vec_IntPush( vPacking, 1 ); + Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit1) ); + Vec_IntAddToEntry( vPacking, 0, 1 ); + } + return iObjLit1; + } + else + { + extern int If_CluMinimumBase( word * t, int * pSupp, int nVarsAll, int * pnVars ); + + static word TruthStore[16][1<<10] = {{0}}, * pTruths[16]; + word Func0, Func1, Func2; + char pLut0[32], pLut1[32], pLut2[32] = {0}; + + if ( TruthStore[0][0] == 0 ) + { + static word Truth6[6] = { + 0xAAAAAAAAAAAAAAAA, + 0xCCCCCCCCCCCCCCCC, + 0xF0F0F0F0F0F0F0F0, + 0xFF00FF00FF00FF00, + 0xFFFF0000FFFF0000, + 0xFFFFFFFF00000000 + }; + int nVarsMax = 16; + int nWordsMax = (1 << 10); + int i, k; + assert( nVarsMax <= 16 ); + for ( i = 0; i < nVarsMax; i++ ) + pTruths[i] = TruthStore[i]; + for ( i = 0; i < 6; i++ ) + for ( k = 0; k < nWordsMax; k++ ) + pTruths[i][k] = Truth6[i]; + for ( i = 6; i < nVarsMax; i++ ) + for ( k = 0; k < nWordsMax; k++ ) + pTruths[i][k] = ((k >> (i-6)) & 1) ? ~(word)0 : 0; + } + // derive truth table + if ( Kit_TruthIsConst0((unsigned *)pRes, nLeaves) || Kit_TruthIsConst1((unsigned *)pRes, nLeaves) ) + { +// fprintf( pFile, ".names %s\n %d\n", Abc_ObjName(Abc_ObjFanout0(pObj)), Kit_TruthIsConst1((unsigned *)pRes, nLeaves) ); + iObjLit1 = Abc_LitNotCond( 0, Kit_TruthIsConst1((unsigned *)pRes, nLeaves) ); + // write mapping + if ( Vec_IntEntry(vMapping, 0) == 0 ) + { + Vec_IntSetEntry( vMapping, 0, Vec_IntSize(vMapping2) ); + Vec_IntPush( vMapping2, 0 ); + Vec_IntPush( vMapping2, 0 ); + } + return iObjLit1; + } + // check for elementary truth table + for ( i = 0; i < nLeaves; i++ ) + { + if ( Kit_TruthIsEqual((unsigned *)pRes, (unsigned *)pTruths[i], nLeaves) ) + return Vec_IntEntry(vLeaves, i); + if ( Kit_TruthIsOpposite((unsigned *)pRes, (unsigned *)pTruths[i], nLeaves) ) + return Abc_LitNot(Vec_IntEntry(vLeaves, i)); + } + + // perform decomposition + if ( fCheck75 ) + { +// if ( nLeaves < 8 && If_CutPerformCheck16( p, (unsigned *)pTruth, nVars, nLeaves, "44" ) ) + if ( nLeaves < 8 && If_CluCheckExt( NULL, pRes, nLeaves, 4, 4, pLut0, pLut1, &Func0, &Func1 ) ) + { + nLutLeaf = 4; + nLutRoot = 4; + } +// if ( If_CutPerformCheck45( p, (unsigned *)pTruth, nVars, nLeaves, pStr ) ) + else if ( If_CluCheckExt( NULL, pRes, nLeaves, 5, 4, pLut0, pLut1, &Func0, &Func1 ) ) + { + nLutLeaf = 5; + nLutRoot = 4; + } +// if ( If_CutPerformCheck54( p, (unsigned *)pTruth, nVars, nLeaves, pStr ) ) + else if ( If_CluCheckExt( NULL, pRes, nLeaves, 4, 5, pLut0, pLut1, &Func0, &Func1 ) ) + { + nLutLeaf = 4; + nLutRoot = 5; + } + else + { + Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " ); + Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" ); + printf( "Node %d is not decomposable. Deriving LUT structures has failed.\n", iObj ); + return -1; + } + } + else + { + if ( Length == 2 ) + { + if ( ((If_Man_t *)pIfMan)->pPars->fEnableStructN ) + { + if ( !If_CluCheckXXExt( NULL, pRes, nLeaves, nLutLeaf, nLutRoot, pLut0, pLut1, &Func0, &Func1 ) ) + { + Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " ); + Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" ); + printf( "Node %d is not decomposable. Deriving LUT structures has failed.\n", iObj ); + return -1; + } + } + else + { + if ( !If_CluCheckExt( NULL, pRes, nLeaves, nLutLeaf, nLutRoot, pLut0, pLut1, &Func0, &Func1 ) ) + { + Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " ); + Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" ); + printf( "Node %d is not decomposable. Deriving LUT structures has failed.\n", iObj ); + return -1; + } + } + } + else + { + if ( !If_CluCheckExt3( pIfMan, pRes, nLeaves, nLutLeaf, nLutLeaf2, nLutRoot, pLut0, pLut1, pLut2, &Func0, &Func1, &Func2 ) ) + { + Extra_PrintHex( stdout, (unsigned *)pRes, nLeaves ); printf( " " ); + Kit_DsdPrintFromTruth( (unsigned*)pRes, nLeaves ); printf( "\n" ); + printf( "Node %d is not decomposable. Deriving LUT structures has failed.\n", iObj ); + return -1; + } + } + } + +/* + // write leaf node + Id = Abc2_NtkAllocObj( pNew, pLut1[0], Abc2_ObjType(pObj) ); + iObjLit1 = Abc_Var2Lit( Id, 0 ); + pObjNew = Abc2_NtkObj( pNew, Id ); + for ( i = 0; i < pLut1[0]; i++ ) + Abc2_ObjSetFaninLit( pObjNew, i, Abc2_ObjFaninCopy(pObj, pLut1[2+i]) ); + Abc2_ObjSetTruth( pObjNew, Func1 ); +*/ + // write leaf node + Vec_IntClear( vLeavesTemp ); + for ( i = 0; i < pLut1[0]; i++ ) + Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, pLut1[2+i]) ); + iObjLit1 = Gia_ManFromIfLogicCreateLut( pNew, &Func1, vLeavesTemp, vCover, vMapping, vMapping2 ); + + if ( Length == 3 && pLut2[0] > 0 ) + { + /* + Id = Abc2_NtkAllocObj( pNew, pLut2[0], Abc2_ObjType(pObj) ); + iObjLit2 = Abc_Var2Lit( Id, 0 ); + pObjNew = Abc2_NtkObj( pNew, Id ); + for ( i = 0; i < pLut2[0]; i++ ) + if ( pLut2[2+i] == nLeaves ) + Abc2_ObjSetFaninLit( pObjNew, i, iObjLit1 ); + else + Abc2_ObjSetFaninLit( pObjNew, i, Abc2_ObjFaninCopy(pObj, pLut2[2+i]) ); + Abc2_ObjSetTruth( pObjNew, Func2 ); + */ + + // write leaf node + Vec_IntClear( vLeavesTemp ); + for ( i = 0; i < pLut2[0]; i++ ) + if ( pLut2[2+i] == nLeaves ) + Vec_IntPush( vLeavesTemp, iObjLit1 ); + else + Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, pLut2[2+i]) ); + iObjLit2 = Gia_ManFromIfLogicCreateLut( pNew, &Func2, vLeavesTemp, vCover, vMapping, vMapping2 ); + + // write packing + Vec_IntPush( vPacking, 3 ); + Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit1) ); + Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit2) ); + } + else + { + // write packing + Vec_IntPush( vPacking, 2 ); + Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit1) ); + iObjLit2 = -1; + } +/* + // write root node + Id = Abc2_NtkAllocObj( pNew, pLut0[0], Abc2_ObjType(pObj) ); + iObjLit3 = Abc_Var2Lit( Id, 0 ); + pObjNew = Abc2_NtkObj( pNew, Id ); + for ( i = 0; i < pLut0[0]; i++ ) + if ( pLut0[2+i] == nLeaves ) + Abc2_ObjSetFaninLit( pObjNew, i, iObjLit1 ); + else if ( pLut0[2+i] == nLeaves+1 ) + Abc2_ObjSetFaninLit( pObjNew, i, iObjLit2 ); + else + Abc2_ObjSetFaninLit( pObjNew, i, Abc2_ObjFaninCopy(pObj, pLut0[2+i]) ); + Abc2_ObjSetTruth( pObjNew, Func0 ); + Abc2_ObjSetCopy( pObj, iObjLit3 ); +*/ + // write root node + Vec_IntClear( vLeavesTemp ); + for ( i = 0; i < pLut0[0]; i++ ) + if ( pLut0[2+i] == nLeaves ) + Vec_IntPush( vLeavesTemp, iObjLit1 ); + else if ( pLut0[2+i] == nLeaves+1 ) + Vec_IntPush( vLeavesTemp, iObjLit2 ); + else + Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, pLut0[2+i]) ); + iObjLit3 = Gia_ManFromIfLogicCreateLut( pNew, &Func0, vLeavesTemp, vCover, vMapping, vMapping2 ); + + // write packing + Vec_IntPush( vPacking, Abc_Lit2Var(iObjLit3) ); + Vec_IntAddToEntry( vPacking, 0, 1 ); + } + return iObjLit3; +} + +/**Function************************************************************* + + Synopsis [Implements delay-driven decomposition of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManFromIfLogicHop( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Cut_t * pCutBest, Vec_Int_t * vLeaves, Vec_Int_t * vLeavesTemp, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2 ) +{ + word * pTruth = If_CutTruthW(pIfMan, pCutBest); + unsigned char decompArray[92]; + int val; + + assert( pCutBest->nLeaves > pIfMan->pPars->nLutDecSize ); + + unsigned delayProfile = pCutBest->decDelay; + val = acd_decompose( pTruth, pCutBest->nLeaves, pIfMan->pPars->nLutDecSize, &(delayProfile), decompArray ); + assert( val == 0 ); + + // convert the LUT-structure into a set of logic nodes in Gia_Man_t + unsigned char bytes_check = decompArray[0]; + assert( bytes_check <= 92 ); + + int byte_p = 2; + unsigned char i, j, k, num_fanins, num_words, num_bytes; + int iObjLits[5]; + int fanin; + word *tt; + + for ( i = 0; i < decompArray[1]; ++i ) + { + num_fanins = decompArray[byte_p++]; + Vec_IntClear( vLeavesTemp ); + for ( j = 0; j < num_fanins; ++j ) + { + fanin = (int)decompArray[byte_p++]; + if ( fanin < If_CutLeaveNum(pCutBest) ) + { + Vec_IntPush( vLeavesTemp, Vec_IntEntry(vLeaves, fanin) ); + } + else + { + Vec_IntPush( vLeavesTemp, iObjLits[fanin - If_CutLeaveNum(pCutBest)] ); + } + } + + /* extract the truth table */ + tt = pIfMan->puTempW; + num_words = ( num_fanins <= 6 ) ? 1 : ( 1 << ( num_fanins - 6 ) ); + num_bytes = ( num_fanins <= 3 ) ? 1 : ( 1 << ( Abc_MinInt( (int)num_fanins, 6 ) - 3 ) ); + for ( j = 0; j < num_words; ++j ) + { + tt[j] = 0; + for ( k = 0; k < num_bytes; ++k ) + { + tt[j] |= ( (word)(decompArray[byte_p++]) ) << ( k << 3 ); + } + } + + /* extend truth table if size < 5 */ + assert( num_fanins != 1 ); + if ( num_fanins == 2 ) + { + tt[0] |= tt[0] << 4; + } + while ( num_bytes < 4 ) + { + tt[0] |= tt[0] << ( num_bytes << 3 ); + num_bytes <<= 1; + } + + iObjLits[i] = Gia_ManFromIfLogicCreateLut( pNew, tt, vLeavesTemp, vCover, vMapping, vMapping2 ); + } + + /* check correct read */ + assert( byte_p == decompArray[0] ); + + return iObjLits[i-1]; +} + +/**Function************************************************************* + + Synopsis [Recursively derives the local AIG for the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManNodeIfToGia_rec( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited, int fHash ) +{ + If_Cut_t * pCut; + If_Obj_t * pTemp; + int iFunc, iFunc0, iFunc1; + // get the best cut + pCut = If_ObjCutBest(pIfObj); + // if the cut is visited, return the result + if ( If_CutDataInt(pCut) ) + return If_CutDataInt(pCut); + // mark the node as visited + Vec_PtrPush( vVisited, pCut ); + // insert the worst case + If_CutSetDataInt( pCut, ~0 ); + // skip in case of primary input + if ( If_ObjIsCi(pIfObj) ) + return If_CutDataInt(pCut); + // compute the functions of the children + for ( pTemp = pIfObj; pTemp; pTemp = pTemp->pEquiv ) + { + iFunc0 = Gia_ManNodeIfToGia_rec( pNew, pIfMan, pTemp->pFanin0, vVisited, fHash ); + if ( iFunc0 == ~0 ) + continue; + iFunc1 = Gia_ManNodeIfToGia_rec( pNew, pIfMan, pTemp->pFanin1, vVisited, fHash ); + if ( iFunc1 == ~0 ) + continue; + // both branches are solved + if ( fHash ) + iFunc = Gia_ManHashAnd( pNew, Abc_LitNotCond(iFunc0, pTemp->fCompl0), Abc_LitNotCond(iFunc1, pTemp->fCompl1) ); + else + iFunc = Gia_ManAppendAnd( pNew, Abc_LitNotCond(iFunc0, pTemp->fCompl0), Abc_LitNotCond(iFunc1, pTemp->fCompl1) ); + if ( pTemp->fPhase != pIfObj->fPhase ) + iFunc = Abc_LitNot(iFunc); + If_CutSetDataInt( pCut, iFunc ); + break; + } + return If_CutDataInt(pCut); +} +int Gia_ManNodeIfToGia( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Int_t * vLeaves, int fHash ) +{ + If_Cut_t * pCut; + If_Obj_t * pLeaf; + int i, iRes; + // get the best cut + pCut = If_ObjCutBest(pIfObj); + assert( pCut->nLeaves > 1 ); + // set the leaf variables + If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) + If_CutSetDataInt( If_ObjCutBest(pLeaf), Vec_IntEntry(vLeaves, i) ); + // recursively compute the function while collecting visited cuts + Vec_PtrClear( pIfMan->vTemp ); + iRes = Gia_ManNodeIfToGia_rec( pNew, pIfMan, pIfObj, pIfMan->vTemp, fHash ); + if ( iRes == ~0 ) + { + Abc_Print( -1, "Gia_ManNodeIfToGia(): Computing local AIG has failed.\n" ); + return ~0; + } + // clean the cuts + If_CutForEachLeaf( pIfMan, pCut, pLeaf, i ) + If_CutSetDataInt( If_ObjCutBest(pLeaf), 0 ); + Vec_PtrForEachEntry( If_Cut_t *, pIfMan->vTemp, pCut, i ) + If_CutSetDataInt( pCut, 0 ); + return iRes; +} + +/**Function************************************************************* + + Synopsis [Converts IF into GIA manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManFromIfLogicFindLut( If_Man_t * pIfMan, Gia_Man_t * pNew, If_Cut_t * pCutBest, sat_solver * pSat, Vec_Int_t * vLeaves, Vec_Int_t * vLits, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2, Vec_Int_t * vPacking ) +{ + word uBound, uFree; + int nLutSize = (int)(pIfMan->pPars->pLutStruct[0] - '0'); + int nVarsF = 0, pVarsF[IF_MAX_FUNC_LUTSIZE]; + int nVarsB = 0, pVarsB[IF_MAX_FUNC_LUTSIZE]; + int nVarsS = 0, pVarsS[IF_MAX_FUNC_LUTSIZE]; + unsigned uSetNew, uSetOld; + int RetValue, RetValue2, k; + char * pPerm; + if ( Vec_IntSize(vLeaves) <= nLutSize ) + { + RetValue = Gia_ManFromIfLogicCreateLut( pNew, If_CutTruthW(pIfMan, pCutBest), vLeaves, vCover, vMapping, vMapping2 ); + // write packing + if ( !Gia_ObjIsCi(Gia_ManObj(pNew, Abc_Lit2Var(RetValue))) && RetValue > 1 ) + { + Vec_IntPush( vPacking, 1 ); + Vec_IntPush( vPacking, Abc_Lit2Var(RetValue) ); + Vec_IntAddToEntry( vPacking, 0, 1 ); + } + return RetValue; + } + assert( If_DsdManSuppSize(pIfMan->pIfDsdMan, If_CutDsdLit(pIfMan, pCutBest)) == (int)pCutBest->nLeaves ); + // find the bound set + if ( pIfMan->pPars->fDelayOptLut ) + uSetOld = pCutBest->uMaskFunc; + else + uSetOld = If_DsdManCheckXY( pIfMan->pIfDsdMan, If_CutDsdLit(pIfMan, pCutBest), nLutSize, 1, 0, 1, 0 ); + // remap bound set + uSetNew = 0; + pPerm = If_CutDsdPerm( pIfMan, pCutBest ); + for ( k = 0; k < If_CutLeaveNum(pCutBest); k++ ) + { + int iVar = Abc_Lit2Var((int)pPerm[k]); + int Value = ((uSetOld >> (k << 1)) & 3); + if ( Value == 1 ) + uSetNew |= (1 << (2*iVar)); + else if ( Value == 3 ) + uSetNew |= (3 << (2*iVar)); + else assert( Value == 0 ); + } + RetValue = If_ManSatCheckXY( pSat, nLutSize, If_CutTruthW(pIfMan, pCutBest), pCutBest->nLeaves, uSetNew, &uBound, &uFree, vLits ); + assert( RetValue ); + // collect variables + for ( k = 0; k < If_CutLeaveNum(pCutBest); k++ ) + { + int Value = ((uSetNew >> (k << 1)) & 3); + if ( Value == 0 ) + pVarsF[nVarsF++] = k; + else if ( Value == 1 ) + pVarsB[nVarsB++] = k; + else if ( Value == 3 ) + pVarsS[nVarsS++] = k; + else assert( Value == 0 ); + } + // collect bound set variables + Vec_IntClear( vLits ); + for ( k = 0; k < nVarsS; k++ ) + Vec_IntPush( vLits, Vec_IntEntry(vLeaves, pVarsS[k]) ); + for ( k = 0; k < nVarsB; k++ ) + Vec_IntPush( vLits, Vec_IntEntry(vLeaves, pVarsB[k]) ); + RetValue = Gia_ManFromIfLogicCreateLut( pNew, &uBound, vLits, vCover, vMapping, vMapping2 ); + // collecct free set variables + Vec_IntClear( vLits ); + Vec_IntPush( vLits, RetValue ); + for ( k = 0; k < nVarsS; k++ ) + Vec_IntPush( vLits, Vec_IntEntry(vLeaves, pVarsS[k]) ); + for ( k = 0; k < nVarsF; k++ ) + Vec_IntPush( vLits, Vec_IntEntry(vLeaves, pVarsF[k]) ); + // add packing + RetValue2 = Gia_ManFromIfLogicCreateLut( pNew, &uFree, vLits, vCover, vMapping, vMapping2 ); + // write packing + Vec_IntPush( vPacking, 2 ); + Vec_IntPush( vPacking, Abc_Lit2Var(RetValue) ); + Vec_IntPush( vPacking, Abc_Lit2Var(RetValue2) ); + Vec_IntAddToEntry( vPacking, 0, 1 ); + return RetValue2; +} + +/**Function************************************************************* + + Synopsis [Converts IF into GIA manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManFromIfGetConfig( Vec_Int_t * vConfigs, If_Man_t * pIfMan, If_Cut_t * pCutBest, int iLit, Vec_Str_t * vConfigsStr ) +{ + If_Obj_t * pIfObj = NULL; + word * pPerm = If_DsdManGetFuncConfig( pIfMan->pIfDsdMan, If_CutDsdLit(pIfMan, pCutBest) ); // cell input -> DSD input + char * pCutPerm = If_CutDsdPerm( pIfMan, pCutBest ); // DSD input -> cut input + word * pArray; int v, i, Lit, Var; + int nVarNum = If_DsdManVarNum(pIfMan->pIfDsdMan); + int nTtBitNum = If_DsdManTtBitNum(pIfMan->pIfDsdMan); + int nPermBitNum = If_DsdManPermBitNum(pIfMan->pIfDsdMan); + int nPermBitOne = nPermBitNum / nVarNum; + // prepare storage + int nIntNum = Vec_IntEntry( vConfigs, 1 ); + for ( i = 0; i < nIntNum; i++ ) + Vec_IntPush( vConfigs, 0 ); + pArray = (word *)Vec_IntEntryP( vConfigs, Vec_IntSize(vConfigs) - nIntNum ); + assert( nPermBitNum % nVarNum == 0 ); + // set truth table bits + for ( i = 0; i < nTtBitNum; i++ ) + if ( Abc_TtGetBit(pPerm + 1, i) ) + Abc_TtSetBit( pArray, i ); + // set permutation bits + for ( v = 0; v < nVarNum; v++ ) + { + // get DSD variable + Var = ((pPerm[0] >> (v * 4)) & 0xF); + assert( Var < (int)pCutBest->nLeaves ); + // get AIG literal + Lit = (int)pCutPerm[Var]; + assert( Abc_Lit2Var(Lit) < (int)pCutBest->nLeaves ); + // complement if polarity has changed + pIfObj = If_ManObj( pIfMan, pCutBest->pLeaves[Abc_Lit2Var(Lit)] ); + Lit = Abc_LitNotCond( Lit, Abc_LitIsCompl(pIfObj->iCopy) ); + // create config literal + for ( i = 0; i < nPermBitOne; i++ ) + if ( (Lit >> i) & 1 ) + Abc_TtSetBit( pArray, nTtBitNum + v * nPermBitOne + i ); + } + // remember complementation + assert( nTtBitNum + nPermBitNum < 32 * nIntNum ); + if ( Abc_LitIsCompl(If_CutDsdLit(pIfMan, pCutBest)) ^ pCutBest->fCompl ^ Abc_LitIsCompl(iLit) ) + Abc_TtSetBit( pArray, nTtBitNum + nPermBitNum ); + // update count + Vec_IntAddToEntry( vConfigs, 0, 1 ); + // write configs + if ( vConfigsStr ) + { + Vec_StrPrintF( vConfigsStr, "%d", Abc_Lit2Var(iLit) ); + Vec_StrPush( vConfigsStr, ' ' ); + for ( i = 0; i < nTtBitNum; i++ ) + Vec_StrPush( vConfigsStr, (char)(Abc_TtGetBit(pArray, i) ? '1' : '0') ); + Vec_StrPush( vConfigsStr, ' ' ); + Vec_StrPush( vConfigsStr, ' ' ); + for ( v = 0; v < nVarNum; v++ ) + { + for ( i = 0; i < nPermBitOne; i++ ) + { + Vec_StrPush( vConfigsStr, (char)(Abc_TtGetBit(pArray, nTtBitNum + v * nPermBitOne + i) ? '1' : '0') ); + if ( i == 0 ) + Vec_StrPush( vConfigsStr, ' ' ); + } + Vec_StrPush( vConfigsStr, ' ' ); + Vec_StrPush( vConfigsStr, ' ' ); + } + Vec_StrPush( vConfigsStr, (char)(Abc_TtGetBit(pArray, nTtBitNum + nPermBitNum) ? '1' : '0') ); + Vec_StrPush( vConfigsStr, '\n' ); + } +} +int Gia_ManFromIfLogicFindCell( If_Man_t * pIfMan, Gia_Man_t * pNew, Gia_Man_t * pTemp, If_Cut_t * pCutBest, Ifn_Ntk_t * pNtkCell, int nLutMax, Vec_Int_t * vLeaves, Vec_Int_t * vLits, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2, Vec_Int_t * vConfigs ) +{ + int iLit; + assert( 0 ); + if ( Vec_IntSize(vLeaves) <= nLutMax ) + iLit = Gia_ManFromIfLogicCreateLut( pNew, If_CutTruthW(pIfMan, pCutBest), vLeaves, vCover, vMapping, vMapping2 ); + else + { + Gia_Obj_t * pObj; + int i, Id, iLitTemp; + // extract variable permutation + //char * pCutPerm = If_CutDsdPerm( pIfMan, pCutBest ); // DSD input -> cut input + word * pPerm = If_DsdManGetFuncConfig( pIfMan->pIfDsdMan, If_CutDsdLit(pIfMan, pCutBest) ); // cell input -> DSD input + //int nBits = If_DsdManTtBitNum( pIfMan->pIfDsdMan ); + // use config bits to generate the network + iLit = If_ManSatDeriveGiaFromBits( pTemp, pNtkCell, pPerm + 1, vLeaves, vCover ); + // copy GIA back into the manager + Vec_IntFillExtra( &pTemp->vCopies, Gia_ManObjNum(pTemp), -1 ); + Gia_ObjSetCopyArray( pTemp, 0, 0 ); + Vec_IntForEachEntry( vLeaves, iLitTemp, i ) + Gia_ObjSetCopyArray( pTemp, Gia_ManCiIdToId(pTemp, i), iLitTemp ); + // collect nodes + Gia_ManIncrementTravId( pTemp ); + Id = Abc_Lit2Var( iLit ); + Gia_ManCollectAnds( pTemp, &Id, 1, vCover, NULL ); + Vec_IntPrint( vCover ); + Gia_ManForEachObjVec( vCover, pTemp, pObj, i ) + Gia_ObjPrint( pTemp, pObj ); + // copy GIA + Gia_ManForEachObjVec( vCover, pTemp, pObj, i ) + { + iLit = Gia_ManAppendAnd( pNew, Gia_ObjFanin0CopyArray(pTemp, pObj), Gia_ObjFanin1CopyArray(pTemp, pObj) ); + Gia_ObjSetCopyArray( pTemp, Gia_ObjId(pTemp, pObj), iLit ); + } + iLit = Abc_LitNotCond( Gia_ObjCopyArray(pTemp, Id), Abc_LitIsCompl(iLit) ); + } + // write packing +// if ( vConfigs && !Gia_ObjIsCi(Gia_ManObj(pNew, Abc_Lit2Var(iLit))) && iLit > 1 ) +// Gia_ManFromIfGetConfig( vConfigs, pIfMan, pCutBest ); + return iLit; +} + + +/**Function************************************************************* + + Synopsis [Converts IF into GIA manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManFromIfLogicCofVars( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Cut_t * pCutBest, Vec_Int_t * vLeaves, Vec_Int_t * vLeaves2, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2 ) +{ + word pTruthCof[128], * pTruth = If_CutTruthW(pIfMan, pCutBest); + int pVarsNew[16], nVarsNew, iLitCofs[3]; + int nLeaves = pCutBest->nLeaves; + int nWords = Abc_Truth6WordNum(nLeaves); + int truthId = Abc_Lit2Var(pCutBest->iCutFunc); + int c, iVar = Vec_StrEntry(pIfMan->vTtVars[nLeaves], truthId), iTemp, iTopLit; + int k, RetValue = -1; + assert( iVar >= 0 && iVar < nLeaves && pIfMan->pPars->nLutSize <= 13 ); + for ( c = 0; c < 2; c++ ) + { + for ( k = 0; k < nLeaves; k++ ) + pVarsNew[k] = k; + if ( c ) + Abc_TtCofactor1p( pTruthCof, pTruth, nWords, iVar ); + else + Abc_TtCofactor0p( pTruthCof, pTruth, nWords, iVar ); + nVarsNew = Abc_TtMinBase( pTruthCof, pVarsNew, pCutBest->nLeaves, Abc_MaxInt(6, pCutBest->nLeaves) ); + // derive LUT + Vec_IntClear( vLeaves2 ); + for ( k = 0; k < nVarsNew; k++ ) + Vec_IntPush( vLeaves2, Vec_IntEntry(vLeaves, pVarsNew[k]) ); + iLitCofs[c] = Kit_TruthToGia( pNew, (unsigned *)pTruthCof, nVarsNew, vCover, vLeaves2, 0 ); + if ( nVarsNew < 2 ) + continue; + // create mapping + assert( Gia_ObjIsAnd(Gia_ManObj(pNew, Abc_Lit2Var(iLitCofs[c]))) ); + Vec_IntSetEntry( vMapping, Abc_Lit2Var(iLitCofs[c]), Vec_IntSize(vMapping2) ); + Vec_IntPush( vMapping2, Vec_IntSize(vLeaves2) ); + Vec_IntForEachEntry( vLeaves2, iTemp, k ) + Vec_IntPush( vMapping2, Abc_Lit2Var(iTemp) ); + Vec_IntPush( vMapping2, Abc_Lit2Var(iLitCofs[c]) ); + } + iLitCofs[2] = Vec_IntEntry(vLeaves, iVar); + // derive MUX + if ( iLitCofs[0] > 1 && iLitCofs[1] > 1 ) + { + pTruthCof[0] = ABC_CONST(0xCACACACACACACACA); + Vec_IntClear( vLeaves2 ); + Vec_IntPush( vLeaves2, iLitCofs[0] ); + Vec_IntPush( vLeaves2, iLitCofs[1] ); + Vec_IntPush( vLeaves2, iLitCofs[2] ); + RetValue = Kit_TruthToGia( pNew, (unsigned *)pTruthCof, Vec_IntSize(vLeaves2), vCover, vLeaves2, 0 ); + iTopLit = RetValue; + } + else + { + assert( iLitCofs[0] > 1 || iLitCofs[1] > 1 ); + // collect leaves + Vec_IntClear( vLeaves2 ); + for ( k = 0; k < 3; k++ ) + if ( iLitCofs[k] > 1 ) + Vec_IntPush( vLeaves2, iLitCofs[k] ); + assert( Vec_IntSize(vLeaves2) == 2 ); + // consider three possibilities + if ( iLitCofs[0] == 0 ) + RetValue = Gia_ManAppendAnd( pNew, iLitCofs[2], iLitCofs[1] ); + else if ( iLitCofs[0] == 1 ) + RetValue = Gia_ManAppendOr( pNew, Abc_LitNot(iLitCofs[2]), iLitCofs[1] ); + else if ( iLitCofs[1] == 0 ) + RetValue = Gia_ManAppendAnd( pNew, Abc_LitNot(iLitCofs[2]), iLitCofs[0] ); + else if ( iLitCofs[1] == 1 ) + RetValue = Gia_ManAppendOr( pNew, iLitCofs[2], iLitCofs[0] ); + else assert( 0 ); + iTopLit = iLitCofs[2]; + } + // create mapping + Vec_IntSetEntry( vMapping, Abc_Lit2Var(RetValue), Vec_IntSize(vMapping2) ); + Vec_IntPush( vMapping2, Vec_IntSize(vLeaves2) ); + Vec_IntForEachEntry( vLeaves2, iTemp, k ) + Vec_IntPush( vMapping2, Abc_Lit2Var(iTemp) ); + Vec_IntPush( vMapping2, -Abc_Lit2Var(iTopLit) ); + RetValue = Abc_LitNotCond( RetValue, pCutBest->fCompl ); + return RetValue; +} +int Gia_ManFromIfLogicAndVars( Gia_Man_t * pNew, If_Man_t * pIfMan, If_Cut_t * pCutBest, Vec_Int_t * vLeaves, Vec_Int_t * vLeaves2, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2 ) +{ + word pFunc[64], uTruth[2]; + int nLeaves = pCutBest->nLeaves; + int truthId = Abc_Lit2Var(pCutBest->iCutFunc); + int c, k, Mask = Vec_IntEntry(pIfMan->vTtDecs[nLeaves], truthId); + int MaskOne[2] = { Mask & 0xFFFF, (Mask >> 16) & 0x3FFF }; + int iLitCofs[2], iTemp, fOrDec = (Mask >> 30) & 1, RetValue = -1; + assert( Mask > 0 && nLeaves <= 2 * (pIfMan->pPars->nLutSize/2) && pIfMan->pPars->nLutSize <= 13 ); + Abc_TtCopy( pFunc, If_CutTruthWR(pIfMan, pCutBest), pIfMan->nTruth6Words[nLeaves], fOrDec ); + Abc_TtDeriveBiDec( pFunc, nLeaves, MaskOne[0], MaskOne[1], pIfMan->pPars->nLutSize/2, &uTruth[0], &uTruth[1] ); + uTruth[0] = fOrDec ? ~uTruth[0] : uTruth[0]; + uTruth[1] = fOrDec ? ~uTruth[1] : uTruth[1]; + for ( c = 0; c < 2; c++ ) + { + Vec_IntClear( vLeaves2 ); + for ( k = 0; k < nLeaves; k++ ) + if ( (MaskOne[c] >> k) & 1 ) + Vec_IntPush( vLeaves2, Vec_IntEntry(vLeaves, k) ); + assert( Vec_IntSize(vLeaves2) >= 1 ); + iLitCofs[c] = Kit_TruthToGia( pNew, (unsigned *)&uTruth[c], Vec_IntSize(vLeaves2), vCover, vLeaves2, 0 ); + if ( Vec_IntSize(vLeaves2) == 1 ) + continue; + // create mapping + assert( Gia_ObjIsAnd(Gia_ManObj(pNew, Abc_Lit2Var(iLitCofs[c]))) ); + Vec_IntSetEntry( vMapping, Abc_Lit2Var(iLitCofs[c]), Vec_IntSize(vMapping2) ); + Vec_IntPush( vMapping2, Vec_IntSize(vLeaves2) ); + Vec_IntForEachEntry( vLeaves2, iTemp, k ) + Vec_IntPush( vMapping2, Abc_Lit2Var(iTemp) ); + Vec_IntPush( vMapping2, Abc_Lit2Var(iLitCofs[c]) ); + } + iLitCofs[0] = Abc_LitNotCond( iLitCofs[0], fOrDec ); + iLitCofs[1] = Abc_LitNotCond( iLitCofs[1], fOrDec ); + RetValue = Gia_ManAppendAnd( pNew, iLitCofs[0], iLitCofs[1] ); + RetValue = Abc_LitNotCond( RetValue, fOrDec ^ Abc_LitIsCompl(pCutBest->iCutFunc) ); + // create mapping + Vec_IntSetEntry( vMapping, Abc_Lit2Var(RetValue), Vec_IntSize(vMapping2) ); + Vec_IntPush( vMapping2, 2 ); + Vec_IntPush( vMapping2, Abc_Lit2Var(iLitCofs[0]) ); + Vec_IntPush( vMapping2, Abc_Lit2Var(iLitCofs[1]) ); + Vec_IntPush( vMapping2, -Abc_Lit2Var(RetValue) ); + RetValue = Abc_LitNotCond( RetValue, pCutBest->fCompl ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Converts IF into GIA manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManFromIfLogic( If_Man_t * pIfMan ) +{ + int fWriteConfigs = 1; + Gia_Man_t * pNew, * pHashed = NULL; + If_Cut_t * pCutBest; + If_Obj_t * pIfObj, * pIfLeaf; + Vec_Int_t * vMapping, * vMapping2, * vPacking = NULL, * vConfigs = NULL; + Vec_Int_t * vLeaves, * vLeaves2, * vCover, * vLits; + Vec_Str_t * vConfigsStr = NULL; + Ifn_Ntk_t * pNtkCell = NULL; + sat_solver * pSat = NULL; + int i, k, Entry; + assert( !pIfMan->pPars->fDeriveLuts || pIfMan->pPars->fTruth ); +// if ( pIfMan->pPars->fEnableCheck07 ) +// pIfMan->pPars->fDeriveLuts = 0; + // start mapping and packing + vMapping = Vec_IntStart( If_ManObjNum(pIfMan) ); + vMapping2 = Vec_IntStart( 1 ); + if ( pIfMan->pPars->fDeriveLuts && (pIfMan->pPars->pLutStruct || pIfMan->pPars->fEnableCheck75 || pIfMan->pPars->fEnableCheck75u || pIfMan->pPars->fEnableCheck07) ) + { + vPacking = Vec_IntAlloc( 1000 ); + Vec_IntPush( vPacking, 0 ); + } + if ( pIfMan->pPars->fUseDsdTune ) + { + int nTtBitNum = If_DsdManTtBitNum(pIfMan->pIfDsdMan); + int nPermBitNum = If_DsdManPermBitNum(pIfMan->pIfDsdMan); + int nConfigInts = Abc_BitWordNum(nTtBitNum + nPermBitNum + 1); + vConfigs = Vec_IntAlloc( 1000 ); + Vec_IntPush( vConfigs, 0 ); + Vec_IntPush( vConfigs, nConfigInts ); + if ( fWriteConfigs ) + vConfigsStr = Vec_StrAlloc( 1000 ); + } + // create new manager + pNew = Gia_ManStart( If_ManObjNum(pIfMan) ); + // iterate through nodes used in the mapping + vLits = Vec_IntAlloc( 1000 ); + vCover = Vec_IntAlloc( 1 << 16 ); + vLeaves = Vec_IntAlloc( 16 ); + vLeaves2 = Vec_IntAlloc( 16 ); + If_ManCleanCutData( pIfMan ); + If_ManForEachObj( pIfMan, pIfObj, i ) + { + if ( pIfObj->nRefs == 0 && !If_ObjIsTerm(pIfObj) ) + continue; + if ( If_ObjIsAnd(pIfObj) ) + { + pCutBest = If_ObjCutBest( pIfObj ); + // perform sorting of cut leaves by delay, so that the slowest pin drives the fastest input of the LUT + if ( !pIfMan->pPars->fUseTtPerm && !pIfMan->pPars->fDelayOpt && !pIfMan->pPars->fDelayOptLut && !pIfMan->pPars->fDsdBalance && + !pIfMan->pPars->pLutStruct && !pIfMan->pPars->fUserRecLib && !pIfMan->pPars->fUserSesLib && !pIfMan->pPars->nGateSize && + !pIfMan->pPars->fEnableCheck75 && !pIfMan->pPars->fEnableCheck75u && !pIfMan->pPars->fEnableCheck07 && !pIfMan->pPars->fUseDsdTune && + !pIfMan->pPars->fUseCofVars && !pIfMan->pPars->fUseAndVars && !pIfMan->pPars->fUseCheck1 && !pIfMan->pPars->fUseCheck2 && !pIfMan->pPars->fUserLutDec ) + If_CutRotatePins( pIfMan, pCutBest ); + // collect leaves of the best cut + Vec_IntClear( vLeaves ); + If_CutForEachLeaf( pIfMan, pCutBest, pIfLeaf, k ) + Vec_IntPush( vLeaves, pIfLeaf->iCopy ); + // perform one of the two types of mapping: with and without structures + if ( pIfMan->pPars->fUseDsd && pIfMan->pPars->pLutStruct ) + { + if ( pSat == NULL ) + pSat = (sat_solver *)If_ManSatBuildXY( (int)(pIfMan->pPars->pLutStruct[0] - '0') ); + if ( pIfMan->pPars->pLutStruct && pIfMan->pPars->fDeriveLuts ) + pIfObj->iCopy = Gia_ManFromIfLogicFindLut( pIfMan, pNew, pCutBest, pSat, vLeaves, vLits, vCover, vMapping, vMapping2, vPacking ); + else + pIfObj->iCopy = Gia_ManFromIfLogicCreateLut( pNew, If_CutTruthW(pIfMan, pCutBest), vLeaves, vCover, vMapping, vMapping2 ); + pIfObj->iCopy = Abc_LitNotCond( pIfObj->iCopy, pCutBest->fCompl ); + } +/* + else if ( pIfMan->pPars->fUseDsd && pIfMan->pPars->fUseDsdTune && pIfMan->pPars->fDeriveLuts ) + { + if ( pNtkCell == NULL ) + { + assert( If_DsdManGetCellStr(pIfMan->pIfDsdMan) != NULL ); + pNtkCell = Ifn_NtkParse( If_DsdManGetCellStr(pIfMan->pIfDsdMan) ); + nLutMax = Ifn_NtkLutSizeMax( pNtkCell ); + pHashed = Gia_ManStart( 10000 ); + Vec_IntFillExtra( &pHashed->vCopies, 10000, -1 ); + for ( k = 0; k < pIfMan->pPars->nLutSize; k++ ) + Gia_ManAppendCi( pHashed ); + Gia_ManHashAlloc( pHashed ); + } + pIfObj->iCopy = Gia_ManFromIfLogicFindCell( pIfMan, pNew, pHashed, pCutBest, pNtkCell, nLutMax, vLeaves, vLits, vCover, vMapping, vMapping2, vConfigs ); + pIfObj->iCopy = Abc_LitNotCond( pIfObj->iCopy, pCutBest->fCompl ); + } +*/ + else if ( pIfMan->pPars->fUseAndVars && pIfMan->pPars->fUseCofVars && pIfMan->pPars->fDeriveLuts && (int)pCutBest->nLeaves > pIfMan->pPars->nLutSize/2 ) + { + int truthId = Abc_Lit2Var(pCutBest->iCutFunc); + int Mask = Vec_IntEntry(pIfMan->vTtDecs[pCutBest->nLeaves], truthId); + if ( Mask ) + pIfObj->iCopy = Gia_ManFromIfLogicAndVars( pNew, pIfMan, pCutBest, vLeaves, vLeaves2, vCover, vMapping, vMapping2 ); + else + pIfObj->iCopy = Gia_ManFromIfLogicCofVars( pNew, pIfMan, pCutBest, vLeaves, vLeaves2, vCover, vMapping, vMapping2 ); + } + else if ( pIfMan->pPars->fUseAndVars && pIfMan->pPars->fDeriveLuts && (int)pCutBest->nLeaves > pIfMan->pPars->nLutSize/2 ) + { + pIfObj->iCopy = Gia_ManFromIfLogicAndVars( pNew, pIfMan, pCutBest, vLeaves, vLeaves2, vCover, vMapping, vMapping2 ); + } + else if ( pIfMan->pPars->fUseCofVars && pIfMan->pPars->fDeriveLuts && (int)pCutBest->nLeaves > pIfMan->pPars->nLutSize/2 ) + { + pIfObj->iCopy = Gia_ManFromIfLogicCofVars( pNew, pIfMan, pCutBest, vLeaves, vLeaves2, vCover, vMapping, vMapping2 ); + } + else if ( pIfMan->pPars->fUserLutDec && (int)pCutBest->nLeaves > pIfMan->pPars->nLutDecSize ) + { + pIfObj->iCopy = Gia_ManFromIfLogicHop( pNew, pIfMan, pCutBest, vLeaves, vLeaves2, vCover, vMapping, vMapping2 ); + } + else if ( (pIfMan->pPars->fDeriveLuts && pIfMan->pPars->fTruth) || pIfMan->pPars->fUseDsd || pIfMan->pPars->fUseTtPerm || pIfMan->pPars->pFuncCell2 ) + { + word * pTruth = If_CutTruthW(pIfMan, pCutBest); + if ( pIfMan->pPars->fUseTtPerm ) + for ( k = 0; k < (int)pCutBest->nLeaves; k++ ) + if ( If_CutLeafBit(pCutBest, k) ) + Abc_TtFlip( pTruth, Abc_TtWordNum(pCutBest->nLeaves), k ); + // perform decomposition of the cut + pIfObj->iCopy = Gia_ManFromIfLogicNode( pIfMan, pNew, i, vLeaves, vLeaves2, pTruth, pIfMan->pPars->pLutStruct, vCover, vMapping, vMapping2, vPacking, (pIfMan->pPars->fEnableCheck75 || pIfMan->pPars->fEnableCheck75u), pIfMan->pPars->fEnableCheck07 ); + pIfObj->iCopy = Abc_LitNotCond( pIfObj->iCopy, pCutBest->fCompl ); + if ( vConfigs && Vec_IntSize(vLeaves) > 1 && !Gia_ObjIsCi(Gia_ManObj(pNew, Abc_Lit2Var(pIfObj->iCopy))) && pIfObj->iCopy > 1 ) + Gia_ManFromIfGetConfig( vConfigs, pIfMan, pCutBest, pIfObj->iCopy, vConfigsStr ); + } + else + { + pIfObj->iCopy = Gia_ManNodeIfToGia( pNew, pIfMan, pIfObj, vLeaves, 0 ); + // write mapping + Vec_IntSetEntry( vMapping, Abc_Lit2Var(pIfObj->iCopy), Vec_IntSize(vMapping2) ); + Vec_IntPush( vMapping2, Vec_IntSize(vLeaves) ); + Vec_IntForEachEntry( vLeaves, Entry, k ) + assert( Abc_Lit2Var(Entry) < Abc_Lit2Var(pIfObj->iCopy) ); + Vec_IntForEachEntry( vLeaves, Entry, k ) + Vec_IntPush( vMapping2, Abc_Lit2Var(Entry) ); + Vec_IntPush( vMapping2, Abc_Lit2Var(pIfObj->iCopy) ); + } + } + else if ( If_ObjIsCi(pIfObj) ) + pIfObj->iCopy = Gia_ManAppendCi(pNew); + else if ( If_ObjIsCo(pIfObj) ) + pIfObj->iCopy = Gia_ManAppendCo( pNew, Abc_LitNotCond(If_ObjFanin0(pIfObj)->iCopy, If_ObjFaninC0(pIfObj)) ); + else if ( If_ObjIsConst1(pIfObj) ) + { + pIfObj->iCopy = 1; + // create const LUT + Vec_IntWriteEntry( vMapping, 0, Vec_IntSize(vMapping2) ); + Vec_IntPush( vMapping2, 0 ); + Vec_IntPush( vMapping2, 0 ); + } + else assert( 0 ); + } + Vec_IntFree( vLits ); + Vec_IntFree( vCover ); + Vec_IntFree( vLeaves ); + Vec_IntFree( vLeaves2 ); + if ( pNtkCell ) + ABC_FREE( pNtkCell ); + if ( pSat ) + sat_solver_delete(pSat); + if ( pHashed ) + Gia_ManStop( pHashed ); +// printf( "Mapping array size: IfMan = %d. Gia = %d. Increase = %.2f\n", +// If_ManObjNum(pIfMan), Gia_ManObjNum(pNew), 1.0 * Gia_ManObjNum(pNew) / If_ManObjNum(pIfMan) ); + // finish mapping + if ( Vec_IntSize(vMapping) > Gia_ManObjNum(pNew) ) + Vec_IntShrink( vMapping, Gia_ManObjNum(pNew) ); + else + Vec_IntFillExtra( vMapping, Gia_ManObjNum(pNew), 0 ); + assert( Vec_IntSize(vMapping) == Gia_ManObjNum(pNew) ); + Vec_IntForEachEntry( vMapping, Entry, i ) + if ( Entry > 0 ) + Vec_IntAddToEntry( vMapping, i, Gia_ManObjNum(pNew) ); + Vec_IntAppend( vMapping, vMapping2 ); + Vec_IntFree( vMapping2 ); + // attach mapping and packing + assert( pNew->vMapping == NULL ); + assert( pNew->vPacking == NULL ); + assert( pNew->vConfigs == NULL ); + assert( pNew->pCellStr == NULL ); + pNew->vMapping = vMapping; + pNew->vPacking = vPacking; + pNew->vConfigs = vConfigs; + pNew->pCellStr = vConfigs ? Abc_UtilStrsav( If_DsdManGetCellStr(pIfMan->pIfDsdMan) ) : NULL; + assert( !vConfigs || Vec_IntSize(vConfigs) == 2 + Vec_IntEntry(vConfigs, 0) * Vec_IntEntry(vConfigs, 1) ); + // verify that COs have mapping + { + Gia_Obj_t * pObj; + Gia_ManForEachCo( pNew, pObj, i ) + assert( !Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) || Gia_ObjIsLut(pNew, Gia_ObjFaninId0p(pNew, pObj)) ); + } + // verify that internal nodes have mapping + { + Gia_Obj_t * pFanin; + Gia_ManForEachLut( pNew, i ) + Gia_LutForEachFaninObj( pNew, i, pFanin, k ) + assert( !Gia_ObjIsAnd(pFanin) || Gia_ObjIsLut(pNew, Gia_ObjId(pNew, pFanin)) ); + } + // verify that CIs have no mapping + { + Gia_Obj_t * pObj; + Gia_ManForEachCi( pNew, pObj, i ) + assert( !Gia_ObjIsLut(pNew, Gia_ObjId(pNew, pObj)) ); + } + // dump configuration strings + if ( vConfigsStr ) + { + FILE * pFile; int status; + char * pStr, Buffer[1000] = {0}; + const char * pNameGen = pIfMan->pName? Extra_FileNameGeneric( pIfMan->pName ) : "nameless_"; + sprintf( Buffer, "%s_configs.txt", pNameGen ); + ABC_FREE( pNameGen ); + pFile = fopen( Buffer, "wb" ); + if ( pFile == NULL ) + { + Vec_StrFree( vConfigsStr ); + printf( "Cannot open file \"%s\".\n", Buffer ); + return pNew; + } + Vec_StrPush( vConfigsStr, '\0' ); + pStr = Vec_StrArray(vConfigsStr); + status = fwrite( pStr, strlen(pStr), 1, pFile ); + Vec_StrFree( vConfigsStr ); + fclose( pFile ); + printf( "Finished dumping configs into file \"%s\".\n", Buffer ); + } + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Verifies mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManMappingVerify_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + int Id, iFan, k, Result = 1; + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return 1; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( !Gia_ObjIsAndNotBuf(pObj) ) + return 1; + if ( !Gia_ObjIsLut(p, Gia_ObjId(p, pObj)) ) + { + Abc_Print( -1, "Gia_ManMappingVerify: Internal node %d does not have mapping.\n", Gia_ObjId(p, pObj) ); + return 0; + } + Id = Gia_ObjId(p, pObj); + Gia_LutForEachFanin( p, Id, iFan, k ) + if ( Result ) + Result &= Gia_ManMappingVerify_rec( p, Gia_ManObj(p, iFan) ); + return Result; +} +void Gia_ManMappingVerify( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj, * pFanin; + int i, Result = 1; + assert( Gia_ManHasMapping(p) ); + Gia_ManIncrementTravId( p ); + Gia_ManForEachBuf( p, pObj, i ) + { + pFanin = Gia_ObjFanin0(pObj); + if ( !Gia_ObjIsAndNotBuf(pFanin) ) + continue; + if ( !Gia_ObjIsLut(p, Gia_ObjId(p, pFanin)) ) + { + Abc_Print( -1, "Gia_ManMappingVerify: Buffer driver %d does not have mapping.\n", Gia_ObjId(p, pFanin) ); + Result = 0; + continue; + } + Result &= Gia_ManMappingVerify_rec( p, pFanin ); + } + Gia_ManForEachCo( p, pObj, i ) + { + pFanin = Gia_ObjFanin0(pObj); + if ( !Gia_ObjIsAndNotBuf(pFanin) ) + continue; + if ( !Gia_ObjIsLut(p, Gia_ObjId(p, pFanin)) ) + { + Abc_Print( -1, "Gia_ManMappingVerify: CO driver %d does not have mapping.\n", Gia_ObjId(p, pFanin) ); + Result = 0; + continue; + } + Result &= Gia_ManMappingVerify_rec( p, pFanin ); + } +// if ( Result && Gia_NtkIsRoot(p) ) +// Abc_Print( 1, "Mapping verified correctly.\n" ); +} + + +/**Function************************************************************* + + Synopsis [Transfers mapping from hie GIA to normalized GIA.] + + Description [Hie GIA (pGia) points to normalized GIA (p).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManTransferMapping( Gia_Man_t * p, Gia_Man_t * pGia ) +{ + Gia_Obj_t * pObj; + int i, k, iFan, iPlace; + if ( !Gia_ManHasMapping(pGia) ) + return; + Gia_ManMappingVerify( pGia ); + Vec_IntFreeP( &p->vMapping ); + p->vMapping = Vec_IntAlloc( 2 * Gia_ManObjNum(p) ); + Vec_IntFill( p->vMapping, Gia_ManObjNum(p), 0 ); + Gia_ManForEachLut( pGia, i ) + { + if ( Gia_ObjValue(Gia_ManObj(pGia, i)) == ~0 ) // handle dangling LUT + continue; + assert( !Abc_LitIsCompl(Gia_ObjValue(Gia_ManObj(pGia, i))) ); + pObj = Gia_ManObj( p, Abc_Lit2Var(Gia_ObjValue(Gia_ManObj(pGia, i))) ); + Vec_IntWriteEntry( p->vMapping, Gia_ObjId(p, pObj), Vec_IntSize(p->vMapping) ); + iPlace = Vec_IntSize( p->vMapping ); + Vec_IntPush( p->vMapping, Gia_ObjLutSize(pGia, i) ); + Gia_LutForEachFanin( pGia, i, iFan, k ) + { + if ( Gia_ObjValue(Gia_ManObj(pGia, iFan)) == ~0 ) // handle dangling LUT fanin + Vec_IntAddToEntry( p->vMapping, iPlace, -1 ); + else + Vec_IntPush( p->vMapping, Abc_Lit2Var(Gia_ObjValue(Gia_ManObj(pGia, iFan))) ); + } + iFan = Abc_Lit2Var( Gia_ObjValue(Gia_ManObj(pGia, Abc_AbsInt(Gia_ObjLutMuxId(pGia, i)))) ); + Vec_IntPush( p->vMapping, Gia_ObjLutIsMux(pGia, i) ? -iFan : iFan ); + } + Gia_ManMappingVerify( p ); +} +void Gia_ManTransferPacking( Gia_Man_t * p, Gia_Man_t * pGia ) +{ + Vec_Int_t * vPackingNew; + Gia_Obj_t * pObj, * pObjNew; + int i, k, Entry, nEntries, nEntries2; + if ( pGia->vPacking == NULL ) + return; + nEntries = Vec_IntEntry( pGia->vPacking, 0 ); + nEntries2 = 0; + // create new packing info + vPackingNew = Vec_IntAlloc( Vec_IntSize(pGia->vPacking) ); + Vec_IntPush( vPackingNew, nEntries ); + Vec_IntForEachEntryStart( pGia->vPacking, Entry, i, 1 ) + { + assert( Entry > 0 && Entry < 4 ); + Vec_IntPush( vPackingNew, Entry ); + i++; + for ( k = 0; k < Entry; k++, i++ ) + { + pObj = Gia_ManObj(pGia, Vec_IntEntry(pGia->vPacking, i)); + pObjNew = Gia_ManObj(p, Abc_Lit2Var(Gia_ObjValue(pObj))); + assert( Gia_ObjIsLut(pGia, Gia_ObjId(pGia, pObj)) ); + assert( Gia_ObjIsLut(p, Gia_ObjId(p, pObjNew)) ); + Vec_IntPush( vPackingNew, Gia_ObjId(p, pObjNew) ); +// printf( "%d -> %d ", Vec_IntEntry(pGia->vPacking, i), Gia_ObjId(p, pObjNew) ); + } + i--; + nEntries2++; + } + assert( nEntries == nEntries2 ); + // attach packing info + assert( p->vPacking == NULL ); + p->vPacking = vPackingNew; +} +void Gia_ManTransferTiming( Gia_Man_t * p, Gia_Man_t * pGia ) +{ + if ( p == pGia ) + return; + if ( pGia->vCiArrs || pGia->vCoReqs || pGia->vCoArrs || pGia->vCoAttrs ) + { + p->vCiArrs = pGia->vCiArrs; pGia->vCiArrs = NULL; + p->vCoReqs = pGia->vCoReqs; pGia->vCoReqs = NULL; + p->vCoArrs = pGia->vCoArrs; pGia->vCoArrs = NULL; + p->vCoAttrs = pGia->vCoAttrs; pGia->vCoAttrs = NULL; + p->And2Delay = pGia->And2Delay; + } + if ( pGia->vInArrs || pGia->vOutReqs ) + { + p->vInArrs = pGia->vInArrs; pGia->vInArrs = NULL; + p->vOutReqs = pGia->vOutReqs; pGia->vOutReqs = NULL; + p->DefInArrs = pGia->DefInArrs; + p->DefOutReqs = pGia->DefOutReqs; + p->And2Delay = pGia->And2Delay; + } + if ( pGia->vNamesIn || pGia->vNamesOut || pGia->vNamesNode ) + { + p->vNamesIn = pGia->vNamesIn; pGia->vNamesIn = NULL; + p->vNamesOut = pGia->vNamesOut; pGia->vNamesOut = NULL; + p->vNamesNode = pGia->vNamesNode; pGia->vNamesNode = NULL; + } + if ( pGia->vConfigs || pGia->pCellStr ) + { + p->vConfigs = pGia->vConfigs; pGia->vConfigs = NULL; + p->pCellStr = pGia->pCellStr; pGia->pCellStr = NULL; + } + if ( pGia->pManTime == NULL ) + return; + p->pManTime = pGia->pManTime; pGia->pManTime = NULL; + p->pAigExtra = pGia->pAigExtra; pGia->pAigExtra = NULL; + p->vRegClasses = pGia->vRegClasses; pGia->vRegClasses = NULL; + p->vRegInits = pGia->vRegInits; pGia->vRegInits = NULL; + p->nAnd2Delay = pGia->nAnd2Delay; pGia->nAnd2Delay = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameMiniAigSetCiArrivals( Abc_Frame_t * pAbc, int * pArrivals ) +{ + Gia_Man_t * pGia; + if ( pArrivals == NULL ) + { printf( "Arrival times are not given.\n" ); return; } + if ( pAbc == NULL ) + { printf( "ABC framework is not initialized by calling Abc_Start().\n" ); return; } + pGia = Abc_FrameReadGia( pAbc ); + if ( pGia == NULL ) + { printf( "Current network in ABC framework is not defined.\n" ); return; } + Vec_IntFreeP( &pGia->vCiArrs ); + pGia->vCiArrs = Vec_IntAllocArrayCopy( pArrivals, Gia_ManCiNum(pGia) ); +} +void Abc_FrameMiniAigSetCoRequireds( Abc_Frame_t * pAbc, int * pRequireds ) +{ + Gia_Man_t * pGia; + if ( pRequireds == NULL ) + { printf( "Required times are not given.\n" ); return; } + if ( pAbc == NULL ) + { printf( "ABC framework is not initialized by calling Abc_Start().\n" ); return; } + pGia = Abc_FrameReadGia( pAbc ); + if ( pGia == NULL ) + { printf( "Current network in ABC framework is not defined.\n" ); return; } + Vec_IntFreeP( &pGia->vCoReqs ); + pGia->vCoReqs = Vec_IntAllocArrayCopy( pRequireds, Gia_ManCoNum(pGia) ); +} +int * Abc_FrameMiniAigReadCoArrivals( Abc_Frame_t * pAbc ) +{ + Vec_Int_t * vArrs; int * pArrs; + Gia_Man_t * pGia; + if ( pAbc == NULL ) + { printf( "ABC framework is not initialized by calling Abc_Start()\n" ); return NULL; } + pGia = Abc_FrameReadGia( pAbc ); + if ( pGia == NULL ) + { printf( "Current network in ABC framework is not defined.\n" ); return NULL; } + if ( pGia->vCoArrs == NULL ) + { printf( "Current network in ABC framework has no CO arrival times.\n" ); return NULL; } + vArrs = Vec_IntDup( pGia->vCoArrs ); + pArrs = Vec_IntReleaseArray( vArrs ); + Vec_IntFree( vArrs ); + return pArrs; +} +void Abc_FrameMiniAigSetAndGateDelay( Abc_Frame_t * pAbc, int Delay ) +{ + Gia_Man_t * pGia; + if ( pAbc == NULL ) + printf( "ABC framework is not initialized by calling Abc_Start()\n" ); + pGia = Abc_FrameReadGia( pAbc ); + if ( pGia == NULL ) + printf( "Current network in ABC framework is not defined.\n" ); + pGia->And2Delay = Delay; +} + +/**Function************************************************************* + + Synopsis [Interface of LUT mapping package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManPerformMappingInt( Gia_Man_t * p, If_Par_t * pPars ) +{ + extern void Gia_ManIffTest( Gia_Man_t * pGia, If_LibLut_t * pLib, int fVerbose ); + Gia_Man_t * pNew; + If_Man_t * pIfMan; int i, Entry;//, Id, EntryF; + assert( pPars->pTimesArr == NULL ); + assert( pPars->pTimesReq == NULL ); + if ( p->vCiArrs ) + { + assert( Vec_IntSize(p->vCiArrs) == Gia_ManCiNum(p) ); + pPars->pTimesArr = ABC_CALLOC( float, Gia_ManCiNum(p) ); + Vec_IntForEachEntry( p->vCiArrs, Entry, i ) + pPars->pTimesArr[i] = (float)Entry; + } +/* // uncommenting this leads to a mysterious memory corruption + else if ( p->vInArrs ) + { + assert( Vec_FltSize(p->vInArrs) == Gia_ManCiNum(p) ); + pPars->pTimesArr = ABC_CALLOC( float, Gia_ManCiNum(p)); + Gia_ManForEachCiId( p, Id, i ) + pPars->pTimesArr[i] = Vec_FltEntry(p->vInArrs, i); + } +*/ + if ( p->vCoReqs ) + { + assert( Vec_IntSize(p->vCoReqs) == Gia_ManCoNum(p) ); + pPars->pTimesReq = ABC_CALLOC( float, Gia_ManCoNum(p) ); + Vec_IntForEachEntry( p->vCoReqs, Entry, i ) + pPars->pTimesReq[i] = (float)Entry; + } +/* // uncommenting this leads to a mysterious memory corruption + else if ( p->vOutReqs ) + { + assert( Vec_FltSize(p->vOutReqs) == Gia_ManCoNum(p) ); + pPars->pTimesReq = ABC_CALLOC( float, Gia_ManCoNum(p) ); + Vec_FltForEachEntry( p->vOutReqs, EntryF, i ) + pPars->pTimesReq[i] = EntryF; + } +*/ + ABC_FREE( p->pCellStr ); + Vec_IntFreeP( &p->vConfigs ); + // disable cut minimization when GIA strucure is needed + if ( !pPars->fDelayOpt && !pPars->fDelayOptLut && !pPars->fDsdBalance && !pPars->fUserRecLib && !pPars->fUserSesLib && !pPars->fDeriveLuts && !pPars->fUseDsd && !pPars->fUseTtPerm && !pPars->pFuncCell2 ) + pPars->fCutMin = 0; + // translate into the mapper + pIfMan = Gia_ManToIf( p, pPars ); + if ( pIfMan == NULL ) + return NULL; + // create DSD manager + if ( pPars->fUseDsd ) + { + If_DsdMan_t * p = (If_DsdMan_t *)Abc_FrameReadManDsd(); + assert( pPars->nLutSize <= If_DsdManVarNum(p) ); + assert( (pPars->pLutStruct == NULL && If_DsdManLutSize(p) == 0) || (pPars->pLutStruct && pPars->pLutStruct[0] - '0' == If_DsdManLutSize(p)) ); + pIfMan->pIfDsdMan = (If_DsdMan_t *)Abc_FrameReadManDsd(); + if ( pPars->fDsdBalance ) + If_DsdManAllocIsops( pIfMan->pIfDsdMan, pPars->nLutSize ); + } + // compute switching for the IF objects + if ( pPars->fPower ) + { + if ( p->pManTime == NULL ) + If_ManComputeSwitching( pIfMan ); + else + Abc_Print( 0, "Switching activity computation for designs with boxes is disabled.\n" ); + } + if ( pPars->pReoMan ) + pIfMan->pUserMan = pPars->pReoMan; + if ( p->pManTime ) + pIfMan->pManTim = Tim_ManDup( (Tim_Man_t *)p->pManTime, pPars->fDelayOpt || pPars->fDelayOptLut || pPars->fDsdBalance || pPars->fUserRecLib || pPars->fUserSesLib ); +// Tim_ManPrint( pIfMan->pManTim ); + if ( p->vCoAttrs ) + { + assert( If_ManCoNum(pIfMan) == Vec_IntSize(p->vCoAttrs) ); + Vec_IntForEachEntry( p->vCoAttrs, Entry, i ) + If_ObjFanin0( If_ManCo(pIfMan, i) )->fSpec = (Entry != 0); + } + if ( !If_ManPerformMapping( pIfMan ) ) + { + If_ManStop( pIfMan ); + return NULL; + } + if ( pPars->pFuncWrite ) + pPars->pFuncWrite( pIfMan ); + // transform the result of mapping into the new network + if ( pIfMan->pPars->fDelayOpt || pIfMan->pPars->fDsdBalance || pIfMan->pPars->fUserRecLib || pIfMan->pPars->fUserSesLib ) + pNew = Gia_ManFromIfAig( pIfMan ); + else + pNew = Gia_ManFromIfLogic( pIfMan ); + if ( p->vCiArrs || p->vCoReqs ) + { + If_Obj_t * pIfObj = NULL; + Vec_IntFreeP( &p->vCoArrs ); + p->vCoArrs = Vec_IntAlloc( Gia_ManCoNum(p) ); + If_ManForEachCo( pIfMan, pIfObj, i ) + Vec_IntPush( p->vCoArrs, (int)If_ObjArrTime(If_ObjFanin0(pIfObj)) ); + } + If_ManStop( pIfMan ); + // transfer name + assert( pNew->pName == NULL ); + pNew->pName = Abc_UtilStrsav( p->pName ); + ABC_FREE( pNew->pSpec ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + // print delay trace + if ( pPars->fVerboseTrace ) + { + pNew->pLutLib = pPars->pLutLib; + Gia_ManDelayTraceLutPrint( pNew, 1 ); + pNew->pLutLib = NULL; + } + return pNew; +} +Gia_Man_t * Gia_ManPerformMapping( Gia_Man_t * p, void * pp ) +{ + Gia_Man_t * pNew; + if ( p->pManTime && Tim_ManBoxNum((Tim_Man_t*)p->pManTime) && Gia_ManIsNormalized(p) ) + { + pNew = Gia_ManDupUnnormalize( p ); + if ( pNew == NULL ) + return NULL; + Gia_ManTransferTiming( pNew, p ); + p = pNew; + // mapping + pNew = Gia_ManPerformMappingInt( p, (If_Par_t *)pp ); + if ( pNew != p ) + { + Gia_ManTransferTiming( pNew, p ); + Gia_ManStop( p ); + } + // normalize + pNew = Gia_ManDupNormalize( p = pNew, ((If_Par_t *)pp)->fHashMapping ); + Gia_ManTransferMapping( pNew, p ); + Gia_ManTransferPacking( pNew, p ); + Gia_ManTransferTiming( pNew, p ); + Gia_ManStop( p ); + assert( Gia_ManIsNormalized(pNew) ); + } + else + { + pNew = Gia_ManPerformMappingInt( p, (If_Par_t *)pp ); + Gia_ManTransferTiming( pNew, p ); + if ( ((If_Par_t *)pp)->fHashMapping ) + { + pNew = Gia_ManDupHashMapping( p = pNew ); + Gia_ManTransferPacking( pNew, p ); + Gia_ManTransferTiming( pNew, p ); + Gia_ManStop( p ); + } + } + pNew->MappedDelay = (int)((If_Par_t *)pp)->FinalDelay; + pNew->MappedArea = (int)((If_Par_t *)pp)->FinalArea; + return pNew; +} + +/**Function************************************************************* + + Synopsis [Interface of other mapping-based procedures.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManPerformSopBalance( Gia_Man_t * p, int nCutNum, int nRelaxRatio, int fVerbose ) +{ + Gia_Man_t * pNew; + If_Man_t * pIfMan; + If_Par_t Pars, * pPars = &Pars; + If_ManSetDefaultPars( pPars ); + pPars->nCutsMax = nCutNum; + pPars->nRelaxRatio = nRelaxRatio; + pPars->fVerbose = fVerbose; + pPars->nLutSize = 6; + pPars->fDelayOpt = 1; + pPars->fCutMin = 1; + pPars->fTruth = 1; + pPars->fExpRed = 0; + // perform mapping + pIfMan = Gia_ManToIf( p, pPars ); + If_ManPerformMapping( pIfMan ); + pNew = Gia_ManFromIfAig( pIfMan ); + If_ManStop( pIfMan ); + Gia_ManTransferTiming( pNew, p ); + // transfer name + assert( pNew->pName == NULL ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} +Gia_Man_t * Gia_ManPerformDsdBalance( Gia_Man_t * p, int nLutSize, int nCutNum, int nRelaxRatio, int fVerbose ) +{ + Gia_Man_t * pNew; + If_Man_t * pIfMan; + If_Par_t Pars, * pPars = &Pars; + If_ManSetDefaultPars( pPars ); + pPars->nCutsMax = nCutNum; + pPars->nRelaxRatio = nRelaxRatio; + pPars->fVerbose = fVerbose; + pPars->nLutSize = nLutSize; + pPars->fDsdBalance = 1; + pPars->fUseDsd = 1; + pPars->fCutMin = 1; + pPars->fTruth = 1; + pPars->fExpRed = 0; + if ( Abc_FrameReadManDsd2() == NULL ) + Abc_FrameSetManDsd2( If_DsdManAlloc(pPars->nLutSize, 0) ); + // perform mapping + pIfMan = Gia_ManToIf( p, pPars ); + pIfMan->pIfDsdMan = (If_DsdMan_t *)Abc_FrameReadManDsd2(); + if ( pPars->fDsdBalance ) + If_DsdManAllocIsops( pIfMan->pIfDsdMan, pPars->nLutSize ); + If_ManPerformMapping( pIfMan ); + pNew = Gia_ManFromIfAig( pIfMan ); + If_ManStop( pIfMan ); + Gia_ManTransferTiming( pNew, p ); + // transfer name + assert( pNew->pName == NULL ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Tests decomposition structures.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManTestStruct( Gia_Man_t * p ) +{ + int nCutMax = 7; + int LutCount[8] = {0}, LutNDecomp[8] = {0}; + int i, k, iFan, nFanins, Status; + Vec_Int_t * vLeaves; + word * pTruth; + + vLeaves = Vec_IntAlloc( 100 ); + Gia_ObjComputeTruthTableStart( p, nCutMax ); + Gia_ManForEachLut( p, i ) + { + nFanins = Gia_ObjLutSize(p, i); + assert( nFanins <= 7 ); + LutCount[Abc_MaxInt(nFanins, 5)]++; + if ( nFanins <= 5 ) + continue; + Vec_IntClear( vLeaves ); + Gia_LutForEachFanin( p, i, iFan, k ) + Vec_IntPush( vLeaves, iFan ); + pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ManObj(p, i), vLeaves ); + // check if it is decomposable + Status = If_CutPerformCheck07( NULL, (unsigned *)pTruth, 7, nFanins, NULL ); + if ( Status == 1 ) + continue; + LutNDecomp[nFanins]++; + if ( LutNDecomp[nFanins] > 10 ) + continue; + Kit_DsdPrintFromTruth( (unsigned *)pTruth, nFanins ); printf( "\n" ); + } + Gia_ObjComputeTruthTableStop( p ); + + printf( "LUT5 = %d ", LutCount[5] ); + printf( "LUT6 = %d NonDec = %d (%.2f %%) ", LutCount[6], LutNDecomp[6], 100.0 * LutNDecomp[6]/Abc_MaxInt(LutCount[6], 1) ); + printf( "LUT7 = %d NonDec = %d (%.2f %%) ", LutCount[7], LutNDecomp[7], 100.0 * LutNDecomp[7]/Abc_MaxInt(LutCount[7], 1) ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Performs hashing for a mapped AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupHashMapping( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Vec_Int_t * vMapping; + Gia_Obj_t * pObj, * pFanin; + int i, k; + assert( Gia_ManHasMapping(p) ); + // copy the old manager with hashing + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + // recreate mapping + vMapping = Vec_IntAlloc( Vec_IntSize(p->vMapping) ); + Vec_IntFill( vMapping, Gia_ManObjNum(p), 0 ); + Gia_ManForEachLut( p, i ) + { + pObj = Gia_ManObj( p, i ); + Vec_IntWriteEntry( vMapping, Abc_Lit2Var(pObj->Value), Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, Gia_ObjLutSize(p, i) ); + Gia_LutForEachFaninObj( p, i, pFanin, k ) + Vec_IntPush( vMapping, Abc_Lit2Var(pFanin->Value) ); + Vec_IntPush( vMapping, Abc_Lit2Var(pObj->Value) ); + } + pNew->vMapping = vMapping; + return pNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaIff.c b/yosys/abc/src/aig/gia/giaIff.c new file mode 100644 index 00000000000..b20da8835e9 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaIff.c @@ -0,0 +1,444 @@ +/**CFile**************************************************************** + + FileName [giaIff.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Hierarchical mapping of AIG with white boxes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaIff.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "map/if/if.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Iff_Man_t_ Iff_Man_t; +struct Iff_Man_t_ +{ + Gia_Man_t * pGia; // mapped GIA + If_LibLut_t * pLib; // LUT library + int nLutSize; // LUT size + int nDegree; // degree + Vec_Flt_t * vTimes; // arrival times + Vec_Int_t * vMatch[4]; // matches +}; + +static inline float Iff_ObjTimeId( Iff_Man_t * p, int iObj ) { return Vec_FltEntry( p->vTimes, iObj ); } +static inline float Iff_ObjTime( Iff_Man_t * p, Gia_Obj_t * pObj ) { return Iff_ObjTimeId( p, Gia_ObjId(p->pGia, pObj) ); } +static inline void Iff_ObjSetTimeId( Iff_Man_t * p, int iObj, float Time ) { Vec_FltWriteEntry( p->vTimes, iObj, Time ); } +static inline void Iff_ObjSetTime( Iff_Man_t * p, Gia_Obj_t * pObj, float Time ) { Iff_ObjSetTimeId( p, Gia_ObjId(p->pGia, pObj), Time ); } + +static inline int Iff_ObjMatchId( Iff_Man_t * p, int iObj, int Type ) { return Vec_IntEntry( p->vMatch[Type], iObj ); } +static inline int Iff_ObjMatch( Iff_Man_t * p, Gia_Obj_t * pObj, int Type ) { return Iff_ObjMatchId( p, Gia_ObjId(p->pGia, pObj), Type ); } +static inline void Iff_ObjSetMatchId( Iff_Man_t * p, int iObj, int Type, int Match ) { Vec_IntWriteEntry( p->vMatch[Type], iObj, Match ); } +static inline void Iff_ObjSetMatch( Iff_Man_t * p, Gia_Obj_t * pObj, int Type, int Match ) { Iff_ObjSetMatchId( p, Gia_ObjId(p->pGia, pObj), Type, Match );} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Iff_Man_t * Gia_ManIffStart( Gia_Man_t * pGia ) +{ + Iff_Man_t * p = ABC_CALLOC( Iff_Man_t, 1 ); + p->vTimes = Vec_FltStartFull( Gia_ManObjNum(pGia) ); + p->vMatch[2] = Vec_IntStartFull( Gia_ManObjNum(pGia) ); + p->vMatch[3] = Vec_IntStartFull( Gia_ManObjNum(pGia) ); + return p; +} +void Gia_ManIffStop( Iff_Man_t * p ) +{ + Vec_FltFree( p->vTimes ); + Vec_IntFree( p->vMatch[2] ); + Vec_IntFree( p->vMatch[3] ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Count the number of unique fanins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_IffObjCount( Gia_Man_t * pGia, int iObj, int iFaninSkip2, int iFaninSkip3 ) +{ + int i, iFanin, Count = 0; + Gia_ManIncrementTravId( pGia ); + Gia_LutForEachFanin( pGia, iObj, iFanin, i ) + { + if ( iFanin == iFaninSkip2 || iFanin == iFaninSkip3 ) + continue; + if ( Gia_ObjIsTravIdCurrentId( pGia, iFanin ) ) + continue; + Gia_ObjSetTravIdCurrentId( pGia, iFanin ); + Count++; + } + if ( iFaninSkip2 >= 0 ) + { + Gia_LutForEachFanin( pGia, iFaninSkip2, iFanin, i ) + { + if ( iFanin == iFaninSkip3 ) + continue; + if ( Gia_ObjIsTravIdCurrentId( pGia, iFanin ) ) + continue; + Gia_ObjSetTravIdCurrentId( pGia, iFanin ); + Count++; + } + } + if ( iFaninSkip3 >= 0 ) + { + Gia_LutForEachFanin( pGia, iFaninSkip3, iFanin, i ) + { + if ( iFanin == iFaninSkip2 ) + continue; + if ( Gia_ObjIsTravIdCurrentId( pGia, iFanin ) ) + continue; + Gia_ObjSetTravIdCurrentId( pGia, iFanin ); + Count++; + } + } + return Count; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Gia_IffObjTimeOne( Iff_Man_t * p, int iObj, int iFaninSkip2, int iFaninSkip3 ) +{ + int i, iFanin; + float DelayMax = -ABC_INFINITY; + Gia_LutForEachFanin( p->pGia, iObj, iFanin, i ) + if ( iFanin != iFaninSkip2 && iFanin != iFaninSkip3 && DelayMax < Iff_ObjTimeId(p, iFanin) ) + DelayMax = Iff_ObjTimeId(p, iFanin); + assert( i == Gia_ObjLutSize(p->pGia, iObj) ); + if ( iFaninSkip2 == -1 ) + return DelayMax; + Gia_LutForEachFanin( p->pGia, iFaninSkip2, iFanin, i ) + if ( iFanin != iFaninSkip3 && DelayMax < Iff_ObjTimeId(p, iFanin) ) + DelayMax = Iff_ObjTimeId(p, iFanin); + if ( iFaninSkip3 == -1 ) + return DelayMax; + Gia_LutForEachFanin( p->pGia, iFaninSkip3, iFanin, i ) + if ( iFanin != iFaninSkip2 && DelayMax < Iff_ObjTimeId(p, iFanin) ) + DelayMax = Iff_ObjTimeId(p, iFanin); + assert( DelayMax >= 0 ); + return DelayMax; +} +float Gia_IffObjTimeTwo( Iff_Man_t * p, int iObj, int * piFanin, float DelayMin ) +{ + int i, iFanin, nSize; + float This; + *piFanin = -1; + Gia_LutForEachFanin( p->pGia, iObj, iFanin, i ) + { + if ( Gia_ObjIsCi(Gia_ManObj(p->pGia, iFanin)) ) + continue; + This = Gia_IffObjTimeOne( p, iObj, iFanin, -1 ); + nSize = Gia_IffObjCount( p->pGia, iObj, iFanin, -1 ); + assert( nSize <= p->pLib->LutMax ); + This += p->pLib->pLutDelays[nSize][0]; + if ( DelayMin > This ) + { + DelayMin = This; + *piFanin = iFanin; + } + } + return DelayMin; +} +float Gia_IffObjTimeThree( Iff_Man_t * p, int iObj, int * piFanin, int * piFanin2, float DelayMin ) +{ + int i, k, iFanin, iFanin2, nSize; + float This; + *piFanin = -1; + *piFanin2 = -1; + Gia_LutForEachFanin( p->pGia, iObj, iFanin, i ) + Gia_LutForEachFanin( p->pGia, iObj, iFanin2, k ) + { + if ( iFanin == iFanin2 ) + continue; + if ( Gia_ObjIsCi(Gia_ManObj(p->pGia, iFanin)) ) + continue; + if ( Gia_ObjIsCi(Gia_ManObj(p->pGia, iFanin2)) ) + continue; + This = Gia_IffObjTimeOne( p, iObj, iFanin, iFanin2 ); + nSize = Gia_IffObjCount( p->pGia, iObj, iFanin, iFanin2 ); + assert( nSize <= p->pLib->LutMax ); + This += p->pLib->pLutDelays[nSize][0]; + if ( DelayMin > This ) + { + DelayMin = This; + *piFanin = iFanin; + *piFanin2 = iFanin2; + } + } + return DelayMin; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Iff_Man_t * Gia_ManIffPerform( Gia_Man_t * pGia, If_LibLut_t * pLib, Tim_Man_t * pTime, int nLutSize, int nDegree ) +{ + Iff_Man_t * p; + Gia_Obj_t * pObj; + int iObj, iFanin, iFanin1, iFanin2; + int CountAll = 0, Count2 = 0, Count3 = 0; + float arrTime1, arrTime2, arrTime3, arrMax = -ABC_INFINITY; + assert( nDegree == 2 || nDegree == 3 ); + // start the mapping manager and set its parameters + p = Gia_ManIffStart( pGia ); + p->pGia = pGia; + p->pLib = pLib; + p->nLutSize = nLutSize; + p->nDegree = nDegree; + // compute arrival times of each node + Iff_ObjSetTimeId( p, 0, 0 ); + Tim_ManIncrementTravId( pTime ); + Gia_ManForEachObj1( pGia, pObj, iObj ) + { + if ( Gia_ObjIsAnd(pObj) ) + { + if ( !Gia_ObjIsLut(pGia, iObj) ) + continue; + CountAll++; + // compute arrival times of LUT inputs + arrTime1 = Gia_IffObjTimeOne( p, iObj, -1, -1 ); + arrTime1 += p->pLib->pLutDelays[Gia_ObjLutSize(pGia, iObj)][0]; + // compute arrival times of LUT pairs + arrTime2 = Gia_IffObjTimeTwo( p, iObj, &iFanin, arrTime1 ); + if ( nDegree == 2 ) + { + // set arrival times + Iff_ObjSetTimeId( p, iObj, arrTime2 ); + if ( arrTime2 < arrTime1 ) + Iff_ObjSetMatchId( p, iObj, 2, iFanin ), Count2++; + } + else if ( nDegree == 3 ) + { + // compute arrival times of LUT triples + arrTime3 = Gia_IffObjTimeThree( p, iObj, &iFanin1, &iFanin2, arrTime2 ); + // set arrival times + Iff_ObjSetTimeId( p, iObj, arrTime3 ); + if ( arrTime3 == arrTime1 ) + continue; + if ( arrTime3 == arrTime2 ) + Iff_ObjSetMatchId( p, iObj, 2, iFanin ), Count2++; + else + { + assert( arrTime3 < arrTime2 ); + Iff_ObjSetMatchId( p, iObj, 2, iFanin1 ); + Iff_ObjSetMatchId( p, iObj, 3, iFanin2 ), Count3++; + } + } + else assert( 0 ); + } + else if ( Gia_ObjIsCi(pObj) ) + { + arrTime1 = Tim_ManGetCiArrival( pTime, Gia_ObjCioId(pObj) ); + Iff_ObjSetTime( p, pObj, arrTime1 ); + } + else if ( Gia_ObjIsCo(pObj) ) + { + arrTime1 = Iff_ObjTimeId( p, Gia_ObjFaninId0p(pGia, pObj) ); + Tim_ManSetCoArrival( pTime, Gia_ObjCioId(pObj), arrTime1 ); + Iff_ObjSetTime( p, pObj, arrTime1 ); + arrMax = Abc_MaxFloat( arrMax, arrTime1 ); + } + else assert( 0 ); + } + printf( "Max delay = %.2f. Count1 = %d. Count2 = %d. Count3 = %d.\n", + arrMax, CountAll - Count2 - Count3, Count2, Count3 ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManIffSelect_rec( Iff_Man_t * p, int iObj, Vec_Int_t * vPacking ) +{ + int i, iFanin, iFaninSkip2, iFaninSkip3; + if ( Gia_ObjIsTravIdCurrentId( p->pGia, iObj ) ) + return; + Gia_ObjSetTravIdCurrentId( p->pGia, iObj ); + assert( Gia_ObjIsLut(p->pGia, iObj) ); + iFaninSkip2 = Iff_ObjMatchId(p, iObj, 2); + iFaninSkip3 = Iff_ObjMatchId(p, iObj, 3); + if ( iFaninSkip2 == -1 ) + { + assert( iFaninSkip3 == -1 ); + Gia_LutForEachFanin( p->pGia, iObj, iFanin, i ) + Gia_ManIffSelect_rec( p, iFanin, vPacking ); + Vec_IntPush( vPacking, 1 ); + Vec_IntPush( vPacking, iObj ); + } + else if ( iFaninSkip3 == -1 ) + { + assert( iFaninSkip2 > 0 ); + Gia_LutForEachFanin( p->pGia, iObj, iFanin, i ) + if ( iFanin != iFaninSkip2 ) + Gia_ManIffSelect_rec( p, iFanin, vPacking ); + Gia_LutForEachFanin( p->pGia, iFaninSkip2, iFanin, i ) + Gia_ManIffSelect_rec( p, iFanin, vPacking ); + Vec_IntPush( vPacking, 2 ); + Vec_IntPush( vPacking, iFaninSkip2 ); + Vec_IntPush( vPacking, iObj ); + } + else + { + assert( iFaninSkip2 > 0 && iFaninSkip3 > 0 ); + Gia_LutForEachFanin( p->pGia, iObj, iFanin, i ) + if ( iFanin != iFaninSkip2 && iFanin != iFaninSkip3 ) + Gia_ManIffSelect_rec( p, iFanin, vPacking ); + Gia_LutForEachFanin( p->pGia, iFaninSkip2, iFanin, i ) + if ( iFanin != iFaninSkip3 ) + Gia_ManIffSelect_rec( p, iFanin, vPacking ); + Gia_LutForEachFanin( p->pGia, iFaninSkip3, iFanin, i ) + if ( iFanin != iFaninSkip2 ) + Gia_ManIffSelect_rec( p, iFanin, vPacking ); + Vec_IntPush( vPacking, 3 ); + Vec_IntPush( vPacking, iFaninSkip2 ); + Vec_IntPush( vPacking, iFaninSkip3 ); + Vec_IntPush( vPacking, iObj ); + } + Vec_IntAddToEntry( vPacking, 0, 1 ); +} +Vec_Int_t * Gia_ManIffSelect( Iff_Man_t * p ) +{ + Vec_Int_t * vPacking; + Gia_Obj_t * pObj; int i; + vPacking = Vec_IntAlloc( Gia_ManObjNum(p->pGia) ); + Vec_IntPush( vPacking, 0 ); + // mark const0 and PIs + Gia_ManIncrementTravId( p->pGia ); + Gia_ObjSetTravIdCurrentId( p->pGia, 0 ); + Gia_ManForEachCi( p->pGia, pObj, i ) + Gia_ObjSetTravIdCurrent( p->pGia, pObj ); + // recursively collect internal nodes + Gia_ManForEachCo( p->pGia, pObj, i ) + Gia_ManIffSelect_rec( p, Gia_ObjFaninId0p(p->pGia, pObj), vPacking ); + return vPacking; +} + +/**Function************************************************************* + + Synopsis [This command performs hierarhical mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManIffTest( Gia_Man_t * pGia, If_LibLut_t * pLib, int fVerbose ) +{ + Iff_Man_t * p; + Tim_Man_t * pTemp = NULL; + int nDegree = -1; + int nLutSize = Gia_ManLutSizeMax( pGia ); + if ( nLutSize <= 4 ) + { + nLutSize = 4; + if ( pLib->LutMax == 7 ) + nDegree = 2; + else if ( pLib->LutMax == 10 ) + nDegree = 3; + else + { printf( "LUT library for packing 4-LUTs should have 7 or 10 inputs.\n" ); return; } + } + else if ( nLutSize <= 6 ) + { + nLutSize = 6; + if ( pLib->LutMax == 11 ) + nDegree = 2; + else if ( pLib->LutMax == 16 ) + nDegree = 3; + else + { printf( "LUT library for packing 6-LUTs should have 11 or 16 inputs.\n" ); return; } + } + else + { + printf( "The LUT size is more than 6.\n" ); + return; + } + if ( fVerbose ) + printf( "Performing %d-clustering with %d-LUTs:\n", nDegree, nLutSize ); + // create timing manager + if ( pGia->pManTime == NULL ) + pGia->pManTime = pTemp = Tim_ManStart( Gia_ManCiNum(pGia), Gia_ManCoNum(pGia) ); + // perform timing computation + p = Gia_ManIffPerform( pGia, pLib, (Tim_Man_t *)pGia->pManTime, nLutSize, nDegree ); + // remove timing manager + if ( pGia->pManTime == pTemp ) + pGia->pManTime = NULL; + Tim_ManStopP( (Tim_Man_t **)&pTemp ); + // derive clustering + Vec_IntFreeP( &pGia->vPacking ); + pGia->vPacking = Gia_ManIffSelect( p ); + Gia_ManIffStop( p ); + // print statistics + if ( fVerbose ) + Gia_ManPrintPackingStats( pGia ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaIiff.c b/yosys/abc/src/aig/gia/giaIiff.c new file mode 100644 index 00000000000..3d546718f39 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaIiff.c @@ -0,0 +1,62 @@ +/**CFile**************************************************************** + + FileName [giaIiff.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Boolean matching.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaIiff.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/st/st.h" +#include "map/mio/mio.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManDeriveMatches( Vec_Ptr_t ** pvNames, Vec_Wrd_t ** pvTruths, Vec_Int_t ** pvTt2Match4, Vec_Int_t ** pvConfigs, Vec_Mem_t * pvTtMem2[3], Vec_Int_t * pvTt2Match2[3] ) +{ + return 0; +} +Gia_Man_t * Gia_ManIiffTest( char * pFileName, Gia_Man_t * pGia, int nLutSize, int nNumCuts, int fUseGates, int fUseCells, int fUseLuts, int fVerbose ) +{ + return NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaIiff.h b/yosys/abc/src/aig/gia/giaIiff.h new file mode 100644 index 00000000000..d1f9b5b3649 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaIiff.h @@ -0,0 +1,54 @@ +/**CFile**************************************************************** + + FileName [giaIiff.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaIiff.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__gia__giaIiff_h +#define ABC__aig__gia__giaIiff_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_HEADER_START + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_HEADER_END + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/yosys/abc/src/aig/gia/giaIso.c b/yosys/abc/src/aig/gia/giaIso.c new file mode 100644 index 00000000000..fcfa34488c5 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaIso.c @@ -0,0 +1,1331 @@ +/**CFile**************************************************************** + + FileName [giaIso.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Graph isomorphism.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaIso.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +#define ISO_MASK 0xFF +static unsigned int s_256Primes[ISO_MASK+1] = +{ + 0x984b6ad9,0x18a6eed3,0x950353e2,0x6222f6eb,0xdfbedd47,0xef0f9023,0xac932a26,0x590eaf55, + 0x97d0a034,0xdc36cd2e,0x22736b37,0xdc9066b0,0x2eb2f98b,0x5d9c7baf,0x85747c9e,0x8aca1055, + 0x50d66b74,0x2f01ae9e,0xa1a80123,0x3e1ce2dc,0xebedbc57,0x4e68bc34,0x855ee0cf,0x17275120, + 0x2ae7f2df,0xf71039eb,0x7c283eec,0x70cd1137,0x7cf651f3,0xa87bfa7a,0x14d87f02,0xe82e197d, + 0x8d8a5ebe,0x1e6a15dc,0x197d49db,0x5bab9c89,0x4b55dea7,0x55dede49,0x9a6a8080,0xe5e51035, + 0xe148d658,0x8a17eb3b,0xe22e4b38,0xe5be2a9a,0xbe938cbb,0x3b981069,0x7f9c0c8e,0xf756df10, + 0x8fa783f7,0x252062ce,0x3dc46b4b,0xf70f6432,0x3f378276,0x44b137a1,0x2bf74b77,0x04892ed6, + 0xfd318de1,0xd58c235e,0x94c6d25b,0x7aa5f218,0x35c9e921,0x5732fbbb,0x06026481,0xf584a44f, + 0x946e1b5f,0x8463d5b2,0x4ebca7b2,0x54887b15,0x08d1e804,0x5b22067d,0x794580f6,0xb351ea43, + 0xbce555b9,0x19ae2194,0xd32f1396,0x6fc1a7f1,0x1fd8a867,0x3a89fdb0,0xea49c61c,0x25f8a879, + 0xde1e6437,0x7c74afca,0x8ba63e50,0xb1572074,0xe4655092,0xdb6f8b1c,0xc2955f3c,0x327f85ba, + 0x60a17021,0x95bd261d,0xdea94f28,0x04528b65,0xbe0109cc,0x26dd5688,0x6ab2729d,0xc4f029ce, + 0xacf7a0be,0x4c912f55,0x34c06e65,0x4fbb938e,0x1533fb5f,0x03da06bd,0x48262889,0xc2523d7d, + 0x28a71d57,0x89f9713a,0xf574c551,0x7a99deb5,0x52834d91,0x5a6f4484,0xc67ba946,0x13ae698f, + 0x3e390f34,0x34fc9593,0x894c7932,0x6cf414a3,0xdb7928ab,0x13a3b8a3,0x4b381c1d,0xa10b54cb, + 0x55359d9d,0x35a3422a,0x58d1b551,0x0fd4de20,0x199eb3f4,0x167e09e2,0x3ee6a956,0x5371a7fa, + 0xd424efda,0x74f521c5,0xcb899ff6,0x4a42e4f4,0x747917b6,0x4b08df0b,0x090c7a39,0x11e909e4, + 0x258e2e32,0xd9fad92d,0x48fe5f69,0x0545cde6,0x55937b37,0x9b4ae4e4,0x1332b40e,0xc3792351, + 0xaff982ef,0x4dba132a,0x38b81ef1,0x28e641bf,0x227208c1,0xec4bbe37,0xc4e1821c,0x512c9d09, + 0xdaef1257,0xb63e7784,0x043e04d7,0x9c2cea47,0x45a0e59a,0x281315ca,0x849f0aac,0xa4071ed3, + 0x0ef707b3,0xfe8dac02,0x12173864,0x471f6d46,0x24a53c0a,0x35ab9265,0xbbf77406,0xa2144e79, + 0xb39a884a,0x0baf5b6d,0xcccee3dd,0x12c77584,0x2907325b,0xfd1adcd2,0xd16ee972,0x345ad6c1, + 0x315ebe66,0xc7ad2b8d,0x99e82c8d,0xe52da8c8,0xba50f1d3,0x66689cd8,0x2e8e9138,0x43e15e74, + 0xf1ced14d,0x188ec52a,0xe0ef3cbb,0xa958aedc,0x4107a1bc,0x5a9e7a3e,0x3bde939f,0xb5b28d5a, + 0x596fe848,0xe85ad00c,0x0b6b3aae,0x44503086,0x25b5695c,0xc0c31dcd,0x5ee617f0,0x74d40c3a, + 0xd2cb2b9f,0x1e19f5fa,0x81e24faf,0xa01ed68f,0xcee172fc,0x7fdf2e4d,0x002f4774,0x664f82dd, + 0xc569c39a,0xa2d4dcbe,0xaadea306,0xa4c947bf,0xa413e4e3,0x81fb5486,0x8a404970,0x752c980c, + 0x98d1d881,0x5c932c1e,0xeee65dfb,0x37592cdd,0x0fd4e65b,0xad1d383f,0x62a1452f,0x8872f68d, + 0xb58c919b,0x345c8ee3,0xb583a6d6,0x43d72cb3,0x77aaa0aa,0xeb508242,0xf2db64f8,0x86294328, + 0x82211731,0x1239a9d5,0x673ba5de,0xaf4af007,0x44203b19,0x2399d955,0xa175cd12,0x595928a7, + 0x6918928b,0xde3126bb,0x6c99835c,0x63ba1fa2,0xdebbdff0,0x3d02e541,0xd6f7aac6,0xe80b4cd0, + 0xd0fa29f1,0x804cac5e,0x2c226798,0x462f624c,0xad05b377,0x22924fcd,0xfbea205c,0x1b47586d +}; + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Gia_IsoMan_t_ Gia_IsoMan_t; +struct Gia_IsoMan_t_ +{ + Gia_Man_t * pGia; + int nObjs; + int nUniques; + int nSingles; + int nEntries; + // internal data + int * pLevels; + int * pUniques; + word * pStoreW; + unsigned * pStoreU; + // equivalence classes + Vec_Int_t * vLevCounts; + Vec_Int_t * vClasses; + Vec_Int_t * vClasses2; + // statistics + abctime timeStart; + abctime timeSim; + abctime timeRefine; + abctime timeSort; + abctime timeOther; + abctime timeTotal; +}; + +static inline unsigned Gia_IsoGetValue( Gia_IsoMan_t * p, int i ) { return (unsigned)(p->pStoreW[i]); } +static inline unsigned Gia_IsoGetItem( Gia_IsoMan_t * p, int i ) { return (unsigned)(p->pStoreW[i] >> 32); } + +static inline void Gia_IsoSetValue( Gia_IsoMan_t * p, int i, unsigned v ) { ((unsigned *)(p->pStoreW + i))[0] = v; } +static inline void Gia_IsoSetItem( Gia_IsoMan_t * p, int i, unsigned v ) { ((unsigned *)(p->pStoreW + i))[1] = v; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_IsoMan_t * Gia_IsoManStart( Gia_Man_t * pGia ) +{ + Gia_IsoMan_t * p; + p = ABC_CALLOC( Gia_IsoMan_t, 1 ); + p->pGia = pGia; + p->nObjs = Gia_ManObjNum( pGia ); + p->nUniques = 1; + p->nEntries = p->nObjs; + // internal data + p->pLevels = ABC_CALLOC( int, p->nObjs ); + p->pUniques = ABC_CALLOC( int, p->nObjs ); + p->pStoreW = ABC_CALLOC( word, p->nObjs ); + // class representation + p->vClasses = Vec_IntAlloc( p->nObjs/4 ); + p->vClasses2 = Vec_IntAlloc( p->nObjs/4 ); + return p; +} +void Gia_IsoManStop( Gia_IsoMan_t * p ) +{ + // class representation + Vec_IntFree( p->vClasses ); + Vec_IntFree( p->vClasses2 ); + // internal data + ABC_FREE( p->pLevels ); + ABC_FREE( p->pUniques ); + ABC_FREE( p->pStoreW ); + ABC_FREE( p ); +} +void Gia_IsoManTransferUnique( Gia_IsoMan_t * p ) +{ + Gia_Obj_t * pObj; + int i; + // copy unique numbers into the nodes + Gia_ManForEachObj( p->pGia, pObj, i ) + pObj->Value = p->pUniques[i]; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_IsoPrintClasses( Gia_IsoMan_t * p ) +{ + int fVerbose = 0; + int i, k, iBegin, nSize; + printf( "The total of %d classes:\n", Vec_IntSize(p->vClasses)/2 ); + Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i ) + { + printf( "%5d : (%3d,%3d) ", i/2, iBegin, nSize ); + if ( fVerbose ) + { + printf( "{" ); + for ( k = 0; k < nSize; k++ ) + printf( " %3d,%08x", Gia_IsoGetItem(p, iBegin+k), Gia_IsoGetValue(p, iBegin+k) ); + printf( " }" ); + } + printf( "\n" ); + } +} +void Gia_IsoPrint( Gia_IsoMan_t * p, int Iter, abctime Time ) +{ + printf( "Iter %4d : ", Iter ); + printf( "Entries =%8d. ", p->nEntries ); +// printf( "Classes =%8d. ", Vec_IntSize(p->vClasses)/2 ); + printf( "Uniques =%8d. ", p->nUniques ); + printf( "Singles =%8d. ", p->nSingles ); + printf( "%9.2f sec", (float)(Time)/(float)(CLOCKS_PER_SEC) ); + printf( "\n" ); + fflush( stdout ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_IsoPrepare( Gia_IsoMan_t * p ) +{ + Gia_Obj_t * pObj; + int * pLevBegins, * pLevSizes; + int i, iObj, MaxLev = 0; + // assign levels + p->pLevels[0] = 0; + Gia_ManForEachCi( p->pGia, pObj, i ) + p->pLevels[Gia_ObjId(p->pGia, pObj)] = 0; + Gia_ManForEachAnd( p->pGia, pObj, i ) + p->pLevels[i] = 1 + Abc_MaxInt( p->pLevels[Gia_ObjFaninId0(pObj, i)], p->pLevels[Gia_ObjFaninId1(pObj, i)] ); + Gia_ManForEachCo( p->pGia, pObj, i ) + { + iObj = Gia_ObjId(p->pGia, pObj); + p->pLevels[iObj] = 1 + p->pLevels[Gia_ObjFaninId0(pObj, iObj)]; // "1 +" is different! + MaxLev = Abc_MaxInt( MaxLev, p->pLevels[Gia_ObjId(p->pGia, pObj)] ); + } + + // count nodes on each level + pLevSizes = ABC_CALLOC( int, MaxLev+1 ); + for ( i = 1; i < p->nObjs; i++ ) + pLevSizes[p->pLevels[i]]++; + // start classes + Vec_IntClear( p->vClasses ); + Vec_IntPush( p->vClasses, 0 ); + Vec_IntPush( p->vClasses, 1 ); + // find beginning of each level + pLevBegins = ABC_CALLOC( int, MaxLev+2 ); + pLevBegins[0] = 1; + for ( i = 0; i <= MaxLev; i++ ) + { + assert( pLevSizes[i] > 0 ); // we do not allow AIG with a const node and no PIs + Vec_IntPush( p->vClasses, pLevBegins[i] ); + Vec_IntPush( p->vClasses, pLevSizes[i] ); + pLevBegins[i+1] = pLevBegins[i] + pLevSizes[i]; + } + assert( pLevBegins[MaxLev+1] == p->nObjs ); + // put them into the structure + for ( i = 1; i < p->nObjs; i++ ) + Gia_IsoSetItem( p, pLevBegins[p->pLevels[i]]++, i ); + ABC_FREE( pLevBegins ); + ABC_FREE( pLevSizes ); +/* + // print the results + for ( i = 0; i < p->nObjs; i++ ) + printf( "%3d : (%d,%d)\n", i, Gia_IsoGetItem(p, i), Gia_IsoGetValue(p, i) ); + printf( "\n" ); +*/ +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_IsoAssignUnique( Gia_IsoMan_t * p ) +{ + int i, iBegin, nSize; + p->nSingles = 0; + Vec_IntClear( p->vClasses2 ); + Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i ) + { + if ( nSize == 1 ) + { + assert( p->pUniques[Gia_IsoGetItem(p, iBegin)] == 0 ); + p->pUniques[Gia_IsoGetItem(p, iBegin)] = p->nUniques++; + p->nSingles++; + } + else + { + Vec_IntPush( p->vClasses2, iBegin ); + Vec_IntPush( p->vClasses2, nSize ); + } + } + ABC_SWAP( Vec_Int_t *, p->vClasses, p->vClasses2 ); + p->nEntries -= p->nSingles; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_IsoSort( Gia_IsoMan_t * p ) +{ + Gia_Obj_t * pObj, * pObj0; + int i, k, fSameValue, iBegin, iBeginOld, nSize, nSizeNew; + int fRefined = 0; + abctime clk; + + // go through the equiv classes + p->nSingles = 0; + Vec_IntClear( p->vClasses2 ); + Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i ) + { + assert( nSize > 1 ); + fSameValue = 1; + pObj0 = Gia_ManObj( p->pGia, Gia_IsoGetItem(p,iBegin) ); + for ( k = 0; k < nSize; k++ ) + { + pObj = Gia_ManObj( p->pGia, Gia_IsoGetItem(p,iBegin+k) ); + Gia_IsoSetValue( p, iBegin+k, pObj->Value ); + if ( pObj->Value != pObj0->Value ) + fSameValue = 0; + } + if ( fSameValue ) + { + Vec_IntPush( p->vClasses2, iBegin ); + Vec_IntPush( p->vClasses2, nSize ); + continue; + } + fRefined = 1; + // sort objects + clk = Abc_Clock(); + Abc_QuickSort3( p->pStoreW + iBegin, nSize, 0 ); + p->timeSort += Abc_Clock() - clk; + // divide into new classes + iBeginOld = iBegin; + pObj0 = Gia_ManObj( p->pGia, Gia_IsoGetItem(p,iBegin) ); + for ( k = 1; k < nSize; k++ ) + { + pObj = Gia_ManObj( p->pGia, Gia_IsoGetItem(p,iBegin+k) ); + if ( pObj0->Value == pObj->Value ) + continue; + nSizeNew = iBegin + k - iBeginOld; + if ( nSizeNew == 1 ) + { + assert( p->pUniques[Gia_IsoGetItem(p, iBeginOld)] == 0 ); + p->pUniques[Gia_IsoGetItem(p, iBeginOld)] = p->nUniques++; + p->nSingles++; + } + else + { + Vec_IntPush( p->vClasses2, iBeginOld ); + Vec_IntPush( p->vClasses2, nSizeNew ); + } + iBeginOld = iBegin + k; + pObj0 = pObj; + } + // add the last one + nSizeNew = iBegin + k - iBeginOld; + if ( nSizeNew == 1 ) + { + assert( p->pUniques[Gia_IsoGetItem(p, iBeginOld)] == 0 ); + p->pUniques[Gia_IsoGetItem(p, iBeginOld)] = p->nUniques++; + p->nSingles++; + } + else + { + Vec_IntPush( p->vClasses2, iBeginOld ); + Vec_IntPush( p->vClasses2, nSizeNew ); + } + } + + ABC_SWAP( Vec_Int_t *, p->vClasses, p->vClasses2 ); + p->nEntries -= p->nSingles; + return fRefined; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Gia_IsoCollectCosClasses( Gia_IsoMan_t * p, int fVerbose ) +{ + Vec_Ptr_t * vGroups; + Vec_Int_t * vLevel; + Gia_Obj_t * pObj; + int i, k, iBegin, nSize; + // add singletons + vGroups = Vec_PtrAlloc( 1000 ); + Gia_ManForEachPo( p->pGia, pObj, i ) + if ( p->pUniques[Gia_ObjId(p->pGia, pObj)] > 0 ) + { + vLevel = Vec_IntAlloc( 1 ); + Vec_IntPush( vLevel, i ); + Vec_PtrPush( vGroups, vLevel ); + } + + // add groups + Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i ) + { + for ( k = 0; k < nSize; k++ ) + { + pObj = Gia_ManObj( p->pGia, Gia_IsoGetItem(p,iBegin+k) ); + if ( Gia_ObjIsPo(p->pGia, pObj) ) + break; + } + if ( k == nSize ) + continue; + vLevel = Vec_IntAlloc( 8 ); + for ( k = 0; k < nSize; k++ ) + { + pObj = Gia_ManObj( p->pGia, Gia_IsoGetItem(p,iBegin+k) ); + if ( Gia_ObjIsPo(p->pGia, pObj) ) + Vec_IntPush( vLevel, Gia_ObjCioId(pObj) ); + } + Vec_PtrPush( vGroups, vLevel ); + } + // canonicize order + Vec_PtrForEachEntry( Vec_Int_t *, vGroups, vLevel, i ) + Vec_IntSort( vLevel, 0 ); + Vec_VecSortByFirstInt( (Vec_Vec_t *)vGroups, 0 ); +// Vec_VecFree( (Vec_Vec_t *)vGroups ); +// return NULL; + return vGroups; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Gia_IsoUpdateValue( int Value, int fCompl ) +{ + return (Value+1) * s_256Primes[Abc_Var2Lit(Value, fCompl) & ISO_MASK]; +} +static inline unsigned Gia_IsoUpdate( Gia_IsoMan_t * p, int Iter, int iObj, int fCompl ) +{ + if ( Iter == 0 ) return Gia_IsoUpdateValue( p->pLevels[iObj], fCompl ); + if ( p->pUniques[iObj] > 0 ) return Gia_IsoUpdateValue( p->pUniques[iObj], fCompl ); +// if ( p->pUniques[iObj] > 0 ) return Gia_IsoUpdateValue( 11, fCompl ); + return 0; +} +void Gia_IsoSimulate( Gia_IsoMan_t * p, int Iter ) +{ + Gia_Obj_t * pObj, * pObjF; + int i, iObj; + // initialize constant, inputs, and flops in the first frame + Gia_ManConst0(p->pGia)->Value += s_256Primes[ISO_MASK]; + Gia_ManForEachPi( p->pGia, pObj, i ) + pObj->Value += s_256Primes[ISO_MASK-1]; + if ( Iter == 0 ) + Gia_ManForEachRo( p->pGia, pObj, i ) + pObj->Value += s_256Primes[ISO_MASK-2]; + // simulate nodes + Gia_ManForEachAnd( p->pGia, pObj, i ) + { + pObj->Value += Gia_ObjFanin0(pObj)->Value + Gia_IsoUpdate(p, Iter, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj)); + pObj->Value += Gia_ObjFanin1(pObj)->Value + Gia_IsoUpdate(p, Iter, Gia_ObjFaninId1(pObj, i), Gia_ObjFaninC1(pObj)); + } + // simulate COs + Gia_ManForEachCo( p->pGia, pObj, i ) + { + iObj = Gia_ObjId(p->pGia, pObj); + pObj->Value += Gia_ObjFanin0(pObj)->Value + Gia_IsoUpdate(p, Iter, Gia_ObjFaninId0(pObj, iObj), Gia_ObjFaninC0(pObj)); + } + // transfer flop values + Gia_ManForEachRiRo( p->pGia, pObjF, pObj, i ) + pObj->Value += pObjF->Value; +} +void Gia_IsoSimulateBack( Gia_IsoMan_t * p, int Iter ) +{ + Gia_Obj_t * pObj, * pObjF; + int i, iObj; + // simulate COs + Gia_ManForEachCo( p->pGia, pObj, i ) + { + iObj = Gia_ObjId(p->pGia, pObj); + Gia_ObjFanin0(pObj)->Value += pObj->Value + Gia_IsoUpdate(p, Iter, iObj, Gia_ObjFaninC0(pObj)); + } + // simulate objects + Gia_ManForEachAndReverse( p->pGia, pObj, i ) + { + Gia_ObjFanin0(pObj)->Value += pObj->Value + Gia_IsoUpdate(p, Iter, i, Gia_ObjFaninC0(pObj)); + Gia_ObjFanin1(pObj)->Value += pObj->Value + Gia_IsoUpdate(p, Iter, i, Gia_ObjFaninC1(pObj)); + } + // transfer flop values + Gia_ManForEachRiRo( p->pGia, pObjF, pObj, i ) + pObjF->Value += pObj->Value; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_IsoAssignOneClass2( Gia_IsoMan_t * p ) +{ + int i, iBegin = -1, nSize = -1; + // find two variable class + assert( Vec_IntSize(p->vClasses) > 0 ); + Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i ) + { + if ( nSize == 2 ) + break; + } + assert( nSize > 1 ); + + if ( nSize == 2 ) + { + assert( p->pUniques[Gia_IsoGetItem(p, iBegin)] == 0 ); + p->pUniques[Gia_IsoGetItem(p, iBegin)] = p->nUniques++; + p->nSingles++; + p->nEntries--; + + assert( p->pUniques[Gia_IsoGetItem(p, iBegin+1)] == 0 ); + p->pUniques[Gia_IsoGetItem(p, iBegin+1)] = p->nUniques++; + p->nSingles++; + p->nEntries--; + } + else + { + assert( p->pUniques[Gia_IsoGetItem(p, iBegin)] == 0 ); + p->pUniques[Gia_IsoGetItem(p, iBegin)] = p->nUniques++; + p->nSingles++; + p->nEntries--; + } + + for ( ; i < Vec_IntSize(p->vClasses) - 2; i += 2 ) + { + p->vClasses->pArray[i+0] = p->vClasses->pArray[i+2]; + p->vClasses->pArray[i+1] = p->vClasses->pArray[i+3]; + } + Vec_IntShrink( p->vClasses, Vec_IntSize(p->vClasses) - 2 ); + + printf( "Broke ties in class %d of size %d at level %d.\n", i/2, nSize, p->pLevels[Gia_IsoGetItem(p, iBegin)] ); +} + +void Gia_IsoAssignOneClass3( Gia_IsoMan_t * p ) +{ + int iBegin, nSize; + // find the last class + assert( Vec_IntSize(p->vClasses) > 0 ); + iBegin = Vec_IntEntry( p->vClasses, Vec_IntSize(p->vClasses) - 2 ); + nSize = Vec_IntEntry( p->vClasses, Vec_IntSize(p->vClasses) - 1 ); + Vec_IntShrink( p->vClasses, Vec_IntSize(p->vClasses) - 2 ); + + // assign the class + assert( nSize > 1 ); + if ( nSize == 2 ) + { + assert( p->pUniques[Gia_IsoGetItem(p, iBegin)] == 0 ); + p->pUniques[Gia_IsoGetItem(p, iBegin)] = p->nUniques++; + p->nSingles++; + p->nEntries--; + + assert( p->pUniques[Gia_IsoGetItem(p, iBegin+1)] == 0 ); + p->pUniques[Gia_IsoGetItem(p, iBegin+1)] = p->nUniques++; + p->nSingles++; + p->nEntries--; + } + else + { + assert( p->pUniques[Gia_IsoGetItem(p, iBegin)] == 0 ); + p->pUniques[Gia_IsoGetItem(p, iBegin)] = p->nUniques++; + p->nSingles++; + p->nEntries--; + } + printf( "Broke ties in last class of size %d at level %d.\n", nSize, p->pLevels[Gia_IsoGetItem(p, iBegin)] ); +} + +void Gia_IsoAssignOneClass( Gia_IsoMan_t * p, int fVerbose ) +{ + int i, k, iBegin0, iBegin, nSize, Shrink; + // find the classes with the highest level + assert( Vec_IntSize(p->vClasses) > 0 ); + iBegin0 = Vec_IntEntry( p->vClasses, Vec_IntSize(p->vClasses) - 2 ); + for ( i = Vec_IntSize(p->vClasses) - 2; i >= 0; i -= 2 ) + { + iBegin = Vec_IntEntry( p->vClasses, i ); + if ( p->pLevels[Gia_IsoGetItem(p, iBegin)] != p->pLevels[Gia_IsoGetItem(p, iBegin0)] ) + break; + } + i += 2; + assert( i >= 0 ); + // assign all classes starting with this one + for ( Shrink = i; i < Vec_IntSize(p->vClasses); i += 2 ) + { + iBegin = Vec_IntEntry( p->vClasses, i ); + nSize = Vec_IntEntry( p->vClasses, i + 1 ); + for ( k = 0; k < nSize; k++ ) + { + assert( p->pUniques[Gia_IsoGetItem(p, iBegin+k)] == 0 ); + p->pUniques[Gia_IsoGetItem(p, iBegin+k)] = p->nUniques++; +// Gia_ManObj(p->pGia, Gia_IsoGetItem(p, iBegin+k))->Value += s_256Primes[0]; /// new addition!!! + p->nSingles++; + p->nEntries--; + } + if ( fVerbose ) + printf( "Broke ties in class of size %d at level %d.\n", nSize, p->pLevels[Gia_IsoGetItem(p, iBegin)] ); + } + Vec_IntShrink( p->vClasses, Shrink ); +} + +/**Function************************************************************* + + Synopsis [Report topmost equiv nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_IsoReportTopmost( Gia_IsoMan_t * p ) +{ + Gia_Obj_t * pObj; + int i, k, iBegin, nSize, Counter = 0; + // go through equivalence classes + Gia_ManIncrementTravId( p->pGia ); + Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i ) + { +// printf( "%d(%d) ", nSize, p->pLevels[Gia_IsoGetItem(p, iBegin)] ); + for ( k = 0; k < nSize; k++ ) + { + pObj = Gia_ManObj( p->pGia, Gia_IsoGetItem(p, iBegin+k) ); + if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ObjSetTravIdCurrent( p->pGia, Gia_ObjFanin0(pObj) ); + Gia_ObjSetTravIdCurrent( p->pGia, Gia_ObjFanin1(pObj) ); + } + else if ( Gia_ObjIsRo(p->pGia, pObj) ) + Gia_ObjSetTravIdCurrent( p->pGia, Gia_ObjFanin0(Gia_ObjRoToRi(p->pGia, pObj)) ); + } + } +// printf( "\n" ); + + // report non-labeled nodes + Vec_IntForEachEntryDouble( p->vClasses, iBegin, nSize, i ) + { + for ( k = 0; k < nSize; k++ ) + { + pObj = Gia_ManObj( p->pGia, Gia_IsoGetItem(p, iBegin+k) ); + if ( !Gia_ObjIsTravIdCurrent(p->pGia, pObj) ) + { + printf( "%5d : ", ++Counter ); + printf( "Obj %6d : Level = %4d. iBegin = %4d. Size = %4d.\n", + Gia_ObjId(p->pGia, pObj), p->pLevels[Gia_ObjId(p->pGia, pObj)], iBegin, nSize ); + break; + } + } + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_IsoRecognizeMuxes( Gia_Man_t * pGia ) +{ + Gia_Obj_t * pObj, * pObjC, * pObj1, * pObj0; + int i; + Gia_ManForEachAnd( pGia, pObj, i ) + { + if ( !Gia_ObjIsMuxType(pObj) ) + continue; + pObjC = Gia_ObjRecognizeMux( pObj, &pObj1, &pObj0 ); + if ( Gia_Regular(pObj0) == Gia_Regular(pObj1) ) + { + // this is XOR + Gia_Regular(pObj)->Value += s_256Primes[233]; + Gia_Regular(pObjC)->Value += s_256Primes[234]; + Gia_Regular(pObj0)->Value += s_256Primes[234]; + } + else + { + // this is MUX + Gia_Regular(pObj)->Value += s_256Primes[235]; + Gia_Regular(pObjC)->Value += s_256Primes[236]; + Gia_Regular(pObj0)->Value += s_256Primes[237]; + Gia_Regular(pObj1)->Value += s_256Primes[237]; + } + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Gia_IsoDeriveEquivPos( Gia_Man_t * pGia, int fForward, int fVerbose ) +{ + int nIterMax = 10000; + int nFixedPoint = 1; + Gia_IsoMan_t * p; + Vec_Ptr_t * vEquivs = NULL; + int fRefined, fRefinedAll; + int i, c; + abctime clk = Abc_Clock(), clkTotal = Abc_Clock(); + assert( Gia_ManCiNum(pGia) > 0 ); + assert( Gia_ManPoNum(pGia) > 0 ); + + Gia_ManCleanValue( pGia ); + p = Gia_IsoManStart( pGia ); + Gia_IsoPrepare( p ); + Gia_IsoAssignUnique( p ); + p->timeStart = Abc_Clock() - clk; + if ( fVerbose ) + Gia_IsoPrint( p, 0, Abc_Clock() - clkTotal ); + +// Gia_IsoRecognizeMuxes( pGia ); + + i = 0; + if ( fForward ) + { + for ( c = 0; i < nIterMax && c < nFixedPoint+1; i++, c = fRefined ? 0 : c+1 ) + { + clk = Abc_Clock(); Gia_IsoSimulate( p, i ); p->timeSim += Abc_Clock() - clk; + clk = Abc_Clock(); fRefined = Gia_IsoSort( p ); p->timeRefine += Abc_Clock() - clk; + if ( fVerbose ) + Gia_IsoPrint( p, i+1, Abc_Clock() - clkTotal ); + } + } + else + { + while ( Vec_IntSize(p->vClasses) > 0 ) + { + for ( fRefinedAll = 1; i < nIterMax && fRefinedAll; ) + { + fRefinedAll = 0; + for ( c = 0; i < nIterMax && c < nFixedPoint+1; i++, c = fRefined ? 0 : c+1 ) + { + clk = Abc_Clock(); Gia_IsoSimulate( p, i ); p->timeSim += Abc_Clock() - clk; + clk = Abc_Clock(); fRefined = Gia_IsoSort( p ); p->timeRefine += Abc_Clock() - clk; + if ( fVerbose ) + Gia_IsoPrint( p, i+1, Abc_Clock() - clkTotal ); + fRefinedAll |= fRefined; + } + for ( c = 0; i < nIterMax && c < nFixedPoint+1; i++, c = fRefined ? 0 : c+1 ) + { + clk = Abc_Clock(); Gia_IsoSimulateBack( p, i ); p->timeSim += Abc_Clock() - clk; + clk = Abc_Clock(); fRefined = Gia_IsoSort( p ); p->timeRefine += Abc_Clock() - clk; + if ( fVerbose ) + Gia_IsoPrint( p, i+1, Abc_Clock() - clkTotal ); + fRefinedAll |= fRefined; + } + } + if ( !fRefinedAll ) + break; + } + +// Gia_IsoReportTopmost( p ); + + while ( Vec_IntSize(p->vClasses) > 0 ) + { + Gia_IsoAssignOneClass( p, fVerbose ); + for ( fRefinedAll = 1; i < nIterMax && fRefinedAll; ) + { + fRefinedAll = 0; + for ( c = 0; i < nIterMax && c < nFixedPoint; i++, c = fRefined ? 0 : c+1 ) + { + clk = Abc_Clock(); Gia_IsoSimulateBack( p, i ); p->timeSim += Abc_Clock() - clk; + clk = Abc_Clock(); fRefined = Gia_IsoSort( p ); p->timeRefine += Abc_Clock() - clk; + if ( fVerbose ) + Gia_IsoPrint( p, i+1, Abc_Clock() - clkTotal ); + fRefinedAll |= fRefined; + } + for ( c = 0; i < nIterMax && c < nFixedPoint; i++, c = fRefined ? 0 : c+1 ) + { + clk = Abc_Clock(); Gia_IsoSimulate( p, i ); p->timeSim += Abc_Clock() - clk; + clk = Abc_Clock(); fRefined = Gia_IsoSort( p ); p->timeRefine += Abc_Clock() - clk; + if ( fVerbose ) + Gia_IsoPrint( p, i+1, Abc_Clock() - clkTotal ); + fRefinedAll |= fRefined; +// if ( fRefined ) +// printf( "Refinedment happened.\n" ); + } + } + } + + if ( fVerbose ) + Gia_IsoPrint( p, i+2, Abc_Clock() - clkTotal ); + } +// Gia_IsoPrintClasses( p ); + if ( fVerbose ) + { + p->timeTotal = Abc_Clock() - clkTotal; + p->timeOther = p->timeTotal - p->timeStart - p->timeSim - p->timeRefine; + ABC_PRTP( "Start ", p->timeStart, p->timeTotal ); + ABC_PRTP( "Simulate ", p->timeSim, p->timeTotal ); + ABC_PRTP( "Refine ", p->timeRefine-p->timeSort, p->timeTotal ); + ABC_PRTP( "Sort ", p->timeSort, p->timeTotal ); + ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); + ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); + } + + if ( Gia_ManPoNum(p->pGia) > 1 ) + vEquivs = Gia_IsoCollectCosClasses( p, fVerbose ); + Gia_IsoManTransferUnique( p ); + Gia_IsoManStop( p ); + + return vEquivs; +} + + + + +/**Function************************************************************* + + Synopsis [Finds canonical ordering of CIs/COs/nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ObjCompareByValue( Gia_Obj_t ** pp1, Gia_Obj_t ** pp2 ) +{ + Gia_Obj_t * pObj1 = *pp1; + Gia_Obj_t * pObj2 = *pp2; +// assert( pObj1->Value != pObj2->Value ); + return (int)pObj1->Value - (int)pObj2->Value; +} +void Gia_ManFindCaninicalOrder_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vAnds ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + assert( Gia_ObjIsAnd(pObj) ); + if ( !Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) || !Gia_ObjIsAnd(Gia_ObjFanin1(pObj)) ) + { + Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin0(pObj), vAnds ); + Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin1(pObj), vAnds ); + } + else + { + assert( Gia_ObjFanin0(pObj)->Value != Gia_ObjFanin1(pObj)->Value ); + if ( Gia_ObjFanin0(pObj)->Value < Gia_ObjFanin1(pObj)->Value ) + { + Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin0(pObj), vAnds ); + Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin1(pObj), vAnds ); + } + else + { + Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin1(pObj), vAnds ); + Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin0(pObj), vAnds ); + } + } + Vec_IntPush( vAnds, Gia_ObjId(p, pObj) ); +} +void Gia_ManFindCaninicalOrder( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos, Vec_Int_t ** pvPiPerm ) +{ + Vec_Ptr_t * vTemp; + Gia_Obj_t * pObj; + int i; + + vTemp = Vec_PtrAlloc( 1000 ); + Vec_IntClear( vCis ); + Vec_IntClear( vAnds ); + Vec_IntClear( vCos ); + + // assign unique IDs to PIs + Vec_PtrClear( vTemp ); + Gia_ManForEachPi( p, pObj, i ) + Vec_PtrPush( vTemp, pObj ); + Vec_PtrSort( vTemp, (int (*)(const void *, const void *))Gia_ObjCompareByValue ); + // create the result + Vec_PtrForEachEntry( Gia_Obj_t *, vTemp, pObj, i ) + Vec_IntPush( vCis, Gia_ObjId(p, pObj) ); + // remember PI permutation + if ( pvPiPerm ) + { + *pvPiPerm = Vec_IntAlloc( Gia_ManPiNum(p) ); + Vec_PtrForEachEntry( Gia_Obj_t *, vTemp, pObj, i ) + Vec_IntPush( *pvPiPerm, Gia_ObjCioId(pObj) ); + } + + // assign unique IDs to POs + if ( Gia_ManPoNum(p) == 1 ) + Vec_IntPush( vCos, Gia_ObjId(p, Gia_ManPo(p, 0)) ); + else + { + Vec_PtrClear( vTemp ); + Gia_ManForEachPo( p, pObj, i ) + { + pObj->Value = Abc_Var2Lit( Gia_ObjFanin0(pObj)->Value, Gia_ObjFaninC0(pObj) ); + Vec_PtrPush( vTemp, pObj ); + } + Vec_PtrSort( vTemp, (int (*)(const void *, const void *))Gia_ObjCompareByValue ); + Vec_PtrForEachEntry( Gia_Obj_t *, vTemp, pObj, i ) + Vec_IntPush( vCos, Gia_ObjId(p, pObj) ); + } + + // assign unique IDs to ROs + Vec_PtrClear( vTemp ); + Gia_ManForEachRo( p, pObj, i ) + Vec_PtrPush( vTemp, pObj ); + Vec_PtrSort( vTemp, (int (*)(const void *, const void *))Gia_ObjCompareByValue ); + // create the result + Vec_PtrForEachEntry( Gia_Obj_t *, vTemp, pObj, i ) + { + Vec_IntPush( vCis, Gia_ObjId(p, pObj) ); + Vec_IntPush( vCos, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)) ); + } + Vec_PtrFree( vTemp ); + + // assign unique IDs to internal nodes + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); + Gia_ManForEachObjVec( vCis, p, pObj, i ) + Gia_ObjSetTravIdCurrent( p, pObj ); + Gia_ManForEachObjVec( vCos, p, pObj, i ) + Gia_ManFindCaninicalOrder_rec( p, Gia_ObjFanin0(pObj), vAnds ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManIsoCanonicize( Gia_Man_t * p, int fVerbose ) +{ + Gia_Man_t * pRes = NULL; + Vec_Int_t * vCis, * vAnds, * vCos; + Vec_Ptr_t * vEquiv; + if ( Gia_ManCiNum(p) == 0 ) // const AIG + { + assert( Gia_ManPoNum(p) == 1 ); + assert( Gia_ManObjNum(p) == 2 ); + return Gia_ManDup(p); + } + // derive canonical values + vEquiv = Gia_IsoDeriveEquivPos( p, 0, fVerbose ); + Vec_VecFreeP( (Vec_Vec_t **)&vEquiv ); + // find canonical order of CIs/COs/nodes + // find canonical order + vCis = Vec_IntAlloc( Gia_ManCiNum(p) ); + vAnds = Vec_IntAlloc( Gia_ManAndNum(p) ); + vCos = Vec_IntAlloc( Gia_ManCoNum(p) ); + Gia_ManFindCaninicalOrder( p, vCis, vAnds, vCos, NULL ); + // derive the new AIG + pRes = Gia_ManDupFromVecs( p, vCis, vAnds, vCos, Gia_ManRegNum(p) ); + // cleanup + Vec_IntFree( vCis ); + Vec_IntFree( vAnds ); + Vec_IntFree( vCos ); + return pRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Str_t * Gia_ManIsoFindString( Gia_Man_t * p, int iPo, int fVerbose, Vec_Int_t ** pvPiPerm ) +{ + Gia_Man_t * pPart; + Vec_Ptr_t * vEquiv; + Vec_Int_t * vCis, * vAnds, * vCos; + Vec_Str_t * vStr; + // duplicate + pPart = Gia_ManDupCones( p, &iPo, 1, 1 ); +//Gia_ManPrint( pPart ); + assert( Gia_ManPoNum(pPart) == 1 ); + if ( Gia_ManCiNum(pPart) == 0 ) // const AIG + { + assert( Gia_ManPoNum(pPart) == 1 ); + assert( Gia_ManObjNum(pPart) == 2 ); + vStr = Gia_AigerWriteIntoMemoryStr( pPart ); + Gia_ManStop( pPart ); + if ( pvPiPerm ) + *pvPiPerm = Vec_IntAlloc( 0 ); + return vStr; + } + // derive canonical values + vEquiv = Gia_IsoDeriveEquivPos( pPart, 0, fVerbose ); + Vec_VecFreeP( (Vec_Vec_t **)&vEquiv ); + // find canonical order + vCis = Vec_IntAlloc( Gia_ManCiNum(pPart) ); + vAnds = Vec_IntAlloc( Gia_ManAndNum(pPart) ); + vCos = Vec_IntAlloc( Gia_ManCoNum(pPart) ); + Gia_ManFindCaninicalOrder( pPart, vCis, vAnds, vCos, pvPiPerm ); +//printf( "Internal: " ); +//Vec_IntPrint( vCis ); + // derive the AIGER string + vStr = Gia_AigerWriteIntoMemoryStrPart( pPart, vCis, vAnds, vCos, Gia_ManRegNum(pPart) ); + // cleanup + Vec_IntFree( vCis ); + Vec_IntFree( vAnds ); + Vec_IntFree( vCos ); + Gia_ManStop( pPart ); + return vStr; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Vec_IntCountNonTrivial( Vec_Ptr_t * vEquivs, int * pnUsed ) +{ + Vec_Int_t * vClass; + int i, nClasses = 0; + *pnUsed = 0; + Vec_PtrForEachEntry( Vec_Int_t *, vEquivs, vClass, i ) + { + if ( Vec_IntSize(vClass) < 2 ) + continue; + nClasses++; + (*pnUsed) += Vec_IntSize(vClass); + } + return nClasses; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManIsoReduce( Gia_Man_t * pInit, Vec_Ptr_t ** pvPosEquivs, Vec_Ptr_t ** pvPiPerms, int fEstimate, int fDualOut, int fVerbose, int fVeryVerbose ) +{ + Gia_Man_t * p, * pPart; + Vec_Ptr_t * vEquivs, * vEquivs2, * vStrings; + Vec_Int_t * vRemain, * vLevel, * vLevel2; + Vec_Str_t * vStr, * vStr2; + int i, k, s, sStart, iPo, Counter; + int nClasses, nUsedPos; + abctime clk = Abc_Clock(); + if ( pvPosEquivs ) + *pvPosEquivs = NULL; + if ( pvPiPerms ) + *pvPiPerms = Vec_PtrStart( Gia_ManPoNum(pInit) ); + + if ( fDualOut ) + { + assert( (Gia_ManPoNum(pInit) & 1) == 0 ); + if ( Gia_ManPoNum(pInit) == 2 ) + return Gia_ManDup(pInit); + p = Gia_ManTransformMiter( pInit ); + p = Gia_ManSeqStructSweep( pPart = p, 1, 1, 0 ); + Gia_ManStop( pPart ); + } + else + { + if ( Gia_ManPoNum(pInit) == 1 ) + return Gia_ManDup(pInit); + p = pInit; + } + + // create preliminary equivalences + vEquivs = Gia_IsoDeriveEquivPos( p, 1, fVeryVerbose ); + if ( vEquivs == NULL ) + { + if ( fDualOut ) + Gia_ManStop( p ); + return NULL; + } + nClasses = Vec_IntCountNonTrivial( vEquivs, &nUsedPos ); + printf( "Reduced %d outputs to %d candidate classes (%d outputs are in %d non-trivial classes). ", + Gia_ManPoNum(p), Vec_PtrSize(vEquivs), nUsedPos, nClasses ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + if ( fEstimate ) + { + Vec_VecFree( (Vec_Vec_t *)vEquivs ); + return Gia_ManDup(pInit); + } + + // perform refinement of equivalence classes + Counter = 0; + vEquivs2 = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Vec_Int_t *, vEquivs, vLevel, i ) + { + if ( Vec_IntSize(vLevel) < 2 ) + { + Vec_PtrPush( vEquivs2, Vec_IntDup(vLevel) ); + for ( k = 0; k < Vec_IntSize(vLevel); k++ ) + if ( ++Counter % 100 == 0 ) + printf( "%6d finished...\r", Counter ); + continue; + } + + if ( fVerbose ) + { + iPo = Vec_IntEntry(vLevel, 0); + printf( "%6d %6d %6d : ", i, Vec_IntSize(vLevel), iPo ); + pPart = Gia_ManDupCones( p, &iPo, 1, 1 ); + Gia_ManPrintStats(pPart, NULL); + Gia_ManStop( pPart ); + } + + sStart = Vec_PtrSize( vEquivs2 ); + vStrings = Vec_PtrAlloc( 100 ); + Vec_IntForEachEntry( vLevel, iPo, k ) + { + if ( ++Counter % 100 == 0 ) + printf( "%6d finished...\r", Counter ); + assert( pvPiPerms == NULL || Vec_PtrArray(*pvPiPerms)[iPo] == NULL ); + vStr = Gia_ManIsoFindString( p, iPo, 0, pvPiPerms ? (Vec_Int_t **)Vec_PtrArray(*pvPiPerms) + iPo : NULL ); + +// printf( "Output %2d : ", iPo ); +// Vec_IntPrint( Vec_PtrArray(*pvPiPerms)[iPo] ); + + // check if this string already exists + Vec_PtrForEachEntry( Vec_Str_t *, vStrings, vStr2, s ) + if ( Vec_StrCompareVec(vStr, vStr2) == 0 ) + break; + if ( s == Vec_PtrSize(vStrings) ) + { + Vec_PtrPush( vStrings, vStr ); + Vec_PtrPush( vEquivs2, Vec_IntAlloc(8) ); + } + else + Vec_StrFree( vStr ); + // add this entry to the corresponding level + vLevel2 = (Vec_Int_t *)Vec_PtrEntry( vEquivs2, sStart + s ); + Vec_IntPush( vLevel2, iPo ); + } +// if ( Vec_PtrSize(vEquivs2) - sStart > 1 ) +// printf( "Refined class %d into %d classes.\n", i, Vec_PtrSize(vEquivs2) - sStart ); + Vec_VecFree( (Vec_Vec_t *)vStrings ); + } + assert( Counter == Gia_ManPoNum(p) ); + Vec_VecSortByFirstInt( (Vec_Vec_t *)vEquivs2, 0 ); + Vec_VecFree( (Vec_Vec_t *)vEquivs ); + vEquivs = vEquivs2; + + // collect the first ones + vRemain = Vec_IntAlloc( 100 ); + Vec_PtrForEachEntry( Vec_Int_t *, vEquivs, vLevel, i ) + Vec_IntPush( vRemain, Vec_IntEntry(vLevel, 0) ); + + if ( fDualOut ) + { + Vec_Int_t * vTemp = Vec_IntAlloc( Vec_IntSize(vRemain) ); + int i, Entry; + Vec_IntForEachEntry( vRemain, Entry, i ) + { +// printf( "%d ", Entry ); + Vec_IntPush( vTemp, 2*Entry ); + Vec_IntPush( vTemp, 2*Entry+1 ); + } +// printf( "\n" ); + Vec_IntFree( vRemain ); + vRemain = vTemp; + Gia_ManStop( p ); + p = pInit; + } + + + // derive the resulting AIG + pPart = Gia_ManDupCones( p, Vec_IntArray(vRemain), Vec_IntSize(vRemain), 0 ); + Vec_IntFree( vRemain ); + // report the results + nClasses = Vec_IntCountNonTrivial( vEquivs, &nUsedPos ); + if ( !fDualOut ) + printf( "Reduced %d outputs to %d equivalence classes (%d outputs are in %d non-trivial classes). ", + Gia_ManPoNum(p), Vec_PtrSize(vEquivs), nUsedPos, nClasses ); + else + printf( "Reduced %d dual outputs to %d dual outputs. ", Gia_ManPoNum(p)/2, Gia_ManPoNum(pPart)/2 ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + if ( fVerbose ) + { + printf( "Nontrivial classes:\n" ); + Vec_VecPrintInt( (Vec_Vec_t *)vEquivs, 1 ); + } + if ( pvPosEquivs ) + *pvPosEquivs = vEquivs; + else + Vec_VecFree( (Vec_Vec_t *)vEquivs ); +// Gia_ManStopP( &pPart ); + return pPart; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_IsoTestOld( Gia_Man_t * p, int fVerbose ) +{ + Vec_Ptr_t * vEquivs; + abctime clk = Abc_Clock(); + vEquivs = Gia_IsoDeriveEquivPos( p, 0, fVerbose ); + printf( "Reduced %d outputs to %d. ", Gia_ManPoNum(p), vEquivs ? Vec_PtrSize(vEquivs) : 1 ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + if ( fVerbose && vEquivs && Gia_ManPoNum(p) != Vec_PtrSize(vEquivs) ) + { + printf( "Nontrivial classes:\n" ); +// Vec_VecPrintInt( (Vec_Vec_t *)vEquivs, 1 ); + } + Vec_VecFreeP( (Vec_Vec_t **)&vEquivs ); +} + +/**Function************************************************************* + + Synopsis [Test remapping of CEXes for isomorphic POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_IsoTestGenPerm( int nPis ) +{ + Vec_Int_t * vPerm; + int i, * pArray; + vPerm = Vec_IntStartNatural( nPis ); + pArray = Vec_IntArray( vPerm ); + for ( i = 0; i < nPis; i++ ) + { + int iNew = rand() % nPis; + ABC_SWAP( int, pArray[i], pArray[iNew] ); + } + return vPerm; +} +void Gia_IsoTest( Gia_Man_t * p, Abc_Cex_t * pCex, int fVerbose ) +{ + Abc_Cex_t * pCexNew; + Vec_Int_t * vPiPerm; + Vec_Ptr_t * vPosEquivs, * vPisPerm; + Vec_Int_t * vPerm0, * vPerm1; + Gia_Man_t * pPerm, * pDouble, * pAig; + assert( Gia_ManPoNum(p) == 1 ); + assert( Gia_ManRegNum(p) > 0 ); + // generate random permutation of PIs + vPiPerm = Gia_IsoTestGenPerm( Gia_ManPiNum(p) ); + printf( "Considering random permutation of the primary inputs of the AIG:\n" ); + Vec_IntPrint( vPiPerm ); + // create AIG with two primary outputs (original and permuted) + pPerm = Gia_ManDupPerm( p, vPiPerm ); + pDouble = Gia_ManDupAppendNew( p, pPerm ); +//Gia_AigerWrite( pDouble, "test.aig", 0, 0, 0 ); + + // analyze the two-output miter + pAig = Gia_ManIsoReduce( pDouble, &vPosEquivs, &vPisPerm, 0, 0, 0, 0 ); + Vec_VecFree( (Vec_Vec_t *)vPosEquivs ); + + // given CEX for output 0, derive CEX for output 1 + vPerm0 = (Vec_Int_t *)Vec_PtrEntry( vPisPerm, 0 ); + vPerm1 = (Vec_Int_t *)Vec_PtrEntry( vPisPerm, 1 ); + pCexNew = Abc_CexPermuteTwo( pCex, vPerm0, vPerm1 ); + Vec_VecFree( (Vec_Vec_t *)vPisPerm ); + + // check that original CEX and the resulting CEX is valid + if ( Gia_ManVerifyCex(p, pCex, 0) ) + printf( "CEX for the init AIG is valid.\n" ); + else + printf( "CEX for the init AIG is not valid.\n" ); + if ( Gia_ManVerifyCex(pPerm, pCexNew, 0) ) + printf( "CEX for the perm AIG is valid.\n" ); + else + printf( "CEX for the perm AIG is not valid.\n" ); + // delete + Gia_ManStop( pAig ); + Gia_ManStop( pDouble ); + Gia_ManStop( pPerm ); + Vec_IntFree( vPiPerm ); + Abc_CexFree( pCexNew ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaIso2.c b/yosys/abc/src/aig/gia/giaIso2.c new file mode 100644 index 00000000000..22b1d09eca1 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaIso2.c @@ -0,0 +1,776 @@ +/**CFile**************************************************************** + + FileName [gia.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/vec/vecHsh.h" +#include "misc/vec/vecWec.h" + + +ABC_NAMESPACE_IMPL_START + + +#define ISO_MASK 0xFF +static unsigned int s_256Primes[ISO_MASK+1] = +{ + 0x984b6ad9,0x18a6eed3,0x950353e2,0x6222f6eb,0xdfbedd47,0xef0f9023,0xac932a26,0x590eaf55, + 0x97d0a034,0xdc36cd2e,0x22736b37,0xdc9066b0,0x2eb2f98b,0x5d9c7baf,0x85747c9e,0x8aca1055, + 0x50d66b74,0x2f01ae9e,0xa1a80123,0x3e1ce2dc,0xebedbc57,0x4e68bc34,0x855ee0cf,0x17275120, + 0x2ae7f2df,0xf71039eb,0x7c283eec,0x70cd1137,0x7cf651f3,0xa87bfa7a,0x14d87f02,0xe82e197d, + 0x8d8a5ebe,0x1e6a15dc,0x197d49db,0x5bab9c89,0x4b55dea7,0x55dede49,0x9a6a8080,0xe5e51035, + 0xe148d658,0x8a17eb3b,0xe22e4b38,0xe5be2a9a,0xbe938cbb,0x3b981069,0x7f9c0c8e,0xf756df10, + 0x8fa783f7,0x252062ce,0x3dc46b4b,0xf70f6432,0x3f378276,0x44b137a1,0x2bf74b77,0x04892ed6, + 0xfd318de1,0xd58c235e,0x94c6d25b,0x7aa5f218,0x35c9e921,0x5732fbbb,0x06026481,0xf584a44f, + 0x946e1b5f,0x8463d5b2,0x4ebca7b2,0x54887b15,0x08d1e804,0x5b22067d,0x794580f6,0xb351ea43, + 0xbce555b9,0x19ae2194,0xd32f1396,0x6fc1a7f1,0x1fd8a867,0x3a89fdb0,0xea49c61c,0x25f8a879, + 0xde1e6437,0x7c74afca,0x8ba63e50,0xb1572074,0xe4655092,0xdb6f8b1c,0xc2955f3c,0x327f85ba, + 0x60a17021,0x95bd261d,0xdea94f28,0x04528b65,0xbe0109cc,0x26dd5688,0x6ab2729d,0xc4f029ce, + 0xacf7a0be,0x4c912f55,0x34c06e65,0x4fbb938e,0x1533fb5f,0x03da06bd,0x48262889,0xc2523d7d, + 0x28a71d57,0x89f9713a,0xf574c551,0x7a99deb5,0x52834d91,0x5a6f4484,0xc67ba946,0x13ae698f, + 0x3e390f34,0x34fc9593,0x894c7932,0x6cf414a3,0xdb7928ab,0x13a3b8a3,0x4b381c1d,0xa10b54cb, + 0x55359d9d,0x35a3422a,0x58d1b551,0x0fd4de20,0x199eb3f4,0x167e09e2,0x3ee6a956,0x5371a7fa, + 0xd424efda,0x74f521c5,0xcb899ff6,0x4a42e4f4,0x747917b6,0x4b08df0b,0x090c7a39,0x11e909e4, + 0x258e2e32,0xd9fad92d,0x48fe5f69,0x0545cde6,0x55937b37,0x9b4ae4e4,0x1332b40e,0xc3792351, + 0xaff982ef,0x4dba132a,0x38b81ef1,0x28e641bf,0x227208c1,0xec4bbe37,0xc4e1821c,0x512c9d09, + 0xdaef1257,0xb63e7784,0x043e04d7,0x9c2cea47,0x45a0e59a,0x281315ca,0x849f0aac,0xa4071ed3, + 0x0ef707b3,0xfe8dac02,0x12173864,0x471f6d46,0x24a53c0a,0x35ab9265,0xbbf77406,0xa2144e79, + 0xb39a884a,0x0baf5b6d,0xcccee3dd,0x12c77584,0x2907325b,0xfd1adcd2,0xd16ee972,0x345ad6c1, + 0x315ebe66,0xc7ad2b8d,0x99e82c8d,0xe52da8c8,0xba50f1d3,0x66689cd8,0x2e8e9138,0x43e15e74, + 0xf1ced14d,0x188ec52a,0xe0ef3cbb,0xa958aedc,0x4107a1bc,0x5a9e7a3e,0x3bde939f,0xb5b28d5a, + 0x596fe848,0xe85ad00c,0x0b6b3aae,0x44503086,0x25b5695c,0xc0c31dcd,0x5ee617f0,0x74d40c3a, + 0xd2cb2b9f,0x1e19f5fa,0x81e24faf,0xa01ed68f,0xcee172fc,0x7fdf2e4d,0x002f4774,0x664f82dd, + 0xc569c39a,0xa2d4dcbe,0xaadea306,0xa4c947bf,0xa413e4e3,0x81fb5486,0x8a404970,0x752c980c, + 0x98d1d881,0x5c932c1e,0xeee65dfb,0x37592cdd,0x0fd4e65b,0xad1d383f,0x62a1452f,0x8872f68d, + 0xb58c919b,0x345c8ee3,0xb583a6d6,0x43d72cb3,0x77aaa0aa,0xeb508242,0xf2db64f8,0x86294328, + 0x82211731,0x1239a9d5,0x673ba5de,0xaf4af007,0x44203b19,0x2399d955,0xa175cd12,0x595928a7, + 0x6918928b,0xde3126bb,0x6c99835c,0x63ba1fa2,0xdebbdff0,0x3d02e541,0xd6f7aac6,0xe80b4cd0, + 0xd0fa29f1,0x804cac5e,0x2c226798,0x462f624c,0xad05b377,0x22924fcd,0xfbea205c,0x1b47586d +}; + +static int s_PrimeC = 49; +//static int s_PrimeC = 1; + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Gia_Iso2Man_t_ Gia_Iso2Man_t; +struct Gia_Iso2Man_t_ +{ + Gia_Man_t * pGia; + int nObjs; + int nUniques; + // internal data + Vec_Int_t * vUniques; // unique numbers + Vec_Int_t * vTied; // tied objects + Vec_Int_t * vTable; // hash table + Vec_Int_t * vPlaces; // used places in the table + Vec_Ptr_t * vSingles; // singleton objects + // isomorphism check + Vec_Int_t * vVec0; // isomorphism map + Vec_Int_t * vVec1; // isomorphism map + Vec_Int_t * vMap0; // isomorphism map + Vec_Int_t * vMap1; // isomorphism map + // statistics + int nIters; + abctime timeStart; + abctime timeSim; + abctime timeRefine; + abctime timeSort; + abctime timeOther; + abctime timeTotal; +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_Iso2ManCollectTies( Gia_Man_t * p ) +{ + Vec_Int_t * vTies; + Gia_Obj_t * pObj; + int i; + vTies = Vec_IntAlloc( Gia_ManCandNum(p) ); + Gia_ManForEachCand( p, pObj, i ) + Vec_IntPush( vTies, i ); + return vTies; +} +void Gia_Iso2ManPrepare( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachObj( p, pObj, i ) + pObj->Value = Gia_ObjIsAnd(pObj) ? 1 + Abc_MaxInt(Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value) : 0; + Gia_ManConst0(p)->Value = s_256Primes[ISO_MASK]; + Gia_ManForEachObj1( p, pObj, i ) + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = s_256Primes[pObj->Value & ISO_MASK] + s_256Primes[ISO_MASK - 10 + Gia_ObjFaninC0(pObj) + Gia_ObjFaninC1(pObj)]; + else if ( Gia_ObjIsPi(p, pObj) ) + pObj->Value = s_256Primes[ISO_MASK-1]; + else if ( Gia_ObjIsRo(p, pObj) ) + pObj->Value = s_256Primes[ISO_MASK-2]; +} +void Gia_Iso2ManPropagate( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObjRo; + int i; + Gia_ManForEachObj1( p, pObj, i ) + if ( Gia_ObjIsAnd(pObj) ) + { + pObj->Value += (Gia_ObjFaninC0(pObj) + s_PrimeC) * Gia_ObjFanin0(pObj)->Value + (Gia_ObjFaninC1(pObj) + s_PrimeC) * Gia_ObjFanin1(pObj)->Value; + if ( Gia_ObjFaninC0(pObj) == Gia_ObjFaninC1(pObj) && Gia_ObjFanin0(pObj)->Value == Gia_ObjFanin1(pObj)->Value ) + pObj->Value += s_256Primes[ISO_MASK - 11]; + } + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value += (Gia_ObjFaninC0(pObj) + s_PrimeC) * Gia_ObjFanin0(pObj)->Value; + Gia_ManForEachRiRo( p, pObj, pObjRo, i ) + { + pObjRo->Value += pObj->Value; + if ( pObjRo == Gia_ObjFanin0(pObj) ) + pObjRo->Value += s_256Primes[ISO_MASK - 12]; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Gia_Iso2ManCone_rec( Gia_Man_t * p, int Id, int Level ) +{ + Gia_Obj_t * pObj; + if ( Level == 0 ) + return 0; + if ( Gia_ObjIsTravIdCurrentId(p, Id) ) + return 0; + Gia_ObjSetTravIdCurrentId(p, Id); + pObj = Gia_ManObj( p, Id ); + if ( Gia_ObjIsAnd(pObj) ) + return pObj->Value + Gia_Iso2ManCone_rec( p, Gia_ObjFaninId0(pObj, Id), Level-1 ) + Gia_Iso2ManCone_rec( p, Gia_ObjFaninId1(pObj, Id), Level-1 ); + if ( Gia_ObjIsPi(p, pObj) ) + return pObj->Value; + if ( Gia_ObjIsRo(p, pObj) ) + return pObj->Value + Gia_Iso2ManCone_rec( p, Gia_ObjId(p, Gia_ObjFanin0(Gia_ObjRoToRi(p, pObj))), Level ); + assert( Gia_ObjIsConst0(pObj) ); + return pObj->Value; +} +unsigned Gia_Iso2ManCone( Gia_Man_t * p, int Id, int Level ) +{ + Gia_ManIncrementTravId( p ); + return Gia_Iso2ManCone_rec( p, Id, Level ); +} +void Gia_Iso2ManUpdate( Gia_Iso2Man_t * p, int Level ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachObjVec( p->vTied, p->pGia, pObj, i ) + pObj->Value += Gia_Iso2ManCone( p->pGia, Gia_ObjId(p->pGia, pObj), Level ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Iso2Man_t * Gia_Iso2ManStart( Gia_Man_t * pGia ) +{ + Gia_Iso2Man_t * p; + p = ABC_CALLOC( Gia_Iso2Man_t, 1 ); + p->pGia = pGia; + p->nObjs = Gia_ManObjNum( pGia ); + p->nUniques = 0; + // internal data + p->vUniques = Vec_IntStartFull( p->nObjs ); + p->vTied = Gia_Iso2ManCollectTies( pGia ); + p->vTable = Vec_IntStart( Abc_PrimeCudd(1*p->nObjs) ); + p->vPlaces = Vec_IntAlloc( 1000 ); + p->vSingles = Vec_PtrAlloc( 1000 ); + p->vVec0 = Vec_IntAlloc( 10000 ); + p->vVec1 = Vec_IntAlloc( 10000 ); + p->vMap0 = Vec_IntStart( p->nObjs ); + p->vMap1 = Vec_IntStart( p->nObjs ); + // add constant 0 object + Vec_IntWriteEntry( p->vUniques, 0, p->nUniques++ ); + return p; +} +void Gia_Iso2ManStop( Gia_Iso2Man_t * p ) +{ + Vec_IntFree( p->vUniques ); + Vec_IntFree( p->vTied ); + Vec_IntFree( p->vTable ); + Vec_IntFree( p->vPlaces ); + Vec_PtrFree( p->vSingles ); + Vec_IntFree( p->vMap0 ); + Vec_IntFree( p->vMap1 ); + Vec_IntFree( p->vVec0 ); + Vec_IntFree( p->vVec1 ); + ABC_FREE( p ); +} +void Gia_Iso2ManPrint( Gia_Iso2Man_t * p, abctime Time, int fVerbose ) +{ + if ( !fVerbose ) + return; + printf( "Iter %4d : ", p->nIters++ ); + printf( "Entries =%8d. ", Vec_IntSize(p->vTied) ); + printf( "Uniques =%8d. ", p->nUniques ); + printf( "Singles =%8d. ", Vec_PtrSize(p->vSingles) ); + printf( "%9.2f sec", (float)(Time)/(float)(CLOCKS_PER_SEC) ); + printf( "\n" ); + fflush( stdout ); +} + +/**Function************************************************************* + + Synopsis [Uniqifies objects using their signature.] + + Description [Assumes the tied objects are in p->vTied. Assumes that + updated signature (pObj->Value) is assigned to these objects. Returns + the array of unique objects p->vSingles sorted by signature. Compacts + the array of tied objects p->vTied.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ObjCompareByValue2( Gia_Obj_t ** pp1, Gia_Obj_t ** pp2 ) { return (int)(*pp1)->Value - (int)(*pp2)->Value; } +int Gia_Iso2ManUniqify( Gia_Iso2Man_t * p ) +{ + int fVerify = 0; + Gia_Obj_t * pObj, * pTemp; + int * pTable = Vec_IntArray(p->vTable); + int i, k, nSize = Vec_IntSize(p->vTable); + + if ( fVerify ) + for ( k = 0; k < nSize; k++ ) + assert( pTable[k] == 0 ); + if ( fVerify ) + Gia_ManForEachObjVec( p->vTied, p->pGia, pObj, i ) + assert( pObj->fMark0 == 0 ); + +#if 0 + Gia_ManForEachObjVec( p->vTied, p->pGia, pObj, i ) + { + printf( "%3d : ", Gia_ObjId(p->pGia, pObj) ); + Extra_PrintBinary( stdout, &pObj->Value, 32 ); + printf( "\n" ); + } +#endif + + // add objects to the table + Vec_IntClear( p->vPlaces ); + Gia_ManForEachObjVec( p->vTied, p->pGia, pObj, i ) + { + for ( k = pObj->Value % nSize; (pTemp = pTable[k] ? Gia_ManObj(p->pGia, pTable[k]) : NULL); k = (k + 1) % nSize ) + if ( pTemp->Value == pObj->Value ) + { + pTemp->fMark0 = 1; + pObj->fMark0 = 1; + break; + } + if ( pTemp != NULL ) + continue; + pTable[k] = Gia_ObjId(p->pGia, pObj); + Vec_IntPush( p->vPlaces, k ); + } + // clean the table + Vec_IntForEachEntry( p->vPlaces, k, i ) + pTable[k] = 0; + // collect singleton objects and compact tied objects + k = 0; + Vec_PtrClear( p->vSingles ); + Gia_ManForEachObjVec( p->vTied, p->pGia, pObj, i ) + if ( pObj->fMark0 == 0 ) + Vec_PtrPush( p->vSingles, pObj ); + else + { + pObj->fMark0 = 0; + Vec_IntWriteEntry( p->vTied, k++, Gia_ObjId(p->pGia, pObj) ); + } + Vec_IntShrink( p->vTied, k ); + // sort singletons + Vec_PtrSort( p->vSingles, (int (*)(const void *, const void *))Gia_ObjCompareByValue2 ); + // add them to unique and increment signature + Vec_PtrForEachEntry( Gia_Obj_t *, p->vSingles, pObj, i ) + { + pObj->Value += s_256Primes[p->nUniques & ISO_MASK]; + assert( Vec_IntEntry(p->vUniques, Gia_ObjId(p->pGia, pObj)) == -1 ); + Vec_IntWriteEntry( p->vUniques, Gia_ObjId(p->pGia, pObj), p->nUniques++ ); + } + return Vec_PtrSize( p->vSingles ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Gia_Iso2ManDerivePoClasses( Gia_Man_t * pGia ) +{ + Vec_Wec_t * vEquivs; + Vec_Int_t * vValues; + Vec_Int_t * vMap; + Gia_Obj_t * pObj; + int i; + vValues = Vec_IntAlloc( Gia_ManPoNum(pGia) ); + Gia_ManForEachPo( pGia, pObj, i ) + Vec_IntPush( vValues, pObj->Value ); + vMap = Hsh_IntManHashArray( vValues, 1 ); + Vec_IntFree( vValues ); + vEquivs = Vec_WecCreateClasses( vMap ); + Vec_IntFree( vMap ); + return vEquivs; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_Iso2ManCollectOrder2_rec( Gia_Man_t * p, int Id, Vec_Int_t * vVec ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjIsTravIdCurrentId(p, Id) ) + return; + Gia_ObjSetTravIdCurrentId(p, Id); + pObj = Gia_ManObj( p, Id ); + if ( Gia_ObjIsAnd(pObj) ) + { + if ( Gia_ObjFanin0(pObj)->Value <= Gia_ObjFanin1(pObj)->Value ) + { + Gia_Iso2ManCollectOrder2_rec( p, Gia_ObjFaninId0(pObj, Id), vVec ); + Gia_Iso2ManCollectOrder2_rec( p, Gia_ObjFaninId1(pObj, Id), vVec ); + } + else + { + Gia_Iso2ManCollectOrder2_rec( p, Gia_ObjFaninId1(pObj, Id), vVec ); + Gia_Iso2ManCollectOrder2_rec( p, Gia_ObjFaninId0(pObj, Id), vVec ); + } + } + else if ( Gia_ObjIsCo(pObj) ) + { + Gia_Iso2ManCollectOrder2_rec( p, Gia_ObjFaninId0(pObj, Id), vVec ); + } + else if ( Gia_ObjIsPi(p, pObj) ) + { + } + else assert( Gia_ObjIsConst0(pObj) ); + Vec_IntPush( vVec, Id ); +} +Vec_Int_t * Gia_Iso2ManCollectOrder2( Gia_Man_t * pGia, int * pPos, int nPos ) +{ + Vec_Int_t * vVec; + int i; + vVec = Vec_IntAlloc( 1000 ); + Gia_ManIncrementTravId( pGia ); + for ( i = 0; i < nPos; i++ ) + Gia_Iso2ManCollectOrder2_rec( pGia, Gia_ObjId(pGia, Gia_ManPo(pGia, pPos[i])), vVec ); + return vVec; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_Iso2ManCollectOrder_rec( Gia_Man_t * p, int Id, Vec_Int_t * vRoots, Vec_Int_t * vVec, Vec_Int_t * vMap ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjIsTravIdCurrentId(p, Id) ) + return; + Gia_ObjSetTravIdCurrentId(p, Id); + pObj = Gia_ManObj( p, Id ); + if ( Gia_ObjIsAnd(pObj) ) + { + if ( Gia_ObjFanin0(pObj)->Value <= Gia_ObjFanin1(pObj)->Value ) + { + Gia_Iso2ManCollectOrder_rec( p, Gia_ObjFaninId0(pObj, Id), vRoots, vVec, vMap ); + Gia_Iso2ManCollectOrder_rec( p, Gia_ObjFaninId1(pObj, Id), vRoots, vVec, vMap ); + } + else + { + Gia_Iso2ManCollectOrder_rec( p, Gia_ObjFaninId1(pObj, Id), vRoots, vVec, vMap ); + Gia_Iso2ManCollectOrder_rec( p, Gia_ObjFaninId0(pObj, Id), vRoots, vVec, vMap ); + } + } + else if ( Gia_ObjIsCo(pObj) ) + { + Gia_Iso2ManCollectOrder_rec( p, Gia_ObjFaninId0(pObj, Id), vRoots, vVec, vMap ); + } + else if ( Gia_ObjIsCi(pObj) ) + { + if ( Gia_ObjIsRo(p, pObj) ) + Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)) ); + } + else assert( Gia_ObjIsConst0(pObj) ); + Vec_IntWriteEntry( vMap, Id, Vec_IntSize(vVec) ); + Vec_IntPush( vVec, Id ); +} +void Gia_Iso2ManCollectOrder( Gia_Man_t * pGia, int * pPos, int nPos, Vec_Int_t * vRoots, Vec_Int_t * vVec, Vec_Int_t * vMap ) +{ + int i, iRoot; + Vec_IntClear( vRoots ); + for ( i = 0; i < nPos; i++ ) + Vec_IntPush( vRoots, Gia_ObjId(pGia, Gia_ManPo(pGia, pPos[i])) ); + Vec_IntClear( vVec ); + Gia_ManIncrementTravId( pGia ); + Vec_IntForEachEntry( vRoots, iRoot, i ) + Gia_Iso2ManCollectOrder_rec( pGia, iRoot, vRoots, vVec, vMap ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_Iso2ManCheckIsoPair( Gia_Man_t * p, Vec_Int_t * vVec0, Vec_Int_t * vVec1, Vec_Int_t * vMap0, Vec_Int_t * vMap1 ) +{ + Gia_Obj_t * pObj0, * pObj1; + int k, iObj0, iObj1; + Vec_IntForEachEntryTwo( vVec0, vVec1, iObj0, iObj1, k ) + { + if ( iObj0 == iObj1 ) + continue; + pObj0 = Gia_ManObj(p, iObj0); + pObj1 = Gia_ManObj(p, iObj1); + if ( pObj0->Value != pObj1->Value ) + return 0; + assert( pObj0->Value == pObj1->Value ); + if ( !Gia_ObjIsAnd(pObj0) ) + continue; + if ( Gia_ObjFanin0(pObj0)->Value <= Gia_ObjFanin1(pObj0)->Value ) + { + if ( Gia_ObjFanin0(pObj1)->Value <= Gia_ObjFanin1(pObj1)->Value ) + { + if ( Gia_ObjFaninC0(pObj0) != Gia_ObjFaninC0(pObj1) || Gia_ObjFaninC1(pObj0) != Gia_ObjFaninC1(pObj1) || + Vec_IntEntry(vMap0, Gia_ObjFaninId0p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId0p(p, pObj1)) || + Vec_IntEntry(vMap0, Gia_ObjFaninId1p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId1p(p, pObj1)) ) + return 0; + } + else + { + if ( Gia_ObjFaninC0(pObj0) != Gia_ObjFaninC1(pObj1) || Gia_ObjFaninC1(pObj0) != Gia_ObjFaninC0(pObj1) || + Vec_IntEntry(vMap0, Gia_ObjFaninId0p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId1p(p, pObj1)) || + Vec_IntEntry(vMap0, Gia_ObjFaninId1p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId0p(p, pObj1)) ) + return 0; + } + } + else + { + if ( Gia_ObjFanin0(pObj1)->Value <= Gia_ObjFanin1(pObj1)->Value ) + { + if ( Gia_ObjFaninC1(pObj0) != Gia_ObjFaninC0(pObj1) || Gia_ObjFaninC0(pObj0) != Gia_ObjFaninC1(pObj1) || + Vec_IntEntry(vMap0, Gia_ObjFaninId1p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId0p(p, pObj1)) || + Vec_IntEntry(vMap0, Gia_ObjFaninId0p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId1p(p, pObj1)) ) + return 0; + } + else + { + if ( Gia_ObjFaninC1(pObj0) != Gia_ObjFaninC1(pObj1) || Gia_ObjFaninC0(pObj0) != Gia_ObjFaninC0(pObj1) || + Vec_IntEntry(vMap0, Gia_ObjFaninId1p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId1p(p, pObj1)) || + Vec_IntEntry(vMap0, Gia_ObjFaninId0p(p, pObj0)) != Vec_IntEntry( vMap1, Gia_ObjFaninId0p(p, pObj1)) ) + return 0; + } + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_Iso2ManCheckIsoClassOneSkip( Gia_Man_t * p, Vec_Int_t * vClass, Vec_Int_t * vRoots, Vec_Int_t * vVec0, Vec_Int_t * vVec1, Vec_Int_t * vMap0, Vec_Int_t * vMap1 ) +{ + int i, iPo; + assert( Vec_IntSize(vClass) > 1 ); + iPo = Vec_IntEntry( vClass, 0 ); + Gia_Iso2ManCollectOrder( p, &iPo, 1, vRoots, vVec0, vMap0 ); + Vec_IntForEachEntryStart( vClass, iPo, i, 1 ) + { + Gia_Iso2ManCollectOrder( p, &iPo, 1, vRoots, vVec1, vMap1 ); + if ( Vec_IntSize(vVec0) != Vec_IntSize(vVec1) ) + return 0; + if ( !Gia_Iso2ManCheckIsoPair( p, vVec0, vVec1, vMap0, vMap1 ) ) + return 0; + } + return 1; +} +Vec_Wec_t * Gia_Iso2ManCheckIsoClassesSkip( Gia_Man_t * p, Vec_Wec_t * vEquivs ) +{ + Vec_Wec_t * vEquivs2; + Vec_Int_t * vRoots = Vec_IntAlloc( 10000 ); + Vec_Int_t * vVec0 = Vec_IntAlloc( 10000 ); + Vec_Int_t * vVec1 = Vec_IntAlloc( 10000 ); + Vec_Int_t * vMap0 = Vec_IntStart( Gia_ManObjNum(p) ); + Vec_Int_t * vMap1 = Vec_IntStart( Gia_ManObjNum(p) ); + Vec_Int_t * vClass, * vClass2; + int i, k, Entry, Counter = 0; + vEquivs2 = Vec_WecAlloc( 2 * Vec_WecSize(vEquivs) ); + Vec_WecForEachLevel( vEquivs, vClass, i ) + { + if ( i % 50 == 0 ) + printf( "Finished %8d outputs (out of %8d)...\r", Counter, Gia_ManPoNum(p) ), fflush(stdout); + Counter += Vec_IntSize(vClass); + if ( Vec_IntSize(vClass) < 2 || Gia_Iso2ManCheckIsoClassOneSkip(p, vClass, vRoots, vVec0, vVec1, vMap0, vMap1) ) + { + vClass2 = Vec_WecPushLevel( vEquivs2 ); + *vClass2 = *vClass; + vClass->pArray = NULL; + vClass->nSize = vClass->nCap = 0; + } + else + { + Vec_IntForEachEntry( vClass, Entry, k ) + { + vClass2 = Vec_WecPushLevel( vEquivs2 ); + Vec_IntPush( vClass2, Entry ); + } + } + } + Vec_IntFree( vRoots ); + Vec_IntFree( vVec0 ); + Vec_IntFree( vVec1 ); + Vec_IntFree( vMap0 ); + Vec_IntFree( vMap1 ); + return vEquivs2; +} + +void Gia_Iso2ManCheckIsoClassOne( Gia_Man_t * p, Vec_Int_t * vClass, Vec_Int_t * vRoots, Vec_Int_t * vVec0, Vec_Int_t * vVec1, Vec_Int_t * vMap0, Vec_Int_t * vMap1, Vec_Int_t * vNewClass ) +{ + int i, k = 1, iPo; + Vec_IntClear( vNewClass ); + if ( Vec_IntSize(vClass) <= 1 ) + return; + assert( Vec_IntSize(vClass) > 1 ); + iPo = Vec_IntEntry( vClass, 0 ); + Gia_Iso2ManCollectOrder( p, &iPo, 1, vRoots, vVec0, vMap0 ); + Vec_IntForEachEntryStart( vClass, iPo, i, 1 ) + { + Gia_Iso2ManCollectOrder( p, &iPo, 1, vRoots, vVec1, vMap1 ); + if ( Vec_IntSize(vVec0) == Vec_IntSize(vVec1) && Gia_Iso2ManCheckIsoPair(p, vVec0, vVec1, vMap0, vMap1) ) + Vec_IntWriteEntry( vClass, k++, iPo ); + else + Vec_IntPush( vNewClass, iPo ); + } + Vec_IntShrink( vClass, k ); +} +Vec_Wec_t * Gia_Iso2ManCheckIsoClasses( Gia_Man_t * p, Vec_Wec_t * vEquivs ) +{ + Vec_Wec_t * vEquivs2; + Vec_Int_t * vRoots = Vec_IntAlloc( 10000 ); + Vec_Int_t * vVec0 = Vec_IntAlloc( 10000 ); + Vec_Int_t * vVec1 = Vec_IntAlloc( 10000 ); + Vec_Int_t * vMap0 = Vec_IntStart( Gia_ManObjNum(p) ); + Vec_Int_t * vMap1 = Vec_IntStart( Gia_ManObjNum(p) ); + Vec_Int_t * vClass, * vClass2, * vNewClass; + int i, Counter = 0; + vNewClass = Vec_IntAlloc( 100 ); + vEquivs2 = Vec_WecAlloc( 2 * Vec_WecSize(vEquivs) ); + Vec_WecForEachLevel( vEquivs, vClass, i ) + { + if ( i % 50 == 0 ) + printf( "Finished %8d outputs (out of %8d)...\r", Counter, Gia_ManPoNum(p) ), fflush(stdout); + // split this class + Gia_Iso2ManCheckIsoClassOne( p, vClass, vRoots, vVec0, vVec1, vMap0, vMap1, vNewClass ); + Counter += Vec_IntSize(vClass); + // add remaining class + vClass2 = Vec_WecPushLevel( vEquivs2 ); + *vClass2 = *vClass; + vClass->pArray = NULL; + vClass->nSize = vClass->nCap = 0; + // add new class + if ( Vec_IntSize(vNewClass) == 0 ) + continue; + vClass = Vec_WecPushLevel( vEquivs ); + Vec_IntAppend( vClass, vNewClass ); + } + Vec_IntFree( vNewClass ); + Vec_IntFree( vRoots ); + Vec_IntFree( vVec0 ); + Vec_IntFree( vVec1 ); + Vec_IntFree( vMap0 ); + Vec_IntFree( vMap1 ); + return vEquivs2; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Gia_Iso2ManPerform( Gia_Man_t * pGia, int fVerbose ) +{ + Gia_Iso2Man_t * p; + abctime clk = Abc_Clock(); + p = Gia_Iso2ManStart( pGia ); + Gia_Iso2ManPrepare( pGia ); + Gia_Iso2ManPropagate( pGia ); + Gia_Iso2ManPrint( p, Abc_Clock() - clk, fVerbose ); + while ( Gia_Iso2ManUniqify( p ) ) + { + Gia_Iso2ManPrint( p, Abc_Clock() - clk, fVerbose ); + Gia_Iso2ManPropagate( pGia ); + } + Gia_Iso2ManPrint( p, Abc_Clock() - clk, fVerbose ); +/* + Gia_Iso2ManUpdate( p, 20 ); + while ( Gia_Iso2ManUniqify( p ) ) + { + Gia_Iso2ManPrint( p, Abc_Clock() - clk, fVerbose ); + Gia_Iso2ManPropagate( pGia ); + } + Gia_Iso2ManPrint( p, Abc_Clock() - clk, fVerbose ); +*/ + Gia_Iso2ManStop( p ); + return Gia_Iso2ManDerivePoClasses( pGia ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManIsoReduce2( Gia_Man_t * pGia, Vec_Ptr_t ** pvPosEquivs, Vec_Ptr_t ** pvPiPerms, int fEstimate, int fBetterQual, int fDualOut, int fVerbose, int fVeryVerbose ) +{ + Gia_Man_t * pPart; + Vec_Wec_t * vEquivs, * vEquivs2; + Vec_Int_t * vRemains; + int nClasses, nUsedPos; + abctime clk = Abc_Clock(); + vEquivs = Gia_Iso2ManPerform( pGia, fVeryVerbose ); + // report class stats + nClasses = Vec_WecCountNonTrivial( vEquivs, &nUsedPos ); + printf( "Reduced %d outputs to %d candidate classes (%d outputs are in %d non-trivial classes). ", + Gia_ManPoNum(pGia), Vec_WecSize(vEquivs), nUsedPos, nClasses ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + if ( fEstimate ) + { + Vec_WecFree( vEquivs ); + return Gia_ManDup(pGia); + } + // verify classes + if ( fBetterQual ) + vEquivs2 = Gia_Iso2ManCheckIsoClasses( pGia, vEquivs ); + else + vEquivs2 = Gia_Iso2ManCheckIsoClassesSkip( pGia, vEquivs ); + Vec_WecFree( vEquivs ); + vEquivs = vEquivs2; + // sort equiv classes by the first integer + Vec_WecSortByFirstInt( vEquivs, 0 ); + // find the first outputs + vRemains = Vec_WecCollectFirsts( vEquivs ); + // derive the final GIA + pPart = Gia_ManDupCones( pGia, Vec_IntArray(vRemains), Vec_IntSize(vRemains), 0 ); + Vec_IntFree( vRemains ); + // report class stats + nClasses = Vec_WecCountNonTrivial( vEquivs, &nUsedPos ); + printf( "Reduced %d outputs to %d equivalence classes (%d outputs are in %d non-trivial classes). ", + Gia_ManPoNum(pGia), Vec_WecSize(vEquivs), nUsedPos, nClasses ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + if ( fVerbose ) + { + printf( "Nontrivial classes:\n" ); + Vec_WecPrint( vEquivs, 1 ); + } + if ( pvPiPerms ) + *pvPiPerms = NULL; + if ( pvPosEquivs ) + *pvPosEquivs = Vec_WecConvertToVecPtr( vEquivs ); + Vec_WecFree( vEquivs ); +// Gia_ManStopP( &pPart ); + return pPart; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaIso3.c b/yosys/abc/src/aig/gia/giaIso3.c new file mode 100644 index 00000000000..b526676d363 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaIso3.c @@ -0,0 +1,258 @@ +/**CFile**************************************************************** + + FileName [giaIso3.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaIso3.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static unsigned Iso_Nodes[6] = { 0x04892ed6, 0xc2523d7d, 0xdc36cd2e, 0xf2db64f8, 0xde3126bb, 0xdebbdff0 }; // ab, a!b, !a!b, pi, po, const0 +static unsigned Iso_Fanio[2] = { 0x855ee0cf, 0x946e1b5f }; // fanin, fanout +static unsigned Iso_Compl[2] = { 0x8ba63e50, 0x14d87f02 }; // non-compl, compl + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Gia_Iso3Node( Gia_Obj_t * pObj ) +{ + if ( Gia_ObjIsAnd(pObj) ) + return Iso_Nodes[Gia_ObjFaninC0(pObj) + Gia_ObjFaninC1(pObj)]; + if ( Gia_ObjIsCi(pObj) ) + return Iso_Nodes[3]; + if ( Gia_ObjIsCo(pObj) ) + return Iso_Nodes[4]; + return Iso_Nodes[5]; +} +void Gia_Iso3Init( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachObj( p, pObj, i ) + pObj->Value = Gia_Iso3Node( pObj ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_Iso3ComputeEdge( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Obj_t * pFanin, int fCompl, Vec_Int_t * vSign ) +{ + pObj->Value += Vec_IntEntry(vSign, Gia_ObjId(p, pFanin)) + Iso_Compl[fCompl] + Iso_Fanio[0]; + pFanin->Value += Vec_IntEntry(vSign, Gia_ObjId(p, pObj)) + Iso_Compl[fCompl] + Iso_Fanio[1]; +} +void Gia_Iso3Compute( Gia_Man_t * p, Vec_Int_t * vSign ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachObj( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) || Gia_ObjIsCo(pObj) ) + Gia_Iso3ComputeEdge( p, pObj, Gia_ObjFanin0(pObj), Gia_ObjFaninC0(pObj), vSign ); + if ( Gia_ObjIsAnd(pObj) ) + Gia_Iso3ComputeEdge( p, pObj, Gia_ObjFanin1(pObj), Gia_ObjFaninC1(pObj), vSign ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Int_t * Gia_Iso3Save( Gia_Man_t * p ) +{ + Vec_Int_t * vSign; + Gia_Obj_t * pObj; + int i; + vSign = Vec_IntAlloc( Gia_ManObjNum(p) ); + Gia_ManForEachObj( p, pObj, i ) + Vec_IntPush( vSign, pObj->Value ); + return vSign; +} +int Gia_Iso3Unique( Vec_Int_t * vSign ) +{ + int nUnique; + Vec_Int_t * vCopy = Vec_IntDup( vSign ); + Vec_IntUniqify( vCopy ); + nUnique = Vec_IntSize(vCopy); + Vec_IntFree( vCopy ); + return nUnique; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_Iso3Test( Gia_Man_t * p ) +{ + int nIterMax = 500; + int i, Prev = -1, This; + abctime clk = Abc_Clock(); + Vec_Int_t * vSign = NULL; + Gia_Iso3Init( p ); + for ( i = 0; i < nIterMax; i++ ) + { + vSign = Gia_Iso3Save( p ); +// This = Gia_Iso3Unique( vSign ); + This = Vec_IntUniqueCount( vSign, 1, NULL ); + printf( "Iter %3d : %6d out of %6d ", i, This, Vec_IntSize(vSign) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + if ( This == Prev ) + break; + Prev = This; + Gia_Iso3Compute( p, vSign ); + Vec_IntFreeP( &vSign ); + } + Vec_IntFreeP( &vSign ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Gia_Iso4Gia( Gia_Man_t * p ) +{ + Vec_Wec_t * vLevs = Gia_ManLevelizeR( p ); + Vec_Int_t * vLevel; int l; + Abc_Random( 1 ); + Vec_WecForEachLevel( vLevs, vLevel, l ) + { + Gia_Obj_t * pObj; int i; + unsigned RandC[2] = { Abc_Random(0), Abc_Random(0) }; + if ( l == 0 ) + { + Gia_ManForEachObjVec( vLevel, p, pObj, i ) + { + assert( Gia_ObjIsCo(pObj) ); + pObj->Value = Abc_Random(0); + Gia_ObjFanin0(pObj)->Value += pObj->Value + RandC[Gia_ObjFaninC0(pObj)]; + } + } + else + { + Gia_ManForEachObjVec( vLevel, p, pObj, i ) if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ObjFanin0(pObj)->Value += pObj->Value + RandC[Gia_ObjFaninC0(pObj)]; + Gia_ObjFanin1(pObj)->Value += pObj->Value + RandC[Gia_ObjFaninC1(pObj)]; + } + } + } + return vLevs; +} +void Gia_Iso4Test( Gia_Man_t * p ) +{ + Vec_Wec_t * vLevs = Gia_Iso4Gia( p ); + Vec_Int_t * vLevel; int l; + Vec_WecForEachLevel( vLevs, vLevel, l ) + { + Gia_Obj_t * pObj; int i; + printf( "Level %d\n", l ); + Gia_ManForEachObjVec( vLevel, p, pObj, i ) + printf( "Obj = %5d. Value = %08x.\n", Gia_ObjId(p, pObj), pObj->Value ); + } + Vec_WecFree( vLevs ); +} +Vec_Int_t * Gia_IsoCollectData( Gia_Man_t * p, Vec_Int_t * vObjs ) +{ + Gia_Obj_t * pObj; int i; + Vec_Int_t * vData = Vec_IntAlloc( Vec_IntSize(vObjs) ); + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + Vec_IntPush( vData, pObj->Value ); + return vData; +} +void Gia_IsoCompareVecs( Gia_Man_t * pGia0, Vec_Wec_t * vLevs0, Gia_Man_t * pGia1, Vec_Wec_t * vLevs1 ) +{ + int i, Common, nLevels = Abc_MinInt( Vec_WecSize(vLevs0), Vec_WecSize(vLevs1) ); + Gia_ManPrintStats( pGia0, NULL ); + Gia_ManPrintStats( pGia1, NULL ); + printf( "Printing %d shared levels:\n", nLevels ); + for ( i = 0; i < nLevels; i++ ) + { + Vec_Int_t * vLev0 = Vec_WecEntry(vLevs0, i); + Vec_Int_t * vLev1 = Vec_WecEntry(vLevs1, i); + Vec_Int_t * vData0 = Gia_IsoCollectData( pGia0, vLev0 ); + Vec_Int_t * vData1 = Gia_IsoCollectData( pGia1, vLev1 ); + Vec_IntSort( vData0, 0 ); + Vec_IntSort( vData1, 0 ); + Common = Vec_IntTwoCountCommon( vData0, vData1 ); + printf( "Level = %3d. One = %6d. Two = %6d. Common = %6d.\n", + i, Vec_IntSize(vData0)-Common, Vec_IntSize(vData1)-Common, Common ); + Vec_IntFree( vData0 ); + Vec_IntFree( vData1 ); + } +} +void Gia_Iso4TestTwo( Gia_Man_t * pGia0, Gia_Man_t * pGia1 ) +{ + Vec_Wec_t * vLevs0 = Gia_Iso4Gia( pGia0 ); + Vec_Wec_t * vLevs1 = Gia_Iso4Gia( pGia1 ); + Gia_IsoCompareVecs( pGia0, vLevs0, pGia1, vLevs1 ); + Vec_WecFree( vLevs0 ); + Vec_WecFree( vLevs1 ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaJf.c b/yosys/abc/src/aig/gia/giaJf.c new file mode 100644 index 00000000000..205ab408018 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaJf.c @@ -0,0 +1,1805 @@ +/**CFile**************************************************************** + + FileName [giaJf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaJf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/vec/vecSet.h" +#include "misc/vec/vecMem.h" +#include "misc/extra/extra.h" +#include "bool/kit/kit.h" +#include "misc/util/utilTruth.h" +#include "opt/dau/dau.h" +#include "sat/cnf/cnf.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define JF_LEAF_MAX 8 +#define JF_WORD_MAX ((JF_LEAF_MAX > 6) ? 1 << (JF_LEAF_MAX-6) : 1) +#define JF_CUT_MAX 16 +#define JF_EPSILON 0.005 + +typedef struct Jf_Cut_t_ Jf_Cut_t; +struct Jf_Cut_t_ +{ + word Sign; // signature + float Flow; // flow + int Time; // arrival time + int iFunc; // function + int Cost; // cut cost + int pCut[JF_LEAF_MAX+2]; // cut +}; + +typedef struct Jf_Man_t_ Jf_Man_t; +struct Jf_Man_t_ +{ + Gia_Man_t * pGia; // user's manager + Jf_Par_t * pPars; // users parameter + Sdm_Man_t * pDsd; // extern DSD manager + Vec_Int_t * vCnfs; // costs of elementary CNFs + Vec_Mem_t * vTtMem; // truth table memory and hash table + Vec_Int_t vCuts; // cuts for each node + Vec_Int_t vArr; // arrival time + Vec_Int_t vDep; // departure time + Vec_Flt_t vFlow; // area flow + Vec_Flt_t vRefs; // ref counters + Vec_Set_t pMem; // cut storage + Vec_Int_t * vTemp; // temporary + float (*pCutCmp) (Jf_Cut_t *, Jf_Cut_t *);// procedure to compare cuts + abctime clkStart; // starting time + word CutCount[4]; // statistics + int nCoarse; // coarse nodes +}; + +static inline int Jf_ObjIsUnit( Gia_Obj_t * p ) { return !p->fMark0; } +static inline void Jf_ObjCleanUnit( Gia_Obj_t * p ) { assert(Jf_ObjIsUnit(p)); p->fMark0 = 1; } +static inline void Jf_ObjSetUnit( Gia_Obj_t * p ) { p->fMark0 = 0; } + +static inline int Jf_ObjCutH( Jf_Man_t * p, int i ) { return Vec_IntEntry(&p->vCuts, i); } +static inline int * Jf_ObjCuts( Jf_Man_t * p, int i ) { return (int *)Vec_SetEntry(&p->pMem, Jf_ObjCutH(p, i)); } +static inline int * Jf_ObjCutBest( Jf_Man_t * p, int i ) { return Jf_ObjCuts(p, i) + 1; } +static inline int Jf_ObjArr( Jf_Man_t * p, int i ) { return Vec_IntEntry(&p->vArr, i); } +static inline int Jf_ObjDep( Jf_Man_t * p, int i ) { return Vec_IntEntry(&p->vDep, i); } +static inline float Jf_ObjFlow( Jf_Man_t * p, int i ) { return Vec_FltEntry(&p->vFlow, i); } +static inline float Jf_ObjRefs( Jf_Man_t * p, int i ) { return Vec_FltEntry(&p->vRefs, i); } +//static inline int Jf_ObjLit( int i, int c ) { return i; } +static inline int Jf_ObjLit( int i, int c ) { return Abc_Var2Lit( i, c ); } + +static inline int Jf_CutSize( int * pCut ) { return pCut[0] & 0xF; } // 4 bits +static inline int Jf_CutCost( int * pCut ) { return (pCut[0] >> 4) & 0xF; } // 4 bits +static inline int Jf_CutFunc( int * pCut ) { return ((unsigned)pCut[0] >> 8); } // 24 bits +static inline int Jf_CutSetAll( int f, int c, int s ) { return (f << 8) | (c << 4) | s; } +static inline void Jf_CutSetSize( int * pCut, int s ) { assert(s>=0 && s<16); pCut[0] ^= (Jf_CutSize(pCut) ^ s); } +static inline void Jf_CutSetCost( int * pCut, int c ) { assert(c>=0 && c<16); pCut[0] ^=((Jf_CutCost(pCut) ^ c) << 4); } +static inline void Jf_CutSetFunc( int * pCut, int f ) { assert(f>=0); pCut[0] ^=((Jf_CutFunc(pCut) ^ f) << 8); } + +static inline int Jf_CutFuncClass( int * pCut ) { return Abc_Lit2Var(Jf_CutFunc(pCut)); } +static inline int Jf_CutFuncCompl( int * pCut ) { return Abc_LitIsCompl(Jf_CutFunc(pCut)); } +static inline int * Jf_CutLits( int * pCut ) { return pCut + 1; } +static inline int Jf_CutLit( int * pCut, int i ) { assert(i);return pCut[i]; } +//static inline int Jf_CutVar( int * pCut, int i ) { assert(i); return pCut[i]; } +static inline int Jf_CutVar( int * pCut, int i ) { assert(i);return Abc_Lit2Var(pCut[i]); } +static inline int Jf_CutIsTriv( int * pCut, int i ) { return Jf_CutSize(pCut) == 1 && Jf_CutVar(pCut, 1) == i; } +static inline int Jf_CutCnfSizeF( Jf_Man_t * p, int f ) { return Vec_IntEntry( p->vCnfs, f ); } +static inline int Jf_CutCnfSize( Jf_Man_t * p, int * c ) { return Jf_CutCnfSizeF( p, Jf_CutFuncClass(c) ); } + +static inline int Jf_ObjFunc0( Gia_Obj_t * p, int * c ) { return Abc_LitNotCond(Jf_CutFunc(c), Gia_ObjFaninC0(p)); } +static inline int Jf_ObjFunc1( Gia_Obj_t * p, int * c ) { return Abc_LitNotCond(Jf_CutFunc(c), Gia_ObjFaninC1(p)); } + +#define Jf_ObjForEachCut( pList, pCut, i ) for ( i = 0, pCut = pList + 1; i < pList[0]; i++, pCut += Jf_CutSize(pCut) + 1 ) +#define Jf_CutForEachLit( pCut, Lit, i ) for ( i = 1; i <= Jf_CutSize(pCut) && (Lit = Jf_CutLit(pCut, i)); i++ ) +#define Jf_CutForEachVar( pCut, Var, i ) for ( i = 1; i <= Jf_CutSize(pCut) && (Var = Jf_CutVar(pCut, i)); i++ ) + +extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives CNF for the mapped GIA.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Jf_ManGenCnf( word uTruth, int iLitOut, Vec_Int_t * vLeaves, Vec_Int_t * vLits, Vec_Int_t * vClas, Vec_Int_t * vCover ) +{ + if ( uTruth == 0 || ~uTruth == 0 ) + { + Vec_IntPush( vClas, Vec_IntSize(vLits) ); + Vec_IntPush( vLits, Abc_LitNotCond(iLitOut, (uTruth == 0)) ); + } + else + { + int i, k, c, Literal, Cube; + assert( Vec_IntSize(vLeaves) > 0 ); + for ( c = 0; c < 2; c ++ ) + { + int RetValue = Kit_TruthIsop( (unsigned *)&uTruth, Vec_IntSize(vLeaves), vCover, 0 ); + assert( RetValue == 0 ); + Vec_IntForEachEntry( vCover, Cube, i ) + { + Vec_IntPush( vClas, Vec_IntSize(vLits) ); + Vec_IntPush( vLits, Abc_LitNotCond(iLitOut, c) ); + for ( k = 0; k < Vec_IntSize(vLeaves); k++ ) + { + Literal = 3 & (Cube >> (k << 1)); + if ( Literal == 1 ) // '0' -> pos lit + Vec_IntPush( vLits, Abc_LitNotCond(Vec_IntEntry(vLeaves, k), 0) ); + else if ( Literal == 2 ) // '1' -> neg lit + Vec_IntPush( vLits, Abc_LitNotCond(Vec_IntEntry(vLeaves, k), 1) ); + else if ( Literal != 0 ) + assert( 0 ); + } + } + uTruth = ~uTruth; + } + } +} +Cnf_Dat_t * Jf_ManCreateCnfRemap( Gia_Man_t * p, Vec_Int_t * vLits, Vec_Int_t * vClas, int fAddOrCla ) +{ + Cnf_Dat_t * pCnf; + Gia_Obj_t * pObj; + int i, Entry, * pMap, nVars = 0; + if ( fAddOrCla ) + { + Vec_IntPush( vClas, Vec_IntSize(vLits) ); + Gia_ManForEachPo( p, pObj, i ) + Vec_IntPush( vLits, Abc_Var2Lit(Gia_ObjId(p, pObj), 0) ); + } + // label nodes present in the mapping + Vec_IntForEachEntry( vLits, Entry, i ) + Gia_ManObj(p, Abc_Lit2Var(Entry))->fMark0 = 1; + // create variable map + pMap = ABC_FALLOC( int, Gia_ManObjNum(p) ); + Gia_ManForEachObjReverse( p, pObj, i ) + if ( pObj->fMark0 ) + pObj->fMark0 = 0, pMap[i] = nVars++; + // relabel literals + Vec_IntForEachEntry( vLits, Entry, i ) + Vec_IntWriteEntry( vLits, i, Abc_Lit2LitV(pMap, Entry) ); + // generate CNF + pCnf = ABC_CALLOC( Cnf_Dat_t, 1 ); + pCnf->pMan = (Aig_Man_t *)p; + pCnf->nVars = nVars; + pCnf->nLiterals = Vec_IntSize(vLits); + pCnf->nClauses = Vec_IntSize(vClas); + pCnf->pClauses = ABC_ALLOC( int *, pCnf->nClauses+1 ); + pCnf->pClauses[0] = Vec_IntReleaseArray(vLits); + Vec_IntForEachEntry( vClas, Entry, i ) + pCnf->pClauses[i] = pCnf->pClauses[0] + Entry; + pCnf->pClauses[i] = pCnf->pClauses[0] + pCnf->nLiterals; + pCnf->pVarNums = pMap; + return pCnf; +} +Cnf_Dat_t * Jf_ManCreateCnf( Gia_Man_t * p, Vec_Int_t * vLits, Vec_Int_t * vClas ) +{ + Cnf_Dat_t * pCnf; + int i, Entry, iOut; + // generate CNF + pCnf = ABC_CALLOC( Cnf_Dat_t, 1 ); + pCnf->pMan = (Aig_Man_t *)p; + pCnf->nVars = Gia_ManObjNum(p); + pCnf->nLiterals = Vec_IntSize(vLits); + pCnf->nClauses = Vec_IntSize(vClas); + pCnf->pClauses = ABC_ALLOC( int *, pCnf->nClauses+1 ); + pCnf->pClauses[0] = Vec_IntReleaseArray(vLits); + Vec_IntForEachEntry( vClas, Entry, i ) + pCnf->pClauses[i] = pCnf->pClauses[0] + Entry; + pCnf->pClauses[i] = pCnf->pClauses[0] + pCnf->nLiterals; + // create mapping of objects into their clauses + pCnf->pObj2Clause = ABC_FALLOC( int, Gia_ManObjNum(p) ); + pCnf->pObj2Count = ABC_FALLOC( int, Gia_ManObjNum(p) ); + for ( i = 0; i < pCnf->nClauses; i++ ) + { + iOut = Abc_Lit2Var(pCnf->pClauses[i][0]); + if ( pCnf->pObj2Clause[iOut] == -1 ) + { + pCnf->pObj2Clause[iOut] = i; + pCnf->pObj2Count[iOut] = 1; + } + else + { + assert( pCnf->pObj2Count[iOut] > 0 ); + pCnf->pObj2Count[iOut]++; + } + } + return pCnf; +} + +/**Function************************************************************* + + Synopsis [Computing references while discounting XOR/MUX.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float * Jf_ManInitRefs( Jf_Man_t * pMan ) +{ + Gia_Man_t * p = pMan->pGia; + Gia_Obj_t * pObj, * pCtrl, * pData0, * pData1; + float * pRes; int i; + assert( p->pRefs == NULL ); + p->pRefs = ABC_CALLOC( int, Gia_ManObjNum(p) ); + Gia_ManForEachAnd( p, pObj, i ) + { + Gia_ObjRefFanin0Inc( p, pObj ); + if ( Gia_ObjIsBuf(pObj) ) + continue; + Gia_ObjRefFanin1Inc( p, pObj ); + if ( !Gia_ObjIsMuxType(pObj) ) + continue; + // discount XOR/MUX + pCtrl = Gia_ObjRecognizeMux( pObj, &pData1, &pData0 ); + Gia_ObjRefDec( p, Gia_Regular(pCtrl) ); + if ( Gia_Regular(pData1) == Gia_Regular(pData0) ) + Gia_ObjRefDec( p, Gia_Regular(pData1) ); + } + Gia_ManForEachCo( p, pObj, i ) + Gia_ObjRefFanin0Inc( p, pObj ); + // mark XOR/MUX internal nodes, which are not used elsewhere + if ( pMan->pPars->fCoarsen ) + { + pMan->nCoarse = 0; + Gia_ManForEachAnd( p, pObj, i ) + { + if ( !Gia_ObjIsMuxType(pObj) ) + continue; + if ( Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) == 1 ) + { + Jf_ObjSetUnit(Gia_ObjFanin0(Gia_ObjFanin0(pObj))); + Jf_ObjSetUnit(Gia_ObjFanin0(Gia_ObjFanin1(pObj))); + Jf_ObjCleanUnit(Gia_ObjFanin0(pObj)), pMan->nCoarse++; + } + if ( Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) == 1 ) + { + Jf_ObjSetUnit(Gia_ObjFanin1(Gia_ObjFanin0(pObj))); + Jf_ObjSetUnit(Gia_ObjFanin1(Gia_ObjFanin1(pObj))); + Jf_ObjCleanUnit(Gia_ObjFanin1(pObj)), pMan->nCoarse++; + } + } + } + // multiply by factor + pRes = ABC_ALLOC( float, Gia_ManObjNum(p) ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + pRes[i] = Abc_MaxInt( 1, p->pRefs[i] ); + return pRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Jf_ManProfileClasses( Jf_Man_t * p ) +{ + Gia_Obj_t * pObj; + int Counts[595] = {0}, Costs[595] = {0}; + int i, iFunc, Total = 0, CostTotal = 0, Other = 0, CostOther = 0; + printf( "DSD classes that appear in more than %.1f %% of mapped nodes:\n", 0.1 * p->pPars->nVerbLimit ); + Gia_ManForEachAnd( p->pGia, pObj, i ) + if ( !Gia_ObjIsBuf(pObj) && Gia_ObjRefNumId(p->pGia, i) ) + { + iFunc = Jf_CutFuncClass( Jf_ObjCutBest(p, i) ); + assert( iFunc < 595 ); + if ( p->pPars->fGenCnf ) + { + Costs[iFunc] += Jf_CutCnfSizeF(p, iFunc); + CostTotal += Jf_CutCnfSizeF(p, iFunc); + } + Counts[iFunc]++; + Total++; + } + CostTotal = Abc_MaxInt(CostTotal, 1); + Total = Abc_MaxInt(Total, 1); + for ( i = 0; i < 595; i++ ) + if ( Counts[i] && 100.0 * Counts[i] / Total >= 0.1 * p->pPars->nVerbLimit ) + { + printf( "%5d : ", i ); + printf( "%-20s ", Sdm_ManReadDsdStr(p->pDsd, i) ); + printf( "%8d ", Counts[i] ); + printf( "%5.1f %% ", 100.0 * Counts[i] / Total ); + printf( "%8d ", Costs[i] ); + printf( "%5.1f %%", 100.0 * Costs[i] / CostTotal ); + printf( "\n" ); + } + else + { + Other += Counts[i]; + CostOther += Costs[i]; + } + printf( "Other : " ); + printf( "%-20s ", "" ); + printf( "%8d ", Other ); + printf( "%5.1f %% ", 100.0 * Other / Total ); + printf( "%8d ", CostOther ); + printf( "%5.1f %%", 100.0 * CostOther / CostTotal ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Manager manipulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Jf_Man_t * Jf_ManAlloc( Gia_Man_t * pGia, Jf_Par_t * pPars ) +{ + Jf_Man_t * p; + assert( pPars->nLutSize <= JF_LEAF_MAX ); + assert( pPars->nCutNum <= JF_CUT_MAX ); + Vec_IntFreeP( &pGia->vMapping ); + p = ABC_CALLOC( Jf_Man_t, 1 ); + p->pGia = pGia; + p->pPars = pPars; + if ( pPars->fCutMin && !pPars->fFuncDsd ) + p->vTtMem = Vec_MemAllocForTT( pPars->nLutSize, 0 ); + else if ( pPars->fCutMin && pPars->fFuncDsd ) + { + p->pDsd = Sdm_ManRead(); + if ( pPars->fGenCnf ) + { + p->vCnfs = Vec_IntStart( 595 ); + Sdm_ManReadCnfCosts( p->pDsd, Vec_IntArray(p->vCnfs), Vec_IntSize(p->vCnfs) ); + } + } + Vec_IntFill( &p->vCuts, Gia_ManObjNum(pGia), 0 ); + Vec_IntFill( &p->vArr, Gia_ManObjNum(pGia), 0 ); + Vec_IntFill( &p->vDep, Gia_ManObjNum(pGia), 0 ); + Vec_FltFill( &p->vFlow, Gia_ManObjNum(pGia), 0 ); + p->vRefs.nCap = p->vRefs.nSize = Gia_ManObjNum(pGia); + p->vRefs.pArray = Jf_ManInitRefs( p ); + Vec_SetAlloc_( &p->pMem, 20 ); + p->vTemp = Vec_IntAlloc( 1000 ); + p->clkStart = Abc_Clock(); + return p; +} +void Jf_ManFree( Jf_Man_t * p ) +{ + if ( p->pPars->fVerbose && p->pDsd ) + Sdm_ManPrintDsdStats( p->pDsd, 0 ); + if ( p->pPars->fVerbose && p->vTtMem ) + { + printf( "Unique truth tables = %d. Memory = %.2f MB ", Vec_MemEntryNum(p->vTtMem), Vec_MemMemory(p->vTtMem) / (1<<20) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); + } + if ( p->pPars->fVeryVerbose && p->pPars->fCutMin && p->pPars->fFuncDsd ) + Jf_ManProfileClasses( p ); + if ( p->pPars->fCoarsen ) + Gia_ManCleanMark0( p->pGia ); + ABC_FREE( p->pGia->pRefs ); + ABC_FREE( p->vCuts.pArray ); + ABC_FREE( p->vArr.pArray ); + ABC_FREE( p->vDep.pArray ); + ABC_FREE( p->vFlow.pArray ); + ABC_FREE( p->vRefs.pArray ); + if ( p->pPars->fCutMin && !p->pPars->fFuncDsd ) + { + Vec_MemHashFree( p->vTtMem ); + Vec_MemFree( p->vTtMem ); + } + Vec_IntFreeP( &p->vCnfs ); + Vec_SetFree_( &p->pMem ); + Vec_IntFreeP( &p->vTemp ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Cut functions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Jf_CutPrint( int * pCut ) +{ + int i; + printf( "%d {", Jf_CutSize(pCut) ); + for ( i = 1; i <= Jf_CutSize(pCut); i++ ) + printf( " %d", Jf_CutLit(pCut, i) ); + printf( " } Func = %d\n", Jf_CutFunc(pCut) ); +} +static inline void Jf_ObjCutPrint( int * pCuts ) +{ + int i, * pCut; + Jf_ObjForEachCut( pCuts, pCut, i ) + Jf_CutPrint( pCut ); + printf( "\n" ); +} +static inline void Jf_ObjBestCutConePrint( Jf_Man_t * p, Gia_Obj_t * pObj ) +{ + int * pCut = Jf_ObjCutBest( p, Gia_ObjId(p->pGia, pObj) ); + printf( "Best cut of node %d : ", Gia_ObjId(p->pGia, pObj) ); + Jf_CutPrint( pCut ); + Gia_ManPrintCone( p->pGia, pObj, Jf_CutLits(pCut), Jf_CutSize(pCut), p->vTemp ); +} +static inline void Jf_CutCheck( int * pCut ) +{ + int i, k; + for ( i = 2; i <= Jf_CutSize(pCut); i++ ) + for ( k = 1; k < i; k++ ) + assert( Jf_CutLit(pCut, i) != Jf_CutLit(pCut, k) ); +} +static inline int Jf_CountBitsSimple( unsigned n ) +{ + int i, Count = 0; + for ( i = 0; i < 32; i++ ) + Count += ((n >> i) & 1); + return Count; +} +static inline int Jf_CountBits32( unsigned i ) +{ + i = i - ((i >> 1) & 0x55555555); + i = (i & 0x33333333) + ((i >> 2) & 0x33333333); + i = ((i + (i >> 4)) & 0x0F0F0F0F); + return (i*(0x01010101))>>24; +} +static inline int Jf_CountBits( word i ) +{ + i = i - ((i >> 1) & 0x5555555555555555); + i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333); + i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F); + return (i*(0x0101010101010101))>>56; +} +static inline unsigned Jf_CutGetSign32( int * pCut ) +{ + unsigned Sign = 0; int i; + for ( i = 1; i <= Jf_CutSize(pCut); i++ ) + Sign |= 1 << (Jf_CutVar(pCut, i) & 0x1F); + return Sign; +} +static inline word Jf_CutGetSign( int * pCut ) +{ + word Sign = 0; int i; + for ( i = 1; i <= Jf_CutSize(pCut); i++ ) + Sign |= ((word)1) << (Jf_CutVar(pCut, i) & 0x3F); + return Sign; +} +static inline int Jf_CutArr( Jf_Man_t * p, int * pCut ) +{ + int i, Time = 0; + for ( i = 1; i <= Jf_CutSize(pCut); i++ ) + Time = Abc_MaxInt( Time, Jf_ObjArr(p, Jf_CutVar(pCut, i)) ); + return Time + 1; +} + +static inline void Jf_ObjSetBestCut( int * pCuts, int * pCut, Vec_Int_t * vTemp ) +{ + assert( pCuts < pCut ); + if ( ++pCuts < pCut ) + { + int nBlock = pCut - pCuts; + int nSize = Jf_CutSize(pCut) + 1; + Vec_IntGrow( vTemp, nBlock ); + memmove( Vec_IntArray(vTemp), pCuts, sizeof(int) * nBlock ); + memmove( pCuts, pCut, sizeof(int) * nSize ); + memmove( pCuts + nSize, Vec_IntArray(vTemp), sizeof(int) * nBlock ); + } +} +static inline void Jf_CutRef( Jf_Man_t * p, int * pCut ) +{ + int i; + for ( i = 1; i <= Jf_CutSize(pCut); i++ ) + Gia_ObjRefIncId( p->pGia, Jf_CutVar(pCut, i) ); +} +static inline void Jf_CutDeref( Jf_Man_t * p, int * pCut ) +{ + int i; + for ( i = 1; i <= Jf_CutSize(pCut); i++ ) + Gia_ObjRefDecId( p->pGia, Jf_CutVar(pCut, i) ); +} +static inline float Jf_CutFlow( Jf_Man_t * p, int * pCut ) +{ + float Flow = 0; int i; + for ( i = 1; i <= Jf_CutSize(pCut); i++ ) + Flow += Jf_ObjFlow( p, Jf_CutVar(pCut, i) ); + assert( Flow >= 0 ); + return Flow; +} + +/**Function************************************************************* + + Synopsis [Cut merging.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Jf_CutIsContainedOrder( int * pBase, int * pCut ) // check if pCut is contained pBase +{ + int nSizeB = Jf_CutSize(pBase); + int nSizeC = Jf_CutSize(pCut); + int i, k; + if ( nSizeB == nSizeC ) + { + for ( i = 1; i <= nSizeB; i++ ) + if ( pBase[i] != pCut[i] ) + return 0; + return 1; + } + assert( nSizeB > nSizeC ); + for ( i = k = 1; i <= nSizeB; i++ ) + { + if ( pBase[i] > pCut[k] ) + return 0; + if ( pBase[i] == pCut[k] ) + { + if ( k++ == nSizeC ) + return 1; + } + } + return 0; +} +static inline int Jf_CutMergeOrder( int * pCut0, int * pCut1, int * pCut, int LutSize ) +{ + int nSize0 = Jf_CutSize(pCut0); + int nSize1 = Jf_CutSize(pCut1); + int * pC0 = pCut0 + 1; + int * pC1 = pCut1 + 1; + int * pC = pCut + 1; + int i, k, c, s; + // the case of the largest cut sizes + if ( nSize0 == LutSize && nSize1 == LutSize ) + { + for ( i = 0; i < nSize0; i++ ) + { + if ( pC0[i] != pC1[i] ) + return 0; + pC[i] = pC0[i]; + } + pCut[0] = LutSize; + return 1; + } + // compare two cuts with different numbers + i = k = c = s = 0; + if ( nSize0 == 0 ) goto FlushCut1; + if ( nSize1 == 0 ) goto FlushCut0; + while ( 1 ) + { + if ( c == LutSize ) return 0; + if ( pC0[i] < pC1[k] ) + { + pC[c++] = pC0[i++]; + if ( i >= nSize0 ) goto FlushCut1; + } + else if ( pC0[i] > pC1[k] ) + { + pC[c++] = pC1[k++]; + if ( k >= nSize1 ) goto FlushCut0; + } + else + { + pC[c++] = pC0[i++]; k++; + if ( i >= nSize0 ) goto FlushCut1; + if ( k >= nSize1 ) goto FlushCut0; + } + } + +FlushCut0: + if ( c + nSize0 > LutSize + i ) return 0; + while ( i < nSize0 ) + pC[c++] = pC0[i++]; + pCut[0] = c; + return 1; + +FlushCut1: + if ( c + nSize1 > LutSize + k ) return 0; + while ( k < nSize1 ) + pC[c++] = pC1[k++]; + pCut[0] = c; + return 1; +} + +/**Function************************************************************* + + Synopsis [Cut merging.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Jf_CutFindLeaf0( int * pCut, int iObj ) +{ + int i, nLits = Jf_CutSize(pCut); + for ( i = 1; i <= nLits; i++ ) + if ( pCut[i] == iObj ) + return i; + return i; +} +static inline int Jf_CutIsContained0( int * pBase, int * pCut ) // check if pCut is contained pBase +{ + int i, nLits = Jf_CutSize(pCut); + for ( i = 1; i <= nLits; i++ ) + if ( Jf_CutFindLeaf0(pBase, pCut[i]) > pBase[0] ) + return 0; + return 1; +} +static inline int Jf_CutMerge0( int * pCut0, int * pCut1, int * pCut, int LutSize ) +{ + int nSize0 = Jf_CutSize(pCut0); + int nSize1 = Jf_CutSize(pCut1), i; + pCut[0] = nSize0; + for ( i = 1; i <= nSize1; i++ ) + if ( Jf_CutFindLeaf0(pCut0, pCut1[i]) > nSize0 ) + { + if ( pCut[0] == LutSize ) + return 0; + pCut[++pCut[0]] = pCut1[i]; + } + memcpy( pCut + 1, pCut0 + 1, sizeof(int) * nSize0 ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Cut merging.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Jf_CutFindLeaf1( int * pCut, int iLit ) +{ + int i, nLits = Jf_CutSize(pCut); + for ( i = 1; i <= nLits; i++ ) + if ( Abc_Lit2Var(pCut[i]) == iLit ) + return i; + return i; +} +static inline int Jf_CutIsContained1( int * pBase, int * pCut ) // check if pCut is contained pBase +{ + int i, nLits = Jf_CutSize(pCut); + for ( i = 1; i <= nLits; i++ ) + if ( Jf_CutFindLeaf1(pBase, Abc_Lit2Var(pCut[i])) > pBase[0] ) + return 0; + return 1; +} +static inline int Jf_CutMerge1( int * pCut0, int * pCut1, int * pCut, int LutSize ) +{ + int nSize0 = Jf_CutSize(pCut0); + int nSize1 = Jf_CutSize(pCut1), i; + pCut[0] = nSize0; + for ( i = 1; i <= nSize1; i++ ) + if ( Jf_CutFindLeaf1(pCut0, Abc_Lit2Var(pCut1[i])) > nSize0 ) + { + if ( pCut[0] == LutSize ) + return 0; + pCut[++pCut[0]] = pCut1[i]; + } + memcpy( pCut + 1, pCut0 + 1, sizeof(int) * nSize0 ); + return 1; +} +static inline int Jf_CutMerge2( int * pCut0, int * pCut1, int * pCut, int LutSize ) +{ + int ConfigMask = 0x3FFFF; // 18 bits + int nSize0 = Jf_CutSize(pCut0); + int nSize1 = Jf_CutSize(pCut1); + int i, iPlace; + pCut[0] = nSize0; + for ( i = 1; i <= nSize1; i++ ) + { + iPlace = Jf_CutFindLeaf1(pCut0, Abc_Lit2Var(pCut1[i])); + if ( iPlace > nSize0 ) + { + if ( pCut[0] == LutSize ) + return 0; + pCut[(iPlace = ++pCut[0])] = pCut1[i]; + } + else if ( pCut0[iPlace] != pCut1[i] ) + ConfigMask |= (1 << (iPlace+17)); + ConfigMask ^= (((i-1) ^ 7) << (3*(iPlace-1))); + } + memcpy( pCut + 1, pCut0 + 1, sizeof(int) * nSize0 ); + return ConfigMask; +} + + +/**Function************************************************************* + + Synopsis [Cut filtering.] + + Description [Returns the number of cuts after filtering and the last + cut in the last entry. If the cut is filtered, its size is set to -1.] + + SideEffects [This was found to be 15% slower.] + + SeeAlso [] + +***********************************************************************/ +int Jf_ObjCutFilterBoth( Jf_Man_t * p, Jf_Cut_t ** pSto, int c ) +{ + int k, last; + // filter this cut using other cuts + for ( k = 0; k < c; k++ ) + if ( pSto[c]->pCut[0] >= pSto[k]->pCut[0] && + (pSto[c]->Sign & pSto[k]->Sign) == pSto[k]->Sign && + Jf_CutIsContained1(pSto[c]->pCut, pSto[k]->pCut) ) + { + pSto[c]->pCut[0] = -1; + return c; + } + // filter other cuts using this cut + for ( k = last = 0; k < c; k++ ) + if ( !(pSto[c]->pCut[0] < pSto[k]->pCut[0] && + (pSto[c]->Sign & pSto[k]->Sign) == pSto[c]->Sign && + Jf_CutIsContained1(pSto[k]->pCut, pSto[c]->pCut)) ) + { + if ( last++ == k ) + continue; + ABC_SWAP( Jf_Cut_t *, pSto[last-1], pSto[k] ); + } + assert( last <= c ); + if ( last < c ) + ABC_SWAP( Jf_Cut_t *, pSto[last], pSto[c] ); + return last; +} +int Jf_ObjCutFilter( Jf_Man_t * p, Jf_Cut_t ** pSto, int c ) +{ + int k; + if ( p->pPars->fCutMin ) + { + for ( k = 0; k < c; k++ ) + if ( pSto[c]->pCut[0] >= pSto[k]->pCut[0] && + (pSto[c]->Sign & pSto[k]->Sign) == pSto[k]->Sign && + Jf_CutIsContained1(pSto[c]->pCut, pSto[k]->pCut) ) + return 0; + } + else + { + for ( k = 0; k < c; k++ ) + if ( pSto[c]->pCut[0] >= pSto[k]->pCut[0] && + (pSto[c]->Sign & pSto[k]->Sign) == pSto[k]->Sign && + Jf_CutIsContainedOrder(pSto[c]->pCut, pSto[k]->pCut) ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Sorting cuts by size.] + + Description [] + + SideEffects [Did not really help.] + + SeeAlso [] + +***********************************************************************/ +static inline void Jf_ObjSortCuts( Jf_Cut_t ** pSto, int nSize ) +{ + int i, j, best_i; + for ( i = 0; i < nSize-1; i++ ) + { + best_i = i; + for ( j = i+1; j < nSize; j++ ) + if ( pSto[j]->pCut[0] < pSto[best_i]->pCut[0] ) + best_i = j; + ABC_SWAP( Jf_Cut_t *, pSto[i], pSto[best_i] ); + } +} + +/**Function************************************************************* + + Synopsis [Reference counting.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Jf_CutRef_rec( Jf_Man_t * p, int * pCut ) +{ + int i, Var, Count = Jf_CutCost(pCut); + Jf_CutForEachVar( pCut, Var, i ) + if ( !Gia_ObjRefIncId(p->pGia, Var) && !Jf_CutIsTriv(Jf_ObjCutBest(p, Var), Var) ) + Count += Jf_CutRef_rec( p, Jf_ObjCutBest(p, Var) ); + return Count; +} +int Jf_CutDeref_rec( Jf_Man_t * p, int * pCut ) +{ + int i, Var, Count = Jf_CutCost(pCut); + Jf_CutForEachVar( pCut, Var, i ) + if ( !Gia_ObjRefDecId(p->pGia, Var) && !Jf_CutIsTriv(Jf_ObjCutBest(p, Var), Var) ) + Count += Jf_CutDeref_rec( p, Jf_ObjCutBest(p, Var) ); + return Count; +} +static inline int Jf_CutAreaOld( Jf_Man_t * p, int * pCut ) +{ + int Ela1, Ela2; + Ela1 = Jf_CutRef_rec( p, pCut ); + Ela2 = Jf_CutDeref_rec( p, pCut ); + assert( Ela1 == Ela2 ); + return Ela1; +} + +int Jf_CutAreaRef_rec( Jf_Man_t * p, int * pCut ) +{ + int i, Var, Count = Jf_CutCost(pCut); + Jf_CutForEachVar( pCut, Var, i ) + { + if ( !Gia_ObjRefIncId(p->pGia, Var) && !Jf_CutIsTriv(Jf_ObjCutBest(p, Var), Var) ) + Count += Jf_CutAreaRef_rec( p, Jf_ObjCutBest(p, Var) ); + Vec_IntPush( p->vTemp, Var ); + } + return Count; +} +int Jf_CutAreaRefEdge_rec( Jf_Man_t * p, int * pCut ) +{ + int i, Var, Count = (Jf_CutCost(pCut) << 4) | Jf_CutSize(pCut); + Jf_CutForEachVar( pCut, Var, i ) + { + if ( !Gia_ObjRefIncId(p->pGia, Var) && !Jf_CutIsTriv(Jf_ObjCutBest(p, Var), Var) ) + Count += Jf_CutAreaRefEdge_rec( p, Jf_ObjCutBest(p, Var) ); + Vec_IntPush( p->vTemp, Var ); + } + return Count; +} +static inline int Jf_CutArea( Jf_Man_t * p, int * pCut, int fEdge ) +{ + int Ela, Entry, i; + Vec_IntClear( p->vTemp ); + if ( fEdge ) + Ela = Jf_CutAreaRefEdge_rec( p, pCut ); + else + Ela = Jf_CutAreaRef_rec( p, pCut ); + Vec_IntForEachEntry( p->vTemp, Entry, i ) + Gia_ObjRefDecId( p->pGia, Entry ); + return Ela; +} +// returns 1 if MFFC size is less than limit +int Jf_CutCheckMffc_rec( Jf_Man_t * p, int * pCut, int Limit ) +{ + int i, Var; + Jf_CutForEachVar( pCut, Var, i ) + { + int fRecur = (!Gia_ObjRefDecId(p->pGia, Var) && !Jf_CutIsTriv(Jf_ObjCutBest(p, Var), Var)); + Vec_IntPush( p->vTemp, Var ); + if ( Vec_IntSize(p->vTemp) >= Limit ) + return 0; + if ( fRecur && !Jf_CutCheckMffc_rec( p, Jf_ObjCutBest(p, Var), Limit ) ) + return 0; + } + return 1; +} +static inline int Jf_CutCheckMffc( Jf_Man_t * p, int * pCut, int Limit ) +{ + int RetValue, Entry, i; + Vec_IntClear( p->vTemp ); + RetValue = Jf_CutCheckMffc_rec( p, pCut, Limit ); + Vec_IntForEachEntry( p->vTemp, Entry, i ) + Gia_ObjRefIncId( p->pGia, Entry ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Comparison procedures.] + + Description [Return positive value if the new cut is better than the old cut.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Jf_CutCompareDelay( Jf_Cut_t * pOld, Jf_Cut_t * pNew ) +{ + if ( pOld->Time != pNew->Time ) return pOld->Time - pNew->Time; + if ( pOld->pCut[0] != pNew->pCut[0] ) return pOld->pCut[0] - pNew->pCut[0]; +// if ( pOld->Flow != pNew->Flow ) return pOld->Flow - pNew->Flow; + if ( pOld->Flow < pNew->Flow - JF_EPSILON ) return -1; + if ( pOld->Flow > pNew->Flow + JF_EPSILON ) return 1; + return 0; +} +float Jf_CutCompareArea( Jf_Cut_t * pOld, Jf_Cut_t * pNew ) +{ +// if ( pOld->Flow != pNew->Flow ) return pOld->Flow - pNew->Flow; + if ( pOld->Flow < pNew->Flow - JF_EPSILON ) return -1; + if ( pOld->Flow > pNew->Flow + JF_EPSILON ) return 1; + if ( pOld->pCut[0] != pNew->pCut[0] ) return pOld->pCut[0] - pNew->pCut[0]; + if ( pOld->Time != pNew->Time ) return pOld->Time - pNew->Time; + return 0; +} +static inline int Jf_ObjAddCutToStore( Jf_Man_t * p, Jf_Cut_t ** pSto, int c, int cMax ) +{ + Jf_Cut_t * pTemp; + int k, last, iPivot; + // if the store is empty, add anything + if ( c == 0 ) + return 1; + // special case when the cut store is full and last cut is better than new cut + if ( c == cMax && p->pCutCmp(pSto[c-1], pSto[c]) <= 0 ) + return c; + // find place of the given cut in the store + assert( c <= cMax ); + for ( iPivot = c-1; iPivot >= 0; iPivot-- ) + if ( p->pCutCmp(pSto[iPivot], pSto[c]) < 0 ) // iPivot-th cut is better than new cut + break; + // filter this cut using other cuts + if ( p->pPars->fCutMin ) + { + for ( k = 0; k <= iPivot; k++ ) + if ( pSto[c]->pCut[0] >= pSto[k]->pCut[0] && + (pSto[c]->Sign & pSto[k]->Sign) == pSto[k]->Sign && + Jf_CutIsContained1(pSto[c]->pCut, pSto[k]->pCut) ) + return c; + } + else + { + for ( k = 0; k <= iPivot; k++ ) + if ( pSto[c]->pCut[0] >= pSto[k]->pCut[0] && + (pSto[c]->Sign & pSto[k]->Sign) == pSto[k]->Sign && + Jf_CutIsContainedOrder(pSto[c]->pCut, pSto[k]->pCut) ) + return c; + } + // insert this cut after iPivot + pTemp = pSto[c]; + for ( ++iPivot, k = c++; k > iPivot; k-- ) + pSto[k] = pSto[k-1]; + pSto[iPivot] = pTemp; + // filter other cuts using this cut + if ( p->pPars->fCutMin ) + { + for ( k = last = iPivot+1; k < c; k++ ) + if ( !(pSto[iPivot]->pCut[0] <= pSto[k]->pCut[0] && + (pSto[iPivot]->Sign & pSto[k]->Sign) == pSto[iPivot]->Sign && + Jf_CutIsContained1(pSto[k]->pCut, pSto[iPivot]->pCut)) ) + { + if ( last++ == k ) + continue; + ABC_SWAP( Jf_Cut_t *, pSto[last-1], pSto[k] ); + } + } + else + { + for ( k = last = iPivot+1; k < c; k++ ) + if ( !(pSto[iPivot]->pCut[0] <= pSto[k]->pCut[0] && + (pSto[iPivot]->Sign & pSto[k]->Sign) == pSto[iPivot]->Sign && + Jf_CutIsContainedOrder(pSto[k]->pCut, pSto[iPivot]->pCut)) ) + { + if ( last++ == k ) + continue; + ABC_SWAP( Jf_Cut_t *, pSto[last-1], pSto[k] ); + } + } + c = last; + // remove the last cut if too many + if ( c == cMax + 1 ) + return c - 1; + return c; +} +static inline void Jf_ObjPrintStore( Jf_Man_t * p, Jf_Cut_t ** pSto, int c ) +{ + int i; + for ( i = 0; i < c; i++ ) + { + printf( "Flow =%9.5f ", pSto[i]->Flow ); + printf( "Time = %5d ", pSto[i]->Time ); + printf( "Func = %5d ", pSto[i]->iFunc ); + printf( " " ); + Jf_CutPrint( pSto[i]->pCut ); + } + printf( "\n" ); +} +static inline void Jf_ObjCheckPtrs( Jf_Cut_t ** pSto, int c ) +{ + int i, k; + for ( i = 1; i < c; i++ ) + for ( k = 0; k < i; k++ ) + assert( pSto[k] != pSto[i] ); +} +static inline void Jf_ObjCheckStore( Jf_Man_t * p, Jf_Cut_t ** pSto, int c, int iObj ) +{ + int i, k; + for ( i = 1; i < c; i++ ) + assert( p->pCutCmp(pSto[i-1], pSto[i]) <= 0 ); + for ( i = 1; i < c; i++ ) + for ( k = 0; k < i; k++ ) + { + assert( !Jf_CutIsContained1(pSto[k]->pCut, pSto[i]->pCut) ); + assert( !Jf_CutIsContained1(pSto[i]->pCut, pSto[k]->pCut) ); + } +} + +/**Function************************************************************* + + Synopsis [Cut minimization.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Jf_TtComputeForCut( Jf_Man_t * p, int iFuncLit0, int iFuncLit1, int * pCut0, int * pCut1, int * pCutOut ) +{ + word uTruth[JF_WORD_MAX], uTruth0[JF_WORD_MAX], uTruth1[JF_WORD_MAX]; + int fCompl, truthId; + int LutSize = p->pPars->nLutSize; + int nWords = Abc_Truth6WordNum(p->pPars->nLutSize); + word * pTruth0 = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(iFuncLit0)); + word * pTruth1 = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(iFuncLit1)); + Abc_TtCopy( uTruth0, pTruth0, nWords, Abc_LitIsCompl(iFuncLit0) ); + Abc_TtCopy( uTruth1, pTruth1, nWords, Abc_LitIsCompl(iFuncLit1) ); + Abc_TtExpand( uTruth0, LutSize, pCut0 + 1, Jf_CutSize(pCut0), pCutOut + 1, Jf_CutSize(pCutOut) ); + Abc_TtExpand( uTruth1, LutSize, pCut1 + 1, Jf_CutSize(pCut1), pCutOut + 1, Jf_CutSize(pCutOut) ); + fCompl = (int)(uTruth0[0] & uTruth1[0] & 1); + Abc_TtAnd( uTruth, uTruth0, uTruth1, nWords, fCompl ); + pCutOut[0] = Abc_TtMinBase( uTruth, pCutOut + 1, pCutOut[0], LutSize ); + assert( (uTruth[0] & 1) == 0 ); + truthId = Vec_MemHashInsert(p->vTtMem, uTruth); + return Abc_Var2Lit( truthId, fCompl ); +} + +/**Function************************************************************* + + Synopsis [Cut enumeration.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Jf_ObjAssignCut( Jf_Man_t * p, Gia_Obj_t * pObj ) +{ + int iObj = Gia_ObjId(p->pGia, pObj); + int pClause[3] = { 1, Jf_CutSetAll(2, 0, 1), Jf_ObjLit(iObj, 0) }; // set function + assert( Gia_ObjIsCi(pObj) || Gia_ObjIsBuf(pObj) ); + Vec_IntWriteEntry( &p->vCuts, iObj, Vec_SetAppend( &p->pMem, pClause, 3 ) ); +} +static inline void Jf_ObjPropagateBuf( Jf_Man_t * p, Gia_Obj_t * pObj, int fReverse ) +{ + int iObj = Gia_ObjId( p->pGia, pObj ); + int iFanin = Gia_ObjFaninId0( pObj, iObj ); + assert( 0 ); + assert( Gia_ObjIsBuf(pObj) ); + if ( fReverse ) + ABC_SWAP( int, iObj, iFanin ); + Vec_IntWriteEntry( &p->vArr, iObj, Jf_ObjArr(p, iFanin) ); + Vec_FltWriteEntry( &p->vFlow, iObj, Jf_ObjFlow(p, iFanin) ); +} +static inline int Jf_ObjHasCutWithSize( Jf_Cut_t ** pSto, int c, int nSize ) +{ + int i; + for ( i = 0; i < c; i++ ) + if ( pSto[i]->pCut[0] <= nSize ) + return 1; + return 0; +} +void Jf_ObjComputeCuts( Jf_Man_t * p, Gia_Obj_t * pObj, int fEdge ) +{ + int LutSize = p->pPars->nLutSize; + int CutNum = p->pPars->nCutNum; + int iObj = Gia_ObjId(p->pGia, pObj); + word Sign0[JF_CUT_MAX+2]; // signatures of the first cut + word Sign1[JF_CUT_MAX+2]; // signatures of the second cut + Jf_Cut_t Sto[JF_CUT_MAX+2]; // cut storage + Jf_Cut_t * pSto[JF_CUT_MAX+2]; // pointers to cut storage + int * pCut0, * pCut1, * pCuts0, * pCuts1; + int nOldSupp, Config, i, k, c = 0; + // prepare cuts + for ( i = 0; i <= CutNum+1; i++ ) + pSto[i] = Sto + i, pSto[i]->Cost = 0, pSto[i]->iFunc = ~0; + // compute signatures + pCuts0 = Jf_ObjCuts( p, Gia_ObjFaninId0(pObj, iObj) ); + Jf_ObjForEachCut( pCuts0, pCut0, i ) + Sign0[i] = Jf_CutGetSign( pCut0 ); + // compute signatures + pCuts1 = Jf_ObjCuts( p, Gia_ObjFaninId1(pObj, iObj) ); + Jf_ObjForEachCut( pCuts1, pCut1, i ) + Sign1[i] = Jf_CutGetSign( pCut1 ); + // merge cuts + p->CutCount[0] += pCuts0[0] * pCuts1[0]; + Jf_ObjForEachCut( pCuts0, pCut0, i ) + Jf_ObjForEachCut( pCuts1, pCut1, k ) + { + if ( Jf_CountBits(Sign0[i] | Sign1[k]) > LutSize ) + continue; + p->CutCount[1]++; + if ( !p->pPars->fCutMin ) + { + if ( !Jf_CutMergeOrder(pCut0, pCut1, pSto[c]->pCut, LutSize) ) + continue; + pSto[c]->Sign = Sign0[i] | Sign1[k]; + } + else if ( p->pPars->fFuncDsd ) + { + if ( !(Config = Jf_CutMerge2(pCut0, pCut1, pSto[c]->pCut, LutSize)) ) + continue; + pSto[c]->Sign = Sign0[i] | Sign1[k]; + nOldSupp = pSto[c]->pCut[0]; + pSto[c]->iFunc = Sdm_ManComputeFunc( p->pDsd, Jf_ObjFunc0(pObj, pCut0), Jf_ObjFunc1(pObj, pCut1), pSto[c]->pCut, Config, 0 ); + if ( pSto[c]->iFunc == -1 ) + continue; + if ( p->pPars->fGenCnf && Jf_CutCnfSizeF(p, Abc_Lit2Var(pSto[c]->iFunc)) >= 12 ) // no more than 15 + continue; + assert( pSto[c]->pCut[0] <= nOldSupp ); + if ( pSto[c]->pCut[0] < nOldSupp ) + pSto[c]->Sign = Jf_CutGetSign( pSto[c]->pCut ); + } + else + { + if ( !Jf_CutMergeOrder(pCut0, pCut1, pSto[c]->pCut, LutSize) ) + continue; + pSto[c]->Sign = Sign0[i] | Sign1[k]; + nOldSupp = pSto[c]->pCut[0]; + pSto[c]->iFunc = Jf_TtComputeForCut( p, Jf_ObjFunc0(pObj, pCut0), Jf_ObjFunc1(pObj, pCut1), pCut0, pCut1, pSto[c]->pCut ); + assert( pSto[c]->pCut[0] <= nOldSupp ); + if ( pSto[c]->pCut[0] < nOldSupp ) + pSto[c]->Sign = Jf_CutGetSign( pSto[c]->pCut ); + if ( pSto[c]->iFunc >= (1 << 24) ) + printf( "Hard limit on the number of different Boolean functions (2^23) is reached. Quitting...\n" ), exit(1); + } + p->CutCount[2]++; + pSto[c]->Time = p->pPars->fAreaOnly ? 0 : Jf_CutArr(p, pSto[c]->pCut); + pSto[c]->Flow = Jf_CutFlow(p, pSto[c]->pCut); + c = Jf_ObjAddCutToStore( p, pSto, c, CutNum ); + assert( c <= CutNum ); + } +// Jf_ObjPrintStore( p, pSto, c ); +// Jf_ObjCheckStore( p, pSto, c, iObj ); + // add two variable cut + if ( !Jf_ObjIsUnit(pObj) && !Jf_ObjHasCutWithSize(pSto, c, 2) ) + { + assert( Jf_ObjIsUnit(Gia_ObjFanin0(pObj)) && Jf_ObjIsUnit(Gia_ObjFanin1(pObj)) ); + if ( p->pPars->fCutMin ) pSto[c]->iFunc = 4; // set function (DSD only!) + pSto[c]->pCut[0] = 2; + pSto[c]->pCut[1] = Jf_ObjLit(Gia_ObjFaninId0(pObj, iObj), Gia_ObjFaninC0(pObj)); + pSto[c]->pCut[2] = Jf_ObjLit(Gia_ObjFaninId1(pObj, iObj), Gia_ObjFaninC1(pObj)); + c++; + } + // add elementary cut + if ( Jf_ObjIsUnit(pObj) && !(p->pPars->fCutMin && Jf_ObjHasCutWithSize(pSto, c, 1)) ) + { + if ( p->pPars->fCutMin ) pSto[c]->iFunc = 2; // set function + pSto[c]->pCut[0] = 1; + pSto[c]->pCut[1] = Jf_ObjLit(iObj, 0); + c++; + } + // reorder cuts +// Jf_ObjSortCuts( pSto + 1, c - 1 ); +// Jf_ObjCheckPtrs( pSto, CutNum ); + // find cost of the best cut + pSto[0]->Cost = p->pPars->fGenCnf ? Jf_CutCnfSizeF(p, Abc_Lit2Var(pSto[0]->iFunc)) : 1; + assert( pSto[0]->Cost >= 0 ); + // save best info + assert( pSto[0]->Flow >= 0 ); + Vec_IntWriteEntry( &p->vArr, iObj, pSto[0]->Time ); + Vec_FltWriteEntry( &p->vFlow, iObj, (pSto[0]->Flow + (fEdge ? pSto[0]->pCut[0] : pSto[0]->Cost)) / Jf_ObjRefs(p, iObj) ); + // add cuts to storage cuts + Vec_IntClear( p->vTemp ); + Vec_IntPush( p->vTemp, c ); + for ( i = 0; i < c; i++ ) + { + pSto[i]->Cost = p->pPars->fGenCnf ? Jf_CutCnfSizeF(p, Abc_Lit2Var(pSto[i]->iFunc)) : 1; + Vec_IntPush( p->vTemp, Jf_CutSetAll(pSto[i]->iFunc, pSto[i]->Cost, pSto[i]->pCut[0]) ); + for ( k = 1; k <= pSto[i]->pCut[0]; k++ ) + Vec_IntPush( p->vTemp, pSto[i]->pCut[k] ); + } + Vec_IntWriteEntry( &p->vCuts, iObj, Vec_SetAppend(&p->pMem, Vec_IntArray(p->vTemp), Vec_IntSize(p->vTemp)) ); + p->CutCount[3] += c; +} +void Jf_ManComputeCuts( Jf_Man_t * p, int fEdge ) +{ + Gia_Obj_t * pObj; int i; + if ( p->pPars->fVerbose ) + { + printf( "Aig: CI = %d CO = %d AND = %d ", Gia_ManCiNum(p->pGia), Gia_ManCoNum(p->pGia), Gia_ManAndNum(p->pGia) ); + printf( "LutSize = %d CutMax = %d Rounds = %d\n", p->pPars->nLutSize, p->pPars->nCutNum, p->pPars->nRounds ); + printf( "Computing cuts...\r" ); + fflush( stdout ); + } + Gia_ManForEachObj( p->pGia, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) || Gia_ObjIsBuf(pObj) ) + Jf_ObjAssignCut( p, pObj ); + if ( Gia_ObjIsBuf(pObj) ) + Jf_ObjPropagateBuf( p, pObj, 0 ); + else if ( Gia_ObjIsAnd(pObj) ) + Jf_ObjComputeCuts( p, pObj, fEdge ); + } + if ( p->pPars->fVerbose ) + { + printf( "CutPair = %lu ", (long)p->CutCount[0] ); + printf( "Merge = %lu ", (long)p->CutCount[1] ); + printf( "Eval = %lu ", (long)p->CutCount[2] ); + printf( "Cut = %lu ", (long)p->CutCount[3] ); + Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); + printf( "Memory: " ); + printf( "Gia = %.2f MB ", Gia_ManMemory(p->pGia) / (1<<20) ); + printf( "Man = %.2f MB ", 6.0 * sizeof(int) * Gia_ManObjNum(p->pGia) / (1<<20) ); + printf( "Cuts = %.2f MB", Vec_ReportMemory(&p->pMem) / (1<<20) ); + if ( p->nCoarse ) + printf( " Coarse = %d (%.1f %%)", p->nCoarse, 100.0 * p->nCoarse / Gia_ManObjNum(p->pGia) ); + printf( "\n" ); + fflush( stdout ); + } +} + + +/**Function************************************************************* + + Synopsis [Computing delay/area.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Jf_ManComputeDelay( Jf_Man_t * p, int fEval ) +{ + Gia_Obj_t * pObj; + int i, Delay = 0; + if ( fEval ) + { + Gia_ManForEachObj( p->pGia, pObj, i ) + if ( Gia_ObjIsBuf(pObj) ) + Jf_ObjPropagateBuf( p, pObj, 0 ); + else if ( Gia_ObjIsAnd(pObj) && Gia_ObjRefNum(p->pGia, pObj) > 0 ) + Vec_IntWriteEntry( &p->vArr, i, Jf_CutArr(p, Jf_ObjCutBest(p, i)) ); + } + Gia_ManForEachCoDriver( p->pGia, pObj, i ) + { + assert( Gia_ObjRefNum(p->pGia, pObj) > 0 ); + Delay = Abc_MaxInt( Delay, Jf_ObjArr(p, Gia_ObjId(p->pGia, pObj)) ); + } + return Delay; +} +int Jf_ManComputeRefs( Jf_Man_t * p ) +{ + Gia_Obj_t * pObj; + float nRefsNew; int i, * pCut; + float * pRefs = Vec_FltArray(&p->vRefs); + float * pFlow = Vec_FltArray(&p->vFlow); + assert( p->pGia->pRefs != NULL ); + memset( p->pGia->pRefs, 0, sizeof(int) * Gia_ManObjNum(p->pGia) ); + p->pPars->Area = p->pPars->Edge = 0; + Gia_ManForEachObjReverse( p->pGia, pObj, i ) + { + if ( Gia_ObjIsCo(pObj) || Gia_ObjIsBuf(pObj) ) + Gia_ObjRefInc( p->pGia, Gia_ObjFanin0(pObj) ); + else if ( Gia_ObjIsAnd(pObj) && Gia_ObjRefNum(p->pGia, pObj) > 0 ) + { + assert( Jf_ObjIsUnit(pObj) ); + pCut = Jf_ObjCutBest(p, i); + Jf_CutRef( p, pCut ); + if ( p->pPars->fGenCnf ) + p->pPars->Clause += Jf_CutCnfSize(p, pCut); + p->pPars->Edge += Jf_CutSize(pCut); + p->pPars->Area++; + } + } + // blend references and normalize flow + for ( i = 0; i < Gia_ManObjNum(p->pGia); i++ ) + { + if ( p->pPars->fOptEdge ) + nRefsNew = Abc_MaxFloat( 1, 0.8 * pRefs[i] + 0.2 * p->pGia->pRefs[i] ); + else + nRefsNew = Abc_MaxFloat( 1, 0.2 * pRefs[i] + 0.8 * p->pGia->pRefs[i] ); + pFlow[i] = pFlow[i] * pRefs[i] / nRefsNew; + pRefs[i] = nRefsNew; + assert( pFlow[i] >= 0 ); + } + // compute delay + p->pPars->Delay = Jf_ManComputeDelay( p, 1 ); + return p->pPars->Area; +} + +/**Function************************************************************* + + Synopsis [Mapping rounds.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Jf_ObjComputeBestCut( Jf_Man_t * p, Gia_Obj_t * pObj, int fEdge, int fEla ) +{ + int i, iObj = Gia_ObjId( p->pGia, pObj ); + int * pCuts = Jf_ObjCuts( p, iObj ); + int * pCut, * pCutBest = NULL; + int Time = ABC_INFINITY, TimeBest = ABC_INFINITY; + float Area, AreaBest = ABC_INFINITY; + Jf_ObjForEachCut( pCuts, pCut, i ) + { + if ( Jf_CutIsTriv(pCut, iObj) ) continue; + if ( fEdge && !fEla ) + Jf_CutSetCost(pCut, Jf_CutSize(pCut)); + Area = fEla ? Jf_CutArea(p, pCut, fEdge) : Jf_CutFlow(p, pCut) + Jf_CutCost(pCut); + if ( pCutBest == NULL || AreaBest > Area + JF_EPSILON || (AreaBest > Area - JF_EPSILON && TimeBest > (Time = Jf_CutArr(p, pCut))) ) + pCutBest = pCut, AreaBest = Area, TimeBest = Time; + } + Vec_IntWriteEntry( &p->vArr, iObj, Jf_CutArr(p, pCutBest) ); + if ( !fEla ) + Vec_FltWriteEntry( &p->vFlow, iObj, AreaBest / Jf_ObjRefs(p, iObj) ); + Jf_ObjSetBestCut( pCuts, pCutBest, p->vTemp ); +// Jf_CutPrint( Jf_ObjCutBest(p, iObj) ); printf( "\n" ); +} +void Jf_ManPropagateFlow( Jf_Man_t * p, int fEdge ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachObj( p->pGia, pObj, i ) + if ( Gia_ObjIsBuf(pObj) ) + Jf_ObjPropagateBuf( p, pObj, 0 ); + else if ( Gia_ObjIsAnd(pObj) && Jf_ObjIsUnit(pObj) ) + Jf_ObjComputeBestCut( p, pObj, fEdge, 0 ); + Jf_ManComputeRefs( p ); +} +void Jf_ManPropagateEla( Jf_Man_t * p, int fEdge ) +{ + Gia_Obj_t * pObj; + int i, CostBef, CostAft; + p->pPars->Area = p->pPars->Edge = p->pPars->Clause = 0; + Gia_ManForEachObjReverse( p->pGia, pObj, i ) + if ( Gia_ObjIsBuf(pObj) ) + Jf_ObjPropagateBuf( p, pObj, 1 ); + else if ( Gia_ObjIsAnd(pObj) && Gia_ObjRefNum(p->pGia, pObj) > 0 ) + { + assert( Jf_ObjIsUnit(pObj) ); + if ( Jf_CutCheckMffc(p, Jf_ObjCutBest(p, i), 50) ) + { + CostBef = Jf_CutDeref_rec( p, Jf_ObjCutBest(p, i) ); + Jf_ObjComputeBestCut( p, pObj, fEdge, 1 ); + CostAft = Jf_CutRef_rec( p, Jf_ObjCutBest(p, i) ); + // if ( CostBef != CostAft ) printf( "%d -> %d ", CostBef, CostAft ); + assert( CostBef >= CostAft ); // does not hold because of JF_EDGE_LIM + } + if ( p->pPars->fGenCnf ) + p->pPars->Clause += Jf_CutCnfSize(p, Jf_ObjCutBest(p, i)); + p->pPars->Edge += Jf_CutSize(Jf_ObjCutBest(p, i)); + p->pPars->Area++; + } + p->pPars->Delay = Jf_ManComputeDelay( p, 1 ); +// printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Derives the result of mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Jf_ManDeriveMappingGia( Jf_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + Vec_Int_t * vCopies = Vec_IntStartFull( Gia_ManObjNum(p->pGia) ); + Vec_Int_t * vMapping = Vec_IntStart( 2 * Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + 2 * (int)p->pPars->Area ); + Vec_Int_t * vMapping2 = Vec_IntStart( (int)p->pPars->Edge + 2 * (int)p->pPars->Area + 1000 ); + Vec_Int_t * vCover = Vec_IntAlloc( 1 << 16 ); + Vec_Int_t * vLeaves = Vec_IntAlloc( 16 ); + Vec_Int_t * vLits = NULL, * vClas = NULL; + int i, k, iLit, Class, * pCut; + word uTruth = 0, * pTruth = &uTruth; + assert( p->pPars->fCutMin ); + if ( p->pPars->fGenCnf ) + { + vLits = Vec_IntAlloc( 1000 ); + vClas = Vec_IntAlloc( 1000 ); + Vec_IntPush( vClas, Vec_IntSize(vLits) ); + Vec_IntPush( vLits, 1 ); + } + // create new manager + pNew = Gia_ManStart( Gia_ManObjNum(p->pGia) ); + pNew->pName = Abc_UtilStrsav( p->pGia->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pGia->pSpec ); + // map primary inputs + Vec_IntWriteEntry( vCopies, 0, 0 ); + Gia_ManForEachCi( p->pGia, pObj, i ) + Vec_IntWriteEntry( vCopies, Gia_ObjId(p->pGia, pObj), Gia_ManAppendCi(pNew) ); + // iterate through nodes used in the mapping + Gia_ManForEachAnd( p->pGia, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) || Gia_ObjRefNum(p->pGia, pObj) == 0 ) + continue; + pCut = Jf_ObjCutBest( p, i ); +// printf( "Best cut of node %d: ", i ); Jf_CutPrint(pCut); + Class = Jf_CutFuncClass( pCut ); + if ( Jf_CutSize(pCut) == 0 ) + { + assert( Class == 0 ); + Vec_IntWriteEntry( vCopies, i, Jf_CutFunc(pCut) ); + continue; + } + if ( Jf_CutSize(pCut) == 1 ) + { + assert( Class == 1 ); + iLit = Abc_LitNotCond( Jf_CutLit(pCut, 1) , Jf_CutFuncCompl(pCut) ); + iLit = Abc_Lit2LitL( Vec_IntArray(vCopies), iLit ); + Vec_IntWriteEntry( vCopies, i, iLit ); + continue; + } + if ( p->pPars->fFuncDsd ) + uTruth = Sdm_ManReadDsdTruth(p->pDsd, Class); + else + pTruth = Vec_MemReadEntry(p->vTtMem, Class); + assert( p->pDsd == NULL || Sdm_ManReadDsdVarNum(p->pDsd, Class) == Jf_CutSize(pCut) ); + // collect leaves + Vec_IntClear( vLeaves ); + Jf_CutForEachLit( pCut, iLit, k ) + Vec_IntPush( vLeaves, Abc_Lit2LitL(Vec_IntArray(vCopies), iLit) ); + // create GIA + iLit = Kit_TruthToGia( pNew, (unsigned *)pTruth, Vec_IntSize(vLeaves), vCover, vLeaves, 0 ); + if ( p->pPars->fGenCnf ) + Jf_ManGenCnf( uTruth, iLit, vLeaves, vLits, vClas, vCover ); + iLit = Abc_LitNotCond( iLit, Jf_CutFuncCompl(pCut) ); + Vec_IntWriteEntry( vCopies, i, iLit ); + // create mapping + Vec_IntSetEntry( vMapping, Abc_Lit2Var(iLit), Vec_IntSize(vMapping2) ); + Vec_IntPush( vMapping2, Vec_IntSize(vLeaves) ); + Vec_IntForEachEntry( vLeaves, iLit, k ) + Vec_IntPush( vMapping2, Abc_Lit2Var(iLit) ); + Vec_IntPush( vMapping2, Abc_Lit2Var(Vec_IntEntry(vCopies, i)) ); + } + Gia_ManForEachCo( p->pGia, pObj, i ) + { + if ( p->pPars->fGenCnf ) + Vec_IntClear( vLeaves ); + iLit = Vec_IntEntry( vCopies, Gia_ObjFaninId0p(p->pGia, pObj) ); + if ( p->pPars->fGenCnf ) + Vec_IntPush( vLeaves, Abc_LitNotCond(iLit, Gia_ObjFaninC0(pObj)) ); + iLit = Gia_ManAppendCo( pNew, Abc_LitNotCond(iLit, Gia_ObjFaninC0(pObj)) ); + if ( p->pPars->fGenCnf ) + Jf_ManGenCnf( ABC_CONST(0xAAAAAAAAAAAAAAAA), iLit, vLeaves, vLits, vClas, vCover ); + } + Vec_IntFree( vCopies ); + Vec_IntFree( vCover ); + Vec_IntFree( vLeaves ); + // finish mapping + if ( Vec_IntSize(vMapping) > Gia_ManObjNum(pNew) ) + Vec_IntShrink( vMapping, Gia_ManObjNum(pNew) ); + else + Vec_IntFillExtra( vMapping, Gia_ManObjNum(pNew), 0 ); + assert( Vec_IntSize(vMapping) == Gia_ManObjNum(pNew) ); + Vec_IntForEachEntry( vMapping, iLit, i ) + if ( iLit > 0 ) + Vec_IntAddToEntry( vMapping, i, Gia_ManObjNum(pNew) ); + Vec_IntAppend( vMapping, vMapping2 ); + Vec_IntFree( vMapping2 ); + // attach mapping and packing + assert( pNew->vMapping == NULL ); + pNew->vMapping = vMapping; + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p->pGia) ); + // derive CNF + if ( p->pPars->fGenCnf ) + { + if ( p->pPars->fCnfObjIds ) + pNew->pData = Jf_ManCreateCnf( pNew, vLits, vClas ); + else + pNew->pData = Jf_ManCreateCnfRemap( pNew, vLits, vClas, p->pPars->fAddOrCla ); + } + Vec_IntFreeP( &vLits ); + Vec_IntFreeP( &vClas ); + return pNew; +} +void Jf_ManDeriveMapping( Jf_Man_t * p ) +{ + Vec_Int_t * vMapping; + Gia_Obj_t * pObj; + int i, k, * pCut; + assert( !p->pPars->fCutMin ); + vMapping = Vec_IntAlloc( Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + (int)p->pPars->Area * 2 ); + Vec_IntFill( vMapping, Gia_ManObjNum(p->pGia), 0 ); + Gia_ManForEachAnd( p->pGia, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) || Gia_ObjRefNum(p->pGia, pObj) == 0 ) + continue; + pCut = Jf_ObjCutBest( p, i ); + Vec_IntWriteEntry( vMapping, i, Vec_IntSize(vMapping) ); + assert( !p->pPars->fCutMin || Jf_CutSize(pCut) <= 6 ); + Vec_IntPush( vMapping, Jf_CutSize(pCut) ); + for ( k = 1; k <= Jf_CutSize(pCut); k++ ) + Vec_IntPush( vMapping, Jf_CutVar(pCut, k) ); + Vec_IntPush( vMapping, i ); + } + assert( Vec_IntCap(vMapping) == 16 || Vec_IntSize(vMapping) == Vec_IntCap(vMapping) ); + p->pGia->vMapping = vMapping; +// Gia_ManMappingVerify( p->pGia ); +} + +/**Function************************************************************* + + Synopsis [Derive GIA without mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Jf_ManDeriveGia( Jf_Man_t * p ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + Vec_Int_t * vCopies = Vec_IntStartFull( Gia_ManObjNum(p->pGia) ); + Vec_Int_t * vCover = Vec_IntAlloc( 1 << 16 ); + Vec_Int_t * vLeaves = Vec_IntAlloc( 16 ); + int i, k, iLit, Class, * pCut; + int nWords = Abc_Truth6WordNum(p->pPars->nLutSize); + word uTruth = 0, * pTruth = &uTruth, Truth[JF_WORD_MAX]; + // create new manager + pNew = Gia_ManStart( Gia_ManObjNum(p->pGia) ); + pNew->pName = Abc_UtilStrsav( p->pGia->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pGia->pSpec ); + pNew->vLevels = Vec_IntStart( 6*Gia_ManObjNum(p->pGia)/5 + 100 ); + // map primary inputs + Vec_IntWriteEntry( vCopies, 0, 0 ); + Gia_ManForEachCi( p->pGia, pObj, i ) + Vec_IntWriteEntry( vCopies, Gia_ObjId(p->pGia, pObj), Gia_ManAppendCi(pNew) ); + // iterate through nodes used in the mapping + if ( !p->pPars->fCutMin ) + Gia_ObjComputeTruthTableStart( p->pGia, p->pPars->nLutSize ); + Gia_ManHashStart( pNew ); + Gia_ManForEachAnd( p->pGia, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) || Gia_ObjRefNum(p->pGia, pObj) == 0 ) + continue; + pCut = Jf_ObjCutBest( p, i ); +// printf( "Best cut of node %d: ", i ); Jf_CutPrint(pCut); + // get the truth table + if ( p->pPars->fCutMin ) + { + Class = Jf_CutFuncClass( pCut ); + if ( Jf_CutSize(pCut) == 0 ) + { + assert( Class == 0 ); + Vec_IntWriteEntry( vCopies, i, Jf_CutFunc(pCut) ); + continue; + } + if ( Jf_CutSize(pCut) == 1 ) + { + assert( Class == 1 ); + iLit = Abc_LitNotCond( Jf_CutLit(pCut, 1) , Jf_CutFuncCompl(pCut) ); + iLit = Abc_Lit2LitL( Vec_IntArray(vCopies), iLit ); + Vec_IntWriteEntry( vCopies, i, iLit ); + continue; + } + if ( p->pPars->fFuncDsd ) + uTruth = Sdm_ManReadDsdTruth(p->pDsd, Class); + else + Abc_TtCopy( (pTruth = Truth), Vec_MemReadEntry(p->vTtMem, Class), nWords, 0 ); + assert( p->pDsd == NULL || Sdm_ManReadDsdVarNum(p->pDsd, Class) == Jf_CutSize(pCut) ); + } + else + { + Vec_IntClear( vLeaves ); + Jf_CutForEachLit( pCut, iLit, k ) + Vec_IntPush( vLeaves, Abc_Lit2Var(iLit) ); + pTruth = Gia_ObjComputeTruthTableCut( p->pGia, pObj, vLeaves ); + } + // collect incoming literals + Vec_IntClear( vLeaves ); + Jf_CutForEachLit( pCut, iLit, k ) + Vec_IntPush( vLeaves, Abc_Lit2LitL(Vec_IntArray(vCopies), iLit) ); + // create GIA + iLit = Dsm_ManTruthToGia( pNew, pTruth, vLeaves, vCover ); + iLit = Abc_LitNotCond( iLit, (p->pPars->fCutMin && Jf_CutFuncCompl(pCut)) ); + Vec_IntWriteEntry( vCopies, i, iLit ); + } + Gia_ManForEachCo( p->pGia, pObj, i ) + { + iLit = Vec_IntEntry( vCopies, Gia_ObjFaninId0p(p->pGia, pObj) ); + Gia_ManAppendCo( pNew, Abc_LitNotCond(iLit, Gia_ObjFaninC0(pObj)) ); + } + if ( !p->pPars->fCutMin ) + Gia_ObjComputeTruthTableStop( p->pGia ); + Vec_IntFree( vCopies ); + Vec_IntFree( vLeaves ); + Vec_IntFree( vCover ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p->pGia) ); +// Dsm_ManReportStats(); + // perform cleanup + if ( !p->pPars->fCutMin ) + { + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + } + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Jf_ManSetDefaultPars( Jf_Par_t * pPars ) +{ + memset( pPars, 0, sizeof(Jf_Par_t) ); + pPars->nLutSize = 6; + pPars->nCutNum = 8; + pPars->nRounds = 1; + pPars->nVerbLimit = 5; + pPars->DelayTarget = -1; + pPars->fAreaOnly = 1; + pPars->fOptEdge = 1; + pPars->fCoarsen = 0; + pPars->fCutMin = 0; + pPars->fFuncDsd = 0; + pPars->fGenCnf = 0; + pPars->fPureAig = 0; + pPars->fVerbose = 0; + pPars->fVeryVerbose = 0; + pPars->nLutSizeMax = JF_LEAF_MAX; + pPars->nCutNumMax = JF_CUT_MAX; +} +void Jf_ManPrintStats( Jf_Man_t * p, char * pTitle ) +{ + if ( !p->pPars->fVerbose ) + return; + printf( "%s : ", pTitle ); + printf( "Level =%6lu ", (long)p->pPars->Delay ); + printf( "Area =%9lu ", (long)p->pPars->Area ); + printf( "Edge =%9lu ", (long)p->pPars->Edge ); + if ( p->pPars->fGenCnf ) + printf( "Cnf =%9lu ", (long)p->pPars->Clause ); + Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); + fflush( stdout ); +} +Gia_Man_t * Jf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ) +{ + Gia_Man_t * pNew = pGia; + Jf_Man_t * p; int i; + assert( !Gia_ManBufNum(pGia) ); + assert( !pPars->fCutMin || !pPars->fFuncDsd || pPars->nLutSize <= 6 ); + if ( pPars->fGenCnf ) + pPars->fCutMin = 1, pPars->fFuncDsd = 1, pPars->fOptEdge = 0; + if ( pPars->fCutMin && !pPars->fFuncDsd ) + pPars->fCoarsen = 0; + p = Jf_ManAlloc( pGia, pPars ); + p->pCutCmp = pPars->fAreaOnly ? Jf_CutCompareArea : Jf_CutCompareDelay; + Jf_ManComputeCuts( p, 0 ); + Jf_ManComputeRefs( p ); Jf_ManPrintStats( p, "Start" ); + for ( i = 0; i < pPars->nRounds; i++ ) + { + if ( !p->pPars->fGenCnf ) + { + Jf_ManPropagateFlow( p, pPars->fOptEdge ); Jf_ManPrintStats( p, "Flow " ); + } + Jf_ManPropagateEla( p, 0 ); Jf_ManPrintStats( p, "Area " ); + Jf_ManPropagateEla( p, 1 ); Jf_ManPrintStats( p, "Edge " ); + } + if ( p->pPars->fVeryVerbose && p->pPars->fCutMin && !p->pPars->fFuncDsd ) + Vec_MemDumpTruthTables( p->vTtMem, Gia_ManName(p->pGia), p->pPars->nLutSize ); + if ( p->pPars->fPureAig ) + pNew = Jf_ManDeriveGia(p); + else if ( p->pPars->fCutMin ) + pNew = Jf_ManDeriveMappingGia(p); + else + Jf_ManDeriveMapping(p); + Jf_ManFree( p ); + return pNew; +} +Gia_Man_t * Jf_ManDeriveCnf( Gia_Man_t * p, int fCnfObjIds ) +{ + Jf_Par_t Pars, * pPars = &Pars; + Jf_ManSetDefaultPars( pPars ); + pPars->fGenCnf = 1; + pPars->fCnfObjIds = fCnfObjIds; + return Jf_ManPerformMapping( p, pPars ); +} +Gia_Man_t * Jf_ManDeriveCnfMiter( Gia_Man_t * p, int fVerbose ) +{ + Jf_Par_t Pars, * pPars = &Pars; + Jf_ManSetDefaultPars( pPars ); + pPars->fGenCnf = 1; + pPars->fCnfObjIds = 0; + pPars->fAddOrCla = 1; + pPars->fVerbose = fVerbose; + return Jf_ManPerformMapping( p, pPars ); +} +void Jf_ManDumpCnf( Gia_Man_t * p, char * pFileName, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Gia_Man_t * pNew; + Cnf_Dat_t * pCnf; + pNew = Jf_ManDeriveCnfMiter( p, fVerbose ); + pCnf = (Cnf_Dat_t *)pNew->pData; pNew->pData = NULL; + Cnf_DataWriteIntoFile( pCnf, pFileName, 0, NULL, NULL ); + Gia_ManStop( pNew ); +// if ( fVerbose ) + { + printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + Cnf_DataFree(pCnf); +} + +void Jf_ManTestCnf( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Cnf_Dat_t * pCnf; + int i; +// Cnf_Dat_t * pCnf = Cnf_DeriveGia( p ); + pNew = Jf_ManDeriveCnf( p, 1 ); + pCnf = (Cnf_Dat_t *)pNew->pData; pNew->pData = NULL; + Cnf_DataWriteIntoFile( pCnf, "test.cnf", 0, NULL, NULL ); + for ( i = 0; i < pCnf->nVars; i++ ) + printf( "%d : %d %d\n", i, pCnf->pObj2Count[i], pCnf->pObj2Clause[i] ); + Gia_ManStop( pNew ); + Cnf_DataFree(pCnf); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaKf.c b/yosys/abc/src/aig/gia/giaKf.c new file mode 100644 index 00000000000..6909851f1a3 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaKf.c @@ -0,0 +1,1346 @@ +/**CFile**************************************************************** + + FileName [giaKf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Cut computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaKf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/vec/vecSet.h" + +#ifdef _MSC_VER +#define unlink _unlink +#else +#include +#endif + +#ifdef ABC_USE_PTHREADS + +#ifdef _WIN32 +#include "../lib/pthread.h" +#else +#include +#endif + +#endif + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#ifndef ABC_USE_PTHREADS + +void Kf_ManSetDefaultPars( Jf_Par_t * pPars ) {} +Gia_Man_t * Kf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ) { return NULL; } + +#else // pthreads are used + +#define KF_LEAF_MAX 16 +#define KF_CUT_MAX 32 +#define KF_PROC_MAX 32 +#define KF_WORD_MAX ((KF_LEAF_MAX > 6) ? 1 << (KF_LEAF_MAX-6) : 1) +#define KF_LOG_TABLE 8 + +#define KF_ADD_ON1 2 // offset in cut storage for each node (cut count; best cut) +#define KF_ADD_ON2 4 // offset in cut storage for each cut (leaf count; function, cut delay; cut area) + +typedef struct Kf_Cut_t_ Kf_Cut_t; +typedef struct Kf_Set_t_ Kf_Set_t; +typedef struct Kf_Man_t_ Kf_Man_t; + +struct Kf_Cut_t_ +{ + word Sign; // signature + int Polar; // polarity + int Delay; // delay + float Area; // area + int iFunc; // function + int iNext; // next cut + int nLeaves; // number of leaves + int pLeaves[KF_LEAF_MAX]; +}; +struct Kf_Set_t_ +{ + Kf_Man_t * pMan; // manager + unsigned short nLutSize; // lut size + unsigned short nCutNum; // cut count + int nCuts0; // fanin0 cut count + int nCuts1; // fanin1 cut count + int nCuts; // resulting cut count + int nTEntries; // hash table entries + int TableMask; // hash table mask + int pTable[1 << KF_LOG_TABLE]; + int pValue[1 << KF_LOG_TABLE]; + int pPlace[KF_LEAF_MAX]; + int pList [KF_LEAF_MAX+1]; + Kf_Cut_t pCuts0[KF_CUT_MAX]; + Kf_Cut_t pCuts1[KF_CUT_MAX]; + Kf_Cut_t pCutsR[KF_CUT_MAX*KF_CUT_MAX]; + Kf_Cut_t * ppCuts[KF_CUT_MAX]; + Kf_Cut_t * pCutBest; + word CutCount[4]; // statistics +}; +struct Kf_Man_t_ +{ + Gia_Man_t * pGia; // user's manager + Jf_Par_t * pPars; // user's parameters + Vec_Set_t pMem; // cut storage + Vec_Int_t vCuts; // node params + Vec_Int_t vTime; // node params + Vec_Flt_t vArea; // node params + Vec_Flt_t vRefs; // node params + Vec_Int_t * vTemp; // temporary + abctime clkStart; // starting time + Kf_Set_t pSett[KF_PROC_MAX]; +}; + +static inline int Kf_SetCutId( Kf_Set_t * p, Kf_Cut_t * pCut ) { return pCut - p->pCutsR; } +static inline Kf_Cut_t * Kf_SetCut( Kf_Set_t * p, int i ) { return i >= 0 ? p->pCutsR + i : NULL; } + +static inline int Kf_ObjTime( Kf_Man_t * p, int i ) { return Vec_IntEntry(&p->vTime, i); } +static inline float Kf_ObjArea( Kf_Man_t * p, int i ) { return Vec_FltEntry(&p->vArea, i); } +static inline float Kf_ObjRefs( Kf_Man_t * p, int i ) { return Vec_FltEntry(&p->vRefs, i); } + +static inline void Kf_ObjSetCuts( Kf_Man_t * p, int i, Vec_Int_t * vVec ) { Vec_IntWriteEntry(&p->vCuts, i, Vec_SetAppend(&p->pMem, Vec_IntArray(vVec), Vec_IntSize(vVec))); } +static inline int * Kf_ObjCuts( Kf_Man_t * p, int i ) { return (int *)Vec_SetEntry(&p->pMem, Vec_IntEntry(&p->vCuts, i)); } +static inline int * Kf_ObjCuts0( Kf_Man_t * p, int i ) { return Kf_ObjCuts(p, Gia_ObjFaninId0(Gia_ManObj(p->pGia, i), i)); } +static inline int * Kf_ObjCuts1( Kf_Man_t * p, int i ) { return Kf_ObjCuts(p, Gia_ObjFaninId1(Gia_ManObj(p->pGia, i), i)); } +static inline int * Kf_ObjCutBest( Kf_Man_t * p, int i ) { int * pCuts = Kf_ObjCuts(p, i); return pCuts + pCuts[1]; } + +#define Kf_ObjForEachCutInt( pList, pCut, i ) for ( i = 0, pCut = pList + KF_ADD_ON1; i < pList[0]; i++, pCut += pCut[0] + KF_ADD_ON2 ) +#define Kf_ListForEachCut( p, iList, pCut ) for ( pCut = Kf_SetCut(p, p->pList[iList]); pCut; pCut = Kf_SetCut(p, pCut->iNext) ) +#define Kf_ListForEachCutP( p, iList, pCut, pPlace ) for ( pPlace = p->pList+iList, pCut = Kf_SetCut(p, *pPlace); pCut; pCut = Kf_SetCut(p, *pPlace) ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Kf_SetLoadCuts( Kf_Cut_t * pCuts, int * pIntCuts ) +{ + Kf_Cut_t * pCut; + int k, * pIntCut, nCuts = 0; + Kf_ObjForEachCutInt( pIntCuts, pIntCut, nCuts ) + { + pCut = pCuts + nCuts; + pCut->Sign = 0; + pCut->Polar = 0; + pCut->iFunc = pIntCut[pIntCut[0] + 1]; + pCut->Delay = pIntCut[pIntCut[0] + 2]; + pCut->Area = Abc_Int2Float(pIntCut[pIntCut[0] + 3]); + pCut->nLeaves = pIntCut[0]; + for ( k = 0; k < pIntCut[0]; k++ ) + { + pCut->pLeaves[k] = Abc_Lit2Var(pIntCut[k+1]); + pCut->Sign |= ((word)1) << (pCut->pLeaves[k] & 0x3F); + if ( Abc_LitIsCompl(pIntCut[k+1]) ) + pCut->Polar |= (1 << k); + } + } + return nCuts; +} +static inline void Kf_SetPrepare( Kf_Set_t * p, int * pCuts0, int * pCuts1 ) +{ + int i; + // prepare hash table +// for ( i = 0; i <= p->TableMask; i++ ) +// assert( p->pTable[i] == 0 ); + // prepare cut storage + for ( i = 0; i <= p->nLutSize; i++ ) + p->pList[i] = -1; + // transfer cuts + p->nCuts0 = Kf_SetLoadCuts( p->pCuts0, pCuts0 ); + p->nCuts1 = Kf_SetLoadCuts( p->pCuts1, pCuts1 ); + p->nCuts = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Kf_ManStoreStart( Vec_Int_t * vTemp, int nCuts ) +{ + Vec_IntClear( vTemp ); + Vec_IntPush( vTemp, nCuts ); // cut count + Vec_IntPush( vTemp, -1 ); // best offset +} +static inline void Kf_ManStoreAddUnit( Vec_Int_t * vTemp, int iObj, int Time, float Area ) +{ + Vec_IntAddToEntry( vTemp, 0, 1 ); + Vec_IntPush( vTemp, 1 ); // cut size + Vec_IntPush( vTemp, Abc_Var2Lit(iObj, 0) ); // leaf + Vec_IntPush( vTemp, 2 ); // function + Vec_IntPush( vTemp, Time ); // delay + Vec_IntPush( vTemp, Abc_Float2Int(Area) ); // area +} +static inline void Kf_ManSaveResults( Kf_Cut_t ** ppCuts, int nCuts, Kf_Cut_t * pCutBest, Vec_Int_t * vTemp ) +{ + int i, k; + assert( nCuts > 0 && nCuts < KF_CUT_MAX ); + Kf_ManStoreStart( vTemp, nCuts ); + for ( i = 0; i < nCuts; i++ ) + { + if ( ppCuts[i] == pCutBest ) + Vec_IntWriteEntry( vTemp, 1, Vec_IntSize(vTemp) ); + Vec_IntPush( vTemp, ppCuts[i]->nLeaves ); +// Vec_IntPushArray( vTemp, ppCuts[i]->pLeaves, ppCuts[i]->nLeaves ); + for ( k = 0; k < ppCuts[i]->nLeaves; k++ ) + Vec_IntPush( vTemp, Abc_Var2Lit(ppCuts[i]->pLeaves[k], 0) ); + Vec_IntPush( vTemp, ppCuts[i]->iFunc ); + Vec_IntPush( vTemp, ppCuts[i]->Delay ); + Vec_IntPush( vTemp, Abc_Float2Int(ppCuts[i]->Area) ); + } + assert( Vec_IntEntry(vTemp, 1) > 0 ); +} +static inline int Kf_SetCompareCuts( Kf_Cut_t * p1, Kf_Cut_t * p2 ) +{ + if ( p1 == NULL || p2 == NULL ) + return (p1 != NULL) - (p2 != NULL); + if ( p1->nLeaves != p2->nLeaves ) + return p1->nLeaves - p2->nLeaves; + return memcmp( p1->pLeaves, p2->pLeaves, sizeof(int)*p1->nLeaves ); +} +static inline void Kf_SetAddToList( Kf_Set_t * p, Kf_Cut_t * pCut, int fSort ) +{ + if ( !fSort ) + pCut->iNext = p->pList[pCut->nLeaves], p->pList[pCut->nLeaves] = Kf_SetCutId(p, pCut); + else + { + int Value, * pPlace; + Kf_Cut_t * pTemp; + Vec_IntSelectSort( pCut->pLeaves, pCut->nLeaves ); + Kf_ListForEachCutP( p, pCut->nLeaves, pTemp, pPlace ) + { + if ( (Value = Kf_SetCompareCuts(pTemp, pCut)) > 0 ) + break; + assert( Value < 0 ); + pPlace = &pTemp->iNext; + } + pCut->iNext = *pPlace, *pPlace = Kf_SetCutId(p, pCut); + } +} +static inline int Kf_CutCompare( Kf_Cut_t * pCut0, Kf_Cut_t * pCut1, int fArea ) +{ + if ( fArea ) + { + if ( pCut0->Area < pCut1->Area ) return -1; + if ( pCut0->Area > pCut1->Area ) return 1; + if ( pCut0->Delay < pCut1->Delay ) return -1; + if ( pCut0->Delay > pCut1->Delay ) return 1; + if ( pCut0->nLeaves < pCut1->nLeaves ) return -1; + if ( pCut0->nLeaves > pCut1->nLeaves ) return 1; + } + else + { + if ( pCut0->Delay < pCut1->Delay ) return -1; + if ( pCut0->Delay > pCut1->Delay ) return 1; + if ( pCut0->nLeaves < pCut1->nLeaves ) return -1; + if ( pCut0->nLeaves > pCut1->nLeaves ) return 1; + if ( pCut0->Area < pCut1->Area ) return -1; + if ( pCut0->Area > pCut1->Area ) return 1; + } + return 0; +} +static inline int Kf_SetStoreAddOne( Kf_Set_t * p, int nCuts, int nCutNum, Kf_Cut_t * pCut, int fArea ) +{ + int i; + p->ppCuts[nCuts] = pCut; + if ( nCuts == 0 ) + return 1; + for ( i = nCuts; i > 0; i-- ) + if ( Kf_CutCompare(p->ppCuts[i-1], p->ppCuts[i], fArea) > 0 ) + ABC_SWAP( Kf_Cut_t *, p->ppCuts[i-1], p->ppCuts[i] ) + else + break; + return Abc_MinInt( nCuts+1, nCutNum ); +} +static inline void Kf_SetSelectBest( Kf_Set_t * p, int fArea, int fSort ) +{ +// int fArea = p->pMan->pPars->fArea; + Kf_Cut_t * pCut; + int i, nCuts = 0; + for ( i = 0; i <= p->nLutSize; i++ ) + Kf_ListForEachCut( p, i, pCut ) + nCuts = Kf_SetStoreAddOne( p, nCuts, p->nCutNum-1, pCut, fArea ); + assert( nCuts > 0 && nCuts < p->nCutNum ); + p->nCuts = nCuts; + p->pCutBest = p->ppCuts[0]; + if ( !fSort ) + return; + // sort by size in the reverse order + for ( i = 0; i <= p->nLutSize; i++ ) + p->pList[i] = -1; + for ( i = 0; i < nCuts; i++ ) + Kf_SetAddToList( p, p->ppCuts[i], 0 ); + p->nCuts = 0; + for ( i = p->nLutSize; i >= 0; i-- ) + Kf_ListForEachCut( p, i, pCut ) + p->ppCuts[p->nCuts++] = pCut; + assert( p->nCuts == nCuts ); +} + +/**Function************************************************************* + + Synopsis [Check correctness of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Kf_CheckCut( Kf_Cut_t * pBase, Kf_Cut_t * pCut ) // check if pCut is contained in pBase +{ + int nSizeB = pBase->nLeaves; + int nSizeC = pCut->nLeaves; + int * pB = pBase->pLeaves; + int * pC = pCut->pLeaves; + int i, k; + for ( i = 0; i < nSizeC; i++ ) + { + for ( k = 0; k < nSizeB; k++ ) + if ( pC[i] == pB[k] ) + break; + if ( k == nSizeB ) + return 0; + } + return 1; +} +static inline int Kf_CheckCuts( Kf_Set_t * p ) +{ + Kf_Cut_t * pCut0, * pCut1; + int i, k, m, n, Value; + assert( p->nCuts > 0 ); + for ( i = 0; i <= p->nLutSize; i++ ) + Kf_ListForEachCut( p, i, pCut0 ) + { + // check duplicates + for ( m = 0; m < pCut0->nLeaves; m++ ) + for ( n = m+1; n < pCut0->nLeaves; n++ ) + assert( pCut0->pLeaves[m] != pCut0->pLeaves[n] ); + // check pairs + for ( k = 0; k <= p->nLutSize; k++ ) + Kf_ListForEachCut( p, k, pCut1 ) + { + if ( pCut0 == pCut1 ) + continue; + // check containments + Value = Kf_CheckCut( pCut0, pCut1 ); + assert( Value == 0 ); + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Kf_HashLookup( Kf_Set_t * p, int i ) +{ + int k; + assert( i > 0 ); + for ( k = i & p->TableMask; p->pTable[k]; k = (k + 1) & p->TableMask ) + if ( p->pTable[k] == i ) + return -1; + return k; +} +static inline int Kf_HashFindOrAdd( Kf_Set_t * p, int i ) +{ + int k = Kf_HashLookup( p, i ); + if ( k == -1 ) + return 0; + if ( p->nTEntries == p->nLutSize ) + return 1; + assert( p->pTable[k] == 0 ); + p->pTable[k] = i; + p->pPlace[p->nTEntries] = k; + p->pValue[k] = p->nTEntries++; + return 0; +} +static inline void Kf_HashPopulate( Kf_Set_t * p, Kf_Cut_t * pCut ) +{ + int i; + assert( p->nTEntries == 0 ); + for ( i = 0; i < pCut->nLeaves; i++ ) + Kf_HashFindOrAdd( p, pCut->pLeaves[i] ); + assert( p->nTEntries == pCut->nLeaves ); +} +static inline void Kf_HashCleanup( Kf_Set_t * p, int iStart ) +{ + int i; + for ( i = iStart; i < p->nTEntries; i++ ) + p->pTable[p->pPlace[i]] = 0; + p->nTEntries = iStart; +} + +/**Function************************************************************* + + Synopsis [Cut merging with arbitary order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Kf_SetCountBits( word i ) +{ + i = i - ((i >> 1) & 0x5555555555555555); + i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333); + i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F); + return (i*(0x0101010101010101))>>56; +} +static inline word Kf_SetCutGetSign( Kf_Cut_t * p ) +{ + word Sign = 0; int i; + for ( i = 0; i < p->nLeaves; i++ ) + Sign |= ((word)1) << (p->pLeaves[i] & 0x3F); + return Sign; +} +// returns 1 if the cut in hash table is dominated by the given one +static inline int Kf_SetCutDominatedByThis( Kf_Set_t * p, Kf_Cut_t * pCut ) +{ + int i; + for ( i = 0; i < pCut->nLeaves; i++ ) + if ( Kf_HashLookup(p, pCut->pLeaves[i]) >= 0 ) + return 0; + return 1; +} +static inline int Kf_SetRemoveDuplicates( Kf_Set_t * p, int nLeaves, word Sign ) +{ + Kf_Cut_t * pCut; + Kf_ListForEachCut( p, nLeaves, pCut ) + if ( pCut->Sign == Sign && Kf_SetCutDominatedByThis(p, pCut) ) + return 1; + return 0; +} +static inline void Kf_SetFilter( Kf_Set_t * p ) +{ + Kf_Cut_t * pCut0, * pCut1; + int i, k, * pPlace; + assert( p->nCuts > 0 ); + for ( i = 0; i <= p->nLutSize; i++ ) + Kf_ListForEachCutP( p, i, pCut0, pPlace ) + { + Kf_HashPopulate( p, pCut0 ); + for ( k = 0; k < pCut0->nLeaves; k++ ) + Kf_ListForEachCut( p, k, pCut1 ) + if ( (pCut0->Sign & pCut1->Sign) == pCut1->Sign && Kf_SetCutDominatedByThis(p, pCut1) ) + { k = pCut0->nLeaves; p->nCuts--; break; } + if ( k == pCut0->nLeaves + 1 ) // remove pCut0 + *pPlace = pCut0->iNext; + else + pPlace = &pCut0->iNext; + Kf_HashCleanup( p, 0 ); + } + assert( p->nCuts > 0 ); +} +static inline void Kf_SetMergePairs( Kf_Set_t * p, Kf_Cut_t * pCut0, Kf_Cut_t * pCuts, int nCuts, int fArea ) +{ + Kf_Cut_t * pCut1, * pCutR; int i; + Kf_HashPopulate( p, pCut0 ); + for ( pCut1 = pCuts; pCut1 < pCuts + nCuts; pCut1++ ) + { + if ( pCut0->nLeaves + pCut1->nLeaves > p->nLutSize && Kf_SetCountBits(pCut0->Sign | pCut1->Sign) > p->nLutSize ) + continue; + Kf_HashCleanup( p, pCut0->nLeaves ); + for ( i = 0; i < pCut1->nLeaves; i++ ) + if ( Kf_HashFindOrAdd(p, pCut1->pLeaves[i]) ) + break; + if ( i < pCut1->nLeaves ) + continue; + p->CutCount[1]++; + if ( Kf_SetRemoveDuplicates(p, p->nTEntries, pCut0->Sign | pCut1->Sign) ) + continue; + // create new cut + pCutR = p->pCutsR + p->nCuts++; + pCutR->nLeaves = p->nTEntries; + for ( i = 0; i < p->nTEntries; i++ ) + pCutR->pLeaves[i] = p->pTable[p->pPlace[i]]; + pCutR->Sign = pCut0->Sign | pCut1->Sign; + pCutR->Delay = Abc_MaxInt(pCut0->Delay, pCut1->Delay); + pCutR->Area = pCut0->Area + pCut1->Area; + // add new cut + Kf_SetAddToList( p, pCutR, 0 ); + } + Kf_HashCleanup( p, 0 ); +} +static inline void Kf_SetMerge( Kf_Set_t * p, int * pCuts0, int * pCuts1, int fArea, int fCutMin ) +{ + int c0, c1; + Kf_SetPrepare( p, pCuts0, pCuts1 ); + p->CutCount[0] += p->nCuts0 * p->nCuts1; +// for ( c0 = 1; c0 < p->nCuts0; c0++ ) +// assert( p->pCuts0[c0-1].nLeaves >= p->pCuts0[c0].nLeaves ); + for ( c0 = c1 = 0; c0 < p->nCuts0 && c1 < p->nCuts1; ) + { + if ( p->pCuts0[c0].nLeaves >= p->pCuts1[c1].nLeaves ) + Kf_SetMergePairs( p, p->pCuts0 + c0++, p->pCuts1 + c1, p->nCuts1 - c1, fArea ); + else + Kf_SetMergePairs( p, p->pCuts1 + c1++, p->pCuts0 + c0, p->nCuts0 - c0, fArea ); + } + p->CutCount[2] += p->nCuts; + Kf_SetFilter( p ); +// Kf_CheckCuts( p ); + p->CutCount[3] += Abc_MinInt( p->nCuts, p->nCutNum-1 ); + Kf_SetSelectBest( p, fArea, 1 ); +} + +/**Function************************************************************* + + Synopsis [Cut merging with fixed order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Kf_SetCutIsContainedSimple( Kf_Cut_t * pBase, Kf_Cut_t * pCut ) // check if pCut is contained in pBase +{ + int nSizeB = pBase->nLeaves; + int nSizeC = pCut->nLeaves; + int * pB = pBase->pLeaves; + int * pC = pCut->pLeaves; + int i, k; + assert( nSizeB >= nSizeC ); + for ( i = 0; i < nSizeC; i++ ) + { + for ( k = 0; k < nSizeB; k++ ) + if ( pC[i] == pB[k] ) + break; + if ( k == nSizeB ) + return 0; + } + return 1; +} +static inline int Kf_SetMergeSimpleOne( Kf_Cut_t * pCut0, Kf_Cut_t * pCut1, Kf_Cut_t * pCut, int nLutSize ) +{ + int nSize0 = pCut0->nLeaves; + int nSize1 = pCut1->nLeaves; + int * pC0 = pCut0->pLeaves; + int * pC1 = pCut1->pLeaves; + int * pC = pCut->pLeaves; + int i, k, c; + // compare two cuts with different numbers + c = nSize0; + for ( i = 0; i < nSize1; i++ ) + { + for ( k = 0; k < nSize0; k++ ) + if ( pC1[i] == pC0[k] ) + break; + if ( k < nSize0 ) + continue; + if ( c == nLutSize ) + return 0; + pC[c++] = pC1[i]; + } + for ( i = 0; i < nSize0; i++ ) + pC[i] = pC0[i]; + pCut->nLeaves = c; + return 1; +} +static inline int Kf_SetRemoveDuplicatesSimple( Kf_Set_t * p, Kf_Cut_t * pCutNew ) +{ + Kf_Cut_t * pCut; + Kf_ListForEachCut( p, pCutNew->nLeaves, pCut ) + if ( pCut->Sign == pCutNew->Sign && Kf_SetCutIsContainedSimple(pCut, pCutNew) ) + return 1; + return 0; +} +static inline void Kf_SetFilterSimple( Kf_Set_t * p ) +{ + Kf_Cut_t * pCut0, * pCut1; + int i, k, * pPlace; + assert( p->nCuts > 0 ); + for ( i = 0; i <= p->nLutSize; i++ ) + Kf_ListForEachCutP( p, i, pCut0, pPlace ) + { + for ( k = 0; k < pCut0->nLeaves; k++ ) + Kf_ListForEachCut( p, k, pCut1 ) + if ( (pCut0->Sign & pCut1->Sign) == pCut1->Sign && Kf_SetCutIsContainedSimple(pCut0, pCut1) ) + { k = pCut0->nLeaves; p->nCuts--; break; } + if ( k == pCut0->nLeaves + 1 ) // remove pCut0 + *pPlace = pCut0->iNext; + else + pPlace = &pCut0->iNext; + } + assert( p->nCuts > 0 ); +} +static inline void Kf_SetMergeSimple( Kf_Set_t * p, int * pCuts0, int * pCuts1, int fArea, int fCutMin ) +{ + Kf_Cut_t * pCut0, * pCut1, * pCutR; + Kf_SetPrepare( p, pCuts0, pCuts1 ); + p->CutCount[0] += p->nCuts0 * p->nCuts1; + for ( pCut0 = p->pCuts0; pCut0 < p->pCuts0 + p->nCuts0; pCut0++ ) + for ( pCut1 = p->pCuts1; pCut1 < p->pCuts1 + p->nCuts1; pCut1++ ) + { + if ( pCut0->nLeaves + pCut1->nLeaves > p->nLutSize && Kf_SetCountBits(pCut0->Sign | pCut1->Sign) > p->nLutSize ) + continue; + p->CutCount[1]++; + pCutR = p->pCutsR + p->nCuts; + if ( !Kf_SetMergeSimpleOne(pCut0, pCut1, pCutR, p->nLutSize) ) + continue; + p->CutCount[2]++; + pCutR->Sign = pCut0->Sign | pCut1->Sign; + if ( Kf_SetRemoveDuplicatesSimple(p, pCutR) ) + continue; + p->nCuts++; + if ( fCutMin ) + { + int nOldSupp = pCutR->nLeaves; +// pCutR->iFunc = Kf_SetComputeTruth( p, pCut0->iFunc, pCut1->iFunc, pCut0, pCut1, pCutR ); + assert( pCutR->nLeaves <= nOldSupp ); + if ( pCutR->nLeaves < nOldSupp ) + pCutR->Sign = Kf_SetCutGetSign( pCutR ); + // delay and area are inaccurate + } + assert( pCutR->nLeaves > 1 ); + pCutR->Delay = Abc_MaxInt(pCut0->Delay, pCut1->Delay); + pCutR->Area = pCut0->Area + pCut1->Area; + // add new cut + Kf_SetAddToList( p, pCutR, 0 ); + } + Kf_SetFilterSimple( p ); +// Kf_CheckCuts( p ); + p->CutCount[3] += Abc_MinInt( p->nCuts, p->nCutNum-1 ); + Kf_SetSelectBest( p, fArea, 1 ); +} + +/**Function************************************************************* + + Synopsis [Cut merging with fixed order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Kf_SetCutIsContainedOrder( Kf_Cut_t * pBase, Kf_Cut_t * pCut ) // check if pCut is contained in pBase +{ + int nSizeB = pBase->nLeaves; + int nSizeC = pCut->nLeaves; + int i, k; + if ( nSizeB == nSizeC ) + { + for ( i = 0; i < nSizeB; i++ ) + if ( pBase->pLeaves[i] != pCut->pLeaves[i] ) + return 0; + return 1; + } + assert( nSizeB > nSizeC ); + for ( i = k = 0; i < nSizeB; i++ ) + { + if ( pBase->pLeaves[i] > pCut->pLeaves[k] ) + return 0; + if ( pBase->pLeaves[i] == pCut->pLeaves[k] ) + { + if ( ++k == nSizeC ) + return 1; + } + } + return 0; +} +static inline int Kf_SetMergeOrderOne( Kf_Cut_t * pCut0, Kf_Cut_t * pCut1, Kf_Cut_t * pCut, int nLutSize ) +{ + int nSize0 = pCut0->nLeaves; + int nSize1 = pCut1->nLeaves; + int * pC0 = pCut0->pLeaves; + int * pC1 = pCut1->pLeaves; + int * pC = pCut->pLeaves; + int i, k, c; + // the case of the largest cut sizes + if ( nSize0 == nLutSize && nSize1 == nLutSize ) + { + for ( i = 0; i < nSize0; i++ ) + { + if ( pC0[i] != pC1[i] ) return 0; + pC[i] = pC0[i]; + } + pCut->nLeaves = nLutSize; + return 1; + } + // compare two cuts with different numbers + i = k = c = 0; + while ( 1 ) + { + if ( c == nLutSize ) return 0; + if ( pC0[i] < pC1[k] ) + { + pC[c++] = pC0[i++]; + if ( i >= nSize0 ) goto FlushCut1; + } + else if ( pC0[i] > pC1[k] ) + { + pC[c++] = pC1[k++]; + if ( k >= nSize1 ) goto FlushCut0; + } + else + { + pC[c++] = pC0[i++]; k++; + if ( i >= nSize0 ) goto FlushCut1; + if ( k >= nSize1 ) goto FlushCut0; + } + } + +FlushCut0: + if ( c + nSize0 > nLutSize + i ) return 0; + while ( i < nSize0 ) + pC[c++] = pC0[i++]; + pCut->nLeaves = c; + return 1; + +FlushCut1: + if ( c + nSize1 > nLutSize + k ) return 0; + while ( k < nSize1 ) + pC[c++] = pC1[k++]; + pCut->nLeaves = c; + return 1; +} +static inline int Kf_SetRemoveDuplicatesOrder( Kf_Set_t * p, Kf_Cut_t * pCutNew ) +{ + Kf_Cut_t * pCut; + Kf_ListForEachCut( p, pCutNew->nLeaves, pCut ) + if ( pCut->Sign == pCutNew->Sign && Kf_SetCutIsContainedOrder(pCut, pCutNew) ) + return 1; + return 0; +} +static inline void Kf_SetFilterOrder( Kf_Set_t * p ) +{ + Kf_Cut_t * pCut0, * pCut1; + int i, k, * pPlace; + assert( p->nCuts > 0 ); + for ( i = 0; i <= p->nLutSize; i++ ) + Kf_ListForEachCutP( p, i, pCut0, pPlace ) + { + for ( k = 0; k < pCut0->nLeaves; k++ ) + Kf_ListForEachCut( p, k, pCut1 ) + if ( (pCut0->Sign & pCut1->Sign) == pCut1->Sign && Kf_SetCutIsContainedOrder(pCut0, pCut1) ) + { k = pCut0->nLeaves; p->nCuts--; break; } + if ( k == pCut0->nLeaves + 1 ) // remove pCut0 + *pPlace = pCut0->iNext; + else + pPlace = &pCut0->iNext; + } + assert( p->nCuts > 0 ); +} +/* +int Kf_SetComputeTruth( Kf_Man_t * p, int iFuncLit0, int iFuncLit1, int * pCut0, int * pCut1, int * pCutOut ) +{ + word uTruth[JF_WORD_MAX], uTruth0[JF_WORD_MAX], uTruth1[JF_WORD_MAX]; + int fCompl, truthId; + int LutSize = p->pPars->nLutSize; + int nWords = Abc_Truth6WordNum(p->pPars->nLutSize); + word * pTruth0 = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(iFuncLit0)); + word * pTruth1 = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(iFuncLit1)); + Abc_TtCopy( uTruth0, pTruth0, nWords, Abc_LitIsCompl(iFuncLit0) ); + Abc_TtCopy( uTruth1, pTruth1, nWords, Abc_LitIsCompl(iFuncLit1) ); + Abc_TtExpand( uTruth0, LutSize, pCut0 + 1, Kf_CutSize(pCut0), pCutOut + 1, Kf_CutSize(pCutOut) ); + Abc_TtExpand( uTruth1, LutSize, pCut1 + 1, Kf_CutSize(pCut1), pCutOut + 1, Kf_CutSize(pCutOut) ); + fCompl = (int)(uTruth0[0] & uTruth1[0] & 1); + Abc_TtAnd( uTruth, uTruth0, uTruth1, nWords, fCompl ); + pCutOut[0] = Abc_TtMinBase( uTruth, pCutOut + 1, pCutOut[0], LutSize ); + assert( (uTruth[0] & 1) == 0 ); + truthId = Vec_MemHashInsert(p->vTtMem, uTruth); + return Abc_Var2Lit( truthId, fCompl ); +} +*/ +static inline void Kf_SetMergeOrder( Kf_Set_t * p, int * pCuts0, int * pCuts1, int fArea, int fCutMin ) +{ + Kf_Cut_t * pCut0, * pCut1, * pCutR; + Kf_SetPrepare( p, pCuts0, pCuts1 ); + p->CutCount[0] += p->nCuts0 * p->nCuts1; + for ( pCut0 = p->pCuts0; pCut0 < p->pCuts0 + p->nCuts0; pCut0++ ) + for ( pCut1 = p->pCuts1; pCut1 < p->pCuts1 + p->nCuts1; pCut1++ ) + { + if ( pCut0->nLeaves + pCut1->nLeaves > p->nLutSize && Kf_SetCountBits(pCut0->Sign | pCut1->Sign) > p->nLutSize ) + continue; + p->CutCount[1]++; + pCutR = p->pCutsR + p->nCuts; + if ( !Kf_SetMergeOrderOne(pCut0, pCut1, pCutR, p->nLutSize) ) + continue; + p->CutCount[2]++; + pCutR->Sign = pCut0->Sign | pCut1->Sign; + if ( Kf_SetRemoveDuplicatesOrder(p, pCutR) ) + continue; + p->nCuts++; + if ( fCutMin ) + { + int nOldSupp = pCutR->nLeaves; +// pCutR->iFunc = Kf_SetComputeTruth( p, pCut0->iFunc, pCut1->iFunc, pCut0, pCut1, pCutR ); + assert( pCutR->nLeaves <= nOldSupp ); + if ( pCutR->nLeaves < nOldSupp ) + pCutR->Sign = Kf_SetCutGetSign( pCutR ); + // delay and area are inaccurate + } + assert( pCutR->nLeaves > 1 ); + pCutR->Delay = Abc_MaxInt(pCut0->Delay, pCut1->Delay); + pCutR->Area = pCut0->Area + pCut1->Area; + // add new cut + Kf_SetAddToList( p, pCutR, 0 ); + } + Kf_SetFilterOrder( p ); +// Kf_CheckCuts( p ); + p->CutCount[3] += Abc_MinInt( p->nCuts, p->nCutNum-1 ); + Kf_SetSelectBest( p, fArea, 1 ); +} + + +/**Function************************************************************* + + Synopsis [Cut operations.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Kf_CutSize( int * pCut ) { return pCut[0]; } +static inline int Kf_CutFunc( int * pCut ) { return pCut[pCut[0] + 1]; } +static inline int Kf_CutLeaf( int * pCut, int i ) { assert(i); return Abc_Lit2Var(pCut[i]); } +static inline int Kf_CutTime( Kf_Man_t * p, int * pCut ) +{ + int i, Time = 0; + for ( i = 1; i <= Kf_CutSize(pCut); i++ ) + Time = Abc_MaxInt( Time, Kf_ObjTime(p, Kf_CutLeaf(pCut, i)) ); + return Time + 1; +} +static inline void Kf_CutRef( Kf_Man_t * p, int * pCut ) +{ + int i; + for ( i = 1; i <= Kf_CutSize(pCut); i++ ) + Gia_ObjRefIncId( p->pGia, Kf_CutLeaf(pCut, i) ); +} +static inline void Kf_CutDeref( Kf_Man_t * p, int * pCut ) +{ + int i; + for ( i = 1; i <= Kf_CutSize(pCut); i++ ) + Gia_ObjRefDecId( p->pGia, Kf_CutLeaf(pCut, i) ); +} +static inline void Kf_CutPrint( int * pCut ) +{ + int i; + printf( "%d {", Kf_CutSize(pCut) ); + for ( i = 1; i <= Kf_CutSize(pCut); i++ ) + printf( " %d", Kf_CutLeaf(pCut, i) ); + printf( " } Func = %d\n", Kf_CutFunc(pCut) ); +} +static inline void Gia_CutSetPrint( int * pCuts ) +{ + int i, * pCut; + Kf_ObjForEachCutInt( pCuts, pCut, i ) + Kf_CutPrint( pCut ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Computing delay/area.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Kf_ManComputeDelay( Kf_Man_t * p, int fEval ) +{ + Gia_Obj_t * pObj; + int i, Delay = 0; + if ( fEval ) + { + Gia_ManForEachAnd( p->pGia, pObj, i ) + if ( Gia_ObjRefNum(p->pGia, pObj) > 0 ) + Vec_IntWriteEntry( &p->vTime, i, Kf_CutTime(p, Kf_ObjCutBest(p, i)) ); + } + Gia_ManForEachCoDriver( p->pGia, pObj, i ) + { + assert( Gia_ObjRefNum(p->pGia, pObj) > 0 ); + Delay = Abc_MaxInt( Delay, Kf_ObjTime(p, Gia_ObjId(p->pGia, pObj)) ); + } + return Delay; +} +int Kf_ManComputeRefs( Kf_Man_t * p ) +{ + Gia_Obj_t * pObj; + float nRefsNew; int i, * pCut; + float * pRefs = Vec_FltArray(&p->vRefs); + float * pFlow = Vec_FltArray(&p->vArea); + assert( p->pGia->pRefs != NULL ); + memset( p->pGia->pRefs, 0, sizeof(int) * Gia_ManObjNum(p->pGia) ); + p->pPars->Area = p->pPars->Edge = 0; + Gia_ManForEachObjReverse( p->pGia, pObj, i ) + { + if ( Gia_ObjIsCo(pObj) || Gia_ObjIsBuf(pObj) ) + Gia_ObjRefInc( p->pGia, Gia_ObjFanin0(pObj) ); + else if ( Gia_ObjIsAnd(pObj) && Gia_ObjRefNum(p->pGia, pObj) > 0 ) + { + pCut = Kf_ObjCutBest(p, i); + Kf_CutRef( p, pCut ); + p->pPars->Edge += Kf_CutSize(pCut); + p->pPars->Area++; + } + } + // blend references and normalize flow + for ( i = 0; i < Gia_ManObjNum(p->pGia); i++ ) + { + if ( p->pPars->fOptEdge ) + nRefsNew = Abc_MaxFloat( 1, 0.8 * pRefs[i] + 0.2 * p->pGia->pRefs[i] ); + else + nRefsNew = Abc_MaxFloat( 1, 0.2 * pRefs[i] + 0.8 * p->pGia->pRefs[i] ); + pFlow[i] = pFlow[i] * pRefs[i] / nRefsNew; + pRefs[i] = nRefsNew; + assert( pFlow[i] >= 0 ); + } + // compute delay + p->pPars->Delay = Kf_ManComputeDelay( p, 1 ); + return p->pPars->Area; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +#define PAR_THR_MAX 100 +typedef struct Kf_ThData_t_ +{ + Kf_Set_t * pSett; + int Id; + int Status; + abctime clkUsed; +} Kf_ThData_t; +void * Kf_WorkerThread( void * pArg ) +{ + Kf_ThData_t * pThData = (Kf_ThData_t *)pArg; + Kf_Man_t * pMan = pThData->pSett->pMan; + int fAreaOnly = pThData->pSett->pMan->pPars->fAreaOnly; + int fCutMin = pThData->pSett->pMan->pPars->fCutMin; + volatile int * pPlace = &pThData->Status; + abctime clk; + while ( 1 ) + { + while ( *pPlace == 0 ); + assert( pThData->Status == 1 ); + if ( pThData->Id == -1 ) + { + pthread_exit( NULL ); + assert( 0 ); + return NULL; + } + assert( pThData->Id >= 0 ); + clk = Abc_Clock(); + Kf_SetMergeOrder( pThData->pSett, Kf_ObjCuts0(pMan, pThData->Id), Kf_ObjCuts1(pMan, pThData->Id), fAreaOnly, fCutMin ); + pThData->clkUsed += Abc_Clock() - clk; + pThData->Status = 0; +// printf( "Finished object %d\n", pThData->Id ); + } + assert( 0 ); + return NULL; +} +Vec_Int_t * Kf_ManCreateFaninCounts( Gia_Man_t * p ) +{ + Vec_Int_t * vCounts; + Gia_Obj_t * pObj; int i; + vCounts = Vec_IntAlloc( Gia_ManObjNum(p) ); + Gia_ManForEachObj( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + Vec_IntPush( vCounts, 2 - Gia_ObjIsCi(Gia_ObjFanin0(pObj)) - Gia_ObjIsCi(Gia_ObjFanin1(pObj)) ); + else + Vec_IntPush( vCounts, 0 ); + } + assert( Vec_IntSize(vCounts) == Gia_ManObjNum(p) ); + return vCounts; +} +void Kf_ManComputeCuts( Kf_Man_t * p ) +{ + pthread_t WorkerThread[PAR_THR_MAX]; + Kf_ThData_t ThData[PAR_THR_MAX]; + Vec_Int_t * vStack, * vFanins; + Gia_Obj_t * pObj; + int nProcs = p->pPars->nProcNum; + int i, k, iFan, status, nCountFanins, fRunning; + abctime clk, clkUsed = 0; + assert( nProcs <= PAR_THR_MAX ); + // start fanins + vFanins = Kf_ManCreateFaninCounts( p->pGia ); + Gia_ManStaticFanoutStart( p->pGia ); + // start the stack + vStack = Vec_IntAlloc( 1000 ); + Gia_ManForEachObjReverse( p->pGia, pObj, k ) + if ( Gia_ObjIsAnd(pObj) && Vec_IntEntry(vFanins, k) == 0 ) + Vec_IntPush( vStack, k ); + // start the threads + for ( i = 0; i < nProcs; i++ ) + { + ThData[i].pSett = p->pSett + i; + ThData[i].Id = -1; + ThData[i].Status = 0; + ThData[i].clkUsed = 0; + status = pthread_create( WorkerThread + i, NULL, Kf_WorkerThread, (void *)(ThData + i) ); assert( status == 0 ); + } + nCountFanins = Vec_IntSum(vFanins); + fRunning = 1; + while ( nCountFanins > 0 || Vec_IntSize(vStack) > 0 || fRunning ) + { + for ( i = 0; i < nProcs; i++ ) + { + if ( ThData[i].Status ) + continue; + assert( ThData[i].Status == 0 ); + if ( ThData[i].Id >= 0 ) + { + int iObj = ThData[i].Id; + Kf_Set_t * pSett = p->pSett + i; + //printf( "Closing obj %d with Thread %d:\n", iObj, i ); + clk = Abc_Clock(); + // finalize the results + Kf_ManSaveResults( pSett->ppCuts, pSett->nCuts, pSett->pCutBest, p->vTemp ); + Vec_IntWriteEntry( &p->vTime, iObj, pSett->pCutBest->Delay + 1 ); + Vec_FltWriteEntry( &p->vArea, iObj, (pSett->pCutBest->Area + 1)/Kf_ObjRefs(p, iObj) ); + if ( pSett->pCutBest->nLeaves > 1 ) + Kf_ManStoreAddUnit( p->vTemp, iObj, Kf_ObjTime(p, iObj), Kf_ObjArea(p, iObj) ); + Kf_ObjSetCuts( p, iObj, p->vTemp ); + //Gia_CutSetPrint( Kf_ObjCuts(p, iObj) ); + clkUsed += Abc_Clock() - clk; + // schedule other nodes + Gia_ObjForEachFanoutStaticId( p->pGia, iObj, iFan, k ) + { + if ( !Gia_ObjIsAnd(Gia_ManObj(p->pGia, iFan)) ) + continue; + assert( Vec_IntEntry(vFanins, iFan) > 0 ); + if ( Vec_IntAddToEntry(vFanins, iFan, -1) == 0 ) + Vec_IntPush( vStack, iFan ); + assert( nCountFanins > 0 ); + nCountFanins--; + } + ThData[i].Id = -1; + } + if ( Vec_IntSize(vStack) > 0 ) + { + ThData[i].Id = Vec_IntPop( vStack ); + ThData[i].Status = 1; + //printf( "Scheduling %d for Thread %d\n", ThData[i].Id, i ); + } + } + fRunning = 0; + for ( i = 0; i < nProcs; i++ ) + if ( ThData[i].Status == 1 || (ThData[i].Status == 0 && ThData[i].Id >= 0) ) + fRunning = 1; +// printf( "fRunning %d\n", fRunning ); + } + Vec_IntForEachEntry( vFanins, iFan, k ) + if ( iFan != 0 ) + { + printf( "%d -> %d ", k, iFan ); + Gia_ObjPrint( p->pGia, Gia_ManObj(p->pGia, k) ); + } + assert( Vec_IntSum(vFanins) == 0 ); + // stop the threads + for ( i = 0; i < nProcs; i++ ) + { + assert( ThData[i].Status == 0 ); + ThData[i].Id = -1; + ThData[i].Status = 1; + } + Gia_ManStaticFanoutStop( p->pGia ); + Vec_IntFree( vStack ); + Vec_IntFree( vFanins ); + if ( !p->pPars->fVerbose ) + return; + // print runtime statistics + printf( "Main : " ); + Abc_PrintTime( 1, "Time", clkUsed ); + for ( i = 0; i < nProcs; i++ ) + { + printf( "Thread %d : ", i ); + Abc_PrintTime( 1, "Time", ThData[i].clkUsed ); + } + +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kf_ManPrintStats( Kf_Man_t * p, char * pTitle ) +{ + if ( !p->pPars->fVerbose ) + return; + printf( "%s : ", pTitle ); + printf( "Level =%6lu ", (long)p->pPars->Delay ); + printf( "Area =%9lu ", (long)p->pPars->Area ); + printf( "Edge =%9lu ", (long)p->pPars->Edge ); + Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); + fflush( stdout ); +} +void Kf_ManComputeMapping( Kf_Man_t * p ) +{ + Gia_Obj_t * pObj; int i, iPi; + if ( p->pPars->fVerbose ) + { + printf( "Aig: CI = %d CO = %d AND = %d ", Gia_ManCiNum(p->pGia), Gia_ManCoNum(p->pGia), Gia_ManAndNum(p->pGia) ); + printf( "LutSize = %d CutMax = %d Threads = %d\n", p->pPars->nLutSize, p->pPars->nCutNum, p->pPars->nProcNum ); + printf( "Computing cuts...\r" ); + fflush( stdout ); + } + Gia_ManForEachCi( p->pGia, pObj, iPi ) + { + i = Gia_ObjId(p->pGia, pObj); + Kf_ManStoreStart( p->vTemp, 0 ); + Kf_ManStoreAddUnit( p->vTemp, i, 0, 0 ); + assert( Vec_IntSize(p->vTemp) == 1 + KF_ADD_ON1 + KF_ADD_ON2 ); + Kf_ObjSetCuts( p, i, p->vTemp ); + } + if ( p->pPars->nProcNum > 0 ) + Kf_ManComputeCuts( p ); + else + { + Gia_ManForEachAnd( p->pGia, pObj, i ) + { + if ( p->pPars->fCutHashing ) + Kf_SetMerge( p->pSett, Kf_ObjCuts0(p, i), Kf_ObjCuts1(p, i), p->pPars->fAreaOnly, p->pPars->fCutMin ); + else if ( p->pPars->fCutSimple ) + Kf_SetMergeSimple( p->pSett, Kf_ObjCuts0(p, i), Kf_ObjCuts1(p, i), p->pPars->fAreaOnly, p->pPars->fCutMin ); + else + Kf_SetMergeOrder( p->pSett, Kf_ObjCuts0(p, i), Kf_ObjCuts1(p, i), p->pPars->fAreaOnly, p->pPars->fCutMin ); + Kf_ManSaveResults( p->pSett->ppCuts, p->pSett->nCuts, p->pSett->pCutBest, p->vTemp ); + Vec_IntWriteEntry( &p->vTime, i, p->pSett->pCutBest->Delay + 1 ); + Vec_FltWriteEntry( &p->vArea, i, (p->pSett->pCutBest->Area + 1)/Kf_ObjRefs(p, i) ); + if ( p->pSett->pCutBest->nLeaves > 1 ) + Kf_ManStoreAddUnit( p->vTemp, i, Kf_ObjTime(p, i), Kf_ObjArea(p, i) ); + Kf_ObjSetCuts( p, i, p->vTemp ); + //Gia_CutSetPrint( Kf_ObjCuts(p, i) ); + } + } + Kf_ManComputeRefs( p ); + if ( p->pPars->fVerbose ) + { + printf( "CutPair = %lu ", (long)p->pSett->CutCount[0] ); + printf( "Merge = %lu ", (long)p->pSett->CutCount[1] ); + printf( "Eval = %lu ", (long)p->pSett->CutCount[2] ); + printf( "Cut = %lu ", (long)p->pSett->CutCount[3] ); + Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); + printf( "Memory: " ); + printf( "Gia = %.2f MB ", Gia_ManMemory(p->pGia) / (1<<20) ); + printf( "Man = %.2f MB ", 4.0 * sizeof(int) * Gia_ManObjNum(p->pGia) / (1<<20) ); + printf( "Cuts = %.2f MB ",Vec_ReportMemory(&p->pMem) / (1<<20) ); + printf( "Set = %.2f KB ", 1.0 * sizeof(Kf_Set_t) / (1<<10) ); + printf( "\n" ); + fflush( stdout ); + Kf_ManPrintStats( p, "Start" ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kf_ManSetInitRefs( Gia_Man_t * p, Vec_Flt_t * vRefs ) +{ + Gia_Obj_t * pObj, * pCtrl, * pData0, * pData1; int i; + Vec_FltFill( vRefs, Gia_ManObjNum(p), 0 ); + Gia_ManForEachAnd( p, pObj, i ) + { + Vec_FltAddToEntry( vRefs, Gia_ObjFaninId0(pObj, i), 1 ); + Vec_FltAddToEntry( vRefs, Gia_ObjFaninId1(pObj, i), 1 ); + if ( !Gia_ObjIsMuxType(pObj) ) + continue; + // discount XOR/MUX + pCtrl = Gia_ObjRecognizeMux( pObj, &pData1, &pData0 ); + Vec_FltAddToEntry( vRefs, Gia_ObjId(p, Gia_Regular(pCtrl)), -1 ); + if ( Gia_Regular(pData0) == Gia_Regular(pData1) ) + Vec_FltAddToEntry( vRefs, Gia_ObjId(p, Gia_Regular(pData0)), -1 ); + } + Gia_ManForEachCo( p, pObj, i ) + Vec_FltAddToEntry( vRefs, Gia_ObjFaninId0(pObj, Gia_ObjId(p, pObj)), 1 ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + Vec_FltUpdateEntry( vRefs, i, 1 ); +} +Kf_Man_t * Kf_ManAlloc( Gia_Man_t * pGia, Jf_Par_t * pPars ) +{ + Kf_Man_t * p; int i; + assert( pPars->nLutSize <= KF_LEAF_MAX ); + assert( pPars->nCutNum <= KF_CUT_MAX ); + assert( pPars->nProcNum <= KF_PROC_MAX ); + Vec_IntFreeP( &pGia->vMapping ); + p = ABC_CALLOC( Kf_Man_t, 1 ); + p->clkStart = Abc_Clock(); + p->pGia = pGia; + p->pPars = pPars; + Vec_SetAlloc_( &p->pMem, 20 ); + Vec_IntFill( &p->vCuts, Gia_ManObjNum(pGia), 0 ); + Vec_IntFill( &p->vTime, Gia_ManObjNum(pGia), 0 ); + Vec_FltFill( &p->vArea, Gia_ManObjNum(pGia), 0 ); + Kf_ManSetInitRefs( pGia, &p->vRefs ); + p->vTemp = Vec_IntAlloc( 1000 ); + pGia->pRefs = ABC_CALLOC( int, Gia_ManObjNum(pGia) ); + // prepare cut sets + for ( i = 0; i < Abc_MaxInt(1, pPars->nProcNum); i++ ) + { + (p->pSett + i)->pMan = p; + (p->pSett + i)->nLutSize = (unsigned short)pPars->nLutSize; + (p->pSett + i)->nCutNum = (unsigned short)pPars->nCutNum; + (p->pSett + i)->TableMask = (1 << KF_LOG_TABLE) - 1; + } + return p; +} +void Kf_ManFree( Kf_Man_t * p ) +{ + ABC_FREE( p->pGia->pRefs ); + ABC_FREE( p->vCuts.pArray ); + ABC_FREE( p->vTime.pArray ); + ABC_FREE( p->vArea.pArray ); + ABC_FREE( p->vRefs.pArray ); + Vec_IntFreeP( &p->vTemp ); + Vec_SetFree_( &p->pMem ); + ABC_FREE( p ); +} +Gia_Man_t * Kf_ManDerive( Kf_Man_t * p ) +{ + Vec_Int_t * vMapping; + Gia_Obj_t * pObj; + int i, k, * pCut; + assert( !p->pPars->fCutMin ); + vMapping = Vec_IntAlloc( Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + (int)p->pPars->Area * 2 ); + Vec_IntFill( vMapping, Gia_ManObjNum(p->pGia), 0 ); + Gia_ManForEachAnd( p->pGia, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) || Gia_ObjRefNum(p->pGia, pObj) == 0 ) + continue; + pCut = Kf_ObjCutBest( p, i ); + Vec_IntWriteEntry( vMapping, i, Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, Kf_CutSize(pCut) ); + for ( k = 1; k <= Kf_CutSize(pCut); k++ ) + Vec_IntPush( vMapping, Kf_CutLeaf(pCut, k) ); + Vec_IntPush( vMapping, i ); + } + assert( Vec_IntCap(vMapping) == 16 || Vec_IntSize(vMapping) == Vec_IntCap(vMapping) ); + p->pGia->vMapping = vMapping; +// Gia_ManMappingVerify( p->pGia ); + return p->pGia; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Kf_ManSetDefaultPars( Jf_Par_t * pPars ) +{ + memset( pPars, 0, sizeof(Jf_Par_t) ); + pPars->nLutSize = 6; + pPars->nCutNum = 8; + pPars->nProcNum = 0; + pPars->nRounds = 1; + pPars->nVerbLimit = 5; + pPars->DelayTarget = -1; + pPars->fAreaOnly = 0; + pPars->fOptEdge = 1; + pPars->fCoarsen = 0; + pPars->fCutMin = 0; + pPars->fFuncDsd = 0; + pPars->fGenCnf = 0; + pPars->fPureAig = 0; + pPars->fCutHashing = 0; + pPars->fCutSimple = 0; + pPars->fVerbose = 0; + pPars->fVeryVerbose = 0; + pPars->nLutSizeMax = KF_LEAF_MAX; + pPars->nCutNumMax = KF_CUT_MAX; + pPars->nProcNumMax = KF_PROC_MAX; +} +Gia_Man_t * Kf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ) +{ + Kf_Man_t * p; + Gia_Man_t * pNew; + p = Kf_ManAlloc( pGia, pPars ); + Kf_ManComputeMapping( p ); + pNew = Kf_ManDerive( p ); + Kf_ManFree( p ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +#endif // pthreads are used + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaLf.c b/yosys/abc/src/aig/gia/giaLf.c new file mode 100644 index 00000000000..13066005038 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaLf.c @@ -0,0 +1,2346 @@ +/**CFile**************************************************************** + + FileName [giaLf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Cut computation.] + + Author [Alan Mishchenko]` + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaLf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/tim/tim.h" +#include "misc/vec/vecSet.h" +#include "misc/vec/vecMem.h" +#include "misc/util/utilTruth.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define LF_LEAF_MAX 13 +#define LF_CUT_MAX 32 +#define LF_LOG_PAGE 12 +#define LF_NO_LEAF 255 +#define LF_CUT_WORDS (4+LF_LEAF_MAX/2) +#define LF_TT_WORDS ((LF_LEAF_MAX > 6) ? 1 << (LF_LEAF_MAX-6) : 1) +#define LF_EPSILON 0.005 + +typedef struct Lf_Cut_t_ Lf_Cut_t; +struct Lf_Cut_t_ +{ + word Sign; // signature + int Delay; // delay + float Flow; // flow + int iFunc; // functionality + unsigned Cost : 22; // misc cut cost + unsigned fLate : 1; // fails timing + unsigned fMux7 : 1; // specialized cut + unsigned nLeaves : 8; // the number of leaves + int pLeaves[0]; // leaves +}; +typedef struct Lf_Plc_t_ Lf_Plc_t; +struct Lf_Plc_t_ +{ + unsigned fUsed : 1; // the cut is used + unsigned Handle : 31; // the cut handle +}; +typedef struct Lf_Bst_t_ Lf_Bst_t; +struct Lf_Bst_t_ +{ + int Delay[3]; // delay + float Flow[3]; // flow + Lf_Plc_t Cut[2]; // cut info +}; +typedef struct Lf_Mem_t_ Lf_Mem_t; +struct Lf_Mem_t_ +{ + int LogPage; // log size of memory page + int MaskPage; // page mask + int nCutWords; // cut size in words + int iCur; // writing position + Vec_Ptr_t vPages; // memory pages + Vec_Ptr_t * vFree; // free pages +}; +typedef struct Lf_Man_t_ Lf_Man_t; +struct Lf_Man_t_ +{ + // user data + Gia_Man_t * pGia; // manager + Jf_Par_t * pPars; // parameters + // cut data + int nCutWords; // cut size in words + int nSetWords; // set size in words + Lf_Bst_t * pObjBests; // best cuts + Vec_Ptr_t vMemSets; // memory for cutsets + Vec_Int_t vFreeSets; // free cutsets + Vec_Mem_t * vTtMem; // truth tables + Vec_Ptr_t vFreePages; // free memory pages + Lf_Mem_t vStoreOld; // previous cuts + Lf_Mem_t vStoreNew; // current cuts + // mapper data + Vec_Int_t vOffsets; // offsets + Vec_Int_t vRequired; // required times + Vec_Int_t vCutSets; // cutsets (pObj->Value stores cut refs) + Vec_Flt_t vFlowRefs; // flow refs + Vec_Int_t vMapRefs; // mapping refs + Vec_Flt_t vSwitches; // switching activity + Vec_Int_t vCiArrivals; // arrival times of the CIs + // statistics + abctime clkStart; // starting time + double CutCount[4]; // cut counts + double Switches; // switching activity + int nFrontMax; // frontier + int nCoDrivers; // CO drivers + int nInverters; // inverters + int nTimeFails; // timing fails + int Iter; // mapping iteration + int fUseEla; // use exact local area + int nCutMux; // non-trivial MUX cuts + int nCutEqual; // equal two cuts + int nCutCounts[LF_LEAF_MAX+1]; +}; + +static inline void Lf_CutCopy( Lf_Cut_t * p, Lf_Cut_t * q, int n ) { memcpy(p, q, sizeof(word) * n); } +static inline Lf_Cut_t * Lf_CutNext( Lf_Cut_t * p, int n ) { return (Lf_Cut_t *)((word *)p + n); } +static inline word * Lf_CutTruth( Lf_Man_t * p, Lf_Cut_t * pCut ) { return Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut->iFunc)); } + +static inline int Lf_ObjOff( Lf_Man_t * p, int i ) { return Vec_IntEntry(&p->vOffsets, i); } +static inline int Lf_ObjRequired( Lf_Man_t * p, int i ) { return Vec_IntEntry(&p->vRequired, i); } +static inline void Lf_ObjSetRequired( Lf_Man_t * p, int i, int t ) { Vec_IntDowndateEntry(&p->vRequired, i, t); } +static inline Lf_Bst_t * Lf_ObjReadBest( Lf_Man_t * p, int i ) { return p->pObjBests + Lf_ObjOff(p,i); } +static inline float Lf_ObjFlowRefs( Lf_Man_t * p, int i ) { return Vec_FltEntry(&p->vFlowRefs, Lf_ObjOff(p,i)); } +static inline int Lf_ObjMapRefNum( Lf_Man_t * p, int i ) { return Vec_IntEntry(&p->vMapRefs, Lf_ObjOff(p,i)); } +static inline int Lf_ObjMapRefInc( Lf_Man_t * p, int i ) { return (*Vec_IntEntryP(&p->vMapRefs, Lf_ObjOff(p,i)))++; } +static inline int Lf_ObjMapRefDec( Lf_Man_t * p, int i ) { return --(*Vec_IntEntryP(&p->vMapRefs, Lf_ObjOff(p,i))); } +static inline float Lf_ObjSwitches( Lf_Man_t * p, int i ) { return Vec_FltEntry(&p->vSwitches, i); } +static inline int Lf_BestDiffCuts( Lf_Bst_t * p ) { return p->Cut[0].Handle != p->Cut[1].Handle; } +static inline int Lf_BestIsMapped( Lf_Bst_t * p ) { return (int)(p->Cut[0].fUsed ^ p->Cut[1].fUsed); } +static inline int Lf_BestIndex( Lf_Bst_t * p ) { return p->Cut[1].fUsed; } +static inline int Lf_BestCutIndex( Lf_Bst_t * p ) { if (p->Cut[0].fUsed) return 0; if (p->Cut[1].fUsed) return 1; return 2; } + +#define Lf_CutSetForEachCut( nWords, pCutSet, pCut, i, nCuts ) for ( i = 0, pCut = pCutSet; i < nCuts; pCut = Lf_CutNext(pCut, nWords), i++ ) +#define Lf_CutForEachVar( pCut, Var, i ) for ( i = 0; i < (int)pCut->nLeaves && (Var = pCut->pLeaves[i]); i++ ) if ( Lf_ObjOff(p, Var) < 0 ) {} else + +extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Lf_ObjSetCiArrival( Lf_Man_t * p, int iCi, int Time ) +{ + Vec_IntWriteEntry( &p->vCiArrivals, iCi, Time ); +} +static inline int Lf_ObjCiArrival( Lf_Man_t * p, int iCi ) +{ + return Vec_IntEntry( &p->vCiArrivals, iCi ); +} +int Lf_ObjArrival_rec( Lf_Man_t * p, Gia_Obj_t * pDriver ) +{ + if ( Gia_ObjIsBuf(pDriver) ) + return Lf_ObjArrival_rec( p, Gia_ObjFanin0(pDriver) ); + if ( Gia_ObjIsAnd(pDriver) ) + return Lf_ObjReadBest(p, Gia_ObjId(p->pGia, pDriver))->Delay[0]; + if ( Gia_ObjIsCi(pDriver) ) + return Lf_ObjCiArrival(p, Gia_ObjCioId(pDriver)); + return 0; +} +static inline int Lf_ObjCoArrival( Lf_Man_t * p, int iCo ) +{ + Gia_Obj_t * pObj = Gia_ManCo(p->pGia, iCo); + Gia_Obj_t * pDriver = Gia_ObjFanin0(pObj); + return Lf_ObjArrival_rec( p, pDriver ); +// if ( Gia_ObjIsAnd(pDriver) ) +// return Lf_ObjReadBest(p, Gia_ObjId(p->pGia, pDriver))->Delay[0]; +// if ( Gia_ObjIsCi(pDriver) ) +// return Lf_ObjCiArrival(p, Gia_ObjCioId(pDriver)); +// return 0; +} +int Lf_ObjCoArrival2_rec( Lf_Man_t * p, Gia_Obj_t * pDriver ) +{ + if ( Gia_ObjIsBuf(pDriver) ) + return Lf_ObjCoArrival2_rec( p, Gia_ObjFanin0(pDriver) ); + if ( Gia_ObjIsAnd(pDriver) ) + { + Lf_Bst_t * pBest = Lf_ObjReadBest(p, Gia_ObjId(p->pGia, pDriver)); + int Index = Lf_BestCutIndex( pBest ); + assert( Index < 2 || Gia_ObjIsMux(p->pGia, pDriver) ); + return pBest->Delay[Index]; + } + if ( Gia_ObjIsCi(pDriver) ) + return Lf_ObjCiArrival(p, Gia_ObjCioId(pDriver)); + return 0; +} +static inline int Lf_ObjCoArrival2( Lf_Man_t * p, int iCo ) +{ + Gia_Obj_t * pObj = Gia_ManCo(p->pGia, iCo); + Gia_Obj_t * pDriver = Gia_ObjFanin0(pObj); + return Lf_ObjCoArrival2_rec( p, pDriver ); +// if ( Gia_ObjIsAnd(pDriver) ) +// { +// Lf_Bst_t * pBest = Lf_ObjReadBest(p, Gia_ObjId(p->pGia, pDriver)); +// int Index = Lf_BestCutIndex( pBest ); +// assert( Index < 2 || Gia_ObjIsMux(p->pGia, pDriver) ); +// return pBest->Delay[Index]; +// } +// if ( Gia_ObjIsCi(pDriver) ) +// return Lf_ObjCiArrival(p, Gia_ObjCioId(pDriver)); +// return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Lf_ManComputeCrossCut( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, nCutMax = 0, nCutCur = 0; + assert( p->pMuxes == NULL ); + Gia_ManForEachObj( p, pObj, i ) + pObj->Value = 0; + Gia_ManForEachAnd( p, pObj, i ) + { + if ( Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) ) + Gia_ObjFanin0(pObj)->Value++; + if ( Gia_ObjIsAnd(Gia_ObjFanin1(pObj)) ) + Gia_ObjFanin1(pObj)->Value++; + } + Gia_ManForEachAnd( p, pObj, i ) + { + if ( pObj->Value ) + nCutCur++; + if ( nCutMax < nCutCur ) + nCutMax = nCutCur; + if ( Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) && --Gia_ObjFanin0(pObj)->Value == 0 ) + nCutCur--; + if ( Gia_ObjIsAnd(Gia_ObjFanin1(pObj)) && --Gia_ObjFanin1(pObj)->Value == 0 ) + nCutCur--; + } + assert( nCutCur == 0 ); + if ( nCutCur ) + printf( "Cutset is not 0\n" ); + Gia_ManForEachObj( p, pObj, i ) + assert( pObj->Value == 0 ); + printf( "CutMax = %d\n", nCutMax ); + return nCutMax; +} + +/**Function************************************************************* + + Synopsis [Detect MUX truth tables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Lf_ManTtIsMux( word t ) +{ + static unsigned s_Muxes[24] = { + (~0xAAAAAAAA & ~0xCCCCCCCC) | ( 0xAAAAAAAA & ~0xF0F0F0F0), + (~0xAAAAAAAA & ~0xCCCCCCCC) | ( 0xAAAAAAAA & 0xF0F0F0F0), + (~0xAAAAAAAA & 0xCCCCCCCC) | ( 0xAAAAAAAA & ~0xF0F0F0F0), + (~0xAAAAAAAA & 0xCCCCCCCC) | ( 0xAAAAAAAA & 0xF0F0F0F0), + ( 0xAAAAAAAA & ~0xCCCCCCCC) | (~0xAAAAAAAA & ~0xF0F0F0F0), + ( 0xAAAAAAAA & ~0xCCCCCCCC) | (~0xAAAAAAAA & 0xF0F0F0F0), + ( 0xAAAAAAAA & 0xCCCCCCCC) | (~0xAAAAAAAA & ~0xF0F0F0F0), + ( 0xAAAAAAAA & 0xCCCCCCCC) | (~0xAAAAAAAA & 0xF0F0F0F0), + + (~0xCCCCCCCC & ~0xAAAAAAAA) | ( 0xCCCCCCCC & ~0xF0F0F0F0), + (~0xCCCCCCCC & ~0xAAAAAAAA) | ( 0xCCCCCCCC & 0xF0F0F0F0), + (~0xCCCCCCCC & 0xAAAAAAAA) | ( 0xCCCCCCCC & ~0xF0F0F0F0), + (~0xCCCCCCCC & 0xAAAAAAAA) | ( 0xCCCCCCCC & 0xF0F0F0F0), + ( 0xCCCCCCCC & ~0xAAAAAAAA) | (~0xCCCCCCCC & ~0xF0F0F0F0), + ( 0xCCCCCCCC & ~0xAAAAAAAA) | (~0xCCCCCCCC & 0xF0F0F0F0), + ( 0xCCCCCCCC & 0xAAAAAAAA) | (~0xCCCCCCCC & ~0xF0F0F0F0), + ( 0xCCCCCCCC & 0xAAAAAAAA) | (~0xCCCCCCCC & 0xF0F0F0F0), + + (~0xF0F0F0F0 & ~0xCCCCCCCC) | ( 0xF0F0F0F0 & ~0xAAAAAAAA), + (~0xF0F0F0F0 & ~0xCCCCCCCC) | ( 0xF0F0F0F0 & 0xAAAAAAAA), + (~0xF0F0F0F0 & 0xCCCCCCCC) | ( 0xF0F0F0F0 & ~0xAAAAAAAA), + (~0xF0F0F0F0 & 0xCCCCCCCC) | ( 0xF0F0F0F0 & 0xAAAAAAAA), + ( 0xF0F0F0F0 & ~0xCCCCCCCC) | (~0xF0F0F0F0 & ~0xAAAAAAAA), + ( 0xF0F0F0F0 & ~0xCCCCCCCC) | (~0xF0F0F0F0 & 0xAAAAAAAA), + ( 0xF0F0F0F0 & 0xCCCCCCCC) | (~0xF0F0F0F0 & ~0xAAAAAAAA), + ( 0xF0F0F0F0 & 0xCCCCCCCC) | (~0xF0F0F0F0 & 0xAAAAAAAA) + }; + int i; + for ( i = 0; i < 24; i++ ) + if ( ((unsigned)t) == s_Muxes[i] ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Count the number of unique drivers and invertors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Lf_ManAnalyzeCoDrivers( Gia_Man_t * p, int * pnDrivers, int * pnInverts ) +{ + Gia_Obj_t * pObj; + int i, Entry, nDrivers, nInverts; + Vec_Int_t * vMarks = Vec_IntStart( Gia_ManObjNum(p) ); + nDrivers = nInverts = 0; + Gia_ManForEachCo( p, pObj, i ) + *Vec_IntEntryP( vMarks, Gia_ObjFaninId0p(p, pObj) ) |= Gia_ObjFaninC0(pObj) ? 2 : 1; + Vec_IntForEachEntry( vMarks, Entry, i ) + nDrivers += (int)(Entry != 0), nInverts += (int)(Entry == 3); + Vec_IntFree( vMarks ); + *pnDrivers = nDrivers; + *pnInverts = nInverts; +} +void Lf_ManComputeSwitching( Gia_Man_t * p, Vec_Flt_t * vSwitches ) +{ +// abctime clk = Abc_Clock(); + Vec_Flt_t * vSwitching = (Vec_Flt_t *)Gia_ManComputeSwitchProbs( p, 48, 16, 0 ); + assert( Vec_FltCap(vSwitches) == 0 ); + *vSwitches = *vSwitching; + ABC_FREE( vSwitching ); +// Abc_PrintTime( 1, "Computing switching activity", Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Lf_CutCreateUnit( Lf_Cut_t * p, int i ) +{ + p->fLate = 0; + p->fMux7 = 0; + p->iFunc = 2; + p->nLeaves = 1; + p->pLeaves[0] = i; + p->Sign = ((word)1) << (i & 0x3F); + return 1; +} +static inline Lf_Cut_t * Lf_ManFetchSet( Lf_Man_t * p, int i ) +{ + int uMaskPage = (1 << LF_LOG_PAGE) - 1; + Gia_Obj_t * pObj = Gia_ManObj( p->pGia, i ); + int iOffSet = Vec_IntEntry( &p->vOffsets, i ); + int Entry = Vec_IntEntry( &p->vCutSets, iOffSet ); + assert( Gia_ObjIsAndNotBuf(pObj) ); + assert( pObj->Value > 0 ); + if ( Entry == -1 ) // first visit + { + if ( Vec_IntSize(&p->vFreeSets) == 0 ) // add new + { + Lf_Cut_t * pCut = (Lf_Cut_t *)ABC_CALLOC( word, p->nSetWords * (1 << LF_LOG_PAGE) ); + int uMaskShift = Vec_PtrSize(&p->vMemSets) << LF_LOG_PAGE; + Vec_PtrPush( &p->vMemSets, pCut ); + for ( Entry = uMaskPage; Entry >= 0; Entry-- ) + { + Vec_IntPush( &p->vFreeSets, uMaskShift | Entry ); + pCut[Entry].nLeaves = LF_NO_LEAF; + } + } + Entry = Vec_IntPop( &p->vFreeSets ); + Vec_IntWriteEntry( &p->vCutSets, iOffSet, Entry ); + p->nFrontMax = Abc_MaxInt( p->nFrontMax, Entry + 1 ); + } + else if ( --pObj->Value == 0 ) + { + Vec_IntPush( &p->vFreeSets, Entry ); + Vec_IntWriteEntry( &p->vCutSets, iOffSet, -1 ); + } + return (Lf_Cut_t *)((word *)Vec_PtrEntry(&p->vMemSets, Entry >> LF_LOG_PAGE) + p->nSetWords * (Entry & uMaskPage)); +} +static inline int Lf_ManPrepareSet( Lf_Man_t * p, int iObj, int Index, Lf_Cut_t ** ppCutSet ) +{ + static word CutTemp[3][LF_CUT_WORDS]; + if ( Vec_IntEntry(&p->vOffsets, iObj) == -1 ) + return Lf_CutCreateUnit( (*ppCutSet = (Lf_Cut_t *)CutTemp[Index]), iObj ); + { + Lf_Cut_t * pCut; + int i, nCutNum = p->pPars->nCutNum; + *ppCutSet = Lf_ManFetchSet(p, iObj); + Lf_CutSetForEachCut( p->nCutWords, *ppCutSet, pCut, i, nCutNum ) + if ( pCut->nLeaves == LF_NO_LEAF ) + return i; + return i; + } +} + +/**Function************************************************************* + + Synopsis [Cut manipulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline word Lf_CutGetSign( Lf_Cut_t * pCut ) +{ + word Sign = 0; int i; + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + Sign |= ((word)1) << (pCut->pLeaves[i] & 0x3F); + return Sign; +} +static inline int Lf_CutCountBits( word i ) +{ + i = i - ((i >> 1) & 0x5555555555555555); + i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333); + i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F); + return (i*(0x0101010101010101))>>56; +} +static inline int Lf_CutEqual( Lf_Cut_t * pCut0, Lf_Cut_t * pCut1 ) +{ + int i; + if ( pCut0->iFunc != pCut1->iFunc ) + return 0; + if ( pCut0->nLeaves != pCut1->nLeaves ) + return 0; + for ( i = 0; i < (int)pCut0->nLeaves; i++ ) + if ( pCut0->pLeaves[i] != pCut1->pLeaves[i] ) + return 0; + return 1; +} +static inline float Lf_CutSwitches( Lf_Man_t * p, Lf_Cut_t * pCut ) +{ + float Switches = 0; int i; + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + Switches += Lf_ObjSwitches(p, pCut->pLeaves[i]); +//printf( "%.2f ", Switches ); + return Switches; +} +static inline void Lf_CutPrint( Lf_Man_t * p, Lf_Cut_t * pCut ) +{ + int i, nDigits = Abc_Base10Log(Gia_ManObjNum(p->pGia)); + printf( "%d {", pCut->nLeaves ); + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + printf( " %*d", nDigits, pCut->pLeaves[i] ); + for ( ; i < (int)p->pPars->nLutSize; i++ ) + printf( " %*s", nDigits, " " ); + printf( " } Late = %d D = %4d A = %9.4f F = %6d\n", + pCut->fLate, pCut->Delay, pCut->Flow, pCut->iFunc ); +} +static inline float Lf_CutArea( Lf_Man_t * p, Lf_Cut_t * pCut ) +{ + if ( pCut->nLeaves < 2 || pCut->fMux7 ) + return 0; + if ( p->pPars->fPower ) + return 1.0 * pCut->nLeaves + Lf_CutSwitches( p, pCut ); + if ( p->pPars->fOptEdge ) + return (pCut->nLeaves + p->pPars->nAreaTuner) * (1 + (p->pPars->fCutGroup && (int)pCut->nLeaves > p->pPars->nLutSize/2)); + return 1 + (p->pPars->fCutGroup && (int)pCut->nLeaves > p->pPars->nLutSize/2); +} +static inline int Lf_CutIsMux( Lf_Man_t * p, Lf_Cut_t * pCut, Gia_Obj_t * pMux ) +{ + int i, Id; + if ( pCut->nLeaves != 3 ) + return 0; + assert( Gia_ObjIsMux(p->pGia, pMux) ); + if ( Gia_ObjIsCi(Gia_ObjFanin0(pMux)) || Gia_ObjIsCi(Gia_ObjFanin1(pMux)) ) + return 0; + Id = Gia_ObjFaninId0p( p->pGia, pMux ); + for ( i = 0; i < 3; i++ ) + if ( pCut->pLeaves[i] == Id ) + break; + if ( i == 3 ) + return 0; + Id = Gia_ObjFaninId1p( p->pGia, pMux ); + for ( i = 0; i < 3; i++ ) + if ( pCut->pLeaves[i] == Id ) + break; + if ( i == 3 ) + return 0; + Id = Gia_ObjFaninId2p( p->pGia, pMux ); + for ( i = 0; i < 3; i++ ) + if ( pCut->pLeaves[i] == Id ) + break; + if ( i == 3 ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Cut packing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Lf_MemAlloc( Lf_Mem_t * p, int LogPage, Vec_Ptr_t * vFree, int nCutWords ) +{ + memset( p, 0, sizeof(Lf_Mem_t) ); + p->LogPage = LogPage; + p->MaskPage = (1 << LogPage) - 1; + p->nCutWords = nCutWords; + p->vFree = vFree; +} +static inline int Lf_MemSaveCut( Lf_Mem_t * p, Lf_Cut_t * pCut, int iObj ) +{ + unsigned char * pPlace; + int i, iPlace, Prev = iObj, iCur = p->iCur; + assert( !pCut->fMux7 ); + if ( Vec_PtrSize(&p->vPages) == (p->iCur >> p->LogPage) ) + Vec_PtrPush( &p->vPages, Vec_PtrSize(p->vFree) ? Vec_PtrPop(p->vFree) : ABC_ALLOC(char,p->MaskPage+1) ); + assert( p->MaskPage - (p->iCur & p->MaskPage) >= 4 * (LF_LEAF_MAX + 2) ); + iPlace = iCur & p->MaskPage; + pPlace = (unsigned char *)Vec_PtrEntry(&p->vPages, p->iCur >> p->LogPage); + iPlace = Gia_AigerWriteUnsignedBuffer( pPlace, iPlace, pCut->nLeaves ); + for ( i = pCut->nLeaves - 1; i >= 0; i-- ) + iPlace = Gia_AigerWriteUnsignedBuffer( pPlace, iPlace, Prev - pCut->pLeaves[i] ), Prev = pCut->pLeaves[i]; + assert( pCut->nLeaves >= 2 || pCut->iFunc <= 3 ); + if ( pCut->iFunc >= 0 ) + iPlace = Gia_AigerWriteUnsignedBuffer( pPlace, iPlace, pCut->iFunc ); + if ( p->MaskPage - (iPlace & p->MaskPage) < 4 * (LF_LEAF_MAX + 2) ) + p->iCur = ((p->iCur >> p->LogPage) + 1) << p->LogPage; + else + p->iCur = (p->iCur & ~p->MaskPage) | iPlace; + return iCur; +} +static inline Lf_Cut_t * Lf_MemLoadCut( Lf_Mem_t * p, int iCur, int iObj, Lf_Cut_t * pCut, int fTruth, int fRecycle ) +{ + unsigned char * pPlace; + int i, Prev = iObj, Page = iCur >> p->LogPage; + assert( Page < Vec_PtrSize(&p->vPages) ); + pPlace = (unsigned char *)Vec_PtrEntry(&p->vPages, Page) + (iCur & p->MaskPage); + pCut->nLeaves = Gia_AigerReadUnsigned(&pPlace); + assert( pCut->nLeaves <= LF_LEAF_MAX ); + for ( i = pCut->nLeaves - 1; i >= 0; i-- ) + pCut->pLeaves[i] = Prev - Gia_AigerReadUnsigned(&pPlace), Prev = pCut->pLeaves[i]; + pCut->iFunc = fTruth ? Gia_AigerReadUnsigned(&pPlace) : -1; + assert( pCut->nLeaves >= 2 || pCut->iFunc <= 3 ); + if ( fRecycle && Page && Vec_PtrEntry(&p->vPages, Page-1) ) + { + Vec_PtrPush( p->vFree, Vec_PtrEntry(&p->vPages, Page-1) ); + Vec_PtrWriteEntry( &p->vPages, Page-1, NULL ); + } + pCut->Sign = fRecycle ? Lf_CutGetSign(pCut) : 0; + pCut->fMux7 = 0; + return pCut; +} +static inline void Lf_MemRecycle( Lf_Mem_t * p ) +{ + void * pPlace; int i; + Vec_PtrForEachEntry( void *, &p->vPages, pPlace, i ) + if ( pPlace ) + Vec_PtrPush( p->vFree, pPlace ); + Vec_PtrClear( &p->vPages ); + p->iCur = 0; +} +static inline Lf_Cut_t * Lf_MemLoadMuxCut( Lf_Man_t * p, int iObj, Lf_Cut_t * pCut ) +{ + Gia_Obj_t * pMux = Gia_ManObj( p->pGia, iObj ); + assert( Gia_ObjIsMux(p->pGia, pMux) ); + pCut->iFunc = p->pPars->fCutMin ? 4 : -1; + pCut->pLeaves[0] = Gia_ObjFaninId0( pMux, iObj ); + pCut->pLeaves[1] = Gia_ObjFaninId1( pMux, iObj ); + pCut->pLeaves[2] = Gia_ObjFaninId2( p->pGia, iObj ); + pCut->nLeaves = 3; + pCut->fMux7 = 1; + return pCut; +} +static inline Lf_Cut_t * Lf_ObjCutMux( Lf_Man_t * p, int i ) +{ + static word CutSet[LF_CUT_WORDS]; + return Lf_MemLoadMuxCut( p, i, (Lf_Cut_t *)CutSet ); +} +static inline Lf_Cut_t * Lf_ObjCutBest( Lf_Man_t * p, int i ) +{ + static word CutSet[LF_CUT_WORDS]; + Lf_Bst_t * pBest = Lf_ObjReadBest( p, i ); + Lf_Cut_t * pCut = (Lf_Cut_t *)CutSet; + int Index = Lf_BestCutIndex( pBest ); + pCut->Delay = pBest->Delay[Index]; + pCut->Flow = pBest->Flow[Index]; + if ( Index == 2 ) + return Lf_MemLoadMuxCut( p, i, pCut ); + return Lf_MemLoadCut( &p->vStoreOld, pBest->Cut[Index].Handle, i, pCut, p->pPars->fCutMin, 0 ); +} +static inline Lf_Cut_t * Lf_ObjCutBestNew( Lf_Man_t * p, int i, Lf_Cut_t * pCut ) +{ + Lf_Bst_t * pBest = Lf_ObjReadBest( p, i ); + int Index = Lf_BestCutIndex( pBest ); + pCut->Delay = pBest->Delay[Index]; + pCut->Flow = pBest->Flow[Index]; + if ( Index == 2 ) + return Lf_MemLoadMuxCut( p, i, pCut ); + return Lf_MemLoadCut( &p->vStoreNew, pBest->Cut[Index].Handle, i, pCut, 0, 0 ); +} + +/**Function************************************************************* + + Synopsis [Check correctness of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Lf_CutCheck( Lf_Cut_t * pBase, Lf_Cut_t * pCut ) // check if pCut is contained in pBase +{ + int nSizeB = pBase->nLeaves; + int nSizeC = pCut->nLeaves; + int i, * pB = pBase->pLeaves; + int k, * pC = pCut->pLeaves; + for ( i = 0; i < nSizeC; i++ ) + { + for ( k = 0; k < nSizeB; k++ ) + if ( pC[i] == pB[k] ) + break; + if ( k == nSizeB ) + return 0; + } + return 1; +} +static inline int Lf_SetCheckArray( Lf_Cut_t ** ppCuts, int nCuts ) +{ + Lf_Cut_t * pCut0, * pCut1; + int i, k, m, n, Value; + assert( nCuts > 0 ); + for ( i = 0; i < nCuts; i++ ) + { + pCut0 = ppCuts[i]; + assert( !pCut0->fMux7 ); + assert( pCut0->nLeaves < LF_LEAF_MAX ); + assert( pCut0->Sign == Lf_CutGetSign(pCut0) ); + // check duplicates + for ( m = 0; m < (int)pCut0->nLeaves; m++ ) + for ( n = m + 1; n < (int)pCut0->nLeaves; n++ ) + assert( pCut0->pLeaves[m] < pCut0->pLeaves[n] ); + // check pairs + for ( k = 0; k < nCuts; k++ ) + { + pCut1 = ppCuts[k]; + if ( pCut0 == pCut1 ) + continue; + // check containments + Value = Lf_CutCheck( pCut0, pCut1 ); + assert( Value == 0 ); + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Lf_CutMergeOrder( Lf_Cut_t * pCut0, Lf_Cut_t * pCut1, Lf_Cut_t * pCut, int nLutSize ) +{ + int nSize0 = pCut0->nLeaves; + int nSize1 = pCut1->nLeaves; + int i, * pC0 = pCut0->pLeaves; + int k, * pC1 = pCut1->pLeaves; + int c, * pC = pCut->pLeaves; + // the case of the largest cut sizes + if ( nSize0 == nLutSize && nSize1 == nLutSize ) + { + for ( i = 0; i < nSize0; i++ ) + { + if ( pC0[i] != pC1[i] ) return 0; + pC[i] = pC0[i]; + } + pCut->nLeaves = nLutSize; + pCut->iFunc = -1; + pCut->Sign = pCut0->Sign | pCut1->Sign; + return 1; + } + // compare two cuts with different numbers + i = k = c = 0; + if ( nSize0 == 0 ) goto FlushCut1; + if ( nSize1 == 0 ) goto FlushCut0; + while ( 1 ) + { + if ( c == nLutSize ) return 0; + if ( pC0[i] < pC1[k] ) + { + pC[c++] = pC0[i++]; + if ( i >= nSize0 ) goto FlushCut1; + } + else if ( pC0[i] > pC1[k] ) + { + pC[c++] = pC1[k++]; + if ( k >= nSize1 ) goto FlushCut0; + } + else + { + pC[c++] = pC0[i++]; k++; + if ( i >= nSize0 ) goto FlushCut1; + if ( k >= nSize1 ) goto FlushCut0; + } + } + +FlushCut0: + if ( c + nSize0 > nLutSize + i ) return 0; + while ( i < nSize0 ) + pC[c++] = pC0[i++]; + pCut->nLeaves = c; + pCut->iFunc = -1; + pCut->fMux7 = 0; + pCut->Sign = pCut0->Sign | pCut1->Sign; + return 1; + +FlushCut1: + if ( c + nSize1 > nLutSize + k ) return 0; + while ( k < nSize1 ) + pC[c++] = pC1[k++]; + pCut->nLeaves = c; + pCut->iFunc = -1; + pCut->fMux7 = 0; + pCut->Sign = pCut0->Sign | pCut1->Sign; + return 1; +} +static inline int Lf_CutMergeOrder2( Lf_Cut_t * pCut0, Lf_Cut_t * pCut1, Lf_Cut_t * pCut, int nLutSize ) +{ + int x0, i0 = 0, nSize0 = pCut0->nLeaves, * pC0 = pCut0->pLeaves; + int x1, i1 = 0, nSize1 = pCut1->nLeaves, * pC1 = pCut1->pLeaves; + int xMin, c = 0, * pC = pCut->pLeaves; + while ( 1 ) + { + x0 = (i0 == nSize0) ? ABC_INFINITY : pC0[i0]; + x1 = (i1 == nSize1) ? ABC_INFINITY : pC1[i1]; + xMin = Abc_MinInt(x0, x1); + if ( xMin == ABC_INFINITY ) break; + if ( c == nLutSize ) return 0; + pC[c++] = xMin; + if (x0 == xMin) i0++; + if (x1 == xMin) i1++; + } + pCut->nLeaves = c; + pCut->iFunc = -1; + pCut->fMux7 = 0; + pCut->Sign = pCut0->Sign | pCut1->Sign; + return 1; +} +static inline int Lf_CutMergeOrderMux( Lf_Cut_t * pCut0, Lf_Cut_t * pCut1, Lf_Cut_t * pCut2, Lf_Cut_t * pCut, int nLutSize ) +{ + int x0, i0 = 0, nSize0 = pCut0->nLeaves, * pC0 = pCut0->pLeaves; + int x1, i1 = 0, nSize1 = pCut1->nLeaves, * pC1 = pCut1->pLeaves; + int x2, i2 = 0, nSize2 = pCut2->nLeaves, * pC2 = pCut2->pLeaves; + int xMin, c = 0, * pC = pCut->pLeaves; + while ( 1 ) + { + x0 = (i0 == nSize0) ? ABC_INFINITY : pC0[i0]; + x1 = (i1 == nSize1) ? ABC_INFINITY : pC1[i1]; + x2 = (i2 == nSize2) ? ABC_INFINITY : pC2[i2]; + xMin = Abc_MinInt( Abc_MinInt(x0, x1), x2 ); + if ( xMin == ABC_INFINITY ) break; + if ( c == nLutSize ) return 0; + pC[c++] = xMin; + if (x0 == xMin) i0++; + if (x1 == xMin) i1++; + if (x2 == xMin) i2++; + } + pCut->nLeaves = c; + pCut->iFunc = -1; + pCut->fMux7 = 0; + pCut->Sign = pCut0->Sign | pCut1->Sign | pCut2->Sign; + return 1; +} + +static inline int Lf_SetCutIsContainedOrder( Lf_Cut_t * pBase, Lf_Cut_t * pCut ) // check if pCut is contained in pBase +{ + int i, nSizeB = pBase->nLeaves; + int k, nSizeC = pCut->nLeaves; + if ( nSizeB == nSizeC ) + { + for ( i = 0; i < nSizeB; i++ ) + if ( pBase->pLeaves[i] != pCut->pLeaves[i] ) + return 0; + return 1; + } + assert( nSizeB > nSizeC ); + if ( nSizeC == 0 ) + return 1; + for ( i = k = 0; i < nSizeB; i++ ) + { + if ( pBase->pLeaves[i] > pCut->pLeaves[k] ) + return 0; + if ( pBase->pLeaves[i] == pCut->pLeaves[k] ) + { + if ( ++k == nSizeC ) + return 1; + } + } + return 0; +} +static inline int Lf_SetLastCutIsContained( Lf_Cut_t ** pCuts, int nCuts ) +{ + int i; + for ( i = 0; i < nCuts; i++ ) + if ( pCuts[i]->nLeaves <= pCuts[nCuts]->nLeaves && (pCuts[i]->Sign & pCuts[nCuts]->Sign) == pCuts[i]->Sign && Lf_SetCutIsContainedOrder(pCuts[nCuts], pCuts[i]) ) + return 1; + return 0; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Lf_CutCompareDelay( Lf_Cut_t * pCut0, Lf_Cut_t * pCut1 ) +{ + if ( pCut0->Delay < pCut1->Delay ) return -1; + if ( pCut0->Delay > pCut1->Delay ) return 1; + if ( pCut0->nLeaves < pCut1->nLeaves ) return -1; + if ( pCut0->nLeaves > pCut1->nLeaves ) return 1; + if ( pCut0->Flow < pCut1->Flow - LF_EPSILON ) return -1; + if ( pCut0->Flow > pCut1->Flow + LF_EPSILON ) return 1; + return 0; +} +static inline int Lf_CutCompareArea( Lf_Cut_t * pCut0, Lf_Cut_t * pCut1 ) +{ + if ( pCut0->fLate < pCut1->fLate ) return -1; + if ( pCut0->fLate > pCut1->fLate ) return 1; + if ( pCut0->Flow < pCut1->Flow - LF_EPSILON ) return -1; + if ( pCut0->Flow > pCut1->Flow + LF_EPSILON ) return 1; + if ( pCut0->Delay < pCut1->Delay ) return -1; + if ( pCut0->Delay > pCut1->Delay ) return 1; + if ( pCut0->nLeaves < pCut1->nLeaves ) return -1; + if ( pCut0->nLeaves > pCut1->nLeaves ) return 1; + return 0; +} +static inline int Lf_SetLastCutContainsArea( Lf_Cut_t ** pCuts, int nCuts ) +{ + int i, k, fChanges = 0; + for ( i = 1; i < nCuts; i++ ) + if ( pCuts[nCuts]->nLeaves < pCuts[i]->nLeaves && (pCuts[nCuts]->Sign & pCuts[i]->Sign) == pCuts[nCuts]->Sign && Lf_SetCutIsContainedOrder(pCuts[i], pCuts[nCuts]) ) + pCuts[i]->nLeaves = LF_NO_LEAF, fChanges = 1; + if ( !fChanges ) + return nCuts; + for ( i = k = 1; i <= nCuts; i++ ) + { + if ( pCuts[i]->nLeaves == LF_NO_LEAF ) + continue; + if ( k < i ) + ABC_SWAP( Lf_Cut_t *, pCuts[k], pCuts[i] ); + k++; + } + return k - 1; +} +static inline void Lf_SetSortByArea( Lf_Cut_t ** pCuts, int nCuts ) +{ + int i; + for ( i = nCuts; i > 1; i-- ) + { + if ( Lf_CutCompareArea(pCuts[i - 1], pCuts[i]) < 0 )//!= 1 ) + return; + ABC_SWAP( Lf_Cut_t *, pCuts[i - 1], pCuts[i] ); + } +} +static inline int Lf_SetAddCut( Lf_Cut_t ** pCuts, int nCuts, int nCutNum ) +{ + if ( nCuts == 0 ) + return 1; + nCuts = Lf_SetLastCutContainsArea(pCuts, nCuts); + assert( nCuts >= 1 ); + if ( Lf_CutCompareDelay(pCuts[0], pCuts[nCuts]) == 1 ) // new cut is better for delay + { + ABC_SWAP( Lf_Cut_t *, pCuts[0], pCuts[nCuts] ); + // if old cut (now cut number nCuts) is contained - remove it + if ( pCuts[0]->nLeaves < pCuts[nCuts]->nLeaves && (pCuts[0]->Sign & pCuts[nCuts]->Sign) == pCuts[0]->Sign && Lf_SetCutIsContainedOrder(pCuts[nCuts], pCuts[0]) ) + return nCuts; + } + // sort area cuts by area + Lf_SetSortByArea( pCuts, nCuts ); + // add new cut if there is room + return Abc_MinInt( nCuts + 1, nCutNum - 1 ); +} +static inline void Lf_SetSortBySize( Lf_Cut_t ** pCutsR, int nCutsR ) +{ + int i, j, best_i; + for ( i = 1; i < nCutsR-1; i++ ) + { + best_i = i; + for ( j = i+1; j < nCutsR; j++ ) + if ( pCutsR[j]->nLeaves > pCutsR[best_i]->nLeaves ) + best_i = j; + ABC_SWAP( Lf_Cut_t *, pCutsR[i], pCutsR[best_i] ); + } +} + +/**Function************************************************************* + + Synopsis [Check if truth table has non-const-cof cofactoring variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Lf_ManFindCofVar( word * pTruth, int nWords, int nVars ) +{ + word uTruthCof[LF_TT_WORDS]; int iVar; + for ( iVar = 0; iVar < nVars; iVar++ ) + { + Abc_TtCofactor0p( uTruthCof, pTruth, nWords, iVar ); + if ( Abc_TtSupportSize(uTruthCof, nVars) < 2 ) + continue; + Abc_TtCofactor1p( uTruthCof, pTruth, nWords, iVar ); + if ( Abc_TtSupportSize(uTruthCof, nVars) < 2 ) + continue; + return iVar; + } + return -1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Lf_CutComputeTruth6( Lf_Man_t * p, Lf_Cut_t * pCut0, Lf_Cut_t * pCut1, int fCompl0, int fCompl1, Lf_Cut_t * pCutR, int fIsXor ) +{ +// extern int Mf_ManTruthCanonicize( word * t, int nVars ); + int nOldSupp = pCutR->nLeaves, truthId, fCompl; word t; + word t0 = *Lf_CutTruth(p, pCut0); + word t1 = *Lf_CutTruth(p, pCut1); + if ( Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ) t0 = ~t0; + if ( Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ) t1 = ~t1; + t0 = Abc_Tt6Expand( t0, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + t1 = Abc_Tt6Expand( t1, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + t = fIsXor ? t0 ^ t1 : t0 & t1; + if ( (fCompl = (int)(t & 1)) ) t = ~t; + pCutR->nLeaves = Abc_Tt6MinBase( &t, pCutR->pLeaves, pCutR->nLeaves ); + assert( (int)(t & 1) == 0 ); + truthId = Vec_MemHashInsert(p->vTtMem, &t); + pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); +// p->nCutMux += Lf_ManTtIsMux( t ); + assert( (int)pCutR->nLeaves <= nOldSupp ); +// Mf_ManTruthCanonicize( &t, pCutR->nLeaves ); + return (int)pCutR->nLeaves < nOldSupp; +} +static inline int Lf_CutComputeTruth( Lf_Man_t * p, Lf_Cut_t * pCut0, Lf_Cut_t * pCut1, int fCompl0, int fCompl1, Lf_Cut_t * pCutR, int fIsXor ) +{ + if ( p->pPars->nLutSize <= 6 ) + return Lf_CutComputeTruth6( p, pCut0, pCut1, fCompl0, fCompl1, pCutR, fIsXor ); + { + word uTruth[LF_TT_WORDS], uTruth0[LF_TT_WORDS], uTruth1[LF_TT_WORDS]; + int nOldSupp = pCutR->nLeaves, truthId; + int LutSize = p->pPars->nLutSize, fCompl; + int nWords = Abc_Truth6WordNum(LutSize); + word * pTruth0 = Lf_CutTruth(p, pCut0); + word * pTruth1 = Lf_CutTruth(p, pCut1); + Abc_TtCopy( uTruth0, pTruth0, nWords, Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ); + Abc_TtCopy( uTruth1, pTruth1, nWords, Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ); + Abc_TtExpand( uTruth0, LutSize, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + Abc_TtExpand( uTruth1, LutSize, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + if ( fIsXor ) + Abc_TtXor( uTruth, uTruth0, uTruth1, nWords, (fCompl = (int)((uTruth0[0] ^ uTruth1[0]) & 1)) ); + else + Abc_TtAnd( uTruth, uTruth0, uTruth1, nWords, (fCompl = (int)((uTruth0[0] & uTruth1[0]) & 1)) ); + pCutR->nLeaves = Abc_TtMinBase( uTruth, pCutR->pLeaves, pCutR->nLeaves, LutSize ); + assert( (uTruth[0] & 1) == 0 ); +//Kit_DsdPrintFromTruth( uTruth, pCutR->nLeaves ), printf("\n" ), printf("\n" ); + truthId = Vec_MemHashInsert(p->vTtMem, uTruth); + pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); + assert( (int)pCutR->nLeaves <= nOldSupp ); + return (int)pCutR->nLeaves < nOldSupp; + } +} +static inline int Lf_CutComputeTruthMux6( Lf_Man_t * p, Lf_Cut_t * pCut0, Lf_Cut_t * pCut1, Lf_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, Lf_Cut_t * pCutR ) +{ + int nOldSupp = pCutR->nLeaves, truthId, fCompl; word t; + word t0 = *Lf_CutTruth(p, pCut0); + word t1 = *Lf_CutTruth(p, pCut1); + word tC = *Lf_CutTruth(p, pCutC); + if ( Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ) t0 = ~t0; + if ( Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ) t1 = ~t1; + if ( Abc_LitIsCompl(pCutC->iFunc) ^ fComplC ) tC = ~tC; + t0 = Abc_Tt6Expand( t0, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + t1 = Abc_Tt6Expand( t1, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + tC = Abc_Tt6Expand( tC, pCutC->pLeaves, pCutC->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + t = (tC & t1) | (~tC & t0); + if ( (fCompl = (int)(t & 1)) ) t = ~t; + pCutR->nLeaves = Abc_Tt6MinBase( &t, pCutR->pLeaves, pCutR->nLeaves ); + assert( (int)(t & 1) == 0 ); + truthId = Vec_MemHashInsert(p->vTtMem, &t); + pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); + assert( (int)pCutR->nLeaves <= nOldSupp ); + return (int)pCutR->nLeaves < nOldSupp; +} +static inline int Lf_CutComputeTruthMux( Lf_Man_t * p, Lf_Cut_t * pCut0, Lf_Cut_t * pCut1, Lf_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, Lf_Cut_t * pCutR ) +{ + if ( p->pPars->nLutSize <= 6 ) + return Lf_CutComputeTruthMux6( p, pCut0, pCut1, pCutC, fCompl0, fCompl1, fComplC, pCutR ); + { + word uTruth[LF_TT_WORDS], uTruth0[LF_TT_WORDS], uTruth1[LF_TT_WORDS], uTruthC[LF_TT_WORDS]; + int nOldSupp = pCutR->nLeaves, truthId; + int LutSize = p->pPars->nLutSize, fCompl; + int nWords = Abc_Truth6WordNum(LutSize); + word * pTruth0 = Lf_CutTruth(p, pCut0); + word * pTruth1 = Lf_CutTruth(p, pCut1); + word * pTruthC = Lf_CutTruth(p, pCutC); + Abc_TtCopy( uTruth0, pTruth0, nWords, Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ); + Abc_TtCopy( uTruth1, pTruth1, nWords, Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ); + Abc_TtCopy( uTruthC, pTruthC, nWords, Abc_LitIsCompl(pCutC->iFunc) ^ fComplC ); + Abc_TtExpand( uTruth0, LutSize, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + Abc_TtExpand( uTruth1, LutSize, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + Abc_TtExpand( uTruthC, LutSize, pCutC->pLeaves, pCutC->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + Abc_TtMux( uTruth, uTruthC, uTruth1, uTruth0, nWords ); + fCompl = (int)(uTruth[0] & 1); + if ( fCompl ) Abc_TtNot( uTruth, nWords ); + pCutR->nLeaves = Abc_TtMinBase( uTruth, pCutR->pLeaves, pCutR->nLeaves, LutSize ); + assert( (uTruth[0] & 1) == 0 ); + truthId = Vec_MemHashInsert(p->vTtMem, uTruth); + pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); + assert( (int)pCutR->nLeaves <= nOldSupp ); + return (int)pCutR->nLeaves < nOldSupp; + } +} + +/**Function************************************************************* + + Synopsis [Exact local area.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Lf_CutRef_rec( Lf_Man_t * p, Lf_Cut_t * pCut ) +{ + word CutTemp[LF_CUT_WORDS] = {0}; + float Count = Lf_CutArea(p, pCut); + int i, Var; + Lf_CutForEachVar( pCut, Var, i ) + if ( !Lf_ObjMapRefInc(p, Var) ) + Count += Lf_CutRef_rec( p, Lf_ObjCutBestNew(p, Var, (Lf_Cut_t *)CutTemp) ); + return Count; +} +float Lf_CutDeref_rec( Lf_Man_t * p, Lf_Cut_t * pCut ) +{ + word CutTemp[LF_CUT_WORDS] = {0}; + float Count = Lf_CutArea(p, pCut); + int i, Var; + Lf_CutForEachVar( pCut, Var, i ) + if ( !Lf_ObjMapRefDec(p, Var) ) + Count += Lf_CutDeref_rec( p, Lf_ObjCutBestNew(p, Var, (Lf_Cut_t *)CutTemp) ); + return Count; +} +static inline float Lf_CutAreaDerefed( Lf_Man_t * p, Lf_Cut_t * pCut ) +{ + float Ela1 = Lf_CutRef_rec( p, pCut ); + Lf_CutDeref_rec( p, pCut ); +// float Ela2 = Lf_CutDeref_rec( p, pCut ); +// assert( Ela1 == Ela2 ); + return Ela1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Lf_CutRequired( Lf_Man_t * p, Lf_Cut_t * pCut ) +{ + int i, Arr, Req, Arrival = 0, Required = 0; + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + { + if ( Lf_ObjOff(p, pCut->pLeaves[i]) < 0 ) +// Arr = Lf_ObjCiArrival( p, Gia_ObjCioId(Gia_ManObj(p->pGia, pCut->pLeaves[i])) ); + Arr = Lf_ObjArrival_rec( p, Gia_ManObj(p->pGia, pCut->pLeaves[i]) ); + else + Arr = Lf_ObjReadBest(p, pCut->pLeaves[i])->Delay[0]; + Arrival = Abc_MaxInt( Arrival, Arr ); + Req = Lf_ObjRequired(p, pCut->pLeaves[i]); + if ( Req < ABC_INFINITY ) + Required = Abc_MaxInt( Required, Req ); + } + return Abc_MaxInt( Required + 2, Arrival + 1 ); +} +static inline void Lf_CutParams( Lf_Man_t * p, Lf_Cut_t * pCut, int Required, float FlowRefs, Gia_Obj_t * pMux ) +{ + Lf_Bst_t * pBest; + int i, Index, Delay; + assert( !pCut->fMux7 || Gia_ObjIsMux(p->pGia, pMux) ); + pCut->fLate = 0; + pCut->Delay = 0; + pCut->Flow = 0; + assert( pCut->nLeaves < LF_NO_LEAF ); + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + { + if ( Lf_ObjOff(p, pCut->pLeaves[i]) < 0 ) +// Delay = Lf_ObjCiArrival( p, Gia_ObjCioId(Gia_ManObj(p->pGia, pCut->pLeaves[i])) ); + Delay = Lf_ObjArrival_rec( p, Gia_ManObj(p->pGia, pCut->pLeaves[i]) ); + else + { + pBest = Lf_ObjReadBest(p, pCut->pLeaves[i]); + assert( pBest->Delay[0] <= pBest->Delay[1] ); + assert( pBest->Flow[0] >= pBest->Flow[1] ); + if ( p->fUseEla ) + Index = Lf_BestIndex(pBest); + else + { + Index = (int)(pBest->Delay[1] + 1 <= Required && Required != ABC_INFINITY); + //pCut->Flow += pBest->Flow[Index]; + if ( pCut->Flow >= (float)1e32 || pBest->Flow[Index] >= (float)1e32 ) + pCut->Flow = (float)1e32; + else + { + pCut->Flow += pBest->Flow[Index]; + if ( pCut->Flow > (float)1e32 ) + pCut->Flow = (float)1e32; + } + } + Delay = pBest->Delay[Index]; + } +// if ( pCut->fMux7 && pCut->pLeaves[i] == Gia_ObjFaninId2p(p->pGia, pMux) ) +// Delay += 1; + pCut->Delay = Abc_MaxInt( pCut->Delay, Delay ); + } + pCut->Delay += (int)(pCut->nLeaves > 1);// && !pCut->fMux7; + if ( pCut->Delay > Required ) + pCut->fLate = 1; + if ( p->fUseEla ) + pCut->Flow = Lf_CutAreaDerefed(p, pCut) / FlowRefs; + else + { + pCut->Flow = (pCut->Flow + Lf_CutArea(p, pCut)) / FlowRefs; + if ( pCut->Flow > (float)1e32 ) + pCut->Flow = (float)1e32; + } +} + +void Lf_ObjMergeOrder( Lf_Man_t * p, int iObj ) +{ + word CutSet[LF_CUT_MAX][LF_CUT_WORDS] = {{0}}; + Lf_Cut_t * pCutSet0, * pCutSet1, * pCutSet2, * pCut0, * pCut1, * pCut2; + Lf_Cut_t * pCutSet = (Lf_Cut_t *)CutSet, * pCutsR[LF_CUT_MAX]; + Gia_Obj_t * pObj = Gia_ManObj(p->pGia, iObj); + Lf_Bst_t * pBest = Lf_ObjReadBest(p, iObj); + float FlowRefs = Lf_ObjFlowRefs(p, iObj); + int Required = Lf_ObjRequired(p, iObj); + int nLutSize = p->pPars->fCutGroup ? p->pPars->nLutSize/2 : p->pPars->nLutSize; + int nCutNum = p->pPars->nCutNum; + int nCutWords = p->nCutWords; + int fComp0 = Gia_ObjFaninC0(pObj); + int fComp1 = Gia_ObjFaninC1(pObj); + int nCuts0 = Lf_ManPrepareSet( p, Gia_ObjFaninId0(pObj, iObj), 0, &pCutSet0 ); + int nCuts1 = Lf_ManPrepareSet( p, Gia_ObjFaninId1(pObj, iObj), 1, &pCutSet1 ); + int iSibl = Gia_ObjSibl(p->pGia, iObj); + int i, k, n, iCutUsed, nCutsR = 0; + float Value1 = -1, Value2 = -1; + assert( !Gia_ObjIsBuf(pObj) ); + Lf_CutSetForEachCut( nCutWords, pCutSet, pCut0, i, nCutNum ) + pCutsR[i] = pCut0; + if ( p->Iter ) + { + assert( nCutsR == 0 ); + // load cuts + Lf_MemLoadCut( &p->vStoreOld, pBest->Cut[0].Handle, iObj, pCutsR[0], p->pPars->fCutMin, 1 ); + if ( Lf_BestDiffCuts(pBest) ) + Lf_MemLoadCut( &p->vStoreOld, pBest->Cut[1].Handle, iObj, pCutsR[1], p->pPars->fCutMin, 1 ); + // deref the cut + if ( p->fUseEla && Lf_ObjMapRefNum(p, iObj) > 0 ) + Value1 = Lf_CutDeref_rec( p, pCutsR[Lf_BestIndex(pBest)] ); + // update required times + if ( Required == ABC_INFINITY )//&& !p->fUseEla ) + Required = Lf_CutRequired( p, pCutsR[0] ); + // compute parameters + Lf_CutParams( p, pCutsR[nCutsR++], Required, FlowRefs, pObj ); + if ( Lf_BestDiffCuts(pBest) ) + { + assert( nCutsR == 1 ); + Lf_CutParams( p, pCutsR[nCutsR], Required, FlowRefs, pObj ); + nCutsR = Lf_SetAddCut( pCutsR, nCutsR, nCutNum ); + } + if ( pCutsR[0]->fLate ) + p->nTimeFails++; + } + if ( iSibl ) + { + Gia_Obj_t * pObjE = Gia_ObjSiblObj(p->pGia, iObj); + int fCompE = Gia_ObjPhase(pObj) ^ Gia_ObjPhase(pObjE); + int nCutsE = Lf_ManPrepareSet( p, iSibl, 2, &pCutSet2 ); + Lf_CutSetForEachCut( nCutWords, pCutSet2, pCut2, n, nCutsE ) + { + if ( pCut2->pLeaves[0] == iSibl ) + continue; + Lf_CutCopy( pCutsR[nCutsR], pCut2, nCutWords ); + if ( pCutsR[nCutsR]->iFunc >= 0 ) + pCutsR[nCutsR]->iFunc = Abc_LitNotCond( pCutsR[nCutsR]->iFunc, fCompE ); + Lf_CutParams( p, pCutsR[nCutsR], Required, FlowRefs, pObj ); + nCutsR = Lf_SetAddCut( pCutsR, nCutsR, nCutNum ); + } + } + if ( Gia_ObjIsMuxId(p->pGia, iObj) ) + { + Lf_Cut_t * pCutSave = NULL; + int fComp2 = Gia_ObjFaninC2(p->pGia, pObj); + int nCuts2 = Lf_ManPrepareSet( p, Gia_ObjFaninId2(p->pGia, iObj), 2, &pCutSet2 ); + p->CutCount[0] += nCuts0 * nCuts1 * nCuts2; + Lf_CutSetForEachCut( nCutWords, pCutSet0, pCut0, i, nCuts0 ) if ( (int)pCut0->nLeaves <= nLutSize ) + Lf_CutSetForEachCut( nCutWords, pCutSet1, pCut1, k, nCuts1 ) if ( (int)pCut1->nLeaves <= nLutSize ) + Lf_CutSetForEachCut( nCutWords, pCutSet2, pCut2, n, nCuts2 ) if ( (int)pCut2->nLeaves <= nLutSize ) + { + pCutSave = pCut2; + if ( Lf_CutCountBits(pCut0->Sign | pCut1->Sign | pCut2->Sign) > nLutSize ) + continue; + p->CutCount[1]++; + if ( !Lf_CutMergeOrderMux(pCut0, pCut1, pCut2, pCutsR[nCutsR], nLutSize) ) + continue; + if ( Lf_SetLastCutIsContained(pCutsR, nCutsR) ) + continue; + p->CutCount[2]++; + if ( p->pPars->fCutMin && Lf_CutComputeTruthMux(p, pCut0, pCut1, pCut2, fComp0, fComp1, fComp2, pCutsR[nCutsR]) ) + pCutsR[nCutsR]->Sign = Lf_CutGetSign(pCutsR[nCutsR]); + if ( p->pPars->nLutSizeMux && p->pPars->nLutSizeMux == (int)pCutsR[nCutsR]->nLeaves && + Lf_ManFindCofVar(Lf_CutTruth(p,pCutsR[nCutsR]), Abc_Truth6WordNum(nLutSize), pCutsR[nCutsR]->nLeaves) == -1 ) + continue; + Lf_CutParams( p, pCutsR[nCutsR], Required, FlowRefs, pObj ); + nCutsR = Lf_SetAddCut( pCutsR, nCutsR, nCutNum ); + } + if ( p->pPars->fCutGroup ) + { + assert( pCutSave->nLeaves == 1 ); + assert( pCutSave->pLeaves[0] == Gia_ObjFaninId2(p->pGia, iObj) ); + Lf_CutSetForEachCut( nCutWords, pCutSet0, pCut0, i, nCuts0 ) if ( (int)pCut0->nLeaves <= nLutSize ) + Lf_CutSetForEachCut( nCutWords, pCutSet1, pCut1, k, nCuts1 ) if ( (int)pCut1->nLeaves <= nLutSize ) + { + assert( (int)pCut0->nLeaves + (int)pCut1->nLeaves + 1 <= p->pPars->nLutSize ); + // if ( Lf_CutCountBits(pCut0->Sign | pCut1->Sign | pCutSave->Sign) > p->pPars->nLutSize ) + // continue; + p->CutCount[1]++; + if ( !Lf_CutMergeOrderMux(pCut0, pCut1, pCutSave, pCutsR[nCutsR], p->pPars->nLutSize) ) + continue; + if ( Lf_SetLastCutIsContained(pCutsR, nCutsR) ) + continue; + p->CutCount[2]++; + if ( p->pPars->fCutMin && Lf_CutComputeTruthMux(p, pCut0, pCut1, pCutSave, fComp0, fComp1, fComp2, pCutsR[nCutsR]) ) + pCutsR[nCutsR]->Sign = Lf_CutGetSign(pCutsR[nCutsR]); + // if ( p->pPars->nLutSizeMux && p->pPars->nLutSizeMux == (int)pCutsR[nCutsR]->nLeaves && + // Lf_ManFindCofVar(Lf_CutTruth(p,pCutsR[nCutsR]), Abc_Truth6WordNum(nLutSize), pCutsR[nCutsR]->nLeaves) == -1 ) + // continue; + Lf_CutParams( p, pCutsR[nCutsR], Required, FlowRefs, pObj ); + nCutsR = Lf_SetAddCut( pCutsR, nCutsR, nCutNum ); + } + } + } + else + { + int fIsXor = Gia_ObjIsXor(pObj); + p->CutCount[0] += nCuts0 * nCuts1; + Lf_CutSetForEachCut( nCutWords, pCutSet0, pCut0, i, nCuts0 ) if ( (int)pCut0->nLeaves <= nLutSize ) + Lf_CutSetForEachCut( nCutWords, pCutSet1, pCut1, k, nCuts1 ) if ( (int)pCut1->nLeaves <= nLutSize ) + { + if ( (int)(pCut0->nLeaves + pCut1->nLeaves) > nLutSize && Lf_CutCountBits(pCut0->Sign | pCut1->Sign) > nLutSize ) + continue; + p->CutCount[1]++; + if ( !Lf_CutMergeOrder(pCut0, pCut1, pCutsR[nCutsR], nLutSize) ) + continue; + if ( Lf_SetLastCutIsContained(pCutsR, nCutsR) ) + continue; + p->CutCount[2]++; + if ( p->pPars->fCutMin && Lf_CutComputeTruth(p, pCut0, pCut1, fComp0, fComp1, pCutsR[nCutsR], fIsXor) ) + pCutsR[nCutsR]->Sign = Lf_CutGetSign(pCutsR[nCutsR]); + if ( p->pPars->nLutSizeMux && p->pPars->nLutSizeMux == (int)pCutsR[nCutsR]->nLeaves && + Lf_ManFindCofVar(Lf_CutTruth(p,pCutsR[nCutsR]), Abc_Truth6WordNum(nLutSize), pCutsR[nCutsR]->nLeaves) == -1 ) + continue; + Lf_CutParams( p, pCutsR[nCutsR], Required, FlowRefs, pObj ); + nCutsR = Lf_SetAddCut( pCutsR, nCutsR, nCutNum ); + } + } + // debug printout + if ( 0 ) + { + printf( "*** Obj = %d FlowRefs = %.2f MapRefs = %2d Required = %2d\n", iObj, FlowRefs, Lf_ObjMapRefNum(p, iObj), Required ); + for ( i = 0; i < nCutsR; i++ ) + Lf_CutPrint( p, pCutsR[i] ); + printf( "\n" ); + } + // verify + assert( nCutsR > 0 && nCutsR < nCutNum ); +// assert( Lf_SetCheckArray(pCutsR, nCutsR) ); + // delay cut + assert( nCutsR == 1 || pCutsR[0]->Delay <= pCutsR[1]->Delay ); + pBest->Cut[0].fUsed = pBest->Cut[1].fUsed = 0; + pBest->Cut[0].Handle = pBest->Cut[1].Handle = Lf_MemSaveCut(&p->vStoreNew, pCutsR[0], iObj); + pBest->Delay[0] = pBest->Delay[1] = pCutsR[0]->Delay; + pBest->Flow[0] = pBest->Flow[1] = pCutsR[0]->Flow; + p->nCutCounts[pCutsR[0]->nLeaves]++; + p->CutCount[3] += nCutsR; + p->nCutEqual++; + // area cut + iCutUsed = 0; + if ( nCutsR > 1 && pCutsR[0]->Flow > pCutsR[1]->Flow + LF_EPSILON )//&& !pCutsR[1]->fLate ) // can remove !fLate + { + pBest->Cut[1].Handle = Lf_MemSaveCut(&p->vStoreNew, pCutsR[1], iObj); + pBest->Delay[1] = pCutsR[1]->Delay; + pBest->Flow[1] = pCutsR[1]->Flow; + p->nCutCounts[pCutsR[1]->nLeaves]++; + p->nCutEqual--; + if ( !pCutsR[1]->fLate ) + iCutUsed = 1; + } + // mux cut + if ( p->pPars->fUseMux7 && Gia_ObjIsMuxId(p->pGia, iObj) ) + { + pCut2 = Lf_ObjCutMux( p, iObj ); + Lf_CutParams( p, pCut2, Required, FlowRefs, pObj ); + pBest->Delay[2] = pCut2->Delay; + pBest->Flow[2] = pCut2->Flow; + // update area value of the best area cut +// if ( !pCut2->fLate ) +// pBest->Flow[1] = Abc_MinFloat( pBest->Flow[1], pBest->Flow[2] ); + } + // reference resulting cut + if ( p->fUseEla ) + { + pBest->Cut[iCutUsed].fUsed = 1; + if ( Lf_ObjMapRefNum(p, iObj) > 0 ) + Value2 = Lf_CutRef_rec( p, pCutsR[iCutUsed] ); +// if ( Value1 < Value2 ) +// printf( "ELA degradated cost at node %d from %d to %d.\n", iObj, Value1, Value2 ), fflush(stdout); +// assert( Value1 >= Value2 ); +// if ( Value1 != -1 ) +// printf( "%.2f -> %.2f ", Value1, Value2 ); + } + if ( pObj->Value == 0 ) + return; + // store the cutset + pCutSet = Lf_ManFetchSet(p, iObj); + Lf_CutSetForEachCut( nCutWords, pCutSet, pCut0, i, nCutNum ) + { + assert( !pCut0->fMux7 ); + if ( i < nCutsR ) + Lf_CutCopy( pCut0, pCutsR[i], nCutWords ); + else if ( i == nCutsR && pCutsR[0]->nLeaves > 1 && (nCutsR == 1 || pCutsR[1]->nLeaves > 1) ) + Lf_CutCreateUnit( pCut0, iObj ); + else + pCut0->nLeaves = LF_NO_LEAF; + } +} + +/**Function************************************************************* + + Synopsis [Computing delay/area.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Lf_ManSetFlowRefInc( Gia_Man_t * p, Vec_Flt_t * vRefs, Vec_Int_t * vOffsets, int i ) +{ + if ( Gia_ObjIsAndNotBuf(Gia_ManObj(p, i)) ) + Vec_FltAddToEntry( vRefs, Vec_IntEntry(vOffsets, i), 1 ); +} +void Lf_ManSetFlowRefs( Gia_Man_t * p, Vec_Flt_t * vRefs, Vec_Int_t * vOffsets ) +{ + int fDiscount = 1; + Gia_Obj_t * pObj, * pCtrl, * pData0, * pData1; + int i, Id; + Vec_FltFill( vRefs, Gia_ManAndNotBufNum(p), 0 ); + Gia_ManForEachAnd( p, pObj, i ) + { + if ( Gia_ObjIsAndNotBuf(Gia_ObjFanin0(pObj)) ) + Vec_FltAddToEntry( vRefs, Vec_IntEntry(vOffsets, Gia_ObjFaninId0(pObj, i)), 1 ); + if ( Gia_ObjIsBuf(pObj) ) + continue; + if ( Gia_ObjIsAndNotBuf(Gia_ObjFanin1(pObj)) ) + Vec_FltAddToEntry( vRefs, Vec_IntEntry(vOffsets, Gia_ObjFaninId1(pObj, i)), 1 ); + if ( p->pMuxes ) + { + if ( Gia_ObjIsMuxId(p, i) && Gia_ObjIsAndNotBuf(Gia_ObjFanin2(p, pObj)) ) + Vec_FltAddToEntry( vRefs, Vec_IntEntry(vOffsets, Gia_ObjFaninId2(p, i)), 1 ); + } + else if ( fDiscount && Gia_ObjIsMuxType(pObj) ) // discount XOR/MUX + { + pCtrl = Gia_Regular(Gia_ObjRecognizeMux(pObj, &pData1, &pData0)); + pData0 = Gia_Regular(pData0); + pData1 = Gia_Regular(pData1); + if ( Gia_ObjIsAndNotBuf(pCtrl) ) + Vec_FltAddToEntry( vRefs, Vec_IntEntry(vOffsets, Gia_ObjId(p, pCtrl)), -1 ); + if ( pData0 == pData1 && Gia_ObjIsAndNotBuf(pData0) ) + Vec_FltAddToEntry( vRefs, Vec_IntEntry(vOffsets, Gia_ObjId(p, pData0)), -1 ); + } + } + Gia_ManForEachCoDriverId( p, Id, i ) + if ( Gia_ObjIsAndNotBuf(Gia_ManObj(p, Id)) ) + Vec_FltAddToEntry( vRefs, Vec_IntEntry(vOffsets, Id), 1 ); + for ( i = 0; i < Vec_FltSize(vRefs); i++ ) + Vec_FltUpdateEntry( vRefs, i, 1 ); +} +void Lf_ManSetCutRefs( Lf_Man_t * p ) +{ + Gia_Obj_t * pObj; int i; + if ( Vec_PtrSize(&p->vMemSets) * (1 << LF_LOG_PAGE) != Vec_IntSize(&p->vFreeSets) ) + printf( "The number of used cutsets = %d.\n", Vec_PtrSize(&p->vMemSets) * (1 << LF_LOG_PAGE) - Vec_IntSize(&p->vFreeSets) ); + Gia_ManForEachAnd( p->pGia, pObj, i ) + { + assert( pObj->Value == 0 ); + if ( Gia_ObjIsBuf(pObj) ) + continue; + if ( Gia_ObjIsAndNotBuf(Gia_ObjFanin0(pObj)) ) + Gia_ObjFanin0(pObj)->Value++; + if ( Gia_ObjIsAndNotBuf(Gia_ObjFanin1(pObj)) ) + Gia_ObjFanin1(pObj)->Value++; + if ( Gia_ObjIsMuxId(p->pGia, i) && Gia_ObjIsAndNotBuf(Gia_ObjFanin2(p->pGia, pObj)) ) + Gia_ObjFanin2(p->pGia, pObj)->Value++; + if ( Gia_ObjSibl(p->pGia, i) && Gia_ObjIsAndNotBuf(Gia_ObjSiblObj(p->pGia, i)) ) + Gia_ObjSiblObj(p->pGia, i)->Value++; + } +} + +static inline int Lf_ManSetMuxCut( Lf_Man_t * p, Lf_Bst_t * pBest, int iObj, int Required ) +{ + Gia_Obj_t * pMux; + if ( !Gia_ObjIsMuxId(p->pGia, iObj) ) + return 0; + if ( pBest->Delay[2] > Required ) + return 0; + if ( pBest->Flow[2] > 1.1 * pBest->Flow[1] ) + return 0; + pMux = Gia_ManObj(p->pGia, iObj); + if ( pMux->fMark0 || Gia_ObjFanin0(pMux)->fMark0 || Gia_ObjFanin1(pMux)->fMark0 ) + return 0; + Gia_ObjFanin0(pMux)->fMark0 = 1; + Gia_ObjFanin1(pMux)->fMark0 = 1; + return 1; +} +void Lf_ManSetMapRefsOne( Lf_Man_t * p, int iObj ) +{ + Lf_Cut_t * pCut; + Lf_Bst_t * pBest = Lf_ObjReadBest( p, iObj ); + int k, Index, Required = Lf_ObjRequired( p, iObj ); + assert( Lf_ObjMapRefNum(p, iObj) > 0 ); + assert( !pBest->Cut[0].fUsed && !pBest->Cut[1].fUsed ); + if ( !p->pPars->fUseMux7 || !Lf_ManSetMuxCut(p, pBest, iObj, Required) ) + { + Index = (int)(Lf_BestDiffCuts(pBest) && pBest->Delay[1] <= Required); + pBest->Cut[Index].fUsed = 1; + } + pCut = Lf_ObjCutBest( p, iObj ); + assert( !pCut->fMux7 || pCut->nLeaves == 3 ); +// assert( pCut->Delay <= Required ); + for ( k = 0; k < (int)pCut->nLeaves; k++ ) + { +// if ( pCut->fMux7 && pCut->pLeaves[k] != Gia_ObjFaninId2(p->pGia, iObj) ) +// Lf_ObjSetRequired( p, pCut->pLeaves[k], Required ); +// else + Lf_ObjSetRequired( p, pCut->pLeaves[k], Required - 1 ); + if ( Gia_ObjIsAndNotBuf(Gia_ManObj(p->pGia, pCut->pLeaves[k])) ) + Lf_ObjMapRefInc( p, pCut->pLeaves[k] ); + } + if ( pCut->fMux7 ) + { + p->pPars->Mux7++; + p->pPars->Edge++; + return; + } + if ( Vec_FltSize(&p->vSwitches) ) + p->Switches += Lf_CutSwitches(p, pCut); + p->pPars->Edge += pCut->nLeaves; + p->pPars->Area++; +} +int Lf_ManSetMapRefs( Lf_Man_t * p ) +{ + float Coef = 1.0 / (1.0 + (p->Iter + 1) * (p->Iter + 1)); + float * pFlowRefs; + int * pMapRefs, i; + Gia_Obj_t * pObj; + // compute delay + int Delay = 0; + for ( i = 0; i < Gia_ManCoNum(p->pGia); i++ ) + Delay = Abc_MaxInt( Delay, Lf_ObjCoArrival(p, i) ); + // check delay target + if ( p->pPars->DelayTarget == -1 && p->pPars->nRelaxRatio ) + p->pPars->DelayTarget = (int)((float)Delay * (100.0 + p->pPars->nRelaxRatio) / 100.0); + if ( p->pPars->DelayTarget != -1 ) + { + if ( Delay < p->pPars->DelayTarget + 0.01 ) + Delay = p->pPars->DelayTarget; + else if ( p->pPars->nRelaxRatio == 0 ) + Abc_Print( 0, "Relaxing user-specified delay target from %d to %d.\n", p->pPars->DelayTarget, Delay ); + } + p->pPars->Delay = Delay; + // compute area/edges/required + p->pPars->Mux7 = p->pPars->Area = p->pPars->Edge = p->Switches = 0; + Vec_IntFill( &p->vMapRefs, Gia_ManAndNotBufNum(p->pGia), 0 ); + Vec_IntFill( &p->vRequired, Gia_ManObjNum(p->pGia), ABC_INFINITY ); + if ( p->pPars->fUseMux7 ) + { + Gia_ManCleanMark0(p->pGia); + Gia_ManForEachCi( p->pGia, pObj, i ) + pObj->fMark0 = 1; + } + if ( p->pGia->pManTime != NULL ) + { + assert( !Gia_ManBufNum(p->pGia) ); + Tim_ManIncrementTravId( (Tim_Man_t*)p->pGia->pManTime ); + if ( p->pPars->fDoAverage ) + for ( i = 0; i < Gia_ManCoNum(p->pGia); i++ ) + Tim_ManSetCoRequired( (Tim_Man_t*)p->pGia->pManTime, i, (int)(Lf_ObjCoArrival(p, i) * (100.0 + p->pPars->nRelaxRatio) / 100.0) ); + else + Tim_ManInitPoRequiredAll( (Tim_Man_t*)p->pGia->pManTime, Delay ); + Gia_ManForEachObjReverse1( p->pGia, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + Lf_ObjSetRequired( p, Gia_ObjFaninId0(pObj, i), Lf_ObjRequired(p, i) ); + else if ( Gia_ObjIsAnd(pObj) ) + { + if ( Lf_ObjMapRefNum(p, i) ) + Lf_ManSetMapRefsOne( p, i ); + } + else if ( Gia_ObjIsCi(pObj) ) + Tim_ManSetCiRequired( (Tim_Man_t*)p->pGia->pManTime, Gia_ObjCioId(pObj), Lf_ObjRequired(p, i) ); + else if ( Gia_ObjIsCo(pObj) ) + { + int iDriverId = Gia_ObjFaninId0(pObj, i); + int reqTime = Tim_ManGetCoRequired( (Tim_Man_t*)p->pGia->pManTime, Gia_ObjCioId(pObj) ); + Lf_ObjSetRequired( p, iDriverId, reqTime ); + if ( Gia_ObjIsAndNotBuf(Gia_ObjFanin0(pObj)) ) + Lf_ObjMapRefInc( p, iDriverId ); + } + else assert( 0 ); + } + } + else + { + Gia_ManForEachCo( p->pGia, pObj, i ) + { + int iDriverId = Gia_ObjFaninId0p(p->pGia, pObj); + int reqTime = p->pPars->fDoAverage ? (int)(Lf_ObjCoArrival(p, i) * (100.0 + p->pPars->nRelaxRatio) / 100.0) : Delay; + Lf_ObjSetRequired( p, iDriverId, reqTime ); + if ( Gia_ObjIsAndNotBuf(Gia_ObjFanin0(pObj)) ) + Lf_ObjMapRefInc( p, iDriverId ); + } + Gia_ManForEachAndReverse( p->pGia, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + { + Lf_ObjSetRequired( p, Gia_ObjFaninId0(pObj, i), Lf_ObjRequired(p, i) ); + if ( Gia_ObjIsAndNotBuf(Gia_ObjFanin0(pObj)) ) + Lf_ObjMapRefInc( p, Gia_ObjFaninId0(pObj, i) ); + } + else if ( Lf_ObjMapRefNum(p, i) ) + Lf_ManSetMapRefsOne( p, i ); + } + } + if ( p->pPars->fUseMux7 ) + Gia_ManCleanMark0(p->pGia); + // blend references + assert( Vec_IntSize(&p->vMapRefs) == Gia_ManAndNotBufNum(p->pGia) ); + assert( Vec_FltSize(&p->vFlowRefs) == Gia_ManAndNotBufNum(p->pGia) ); + pMapRefs = Vec_IntArray(&p->vMapRefs); + pFlowRefs = Vec_FltArray(&p->vFlowRefs); + for ( i = 0; i < Vec_IntSize(&p->vMapRefs); i++ ) + pFlowRefs[i] = Coef * pFlowRefs[i] + (1.0 - Coef) * Abc_MaxFloat(1, pMapRefs[i]); +// pFlowRefs[i] = 0.2 * pFlowRefs[i] + 0.8 * Abc_MaxFloat(1, pMapRefs[i]); + return p->pPars->Area; +} + +void Lf_ManCountMapRefsOne( Lf_Man_t * p, int iObj ) +{ + Lf_Bst_t * pBest = Lf_ObjReadBest( p, iObj ); + Lf_Cut_t * pCut = Lf_ObjCutBest( p, iObj ); + int k ,Required = Lf_ObjRequired( p, iObj ); + assert( Lf_ObjMapRefNum(p, iObj) > 0 ); + assert( Lf_BestIsMapped(pBest) ); + assert( !pCut->fMux7 ); +// assert( pCut->Delay <= Required ); + for ( k = 0; k < (int)pCut->nLeaves; k++ ) + Lf_ObjSetRequired( p, pCut->pLeaves[k], Required - 1 ); + if ( Vec_FltSize(&p->vSwitches) ) + p->Switches += Lf_CutSwitches(p, pCut); + p->pPars->Edge += pCut->nLeaves; + p->pPars->Area++; +} +void Lf_ManCountMapRefs( Lf_Man_t * p ) +{ + // compute delay + Gia_Obj_t * pObj; + int i, Id, Delay = 0; + for ( i = 0; i < Gia_ManCoNum(p->pGia); i++ ) + Delay = Abc_MaxInt( Delay, Lf_ObjCoArrival2(p, i) ); + // check delay target + if ( p->pPars->DelayTarget == -1 && p->pPars->nRelaxRatio ) + p->pPars->DelayTarget = (int)((float)Delay * (100.0 + p->pPars->nRelaxRatio) / 100.0); + if ( p->pPars->DelayTarget != -1 ) + { + if ( Delay < p->pPars->DelayTarget + 0.01 ) + Delay = p->pPars->DelayTarget; + else if ( p->pPars->nRelaxRatio == 0 ) + Abc_Print( 0, "Relaxing user-specified delay target from %d to %d.\n", p->pPars->DelayTarget, Delay ); + } + p->pPars->Delay = Delay; + // compute area/edges/required + p->pPars->Mux7 = p->pPars->Area = p->pPars->Edge = p->Switches = 0; + Vec_IntFill( &p->vRequired, Gia_ManObjNum(p->pGia), ABC_INFINITY ); + if ( p->pPars->fUseMux7 ) + Gia_ManCleanMark0(p->pGia); + if ( p->pGia->pManTime != NULL ) + { + Tim_ManIncrementTravId( (Tim_Man_t*)p->pGia->pManTime ); + if ( p->pPars->fDoAverage ) + for ( i = 0; i < Gia_ManCoNum(p->pGia); i++ ) + Tim_ManSetCoRequired( (Tim_Man_t*)p->pGia->pManTime, i, (int)(Lf_ObjCoArrival(p, i) * (100.0 + p->pPars->nRelaxRatio) / 100.0) ); + else + Tim_ManInitPoRequiredAll( (Tim_Man_t*)p->pGia->pManTime, Delay ); + Gia_ManForEachObjReverse1( p->pGia, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + Lf_ObjSetRequired( p, Gia_ObjFaninId0(pObj, i), Lf_ObjRequired(p, i) ); + else if ( Gia_ObjIsAnd(pObj) ) + { + if ( Lf_ObjMapRefNum(p, i) ) + Lf_ManCountMapRefsOne( p, i ); + } + else if ( Gia_ObjIsCi(pObj) ) + Tim_ManSetCiRequired( (Tim_Man_t*)p->pGia->pManTime, Gia_ObjCioId(pObj), Lf_ObjRequired(p, i) ); + else if ( Gia_ObjIsCo(pObj) ) + { + int reqTime = Tim_ManGetCoRequired( (Tim_Man_t*)p->pGia->pManTime, Gia_ObjCioId(pObj) ); + Lf_ObjSetRequired( p, Gia_ObjFaninId0(pObj, i), reqTime ); + } + else assert( 0 ); + } + } + else + { + Gia_ManForEachCoDriverId( p->pGia, Id, i ) + Lf_ObjSetRequired( p, Id, p->pPars->fDoAverage ? (int)(Lf_ObjCoArrival(p, i) * (100.0 + p->pPars->nRelaxRatio) / 100.0) : Delay ); + Gia_ManForEachAndReverse( p->pGia, pObj, i ) + if ( Gia_ObjIsBuf(pObj) ) + Lf_ObjSetRequired( p, Gia_ObjFaninId0(pObj, i), Lf_ObjRequired(p, i) ); + else if ( Lf_ObjMapRefNum(p, i) ) + Lf_ManCountMapRefsOne( p, i ); + } + if ( p->pPars->fUseMux7 ) + Gia_ManCleanMark0(p->pGia); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Lf_ManDeriveMapping( Lf_Man_t * p ) +{ + Vec_Int_t * vMapping; + Lf_Cut_t * pCut; + int i, k; + assert( !p->pPars->fCutMin && p->pGia->vMapping == NULL ); + vMapping = Vec_IntAlloc( Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + (int)p->pPars->Area * 2 ); + Vec_IntFill( vMapping, Gia_ManObjNum(p->pGia), 0 ); + Gia_ManForEachAndId( p->pGia, i ) + { + if ( !Lf_ObjMapRefNum(p, i) ) + continue; + assert( !Gia_ObjIsBuf(Gia_ManObj(p->pGia,i)) ); + pCut = Lf_ObjCutBest( p, i ); + assert( !pCut->fMux7 ); + Vec_IntWriteEntry( vMapping, i, Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, pCut->nLeaves ); + for ( k = 0; k < (int)pCut->nLeaves; k++ ) + Vec_IntPush( vMapping, pCut->pLeaves[k] ); + Vec_IntPush( vMapping, i ); + } + assert( Vec_IntCap(vMapping) == 16 || Vec_IntSize(vMapping) == Vec_IntCap(vMapping) ); + p->pGia->vMapping = vMapping; + return p->pGia; +} +Gia_Man_t * Lf_ManDeriveMappingCoarse( Lf_Man_t * p ) +{ + Gia_Man_t * pNew, * pGia = p->pGia; + Gia_Obj_t * pObj; + Lf_Cut_t * pCut; + int i, k; + assert( !p->pPars->fCutMin && pGia->pMuxes ); + // create new manager + pNew = Gia_ManStart( Gia_ManObjNum(pGia) ); + pNew->pName = Abc_UtilStrsav( pGia->pName ); + pNew->pSpec = Abc_UtilStrsav( pGia->pSpec ); + // start mapping + pNew->vMapping = Vec_IntAlloc( Gia_ManObjNum(pGia) + 2*Gia_ManXorNum(pGia) + 2*Gia_ManMuxNum(pGia) + (int)p->pPars->Edge + 2*(int)p->pPars->Area + 4*(int)p->pPars->Mux7 ); + Vec_IntFill( pNew->vMapping, Gia_ManObjNum(pGia) + 2*Gia_ManXorNum(pGia) + 2*Gia_ManMuxNum(pGia), 0 ); + // process objects + Gia_ManConst0(pGia)->Value = 0; + Gia_ManForEachObj1( pGia, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + { pObj->Value = Gia_ManAppendCi( pNew ); continue; } + if ( Gia_ObjIsCo(pObj) ) + { pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); continue; } + if ( Gia_ObjIsBuf(pObj) ) + { pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); continue; } + if ( Gia_ObjIsMuxId(pGia, i) ) + pObj->Value = Gia_ManAppendMux( pNew, Gia_ObjFanin2Copy(pGia, pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsXor(pObj) ) + pObj->Value = Gia_ManAppendXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( !Lf_ObjMapRefNum(p, i) ) + continue; + pCut = Lf_ObjCutBest( p, i ); + Vec_IntWriteEntry( pNew->vMapping, Abc_Lit2Var(pObj->Value), Vec_IntSize(pNew->vMapping) ); + Vec_IntPush( pNew->vMapping, pCut->nLeaves ); + for ( k = 0; k < (int)pCut->nLeaves; k++ ) + Vec_IntPush( pNew->vMapping, Abc_Lit2Var(Gia_ManObj(pGia, pCut->pLeaves[k])->Value) ); + Vec_IntPush( pNew->vMapping, pCut->fMux7 ? -Abc_Lit2Var(pObj->Value) : Abc_Lit2Var(pObj->Value) ); + } + Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia) ); + assert( Vec_IntCap(pNew->vMapping) == 16 || Vec_IntSize(pNew->vMapping) == Vec_IntCap(pNew->vMapping) ); + return pNew; +} +static inline int Lf_ManDerivePart( Lf_Man_t * p, Gia_Man_t * pNew, Vec_Int_t * vMapping, Vec_Int_t * vMapping2, Vec_Int_t * vCopies, Lf_Cut_t * pCut, Vec_Int_t * vLeaves, Vec_Int_t * vCover, Gia_Obj_t * pObj ) +{ + word * pTruth; + int k, iLit, iTemp; + if ( p->pPars->nLutSizeMux && p->pPars->nLutSizeMux == (int)pCut->nLeaves ) + { + word pTruthCof[LF_TT_WORDS], * pTruth = Lf_CutTruth( p, pCut ); + int pVarsNew[LF_LEAF_MAX], nVarsNew, iLitCofs[2]; + int LutSize = p->pPars->nLutSize; + int nWords = Abc_Truth6WordNum(LutSize); + int c, iVar = Lf_ManFindCofVar( pTruth, nWords, pCut->nLeaves ); + assert( iVar >= 0 && iVar < (int)pCut->nLeaves ); + for ( c = 0; c < 2; c++ ) + { + for ( k = 0; k < (int)pCut->nLeaves; k++ ) + pVarsNew[k] = k; + if ( c ) + Abc_TtCofactor1p( pTruthCof, pTruth, nWords, iVar ); + else + Abc_TtCofactor0p( pTruthCof, pTruth, nWords, iVar ); + nVarsNew = Abc_TtMinBase( pTruthCof, pVarsNew, pCut->nLeaves, LutSize ); + assert( nVarsNew > 0 ); + // derive LUT + Vec_IntClear( vLeaves ); + for ( k = 0; k < nVarsNew; k++ ) + Vec_IntPush( vLeaves, Vec_IntEntry(vCopies, pCut->pLeaves[pVarsNew[k]]) ); + iLitCofs[c] = Kit_TruthToGia( pNew, (unsigned *)pTruthCof, nVarsNew, vCover, vLeaves, 0 ); + // create mapping + Vec_IntSetEntry( vMapping, Abc_Lit2Var(iLitCofs[c]), Vec_IntSize(vMapping2) ); + Vec_IntPush( vMapping2, Vec_IntSize(vLeaves) ); + Vec_IntForEachEntry( vLeaves, iTemp, k ) + Vec_IntPush( vMapping2, Abc_Lit2Var(iTemp) ); + Vec_IntPush( vMapping2, Abc_Lit2Var(iLitCofs[c]) ); + } + // derive MUX + pTruthCof[0] = ABC_CONST(0xCACACACACACACACA); + Vec_IntClear( vLeaves ); + Vec_IntPush( vLeaves, iLitCofs[0] ); + Vec_IntPush( vLeaves, iLitCofs[1] ); + Vec_IntPush( vLeaves, Vec_IntEntry(vCopies, pCut->pLeaves[iVar]) ); + iLit = Kit_TruthToGia( pNew, (unsigned *)pTruthCof, Vec_IntSize(vLeaves), vCover, vLeaves, 0 ); + // create mapping + Vec_IntSetEntry( vMapping, Abc_Lit2Var(iLit), Vec_IntSize(vMapping2) ); + Vec_IntPush( vMapping2, Vec_IntSize(vLeaves) ); + Vec_IntForEachEntry( vLeaves, iTemp, k ) + Vec_IntPush( vMapping2, Abc_Lit2Var(iTemp) ); + Vec_IntPush( vMapping2, -Abc_Lit2Var(iLit) ); + return iLit; + } + Vec_IntClear( vLeaves ); + if ( pCut->fMux7 ) + { + assert( pCut->nLeaves == 3 ); + Vec_IntPush( vLeaves, Abc_LitNotCond(Vec_IntEntry(vCopies, pCut->pLeaves[0]), Gia_ObjFaninC0(pObj)) ); + Vec_IntPush( vLeaves, Abc_LitNotCond(Vec_IntEntry(vCopies, pCut->pLeaves[1]), Gia_ObjFaninC1(pObj)) ); + Vec_IntPush( vLeaves, Abc_LitNotCond(Vec_IntEntry(vCopies, pCut->pLeaves[2]), Gia_ObjFaninC2(p->pGia,pObj)) ); + } + else + { + for ( k = 0; k < (int)pCut->nLeaves; k++ ) + Vec_IntPush( vLeaves, Vec_IntEntry(vCopies, pCut->pLeaves[k]) ); + } + pTruth = Lf_CutTruth( p, pCut ); + iLit = Kit_TruthToGia( pNew, (unsigned *)pTruth, Vec_IntSize(vLeaves), vCover, vLeaves, 0 ); + // create mapping + Vec_IntSetEntry( vMapping, Abc_Lit2Var(iLit), Vec_IntSize(vMapping2) ); + Vec_IntPush( vMapping2, Vec_IntSize(vLeaves) ); + Vec_IntForEachEntry( vLeaves, iTemp, k ) + Vec_IntPush( vMapping2, Abc_Lit2Var(iTemp) ); + Vec_IntPush( vMapping2, pCut->fMux7 ? -Abc_Lit2Var(iLit) : Abc_Lit2Var(iLit) ); + return iLit; +} +Gia_Man_t * Lf_ManDeriveMappingGia( Lf_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + Vec_Int_t * vCopies = Vec_IntStartFull( Gia_ManObjNum(p->pGia) ); + Vec_Int_t * vMapping = Vec_IntStart( 2*Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + 2*(int)p->pPars->Area + 4*(int)p->pPars->Mux7 ); + Vec_Int_t * vMapping2 = Vec_IntStart( (int)p->pPars->Edge + 2*(int)p->pPars->Area + 1000 ); + Vec_Int_t * vCover = Vec_IntAlloc( 1 << 16 ); + Vec_Int_t * vLeaves = Vec_IntAlloc( 16 ); + Lf_Cut_t * pCut; + int i, iLit; + assert( p->pPars->fCutMin ); + // create new manager + pNew = Gia_ManStart( Gia_ManObjNum(p->pGia) ); + pNew->pName = Abc_UtilStrsav( p->pGia->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pGia->pSpec ); + Vec_IntWriteEntry( vCopies, 0, 0 ); + Gia_ManForEachObj1( p->pGia, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + { + Vec_IntWriteEntry( vCopies, i, Gia_ManAppendCi(pNew) ); + continue; + } + if ( Gia_ObjIsCo(pObj) ) + { + iLit = Vec_IntEntry( vCopies, Gia_ObjFaninId0p(p->pGia, pObj) ); + iLit = Gia_ManAppendCo( pNew, Abc_LitNotCond(iLit, Gia_ObjFaninC0(pObj)) ); + continue; + } + if ( Gia_ObjIsBuf(pObj) ) + { + iLit = Vec_IntEntry( vCopies, Gia_ObjFaninId0p(p->pGia, pObj) ); + iLit = Gia_ManAppendBuf( pNew, Abc_LitNotCond(iLit, Gia_ObjFaninC0(pObj)) ); + Vec_IntWriteEntry( vCopies, i, iLit ); + continue; + } + if ( !Lf_ObjMapRefNum(p, i) ) + continue; + pCut = Lf_ObjCutBest( p, i ); + assert( pCut->iFunc >= 0 ); + if ( pCut->nLeaves == 0 ) + { + assert( Abc_Lit2Var(pCut->iFunc) == 0 ); + Vec_IntWriteEntry( vCopies, i, pCut->iFunc ); + continue; + } + if ( pCut->nLeaves == 1 ) + { + assert( Abc_Lit2Var(pCut->iFunc) == 1 ); + iLit = Vec_IntEntry( vCopies, pCut->pLeaves[0] ); + Vec_IntWriteEntry( vCopies, i, Abc_LitNotCond(iLit, Abc_LitIsCompl(pCut->iFunc)) ); + continue; + } + iLit = Lf_ManDerivePart( p, pNew, vMapping, vMapping2, vCopies, pCut, vLeaves, vCover, pObj ); + Vec_IntWriteEntry( vCopies, i, Abc_LitNotCond(iLit, Abc_LitIsCompl(pCut->iFunc)) ); + } + Vec_IntFree( vCopies ); + Vec_IntFree( vCover ); + Vec_IntFree( vLeaves ); + // finish mapping + if ( Vec_IntSize(vMapping) > Gia_ManObjNum(pNew) ) + Vec_IntShrink( vMapping, Gia_ManObjNum(pNew) ); + else + Vec_IntFillExtra( vMapping, Gia_ManObjNum(pNew), 0 ); + assert( Vec_IntSize(vMapping) == Gia_ManObjNum(pNew) ); + Vec_IntForEachEntry( vMapping, iLit, i ) + if ( iLit > 0 ) + Vec_IntAddToEntry( vMapping, i, Gia_ManObjNum(pNew) ); + Vec_IntAppend( vMapping, vMapping2 ); + Vec_IntFree( vMapping2 ); + // attach mapping and packing + assert( pNew->vMapping == NULL ); + pNew->vMapping = vMapping; + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p->pGia) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Lf_Man_t * Lf_ManAlloc( Gia_Man_t * pGia, Jf_Par_t * pPars ) +{ + Lf_Man_t * p; int i, k = 0; + assert( pPars->nCutNum > 1 && pPars->nCutNum <= LF_CUT_MAX ); + assert( pPars->nLutSize > 1 && pPars->nLutSize <= LF_LEAF_MAX ); + ABC_FREE( pGia->pRefs ); + Vec_IntFreeP( &pGia->vMapping ); + Gia_ManCleanValue( pGia ); + if ( Gia_ManHasChoices(pGia) ) + Gia_ManSetPhase(pGia); + p = ABC_CALLOC( Lf_Man_t, 1 ); + Lf_ManAnalyzeCoDrivers( pGia, &p->nCoDrivers, &p->nInverters ); + if ( pPars->fPower ) + Lf_ManComputeSwitching( pGia, &p->vSwitches ); + p->clkStart = Abc_Clock(); + p->pGia = pGia; + p->pPars = pPars; + p->nCutWords = (sizeof(Lf_Cut_t)/sizeof(int) + pPars->nLutSize + 1) >> 1; + p->nSetWords = p->nCutWords * pPars->nCutNum; + p->vTtMem = pPars->fCutMin ? Vec_MemAllocForTT( pPars->nLutSize, 0 ) : NULL; + if ( pPars->fCutMin && pPars->fUseMux7 ) + Vec_MemAddMuxTT( p->vTtMem, pPars->nLutSize ); + p->pObjBests = ABC_CALLOC( Lf_Bst_t, Gia_ManAndNotBufNum(pGia) ); + Vec_IntGrow( &p->vFreeSets, (1<<14) ); + Vec_PtrGrow( &p->vFreePages, 256 ); + Lf_MemAlloc( &p->vStoreOld, 16, &p->vFreePages, p->nCutWords ); + Lf_MemAlloc( &p->vStoreNew, 16, &p->vFreePages, p->nCutWords ); + Vec_IntFill( &p->vOffsets, Gia_ManObjNum(pGia), -1 ); + Vec_IntFill( &p->vRequired, Gia_ManObjNum(pGia), ABC_INFINITY ); + Vec_IntFill( &p->vCutSets, Gia_ManAndNotBufNum(pGia), -1 ); + Vec_FltFill( &p->vFlowRefs, Gia_ManAndNotBufNum(pGia), 0 ); + Vec_IntFill( &p->vMapRefs, Gia_ManAndNotBufNum(pGia), 0 ); + Vec_IntFill( &p->vCiArrivals, Gia_ManCiNum(pGia), 0 ); + Gia_ManForEachAndId( pGia, i ) + if ( !Gia_ObjIsBuf(Gia_ManObj(pGia, i)) ) + Vec_IntWriteEntry( &p->vOffsets, i, k++ ); + assert( k == Gia_ManAndNotBufNum(pGia) ); + Lf_ManSetFlowRefs( pGia, &p->vFlowRefs, &p->vOffsets ); + if ( pPars->pTimesArr ) + for ( i = 0; i < Gia_ManPiNum(pGia); i++ ) + Vec_IntWriteEntry( &p->vCiArrivals, i, pPars->pTimesArr[i] ); + return p; +} +void Lf_ManFree( Lf_Man_t * p ) +{ + ABC_FREE( p->pPars->pTimesArr ); + ABC_FREE( p->pPars->pTimesReq ); + if ( p->pPars->fCutMin ) + Vec_MemHashFree( p->vTtMem ); + if ( p->pPars->fCutMin ) + Vec_MemFree( p->vTtMem ); + Vec_PtrFreeData( &p->vMemSets ); + Vec_PtrFreeData( &p->vFreePages ); + Vec_PtrFreeData( &p->vStoreOld.vPages ); + Vec_PtrFreeData( &p->vStoreNew.vPages ); + ABC_FREE( p->vMemSets.pArray ); + ABC_FREE( p->vFreePages.pArray ); + ABC_FREE( p->vStoreOld.vPages.pArray ); + ABC_FREE( p->vStoreNew.vPages.pArray ); + ABC_FREE( p->vFreePages.pArray ); + ABC_FREE( p->vFreeSets.pArray ); + ABC_FREE( p->vOffsets.pArray ); + ABC_FREE( p->vRequired.pArray ); + ABC_FREE( p->vCutSets.pArray ); + ABC_FREE( p->vFlowRefs.pArray ); + ABC_FREE( p->vMapRefs.pArray ); + ABC_FREE( p->vSwitches.pArray ); + ABC_FREE( p->vCiArrivals.pArray ); + ABC_FREE( p->pObjBests ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Lf_ManSetDefaultPars( Jf_Par_t * pPars ) +{ + memset( pPars, 0, sizeof(Jf_Par_t) ); + pPars->nLutSize = 6; + pPars->nCutNum = 8; + pPars->nProcNum = 0; + pPars->nRounds = 4; + pPars->nRoundsEla = 1; + pPars->nRelaxRatio = 0; + pPars->nCoarseLimit = 3; + pPars->nAreaTuner = 1; + pPars->nVerbLimit = 5; + pPars->DelayTarget = -1; + pPars->fAreaOnly = 0; + pPars->fOptEdge = 1; + pPars->fUseMux7 = 0; + pPars->fPower = 0; + pPars->fCoarsen = 1; + pPars->fCutMin = 0; + pPars->fFuncDsd = 0; + pPars->fGenCnf = 0; + pPars->fPureAig = 0; + pPars->fCutHashing = 0; + pPars->fCutSimple = 0; + pPars->fVerbose = 0; + pPars->fVeryVerbose = 0; + pPars->nLutSizeMax = LF_LEAF_MAX; + pPars->nCutNumMax = LF_CUT_MAX; +} +void Lf_ManPrintStats( Lf_Man_t * p, char * pTitle ) +{ + if ( !p->pPars->fVerbose ) + return; + printf( "%s : ", pTitle ); + printf( "Level =%6lu ", (long)p->pPars->Delay ); + printf( "Area =%9lu ", (long)p->pPars->Area ); + printf( "Edge =%9lu ", (long)p->pPars->Edge ); + printf( "LUT =%9lu ", (long)p->pPars->Area+p->nInverters ); + if ( Vec_FltSize(&p->vSwitches) ) + printf( "Swt =%8.1f ", p->Switches ); + if ( p->pPars->fUseMux7 ) + printf( "Mux7 =%7lu ", (long)p->pPars->Mux7 ); + Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); + fflush( stdout ); +} +void Lf_ManPrintInit( Lf_Man_t * p ) +{ + if ( !p->pPars->fVerbose ) + return; + printf( "LutSize = %d ", p->pPars->nLutSize ); + printf( "CutNum = %d ", p->pPars->nCutNum ); + printf( "Iter = %d ", p->pPars->nRounds + p->pPars->nRoundsEla ); + if ( p->pPars->nRelaxRatio ) + printf( "Ratio = %d ", p->pPars->nRelaxRatio ); + printf( "Edge = %d ", p->pPars->fOptEdge ); + if ( p->pPars->DelayTarget != -1 ) + printf( "Delay = %d ", p->pPars->DelayTarget ); + printf( "CutMin = %d ", p->pPars->fCutMin ); + printf( "Coarse = %d ", p->pPars->fCoarsen ); + printf( "Cut/Set = %d/%d Bytes", 8*p->nCutWords, 8*p->nSetWords ); + printf( "\n" ); + printf( "Computing cuts...\r" ); + fflush( stdout ); +} +void Lf_ManPrintQuit( Lf_Man_t * p, Gia_Man_t * pNew ) +{ + float MemGia = Gia_ManMemory(p->pGia) / (1<<20); + float MemMan = 1.0 * sizeof(int) * (2 * Gia_ManObjNum(p->pGia) + 3 * Gia_ManAndNotBufNum(p->pGia)) / (1<<20); // offset, required, cutsets, maprefs, flowrefs + float MemCutsB = 1.0 * (p->vStoreOld.MaskPage + 1) * (Vec_PtrSize(&p->vFreePages) + Vec_PtrSize(&p->vStoreOld.vPages)) / (1<<20) + 1.0 * sizeof(Lf_Bst_t) * Gia_ManAndNotBufNum(p->pGia) / (1<<20); + float MemCutsF = 1.0 * sizeof(word) * p->nSetWords * (1<vMemSets) / (1<<20); + float MemTt = p->vTtMem ? Vec_MemMemory(p->vTtMem) / (1<<20) : 0; + float MemMap = Vec_IntMemory(pNew->vMapping) / (1<<20); + if ( p->CutCount[0] == 0 ) + p->CutCount[0] = 1; + if ( !p->pPars->fVerbose ) + { + int i, CountOver[2] = {0}; + int nLutSize = p->pPars->fCutGroup ? p->pPars->nLutSize/2 : p->pPars->nLutSize; + Gia_ManForEachLut( pNew, i ) + CountOver[Gia_ObjLutSize(pNew, i) > nLutSize]++; + if ( p->pPars->fCutGroup ) + printf( "Created %d regular %d-LUTs and %d dual %d-LUTs. The total of %d %d-LUTs.\n", + CountOver[0], nLutSize, CountOver[1], nLutSize, CountOver[0] + 2*CountOver[1], nLutSize ); + return; + } + printf( "CutPair = %.0f ", p->CutCount[0] ); + printf( "Merge = %.0f (%.2f %%) ", p->CutCount[1], 100.0*p->CutCount[1]/p->CutCount[0] ); + printf( "Eval = %.0f (%.2f %%) ", p->CutCount[2], 100.0*p->CutCount[2]/p->CutCount[0] ); + printf( "Cut = %.0f (%.2f %%) ", p->CutCount[3], 100.0*p->CutCount[3]/p->CutCount[0] ); + printf( "\n" ); + printf( "Gia = %.2f MB ", MemGia ); + printf( "Man = %.2f MB ", MemMan ); + printf( "Best = %.2f MB ", MemCutsB ); + printf( "Front = %.2f MB ", MemCutsF ); + printf( "Map = %.2f MB ", MemMap ); + printf( "TT = %.2f MB ", MemTt ); + printf( "Total = %.2f MB", MemGia + MemMan + MemCutsB + MemCutsF + MemMap + MemTt ); + printf( "\n" ); + if ( 1 ) + { + int i; + for ( i = 0; i <= p->pPars->nLutSize; i++ ) + printf( "%d:%d ", i, p->nCutCounts[i] ); + printf( "Equal = %d (%.0f %%) ", p->nCutEqual, 100.0 * p->nCutEqual / p->Iter / Gia_ManAndNotBufNum(p->pGia) ); + if ( p->vTtMem ) + printf( "TT = %d (%.2f %%) ", Vec_MemEntryNum(p->vTtMem), 100.0 * Vec_MemEntryNum(p->vTtMem) / p->CutCount[2] ); + if ( p->pGia->pMuxes && p->nCutMux ) + printf( "MuxTT = %d (%.0f %%) ", p->nCutMux, 100.0 * p->nCutMux / p->Iter / Gia_ManMuxNum(p->pGia) ); + printf( "\n" ); + } + printf( "CoDrvs = %d (%.2f %%) ", p->nCoDrivers, 100.0*p->nCoDrivers/Gia_ManCoNum(p->pGia) ); + printf( "CoInvs = %d (%.2f %%) ", p->nInverters, 100.0*p->nInverters/Gia_ManCoNum(p->pGia) ); + printf( "Front = %d (%.2f %%) ", p->nFrontMax, 100.0*p->nFrontMax/Gia_ManAndNum(p->pGia) ); + printf( "TimeFails = %d ", p->nTimeFails ); + Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); + fflush( stdout ); +} +void Lf_ManComputeMapping( Lf_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, arrTime; + assert( p->vStoreNew.iCur == 0 ); + Lf_ManSetCutRefs( p ); + if ( p->pGia->pManTime != NULL ) + { + assert( !Gia_ManBufNum(p->pGia) ); + Tim_ManIncrementTravId( (Tim_Man_t*)p->pGia->pManTime ); + Gia_ManForEachObj1( p->pGia, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + continue; + if ( Gia_ObjIsAnd(pObj) ) + Lf_ObjMergeOrder( p, i ); + else if ( Gia_ObjIsCi(pObj) ) + { + arrTime = Tim_ManGetCiArrival( (Tim_Man_t*)p->pGia->pManTime, Gia_ObjCioId(pObj) ); + Lf_ObjSetCiArrival( p, Gia_ObjCioId(pObj), arrTime ); + } + else if ( Gia_ObjIsCo(pObj) ) + { + arrTime = Lf_ObjCoArrival( p, Gia_ObjCioId(pObj) ); + Tim_ManSetCoArrival( (Tim_Man_t*)p->pGia->pManTime, Gia_ObjCioId(pObj), arrTime ); + } + else assert( 0 ); + } +// Tim_ManPrint( p->pGia->pManTime ); + } + else + { + Gia_ManForEachAnd( p->pGia, pObj, i ) + if ( !Gia_ObjIsBuf(pObj) ) + Lf_ObjMergeOrder( p, i ); + } + Lf_MemRecycle( &p->vStoreOld ); + ABC_SWAP( Lf_Mem_t, p->vStoreOld, p->vStoreNew ); + if ( p->fUseEla ) + Lf_ManCountMapRefs( p ); + else + Lf_ManSetMapRefs( p ); + Lf_ManPrintStats( p, (char *)(p->fUseEla ? "Ela " : (p->Iter ? "Area " : "Delay")) ); +} +Gia_Man_t * Lf_ManPerformMappingInt( Gia_Man_t * pGia, Jf_Par_t * pPars ) +{ + int fUsePowerMode = 0; + Lf_Man_t * p; + Gia_Man_t * pNew, * pCls; + if ( pPars->fUseMux7 ) + pPars->fCoarsen = 1, pPars->nRoundsEla = 0; + if ( Gia_ManHasChoices(pGia) || pPars->nLutSizeMux ) + pPars->fCutMin = 1; + if ( pPars->fCoarsen ) + { + pCls = Gia_ManDupMuxes(pGia, pPars->nCoarseLimit); + pCls->pManTime = pGia->pManTime; pGia->pManTime = NULL; + } + else pCls = pGia; + p = Lf_ManAlloc( pCls, pPars ); + if ( pPars->fVerbose && pPars->fCoarsen ) + { + printf( "Initial " ); Gia_ManPrintMuxStats( pGia ); printf( "\n" ); + printf( "Derived " ); Gia_ManPrintMuxStats( pCls ); printf( "\n" ); + } + Lf_ManPrintInit( p ); + + // power mode + if ( fUsePowerMode && Vec_FltSize(&p->vSwitches) ) + pPars->fPower = 0; + + // perform mapping + for ( p->Iter = 0; p->Iter < p->pPars->nRounds; p->Iter++ ) + Lf_ManComputeMapping( p ); + p->fUseEla = 1; + for ( ; p->Iter < p->pPars->nRounds + pPars->nRoundsEla; p->Iter++ ) + Lf_ManComputeMapping( p ); + + // power mode + if ( fUsePowerMode && Vec_FltSize(&p->vSwitches) ) + { + pPars->fPower = 1; + for ( ; p->Iter < p->pPars->nRounds + pPars->nRoundsEla + 2; p->Iter++ ) + Lf_ManComputeMapping( p ); + } + + if ( pPars->fVeryVerbose && pPars->fCutMin ) + Vec_MemDumpTruthTables( p->vTtMem, Gia_ManName(p->pGia), pPars->nLutSize ); + if ( pPars->fCutMin ) + pNew = Lf_ManDeriveMappingGia( p ); + else if ( pPars->fCoarsen ) + pNew = Lf_ManDeriveMappingCoarse( p ); + else + pNew = Lf_ManDeriveMapping( p ); + Gia_ManMappingVerify( pNew ); + Lf_ManPrintQuit( p, pNew ); + Lf_ManFree( p ); + if ( pCls != pGia ) + { + pGia->pManTime = pCls->pManTime; pCls->pManTime = NULL; + Gia_ManStop( pCls ); + } + return pNew; +} +Gia_Man_t * Lf_ManPerformMapping( Gia_Man_t * p, Jf_Par_t * pPars ) +{ + Gia_Man_t * pNew; + if ( p->pManTime && Tim_ManBoxNum((Tim_Man_t*)p->pManTime) && Gia_ManIsNormalized(p) ) + { + Tim_Man_t * pTimOld = (Tim_Man_t *)p->pManTime; + p->pManTime = Tim_ManDup( pTimOld, 1 ); + pNew = Gia_ManDupUnnormalize( p ); + if ( pNew == NULL ) + return NULL; + Gia_ManTransferTiming( pNew, p ); + p = pNew; + // mapping + pNew = Lf_ManPerformMappingInt( p, pPars ); + if ( pNew != p ) + { + Gia_ManTransferTiming( pNew, p ); + Gia_ManStop( p ); + } + // normalize + pNew = Gia_ManDupNormalize( p = pNew, 0 ); + Gia_ManTransferMapping( pNew, p ); +// Gia_ManTransferPacking( pNew, p ); + Gia_ManTransferTiming( pNew, p ); + Gia_ManStop( p ); // do not delete if the original one! + // cleanup + Tim_ManStop( (Tim_Man_t *)pNew->pManTime ); + pNew->pManTime = pTimOld; + assert( Gia_ManIsNormalized(pNew) ); + } + else + { + // mapping + pNew = Lf_ManPerformMappingInt( p, pPars ); + Gia_ManTransferTiming( pNew, p ); + } + return pNew; +} + +/**Function************************************************************* + + Synopsis [Interface of LUT mapping package.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManPerformLfMapping( Gia_Man_t * p, Jf_Par_t * pPars, int fNormalized ) +{ + Gia_Man_t * pNew; + assert( !pPars->fCutGroup || pPars->nLutSize == 9 || pPars->nLutSize == 11 || pPars->nLutSize == 13 ); + // reconstruct GIA according to the hierarchy manager + assert( pPars->pTimesArr == NULL ); + assert( pPars->pTimesReq == NULL ); + if ( p->pManTime ) + { + if ( fNormalized ) + { + pNew = Gia_ManDupUnnormalize( p ); + if ( pNew == NULL ) + return NULL; + Gia_ManTransferTiming( pNew, p ); + p = pNew; + // set arrival and required times + pPars->pTimesArr = Tim_ManGetArrTimes( (Tim_Man_t *)p->pManTime ); + pPars->pTimesReq = Tim_ManGetReqTimes( (Tim_Man_t *)p->pManTime ); + } + else + p = Gia_ManDup( p ); + } + else + p = Gia_ManDup( p ); + // perform mapping + pNew = Lf_ManPerformMappingInt( p, pPars ); + if ( pNew != p ) + { + // transfer name + ABC_FREE( pNew->pName ); + ABC_FREE( pNew->pSpec ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + // return the original (unmodified by the mapper) timing manager + Gia_ManTransferTiming( pNew, p ); + Gia_ManStop( p ); + } + // normalize and transfer mapping + pNew = Gia_ManDupNormalize( p = pNew, 0 ); + Gia_ManTransferMapping( pNew, p ); +// Gia_ManTransferPacking( pNew, p ); + Gia_ManTransferTiming( pNew, p ); + Gia_ManStop( p ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaMan.c b/yosys/abc/src/aig/gia/giaMan.c new file mode 100644 index 00000000000..d0af551b0b4 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaMan.c @@ -0,0 +1,2378 @@ +/**CFile**************************************************************** + + FileName [giaMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Package manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include + +#include "gia.h" +#include "misc/tim/tim.h" +#include "proof/abs/abs.h" +#include "opt/dar/dar.h" +#include "misc/extra/extra.h" + +#ifdef WIN32 +#include +#endif + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern void Gia_ManDfsSlacksPrint( Gia_Man_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManStart( int nObjsMax ) +{ + Gia_Man_t * p; + assert( nObjsMax > 0 ); + p = ABC_CALLOC( Gia_Man_t, 1 ); + p->nObjsAlloc = nObjsMax; + p->pObjs = ABC_CALLOC( Gia_Obj_t, nObjsMax ); + p->pObjs->iDiff0 = p->pObjs->iDiff1 = GIA_NONE; + p->nObjs = 1; + p->vCis = Vec_IntAlloc( nObjsMax / 20 ); + p->vCos = Vec_IntAlloc( nObjsMax / 20 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Deletes AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManStop( Gia_Man_t * p ) +{ + if ( p->vSeqModelVec ) + Vec_PtrFreeFree( p->vSeqModelVec ); + Gia_ManStaticFanoutStop( p ); + Tim_ManStopP( (Tim_Man_t **)&p->pManTime ); + assert( p->pManTime == NULL ); + Vec_PtrFreeFree( p->vNamesIn ); + Vec_PtrFreeFree( p->vNamesOut ); + Vec_PtrFreeFree( p->vNamesNode ); + Vec_IntFreeP( &p->vSwitching ); + Vec_IntFreeP( &p->vSuper ); + Vec_IntFreeP( &p->vStore ); + Vec_IntFreeP( &p->vClassNew ); + Vec_IntFreeP( &p->vClassOld ); + Vec_IntFreeP( &p->vPats ); + Vec_BitFreeP( &p->vPolars ); + Vec_WrdFreeP( &p->vSims ); + Vec_WrdFreeP( &p->vSimsT ); + Vec_WrdFreeP( &p->vSimsPi ); + Vec_WrdFreeP( &p->vSimsPo ); + Vec_IntFreeP( &p->vTimeStamps ); + Vec_FltFreeP( &p->vTiming ); + Vec_VecFreeP( &p->vClockDoms ); + Vec_IntFreeP( &p->vCofVars ); + Vec_IntFreeP( &p->vIdsOrig ); + Vec_IntFreeP( &p->vIdsEquiv ); + Vec_IntFreeP( &p->vLutConfigs ); + Vec_IntFreeP( &p->vEdgeDelay ); + Vec_IntFreeP( &p->vEdgeDelayR ); + Vec_IntFreeP( &p->vEdge1 ); + Vec_IntFreeP( &p->vEdge2 ); + Vec_IntFreeP( &p->vUserPiIds ); + Vec_IntFreeP( &p->vUserPoIds ); + Vec_IntFreeP( &p->vUserFfIds ); + Vec_IntFreeP( &p->vFlopClasses ); + Vec_IntFreeP( &p->vGateClasses ); + Vec_IntFreeP( &p->vObjClasses ); + Vec_IntFreeP( &p->vInitClasses ); + Vec_IntFreeP( &p->vRegClasses ); + Vec_IntFreeP( &p->vRegInits ); + Vec_IntFreeP( &p->vDoms ); + Vec_IntFreeP( &p->vBarBufs ); + Vec_IntFreeP( &p->vXors ); + Vec_IntFreeP( &p->vLevels ); + Vec_IntFreeP( &p->vTruths ); + Vec_IntErase( &p->vCopies ); + Vec_IntErase( &p->vCopies2 ); + Vec_IntFreeP( &p->vVar2Obj ); + Vec_IntErase( &p->vCopiesTwo ); + Vec_IntErase( &p->vSuppVars ); + Vec_IntErase( &p->vVarMap ); + Vec_WrdFreeP( &p->vSuppWords ); + Vec_IntFreeP( &p->vTtNums ); + Vec_IntFreeP( &p->vTtNodes ); + Vec_WrdFreeP( &p->vTtMemory ); + Vec_PtrFreeP( &p->vTtInputs ); + Vec_IntFreeP( &p->vMapping ); + Vec_WecFreeP( &p->vMapping2 ); + Vec_WecFreeP( &p->vFanouts2 ); + Vec_IntFreeP( &p->vCellMapping ); + Vec_IntFreeP( &p->vPacking ); + Vec_IntFreeP( &p->vConfigs ); + ABC_FREE( p->pCellStr ); + Vec_FltFreeP( &p->vInArrs ); + Vec_FltFreeP( &p->vOutReqs ); + Vec_IntFreeP( &p->vCiArrs ); + Vec_IntFreeP( &p->vCoReqs ); + Vec_IntFreeP( &p->vCoArrs ); + Vec_IntFreeP( &p->vCoAttrs ); + Vec_IntFreeP( &p->vWeights ); + Gia_ManStopP( &p->pAigExtra ); + Vec_IntFree( p->vCis ); + Vec_IntFree( p->vCos ); + Vec_IntErase( &p->vHash ); + Vec_IntErase( &p->vHTable ); + Vec_IntErase( &p->vRefs ); + Vec_StrFreeP( &p->vStopsF ); + Vec_StrFreeP( &p->vStopsB ); + ABC_FREE( p->pData2 ); + ABC_FREE( p->pTravIds ); + ABC_FREE( p->pPlacement ); + ABC_FREE( p->pSwitching ); + ABC_FREE( p->pCexSeq ); + ABC_FREE( p->pCexComb ); + ABC_FREE( p->pIso ); +// ABC_FREE( p->pMapping ); + ABC_FREE( p->pFanData ); + ABC_FREE( p->pReprsOld ); + ABC_FREE( p->pReprs ); + ABC_FREE( p->pNexts ); + ABC_FREE( p->pSibls ); + ABC_FREE( p->pRefs ); + ABC_FREE( p->pLutRefs ); + ABC_FREE( p->pMuxes ); + ABC_FREE( p->pObjs ); + ABC_FREE( p->pSpec ); + ABC_FREE( p->pName ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Returns memory used in megabytes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +double Gia_ManMemory( Gia_Man_t * p ) +{ + double Memory = sizeof(Gia_Man_t); + Memory += sizeof(Gia_Obj_t) * Gia_ManObjNum(p); + Memory += sizeof(int) * Gia_ManCiNum(p); + Memory += sizeof(int) * Gia_ManCoNum(p); + Memory += sizeof(int) * Vec_IntSize(&p->vHTable); + Memory += sizeof(int) * Gia_ManObjNum(p) * (p->pRefs != NULL); + Memory += Vec_IntMemory( p->vLevels ); + Memory += Vec_IntMemory( p->vCellMapping ); + Memory += Vec_IntMemory( &p->vCopies ); + Memory += Vec_FltMemory( p->vInArrs ); + Memory += Vec_FltMemory( p->vOutReqs ); + Memory += Vec_PtrMemory( p->vNamesIn ); + Memory += Vec_PtrMemory( p->vNamesOut ); + Memory += Vec_PtrMemory( p->vNamesNode ); + return Memory; +} + +/**Function************************************************************* + + Synopsis [Stops the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManStopP( Gia_Man_t ** p ) +{ + if ( *p == NULL ) + return; + Gia_ManStop( *p ); + *p = NULL; +} + +/**Function************************************************************* + + Synopsis [Prints stats for the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintClasses_old( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + if ( p->vFlopClasses == NULL ) + return; + Gia_ManForEachRo( p, pObj, i ) + Abc_Print( 1, "%d", Vec_IntEntry(p->vFlopClasses, i) ); + Abc_Print( 1, "\n" ); + + { + Gia_Man_t * pTemp; + pTemp = Gia_ManDupFlopClass( p, 1 ); + Gia_AigerWrite( pTemp, "dom1.aig", 0, 0, 0 ); + Gia_ManStop( pTemp ); + pTemp = Gia_ManDupFlopClass( p, 2 ); + Gia_AigerWrite( pTemp, "dom2.aig", 0, 0, 0 ); + Gia_ManStop( pTemp ); + } +} + +/**Function************************************************************* + + Synopsis [Prints stats for the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintPlacement( Gia_Man_t * p ) +{ + int i, nFixed = 0, nUndef = 0; + if ( p->pPlacement == NULL ) + return; + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + { + nFixed += p->pPlacement[i].fFixed; + nUndef += p->pPlacement[i].fUndef; + } + Abc_Print( 1, "Placement: Objects = %8d. Fixed = %8d. Undef = %8d.\n", Gia_ManObjNum(p), nFixed, nUndef ); +} + + +/**Function************************************************************* + + Synopsis [Duplicates AIG for unrolling.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintTents_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vObjs ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + Vec_IntPush( vObjs, Gia_ObjId(p, pObj) ); + if ( Gia_ObjIsCi(pObj) ) + return; + Gia_ManPrintTents_rec( p, Gia_ObjFanin0(pObj), vObjs ); + if ( Gia_ObjIsAnd(pObj) ) + Gia_ManPrintTents_rec( p, Gia_ObjFanin1(pObj), vObjs ); +} +void Gia_ManPrintTents( Gia_Man_t * p ) +{ + Vec_Int_t * vObjs; + Gia_Obj_t * pObj; + int t, i, iObjId, nSizePrev, nSizeCurr; + assert( Gia_ManPoNum(p) > 0 ); + vObjs = Vec_IntAlloc( 100 ); + // save constant class + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); + Vec_IntPush( vObjs, 0 ); + // create starting root + nSizePrev = Vec_IntSize(vObjs); + Gia_ManForEachPo( p, pObj, i ) + Gia_ManPrintTents_rec( p, pObj, vObjs ); + // build tents + Abc_Print( 1, "Tents: " ); + for ( t = 1; nSizePrev < Vec_IntSize(vObjs); t++ ) + { + int nPis = 0; + nSizeCurr = Vec_IntSize(vObjs); + Vec_IntForEachEntryStartStop( vObjs, iObjId, i, nSizePrev, nSizeCurr ) + { + nPis += Gia_ObjIsPi(p, Gia_ManObj(p, iObjId)); + if ( Gia_ObjIsRo(p, Gia_ManObj(p, iObjId)) ) + Gia_ManPrintTents_rec( p, Gia_ObjRoToRi(p, Gia_ManObj(p, iObjId)), vObjs ); + } + Abc_Print( 1, "%d=%d(%d) ", t, nSizeCurr - nSizePrev, nPis ); + nSizePrev = nSizeCurr; + } + Abc_Print( 1, " Unused=%d\n", Gia_ManObjNum(p) - Vec_IntSize(vObjs) ); + Vec_IntFree( vObjs ); + // the remaining objects are PIs without fanout +// Gia_ManForEachObj( p, pObj, i ) +// if ( !Gia_ObjIsTravIdCurrent(p, pObj) ) +// Gia_ObjPrint( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintInitClasses( Vec_Int_t * vInits ) +{ + int i, Value; + int Counts[6] = {0}; + Vec_IntForEachEntry( vInits, Value, i ) + Counts[Value]++; + for ( i = 0; i < 6; i++ ) + if ( Counts[i] ) + printf( "%d = %d ", i, Counts[i] ); + printf( " " ); + printf( "B = %d ", Counts[0] + Counts[1] ); + printf( "X = %d ", Counts[2] + Counts[3] ); + printf( "Q = %d\n", Counts[4] + Counts[5] ); + Vec_IntForEachEntry( vInits, Value, i ) + { + Counts[Value]++; + if ( Value == 0 ) + printf( "0" ); + else if ( Value == 1 ) + printf( "1" ); + else if ( Value == 2 ) + printf( "2" ); + else if ( Value == 3 ) + printf( "3" ); + else if ( Value == 4 ) + printf( "4" ); + else if ( Value == 5 ) + printf( "5" ); + else assert( 0 ); + } + printf( "\n" ); + +} + +/**Function************************************************************* + + Synopsis [Prints stats for the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintChoiceStats( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, nEquivs = 0, nChoices = 0; + Gia_ManMarkFanoutDrivers( p ); + Gia_ManForEachAnd( p, pObj, i ) + { + if ( !Gia_ObjSibl(p, i) ) + continue; + nEquivs++; + if ( pObj->fMark0 ) + nChoices++; + assert( !Gia_ObjSiblObj(p, i)->fMark0 ); + assert( Gia_ObjIsAnd(Gia_ObjSiblObj(p, i)) ); + } + Abc_Print( 1, "Choice stats: Equivs =%7d. Choices =%7d.\n", nEquivs, nChoices ); + Gia_ManCleanMark0( p ); +} + + +/**Function************************************************************* + + Synopsis [Prints stats for the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManPrintEdges( Gia_Man_t * p ) +{ + printf( "Edges (Q=2) : " ); + printf( "edge =%8d ", (Vec_IntCountPositive(p->vEdge1) + Vec_IntCountPositive(p->vEdge2))/2 ); + printf( "lev =%5.1f", 0.1*Gia_ManEvalEdgeDelay(p) ); + printf( "\n" ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Prints stats for the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +/* +void Gia_ManLogAigStats( Gia_Man_t * p, char * pDumpFile ) +{ + FILE * pTable = fopen( pDumpFile, "wb" ); + fprintf( pTable, "Name = %24s ", p->pName ); + fprintf( pTable, "In = %6d ", Gia_ManCiNum(p) ); + fprintf( pTable, "Out = %6d ", Gia_ManCoNum(p) ); + fprintf( pTable, "And = %8d ", Gia_ManAndNum(p) ); + fprintf( pTable, "Lev = %6d", Gia_ManLevelNum(p) ); + fprintf( pTable, "\n" ); + fclose( pTable ); +} +*/ +void Gia_ManLogAigStats( Gia_Man_t * p, char * pDumpFile ) +{ + FILE * pTable = fopen( pDumpFile, "wb" ); + fprintf( pTable, "{\n" ); + fprintf( pTable, " \"name\" : \"%s\",\n", p->pName ); + fprintf( pTable, " \"input\" : %d,\n", Gia_ManCiNum(p) ); + fprintf( pTable, " \"output\" : %d,\n", Gia_ManCoNum(p) ); + fprintf( pTable, " \"and\" : %d,\n", Gia_ManAndNum(p) ); + fprintf( pTable, " \"level\" : %d\n", Gia_ManLevelNum(p) ); + fprintf( pTable, "}\n" ); + fclose( pTable ); +} + +/**Function************************************************************* + + Synopsis [Prints stats for the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintStats( Gia_Man_t * p, Gps_Par_t * pPars ) +{ + extern float Gia_ManLevelAve( Gia_Man_t * p ); + int fHaveLevels = p->vLevels != NULL; + if ( pPars && pPars->fMiter ) + { + Gia_ManPrintStatsMiter( p, 0 ); + return; + } + if ( pPars && pPars->fNoColor ) + { + if ( p->pName ) + Abc_Print( 1, "%-8s : ", p->pName ); + } + else + { +#ifdef WIN32 + SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 15 ); // bright + if ( p->pName ) + Abc_Print( 1, "%-8s : ", p->pName ); + SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), 7 ); // normal +#else + if ( p->pName ) + Abc_Print( 1, "%s%-8s%s : ", "\033[1;37m", p->pName, "\033[0m" ); // bright +#endif + } + Abc_Print( 1, "i/o =%7d/%7d", + Gia_ManPiNum(p) - Gia_ManBoxCiNum(p) - Gia_ManRegBoxNum(p), + Gia_ManPoNum(p) - Gia_ManBoxCoNum(p) - Gia_ManRegBoxNum(p) ); + if ( Gia_ManConstrNum(p) ) + Abc_Print( 1, "(c=%d)", Gia_ManConstrNum(p) ); + if ( Gia_ManRegNum(p) ) + Abc_Print( 1, " ff =%7d", Gia_ManRegNum(p) ); + if ( Gia_ManRegBoxNum(p) ) + Abc_Print( 1, " boxff =%d(%d)", Gia_ManRegBoxNum(p), Gia_ManClockDomainNum(p) ); + if ( pPars && pPars->fNoColor ) + { + Abc_Print( 1, " %s =%8d", p->pMuxes? "nod" : "and", Gia_ManAndNum(p) ); + Abc_Print( 1, " lev =%5d", Gia_ManLevelNum(p) ); + Abc_Print( 1, " (%.2f)", Gia_ManLevelAve(p) ); + } + else + { +#ifdef WIN32 + { + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + SetConsoleTextAttribute( hConsole, 11 ); // blue + Abc_Print( 1, " %s =%8d", p->pMuxes? "nod" : "and", Gia_ManAndNum(p) ); + SetConsoleTextAttribute( hConsole, 13 ); // magenta + Abc_Print( 1, " lev =%5d", Gia_ManLevelNum(p) ); + Abc_Print( 1, " (%7.2f)", Gia_ManLevelAve(p) ); + SetConsoleTextAttribute( hConsole, 7 ); // normal + } +#else + Abc_Print( 1, " %s%s =%8d%s", "\033[1;36m", p->pMuxes? "nod" : "and", Gia_ManAndNum(p), "\033[0m" ); // blue + Abc_Print( 1, " %slev =%5d%s", "\033[1;35m", Gia_ManLevelNum(p), "\033[0m" ); // magenta + Abc_Print( 1, " %s(%.2f)%s", "\033[1;35m", Gia_ManLevelAve(p), "\033[0m" ); +#endif + } + if ( !fHaveLevels ) + Vec_IntFreeP( &p->vLevels ); + if ( pPars && pPars->fCut ) + Abc_Print( 1, " cut = %d(%d)", Gia_ManCrossCut(p, 0), Gia_ManCrossCut(p, 1) ); + Abc_Print( 1, " mem =%5.2f MB", Gia_ManMemory(p)/(1<<20) ); + if ( Gia_ManHasChoices(p) ) + Abc_Print( 1, " ch =%5d", Gia_ManChoiceNum(p) ); + if ( p->pManTime ) + Abc_Print( 1, " box = %d", Gia_ManNonRegBoxNum(p) ); + if ( p->pManTime ) + Abc_Print( 1, " bb = %d", Gia_ManBlackBoxNum(p) ); + if ( Gia_ManBufNum(p) ) + Abc_Print( 1, " buf = %d", Gia_ManBufNum(p) ); + if ( Gia_ManXorNum(p) && p->pMuxes == NULL ) + Abc_Print( 1, " xor = %d", Gia_ManXorNum(p) ); + if ( pPars && pPars->fMuxXor ) + printf( "\nXOR/MUX " ), Gia_ManPrintMuxStats( p ); + if ( pPars && pPars->fSwitch ) + { + static int nPiPo = 0; + static float PrevSwiTotal = 0; + float SwiTotal = Gia_ManComputeSwitching( p, 48, 16, 0 ); + Abc_Print( 1, " power =%8.1f", SwiTotal ); + if ( PrevSwiTotal > 0 && nPiPo == Gia_ManCiNum(p) + Gia_ManCoNum(p) ) + Abc_Print( 1, " %6.2f %%", 100.0*(PrevSwiTotal-SwiTotal)/PrevSwiTotal ); + else if ( PrevSwiTotal == 0 || nPiPo != Gia_ManCiNum(p) + Gia_ManCoNum(p) ) + PrevSwiTotal = SwiTotal, nPiPo = Gia_ManCiNum(p) + Gia_ManCoNum(p); + } +// Abc_Print( 1, "obj =%5d ", Gia_ManObjNum(p) ); + Abc_Print( 1, "\n" ); + +// Gia_ManSatExperiment( p ); + if ( p->pReprs && p->pNexts ) + Gia_ManEquivPrintClasses( p, 0, 0.0 ); + if ( Gia_ManHasMapping(p) && (pPars == NULL || !pPars->fSkipMap) ) + Gia_ManPrintMappingStats( p, pPars ? pPars->pDumpFile : NULL ); + else if ( pPars && pPars->pDumpFile ) + Gia_ManLogAigStats( p, pPars->pDumpFile ); + if ( pPars && pPars->fNpn && Gia_ManHasMapping(p) ) + Gia_ManPrintNpnClasses( p ); + if ( p->vPacking ) + Gia_ManPrintPackingStats( p ); + if ( p->vEdge1 ) + Gia_ManPrintEdges( p ); + if ( pPars && pPars->fLutProf && Gia_ManHasMapping(p) ) + Gia_ManPrintLutStats( p ); + if ( p->pPlacement ) + Gia_ManPrintPlacement( p ); +// if ( p->pManTime ) +// Tim_ManPrintStats( (Tim_Man_t *)p->pManTime, p->nAnd2Delay ); + Gia_ManPrintFlopClasses( p ); + Gia_ManPrintGateClasses( p ); + Gia_ManPrintObjClasses( p ); +// if ( p->vRegClasses ) +// { +// printf( "The design has %d flops with the following class info: ", Vec_IntSize(p->vRegClasses) ); +// Vec_IntPrint( p->vRegClasses ); +// } + if ( p->vInitClasses ) + Gia_ManPrintInitClasses( p->vInitClasses ); + // check integrity of boxes + Gia_ManCheckIntegrityWithBoxes( p ); +/* + if ( Gia_ManRegBoxNum(p) ) + { + int i, Limit = Vec_IntFindMax(p->vRegClasses); + for ( i = 1; i <= Limit; i++ ) + printf( "%d ", Vec_IntCountEntry(p->vRegClasses, i) ); + printf( "\n" ); + } +*/ + if ( pPars && pPars->fTents ) + { +/* + int k, Entry, Prev = 1; + Vec_Int_t * vLimit = Vec_IntAlloc( 1000 ); + Gia_Man_t * pNew = Gia_ManUnrollDup( p, vLimit ); + Abc_Print( 1, "Tents: " ); + Vec_IntForEachEntryStart( vLimit, Entry, k, 1 ) + Abc_Print( 1, "%d=%d ", k, Entry-Prev ), Prev = Entry; + Abc_Print( 1, " Unused=%d.", Gia_ManObjNum(p) - Gia_ManObjNum(pNew) ); + Abc_Print( 1, "\n" ); + Vec_IntFree( vLimit ); + Gia_ManStop( pNew ); +*/ + Gia_ManPrintTents( p ); + } + if ( pPars && pPars->fSlacks ) + Gia_ManDfsSlacksPrint( p ); +} + +/**Function************************************************************* + + Synopsis [Prints stats for the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintStatsShort( Gia_Man_t * p ) +{ + Abc_Print( 1, "i/o =%7d/%7d ", Gia_ManPiNum(p), Gia_ManPoNum(p) ); + Abc_Print( 1, "ff =%7d ", Gia_ManRegNum(p) ); + Abc_Print( 1, "and =%8d ", Gia_ManAndNum(p) ); + Abc_Print( 1, "lev =%5d ", Gia_ManLevelNum(p) ); +// Abc_Print( 1, "mem =%5.2f MB", 12.0*Gia_ManObjNum(p)/(1<<20) ); + Abc_Print( 1, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints stats for the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintMiterStatus( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj, * pChild; + int i, nSat = 0, nUnsat = 0, nUndec = 0, iOut = -1; + Gia_ManForEachPo( p, pObj, i ) + { + pChild = Gia_ObjChild0(pObj); + // check if the output is constant 0 + if ( pChild == Gia_ManConst0(p) ) + nUnsat++; + // check if the output is constant 1 + else if ( pChild == Gia_ManConst1(p) ) + { + nSat++; + if ( iOut == -1 ) + iOut = i; + } + // check if the output is a primary input + else if ( Gia_ObjIsPi(p, Gia_Regular(pChild)) ) + { + nSat++; + if ( iOut == -1 ) + iOut = i; + } +/* + // check if the output is 1 for the 0000 pattern + else if ( Gia_Regular(pChild)->fPhase != (unsigned)Gia_IsComplement(pChild) ) + { + nSat++; + if ( iOut == -1 ) + iOut = i; + } +*/ + else + nUndec++; + } + Abc_Print( 1, "Outputs = %7d. Unsat = %7d. Sat = %7d. Undec = %7d.\n", + Gia_ManPoNum(p), nUnsat, nSat, nUndec ); +} + +/**Function************************************************************* + + Synopsis [Statistics of the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintStatsMiter( Gia_Man_t * p, int fVerbose ) +{ + Gia_Obj_t * pObj; + Vec_Flt_t * vProb; + int i, iObjId; + Gia_ManLevelNum( p ); + Gia_ManCreateRefs( p ); + vProb = Gia_ManPrintOutputProb( p ); + printf( "Statistics for each outputs of the miter:\n" ); + Gia_ManForEachPo( p, pObj, i ) + { + iObjId = Gia_ObjId(p, pObj); + printf( "%4d : ", i ); + printf( "Level = %5d ", Gia_ObjLevelId(p, iObjId) ); + printf( "Supp = %5d ", Gia_ManSuppSize(p, &iObjId, 1) ); + printf( "Cone = %5d ", Gia_ManConeSize(p, &iObjId, 1) ); + printf( "Mffc = %5d ", Gia_NodeMffcSize(p, Gia_ObjFanin0(pObj)) ); + printf( "Prob = %8.4f ", Vec_FltEntry(vProb, iObjId) ); + printf( "\n" ); + } + Vec_FltFree( vProb ); +} + +/**Function************************************************************* + + Synopsis [Prints stats for the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSetRegNum( Gia_Man_t * p, int nRegs ) +{ + assert( p->nRegs == 0 ); + p->nRegs = nRegs; +} + + +/**Function************************************************************* + + Synopsis [Reports the reduction of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManReportImprovement( Gia_Man_t * p, Gia_Man_t * pNew ) +{ + Abc_Print( 1, "REG: Beg = %5d. End = %5d. (R =%5.1f %%) ", + Gia_ManRegNum(p), Gia_ManRegNum(pNew), + Gia_ManRegNum(p)? 100.0*(Gia_ManRegNum(p)-Gia_ManRegNum(pNew))/Gia_ManRegNum(p) : 0.0 ); + Abc_Print( 1, "AND: Beg = %6d. End = %6d. (R =%5.1f %%)", + Gia_ManAndNum(p), Gia_ManAndNum(pNew), + Gia_ManAndNum(p)? 100.0*(Gia_ManAndNum(p)-Gia_ManAndNum(pNew))/Gia_ManAndNum(p) : 0.0 ); + Abc_Print( 1, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Prints NPN class statistics.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintNpnClasses( Gia_Man_t * p ) +{ + extern char ** Kit_DsdNpn4ClassNames(); + char ** pNames = Kit_DsdNpn4ClassNames(); + Vec_Int_t * vLeaves, * vTruth, * vVisited; + int * pLutClass, ClassCounts[222] = {0}; + int i, k, iFan, Class, OtherClasses, OtherClasses2, nTotal, Counter, Counter2; + unsigned * pTruth; int nLutSize = 0; + assert( Gia_ManHasMapping(p) ); + //assert( Gia_ManLutSizeMax( p ) <= 4 ); + vLeaves = Vec_IntAlloc( 100 ); + vVisited = Vec_IntAlloc( 100 ); + vTruth = Vec_IntAlloc( (1<<16) ); + pLutClass = ABC_CALLOC( int, Gia_ManObjNum(p) ); + Gia_ManCleanTruth( p ); + Gia_ManForEachLut( p, i ) + { + nLutSize = Abc_MaxInt( nLutSize, Gia_ObjLutSize(p,i) ); + if ( Gia_ObjLutSize(p,i) > 4 ) + continue; + Vec_IntClear( vLeaves ); + Gia_LutForEachFanin( p, i, iFan, k ) + Vec_IntPush( vLeaves, iFan ); + for ( ; k < 4; k++ ) + Vec_IntPush( vLeaves, 0 ); + pTruth = Gia_ManConvertAigToTruth( p, Gia_ManObj(p, i), vLeaves, vTruth, vVisited ); + Class = Dar_LibReturnClass( *pTruth ); + ClassCounts[ Class ]++; + pLutClass[i] = Class; + } + Vec_IntFree( vLeaves ); + Vec_IntFree( vTruth ); + Vec_IntFree( vVisited ); + Vec_IntFreeP( &p->vTruths ); + nTotal = 0; + for ( i = 0; i < 222; i++ ) + nTotal += ClassCounts[i]; + Abc_Print( 1, "NPN CLASS STATISTICS (for %d LUT4 present in the current mapping):\n", nTotal ); + OtherClasses = 0; + for ( i = k = 0; i < 222; i++ ) + { + if ( ClassCounts[i] == 0 ) + continue; +// if ( 100.0 * ClassCounts[i] / (nTotal+1) < 0.1 ) // do not show anything below 0.1 percent +// continue; + OtherClasses += ClassCounts[i]; + Abc_Print( 1, "%3d: Class %3d : Count = %6d (%7.2f %%) %s\n", + ++k, i, ClassCounts[i], 100.0 * ClassCounts[i] / (nTotal+1), pNames[i] ); + } + OtherClasses = nTotal - OtherClasses; + Abc_Print( 1, "Other : Count = %6d (%7.2f %%)\n", + OtherClasses, 100.0 * OtherClasses / (nTotal+1) ); + // count the number of LUTs that have MUX function and two fanins with MUX functions + OtherClasses = OtherClasses2 = 0; + ABC_FREE( p->pRefs ); + Gia_ManSetRefsMapped( p ); + Gia_ManForEachLut( p, i ) + { + if ( pLutClass[i] != 109 ) + continue; + Counter = Counter2 = 0; + Gia_LutForEachFanin( p, i, iFan, k ) + { + Counter += (pLutClass[iFan] == 109); + Counter2 += (pLutClass[iFan] == 109) && (Gia_ObjRefNumId(p, iFan) == 1); + } + OtherClasses += (Counter > 1); + OtherClasses2 += (Counter2 > 1); +// Abc_Print( 1, "%d -- ", pLutClass[i] ); +// Gia_LutForEachFanin( p, i, iFan, k ) +// Abc_Print( 1, "%d ", pLutClass[iFan] ); +// Abc_Print( 1, "\n" ); + } + ABC_FREE( p->pRefs ); + Abc_Print( 1, "Approximate number of 4:1 MUX structures: All = %6d (%7.2f %%) MFFC = %6d (%7.2f %%)\n", + OtherClasses, 100.0 * OtherClasses / (nTotal+1), + OtherClasses2, 100.0 * OtherClasses2 / (nTotal+1) ); + // print information about LUT pairs + if ( nLutSize <= 4 ) + { + int nTopPairs = 100, nTopShow = 30; + int i, j, k, iFan, * pVec = NULL; + Vec_Int_t * vPairs = Vec_IntAlloc( 3 * nTopPairs ); + Gia_ManForEachLut( p, j ) { + Gia_LutForEachFanin( p, j, iFan, k ) { + int Num1 = pLutClass[iFan]; + int Num2 = pLutClass[j]; + assert( Vec_IntSize(vPairs) % 3 == 0 ); + for ( i = 0; i < Vec_IntSize(vPairs); i += 3 ) + if ( Vec_IntEntry(vPairs, i+0) == Num1 && Vec_IntEntry(vPairs, i+1) == Num2 ) + break; + if ( i == Vec_IntSize(vPairs) ) { + if ( Vec_IntSize(vPairs) < 3*nTopPairs ) { + Vec_IntPush( vPairs, Num1 ); + Vec_IntPush( vPairs, Num2 ); + Vec_IntPush( vPairs, 1 ); + } + continue; + } + // found this pair + assert( Vec_IntEntry(vPairs, i+0) == Num1 ); + assert( Vec_IntEntry(vPairs, i+1) == Num2 ); + Vec_IntAddToEntry( vPairs, i+2, 1 ); + // sort + pVec = Vec_IntArray( vPairs ); + while ( i > 0 && pVec[i+2] > pVec[i-1] ) { + ABC_SWAP( int, pVec[i+0], pVec[i-3] ) + ABC_SWAP( int, pVec[i+1], pVec[i-2] ) + ABC_SWAP( int, pVec[i+2], pVec[i-1] ) + i -= 3; + } + while ( i < Vec_IntSize(vPairs) - 3 && pVec[i+2] < pVec[i+5] ) { + ABC_SWAP( int, pVec[i+0], pVec[i+3] ) + ABC_SWAP( int, pVec[i+1], pVec[i+4] ) + ABC_SWAP( int, pVec[i+2], pVec[i+5] ) + i += 3; + assert( 0 ); + } + } + } + pVec = Vec_IntArray( vPairs ); + nTopShow = Abc_MinInt( nTopShow, Vec_IntSize(vPairs)/3 ); + for ( i = 0; i < 3*nTopShow; i += 3 ) + printf( "%3d : (%3d %3d) x %3d\n", i/3, pVec[i+0], pVec[i+1], pVec[i+2] ); + Vec_IntFree( vPairs ); + } + ABC_FREE( pLutClass ); +} + + +/**Function************************************************************* + + Synopsis [Collects internal nodes and boxes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDfsCollect_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vObjs ) +{ + if ( Gia_ObjIsTravIdCurrent( p, pObj ) ) + return; + Gia_ObjSetTravIdCurrent( p, pObj ); + if ( Gia_ObjIsCi(pObj) ) + { + Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; + if ( pManTime ) + { + int i, iFirst, nTerms, iBox; + iBox = Tim_ManBoxForCi( pManTime, Gia_ObjCioId(pObj) ); + if ( iBox >= 0 ) // pObj is a box input + { + // mark box outputs + iFirst = Tim_ManBoxOutputFirst( pManTime, iBox ); + nTerms = Tim_ManBoxOutputNum( pManTime, iBox ); + for ( i = 0; i < nTerms; i++ ) + { + pObj = Gia_ManCi( p, iFirst + i ); + Gia_ObjSetTravIdCurrent( p, pObj ); + } + // traverse box inputs + iFirst = Tim_ManBoxInputFirst( pManTime, iBox ); + nTerms = Tim_ManBoxInputNum( pManTime, iBox ); + for ( i = 0; i < nTerms; i++ ) + { + pObj = Gia_ManCo( p, iFirst + i ); + Gia_ManDfsCollect_rec( p, pObj, vObjs ); + } + // save the box + Vec_IntPush( vObjs, -iBox-1 ); + } + } + return; + } + else if ( Gia_ObjIsCo(pObj) ) + { + Gia_ManDfsCollect_rec( p, Gia_ObjFanin0(pObj), vObjs ); + } + else if ( Gia_ObjIsAnd(pObj) ) + { + int iFan, k, iObj = Gia_ObjId(p, pObj); + if ( Gia_ManHasMapping(p) ) + { + assert( Gia_ObjIsLut(p, iObj) ); + Gia_LutForEachFanin( p, iObj, iFan, k ) + Gia_ManDfsCollect_rec( p, Gia_ManObj(p, iFan), vObjs ); + } + else + { + Gia_ManDfsCollect_rec( p, Gia_ObjFanin0(pObj), vObjs ); + Gia_ManDfsCollect_rec( p, Gia_ObjFanin1(pObj), vObjs ); + } + // save the object + Vec_IntPush( vObjs, iObj ); + } + else if ( !Gia_ObjIsConst0(pObj) ) + assert( 0 ); +} +Vec_Int_t * Gia_ManDfsCollect( Gia_Man_t * p ) +{ + Vec_Int_t * vObjs = Vec_IntAlloc( Gia_ManObjNum(p) ); + Gia_Obj_t * pObj; int i; + Gia_ManIncrementTravId( p ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManDfsCollect_rec( p, pObj, vObjs ); + Gia_ManForEachCi( p, pObj, i ) + Gia_ManDfsCollect_rec( p, pObj, vObjs ); + return vObjs; +} + +/**Function************************************************************* + + Synopsis [Compute arrival/required times.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManDfsArrivals( Gia_Man_t * p, Vec_Int_t * vObjs ) +{ + Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; + Vec_Int_t * vTimes = Vec_IntStartFull( Gia_ManObjNum(p) ); + Gia_Obj_t * pObj; int j, Entry, k, iFan; + Vec_IntWriteEntry( vTimes, 0, 0 ); + if ( pManTime ) + { + Tim_ManIncrementTravId( pManTime ); + Gia_ManForEachCi( p, pObj, j ) + if ( j < Tim_ManPiNum(pManTime) ) + { + float arrTime = Tim_ManGetCiArrival( pManTime, j ); + Vec_IntWriteEntry( vTimes, Gia_ObjId(p, pObj), (int)arrTime ); + } + } + else + { + Gia_ManForEachCi( p, pObj, j ) + Vec_IntWriteEntry( vTimes, Gia_ObjId(p, pObj), 0 ); + } + Vec_IntForEachEntry( vObjs, Entry, j ) + { + if ( Entry < 0 ) // box + { + int Time0, iFirst, nTerms, iBox = -Entry-1; + assert( iBox >= 0 ); + // set arrivals for box inputs + iFirst = Tim_ManBoxInputFirst( pManTime, iBox ); + nTerms = Tim_ManBoxInputNum( pManTime, iBox ); + for ( k = 0; k < nTerms; k++ ) + { + pObj = Gia_ManCo( p, iFirst + k ); + Time0 = Vec_IntEntry( vTimes, Gia_ObjFaninId0p(p, pObj) ); + assert( Time0 >= 0 ); + Tim_ManSetCoArrival( pManTime, Gia_ObjCioId(pObj), Time0 ); + } + // derive arrivals for box outputs + iFirst = Tim_ManBoxOutputFirst( pManTime, iBox ); + nTerms = Tim_ManBoxOutputNum( pManTime, iBox ); + for ( k = 0; k < nTerms; k++ ) + { + pObj = Gia_ManCi( p, iFirst + k ); + Time0 = Tim_ManGetCiArrival( pManTime, Gia_ObjCioId(pObj) ); + assert( Time0 >= 0 ); + Vec_IntWriteEntry( vTimes, Gia_ObjId(p, pObj), Time0 ); + } + } + else if ( Entry > 0 ) // node + { + int Time0, Time1, TimeMax = 0; + if ( Gia_ManHasMapping(p) ) + { + assert( Gia_ObjIsLut(p, Entry) ); + Gia_LutForEachFanin( p, Entry, iFan, k ) + { + Time0 = Vec_IntEntry( vTimes, iFan ); + assert( Time0 >= 0 ); + TimeMax = Abc_MaxInt( TimeMax, Time0 ); + } + } + else + { + pObj = Gia_ManObj( p, Entry ); + Time0 = Vec_IntEntry( vTimes, Gia_ObjFaninId0(pObj, Entry) ); + Time1 = Vec_IntEntry( vTimes, Gia_ObjFaninId1(pObj, Entry) ); + assert( Time0 >= 0 && Time1 >= 0 ); + TimeMax = Abc_MaxInt( Time0, Time1 ); + } + Vec_IntWriteEntry( vTimes, Entry, TimeMax + 10 ); + } + else assert( 0 ); + } + return vTimes; +} +static inline void Gia_ManDfsUpdateRequired( Vec_Int_t * vTimes, int iObj, int Req ) +{ + int *pTime = Vec_IntEntryP( vTimes, iObj ); + if (*pTime == -1 || *pTime > Req) + *pTime = Req; +} +Vec_Int_t * Gia_ManDfsRequireds( Gia_Man_t * p, Vec_Int_t * vObjs, int ReqTime ) +{ + Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; + Vec_Int_t * vTimes = Vec_IntStartFull( Gia_ManObjNum(p) ); + Gia_Obj_t * pObj; + int j, Entry, k, iFan, Req; + Vec_IntWriteEntry( vTimes, 0, 0 ); + if ( pManTime ) + { + int nCoLimit = Gia_ManCoNum(p) - Tim_ManPoNum(pManTime); + Tim_ManIncrementTravId( pManTime ); + //Tim_ManInitPoRequiredAll( pManTime, (float)ReqTime ); + Gia_ManForEachCo( p, pObj, j ) + if ( j >= nCoLimit ) + { + Tim_ManSetCoRequired( pManTime, j, ReqTime ); + Gia_ManDfsUpdateRequired( vTimes, Gia_ObjFaninId0p(p, pObj), ReqTime ); + } + } + else + { + Gia_ManForEachCo( p, pObj, j ) + Gia_ManDfsUpdateRequired( vTimes, Gia_ObjFaninId0p(p, pObj), ReqTime ); + } + Vec_IntForEachEntryReverse( vObjs, Entry, j ) + { + if ( Entry < 0 ) // box + { + int iFirst, nTerms, iBox = -Entry-1; + assert( iBox >= 0 ); + // set requireds for box outputs + iFirst = Tim_ManBoxOutputFirst( pManTime, iBox ); + nTerms = Tim_ManBoxOutputNum( pManTime, iBox ); + for ( k = 0; k < nTerms; k++ ) + { + pObj = Gia_ManCi( p, iFirst + k ); + Req = Vec_IntEntry( vTimes, Gia_ObjId(p, pObj) ); + Req = Req == -1 ? ReqTime : Req; // dangling box output + assert( Req >= 0 ); + Tim_ManSetCiRequired( pManTime, Gia_ObjCioId(pObj), Req ); + } + // derive requireds for box inputs + iFirst = Tim_ManBoxInputFirst( pManTime, iBox ); + nTerms = Tim_ManBoxInputNum( pManTime, iBox ); + for ( k = 0; k < nTerms; k++ ) + { + pObj = Gia_ManCo( p, iFirst + k ); + Req = Tim_ManGetCoRequired( pManTime, Gia_ObjCioId(pObj) ); + assert( Req >= 0 ); + Gia_ManDfsUpdateRequired( vTimes, Gia_ObjFaninId0p(p, pObj), Req ); + } + } + else if ( Entry > 0 ) // node + { + Req = Vec_IntEntry(vTimes, Entry) - 10; + assert( Req >= 0 ); + if ( Gia_ManHasMapping(p) ) + { + assert( Gia_ObjIsLut(p, Entry) ); + Gia_LutForEachFanin( p, Entry, iFan, k ) + Gia_ManDfsUpdateRequired( vTimes, iFan, Req ); + } + else + { + pObj = Gia_ManObj( p, Entry ); + Gia_ManDfsUpdateRequired( vTimes, Gia_ObjFaninId0(pObj, Entry), Req ); + Gia_ManDfsUpdateRequired( vTimes, Gia_ObjFaninId1(pObj, Entry), Req ); + } + } + else assert( 0 ); + } + return vTimes; +} +Vec_Int_t * Gia_ManDfsSlacks( Gia_Man_t * p ) +{ + Vec_Int_t * vSlack = Vec_IntStartFull( Gia_ManObjNum(p) ); + Vec_Int_t * vObjs = Gia_ManDfsCollect( p ); + if ( Vec_IntSize(vObjs) > 0 ) + { + Vec_Int_t * vArrs = Gia_ManDfsArrivals( p, vObjs ); + int Required = Vec_IntFindMax( vArrs ); + Vec_Int_t * vReqs = Gia_ManDfsRequireds( p, vObjs, Required ); + int i, Arr, Req, Arrivals = ABC_INFINITY; + Vec_IntForEachEntry( vReqs, Req, i ) + if ( Req != -1 ) + Arrivals = Abc_MinInt( Arrivals, Req ); + //if ( Arrivals != 0 ) + // printf( "\nGlobal timing check has failed.\n\n" ); + //assert( Arrivals == 0 ); + Vec_IntForEachEntryTwo( vArrs, vReqs, Arr, Req, i ) + { + if ( !Gia_ObjIsAnd(Gia_ManObj(p, i)) ) + continue; + if ( Gia_ManHasMapping(p) && !Gia_ObjIsLut(p, i) ) + continue; + assert( Arr <= Req ); + Vec_IntWriteEntry( vSlack, i, Req - Arr ); + } + Vec_IntFree( vArrs ); + Vec_IntFree( vReqs ); + } + Vec_IntFree( vObjs ); + return vSlack; +} +void Gia_ManDfsSlacksPrint( Gia_Man_t * p ) +{ + Vec_Int_t * vCounts, * vSlacks = Gia_ManDfsSlacks( p ); + int i, Entry, nRange, nTotal; + if ( Vec_IntSize(vSlacks) == 0 ) + { + printf( "Network contains no internal objects.\n" ); + Vec_IntFree( vSlacks ); + return; + } + // compute slacks + Vec_IntForEachEntry( vSlacks, Entry, i ) + if ( Entry != -1 ) + Vec_IntWriteEntry( vSlacks, i, Entry/10 ); + nRange = Vec_IntFindMax( vSlacks ); + // count items + vCounts = Vec_IntStart( nRange + 1 ); + Vec_IntForEachEntry( vSlacks, Entry, i ) + if ( Entry != -1 ) + Vec_IntAddToEntry( vCounts, Entry, 1 ); + // print slack ranges + nTotal = Vec_IntSum( vCounts ); + assert( nTotal > 0 ); + Vec_IntForEachEntry( vCounts, Entry, i ) + { + printf( "Slack range %3d = ", i ); + printf( "[%4d, %4d) ", 10*i, 10*(i+1) ); + printf( "Nodes = %5d ", Entry ); + printf( "(%6.2f %%) ", 100.0*Entry/nTotal ); + printf( "\n" ); + } + Vec_IntFree( vSlacks ); + Vec_IntFree( vCounts ); +} + + +/**Function************************************************************* + + Synopsis [Dump interface module] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManWriteNamesInter( FILE * pFile, char c, int n, int Start, int Skip, int nRegs, int fReverse ) +{ + int Length = Start, i, fFirst = 1; + char pName[100]; + for ( i = 0; i < n-nRegs; i++ ) + { + sprintf( pName, "%c[%d]", c, i ); + Length += strlen(pName) + 2; + if ( Length > 60 ) + { + fprintf( pFile, ",\n " ); + Length = Skip; + fFirst = 1; + } + fprintf( pFile, "%s%s", fFirst ? "":", ", pName ); + fFirst = 0; + } + for ( i = n-nRegs; i < n; i++ ) + { + sprintf( pName, "%c%c[%d]", c, c, i ); + Length += strlen(pName) + 2; + if ( Length > 60 ) + { + fprintf( pFile, ",\n " ); + Length = Skip; + fFirst = 1; + } + fprintf( pFile, "%s%s", fFirst ? "":", ", pName ); + fFirst = 0; + }} +void Gia_ManDumpModuleName( FILE * pFile, char * pName ) +{ + int i; + for ( i = 0; i < (int)strlen(pName); i++ ) + if ( isalpha(pName[i]) || isdigit(pName[i]) ) + fprintf( pFile, "%c", pName[i] ); + else + fprintf( pFile, "_" ); +} +void Gia_ManDumpInterface2( Gia_Man_t * p, FILE * pFile ) +{ + int fPrintClk = 0; + fprintf( pFile, "module " ); + Gia_ManDumpModuleName( pFile, p->pName ); + fprintf( pFile, "_wrapper" ); + fprintf( pFile, " (%s i, o );\n\n", fPrintClk && Gia_ManRegNum(p) ? " clk," : "" ); + if ( fPrintClk && Gia_ManRegNum(p) ) + fprintf( pFile, " input clk;\n" ); + fprintf( pFile, " input [%d:0] i;\n", Gia_ManPiNum(p)-1 ); + fprintf( pFile, " output [%d:0] o;\n\n", Gia_ManPoNum(p)-1 ); + + if ( Gia_ManRegNum(p) ) { + fprintf( pFile, " wire [%d:%d] ii;\n", Gia_ManCiNum(p)-1, Gia_ManPiNum(p) ); + fprintf( pFile, " wire [%d:%d] oo;\n\n", Gia_ManCoNum(p)-1, Gia_ManPoNum(p) ); + fprintf( pFile, " always @ (posedge %s)\n ii <= oo;\n\n", fPrintClk ? "clk" : "i[0]" ); + } + + fprintf( pFile, " " ); + Gia_ManDumpModuleName( pFile, p->pName ); + fprintf( pFile, " " ); + Gia_ManDumpModuleName( pFile, p->pName ); + fprintf( pFile, "_inst" ); + + fprintf( pFile, " (\n " ); + Gia_ManWriteNamesInter( pFile, 'i', Gia_ManCiNum(p), 4, 4, Gia_ManRegNum(p), 0 ); + fprintf( pFile, ",\n " ); + Gia_ManWriteNamesInter( pFile, 'o', Gia_ManCoNum(p), 4, 4, Gia_ManRegNum(p), 0 ); + fprintf( pFile, "\n );\n\n" ); + + fprintf( pFile, "endmodule\n\n" ); +} + +/**Function************************************************************* + + Synopsis [Compute arrival/required times.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Bit_t * Gia_ManGenUsed( Gia_Man_t * p, int fBuf ) +{ + Gia_Obj_t * pObj; int i; + Vec_Bit_t * vUsed = Vec_BitStart( Gia_ManObjNum(p) ); + Gia_ManForEachAnd( p, pObj, i ) + { + if ( fBuf ) + Vec_BitWriteEntry( vUsed, i, 1 ); + if ( Gia_ObjFaninC0(pObj) ^ fBuf ) + Vec_BitWriteEntry( vUsed, Gia_ObjFaninId0(pObj, i), 1 ); + if ( Gia_ObjFaninC1(pObj) ^ fBuf ) + Vec_BitWriteEntry( vUsed, Gia_ObjFaninId1(pObj, i), 1 ); + } + Gia_ManForEachCo( p, pObj, i ) + if ( Gia_ObjFaninC0(pObj) ^ fBuf ) + Vec_BitWriteEntry( vUsed, Gia_ObjFaninId0p(p, pObj), 1 ); + Vec_BitWriteEntry( vUsed, 0, 0 ); // clean zero + return vUsed; +} +int Gia_ManNameIsLegalInVerilog( char * pName ) +{ + // identifier ::= simple_identifier | escaped_identifier + // simple_identifier ::= [a-zA-Z_][a-zA-Z0-9_$] + // escaped_identifier ::= \ {Any_ASCII_character_except_white_space} white_space + // white_space ::= space | tab | newline + assert( pName != NULL && *pName != '\0' ); + if ( *pName == '\\' ) + return 1; + if ( (*pName < 'a' || *pName > 'z') && (*pName < 'A' || *pName > 'Z') && *pName != '_' ) + return 0; + while ( *(++pName) ) + if ( (*pName < 'a' || *pName > 'z') && (*pName < 'A' || *pName > 'Z') && (*pName < '0' || *pName > '9') && *pName != '_' && *pName != '$' ) + return 0; + return 1; +} +char * Gia_ObjGetDumpName( Vec_Ptr_t * vNames, char c, int i, int d ) +{ + static char pBuffer[10000]; + if ( vNames ) + { + char * pName = (char *)Vec_PtrEntry(vNames, i); + if ( Gia_ManNameIsLegalInVerilog(pName) ) + sprintf( pBuffer, "%s", pName ); + else + sprintf( pBuffer, "\\%s ", pName ); + } + else + sprintf( pBuffer, "%c%0*d%c", c, d, i, c ); + return pBuffer; +} +void Gia_ManWriteNames( FILE * pFile, char c, int n, Vec_Ptr_t * vNames, int Start, int Skip, Vec_Bit_t * vObjs, int fReverse ) +{ + int Digits = Abc_Base10Log( n ); + int Length = Start, i, fFirst = 1; + char * pName; + for ( i = 0; i < n; i++ ) + { + int k = fReverse ? n-1-i : i; + if ( vObjs && !Vec_BitEntry(vObjs, k) ) + continue; + pName = Gia_ObjGetDumpName( vNames, c, k, Digits ); + Length += strlen(pName) + 2; + if ( Length > 60 ) + { + fprintf( pFile, ",\n " ); + Length = Skip; + fFirst = 1; + } + fprintf( pFile, "%s%s", fFirst ? "":", ", pName ); + fFirst = 0; + } +} +void Gia_ManDumpVerilog( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter, int fInterComb, int fAssign, int fReverse ) +{ + if ( fInterComb ) + { + if ( fAssign ) { + extern void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName ); + Gia_ManDumpInterfaceAssign( p, pFileName ); + } + else { + extern void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName ); + Gia_ManDumpInterface( p, pFileName ); + } + } + else + { + if ( fAssign ) { + extern void Gia_ManDumpVerilogNoInterAssign( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter ); + Gia_ManDumpVerilogNoInterAssign( p, pFileName, vObjs, fVerBufs, fInter ); + } + else { + extern void Gia_ManDumpVerilogNoInter( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter ); + Gia_ManDumpVerilogNoInter( p, pFileName, vObjs, fVerBufs, fInter ); + } + } +} +void Gia_ManDumpVerilogNoInter( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter ) +{ + Gia_Obj_t * pObj; + Vec_Bit_t * vInvs, * vUsed; + int nDigits = Abc_Base10Log( Gia_ManObjNum(p) ); + int nDigitsI = Abc_Base10Log( Gia_ManPiNum(p) ); + int nDigitsO = Abc_Base10Log( Gia_ManPoNum(p) ); + int i, k, iObj, nRegs = Gia_ManRegNum(p); + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open output file \"%s\".\n", pFileName ); + return; + } + + if ( fInter || nRegs ) + Gia_ManDumpInterface2( p, pFile ); + //Gia_ManSetRegNum( p, 0 ); + p->nRegs = 0; + + vInvs = Gia_ManGenUsed( p, 0 ); + vUsed = Gia_ManGenUsed( p, 1 ); + + //fprintf( pFile, "// This Verilog file is written by ABC on %s\n\n", Extra_TimeStamp() ); + + fprintf( pFile, "module " ); + Gia_ManDumpModuleName( pFile, p->pName ); + + if ( fVerBufs ) + { + fprintf( pFile, " (\n " ); + Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 4, 4, NULL, 0 ); + fprintf( pFile, ",\n " ); + + Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 4, 4, NULL, 0 ); + fprintf( pFile, "\n );\n\n" ); + + fprintf( pFile, " input " ); + Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 8, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " output " ); + Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 9, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + + Gia_ManForEachPi( p, pObj, i ) + { + fprintf( pFile, " buf ( %s,", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(NULL, 'a', i, nDigitsI) ); + } + fprintf( pFile, "\n" ); + + Gia_ManForEachPo( p, pObj, i ) + { + fprintf( pFile, " buf ( %s,", Gia_ObjGetDumpName(NULL, 'y', i, nDigitsO) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigitsO) ); + } + fprintf( pFile, "\n" ); + } + else + { + fprintf( pFile, " (\n " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 4, 4, NULL, 0 ); + fprintf( pFile, ",\n " ); + + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 4, 4, NULL, 0 ); + fprintf( pFile, "\n );\n\n" ); + + fprintf( pFile, " input " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " output " ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + } + + if ( Vec_BitCount(vUsed) ) + { + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed, 0 ); + fprintf( pFile, ";\n\n" ); + } + + if ( Vec_BitCount(vInvs) ) + { + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs, 0 ); + fprintf( pFile, ";\n\n" ); + } + + if ( vObjs ) + { + fprintf( pFile, " wire " ); + Vec_IntForEachEntry( vObjs, iObj, i ) + fprintf( pFile, " t_%d%s", i, i==Vec_IntSize(vObjs)-1 ? "" : "," ); + fprintf( pFile, ";\n\n" ); + Vec_IntForEachEntry( vObjs, iObj, i ) + { + fprintf( pFile, " buf ( %s,", Gia_ObjGetDumpName(NULL, 'n', iObj, nDigits) ); + fprintf( pFile, " t_%d );\n", i ); + } + fprintf( pFile, "\n" ); + } + + // input inverters + Gia_ManForEachPi( p, pObj, i ) + { + if ( Vec_BitEntry(vUsed, Gia_ObjId(p, pObj)) ) + { + fprintf( pFile, " buf ( %s,", Gia_ObjGetDumpName(NULL, 'n', Gia_ObjId(p, pObj), nDigits) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + } + if ( Vec_BitEntry(vInvs, Gia_ObjId(p, pObj)) ) + { + fprintf( pFile, " not ( %s,", Gia_ObjGetDumpName(NULL, 'i', Gia_ObjId(p, pObj), nDigits) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + } + } + + // internal nodes and their inverters + fprintf( pFile, "\n" ); + Gia_ManForEachAnd( p, pObj, i ) + { + int fSkip = 0; + if ( vObjs ) + { + Vec_IntForEachEntry( vObjs, iObj, k ) + if ( iObj == i ) + break; + if ( k < Vec_IntSize(vObjs) ) + fSkip = 1; + } + if ( !fSkip ) + { + fprintf( pFile, " and ( %s,", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); + fprintf( pFile, " %s,", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0(pObj, i), nDigits) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC1(pObj)? 'i':'n'), Gia_ObjFaninId1(pObj, i), nDigits) ); + } + if ( Vec_BitEntry(vInvs, i) ) + { + fprintf( pFile, " not ( %s,", Gia_ObjGetDumpName(NULL, 'i', i, nDigits) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); + } + } + + // output drivers + fprintf( pFile, "\n" ); + Gia_ManForEachPo( p, pObj, i ) + { +/* + fprintf( pFile, " assign %s = ", Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigits2) ); + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) + fprintf( pFile, "1\'b%d;\n", Gia_ObjFaninC0(pObj) ); + else + fprintf( pFile, "%s;\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0p(p, pObj), nDigits) ); +*/ + fprintf( pFile, " buf ( %s, ", Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigitsO) ); + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) + fprintf( pFile, "1\'b%d );\n", Gia_ObjFaninC0(pObj) ); + else + fprintf( pFile, "%s );\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0p(p, pObj), nDigits) ); + } + + fprintf( pFile, "\nendmodule\n\n" ); + fclose( pFile ); + + Vec_BitFree( vInvs ); + Vec_BitFree( vUsed ); + + Gia_ManSetRegNum( p, nRegs ); +} +void Gia_ManDumpVerilogNoInterAssign( Gia_Man_t * p, char * pFileName, Vec_Int_t * vObjs, int fVerBufs, int fInter ) +{ + Gia_Obj_t * pObj; + Vec_Bit_t * vInvs, * vUsed; + int nDigits = Abc_Base10Log( Gia_ManObjNum(p) ); + int nDigitsI = Abc_Base10Log( Gia_ManPiNum(p) ); + int nDigitsO = Abc_Base10Log( Gia_ManPoNum(p) ); + int i, k, iObj, nRegs = Gia_ManRegNum(p); + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open output file \"%s\".\n", pFileName ); + return; + } + + if ( fInter || nRegs ) + Gia_ManDumpInterface2( p, pFile ); + //Gia_ManSetRegNum( p, 0 ); + p->nRegs = 0; + + vInvs = Gia_ManGenUsed( p, 0 ); + vUsed = Gia_ManGenUsed( p, 1 ); + + //fprintf( pFile, "// This Verilog file is written by ABC on %s\n\n", Extra_TimeStamp() ); + + fprintf( pFile, "module " ); + Gia_ManDumpModuleName( pFile, p->pName ); + + if ( fVerBufs ) + { + fprintf( pFile, " (\n " ); + Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 4, 4, NULL, 0 ); + fprintf( pFile, ",\n " ); + + Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 4, 4, NULL, 0 ); + fprintf( pFile, "\n );\n\n" ); + + fprintf( pFile, " input " ); + Gia_ManWriteNames( pFile, 'a', Gia_ManPiNum(p), NULL, 8, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " output " ); + Gia_ManWriteNames( pFile, 'y', Gia_ManPoNum(p), NULL, 9, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + + Gia_ManForEachPi( p, pObj, i ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + fprintf( pFile, " %s;\n", Gia_ObjGetDumpName(NULL, 'a', i, nDigitsI) ); + } + fprintf( pFile, "\n" ); + + Gia_ManForEachPo( p, pObj, i ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'y', i, nDigitsO) ); + fprintf( pFile, " %s;\n", Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigitsO) ); + } + fprintf( pFile, "\n" ); + } + else + { + fprintf( pFile, " (\n " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 4, 4, NULL, 0 ); + fprintf( pFile, ",\n " ); + + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 4, 4, NULL, 0 ); + fprintf( pFile, "\n );\n\n" ); + + fprintf( pFile, " input " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " output " ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + } + + if ( Vec_BitCount(vUsed) ) + { + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed, 0 ); + fprintf( pFile, ";\n\n" ); + } + + if ( Vec_BitCount(vInvs) ) + { + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs, 0 ); + fprintf( pFile, ";\n\n" ); + } + + if ( vObjs ) + { + fprintf( pFile, " wire " ); + Vec_IntForEachEntry( vObjs, iObj, i ) + fprintf( pFile, " t_%d%s", i, i==Vec_IntSize(vObjs)-1 ? "" : "," ); + fprintf( pFile, ";\n\n" ); + Vec_IntForEachEntry( vObjs, iObj, i ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'n', iObj, nDigits) ); + fprintf( pFile, " t_%d;\n", i ); + } + fprintf( pFile, "\n" ); + } + + // input inverters + Gia_ManForEachPi( p, pObj, i ) + { + if ( Vec_BitEntry(vUsed, Gia_ObjId(p, pObj)) ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'n', Gia_ObjId(p, pObj), nDigits) ); + fprintf( pFile, " %s;\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + } + if ( Vec_BitEntry(vInvs, Gia_ObjId(p, pObj)) ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'i', Gia_ObjId(p, pObj), nDigits) ); + fprintf( pFile, " ~%s;\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + } + } + + // internal nodes and their inverters + fprintf( pFile, "\n" ); + Gia_ManForEachAnd( p, pObj, i ) + { + int fSkip = 0; + if ( vObjs ) + { + Vec_IntForEachEntry( vObjs, iObj, k ) + if ( iObj == i ) + break; + if ( k < Vec_IntSize(vObjs) ) + fSkip = 1; + } + if ( !fSkip ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); + fprintf( pFile, " %s &", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0(pObj, i), nDigits) ); + fprintf( pFile, " %s;\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC1(pObj)? 'i':'n'), Gia_ObjFaninId1(pObj, i), nDigits) ); + } + if ( Vec_BitEntry(vInvs, i) ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'i', i, nDigits) ); + fprintf( pFile, " ~%s;\n", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); + } + } + + // output drivers + fprintf( pFile, "\n" ); + Gia_ManForEachPo( p, pObj, i ) + { + fprintf( pFile, " assign %s = ", Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigitsO) ); + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) + fprintf( pFile, "1\'b%d;\n", Gia_ObjFaninC0(pObj) ); + else + fprintf( pFile, "%s;\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0p(p, pObj), nDigits) ); + } + + fprintf( pFile, "\nendmodule\n\n" ); + fclose( pFile ); + + Vec_BitFree( vInvs ); + Vec_BitFree( vUsed ); + + Gia_ManSetRegNum( p, nRegs ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintOneName( FILE * pFile, char * pName, int Size ) +{ + int i; + for ( i = 0; i < Size; i++ ) + fprintf( pFile, "%c", pName[i] ); +} +int Gia_ManCountSymbs( char * pName ) +{ + int i; + for ( i = 0; pName[i]; i++ ) + if ( pName[i] == '[' ) + break; + return i; +} +int Gia_ManReadRangeNum( char * pName, int Size ) +{ + if ( pName[Size] == 0 ) + return -1; + assert( pName[Size] == '[' ); + return atoi(pName+Size+1); +} +Vec_Int_t * Gia_ManCountSymbsAll( Vec_Ptr_t * vNames ) +{ + char * pNameLast = (char *)Vec_PtrEntry(vNames, 0), * pName; + int i, nSymbsLast = Gia_ManCountSymbs(pNameLast); + Vec_Int_t * vArray = Vec_IntAlloc( Vec_PtrSize(vNames) * 2 ); + Vec_IntPush( vArray, 0 ); + Vec_IntPush( vArray, nSymbsLast ); + Vec_PtrForEachEntryStart( char *, vNames, pName, i, 1 ) + { + int nSymbs = Gia_ManCountSymbs(pName); + if ( nSymbs == nSymbsLast && !strncmp(pName, pNameLast, nSymbsLast) ) + continue; + Vec_IntPush( vArray, i ); + Vec_IntPush( vArray, nSymbs ); + pNameLast = pName; + nSymbsLast = nSymbs; + } + return vArray; +} +void Gia_ManDumpIoList( Gia_Man_t * p, FILE * pFile, int fOuts, int fReverse ) +{ + Vec_Ptr_t * vNames = fOuts ? p->vNamesOut : p->vNamesIn; + if ( vNames == NULL ) + fprintf( pFile, "_%c_", fOuts ? 'o' : 'i' ); + else + { + Vec_Int_t * vArray = Gia_ManCountSymbsAll( vNames ); + int iName, Size, i; + Vec_IntForEachEntryDouble( vArray, iName, Size, i ) + { + if ( fReverse ) + { + iName = Vec_IntEntry(vArray, Vec_IntSize(vArray)-2-i); + Size = Vec_IntEntry(vArray, Vec_IntSize(vArray)-1-i); + } + if ( i ) fprintf( pFile, ", " ); + Gia_ManPrintOneName( pFile, (char *)Vec_PtrEntry(vNames, iName), Size ); + } + Vec_IntFree( vArray ); + } +} +void Gia_ManDumpIoRanges( Gia_Man_t * p, FILE * pFile, int fOuts ) +{ + Vec_Ptr_t * vNames = fOuts ? p->vNamesOut : p->vNamesIn; + if ( p->vNamesOut == NULL ) + fprintf( pFile, "%s [%d:0] _%c_;\n", fOuts ? "output" : "input", fOuts ? Gia_ManPoNum(p)-1 : Gia_ManPiNum(p)-1, fOuts ? 'o' : 'i' ); + else + { + Vec_Int_t * vArray = Gia_ManCountSymbsAll( vNames ); + int iName, Size, i; + Vec_IntForEachEntryDouble( vArray, iName, Size, i ) + { + int iNameNext = Vec_IntSize(vArray) > i+2 ? Vec_IntEntry(vArray, i+2) : Vec_PtrSize(vNames); + char * pName = (char *)Vec_PtrEntry(vNames, iName); + char * pNameLast = (char *)Vec_PtrEntry(vNames, iNameNext-1); + assert( !strncmp(pName, pNameLast, Size) ); + int NumBeg = Gia_ManReadRangeNum( pName, Size ); + int NumEnd = Gia_ManReadRangeNum( pNameLast, Size ); + fprintf( pFile, " %s ", fOuts ? "output" : "input" ); + if ( NumBeg != -1 && iName < iNameNext-1 ) + fprintf( pFile, "[%d:%d] ", NumEnd, NumBeg ); + Gia_ManPrintOneName( pFile, pName, Size ); + fprintf( pFile, ";\n" ); + } + Vec_IntFree( vArray ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDumpInterface( Gia_Man_t * p, char * pFileName ) +{ + Gia_Obj_t * pObj; + Vec_Bit_t * vInvs, * vUsed; + int nDigits = Abc_Base10Log( Gia_ManObjNum(p) ); + int nDigitsI = Abc_Base10Log( Gia_ManPiNum(p) ); + int nDigitsO = Abc_Base10Log( Gia_ManPoNum(p) ); + int i; + + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open output file \"%s\".\n", pFileName ); + return; + } + + vInvs = Gia_ManGenUsed( p, 0 ); + vUsed = Gia_ManGenUsed( p, 1 ); + + fprintf( pFile, "module " ); + Gia_ManDumpModuleName( pFile, p->pName ); + fprintf( pFile, "_wrapper" ); + fprintf( pFile, " ( " ); + Gia_ManDumpIoList( p, pFile, 0, 0 ); + fprintf( pFile, ", " ); + Gia_ManDumpIoList( p, pFile, 1, 0 ); + fprintf( pFile, " );\n\n" ); + Gia_ManDumpIoRanges( p, pFile, 0 ); + Gia_ManDumpIoRanges( p, pFile, 1 ); + fprintf( pFile, "\n" ); + + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " assign { " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManCiNum(p), p->vNamesIn, 8, 4, NULL, 1 ); + fprintf( pFile, " } = { " ); + Gia_ManDumpIoList( p, pFile, 0, 1 ); + fprintf( pFile, " };\n\n" ); + + fprintf( pFile, " assign { " ); + Gia_ManDumpIoList( p, pFile, 1, 1 ); + fprintf( pFile, " } = { " ); + Gia_ManWriteNames( pFile, 'z', Gia_ManCoNum(p), p->vNamesOut, 9, 4, NULL, 1 ); + fprintf( pFile, " };\n\n" ); + + if ( Vec_BitCount(vUsed) ) + { + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed, 0 ); + fprintf( pFile, ";\n\n" ); + } + + if ( Vec_BitCount(vInvs) ) + { + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs, 0 ); + fprintf( pFile, ";\n\n" ); + } + + // input inverters + Gia_ManForEachCi( p, pObj, i ) + { + if ( Vec_BitEntry(vUsed, Gia_ObjId(p, pObj)) ) + { + fprintf( pFile, " buf ( %s,", Gia_ObjGetDumpName(NULL, 'n', Gia_ObjId(p, pObj), nDigits) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + } + if ( Vec_BitEntry(vInvs, Gia_ObjId(p, pObj)) ) + { + fprintf( pFile, " not ( %s,", Gia_ObjGetDumpName(NULL, 'i', Gia_ObjId(p, pObj), nDigits) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + } + } + + // internal nodes and their inverters + fprintf( pFile, "\n" ); + Gia_ManForEachAnd( p, pObj, i ) + { + fprintf( pFile, " and ( %s,", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); + fprintf( pFile, " %s,", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0(pObj, i), nDigits) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC1(pObj)? 'i':'n'), Gia_ObjFaninId1(pObj, i), nDigits) ); + if ( Vec_BitEntry(vInvs, i) ) + { + fprintf( pFile, " not ( %s,", Gia_ObjGetDumpName(NULL, 'i', i, nDigits) ); + fprintf( pFile, " %s );\n", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); + } + } + + // output drivers + fprintf( pFile, "\n" ); + Gia_ManForEachCo( p, pObj, i ) + { + fprintf( pFile, " buf ( %s, ", Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigitsO) ); + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) + fprintf( pFile, "1\'b%d );\n", Gia_ObjFaninC0(pObj) ); + else + fprintf( pFile, "%s );\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0p(p, pObj), nDigits) ); + } + + fprintf( pFile, "\nendmodule\n\n" ); + fclose( pFile ); + + Vec_BitFree( vInvs ); + Vec_BitFree( vUsed ); +} +void Gia_ManDumpInterfaceAssign( Gia_Man_t * p, char * pFileName ) +{ + Gia_Obj_t * pObj; + Vec_Bit_t * vInvs, * vUsed; + int nDigits = Abc_Base10Log( Gia_ManObjNum(p) ); + int nDigitsI = Abc_Base10Log( Gia_ManPiNum(p) ); + int nDigitsO = Abc_Base10Log( Gia_ManPoNum(p) ); + int i; + + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open output file \"%s\".\n", pFileName ); + return; + } + + vInvs = Gia_ManGenUsed( p, 0 ); + vUsed = Gia_ManGenUsed( p, 1 ); + + fprintf( pFile, "module " ); + Gia_ManDumpModuleName( pFile, p->pName ); + fprintf( pFile, "_wrapper" ); + fprintf( pFile, " ( " ); + Gia_ManDumpIoList( p, pFile, 0, 0 ); + fprintf( pFile, ", " ); + Gia_ManDumpIoList( p, pFile, 1, 0 ); + fprintf( pFile, " );\n\n" ); + Gia_ManDumpIoRanges( p, pFile, 0 ); + Gia_ManDumpIoRanges( p, pFile, 1 ); + fprintf( pFile, "\n" ); + + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManPiNum(p), p->vNamesIn, 8, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'z', Gia_ManPoNum(p), p->vNamesOut, 9, 4, NULL, 0 ); + fprintf( pFile, ";\n\n" ); + + fprintf( pFile, " assign { " ); + Gia_ManWriteNames( pFile, 'x', Gia_ManCiNum(p), p->vNamesIn, 8, 4, NULL, 1 ); + fprintf( pFile, " } = { " ); + Gia_ManDumpIoList( p, pFile, 0, 1 ); + fprintf( pFile, " };\n\n" ); + + fprintf( pFile, " assign { " ); + Gia_ManDumpIoList( p, pFile, 1, 1 ); + fprintf( pFile, " } = { " ); + Gia_ManWriteNames( pFile, 'z', Gia_ManCoNum(p), p->vNamesOut, 9, 4, NULL, 1 ); + fprintf( pFile, " };\n\n" ); + + if ( Vec_BitCount(vUsed) ) + { + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'n', Gia_ManObjNum(p), NULL, 7, 4, vUsed, 0 ); + fprintf( pFile, ";\n\n" ); + } + + if ( Vec_BitCount(vInvs) ) + { + fprintf( pFile, " wire " ); + Gia_ManWriteNames( pFile, 'i', Gia_ManObjNum(p), NULL, 7, 4, vInvs, 0 ); + fprintf( pFile, ";\n\n" ); + } + + // input inverters + Gia_ManForEachCi( p, pObj, i ) + { + if ( Vec_BitEntry(vUsed, Gia_ObjId(p, pObj)) ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'n', Gia_ObjId(p, pObj), nDigits) ); + fprintf( pFile, " %s;\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + } + if ( Vec_BitEntry(vInvs, Gia_ObjId(p, pObj)) ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'i', Gia_ObjId(p, pObj), nDigits) ); + fprintf( pFile, " ~%s;\n", Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + } + } + + // internal nodes and their inverters + fprintf( pFile, "\n" ); + Gia_ManForEachAnd( p, pObj, i ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); + fprintf( pFile, " %s &", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0(pObj, i), nDigits) ); + fprintf( pFile, " %s;\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC1(pObj)? 'i':'n'), Gia_ObjFaninId1(pObj, i), nDigits) ); + if ( Vec_BitEntry(vInvs, i) ) + { + fprintf( pFile, " assign %s =", Gia_ObjGetDumpName(NULL, 'i', i, nDigits) ); + fprintf( pFile, " ~%s;\n", Gia_ObjGetDumpName(NULL, 'n', i, nDigits) ); + } + } + + // output drivers + fprintf( pFile, "\n" ); + Gia_ManForEachCo( p, pObj, i ) + { + fprintf( pFile, " assign %s = ", Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigitsO) ); + if ( Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) + fprintf( pFile, "1\'b%d;\n", Gia_ObjFaninC0(pObj) ); + else + fprintf( pFile, "%s;\n", Gia_ObjGetDumpName(NULL, (char)(Gia_ObjFaninC0(pObj)? 'i':'n'), Gia_ObjFaninId0p(p, pObj), nDigits) ); + } + + fprintf( pFile, "\nendmodule\n\n" ); + fclose( pFile ); + + Vec_BitFree( vInvs ); + Vec_BitFree( vUsed ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDumpNandLit( FILE * pFile, int nIns, int Lit, int nDigits ) +{ + if ( Lit == 0 ) + fprintf( pFile, "1\'b0" ); + else if ( Lit == 1 ) + fprintf( pFile, "1\'b1" ); + else if ( Abc_Lit2Var(Lit) <= nIns ) + fprintf( pFile, "%cn%0*d", (char)(Abc_LitIsCompl(Lit)? '~':' '), nDigits, Abc_Lit2Var(Lit) ); + else + fprintf( pFile, "%cn%0*d", (char)(Abc_LitIsCompl(Lit)? ' ':'~'), nDigits, Abc_Lit2Var(Lit) ); +} +void Gia_ManDumpVerilogNand( Gia_Man_t * p, char * pFileName ) +{ + Gia_Obj_t * pObj; int i, nPis = Gia_ManPiNum(p); + int nDigits = Abc_Base10Log( Gia_ManObjNum(p) ); + int nDigitsI = Abc_Base10Log( Gia_ManPiNum(p) ); + int nDigitsO = Abc_Base10Log( Gia_ManPoNum(p) ); + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open output file \"%s\".\n", pFileName ); + return; + } + assert( Gia_ManRegNum(p) == 0 ); + fprintf( pFile, "module " ); + Gia_ManDumpModuleName( pFile, p->pName ); + fprintf( pFile, "_wrapper" ); + fprintf( pFile, " ( " ); + if ( p->vNamesIn ) { + Gia_ManDumpIoList( p, pFile, 0, 0 ); + fprintf( pFile, ", " ); + Gia_ManDumpIoList( p, pFile, 1, 0 ); + fprintf( pFile, " );\n\n" ); + Gia_ManDumpIoRanges( p, pFile, 0 ); + Gia_ManDumpIoRanges( p, pFile, 1 ); + } + else { + fprintf( pFile, "\n " ); + Gia_ManForEachPi( p, pObj, i ) + fprintf( pFile, "%s, ", Gia_ObjGetDumpName(NULL, 'x', i, nDigitsI) ); + fprintf( pFile, "\n " ); + Gia_ManForEachPo( p, pObj, i ) + fprintf( pFile, "%s%s ", Gia_ObjGetDumpName(NULL, 'z', i, nDigitsO), i < Gia_ManPoNum(p)-1 ? ",":"" ); + fprintf( pFile, "\n);\n\n" ); + fprintf( pFile, " input" ); + Gia_ManForEachPi( p, pObj, i ) + fprintf( pFile, " %s%s", Gia_ObjGetDumpName(NULL, 'x', i, nDigitsI), i < Gia_ManPiNum(p)-1 ? ",":"" ); + fprintf( pFile, ";\n" ); + fprintf( pFile, " output" ); + Gia_ManForEachPo( p, pObj, i ) + fprintf( pFile, " %s%s", Gia_ObjGetDumpName(NULL, 'z', i, nDigitsO), i < Gia_ManPoNum(p)-1 ? ",":"" ); + fprintf( pFile, ";\n" ); + } + fprintf( pFile, "\n" ); + Gia_ManForEachPi( p, pObj, i ) + fprintf( pFile, " wire n%0*d = %s;\n", nDigits, i+1, p->vNamesIn ? (char *)Vec_PtrEntry(p->vNamesIn, i) : Gia_ObjGetDumpName(p->vNamesIn, 'x', i, nDigitsI) ); + fprintf( pFile, "\n" ); + Gia_ManForEachAnd( p, pObj, i ) + { + fprintf( pFile, " wire n%0*d = ~(", nDigits, i ); + Gia_ManDumpNandLit( pFile, nPis, Gia_ObjFaninLit0(pObj, i), nDigits ); + fprintf( pFile, " & " ); + Gia_ManDumpNandLit( pFile, nPis, Gia_ObjFaninLit1(pObj, i), nDigits ); + fprintf( pFile, ");\n" ); + } + fprintf( pFile, "\n" ); + Gia_ManForEachPo( p, pObj, i ) + { + fprintf( pFile, " assign %s = ", p->vNamesOut ? (char *)Vec_PtrEntry(p->vNamesOut, i) : Gia_ObjGetDumpName(p->vNamesOut, 'z', i, nDigitsO) ); + Gia_ManDumpNandLit( pFile, nPis, Gia_ObjFaninLit0p(p, pObj), nDigits ); + fprintf( pFile, ";\n" ); + } + fprintf( pFile, "\nendmodule\n\n" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Generate hierarchical design.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_FreeMany( Gia_Man_t ** pGias, int nGias ) +{ + int i; + for ( i = 0; i < nGias; i++ ) + Gia_ManStopP( &pGias[i] ); +} +void Gia_GenSandwich( char ** pFNames, int nFNames, char * pFileName ) +{ + FILE * pFile = NULL; + Gia_Man_t * pGias[16] = {0}; + int i, k; + assert( nFNames <= 16 ); + for ( i = 0; i < nFNames; i++ ) + { + FILE * pFile = fopen( pFNames[i], "rb" ); + if ( pFile == NULL ) { + printf( "Cannot open input file \"%s\".\n", pFNames[i] ); + Gia_FreeMany( pGias, nFNames ); + return; + } + fclose( pFile ); + pGias[i] = Gia_AigerRead( pFNames[i], 0, 0, 0 ); + if ( pGias[i] == NULL ) { + printf( "Failed to read an AIG from file \"%s\".\n", pFNames[i] ); + Gia_FreeMany( pGias, nFNames ); + return; + } + } + for ( i = 0; i < nFNames-1; i++ ) + if ( Gia_ManPoNum(pGias[i]) < Gia_ManPiNum(pGias[i+1]) ) { + printf( "AIG in file \"%s\" has fewer outputs than inputs of AIG in file \"%s\".\n", pFNames[i], pFNames[i+1] ); + Gia_FreeMany( pGias, nFNames ); + return; + } + pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open output file \"%s\".\n", pFileName ); + Gia_FreeMany( pGias, nFNames ); + return; + } + fprintf( pFile, "\n" ); + for ( i = 0; i < nFNames; i++ ) + fprintf( pFile, "`include \"%s\"\n", Extra_FileNameGenericAppend(pGias[i]->pSpec, ".v") ); + fprintf( pFile, "\n" ); + fprintf( pFile, "module sandwich ( in, out );\n" ); + fprintf( pFile, " input [%3d:0] in;\n", Gia_ManPiNum(pGias[0])-1 ); + fprintf( pFile, " output [%3d:0] out;\n", Gia_ManPoNum(pGias[nFNames-1])-1 ); + fprintf( pFile, " wire [%3d:0] tmp0 = in;\n", Gia_ManPiNum(pGias[0])-1 ); + for ( i = 0; i < nFNames; i++ ) { + fprintf( pFile, " wire [%3d:0] tmp%d; ", Gia_ManPoNum(pGias[i])-1, i+1 ); + Gia_ManDumpModuleName( pFile, pGias[i]->pName ); + fprintf( pFile, "_wrapper" ); + for ( k = strlen(pGias[i]->pName); k < 24; k++ ) + fprintf( pFile, " " ); + fprintf( pFile, " i%d ( tmp%d, tmp%d );\n", i+1, i, i+1 ); + } + fprintf( pFile, " assign out = tmp%d;\n", nFNames ); + fprintf( pFile, "endmodule\n" ); + fclose( pFile ); + for ( i = 0; i < nFNames; i++ ) { + Vec_PtrFreeFree( pGias[i]->vNamesIn ); pGias[i]->vNamesIn = NULL; + Vec_PtrFreeFree( pGias[i]->vNamesOut ); pGias[i]->vNamesOut = NULL; + Gia_ManDumpVerilog( pGias[i], Extra_FileNameGenericAppend(pGias[i]->pSpec, ".v"), NULL, 0, 0, 1, 0, 0 ); + printf( "Dumped Verilog file \"%s\"\n", Extra_FileNameGenericAppend(pGias[i]->pSpec, ".v") ); + } + Gia_FreeMany( pGias, nFNames ); + printf( "Dumped hierarchical design into file \"%s\"\n", pFileName ); +} + +/**Function************************************************************* + + Synopsis [Generate hierarchical design.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_GenPutOnTopOne( Gia_Man_t * pNew, Gia_Man_t * p, Vec_Int_t * vLits ) +{ + Gia_Obj_t * pObj; int i; + Gia_ManConst0(p)->Value = 0; + assert( Vec_IntSize(vLits) == Gia_ManCiNum(p) ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Vec_IntEntry(vLits, i); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Vec_IntClear( vLits ); + Gia_ManForEachCo( p, pObj, i ) + Vec_IntPush( vLits, Gia_ObjFanin0Copy(pObj) ); + assert( Vec_IntSize(vLits) == Gia_ManCoNum(p) ); +} +Gia_Man_t * Gia_GenPutOnTop( char ** pFNames, int nFNames ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Man_t * pGias[16] = {0}; + Vec_Int_t * vLits; + int i, iLit, nObjs = 0; + assert( nFNames <= 16 ); + for ( i = 0; i < nFNames; i++ ) + { + FILE * pFile = fopen( pFNames[i], "rb" ); + if ( pFile == NULL ) { + printf( "Cannot open input file \"%s\".\n", pFNames[i] ); + Gia_FreeMany( pGias, nFNames ); + return NULL; + } + fclose( pFile ); + pGias[i] = Gia_AigerRead( pFNames[i], 0, 0, 0 ); + if ( pGias[i] == NULL ) { + printf( "Failed to read an AIG from file \"%s\".\n", pFNames[i] ); + Gia_FreeMany( pGias, nFNames ); + return NULL; + } + nObjs += Gia_ManObjNum(pGias[i]); + } + // start new AIG + pNew = Gia_ManStart( nObjs ); + pNew->pName = Abc_UtilStrsav( "putontop" ); + Gia_ManHashAlloc( pNew ); + // collect inputs + vLits = Vec_IntAlloc( Gia_ManCiNum(pGias[0]) ); + for ( i = 0; i < Gia_ManCiNum(pGias[0]); i++ ) + Vec_IntPush( vLits, Gia_ManAppendCi(pNew) ); + // add parts + for ( i = 0; i < nFNames; i++ ) + { + Gia_Man_t * p = pGias[i]; + while ( Vec_IntSize(vLits) < Gia_ManCiNum(p) ) + Vec_IntPush( vLits, Gia_ManAppendCi(pNew) ); + while ( Vec_IntSize(vLits) > Gia_ManCiNum(p) ) + Gia_ManAppendCo( pNew, Vec_IntPop(vLits) ); + Gia_GenPutOnTopOne( pNew, p, vLits ); + } + // create outputs + Vec_IntForEachEntry( vLits, iLit, i ) + Gia_ManAppendCo( pNew, iLit ); + Vec_IntFree( vLits ); + // cleanup + pNew = Gia_ManDupNormalize( pTemp = pNew, 0 ); + Gia_ManStop( pTemp ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END diff --git a/yosys/abc/src/aig/gia/giaMem.c b/yosys/abc/src/aig/gia/giaMem.c new file mode 100644 index 00000000000..d77ddfd5113 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaMem.c @@ -0,0 +1,598 @@ +/**CFile**************************************************************** + + FileName [giaMem.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Memory managers.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: giaMem.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +struct Gia_MmFixed_t_ +{ + // information about individual entries + int nEntrySize; // the size of one entry + int nEntriesAlloc; // the total number of entries allocated + int nEntriesUsed; // the number of entries in use + int nEntriesMax; // the max number of entries in use + char * pEntriesFree; // the linked list of free entries + + // this is where the memory is stored + int nChunkSize; // the size of one chunk + int nChunksAlloc; // the maximum number of memory chunks + int nChunks; // the current number of memory chunks + char ** pChunks; // the allocated memory + + // statistics + int nMemoryUsed; // memory used in the allocated entries + int nMemoryAlloc; // memory allocated +}; + +struct Gia_MmFlex_t_ +{ + // information about individual entries + int nEntriesUsed; // the number of entries allocated + char * pCurrent; // the current pointer to free memory + char * pEnd; // the first entry outside the free memory + + // this is where the memory is stored + int nChunkSize; // the size of one chunk + int nChunksAlloc; // the maximum number of memory chunks + int nChunks; // the current number of memory chunks + char ** pChunks; // the allocated memory + + // statistics + int nMemoryUsed; // memory used in the allocated entries + int nMemoryAlloc; // memory allocated +}; + +struct Gia_MmStep_t_ +{ + int nMems; // the number of fixed memory managers employed + Gia_MmFixed_t ** pMems; // memory managers: 2^1 words, 2^2 words, etc + int nMapSize; // the size of the memory array + Gia_MmFixed_t ** pMap; // maps the number of bytes into its memory manager + // additional memory chunks + int nChunksAlloc; // the maximum number of memory chunks + int nChunks; // the current number of memory chunks + char ** pChunks; // the allocated memory +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates memory pieces of fixed size.] + + Description [The size of the chunk is computed as the minimum of + 1024 entries and 64K. Can only work with entry size at least 4 byte long.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_MmFixed_t * Gia_MmFixedStart( int nEntrySize, int nEntriesMax ) +{ + Gia_MmFixed_t * p; + + p = ABC_ALLOC( Gia_MmFixed_t, 1 ); + memset( p, 0, sizeof(Gia_MmFixed_t) ); + + p->nEntrySize = nEntrySize; + p->nEntriesAlloc = 0; + p->nEntriesUsed = 0; + p->pEntriesFree = NULL; + + p->nChunkSize = nEntriesMax / 8; + if ( p->nChunkSize < 8 ) + p->nChunkSize = 8; + + p->nChunksAlloc = 64; + p->nChunks = 0; + p->pChunks = ABC_ALLOC( char *, p->nChunksAlloc ); + + p->nMemoryUsed = 0; + p->nMemoryAlloc = 0; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_MmFixedStop( Gia_MmFixed_t * p, int fVerbose ) +{ + int i; + if ( p == NULL ) + return; + if ( fVerbose ) + { + printf( "Fixed memory manager: Entry = %5d. Chunk = %5d. Chunks used = %5d.\n", + p->nEntrySize, p->nChunkSize, p->nChunks ); + printf( " Entries used = %8d. Entries peak = %8d. Memory used = %8d. Memory alloc = %8d.\n", + p->nEntriesUsed, p->nEntriesMax, p->nEntrySize * p->nEntriesUsed, p->nMemoryAlloc ); + } + for ( i = 0; i < p->nChunks; i++ ) + ABC_FREE( p->pChunks[i] ); + ABC_FREE( p->pChunks ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Gia_MmFixedEntryFetch( Gia_MmFixed_t * p ) +{ + char * pTemp; + int i; + + // check if there are still free entries + if ( p->nEntriesUsed == p->nEntriesAlloc ) + { // need to allocate more entries + assert( p->pEntriesFree == NULL ); + if ( p->nChunks == p->nChunksAlloc ) + { + p->nChunksAlloc *= 2; + p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); + } + p->pEntriesFree = ABC_ALLOC( char, p->nEntrySize * p->nChunkSize ); + p->nMemoryAlloc += p->nEntrySize * p->nChunkSize; + // transform these entries into a linked list + pTemp = p->pEntriesFree; + for ( i = 1; i < p->nChunkSize; i++ ) + { + *((char **)pTemp) = pTemp + p->nEntrySize; + pTemp += p->nEntrySize; + } + // set the last link + *((char **)pTemp) = NULL; + // add the chunk to the chunk storage + p->pChunks[ p->nChunks++ ] = p->pEntriesFree; + // add to the number of entries allocated + p->nEntriesAlloc += p->nChunkSize; + } + // incrememt the counter of used entries + p->nEntriesUsed++; + if ( p->nEntriesMax < p->nEntriesUsed ) + p->nEntriesMax = p->nEntriesUsed; + // return the first entry in the free entry list + pTemp = p->pEntriesFree; + p->pEntriesFree = *((char **)pTemp); + return pTemp; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_MmFixedEntryRecycle( Gia_MmFixed_t * p, char * pEntry ) +{ + // decrement the counter of used entries + p->nEntriesUsed--; + // add the entry to the linked list of free entries + *((char **)pEntry) = p->pEntriesFree; + p->pEntriesFree = pEntry; +} + +/**Function************************************************************* + + Synopsis [] + + Description [Relocates all the memory except the first chunk.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_MmFixedRestart( Gia_MmFixed_t * p ) +{ + int i; + char * pTemp; + if ( p->nChunks == 0 ) + return; + // deallocate all chunks except the first one + for ( i = 1; i < p->nChunks; i++ ) + ABC_FREE( p->pChunks[i] ); + p->nChunks = 1; + // transform these entries into a linked list + pTemp = p->pChunks[0]; + for ( i = 1; i < p->nChunkSize; i++ ) + { + *((char **)pTemp) = pTemp + p->nEntrySize; + pTemp += p->nEntrySize; + } + // set the last link + *((char **)pTemp) = NULL; + // set the free entry list + p->pEntriesFree = p->pChunks[0]; + // set the correct statistics + p->nMemoryAlloc = p->nEntrySize * p->nChunkSize; + p->nMemoryUsed = 0; + p->nEntriesAlloc = p->nChunkSize; + p->nEntriesUsed = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_MmFixedReadMemUsage( Gia_MmFixed_t * p ) +{ + return p->nMemoryAlloc; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_MmFixedReadMaxEntriesUsed( Gia_MmFixed_t * p ) +{ + return p->nEntriesMax; +} + + + +/**Function************************************************************* + + Synopsis [Allocates entries of flexible size.] + + Description [Can only work with entry size at least 4 byte long.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_MmFlex_t * Gia_MmFlexStart() +{ + Gia_MmFlex_t * p; + + p = ABC_ALLOC( Gia_MmFlex_t, 1 ); + memset( p, 0, sizeof(Gia_MmFlex_t) ); + + p->nEntriesUsed = 0; + p->pCurrent = NULL; + p->pEnd = NULL; + + p->nChunkSize = (1 << 18); + p->nChunksAlloc = 64; + p->nChunks = 0; + p->pChunks = ABC_ALLOC( char *, p->nChunksAlloc ); + + p->nMemoryUsed = 0; + p->nMemoryAlloc = 0; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_MmFlexStop( Gia_MmFlex_t * p, int fVerbose ) +{ + int i; + if ( p == NULL ) + return; + if ( fVerbose ) + { + printf( "Flexible memory manager: Chunk size = %d. Chunks used = %d.\n", + p->nChunkSize, p->nChunks ); + printf( " Entries used = %d. Memory used = %d. Memory alloc = %d.\n", + p->nEntriesUsed, p->nMemoryUsed, p->nMemoryAlloc ); + } + for ( i = 0; i < p->nChunks; i++ ) + ABC_FREE( p->pChunks[i] ); + ABC_FREE( p->pChunks ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Gia_MmFlexEntryFetch( Gia_MmFlex_t * p, int nBytes ) +{ + char * pTemp; + // check if there are still free entries + if ( p->pCurrent == NULL || p->pCurrent + nBytes > p->pEnd ) + { // need to allocate more entries + if ( p->nChunks == p->nChunksAlloc ) + { + p->nChunksAlloc *= 2; + p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); + } + if ( nBytes > p->nChunkSize ) + { + // resize the chunk size if more memory is requested than it can give + // (ideally, this should never happen) + p->nChunkSize = 2 * nBytes; + } + p->pCurrent = ABC_ALLOC( char, p->nChunkSize ); + p->pEnd = p->pCurrent + p->nChunkSize; + p->nMemoryAlloc += p->nChunkSize; + // add the chunk to the chunk storage + p->pChunks[ p->nChunks++ ] = p->pCurrent; + } + assert( p->pCurrent + nBytes <= p->pEnd ); + // increment the counter of used entries + p->nEntriesUsed++; + // keep track of the memory used + p->nMemoryUsed += nBytes; + // return the next entry + pTemp = p->pCurrent; + p->pCurrent += nBytes; + return pTemp; +} + +/**Function************************************************************* + + Synopsis [] + + Description [Relocates all the memory except the first chunk.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_MmFlexRestart( Gia_MmFlex_t * p ) +{ + int i; + if ( p->nChunks == 0 ) + return; + // deallocate all chunks except the first one + for ( i = 1; i < p->nChunks; i++ ) + ABC_FREE( p->pChunks[i] ); + p->nChunks = 1; + p->nMemoryAlloc = p->nChunkSize; + // transform these entries into a linked list + p->pCurrent = p->pChunks[0]; + p->pEnd = p->pCurrent + p->nChunkSize; + p->nEntriesUsed = 0; + p->nMemoryUsed = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_MmFlexReadMemUsage( Gia_MmFlex_t * p ) +{ + return p->nMemoryUsed; +} + + + + + +/**Function************************************************************* + + Synopsis [Starts the hierarchical memory manager.] + + Description [This manager can allocate entries of any size. + Iternally they are mapped into the entries with the number of bytes + equal to the power of 2. The smallest entry size is 8 bytes. The + next one is 16 bytes etc. So, if the user requests 6 bytes, he gets + 8 byte entry. If we asks for 25 bytes, he gets 32 byte entry etc. + The input parameters "nSteps" says how many fixed memory managers + are employed internally. Calling this procedure with nSteps equal + to 10 results in 10 hierarchically arranged internal memory managers, + which can allocate up to 4096 (1Kb) entries. Requests for larger + entries are handed over to malloc() and then ABC_FREE()ed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_MmStep_t * Gia_MmStepStart( int nSteps ) +{ + Gia_MmStep_t * p; + int i, k; + p = ABC_ALLOC( Gia_MmStep_t, 1 ); + memset( p, 0, sizeof(Gia_MmStep_t) ); + p->nMems = nSteps; + // start the fixed memory managers + p->pMems = ABC_ALLOC( Gia_MmFixed_t *, p->nMems ); + for ( i = 0; i < p->nMems; i++ ) + p->pMems[i] = Gia_MmFixedStart( (8<nMapSize = (4<nMems); + p->pMap = ABC_ALLOC( Gia_MmFixed_t *, p->nMapSize+1 ); + p->pMap[0] = NULL; + for ( k = 1; k <= 4; k++ ) + p->pMap[k] = p->pMems[0]; + for ( i = 0; i < p->nMems; i++ ) + for ( k = (4<pMap[k] = p->pMems[i]; +//for ( i = 1; i < 100; i ++ ) +//printf( "%10d: size = %10d\n", i, p->pMap[i]->nEntrySize ); + p->nChunksAlloc = 64; + p->nChunks = 0; + p->pChunks = ABC_ALLOC( char *, p->nChunksAlloc ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_MmStepStop( Gia_MmStep_t * p, int fVerbose ) +{ + int i; + for ( i = 0; i < p->nMems; i++ ) + Gia_MmFixedStop( p->pMems[i], fVerbose ); + if ( p->nChunksAlloc ) + { + for ( i = 0; i < p->nChunks; i++ ) + ABC_FREE( p->pChunks[i] ); + ABC_FREE( p->pChunks ); + } + ABC_FREE( p->pMems ); + ABC_FREE( p->pMap ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Creates the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Gia_MmStepEntryFetch( Gia_MmStep_t * p, int nBytes ) +{ + if ( nBytes == 0 ) + return NULL; + if ( nBytes > p->nMapSize ) + { + if ( p->nChunks == p->nChunksAlloc ) + { + p->nChunksAlloc *= 2; + p->pChunks = ABC_REALLOC( char *, p->pChunks, p->nChunksAlloc ); + } + p->pChunks[ p->nChunks++ ] = ABC_ALLOC( char, nBytes ); + return p->pChunks[p->nChunks-1]; + } + return Gia_MmFixedEntryFetch( p->pMap[nBytes] ); +} + + +/**Function************************************************************* + + Synopsis [Recycles the entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_MmStepEntryRecycle( Gia_MmStep_t * p, char * pEntry, int nBytes ) +{ + if ( nBytes == 0 ) + return; + if ( nBytes > p->nMapSize ) + { +// ABC_FREE( pEntry ); + return; + } + Gia_MmFixedEntryRecycle( p->pMap[nBytes], pEntry ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_MmStepReadMemUsage( Gia_MmStep_t * p ) +{ + int i, nMemTotal = 0; + for ( i = 0; i < p->nMems; i++ ) + nMemTotal += p->pMems[i]->nMemoryAlloc; + return nMemTotal; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaMf.c b/yosys/abc/src/aig/gia/giaMf.c new file mode 100644 index 00000000000..0e1ae9a975f --- /dev/null +++ b/yosys/abc/src/aig/gia/giaMf.c @@ -0,0 +1,1915 @@ +/**CFile**************************************************************** + + FileName [giaMf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Cut computation.] + + Author [Alan Mishchenko]` + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaMf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/vec/vecMem.h" +#include "misc/util/utilTruth.h" +#include "misc/extra/extra.h" +#include "sat/cnf/cnf.h" +#include "opt/dau/dau.h" +#include "bool/kit/kit.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define MF_LEAF_MAX 10 +#define MF_CUT_MAX 16 +#define MF_LOG_PAGE 12 +#define MF_NO_LEAF 31 +#define MF_TT_WORDS ((MF_LEAF_MAX > 6) ? 1 << (MF_LEAF_MAX-6) : 1) +#define MF_NO_FUNC 134217727 // (1<<27)-1 +#define MF_EPSILON 0.005 + +typedef struct Mf_Cut_t_ Mf_Cut_t; +struct Mf_Cut_t_ +{ + word Sign; // signature + int Delay; // delay + float Flow; // flow + unsigned iFunc : 27; // function (MF_NO_FUNC) + unsigned nLeaves : 5; // leaf number (MF_NO_LEAF) + int pLeaves[MF_LEAF_MAX+1]; // leaves +}; +typedef struct Mf_Obj_t_ Mf_Obj_t; +struct Mf_Obj_t_ +{ + int iCutSet; // cutset + float Flow; // area + float nFlowRefs; // flow references + unsigned Delay : 16; // delay + unsigned nMapRefs : 16; // map references +}; +typedef struct Mf_Man_t_ Mf_Man_t; +struct Mf_Man_t_ +{ + // user data + Gia_Man_t * pGia0; // original manager + Gia_Man_t * pGia; // derived manager + Jf_Par_t * pPars; // parameters + // cut data + Mf_Obj_t * pLfObjs; // best cuts + Vec_Ptr_t vPages; // cut memory + Vec_Mem_t * vTtMem; // truth tables + Vec_Int_t vCnfSizes; // handles to CNF + Vec_Int_t vCnfMem; // memory for CNF + Vec_Int_t vTemp; // temporary array + int iCur; // current position + int Iter; // mapping iterations + int fUseEla; // use exact area + // statistics + abctime clkStart; // starting time + double CutCount[4]; // cut counts + int nCutCounts[MF_LEAF_MAX+1]; +}; + +static inline Mf_Obj_t * Mf_ManObj( Mf_Man_t * p, int i ) { return p->pLfObjs + i; } +static inline int * Mf_ManCutSet( Mf_Man_t * p, int i ) { return (int *)Vec_PtrEntry(&p->vPages, i >> 16) + (i & 0xFFFF); } +static inline int * Mf_ObjCutSet( Mf_Man_t * p, int i ) { return Mf_ManCutSet(p, Mf_ManObj(p, i)->iCutSet); } +static inline int * Mf_ObjCutBest( Mf_Man_t * p, int i ) { return Mf_ObjCutSet(p, i) + 1; } + +static inline int Mf_ObjMapRefNum( Mf_Man_t * p, int i ) { return Mf_ManObj(p, i)->nMapRefs; } +static inline int Mf_ObjMapRefInc( Mf_Man_t * p, int i ) { return Mf_ManObj(p, i)->nMapRefs++; } +static inline int Mf_ObjMapRefDec( Mf_Man_t * p, int i ) { return --Mf_ManObj(p, i)->nMapRefs; } + +static inline int Mf_CutSize( int * pCut ) { return pCut[0] & MF_NO_LEAF; } +static inline int Mf_CutFunc( int * pCut ) { return ((unsigned)pCut[0] >> 5); } +static inline int Mf_CutSetBoth( int n, int f ) { return n | (f << 5); } +static inline int Mf_CutIsTriv( int * pCut, int i ) { return Mf_CutSize(pCut) == 1 && pCut[1] == i; } + +#define Mf_SetForEachCut( pList, pCut, i ) for ( i = 0, pCut = pList + 1; i < pList[0]; i++, pCut += Mf_CutSize(pCut) + 1 ) +#define Mf_ObjForEachCut( pCuts, i, nCuts ) for ( i = 0, i < nCuts; i++ ) + +extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computing truth tables of useful DSD classes of 6-functions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int s_nCalls = 0; +static Vec_Mem_t * s_vTtMem = NULL; +int Mf_ManTruthCanonicize( word * t, int nVars ) +{ + word Temp, Best = *t; + int r, i, Config = 0; + for ( r = 0; r < 1; r++ ) + { + if ( Best > (Temp = ~Best) ) + Best = Temp, Config ^= (1 << nVars); + for ( i = 0; i < nVars; i++ ) + if ( Best > (Temp = Abc_Tt6Flip(Best, i)) ) + Best = Temp, Config ^= (1 << i); + } + *t = Best; + if ( s_vTtMem == NULL ) + s_vTtMem = Vec_MemAllocForTT( 6, 0 ); + Vec_MemHashInsert( s_vTtMem, t ); + s_nCalls++; + return Config; +} +void Mf_ManTruthQuit() +{ + if ( s_vTtMem == NULL ) + return; + printf( "TT = %d (%.2f %%)\n", Vec_MemEntryNum(s_vTtMem), 100.0 * Vec_MemEntryNum(s_vTtMem) / s_nCalls ); + Vec_MemHashFree( s_vTtMem ); + Vec_MemFree( s_vTtMem ); + s_vTtMem = NULL; + s_nCalls = 0; +} + +Vec_Wrd_t * Mf_ManTruthCollect( int Limit ) +{ + extern Vec_Wrd_t * Mpm_ManGetTruthWithCnf( int Limit ); + int * pPerm = Extra_PermSchedule( 6 ); + int * pComp = Extra_GreyCodeSchedule( 6 ); + Vec_Wrd_t * vTruths = Mpm_ManGetTruthWithCnf( Limit ); + Vec_Wrd_t * vResult = Vec_WrdAlloc( 1 << 20 ); + word uTruth, tCur, tTemp1, tTemp2; + int i, p, c, k; + Vec_WrdForEachEntry( vTruths, uTruth, k ) + { + for ( i = 0; i < 2; i++ ) + { + tCur = i ? ~uTruth : uTruth; + tTemp1 = tCur; + for ( p = 0; p < 720; p++ ) + { + tTemp2 = tCur; + for ( c = 0; c < 64; c++ ) + { + tCur = Abc_Tt6Flip( tCur, pComp[c] ); + Vec_WrdPush( vResult, tCur ); + } + assert( tTemp2 == tCur ); + tCur = Abc_Tt6SwapAdjacent( tCur, pPerm[p] ); + } + assert( tTemp1 == tCur ); + } + } + ABC_FREE( pPerm ); + ABC_FREE( pComp ); + printf( "Original = %d. ", Vec_WrdSize(vTruths) ); + Vec_WrdFree( vTruths ); + printf( "Total = %d. ", Vec_WrdSize(vResult) ); + vTruths = Vec_WrdUniqifyHash( vResult, 1 ); + Vec_WrdFree( vResult ); + printf( "Unique = %d. ", Vec_WrdSize(vTruths) ); + Vec_WrdForEachEntry( vTruths, uTruth, k ) + { + Mf_ManTruthCanonicize( &uTruth, 6 ); + Vec_WrdWriteEntry( vTruths, k, uTruth ); + } + vResult = Vec_WrdUniqifyHash( vTruths, 1 ); + Vec_WrdFree( vTruths ); + printf( "Unique = %d. \n", Vec_WrdSize(vResult) ); + return vResult; +} +int Mf_ManTruthCount() +{ + Vec_Wrd_t * vTruths = Mf_ManTruthCollect( 10 ); + int RetValue = Vec_WrdSize( vTruths ); + Vec_WrdFree( vTruths ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Collect truth tables used by the mapper.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mf_ManProfileTruths( Mf_Man_t * p ) +{ + Vec_Int_t * vCounts; + int i, Entry, * pCut, Counter = 0; + vCounts = Vec_IntStart( Vec_IntSize(&p->vCnfSizes) ); + Gia_ManForEachAndId( p->pGia, i ) + { + if ( !Mf_ObjMapRefNum(p, i) ) + continue; + pCut = Mf_ObjCutBest( p, i ); + Vec_IntAddToEntry( vCounts, Abc_Lit2Var(Mf_CutFunc(pCut)), 1 ); + } + Vec_IntForEachEntry( vCounts, Entry, i ) + { + if ( Entry == 0 ) + continue; + printf( "%6d : ", Counter++ ); + printf( "%6d : ", i ); + printf( "Occur = %4d ", Entry ); + printf( "CNF size = %2d ", Vec_IntEntry(&p->vCnfSizes, i) ); + Dau_DsdPrintFromTruth( Vec_MemReadEntry(p->vTtMem, i), p->pPars->nLutSize ); + } + Vec_IntFree( vCounts ); +} + +/**Function************************************************************* + + Synopsis [Derives CNFs for each function used in the mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Mf_CutPrintOne( int * pCut ) +{ + int i; + printf( "%d {", Mf_CutSize(pCut) ); + for ( i = 1; i <= Mf_CutSize(pCut); i++ ) + printf( " %d", pCut[i] ); + printf( " }\n" ); +} +static inline int Mf_CubeLit( int Cube, int iVar ) { return (Cube >> (iVar << 1)) & 3; } +static inline int Mf_ManCountLits( int * pCnf, int nCubes, int nVars ) +{ + int i, k, nLits = nCubes; + for ( i = 0; i < nCubes; i++ ) + for ( k = 0; k < nVars; k++ ) + if ( Mf_CubeLit(pCnf[i], k) ) + nLits++; + return nLits; +} +Vec_Int_t * Mf_ManDeriveCnfs( Mf_Man_t * p, int * pnVars, int * pnClas, int * pnLits ) +{ + int i, k, iFunc, nCubes, nLits, * pCut, pCnf[512]; + Vec_Int_t * vLits = Vec_IntStart( Vec_IntSize(&p->vCnfSizes) ); + Vec_Int_t * vCnfs = Vec_IntAlloc( 3 * Vec_IntSize(&p->vCnfSizes) ); + Vec_IntFill( vCnfs, Vec_IntSize(&p->vCnfSizes), -1 ); + assert( p->pPars->nLutSize <= 8 ); + // constant/buffer + for ( iFunc = 0; iFunc < 2; iFunc++ ) + { + if ( p->pPars->nLutSize <= 6 ) + nCubes = Abc_Tt6Cnf( *Vec_MemReadEntry(p->vTtMem, iFunc), iFunc, pCnf ); + else + nCubes = Abc_Tt8Cnf( Vec_MemReadEntry(p->vTtMem, iFunc), iFunc, pCnf ); + nLits = Mf_ManCountLits( pCnf, nCubes, iFunc ); + Vec_IntWriteEntry( vLits, iFunc, nLits ); + Vec_IntWriteEntry( vCnfs, iFunc, Vec_IntSize(vCnfs) ); + Vec_IntPush( vCnfs, nCubes ); + for ( k = 0; k < nCubes; k++ ) + Vec_IntPush( vCnfs, pCnf[k] ); + } + // other functions + *pnVars = 1 + Gia_ManCiNum(p->pGia) + Gia_ManCoNum(p->pGia); + *pnClas = 1 + 2 * Gia_ManCoNum(p->pGia); + *pnLits = 1 + 4 * Gia_ManCoNum(p->pGia); + Gia_ManForEachAndId( p->pGia, i ) + { + if ( !Mf_ObjMapRefNum(p, i) ) + continue; + pCut = Mf_ObjCutBest( p, i ); + //Mf_CutPrintOne( pCut ); + iFunc = Abc_Lit2Var( Mf_CutFunc(pCut) ); + if ( Vec_IntEntry(vCnfs, iFunc) == -1 ) + { + if ( p->pPars->nLutSize <= 6 ) + nCubes = Abc_Tt6Cnf( *Vec_MemReadEntry(p->vTtMem, iFunc), Mf_CutSize(pCut), pCnf ); + else + nCubes = Abc_Tt8Cnf( Vec_MemReadEntry(p->vTtMem, iFunc), Mf_CutSize(pCut), pCnf ); + assert( nCubes == Vec_IntEntry(&p->vCnfSizes, iFunc) ); + nLits = Mf_ManCountLits( pCnf, nCubes, Mf_CutSize(pCut) ); + // save CNF + Vec_IntWriteEntry( vLits, iFunc, nLits ); + Vec_IntWriteEntry( vCnfs, iFunc, Vec_IntSize(vCnfs) ); + Vec_IntPush( vCnfs, nCubes ); + for ( k = 0; k < nCubes; k++ ) + Vec_IntPush( vCnfs, pCnf[k] ); + } + *pnVars += 1; + *pnClas += Vec_IntEntry(&p->vCnfSizes, iFunc); + *pnLits += Vec_IntEntry(vLits, iFunc); + } + Vec_IntFree( vLits ); + return vCnfs; +} + +/**Function************************************************************* + + Synopsis [Derives CNF for the AIG using the mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Cnf_Dat_t * Mf_ManDeriveCnf( Mf_Man_t * p, int fCnfObjIds, int fAddOrCla ) +{ + Cnf_Dat_t * pCnf; + Gia_Obj_t * pObj; + int Id, DriId, nVars, nClas, nLits, iVar = 1, iCla = 0, iLit = 0; + Vec_Int_t * vCnfs = Mf_ManDeriveCnfs( p, &nVars, &nClas, &nLits ); + Vec_Int_t * vCnfIds = Vec_IntStartFull( Gia_ManObjNum(p->pGia) ); + int pFanins[16], * pCut, * pCnfIds = Vec_IntArray( vCnfIds ); + int i, k, c, iFunc, nCubes, * pCubes, fComplLast; + nVars++; // zero-ID to remain unused + if ( fAddOrCla ) + { + nClas++; + nLits += Gia_ManCoNum(p->pGia); + } + // create CNF IDs + if ( fCnfObjIds ) + { + iVar += 1 + Gia_ManCiNum(p->pGia) + Gia_ManCoNum(p->pGia); + Gia_ManForEachCoId( p->pGia, Id, i ) + Vec_IntWriteEntry( vCnfIds, Id, Id ); + Gia_ManForEachAndReverseId( p->pGia, Id ) + if ( Mf_ObjMapRefNum(p, Id) ) + Vec_IntWriteEntry( vCnfIds, Id, Id ), iVar++; + Vec_IntWriteEntry( vCnfIds, 0, 0 ); + Gia_ManForEachCiId( p->pGia, Id, i ) + Vec_IntWriteEntry( vCnfIds, Id, Id ); + assert( iVar == nVars ); + } + else + { + Gia_ManForEachCoId( p->pGia, Id, i ) + Vec_IntWriteEntry( vCnfIds, Id, iVar++ ); + Gia_ManForEachAndReverseId( p->pGia, Id ) + if ( Mf_ObjMapRefNum(p, Id) ) + Vec_IntWriteEntry( vCnfIds, Id, iVar++ ); + Vec_IntWriteEntry( vCnfIds, 0, iVar++ ); + Gia_ManForEachCiId( p->pGia, Id, i ) + Vec_IntWriteEntry( vCnfIds, Id, iVar++ ); + assert( iVar == nVars ); + } + // generate CNF + pCnf = ABC_CALLOC( Cnf_Dat_t, 1 ); + pCnf->pMan = (Aig_Man_t *)p->pGia; + pCnf->nVars = nVars; + pCnf->nLiterals = nLits; + pCnf->nClauses = nClas; + pCnf->pClauses = ABC_ALLOC( int *, nClas+1 ); + pCnf->pClauses[0] = ABC_ALLOC( int, nLits ); + // add last clause + if ( fAddOrCla ) + { + pCnf->pClauses[iCla++] = pCnf->pClauses[0] + iLit; + Gia_ManForEachCoId( p->pGia, Id, i ) + pCnf->pClauses[0][iLit++] = Abc_Var2Lit(pCnfIds[Id], 0); + } + if ( p->pPars->fCnfMapping ) + pCnf->vMapping = Vec_IntStart( nVars ); + // add clauses for the COs + Gia_ManForEachCo( p->pGia, pObj, i ) + { + Id = Gia_ObjId( p->pGia, pObj ); + DriId = Gia_ObjFaninId0( pObj, Id ); + + pCnf->pClauses[iCla++] = pCnf->pClauses[0] + iLit; + pCnf->pClauses[0][iLit++] = Abc_Var2Lit(pCnfIds[Id], 0); + pCnf->pClauses[0][iLit++] = Abc_Var2Lit(pCnfIds[DriId], !Gia_ObjFaninC0(pObj)); + + pCnf->pClauses[iCla++] = pCnf->pClauses[0] + iLit; + pCnf->pClauses[0][iLit++] = Abc_Var2Lit(pCnfIds[Id], 1); + pCnf->pClauses[0][iLit++] = Abc_Var2Lit(pCnfIds[DriId], Gia_ObjFaninC0(pObj)); + // generate mapping + if ( pCnf->vMapping ) + { + Vec_IntWriteEntry( pCnf->vMapping, pCnfIds[Id], Vec_IntSize(pCnf->vMapping) ); + Vec_IntPush( pCnf->vMapping, 1 ); + Vec_IntPush( pCnf->vMapping, pCnfIds[DriId] ); + Vec_IntPush( pCnf->vMapping, Gia_ObjFaninC0(pObj) ? 0x55555555 : 0xAAAAAAAA ); + } + } + // add clauses for the mapping + Gia_ManForEachAndReverseId( p->pGia, Id ) + { + if ( !Mf_ObjMapRefNum(p, Id) ) + continue; + pCut = Mf_ObjCutBest( p, Id ); + iFunc = Abc_Lit2Var( Mf_CutFunc(pCut) ); + fComplLast = Abc_LitIsCompl( Mf_CutFunc(pCut) ); + if ( iFunc == 0 ) // constant cut + { + pCnf->pClauses[iCla++] = pCnf->pClauses[0] + iLit; + pCnf->pClauses[0][iLit++] = Abc_Var2Lit(pCnfIds[Id], !fComplLast); + assert( pCnf->vMapping == NULL ); // bug fix does not handle generated mapping + continue; + } + for ( k = 0; k < Mf_CutSize(pCut); k++ ) + pFanins[k] = pCnfIds[pCut[k+1]]; + pFanins[k++] = pCnfIds[Id]; + // get clauses + pCubes = Vec_IntEntryP( vCnfs, Vec_IntEntry(vCnfs, iFunc) ); + nCubes = *pCubes++; + for ( c = 0; c < nCubes; c++ ) + { + pCnf->pClauses[iCla++] = pCnf->pClauses[0] + iLit; + k = Mf_CutSize(pCut); + assert( Mf_CubeLit(pCubes[c], k) ); + pCnf->pClauses[0][iLit++] = Abc_Var2Lit( pFanins[k], (Mf_CubeLit(pCubes[c], k) == 2) ^ fComplLast ); + for ( k = 0; k < Mf_CutSize(pCut); k++ ) + if ( Mf_CubeLit(pCubes[c], k) ) + pCnf->pClauses[0][iLit++] = Abc_Var2Lit( pFanins[k], Mf_CubeLit(pCubes[c], k) == 2 ); + } + // generate mapping + if ( pCnf->vMapping ) + { + word pTruth[4], * pTruthP = Vec_MemReadEntry(p->vTtMem, iFunc); + assert( p->pPars->nLutSize <= 8 ); + Abc_TtCopy( pTruth, pTruthP, Abc_Truth6WordNum(p->pPars->nLutSize), Abc_LitIsCompl(iFunc) ); + assert( pCnfIds[Id] >= 0 && pCnfIds[Id] < nVars ); + Vec_IntWriteEntry( pCnf->vMapping, pCnfIds[Id], Vec_IntSize(pCnf->vMapping) ); + Vec_IntPush( pCnf->vMapping, Mf_CutSize(pCut) ); + for ( k = 0; k < Mf_CutSize(pCut); k++ ) + Vec_IntPush( pCnf->vMapping, pCnfIds[pCut[k+1]] ); + Vec_IntPush( pCnf->vMapping, (unsigned)pTruth[0] ); + if ( Mf_CutSize(pCut) >= 6 ) + { + Vec_IntPush( pCnf->vMapping, (unsigned)(pTruth[0] >> 32) ); + if ( Mf_CutSize(pCut) >= 7 ) + { + Vec_IntPush( pCnf->vMapping, (unsigned)(pTruth[1]) ); + Vec_IntPush( pCnf->vMapping, (unsigned)(pTruth[1] >> 32) ); + } + if ( Mf_CutSize(pCut) >= 8 ) + { + Vec_IntPush( pCnf->vMapping, (unsigned)(pTruth[2]) ); + Vec_IntPush( pCnf->vMapping, (unsigned)(pTruth[2] >> 32) ); + Vec_IntPush( pCnf->vMapping, (unsigned)(pTruth[3]) ); + Vec_IntPush( pCnf->vMapping, (unsigned)(pTruth[3] >> 32) ); + } + } + } + } + // constant clause + pCnf->pClauses[iCla++] = pCnf->pClauses[0] + iLit; + pCnf->pClauses[0][iLit++] = Abc_Var2Lit(pCnfIds[0], 1); + assert( iCla == nClas ); + assert( iLit == nLits ); + // add closing pointer + pCnf->pClauses[iCla++] = pCnf->pClauses[0] + iLit; + // cleanup + Vec_IntFree( vCnfs ); + // create mapping of objects into their clauses + if ( fCnfObjIds ) + { + pCnf->pObj2Clause = ABC_FALLOC( int, Gia_ManObjNum(p->pGia) ); + pCnf->pObj2Count = ABC_FALLOC( int, Gia_ManObjNum(p->pGia) ); + for ( i = 0; i < pCnf->nClauses; i++ ) + { + Id = Abc_Lit2Var(pCnf->pClauses[i][0]); + if ( pCnf->pObj2Clause[Id] == -1 ) + { + pCnf->pObj2Clause[Id] = i; + pCnf->pObj2Count[Id] = 1; + } + else + { + assert( pCnf->pObj2Count[Id] > 0 ); + pCnf->pObj2Count[Id]++; + } + } + } + else + { + if ( p->pGia != p->pGia0 ) // diff managers - create map for CIs/COs + { + pCnf->pVarNums = ABC_FALLOC( int, Gia_ManObjNum(p->pGia0) ); + Gia_ManForEachCiId( p->pGia0, Id, i ) + pCnf->pVarNums[Id] = pCnfIds[Gia_ManCiIdToId(p->pGia, i)]; + Gia_ManForEachCoId( p->pGia0, Id, i ) + pCnf->pVarNums[Id] = pCnfIds[Gia_ManCoIdToId(p->pGia, i)]; +/* + // transform polarity of the internal nodes + Gia_ManSetPhase( p->pGia ); + Gia_ManForEachCo( p->pGia, pObj, i ) + pObj->fPhase = 0; + for ( i = 0; i < pCnf->nLiterals; i++ ) + if ( Gia_ManObj(p->pGia, Abc_Lit2Var(pCnf->pClauses[0][i]))->fPhase ) + pCnf->pClauses[0][i] = Abc_LitNot( pCnf->pClauses[0][i] ); +*/ + } + else + pCnf->pVarNums = Vec_IntReleaseArray(vCnfIds); + } + Vec_IntFree( vCnfIds ); + return pCnf; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Mf_CutComputeTruth6( Mf_Man_t * p, Mf_Cut_t * pCut0, Mf_Cut_t * pCut1, int fCompl0, int fCompl1, Mf_Cut_t * pCutR, int fIsXor ) +{ +// extern int Mf_ManTruthCanonicize( word * t, int nVars ); + int nOldSupp = pCutR->nLeaves, truthId, fCompl; word t; + word t0 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut0->iFunc)); + word t1 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut1->iFunc)); + if ( Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ) t0 = ~t0; + if ( Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ) t1 = ~t1; + t0 = Abc_Tt6Expand( t0, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + t1 = Abc_Tt6Expand( t1, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + t = fIsXor ? t0 ^ t1 : t0 & t1; + if ( (fCompl = (int)(t & 1)) ) t = ~t; + if ( !p->pPars->fCnfObjIds ) + pCutR->nLeaves = Abc_Tt6MinBase( &t, pCutR->pLeaves, pCutR->nLeaves ); + assert( (int)(t & 1) == 0 ); + truthId = Vec_MemHashInsert(p->vTtMem, &t); + pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); + if ( (p->pPars->fGenCnf || p->pPars->fGenLit) && truthId == Vec_IntSize(&p->vCnfSizes) ) + Vec_IntPush( &p->vCnfSizes, p->pPars->fGenCnf ? Abc_Tt6CnfSize(t, pCutR->nLeaves) : Kit_TruthLitNum((unsigned *)&t, pCutR->nLeaves, &p->vCnfMem) ); +// p->nCutMux += Mf_ManTtIsMux( t ); + assert( (int)pCutR->nLeaves <= nOldSupp ); +// Mf_ManTruthCanonicize( &t, pCutR->nLeaves ); + return (int)pCutR->nLeaves < nOldSupp; +} +static inline int Mf_CutComputeTruth( Mf_Man_t * p, Mf_Cut_t * pCut0, Mf_Cut_t * pCut1, int fCompl0, int fCompl1, Mf_Cut_t * pCutR, int fIsXor ) +{ + if ( p->pPars->nLutSize <= 6 ) + return Mf_CutComputeTruth6( p, pCut0, pCut1, fCompl0, fCompl1, pCutR, fIsXor ); + { + word uTruth[MF_TT_WORDS], uTruth0[MF_TT_WORDS], uTruth1[MF_TT_WORDS]; + int nOldSupp = pCutR->nLeaves, truthId; + int LutSize = p->pPars->nLutSize, fCompl; + int nWords = Abc_Truth6WordNum(LutSize); + word * pTruth0 = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut0->iFunc)); + word * pTruth1 = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut1->iFunc)); + Abc_TtCopy( uTruth0, pTruth0, nWords, Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ); + Abc_TtCopy( uTruth1, pTruth1, nWords, Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ); + Abc_TtExpand( uTruth0, LutSize, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + Abc_TtExpand( uTruth1, LutSize, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + if ( fIsXor ) + Abc_TtXor( uTruth, uTruth0, uTruth1, nWords, (fCompl = (int)((uTruth0[0] ^ uTruth1[0]) & 1)) ); + else + Abc_TtAnd( uTruth, uTruth0, uTruth1, nWords, (fCompl = (int)((uTruth0[0] & uTruth1[0]) & 1)) ); + pCutR->nLeaves = Abc_TtMinBase( uTruth, pCutR->pLeaves, pCutR->nLeaves, LutSize ); + assert( (uTruth[0] & 1) == 0 ); +//Kit_DsdPrintFromTruth( uTruth, pCutR->nLeaves ), printf("\n" ), printf("\n" ); + truthId = Vec_MemHashInsert(p->vTtMem, uTruth); + pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); + if ( (p->pPars->fGenCnf || p->pPars->fGenLit) && truthId == Vec_IntSize(&p->vCnfSizes) && LutSize <= 8 ) + Vec_IntPush( &p->vCnfSizes, p->pPars->fGenCnf ? Abc_Tt8CnfSize(uTruth, pCutR->nLeaves) : Kit_TruthLitNum((unsigned *)uTruth, pCutR->nLeaves, &p->vCnfMem) ); + assert( (int)pCutR->nLeaves <= nOldSupp ); + return (int)pCutR->nLeaves < nOldSupp; + } +} +static inline int Mf_CutComputeTruthMux6( Mf_Man_t * p, Mf_Cut_t * pCut0, Mf_Cut_t * pCut1, Mf_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, Mf_Cut_t * pCutR ) +{ + int nOldSupp = pCutR->nLeaves, truthId, fCompl; word t; + word t0 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut0->iFunc)); + word t1 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut1->iFunc)); + word tC = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCutC->iFunc)); + if ( Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ) t0 = ~t0; + if ( Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ) t1 = ~t1; + if ( Abc_LitIsCompl(pCutC->iFunc) ^ fComplC ) tC = ~tC; + t0 = Abc_Tt6Expand( t0, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + t1 = Abc_Tt6Expand( t1, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + tC = Abc_Tt6Expand( tC, pCutC->pLeaves, pCutC->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + t = (tC & t1) | (~tC & t0); + if ( (fCompl = (int)(t & 1)) ) t = ~t; + pCutR->nLeaves = Abc_Tt6MinBase( &t, pCutR->pLeaves, pCutR->nLeaves ); + assert( (int)(t & 1) == 0 ); + truthId = Vec_MemHashInsert(p->vTtMem, &t); + pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); + if ( (p->pPars->fGenCnf || p->pPars->fGenLit) && truthId == Vec_IntSize(&p->vCnfSizes) ) + Vec_IntPush( &p->vCnfSizes, p->pPars->fGenCnf ? Abc_Tt6CnfSize(t, pCutR->nLeaves) : Kit_TruthLitNum((unsigned *)&t, pCutR->nLeaves, &p->vCnfMem) ); + assert( (int)pCutR->nLeaves <= nOldSupp ); + return (int)pCutR->nLeaves < nOldSupp; +} +static inline int Mf_CutComputeTruthMux( Mf_Man_t * p, Mf_Cut_t * pCut0, Mf_Cut_t * pCut1, Mf_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, Mf_Cut_t * pCutR ) +{ + if ( p->pPars->nLutSize <= 6 ) + return Mf_CutComputeTruthMux6( p, pCut0, pCut1, pCutC, fCompl0, fCompl1, fComplC, pCutR ); + { + word uTruth[MF_TT_WORDS], uTruth0[MF_TT_WORDS], uTruth1[MF_TT_WORDS], uTruthC[MF_TT_WORDS]; + int nOldSupp = pCutR->nLeaves, truthId; + int LutSize = p->pPars->nLutSize, fCompl; + int nWords = Abc_Truth6WordNum(LutSize); + word * pTruth0 = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut0->iFunc)); + word * pTruth1 = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut1->iFunc)); + word * pTruthC = Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCutC->iFunc)); + Abc_TtCopy( uTruth0, pTruth0, nWords, Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ); + Abc_TtCopy( uTruth1, pTruth1, nWords, Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ); + Abc_TtCopy( uTruthC, pTruthC, nWords, Abc_LitIsCompl(pCutC->iFunc) ^ fComplC ); + Abc_TtExpand( uTruth0, LutSize, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + Abc_TtExpand( uTruth1, LutSize, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + Abc_TtExpand( uTruthC, LutSize, pCutC->pLeaves, pCutC->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + Abc_TtMux( uTruth, uTruthC, uTruth1, uTruth0, nWords ); + fCompl = (int)(uTruth[0] & 1); + if ( fCompl ) Abc_TtNot( uTruth, nWords ); + pCutR->nLeaves = Abc_TtMinBase( uTruth, pCutR->pLeaves, pCutR->nLeaves, LutSize ); + assert( (uTruth[0] & 1) == 0 ); + truthId = Vec_MemHashInsert(p->vTtMem, uTruth); + pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); + if ( (p->pPars->fGenCnf || p->pPars->fGenLit) && truthId == Vec_IntSize(&p->vCnfSizes) && LutSize <= 8 ) + Vec_IntPush( &p->vCnfSizes, p->pPars->fGenCnf ? Abc_Tt8CnfSize(uTruth, pCutR->nLeaves) : Kit_TruthLitNum((unsigned *)uTruth, pCutR->nLeaves, &p->vCnfMem) ); + assert( (int)pCutR->nLeaves <= nOldSupp ); + return (int)pCutR->nLeaves < nOldSupp; + } +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Mf_CutCountBits( word i ) +{ + i = i - ((i >> 1) & 0x5555555555555555); + i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333); + i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F); + return (i*(0x0101010101010101))>>56; +} +static inline word Mf_CutGetSign( int * pLeaves, int nLeaves ) +{ + word Sign = 0; int i; + for ( i = 0; i < nLeaves; i++ ) + Sign |= ((word)1) << (pLeaves[i] & 0x3F); + return Sign; +} +static inline int Mf_CutCreateUnit( Mf_Cut_t * p, int i ) +{ + p->Delay = 0; + p->Flow = 0; + p->iFunc = 2; + p->nLeaves = 1; + p->pLeaves[0] = i; + p->Sign = ((word)1) << (i & 0x3F); + return 1; +} +static inline void Mf_CutPrint( Mf_Man_t * p, Mf_Cut_t * pCut ) +{ + int i, nDigits = Abc_Base10Log(Gia_ManObjNum(p->pGia)); + printf( "%d {", pCut->nLeaves ); + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + printf( " %*d", nDigits, pCut->pLeaves[i] ); + for ( ; i < (int)p->pPars->nLutSize; i++ ) + printf( " %*s", nDigits, " " ); + printf( " } D = %4d A = %9.4f F = %6d ", + pCut->Delay, pCut->Flow, pCut->iFunc ); + if ( p->vTtMem ) + { + if ( p->pPars->fGenCnf ) + printf( "CNF = %2d ", Vec_IntEntry(&p->vCnfSizes, Abc_Lit2Var(pCut->iFunc)) ); + if ( p->pPars->fGenLit ) + printf( "Lit = %2d ", Vec_IntEntry(&p->vCnfSizes, Abc_Lit2Var(pCut->iFunc)) ); + Dau_DsdPrintFromTruth( Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut->iFunc)), pCut->nLeaves ); + } + else + printf( "\n" ); +} +static inline int Mf_ManPrepareCuts( Mf_Cut_t * pCuts, Mf_Man_t * p, int iObj, int fAddUnit ) +{ + if ( Mf_ManObj(p, iObj)->iCutSet ) + { + Mf_Cut_t * pMfCut = pCuts; + int i, * pCut, * pList = Mf_ObjCutSet(p, iObj); + Mf_SetForEachCut( pList, pCut, i ) + { + pMfCut->Delay = 0; + pMfCut->Flow = 0; + pMfCut->iFunc = Mf_CutFunc( pCut ); + pMfCut->nLeaves = Mf_CutSize( pCut ); + pMfCut->Sign = Mf_CutGetSign( pCut+1, Mf_CutSize(pCut) ); + memcpy( pMfCut->pLeaves, pCut+1, sizeof(int) * Mf_CutSize(pCut) ); + pMfCut++; + } + if ( fAddUnit && pCuts->nLeaves > 1 ) + return pList[0] + Mf_CutCreateUnit( pMfCut, iObj ); + return pList[0]; + } + return Mf_CutCreateUnit( pCuts, iObj ); +} +static inline int Mf_ManSaveCuts( Mf_Man_t * p, Mf_Cut_t ** pCuts, int nCuts ) +{ + int i, * pPlace, iCur, nInts = 1; + for ( i = 0; i < nCuts; i++ ) + nInts += pCuts[i]->nLeaves + 1; + if ( (p->iCur & 0xFFFF) + nInts > 0xFFFF ) + p->iCur = ((p->iCur >> 16) + 1) << 16; + if ( Vec_PtrSize(&p->vPages) == (p->iCur >> 16) ) + Vec_PtrPush( &p->vPages, ABC_ALLOC(int, (1<<16)) ); + iCur = p->iCur; p->iCur += nInts; + pPlace = Mf_ManCutSet( p, iCur ); + *pPlace++ = nCuts; + for ( i = 0; i < nCuts; i++ ) + { + *pPlace++ = Mf_CutSetBoth(pCuts[i]->nLeaves, pCuts[i]->iFunc); + memcpy( pPlace, pCuts[i]->pLeaves, sizeof(int) * pCuts[i]->nLeaves ); + pPlace += pCuts[i]->nLeaves; + } + return iCur; +} +static inline void Mf_ObjSetBestCut( int * pCuts, int * pCut ) +{ + assert( pCuts < pCut ); + if ( ++pCuts < pCut ) + { + int pTemp[MF_CUT_MAX*(MF_LEAF_MAX+2)]; + int nBlock = pCut - pCuts; + int nSize = Mf_CutSize(pCut) + 1; + memmove( pTemp, pCuts, sizeof(int) * nBlock ); + memmove( pCuts, pCut, sizeof(int) * nSize ); + memmove( pCuts + nSize, pTemp, sizeof(int) * nBlock ); + } +} + +/**Function************************************************************* + + Synopsis [Check correctness of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Mf_CutCheck( Mf_Cut_t * pBase, Mf_Cut_t * pCut ) // check if pCut is contained in pBase +{ + int nSizeB = pBase->nLeaves; + int nSizeC = pCut->nLeaves; + int i, * pB = pBase->pLeaves; + int k, * pC = pCut->pLeaves; + for ( i = 0; i < nSizeC; i++ ) + { + for ( k = 0; k < nSizeB; k++ ) + if ( pC[i] == pB[k] ) + break; + if ( k == nSizeB ) + return 0; + } + return 1; +} +static inline int Mf_SetCheckArray( Mf_Cut_t ** ppCuts, int nCuts ) +{ + Mf_Cut_t * pCut0, * pCut1; + int i, k, m, n, Value; + assert( nCuts > 0 ); + for ( i = 0; i < nCuts; i++ ) + { + pCut0 = ppCuts[i]; + assert( pCut0->nLeaves <= MF_LEAF_MAX ); + assert( pCut0->Sign == Mf_CutGetSign(pCut0->pLeaves, pCut0->nLeaves) ); + // check duplicates + for ( m = 0; m < (int)pCut0->nLeaves; m++ ) + for ( n = m + 1; n < (int)pCut0->nLeaves; n++ ) + assert( pCut0->pLeaves[m] < pCut0->pLeaves[n] ); + // check pairs + for ( k = 0; k < nCuts; k++ ) + { + pCut1 = ppCuts[k]; + if ( pCut0 == pCut1 ) + continue; + // check containments + Value = Mf_CutCheck( pCut0, pCut1 ); + assert( Value == 0 ); + } + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Mf_CutMergeOrder( Mf_Cut_t * pCut0, Mf_Cut_t * pCut1, Mf_Cut_t * pCut, int nLutSize ) +{ + int nSize0 = pCut0->nLeaves; + int nSize1 = pCut1->nLeaves; + int i, * pC0 = pCut0->pLeaves; + int k, * pC1 = pCut1->pLeaves; + int c, * pC = pCut->pLeaves; + // the case of the largest cut sizes + if ( nSize0 == nLutSize && nSize1 == nLutSize ) + { + for ( i = 0; i < nSize0; i++ ) + { + if ( pC0[i] != pC1[i] ) return 0; + pC[i] = pC0[i]; + } + pCut->nLeaves = nLutSize; + pCut->iFunc = MF_NO_FUNC; + pCut->Sign = pCut0->Sign | pCut1->Sign; + return 1; + } + // compare two cuts with different numbers + i = k = c = 0; + if ( nSize0 == 0 ) goto FlushCut1; + if ( nSize1 == 0 ) goto FlushCut0; + while ( 1 ) + { + if ( c == nLutSize ) return 0; + if ( pC0[i] < pC1[k] ) + { + pC[c++] = pC0[i++]; + if ( i >= nSize0 ) goto FlushCut1; + } + else if ( pC0[i] > pC1[k] ) + { + pC[c++] = pC1[k++]; + if ( k >= nSize1 ) goto FlushCut0; + } + else + { + pC[c++] = pC0[i++]; k++; + if ( i >= nSize0 ) goto FlushCut1; + if ( k >= nSize1 ) goto FlushCut0; + } + } + +FlushCut0: + if ( c + nSize0 > nLutSize + i ) return 0; + while ( i < nSize0 ) + pC[c++] = pC0[i++]; + pCut->nLeaves = c; + pCut->iFunc = MF_NO_FUNC; + pCut->Sign = pCut0->Sign | pCut1->Sign; + return 1; + +FlushCut1: + if ( c + nSize1 > nLutSize + k ) return 0; + while ( k < nSize1 ) + pC[c++] = pC1[k++]; + pCut->nLeaves = c; + pCut->iFunc = MF_NO_FUNC; + pCut->Sign = pCut0->Sign | pCut1->Sign; + return 1; +} +static inline int Mf_CutMergeOrderMux( Mf_Cut_t * pCut0, Mf_Cut_t * pCut1, Mf_Cut_t * pCut2, Mf_Cut_t * pCut, int nLutSize ) +{ + int x0, i0 = 0, nSize0 = pCut0->nLeaves, * pC0 = pCut0->pLeaves; + int x1, i1 = 0, nSize1 = pCut1->nLeaves, * pC1 = pCut1->pLeaves; + int x2, i2 = 0, nSize2 = pCut2->nLeaves, * pC2 = pCut2->pLeaves; + int xMin, c = 0, * pC = pCut->pLeaves; + while ( 1 ) + { + x0 = (i0 == nSize0) ? ABC_INFINITY : pC0[i0]; + x1 = (i1 == nSize1) ? ABC_INFINITY : pC1[i1]; + x2 = (i2 == nSize2) ? ABC_INFINITY : pC2[i2]; + xMin = Abc_MinInt( Abc_MinInt(x0, x1), x2 ); + if ( xMin == ABC_INFINITY ) break; + if ( c == nLutSize ) return 0; + pC[c++] = xMin; + if (x0 == xMin) i0++; + if (x1 == xMin) i1++; + if (x2 == xMin) i2++; + } + pCut->nLeaves = c; + pCut->iFunc = MF_NO_FUNC; + pCut->Sign = pCut0->Sign | pCut1->Sign | pCut2->Sign; + return 1; +} +static inline int Mf_SetCutIsContainedOrder( Mf_Cut_t * pBase, Mf_Cut_t * pCut ) // check if pCut is contained in pBase +{ + int i, nSizeB = pBase->nLeaves; + int k, nSizeC = pCut->nLeaves; + if ( nSizeB == nSizeC ) + { + for ( i = 0; i < nSizeB; i++ ) + if ( pBase->pLeaves[i] != pCut->pLeaves[i] ) + return 0; + return 1; + } + assert( nSizeB > nSizeC ); + if ( nSizeC == 0 ) + return 1; + for ( i = k = 0; i < nSizeB; i++ ) + { + if ( pBase->pLeaves[i] > pCut->pLeaves[k] ) + return 0; + if ( pBase->pLeaves[i] == pCut->pLeaves[k] ) + { + if ( ++k == nSizeC ) + return 1; + } + } + return 0; +} +static inline int Mf_SetLastCutIsContained( Mf_Cut_t ** pCuts, int nCuts ) +{ + int i; + for ( i = 0; i < nCuts; i++ ) + if ( pCuts[i]->nLeaves <= pCuts[nCuts]->nLeaves && (pCuts[i]->Sign & pCuts[nCuts]->Sign) == pCuts[i]->Sign && Mf_SetCutIsContainedOrder(pCuts[nCuts], pCuts[i]) ) + return 1; + return 0; +} +static inline int Mf_SetLastCutContainsArea( Mf_Cut_t ** pCuts, int nCuts ) +{ + int i, k, fChanges = 0; + for ( i = 0; i < nCuts; i++ ) + if ( pCuts[nCuts]->nLeaves < pCuts[i]->nLeaves && (pCuts[nCuts]->Sign & pCuts[i]->Sign) == pCuts[nCuts]->Sign && Mf_SetCutIsContainedOrder(pCuts[i], pCuts[nCuts]) ) + pCuts[i]->nLeaves = MF_NO_LEAF, fChanges = 1; + if ( !fChanges ) + return nCuts; + for ( i = k = 0; i <= nCuts; i++ ) + { + if ( pCuts[i]->nLeaves == MF_NO_LEAF ) + continue; + if ( k < i ) + ABC_SWAP( Mf_Cut_t *, pCuts[k], pCuts[i] ); + k++; + } + return k - 1; +} +static inline int Mf_CutCompareArea( Mf_Cut_t * pCut0, Mf_Cut_t * pCut1 ) +{ + if ( pCut0->Flow < pCut1->Flow - MF_EPSILON ) return -1; + if ( pCut0->Flow > pCut1->Flow + MF_EPSILON ) return 1; + if ( pCut0->Delay < pCut1->Delay ) return -1; + if ( pCut0->Delay > pCut1->Delay ) return 1; + if ( pCut0->nLeaves < pCut1->nLeaves ) return -1; + if ( pCut0->nLeaves > pCut1->nLeaves ) return 1; + return 0; +} +static inline void Mf_SetSortByArea( Mf_Cut_t ** pCuts, int nCuts ) +{ + int i; + for ( i = nCuts; i > 0; i-- ) + { + if ( Mf_CutCompareArea(pCuts[i - 1], pCuts[i]) < 0 )//!= 1 ) + return; + ABC_SWAP( Mf_Cut_t *, pCuts[i - 1], pCuts[i] ); + } +} +static inline int Mf_SetAddCut( Mf_Cut_t ** pCuts, int nCuts, int nCutNum ) +{ + if ( nCuts == 0 ) + return 1; + nCuts = Mf_SetLastCutContainsArea(pCuts, nCuts); + Mf_SetSortByArea( pCuts, nCuts ); + return Abc_MinInt( nCuts + 1, nCutNum - 1 ); +} +static inline int Mf_CutArea( Mf_Man_t * p, int nLeaves, int iFunc ) +{ + if ( nLeaves < 2 ) + return 0; + if ( p->pPars->fGenCnf || p->pPars->fGenLit ) + return Vec_IntEntry(&p->vCnfSizes, Abc_Lit2Var(iFunc)); + if ( p->pPars->fOptEdge ) + return nLeaves + p->pPars->nAreaTuner; + return 1; +} +static inline void Mf_CutParams( Mf_Man_t * p, Mf_Cut_t * pCut, float FlowRefs ) +{ + Mf_Obj_t * pBest; + int i, nLeaves = pCut->nLeaves; + assert( nLeaves <= p->pPars->nLutSize ); + pCut->Delay = 0; + pCut->Flow = 0; + for ( i = 0; i < nLeaves; i++ ) + { + pBest = Mf_ManObj(p, pCut->pLeaves[i]); + pCut->Delay = Abc_MaxInt( pCut->Delay, pBest->Delay ); + pCut->Flow += pBest->Flow; + } + pCut->Delay += (int)(nLeaves > 1); + pCut->Flow = (pCut->Flow + Mf_CutArea(p, nLeaves, pCut->iFunc)) / FlowRefs; +} +void Mf_ObjMergeOrder( Mf_Man_t * p, int iObj ) +{ + Mf_Cut_t pCuts0[MF_CUT_MAX], pCuts1[MF_CUT_MAX], pCuts[MF_CUT_MAX], * pCutsR[MF_CUT_MAX]; + Gia_Obj_t * pObj = Gia_ManObj(p->pGia, iObj); + Mf_Obj_t * pBest = Mf_ManObj(p, iObj); + int nLutSize = p->pPars->nLutSize; + int nCutNum = p->pPars->nCutNum; + int nCuts0 = Mf_ManPrepareCuts(pCuts0, p, Gia_ObjFaninId0(pObj, iObj), 1); + int nCuts1 = Mf_ManPrepareCuts(pCuts1, p, Gia_ObjFaninId1(pObj, iObj), 1); + int fComp0 = Gia_ObjFaninC0(pObj); + int fComp1 = Gia_ObjFaninC1(pObj); + int iSibl = Gia_ObjSibl(p->pGia, iObj); + Mf_Cut_t * pCut0, * pCut1, * pCut0Lim = pCuts0 + nCuts0, * pCut1Lim = pCuts1 + nCuts1; + int i, nCutsR = 0; + for ( i = 0; i < nCutNum; i++ ) + pCutsR[i] = pCuts + i; + if ( iSibl ) + { + Mf_Cut_t pCuts2[MF_CUT_MAX]; + Gia_Obj_t * pObjE = Gia_ObjSiblObj(p->pGia, iObj); + int fCompE = Gia_ObjPhase(pObj) ^ Gia_ObjPhase(pObjE); + int nCuts2 = Mf_ManPrepareCuts(pCuts2, p, iSibl, 0); + Mf_Cut_t * pCut2, * pCut2Lim = pCuts2 + nCuts2; + for ( pCut2 = pCuts2; pCut2 < pCut2Lim; pCut2++ ) + { + *pCutsR[nCutsR] = *pCut2; + if ( pCutsR[nCutsR]->iFunc >= 0 ) + pCutsR[nCutsR]->iFunc = Abc_LitNotCond( pCutsR[nCutsR]->iFunc, fCompE ); + Mf_CutParams( p, pCutsR[nCutsR], pBest->nFlowRefs ); + nCutsR = Mf_SetAddCut( pCutsR, nCutsR, nCutNum ); + } + } + if ( Gia_ObjIsMuxId(p->pGia, iObj) ) + { + Mf_Cut_t pCuts2[MF_CUT_MAX]; + int nCuts2 = Mf_ManPrepareCuts(pCuts2, p, Gia_ObjFaninId2(p->pGia, iObj), 1); + int fComp2 = Gia_ObjFaninC2(p->pGia, pObj); + Mf_Cut_t * pCut2, * pCut2Lim = pCuts2 + nCuts2; + p->CutCount[0] += nCuts0 * nCuts1 * nCuts2; + for ( pCut0 = pCuts0; pCut0 < pCut0Lim; pCut0++ ) + for ( pCut1 = pCuts1; pCut1 < pCut1Lim; pCut1++ ) + for ( pCut2 = pCuts2; pCut2 < pCut2Lim; pCut2++ ) + { + if ( Mf_CutCountBits(pCut0->Sign | pCut1->Sign | pCut2->Sign) > nLutSize ) + continue; + p->CutCount[1]++; + if ( !Mf_CutMergeOrderMux(pCut0, pCut1, pCut2, pCutsR[nCutsR], nLutSize) ) + continue; + if ( Mf_SetLastCutIsContained(pCutsR, nCutsR) ) + continue; + p->CutCount[2]++; + if ( p->pPars->fCutMin && Mf_CutComputeTruthMux(p, pCut0, pCut1, pCut2, fComp0, fComp1, fComp2, pCutsR[nCutsR]) ) + pCutsR[nCutsR]->Sign = Mf_CutGetSign(pCutsR[nCutsR]->pLeaves, pCutsR[nCutsR]->nLeaves); + Mf_CutParams( p, pCutsR[nCutsR], pBest->nFlowRefs ); + nCutsR = Mf_SetAddCut( pCutsR, nCutsR, nCutNum ); + } + } + else + { + int fIsXor = Gia_ObjIsXor(pObj); + p->CutCount[0] += nCuts0 * nCuts1; + for ( pCut0 = pCuts0; pCut0 < pCut0Lim; pCut0++ ) + for ( pCut1 = pCuts1; pCut1 < pCut1Lim; pCut1++ ) + { + if ( (int)(pCut0->nLeaves + pCut1->nLeaves) > nLutSize && Mf_CutCountBits(pCut0->Sign | pCut1->Sign) > nLutSize ) + continue; + p->CutCount[1]++; + if ( !Mf_CutMergeOrder(pCut0, pCut1, pCutsR[nCutsR], nLutSize) ) + continue; + if ( Mf_SetLastCutIsContained(pCutsR, nCutsR) ) + continue; + p->CutCount[2]++; + if ( p->pPars->fCutMin && Mf_CutComputeTruth(p, pCut0, pCut1, fComp0, fComp1, pCutsR[nCutsR], fIsXor) ) + pCutsR[nCutsR]->Sign = Mf_CutGetSign(pCutsR[nCutsR]->pLeaves, pCutsR[nCutsR]->nLeaves); + Mf_CutParams( p, pCutsR[nCutsR], pBest->nFlowRefs ); + nCutsR = Mf_SetAddCut( pCutsR, nCutsR, nCutNum ); + } + } + // debug printout + if ( 0 ) +// if ( iObj % 1000 == 0 ) +// if ( iObj == 474 ) + { + printf( "*** Obj = %d FlowRefs = %.2f MapRefs = %2d\n", iObj, pBest->nFlowRefs, pBest->nMapRefs ); + for ( i = 0; i < nCutsR; i++ ) + Mf_CutPrint( p, pCutsR[i] ); + printf( "\n" ); + } + // store the cutset + pBest->Flow = pCutsR[0]->Flow; + pBest->Delay = pCutsR[0]->Delay; + pBest->iCutSet = Mf_ManSaveCuts( p, pCutsR, nCutsR ); + // verify + assert( nCutsR > 0 && nCutsR < nCutNum ); +// assert( Mf_SetCheckArray(pCutsR, nCutsR) ); + p->nCutCounts[pCutsR[0]->nLeaves]++; + p->CutCount[3] += nCutsR; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mf_ManSetFlowRefs( Gia_Man_t * p, Vec_Int_t * vRefs ) +{ + int fDiscount = 1; + Gia_Obj_t * pObj, * pCtrl, * pData0, * pData1; + int i, Id; + Vec_IntFill( vRefs, Gia_ManObjNum(p), 0 ); + Gia_ManForEachAnd( p, pObj, i ) + { + if ( Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) ) + Vec_IntAddToEntry( vRefs, Gia_ObjFaninId0(pObj, i), 1 ); + if ( Gia_ObjIsAnd(Gia_ObjFanin1(pObj)) ) + Vec_IntAddToEntry( vRefs, Gia_ObjFaninId1(pObj, i), 1 ); + if ( p->pMuxes ) + { + if ( Gia_ObjIsMuxId(p, i) && Gia_ObjIsAnd(Gia_ObjFanin2(p, pObj)) ) + Vec_IntAddToEntry( vRefs, Gia_ObjFaninId2(p, i), 1 ); + } + else if ( fDiscount && Gia_ObjIsMuxType(pObj) ) // discount XOR/MUX + { + pCtrl = Gia_Regular(Gia_ObjRecognizeMux(pObj, &pData1, &pData0)); + pData0 = Gia_Regular(pData0); + pData1 = Gia_Regular(pData1); + if ( Gia_ObjIsAnd(pCtrl) ) + Vec_IntAddToEntry( vRefs, Gia_ObjId(p, pCtrl), -1 ); + if ( pData0 == pData1 && Gia_ObjIsAnd(pData0) ) + Vec_IntAddToEntry( vRefs, Gia_ObjId(p, pData0), -1 ); + } + } + Gia_ManForEachCoDriverId( p, Id, i ) + if ( Gia_ObjIsAnd(Gia_ManObj(p, Id)) ) + Vec_IntAddToEntry( vRefs, Id, 1 ); + for ( i = 0; i < Vec_IntSize(vRefs); i++ ) + Vec_IntUpdateEntry( vRefs, i, 1 ); +} +int Mf_ManSetMapRefs( Mf_Man_t * p ) +{ + float Coef = 1.0 / (1.0 + (p->Iter + 1) * (p->Iter + 1)); + int * pCut, i, k, Id; + // compute delay + int Delay = 0; + Gia_ManForEachCoDriverId( p->pGia, Id, i ) + Delay = Abc_MaxInt( Delay, Mf_ManObj(p, Id)->Delay ); + // check delay target + if ( p->pPars->DelayTarget == -1 && p->pPars->nRelaxRatio ) + p->pPars->DelayTarget = (int)((float)Delay * (100.0 + p->pPars->nRelaxRatio) / 100.0); + if ( p->pPars->DelayTarget != -1 ) + { + if ( Delay < p->pPars->DelayTarget + 0.01 ) + Delay = p->pPars->DelayTarget; + else if ( p->pPars->nRelaxRatio == 0 ) + Abc_Print( 0, "Relaxing user-specified delay target from %d to %d.\n", p->pPars->DelayTarget, Delay ); + } + p->pPars->Delay = Delay; + // check references +// Gia_ManForEachAndId( p->pGia, i ) +// assert( Mf_ManObj(p, i)->nMapRefs == 0 ); + // compute area and edges + if ( !p->fUseEla ) + Gia_ManForEachCoDriverId( p->pGia, Id, i ) + Mf_ObjMapRefInc( p, Id ); + p->pPars->Area = p->pPars->Edge = p->pPars->Clause = 0; + Gia_ManForEachAndReverseId( p->pGia, i ) + { + if ( !Mf_ObjMapRefNum(p, i) ) + continue; + pCut = Mf_ObjCutBest( p, i ); + if ( !p->fUseEla ) + for ( k = 1; k <= Mf_CutSize(pCut); k++ ) + Mf_ObjMapRefInc( p, pCut[k] ); + p->pPars->Edge += Mf_CutSize(pCut); + p->pPars->Area++; + if ( p->pPars->fGenCnf || p->pPars->fGenLit ) + p->pPars->Clause += Mf_CutArea(p, Mf_CutSize(pCut), Mf_CutFunc(pCut)); + } + // blend references + for ( i = 0; i < Gia_ManObjNum(p->pGia); i++ ) + p->pLfObjs[i].nFlowRefs = Coef * p->pLfObjs[i].nFlowRefs + (1.0 - Coef) * Abc_MaxFloat(1, p->pLfObjs[i].nMapRefs); +// p->pLfObjs[i]. = 0.2 * p->pLfObjs[i]. + 0.8 * Abc_MaxFloat(1, p->pLfObjs[i].nMapRefs); + return p->pPars->Area; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Mf_ManDeriveMapping( Mf_Man_t * p ) +{ + Vec_Int_t * vMapping; + int i, k, * pCut; + assert( !p->pPars->fCutMin && p->pGia->vMapping == NULL ); + vMapping = Vec_IntAlloc( Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + (int)p->pPars->Area * 2 ); + Vec_IntFill( vMapping, Gia_ManObjNum(p->pGia), 0 ); + Gia_ManForEachAndId( p->pGia, i ) + { + if ( !Mf_ObjMapRefNum(p, i) ) + continue; + pCut = Mf_ObjCutBest( p, i ); + Vec_IntWriteEntry( vMapping, i, Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, Mf_CutSize(pCut) ); + for ( k = 1; k <= Mf_CutSize(pCut); k++ ) + Vec_IntPush( vMapping, pCut[k] ); + Vec_IntPush( vMapping, i ); + } + assert( Vec_IntCap(vMapping) == 16 || Vec_IntSize(vMapping) == Vec_IntCap(vMapping) ); + p->pGia->vMapping = vMapping; + return p->pGia; +} +Gia_Man_t * Mf_ManDeriveMappingCoarse( Mf_Man_t * p ) +{ + Gia_Man_t * pNew, * pGia = p->pGia; + Gia_Obj_t * pObj; + int i, k, * pCut; + assert( !p->pPars->fCutMin && pGia->pMuxes ); + // create new manager + pNew = Gia_ManStart( Gia_ManObjNum(pGia) ); + pNew->pName = Abc_UtilStrsav( pGia->pName ); + pNew->pSpec = Abc_UtilStrsav( pGia->pSpec ); + // map primary inputs + Gia_ManConst0(pGia)->Value = 0; + Gia_ManForEachCi( pGia, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + // start mapping + pNew->vMapping = Vec_IntAlloc( Gia_ManObjNum(pGia) + 2*Gia_ManXorNum(pGia) + 2*Gia_ManMuxNum(pGia) + (int)p->pPars->Edge + (int)p->pPars->Area * 2 ); + Vec_IntFill( pNew->vMapping, Gia_ManObjNum(pGia) + 2*Gia_ManXorNum(pGia) + 2*Gia_ManMuxNum(pGia), 0 ); + // iterate through nodes used in the mapping + Gia_ManForEachAnd( pGia, pObj, i ) + { + if ( Gia_ObjIsMuxId(pGia, i) ) + pObj->Value = Gia_ManAppendMux( pNew, Gia_ObjFanin2Copy(pGia, pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsXor(pObj) ) + pObj->Value = Gia_ManAppendXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( !Mf_ObjMapRefNum(p, i) ) + continue; + pCut = Mf_ObjCutBest( p, i ); + Vec_IntWriteEntry( pNew->vMapping, Abc_Lit2Var(pObj->Value), Vec_IntSize(pNew->vMapping) ); + Vec_IntPush( pNew->vMapping, Mf_CutSize(pCut)); + for ( k = 1; k <= Mf_CutSize(pCut); k++ ) + Vec_IntPush( pNew->vMapping, Abc_Lit2Var(Gia_ManObj(pGia, pCut[k])->Value) ); + Vec_IntPush( pNew->vMapping, Abc_Lit2Var(pObj->Value) ); + } + Gia_ManForEachCo( pGia, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia) ); + assert( Vec_IntCap(pNew->vMapping) == 16 || Vec_IntSize(pNew->vMapping) == Vec_IntCap(pNew->vMapping) ); + return pNew; +} +Gia_Man_t * Mf_ManDeriveMappingGia( Mf_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + Vec_Int_t * vCopies = Vec_IntStartFull( Gia_ManObjNum(p->pGia) ); + Vec_Int_t * vMapping = Vec_IntStart( 2 * Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + 2 * (int)p->pPars->Area ); + Vec_Int_t * vMapping2 = Vec_IntStart( (int)p->pPars->Edge + 2 * (int)p->pPars->Area + 1000 ); + Vec_Int_t * vCover = Vec_IntAlloc( 1 << 16 ); + Vec_Int_t * vLeaves = Vec_IntAlloc( 16 ); + int i, k, Id, iLit, * pCut; + word uTruth = 0, * pTruth = &uTruth; + assert( p->pPars->fCutMin ); + // create new manager + pNew = Gia_ManStart( Gia_ManObjNum(p->pGia) ); + pNew->pName = Abc_UtilStrsav( p->pGia->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pGia->pSpec ); + // map primary inputs + Vec_IntWriteEntry( vCopies, 0, 0 ); + Gia_ManForEachCiId( p->pGia, Id, i ) + Vec_IntWriteEntry( vCopies, Id, Gia_ManAppendCi(pNew) ); + // iterate through nodes used in the mapping + Gia_ManForEachAnd( p->pGia, pObj, i ) + { + if ( !Mf_ObjMapRefNum(p, i) ) + continue; + pCut = Mf_ObjCutBest( p, i ); + if ( Mf_CutSize(pCut) == 0 ) + { + assert( Abc_Lit2Var(Mf_CutFunc(pCut)) == 0 ); + Vec_IntWriteEntry( vCopies, i, Mf_CutFunc(pCut) ); + continue; + } + if ( Mf_CutSize(pCut) == 1 ) + { + assert( Abc_Lit2Var(Mf_CutFunc(pCut)) == 1 ); + iLit = Vec_IntEntry( vCopies, pCut[1] ); + Vec_IntWriteEntry( vCopies, i, Abc_LitNotCond(iLit, Abc_LitIsCompl(Mf_CutFunc(pCut))) ); + continue; + } + Vec_IntClear( vLeaves ); + for ( k = 1; k <= Mf_CutSize(pCut); k++ ) + Vec_IntPush( vLeaves, Vec_IntEntry(vCopies, pCut[k]) ); + pTruth = Vec_MemReadEntry( p->vTtMem, Abc_Lit2Var(Mf_CutFunc(pCut)) ); + iLit = Kit_TruthToGia( pNew, (unsigned *)pTruth, Vec_IntSize(vLeaves), vCover, vLeaves, 0 ); + Vec_IntWriteEntry( vCopies, i, Abc_LitNotCond(iLit, Abc_LitIsCompl(Mf_CutFunc(pCut))) ); + // create mapping + Vec_IntSetEntry( vMapping, Abc_Lit2Var(iLit), Vec_IntSize(vMapping2) ); + Vec_IntPush( vMapping2, Vec_IntSize(vLeaves) ); + Vec_IntForEachEntry( vLeaves, iLit, k ) + Vec_IntPush( vMapping2, Abc_Lit2Var(iLit) ); + Vec_IntPush( vMapping2, Abc_Lit2Var(Vec_IntEntry(vCopies, i)) ); + } + Gia_ManForEachCo( p->pGia, pObj, i ) + { + iLit = Vec_IntEntry( vCopies, Gia_ObjFaninId0p(p->pGia, pObj) ); + iLit = Gia_ManAppendCo( pNew, Abc_LitNotCond(iLit, Gia_ObjFaninC0(pObj)) ); + } + Vec_IntFree( vCopies ); + Vec_IntFree( vCover ); + Vec_IntFree( vLeaves ); + // finish mapping + if ( Vec_IntSize(vMapping) > Gia_ManObjNum(pNew) ) + Vec_IntShrink( vMapping, Gia_ManObjNum(pNew) ); + else + Vec_IntFillExtra( vMapping, Gia_ManObjNum(pNew), 0 ); + assert( Vec_IntSize(vMapping) == Gia_ManObjNum(pNew) ); + Vec_IntForEachEntry( vMapping, iLit, i ) + if ( iLit > 0 ) + Vec_IntAddToEntry( vMapping, i, Gia_ManObjNum(pNew) ); + Vec_IntAppend( vMapping, vMapping2 ); + Vec_IntFree( vMapping2 ); + // attach mapping and packing + assert( pNew->vMapping == NULL ); + pNew->vMapping = vMapping; + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p->pGia) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mf_Man_t * Mf_ManAlloc( Gia_Man_t * pGia, Jf_Par_t * pPars ) +{ + Mf_Man_t * p; + Vec_Int_t * vFlowRefs; + int i, Entry; + assert( pPars->nCutNum > 1 && pPars->nCutNum <= MF_CUT_MAX ); + assert( pPars->nLutSize > 1 && pPars->nLutSize <= MF_LEAF_MAX ); + ABC_FREE( pGia->pRefs ); + Vec_IntFreeP( &pGia->vMapping ); + if ( Gia_ManHasChoices(pGia) ) + Gia_ManSetPhase(pGia); + p = ABC_CALLOC( Mf_Man_t, 1 ); + p->clkStart = Abc_Clock(); + p->pGia = pGia; + p->pPars = pPars; + p->vTtMem = pPars->fCutMin ? Vec_MemAllocForTT( pPars->nLutSize, 0 ) : NULL; + p->pLfObjs = ABC_CALLOC( Mf_Obj_t, Gia_ManObjNum(pGia) ); + p->iCur = 2; + Vec_PtrGrow( &p->vPages, 256 ); + if ( pPars->fGenCnf || pPars->fGenLit ) + { + Vec_IntGrow( &p->vCnfSizes, 10000 ); + Vec_IntPush( &p->vCnfSizes, 1 ); + Vec_IntPush( &p->vCnfSizes, 2 ); + Vec_IntGrow( &p->vCnfMem, 10000 ); + } + vFlowRefs = Vec_IntAlloc(0); + Mf_ManSetFlowRefs( pGia, vFlowRefs ); + Vec_IntForEachEntry( vFlowRefs, Entry, i ) + p->pLfObjs[i].nFlowRefs = Entry; + Vec_IntFree(vFlowRefs); + return p; +} +void Mf_ManFree( Mf_Man_t * p ) +{ + assert( !p->pPars->fGenCnf || !p->pPars->fGenLit || Vec_IntSize(&p->vCnfSizes) == Vec_MemEntryNum(p->vTtMem) ); + if ( p->pPars->fCutMin ) + Vec_MemHashFree( p->vTtMem ); + if ( p->pPars->fCutMin ) + Vec_MemFree( p->vTtMem ); + Vec_PtrFreeData( &p->vPages ); + ABC_FREE( p->vCnfSizes.pArray ); + ABC_FREE( p->vCnfMem.pArray ); + ABC_FREE( p->vPages.pArray ); + ABC_FREE( p->vTemp.pArray ); + ABC_FREE( p->pLfObjs ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mf_ManSetDefaultPars( Jf_Par_t * pPars ) +{ + memset( pPars, 0, sizeof(Jf_Par_t) ); + pPars->nLutSize = 6; + pPars->nCutNum = 8; + pPars->nProcNum = 0; + pPars->nRounds = 2; + pPars->nRoundsEla = 1; + pPars->nRelaxRatio = 0; + pPars->nCoarseLimit = 3; + pPars->nAreaTuner = 1; + pPars->nVerbLimit = 5; + pPars->DelayTarget = -1; + pPars->fAreaOnly = 0; + pPars->fOptEdge = 1; + pPars->fCoarsen = 1; + pPars->fCutMin = 0; + pPars->fGenCnf = 0; + pPars->fGenLit = 0; + pPars->fPureAig = 0; + pPars->fVerbose = 0; + pPars->fVeryVerbose = 0; + pPars->nLutSizeMax = MF_LEAF_MAX; + pPars->nCutNumMax = MF_CUT_MAX; +} +void Mf_ManPrintStats( Mf_Man_t * p, char * pTitle ) +{ + if ( !p->pPars->fVerbose ) + return; + printf( "%s : ", pTitle ); + printf( "Level =%6lu ", (long)p->pPars->Delay ); + printf( "Area =%9lu ", (long)p->pPars->Area ); + printf( "Edge =%9lu ", (long)p->pPars->Edge ); + if ( p->pPars->fGenCnf ) + printf( "CNF =%9lu ", (long)p->pPars->Clause ); + if ( p->pPars->fGenLit ) + printf( "FFL =%9lu ", (long)p->pPars->Clause ); + Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); + fflush( stdout ); +} +void Mf_ManPrintInit( Mf_Man_t * p ) +{ + if ( !p->pPars->fVerbose ) + return; + printf( "LutSize = %d ", p->pPars->nLutSize ); + printf( "CutNum = %d ", p->pPars->nCutNum ); + printf( "Iter = %d ", p->pPars->nRounds + p->pPars->nRoundsEla ); + printf( "Edge = %d ", p->pPars->fOptEdge ); + printf( "CutMin = %d ", p->pPars->fCutMin ); + printf( "Coarse = %d ", p->pPars->fCoarsen ); + printf( "CNF = %d ", p->pPars->fGenCnf ); + printf( "FFL = %d ", p->pPars->fGenLit ); + printf( "\n" ); + printf( "Computing cuts...\r" ); + fflush( stdout ); +} +void Mf_ManPrintQuit( Mf_Man_t * p, Gia_Man_t * pNew ) +{ + float MemGia = Gia_ManMemory(p->pGia) / (1<<20); + float MemMan = 1.0 * sizeof(Mf_Obj_t) * Gia_ManObjNum(p->pGia) / (1<<20); + float MemCuts = 1.0 * sizeof(int) * (1 << 16) * Vec_PtrSize(&p->vPages) / (1<<20); + float MemTt = p->vTtMem ? Vec_MemMemory(p->vTtMem) / (1<<20) : 0; + float MemMap = Vec_IntMemory(pNew->vMapping) / (1<<20); + if ( p->CutCount[0] == 0 ) + p->CutCount[0] = 1; + if ( !p->pPars->fVerbose ) + return; + printf( "CutPair = %.0f ", p->CutCount[0] ); + printf( "Merge = %.0f (%.2f %%) ", p->CutCount[1], 100.0*p->CutCount[1]/p->CutCount[0] ); + printf( "Eval = %.0f (%.2f %%) ", p->CutCount[2], 100.0*p->CutCount[2]/p->CutCount[0] ); + printf( "Cut = %.0f (%.2f %%) ", p->CutCount[3], 100.0*p->CutCount[3]/p->CutCount[0] ); + printf( "\n" ); + printf( "Gia = %.2f MB ", MemGia ); + printf( "Man = %.2f MB ", MemMan ); + printf( "Cut = %.2f MB ", MemCuts ); + printf( "Map = %.2f MB ", MemMap ); + printf( "TT = %.2f MB ", MemTt ); + printf( "Total = %.2f MB", MemGia + MemMan + MemCuts + MemMap + MemTt ); + printf( "\n" ); + if ( 1 ) + { + int i; + for ( i = 0; i <= p->pPars->nLutSize; i++ ) + printf( "%d = %d ", i, p->nCutCounts[i] ); + if ( p->vTtMem ) + printf( "TT = %d (%.2f %%) ", Vec_MemEntryNum(p->vTtMem), 100.0 * Vec_MemEntryNum(p->vTtMem) / p->CutCount[2] ); + Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); + } + fflush( stdout ); +} +void Mf_ManComputeCuts( Mf_Man_t * p ) +{ + int i; + Gia_ManForEachAndId( p->pGia, i ) + Mf_ObjMergeOrder( p, i ); + Mf_ManSetMapRefs( p ); + Mf_ManPrintStats( p, (char *)(p->fUseEla ? "Ela " : (p->Iter ? "Area " : "Delay")) ); +} + +/**Function************************************************************* + + Synopsis [Flow and area.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mf_CutRef_rec( Mf_Man_t * p, int * pCut ) +{ + int i, Count = Mf_CutArea(p, Mf_CutSize(pCut), Mf_CutFunc(pCut)); + for ( i = 1; i <= Mf_CutSize(pCut); i++ ) + if ( !Mf_ObjMapRefInc(p, pCut[i]) && Mf_ManObj(p, pCut[i])->iCutSet ) + Count += Mf_CutRef_rec( p, Mf_ObjCutBest(p, pCut[i]) ); + return Count; +} +int Mf_CutDeref_rec( Mf_Man_t * p, int * pCut ) +{ + int i, Count = Mf_CutArea(p, Mf_CutSize(pCut), Mf_CutFunc(pCut)); + for ( i = 1; i <= Mf_CutSize(pCut); i++ ) + if ( !Mf_ObjMapRefDec(p, pCut[i]) && Mf_ManObj(p, pCut[i])->iCutSet ) + Count += Mf_CutDeref_rec( p, Mf_ObjCutBest(p, pCut[i]) ); + return Count; +} +static inline int Mf_CutAreaRefed( Mf_Man_t * p, int * pCut ) +{ + int Ela1 = Mf_CutDeref_rec( p, pCut ); + int Ela2 = Mf_CutRef_rec( p, pCut ); + assert( Ela1 == Ela2 ); + return Ela1; +} +static inline int Mf_CutAreaDerefed( Mf_Man_t * p, int * pCut ) +{ + int Ela1 = Mf_CutRef_rec( p, pCut ); + int Ela2 = Mf_CutDeref_rec( p, pCut ); + assert( Ela1 == Ela2 ); + return Ela1; +} +static inline int Mf_CutAreaMffc( Mf_Man_t * p, int iObj ) +{ + return Mf_ObjMapRefNum(p, iObj) ? + Mf_CutAreaRefed (p, Mf_ObjCutBest(p, iObj)) : + Mf_CutAreaDerefed(p, Mf_ObjCutBest(p, iObj)); +} + +int Mf_CutRef2_rec( Mf_Man_t * p, int * pCut, Vec_Int_t * vTemp, int Limit ) +{ + int i, Count = Mf_CutArea(p, Mf_CutSize(pCut), Mf_CutFunc(pCut)); + if ( Limit == 0 ) return Count; + for ( i = 1; i <= Mf_CutSize(pCut); i++ ) + { + Vec_IntPush( vTemp, pCut[i] ); + if ( !Mf_ObjMapRefInc(p, pCut[i]) && Mf_ManObj(p, pCut[i])->iCutSet ) + Count += Mf_CutRef2_rec( p, Mf_ObjCutBest(p, pCut[i]), vTemp, Limit-1 ); + } + return Count; +} +int Mf_CutDeref2_rec( Mf_Man_t * p, int * pCut, Vec_Int_t * vTemp, int Limit ) +{ + int i, Count = Mf_CutArea(p, Mf_CutSize(pCut), Mf_CutFunc(pCut)); + if ( Limit == 0 ) return Count; + for ( i = 1; i <= Mf_CutSize(pCut); i++ ) + { + Vec_IntPush( vTemp, pCut[i] ); + if ( !Mf_ObjMapRefDec(p, pCut[i]) && Mf_ManObj(p, pCut[i])->iCutSet ) + Count += Mf_CutDeref2_rec( p, Mf_ObjCutBest(p, pCut[i]), vTemp, Limit-1 ); + } + return Count; +} +static inline int Mf_CutAreaRefed2( Mf_Man_t * p, int * pCut ) +{ + int Ela1, iObj, i; + Vec_IntClear( &p->vTemp ); + Ela1 = Mf_CutDeref2_rec( p, pCut, &p->vTemp, 8 ); + Vec_IntForEachEntry( &p->vTemp, iObj, i ) + Mf_ObjMapRefInc( p, iObj ); + return Ela1; +} +static inline int Mf_CutAreaDerefed2( Mf_Man_t * p, int * pCut ) +{ + int Ela1, iObj, i; + Vec_IntClear( &p->vTemp ); + Ela1 = Mf_CutRef2_rec( p, pCut, &p->vTemp, 8 ); + Vec_IntForEachEntry( &p->vTemp, iObj, i ) + Mf_ObjMapRefDec( p, iObj ); + return Ela1; +} +static inline int Mf_CutAreaRefed2Multi( Mf_Man_t * p, int iObj, int ** ppCuts, int nCuts ) +{ + int Ela1 = 0, iTemp, i; + Vec_IntClear( &p->vTemp ); + for ( i = 0; i < nCuts; i++ ) + Ela1 += Mf_CutDeref2_rec( p, ppCuts[i], &p->vTemp, ABC_INFINITY ); + assert( Mf_ObjMapRefNum(p, iObj) == 0 ); + Vec_IntForEachEntry( &p->vTemp, iTemp, i ) + Mf_ObjMapRefInc( p, iTemp ); + return Ela1; +} + +static inline float Mf_CutFlow( Mf_Man_t * p, int * pCut, int * pTime ) +{ + Mf_Obj_t * pObj; + float Flow = 0; + int i, Time = 0; + for ( i = 1; i <= Mf_CutSize(pCut); i++ ) + { + pObj = Mf_ManObj( p, pCut[i] ); + Time = Abc_MaxInt( Time, pObj->Delay ); + Flow += pObj->Flow; + } + *pTime = Time + 1; + return Flow + Mf_CutArea(p, Mf_CutSize(pCut), Mf_CutFunc(pCut)); +} +static inline void Mf_ObjComputeBestCut( Mf_Man_t * p, int iObj ) +{ + Mf_Obj_t * pBest = Mf_ManObj(p, iObj); + int * pCutSet = Mf_ObjCutSet( p, iObj ); + int * pCut, * pCutBest = NULL; + int Value1 = -1, Value2 = -1; + int i, Time = 0, TimeBest = ABC_INFINITY; + float Flow, FlowBest = ABC_INFINITY; + if ( p->fUseEla && pBest->nMapRefs ) + Value1 = Mf_CutDeref_rec( p, Mf_ObjCutBest(p, iObj) ); + Mf_SetForEachCut( pCutSet, pCut, i ) + { + assert( !Mf_CutIsTriv(pCut, iObj) ); + assert( Mf_CutSize(pCut) <= p->pPars->nLutSize ); + Flow = p->fUseEla ? Mf_CutAreaDerefed2(p, pCut) : Mf_CutFlow(p, pCut, &Time); + if ( pCutBest == NULL || FlowBest > Flow + MF_EPSILON || (FlowBest > Flow - MF_EPSILON && TimeBest > Time) ) + pCutBest = pCut, FlowBest = Flow, TimeBest = Time; + } + assert( pCutBest != NULL ); + if ( p->fUseEla && pBest->nMapRefs ) + Value1 = Mf_CutRef_rec( p, pCutBest ); + else + pBest->nMapRefs = 0; + assert( Value1 >= Value2 ); + if ( p->fUseEla ) + Mf_CutFlow( p, pCutBest, &TimeBest ); + pBest->Delay = TimeBest; + pBest->Flow = FlowBest / Mf_ManObj(p, iObj)->nFlowRefs; + Mf_ObjSetBestCut( pCutSet, pCutBest ); +// Mf_CutPrint( Mf_ObjCutBest(p, iObj) ); printf( "\n" ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Mf_ManMappingFromMapping( Mf_Man_t * p ) +{ + Gia_Man_t * pGia = p->pGia0; + Gia_Obj_t * pObj; + int i, iObj, Count = 0; + Vec_Int_t * vMapping = Vec_IntAlloc( 3 * Gia_ManObjNum(pGia) ); + Vec_IntFill( vMapping, Gia_ManObjNum(pGia), 0 ); + Gia_ManForEachAnd( pGia, pObj, iObj ) + if ( Mf_ObjMapRefNum(p, iObj) ) + { + int * pCut = Mf_ObjCutBest(p, iObj); + Vec_IntWriteEntry( vMapping, iObj, Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, Mf_CutSize(pCut) ); + for ( i = 1; i <= Mf_CutSize(pCut); i++ ) + Vec_IntPush( vMapping, pCut[i] ); + Vec_IntPush( vMapping, iObj ); + Count++; + } + assert( pGia->vMapping == NULL ); + pGia->vMapping = vMapping; + printf( "Mapping is %.2fx larger than AIG manager.\n", 1.0*Vec_IntSize(vMapping)/Gia_ManObjNum(pGia) ); + return Count; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mf_ManPrintFanoutProfile( Mf_Man_t * p, Vec_Int_t * vFanCounts ) +{ + Gia_Man_t * pGia = p->pGia0; + int i, Count, nMax = Vec_IntFindMax( vFanCounts ); + Vec_Int_t * vCounts = Vec_IntStart( nMax + 1 ); + Vec_IntForEachEntry( vFanCounts, Count, i ) + if ( Count && Gia_ObjIsAnd(Gia_ManObj(pGia, i)) ) + Vec_IntAddToEntry( vCounts, Count, 1 ); + printf( "\nFanout distribution for internal nodes:\n" ); + Vec_IntForEachEntry( vCounts, Count, i ) + if ( Count ) printf( "Fanout = %5d : Nodes = %5d.\n", i, Count ); + printf( "Total nodes with fanout = %d. Max fanout = %d.\n\n", Vec_IntCountPositive(vCounts), nMax ); + Vec_IntFree( vCounts ); +} +int Mf_ManPrintMfccStats( Mf_Man_t * p, int iObj ) +{ + Gia_Man_t * pGia = p->pGia0; + int Area; + printf( "%5d : Level = %5d Refs = %5d Mffc = %5d\n", + iObj, Gia_ObjLevelId(pGia, iObj), Mf_ObjMapRefNum(p, iObj), (Area = Mf_CutAreaMffc(p, iObj)) ); + return Area; +} +void Mf_ManOptimizationOne( Mf_Man_t * p, int iObj ) +{ + Gia_Man_t * pGia = p->pGia0; + int * ppCuts[32], nCuts = 0; + int iFanout, i, nAreaSum = 0, nAreaBest = 0; + // skip pivots whose MFFC fanouts are pointed to by COs + Gia_ObjForEachFanoutStaticId( pGia, iObj, iFanout, i ) + if ( Gia_ObjIsCo(Gia_ManObj(pGia, iFanout)) ) + return; + // the pivot is used in the mapping as well as all of its fanouts + assert( Mf_ObjMapRefNum(p, iObj) > 1 ); + Gia_ObjForEachFanoutStaticId( pGia, iObj, iFanout, i ) + assert( Mf_ObjMapRefNum(p, iFanout) > 0 ); + // print this pivot and its fanouts + printf( "\nPivot node = %d\n", iObj ); + printf( "Pivot " ), Mf_ManPrintMfccStats( p, iObj ); + Gia_ObjForEachFanoutStaticId( pGia, iObj, iFanout, i ) + printf( "Node " ), nAreaSum += Mf_ManPrintMfccStats( p, iFanout ); + // calculate the shared MFFC + Gia_ObjForEachFanoutStaticId( pGia, iObj, iFanout, i ) + Mf_ObjMapRefInc( p, iFanout ); + Gia_ObjForEachFanoutStaticId( pGia, iObj, iFanout, i ) + ppCuts[nCuts++] = Mf_ObjCutBest( p, iFanout ); + nAreaBest = Mf_CutAreaRefed2Multi( p, iObj, ppCuts, nCuts ); + Gia_ObjForEachFanoutStaticId( pGia, iObj, iFanout, i ) + Mf_ObjMapRefDec( p, iFanout ); + printf( "Sum of MFFC sizes = %d\n", nAreaSum ); + printf( "Shared MFFC size = %d\n", nAreaBest ); +} +void Mf_ManOptimization( Mf_Man_t * p ) +{ + int nOutMax = 3; + Gia_Man_t * pGia = p->pGia0; + int i, Count, nNodes = Mf_ManMappingFromMapping( p ); + Gia_ManLevelNum( pGia ); + Gia_ManStaticMappingFanoutStart( pGia, NULL ); + Mf_ManPrintFanoutProfile( p, pGia->vFanoutNums ); + printf( "\nIndividual logic cones for mapping with %d nodes:\n", nNodes ); + Vec_IntForEachEntry( pGia->vFanoutNums, Count, i ) + if ( Count >= 2 && Count <= nOutMax && Gia_ObjIsAnd(Gia_ManObj(pGia, i)) ) + Mf_ManOptimizationOne( p, i ); + printf( "\nFinished printing individual logic cones.\n" ); + Gia_ManStaticFanoutStop( pGia ); + Vec_IntFreeP( &pGia->vMapping ); +} + +/**Function************************************************************* + + Synopsis [Technology mappping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Mf_ManComputeMapping( Mf_Man_t * p ) +{ + int i; + Gia_ManForEachAndId( p->pGia, i ) + Mf_ObjComputeBestCut( p, i ); + Mf_ManSetMapRefs( p ); + Mf_ManPrintStats( p, (char *)(p->fUseEla ? "Ela " : (p->Iter ? "Area " : "Delay")) ); +} +Gia_Man_t * Mf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ) +{ + Mf_Man_t * p; + Gia_Man_t * pNew, * pCls; + if ( pPars->fGenCnf || pPars->fGenLit ) + pPars->fCutMin = 1; + if ( Gia_ManHasChoices(pGia) ) + pPars->fCutMin = 1, pPars->fCoarsen = 0; + pCls = pPars->fCoarsen ? Gia_ManDupMuxes(pGia, pPars->nCoarseLimit) : pGia; + p = Mf_ManAlloc( pCls, pPars ); + p->pGia0 = pGia; + if ( pPars->fVerbose && pPars->fCoarsen ) + { + printf( "Initial " ); Gia_ManPrintMuxStats( pGia ); printf( "\n" ); + printf( "Derived " ); Gia_ManPrintMuxStats( pCls ); printf( "\n" ); + } + Mf_ManPrintInit( p ); + Mf_ManComputeCuts( p ); + for ( p->Iter = 1; p->Iter < p->pPars->nRounds; p->Iter++ ) + Mf_ManComputeMapping( p ); + p->fUseEla = 1; + for ( ; p->Iter < p->pPars->nRounds + pPars->nRoundsEla; p->Iter++ ) + Mf_ManComputeMapping( p ); + //Mf_ManOptimization( p ); + if ( pPars->fVeryVerbose && pPars->fCutMin ) + Vec_MemDumpTruthTables( p->vTtMem, Gia_ManName(p->pGia), pPars->nLutSize ); + if ( pPars->fCutMin ) + pNew = Mf_ManDeriveMappingGia( p ); + else if ( pPars->fCoarsen ) + pNew = Mf_ManDeriveMappingCoarse( p ); + else + pNew = Mf_ManDeriveMapping( p ); + if ( p->pPars->fGenCnf ) + pGia->pData = Mf_ManDeriveCnf( p, p->pPars->fCnfObjIds, p->pPars->fAddOrCla ); + //if ( p->pPars->fGenCnf || p->pPars->fGenLit ) + // Mf_ManProfileTruths( p ); + Gia_ManMappingVerify( pNew ); + Mf_ManPrintQuit( p, pNew ); + Mf_ManFree( p ); + if ( pCls != pGia ) + Gia_ManStop( pCls ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [CNF generation] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fMapping, int fVerbose ) +{ + Gia_Man_t * pNew; + Jf_Par_t Pars, * pPars = &Pars; + assert( nLutSize >= 3 && nLutSize <= 8 ); + Mf_ManSetDefaultPars( pPars ); + pPars->fGenCnf = 1; + pPars->fCoarsen = !fCnfObjIds; + pPars->nLutSize = nLutSize; + pPars->fCnfObjIds = fCnfObjIds; + pPars->fAddOrCla = fAddOrCla; + pPars->fCnfMapping = fMapping; + pPars->fVerbose = fVerbose; + pNew = Mf_ManPerformMapping( pGia, pPars ); + Gia_ManStopP( &pNew ); +// Cnf_DataPrint( (Cnf_Dat_t *)pGia->pData, 1 ); + return pGia->pData; +} +void Mf_ManDumpCnf( Gia_Man_t * p, char * pFileName, int nLutSize, int fCnfObjIds, int fAddOrCla, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Cnf_Dat_t * pCnf; + pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( p, nLutSize, fCnfObjIds, fAddOrCla, 0, fVerbose ); + Cnf_DataWriteIntoFile( pCnf, pFileName, 0, NULL, NULL ); +// if ( fVerbose ) + { + printf( "CNF stats: Vars = %6d. Clauses = %7d. Literals = %8d. ", pCnf->nVars, pCnf->nClauses, pCnf->nLiterals ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + Cnf_DataFree(pCnf); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaMffc.c b/yosys/abc/src/aig/gia/giaMffc.c new file mode 100644 index 00000000000..de44ae1de6d --- /dev/null +++ b/yosys/abc/src/aig/gia/giaMffc.c @@ -0,0 +1,313 @@ +/**CFile**************************************************************** + + FileName [gia.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Gia_ObjDom( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Vec_IntEntry(p->vDoms, Gia_ObjId(p, pObj)); } +static inline void Gia_ObjSetDom( Gia_Man_t * p, Gia_Obj_t * pObj, int d ) { Vec_IntWriteEntry(p->vDoms, Gia_ObjId(p, pObj), d); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes one-node dominators.] + + Description [For each node, computes the closest one-node dominator, + which can be the node itself if the node has no other dominators.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManAddDom( Gia_Man_t * p, Gia_Obj_t * pObj, int iDom0 ) +{ + int iDom1, iDomNext; + if ( Gia_ObjDom(p, pObj) == -1 ) + { + Gia_ObjSetDom( p, pObj, iDom0 ); + return; + } + iDom1 = Gia_ObjDom( p, pObj ); + while ( 1 ) + { + if ( iDom0 > iDom1 ) + { + iDomNext = Gia_ObjDom( p, Gia_ManObj(p, iDom1) ); + if ( iDomNext == iDom1 ) + break; + iDom1 = iDomNext; + continue; + } + if ( iDom1 > iDom0 ) + { + iDomNext = Gia_ObjDom( p, Gia_ManObj(p, iDom0) ); + if ( iDomNext == iDom0 ) + break; + iDom0 = iDomNext; + continue; + } + assert( iDom0 == iDom1 ); + Gia_ObjSetDom( p, pObj, iDom0 ); + return; + } + Gia_ObjSetDom( p, pObj, Gia_ObjId(p, pObj) ); +} +static inline void Gia_ManComputeDoms( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + if ( p->vDoms == NULL ) + p->vDoms = Vec_IntAlloc( 0 ); + Vec_IntFill( p->vDoms, Gia_ManObjNum(p), -1 ); + Gia_ManForEachObjReverse( p, pObj, i ) + { + if ( i == 0 || Gia_ObjIsCi(pObj) ) + continue; + if ( Gia_ObjIsCo(pObj) ) + { + Gia_ObjSetDom( p, pObj, i ); + Gia_ManAddDom( p, Gia_ObjFanin0(pObj), i ); + continue; + } + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManAddDom( p, Gia_ObjFanin0(pObj), i ); + Gia_ManAddDom( p, Gia_ObjFanin1(pObj), i ); + } +} + + +/**Function************************************************************* + + Synopsis [Returns the number of internal nodes in the MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_NodeDeref_rec( Gia_Man_t * p, Gia_Obj_t * pNode ) +{ + Gia_Obj_t * pFanin; + int Counter = 0; + if ( Gia_ObjIsCi(pNode) ) + return 0; + assert( Gia_ObjIsAnd(pNode) ); + pFanin = Gia_ObjFanin0(pNode); + assert( Gia_ObjRefNum(p, pFanin) > 0 ); + if ( Gia_ObjRefDec(p, pFanin) == 0 ) + Counter += Gia_NodeDeref_rec( p, pFanin ); + pFanin = Gia_ObjFanin1(pNode); + assert( Gia_ObjRefNum(p, pFanin) > 0 ); + if ( Gia_ObjRefDec(p, pFanin) == 0 ) + Counter += Gia_NodeDeref_rec( p, pFanin ); + return Counter + 1; +} +static inline int Gia_NodeRef_rec( Gia_Man_t * p, Gia_Obj_t * pNode ) +{ + Gia_Obj_t * pFanin; + int Counter = 0; + if ( Gia_ObjIsCi(pNode) ) + return 0; + assert( Gia_ObjIsAnd(pNode) ); + pFanin = Gia_ObjFanin0(pNode); + if ( Gia_ObjRefInc(p, pFanin) == 0 ) + Counter += Gia_NodeRef_rec( p, pFanin ); + pFanin = Gia_ObjFanin1(pNode); + if ( Gia_ObjRefInc(p, pFanin) == 0 ) + Counter += Gia_NodeRef_rec( p, pFanin ); + return Counter + 1; +} +static inline void Gia_NodeCollect_rec( Gia_Man_t * p, Gia_Obj_t * pNode, Vec_Int_t * vSupp, Vec_Int_t * vSuppRefs ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pNode) ) + return; + Gia_ObjSetTravIdCurrent(p, pNode); + if ( Gia_ObjRefNum(p, pNode) || Gia_ObjIsCi(pNode) ) + { + Vec_IntPush( vSupp, Gia_ObjId(p, pNode) ); + Vec_IntPush( vSuppRefs, Gia_ObjRefNum(p, pNode) ); + return; + } + assert( Gia_ObjIsAnd(pNode) ); + Gia_NodeCollect_rec( p, Gia_ObjFanin0(pNode), vSupp, vSuppRefs ); + Gia_NodeCollect_rec( p, Gia_ObjFanin1(pNode), vSupp, vSuppRefs ); +} +static inline int Gia_NodeMffcSizeSupp( Gia_Man_t * p, Gia_Obj_t * pNode, Vec_Int_t * vSupp, Vec_Int_t * vSuppRefs ) +{ + int ConeSize1, ConeSize2, i, iObj; + assert( !Gia_IsComplement(pNode) ); + assert( Gia_ObjIsAnd(pNode) ); + Vec_IntClear( vSupp ); + Vec_IntClear( vSuppRefs ); + Gia_ManIncrementTravId( p ); + ConeSize1 = Gia_NodeDeref_rec( p, pNode ); + Gia_NodeCollect_rec( p, Gia_ObjFanin0(pNode), vSupp, vSuppRefs ); + Gia_NodeCollect_rec( p, Gia_ObjFanin1(pNode), vSupp, vSuppRefs ); + ConeSize2 = Gia_NodeRef_rec( p, pNode ); + assert( ConeSize1 == ConeSize2 ); + assert( ConeSize1 >= 0 ); + // record supp refs + Vec_IntForEachEntry( vSupp, iObj, i ) + Vec_IntAddToEntry( vSuppRefs, i, -Gia_ObjRefNumId(p, iObj) ); + return ConeSize1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManDomDerive_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pNode ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pNode) ) + return pNode->Value; + Gia_ObjSetTravIdCurrent(p, pNode); + assert( Gia_ObjIsAnd(pNode) ); + Gia_ManDomDerive_rec( pNew, p, Gia_ObjFanin0(pNode) ); + Gia_ManDomDerive_rec( pNew, p, Gia_ObjFanin1(pNode) ); + return pNode->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pNode), Gia_ObjFanin1Copy(pNode) ); +} +Gia_Man_t * Gia_ManDomDerive( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vSupp, int nVars ) +{ + Gia_Man_t * pNew, * pTemp; + int nMints = 1 << nVars; + int i, m, iResLit; + assert( nVars >= 0 && nVars <= 5 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashAlloc( pNew ); + for ( i = 0; i < Vec_IntSize(vSupp); i++ ) + Gia_ManAppendCi(pNew); + for ( m = 0; m < nMints; m++ ) + { + Gia_Obj_t * pObj; + Gia_ManIncrementTravId( p ); + Gia_ManForEachObjVec( vSupp, p, pObj, i ) + { + if ( i < nVars ) + pObj->Value = (m >> i) & 1; + else + pObj->Value = Gia_ObjToLit(pNew, Gia_ManCi(pNew, i)); + Gia_ObjSetTravIdCurrent( p, pObj ); + } + iResLit = Gia_ManDomDerive_rec( pNew, p, pRoot ); + Gia_ManAppendCo( pNew, iResLit ); + } + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManComputeDomsTry( Gia_Man_t * p ) +{ + extern void Gia_ManCollapseTestTest( Gia_Man_t * p ); + + Vec_Int_t * vSupp, * vSuppRefs; + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i, nSize, Entry, k; + abctime clk = Abc_Clock(); + ABC_FREE( p->pRefs ); + Gia_ManLevelNum( p ); + Gia_ManCreateRefs( p ); + Gia_ManComputeDoms( p ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + vSupp = Vec_IntAlloc( 1000 ); + vSuppRefs = Vec_IntAlloc( 1000 ); + Gia_ManForEachObj( p, pObj, i ) + { + if ( !Gia_ObjIsAnd(pObj) && !Gia_ObjIsCo(pObj) ) + continue; + if ( Gia_ObjDom(p, pObj) != i ) + continue; + if ( Gia_ObjIsCo(pObj) ) + pObj = Gia_ObjFanin0(pObj); + if ( !Gia_ObjIsAnd(pObj) ) + continue; + nSize = Gia_NodeMffcSizeSupp( p, pObj, vSupp, vSuppRefs ); + if ( nSize < 10 )//|| nSize > 100 ) + continue; + // sort by cost + Vec_IntSelectSortCost2( Vec_IntArray(vSupp), Vec_IntSize(vSupp), Vec_IntArray(vSuppRefs) ); + + printf( "Obj %6d : ", i ); + printf( "Cone = %4d ", nSize ); + printf( "Supp = %4d ", Vec_IntSize(vSupp) ); +// Vec_IntForEachEntry( vSuppRefs, Entry, k ) +// printf( "%d(%d) ", -Entry, Gia_ObjLevelId(p, Vec_IntEntry(vSupp, k)) ); + printf( "\n" ); + + // selected k + for ( k = 0; k < Vec_IntSize(vSupp); k++ ) + if ( Vec_IntEntry(vSuppRefs, k) == 1 ) + break; + k = Abc_MinInt( k, 3 ); + k = 0; + + // dump + pNew = Gia_ManDomDerive( p, pObj, vSupp, k ); + Gia_DumpAiger( pNew, "mffc", i, 6 ); + Gia_ManCollapseTestTest( pNew ); + + Gia_ManStop( pNew ); + } + Vec_IntFree( vSuppRefs ); + Vec_IntFree( vSupp ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaMfs.c b/yosys/abc/src/aig/gia/giaMfs.c new file mode 100644 index 00000000000..81eb298d31e --- /dev/null +++ b/yosys/abc/src/aig/gia/giaMfs.c @@ -0,0 +1,574 @@ +/**CFile**************************************************************** + + FileName [giaMfs.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Interface with the MFS package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaMfs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "opt/sfm/sfm.h" +#include "misc/tim/tim.h" +#include "misc/util/utilTruth.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Sfm_Ntk_t * Gia_ManExtractMfs( Gia_Man_t * p ) +{ + word uTruth, * pTruth, uTruths6[6] = { + ABC_CONST(0xAAAAAAAAAAAAAAAA), + ABC_CONST(0xCCCCCCCCCCCCCCCC), + ABC_CONST(0xF0F0F0F0F0F0F0F0), + ABC_CONST(0xFF00FF00FF00FF00), + ABC_CONST(0xFFFF0000FFFF0000), + ABC_CONST(0xFFFFFFFF00000000) + }; + Gia_Obj_t * pObj, * pObjExtra; + Vec_Wec_t * vFanins; // mfs data + Vec_Str_t * vFixed; // mfs data + Vec_Str_t * vEmpty; // mfs data + Vec_Str_t * vDenied; // mfs data + Vec_Wrd_t * vTruths; // mfs data + Vec_Int_t * vArray; + Vec_Int_t * vStarts; + Vec_Wrd_t * vTruths2; + Vec_Int_t * vLeaves; + Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; + int nBoxes = Gia_ManBoxNum(p), nVars; + int nRealPis = nBoxes ? Tim_ManPiNum(pManTime) : Gia_ManPiNum(p); + int nRealPos = nBoxes ? Tim_ManPoNum(pManTime) : Gia_ManPoNum(p); + int i, j, k, curCi, curCo, nBoxIns, nBoxOuts, w, nWords; + int Id, iFan, nMfsVars, nBbIns = 0, nBbOuts = 0, Counter = 0; + int nLutSizeMax = Gia_ManLutSizeMax( p ); + nLutSizeMax = Abc_MaxInt( nLutSizeMax, 6 ); + assert( nLutSizeMax < 16 ); + //assert( !p->pAigExtra || Gia_ManPiNum(p->pAigExtra) <= 6 ); + if ( pManTime ) Tim_ManBlackBoxIoNum( pManTime, &nBbIns, &nBbOuts ); + // skip PIs due to box outputs + Counter += nBbOuts; + // prepare storage + nMfsVars = Gia_ManCiNum(p) + 1 + Gia_ManLutNum(p) + Gia_ManCoNum(p) + nBbIns + nBbOuts; + vFanins = Vec_WecStart( nMfsVars ); + vFixed = Vec_StrStart( nMfsVars ); + vEmpty = Vec_StrStart( nMfsVars ); + vDenied = Vec_StrStart( nMfsVars ); + vTruths = Vec_WrdStart( nMfsVars ); + vStarts = Vec_IntStart( nMfsVars ); + vTruths2 = Vec_WrdAlloc( 10000 ); + // deny the PIs which are modeling blackbox outputs from being considered + // in substitutions + for (int i = 0; i < nBbOuts; i++) + Vec_StrWriteEntry( vDenied, i, (char)1 ); + // set internal PIs + Gia_ManCleanCopyArray( p ); + Gia_ManForEachCiId( p, Id, i ) + Gia_ObjSetCopyArray( p, Id, Counter++ ); + // set constant node + Vec_StrWriteEntry( vFixed, Counter, (char)1 ); + Vec_WrdWriteEntry( vTruths, Counter, (word)0 ); + Gia_ObjSetCopyArray( p, 0, Counter++ ); + // set internal LUTs + vLeaves = Vec_IntAlloc( nLutSizeMax ); + Gia_ObjComputeTruthTableStart( p, nLutSizeMax ); + Gia_ManForEachLut( p, Id ) + { + Vec_IntClear( vLeaves ); + vArray = Vec_WecEntry( vFanins, Counter ); + Vec_IntGrow( vArray, Gia_ObjLutSize(p, Id) ); + Gia_LutForEachFanin( p, Id, iFan, k ) + { + assert( Gia_ObjCopyArray(p, iFan) >= 0 ); + Vec_IntPush( vArray, Gia_ObjCopyArray(p, iFan) ); + Vec_IntPush( vLeaves, iFan ); + } + assert( Vec_IntSize(vLeaves) < 16 ); + assert( Vec_IntSize(vLeaves) == Gia_ObjLutSize(p, Id) ); +// uTruth = *Gia_ObjComputeTruthTableCut( p, Gia_ManObj(p, Id), vLeaves ); +// nVars = Abc_Tt6MinBase( &uTruth, Vec_IntArray(vArray), Vec_IntSize(vArray) ); + pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ManObj(p, Id), vLeaves ); + nVars = Abc_TtMinBase( pTruth, Vec_IntArray(vArray), Vec_IntSize(vArray), Vec_IntSize(vLeaves) ); + Vec_IntShrink( vArray, nVars ); + Vec_WrdWriteEntry( vTruths, Counter, pTruth[0] ); + nWords = Abc_Truth6WordNum( nVars ); + Vec_IntWriteEntry( vStarts, Counter, Vec_WrdSize(vTruths2) ); + for ( w = 0; w < nWords; w++ ) + Vec_WrdPush( vTruths2, pTruth[w] ); + if ( Gia_ObjLutIsMux(p, Id) ) + { + Vec_StrWriteEntry( vFixed, Counter, (char)1 ); + Vec_StrWriteEntry( vEmpty, Counter, (char)1 ); + } + Gia_ObjSetCopyArray( p, Id, Counter++ ); + } + Gia_ObjComputeTruthTableStop( p ); + // set all POs + Gia_ManForEachCo( p, pObj, i ) + { + iFan = Gia_ObjFaninId0p( p, pObj ); + assert( Gia_ObjCopyArray(p, iFan) >= 0 ); + vArray = Vec_WecEntry( vFanins, Counter ); + Vec_IntFill( vArray, 1, Gia_ObjCopyArray(p, iFan) ); + if ( i < Gia_ManCoNum(p) - nRealPos ) // internal PO + { + Vec_StrWriteEntry( vFixed, Counter, (char)1 ); + Vec_StrWriteEntry( vEmpty, Counter, (char)1 ); + uTruth = Gia_ObjFaninC0(pObj) ? ~uTruths6[0]: uTruths6[0]; + Vec_WrdWriteEntry( vTruths, Counter, uTruth ); + Vec_IntWriteEntry( vStarts, Counter, Vec_WrdSize(vTruths2) ); + Vec_WrdPush( vTruths2, uTruth ); + } + Gia_ObjSetCopyArray( p, Gia_ObjId(p, pObj), Counter++ ); + } + // skip POs due to box inputs + Counter += nBbIns; + assert( Counter == nMfsVars ); + + // add functions of the boxes + if ( p->pAigExtra ) + { + assert( Gia_ManCiNum(p->pAigExtra) < 16 ); + Gia_ObjComputeTruthTableStart( p->pAigExtra, Gia_ManCiNum(p->pAigExtra) ); + } + + { + int iBbIn = 0, iBbOut = 0; + curCi = nRealPis; + curCo = 0; + for ( k = 0; k < nBoxes; k++ ) + { + nBoxIns = Tim_ManBoxInputNum( pManTime, k ); + nBoxOuts = Tim_ManBoxOutputNum( pManTime, k ); + // iterate through box outputs + if ( !Tim_ManBoxIsBlack(pManTime, k) ) //&& Tim_ManBoxInputNum(pManTime, k) <= 6 ) + { + assert(p->pAigExtra); + // collect truth table leaves + Vec_IntClear( vLeaves ); + for ( i = 0; i < nBoxIns; i++ ) + Vec_IntPush( vLeaves, Gia_ObjId(p->pAigExtra, Gia_ManCi(p->pAigExtra, i)) ); + for ( j = 0; j < nBoxOuts; j++ ) + { + // CI corresponding to the box outputs + pObj = Gia_ManCi( p, curCi + j ); + Counter = Gia_ObjCopyArray( p, Gia_ObjId(p, pObj) ); + // add box inputs (POs of the AIG) as fanins + vArray = Vec_WecEntry( vFanins, Counter ); + Vec_IntGrow( vArray, nBoxIns ); + for ( i = 0; i < nBoxIns; i++ ) + { + iFan = Gia_ObjId( p, Gia_ManCo(p, curCo + i) ); + assert( Gia_ObjCopyArray(p, iFan) >= 0 ); + Vec_IntPush( vArray, Gia_ObjCopyArray(p, iFan) ); + } + Vec_StrWriteEntry( vFixed, Counter, (char)1 ); + // box output in the extra manager + pObjExtra = Gia_ManCo( p->pAigExtra, curCi - nRealPis + j ); + // compute truth table + pTruth = NULL; + if ( Gia_ObjFaninId0p(p->pAigExtra, pObjExtra) == 0 ) + { + uTruth = 0; + uTruth = Gia_ObjFaninC0(pObjExtra) ? ~uTruth : uTruth; + pTruth = &uTruth; + } + else if ( Gia_ObjIsCi(Gia_ObjFanin0(pObjExtra)) ) + { + uTruth = uTruths6[Gia_ObjCioId(Gia_ObjFanin0(pObjExtra))]; + uTruth = Gia_ObjFaninC0(pObjExtra) ? ~uTruth : uTruth; + pTruth = &uTruth; + } + else + { + pTruth = Gia_ObjComputeTruthTableCut( p->pAigExtra, Gia_ObjFanin0(pObjExtra), vLeaves ); + if ( Gia_ObjFaninC0(pObjExtra) ) + Abc_TtNot( pTruth, Abc_Truth6WordNum(Vec_IntSize(vLeaves)) ); + } + //uTruth = Gia_ObjFaninC0(pObjExtra) ? ~uTruth : uTruth; + //Dau_DsdPrintFromTruth( &uTruth, Vec_IntSize(vArray) ); + //nVars = Abc_Tt6MinBase( &uTruth, Vec_IntArray(vArray), Vec_IntSize(vArray) ); + nVars = Abc_TtMinBase( pTruth, Vec_IntArray(vArray), Vec_IntSize(vArray), Vec_IntSize(vLeaves) ); + Vec_IntShrink( vArray, nVars ); + if ( nVars <= 6 ) + Vec_WrdWriteEntry( vTruths, Counter, pTruth[0] ); + else + { + int w, nWords = Abc_Truth6WordNum( nVars ); + Vec_IntWriteEntry( vStarts, Counter, Vec_WrdSize(vTruths2) ); + for ( w = 0; w < nWords; w++ ) + Vec_WrdPush( vTruths2, pTruth[w] ); + } + } + } + else // create buffers for black box inputs and outputs + { + for ( j = 0; j < nBoxOuts; j++ ) + { + // CI corresponding to the box outputs + pObj = Gia_ManCi( p, curCi + j ); + Counter = Gia_ObjCopyArray( p, Gia_ObjId(p, pObj) ); + // connect it with the special primary input (iBbOut) + vArray = Vec_WecEntry( vFanins, Counter ); + assert( Vec_IntSize(vArray) == 0 ); + Vec_IntFill( vArray, 1, iBbOut++ ); + Vec_StrWriteEntry( vFixed, Counter, (char)1 ); + Vec_StrWriteEntry( vEmpty, Counter, (char)1 ); + Vec_StrWriteEntry( vDenied, Counter, (char)1 ); + Vec_WrdWriteEntry( vTruths, Counter, uTruths6[0] ); + } + for ( i = 0; i < nBoxIns; i++ ) + { + // CO corresponding to the box inputs + pObj = Gia_ManCo( p, curCo + i ); + Counter = Gia_ObjCopyArray( p, Gia_ObjId(p, pObj) ); + // connect it with the special primary output (iBbIn) + int poNum = nMfsVars - nBbIns + iBbIn++; + vArray = Vec_WecEntry( vFanins, poNum ); + Vec_StrWriteEntry( vFixed, poNum, (char)1 ); + assert( Vec_IntSize(vArray) == 0 ); + Vec_IntFill( vArray, 1, Counter ); + } + } + // set internal POs pointing directly to internal PIs as no-delay + for ( i = 0; i < nBoxIns; i++ ) + { + pObj = Gia_ManCo( p, curCo + i ); + if ( !Gia_ObjIsCi( Gia_ObjFanin0(pObj) ) ) + continue; + Counter = Gia_ObjCopyArray( p, Gia_ObjFaninId0p(p, pObj) ); + Vec_StrWriteEntry( vEmpty, Counter, (char)1 ); + } + curCo += nBoxIns; + curCi += nBoxOuts; + } + curCo += nRealPos; + // verify counts + assert( curCi == Gia_ManCiNum(p) ); + assert( curCo == Gia_ManCoNum(p) ); + assert( iBbIn == nBbIns ); + assert( iBbOut == nBbOuts ); + } + + if (p->pAigExtra) { + Gia_ObjComputeTruthTableStop( p->pAigExtra ); + assert( curCi - nRealPis == Gia_ManCoNum(p->pAigExtra) ); + } + + // finalize + Vec_IntFree( vLeaves ); + return Sfm_NtkConstruct( vFanins, nBbOuts + nRealPis, nRealPos + nBbIns, vFixed, vEmpty, vDenied, vTruths, vStarts, vTruths2 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManInsertMfs( Gia_Man_t * p, Sfm_Ntk_t * pNtk, int fAllBoxes ) +{ + extern int Gia_ManFromIfLogicCreateLut( Gia_Man_t * pNew, word * pRes, Vec_Int_t * vLeaves, Vec_Int_t * vCover, Vec_Int_t * vMapping, Vec_Int_t * vMapping2 ); + Gia_Man_t * pNew; Gia_Obj_t * pObj; + Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; + int nBoxes = Gia_ManBoxNum(p); + int nRealPis = nBoxes ? Tim_ManPiNum(pManTime) : Gia_ManPiNum(p); + int nRealPos = nBoxes ? Tim_ManPoNum(pManTime) : Gia_ManPoNum(p); + int i, k, Id, curCi, curCo, nBoxIns, nBoxOuts, iLitNew, iMfsId, iGroup, Fanin; + int nMfsNodes; + word * pTruth, uTruthVar = ABC_CONST(0xAAAAAAAAAAAAAAAA); + Vec_Wec_t * vGroups = Vec_WecStart( nBoxes ); + Vec_Int_t * vMfs2Gia, * vMfs2Old; + Vec_Int_t * vGroupMap; + Vec_Int_t * vMfsTopo, * vCover, * vBoxesLeft; + Vec_Int_t * vArray, * vLeaves; + Vec_Int_t * vMapping, * vMapping2; + int nBbIns = 0, nBbOuts = 0; + if ( pManTime ) Tim_ManBlackBoxIoNum( pManTime, &nBbIns, &nBbOuts ); + nMfsNodes = 1 + Gia_ManCiNum(p) + Gia_ManLutNum(p) + Gia_ManCoNum(p) + nBbIns + nBbOuts; + vMfs2Gia = Vec_IntStartFull( nMfsNodes ); + vMfs2Old = Vec_IntStartFull( nMfsNodes ); + vGroupMap = Vec_IntStartFull( nMfsNodes ); + Gia_ManForEachObj( p, pObj, i ) + if ( Gia_ObjCopyArray(p, i) > 0 ) + Vec_IntWriteEntry( vMfs2Old, Gia_ObjCopyArray(p, i), i ); + // collect nodes + curCi = nRealPis; + curCo = 0; + for ( i = 0; i < nBoxes; i++ ) + { + nBoxIns = Tim_ManBoxInputNum( pManTime, i ); + nBoxOuts = Tim_ManBoxOutputNum( pManTime, i ); + vArray = Vec_WecEntry( vGroups, i ); + for ( k = 0; k < nBoxIns; k++ ) + { + pObj = Gia_ManCo( p, curCo + k ); + iMfsId = Gia_ObjCopyArray( p, Gia_ObjId(p, pObj) ); + assert( iMfsId > 0 ); + Vec_IntPush( vArray, iMfsId ); + Vec_IntWriteEntry( vGroupMap, iMfsId, Abc_Var2Lit(i,0) ); + } + for ( k = 0; k < nBoxOuts; k++ ) + { + pObj = Gia_ManCi( p, curCi + k ); + iMfsId = Gia_ObjCopyArray( p, Gia_ObjId(p, pObj) ); + assert( iMfsId > 0 ); + Vec_IntPush( vArray, iMfsId ); + Vec_IntWriteEntry( vGroupMap, iMfsId, Abc_Var2Lit(i,1) ); + } + curCo += nBoxIns; + curCi += nBoxOuts; + } + curCo += nRealPos; + assert( curCi == Gia_ManCiNum(p) ); + assert( curCo == Gia_ManCoNum(p) ); + + // collect nodes in the given order + vBoxesLeft = Vec_IntAlloc( nBoxes ); + vMfsTopo = Sfm_NtkDfs( pNtk, vGroups, vGroupMap, vBoxesLeft, fAllBoxes ); + assert( Vec_IntSize(vBoxesLeft) <= nBoxes ); + assert( Vec_IntSize(vMfsTopo) > 0 ); + + // start new GIA + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + + // start mapping + vMapping = Vec_IntStart( Gia_ManObjNum(p) ); + vMapping2 = Vec_IntStart( 1 ); + // create const LUT + Vec_IntWriteEntry( vMapping, 0, Vec_IntSize(vMapping2) ); + Vec_IntPush( vMapping2, 0 ); + Vec_IntPush( vMapping2, 0 ); + + // map constant + Vec_IntWriteEntry( vMfs2Gia, Gia_ObjCopyArray(p, 0), 0 ); + // map primary inputs + Gia_ManForEachCiId( p, Id, i ) + if ( i < nRealPis ) + Vec_IntWriteEntry( vMfs2Gia, Gia_ObjCopyArray(p, Id), Gia_ManAppendCi(pNew) ); + // map internal nodes + vLeaves = Vec_IntAlloc( 6 ); + vCover = Vec_IntAlloc( 1 << 16 ); + Vec_IntForEachEntry( vMfsTopo, iMfsId, i ) + { + pTruth = Sfm_NodeReadTruth( pNtk, iMfsId ); + iGroup = Vec_IntEntry( vGroupMap, iMfsId ); + vArray = Sfm_NodeReadFanins( pNtk, iMfsId ); // belongs to pNtk + if ( Vec_IntSize(vArray) == 1 && Vec_IntEntry(vArray,0) < nBbOuts ) // skip unreal inputs + { + // create CI for the output of black box + assert( Abc_LitIsCompl(iGroup) ); + iLitNew = Gia_ManAppendCi( pNew ); + Vec_IntWriteEntry( vMfs2Gia, iMfsId, iLitNew ); + continue; + } + Vec_IntClear( vLeaves ); + + // handle internal CIs first, before we go looking for vLeaves + if ( iGroup != -1 && Abc_LitIsCompl(iGroup) ) + { + //Dau_DsdPrintFromTruth( pTruth, Vec_IntSize(vLeaves) ); + iLitNew = Gia_ManAppendCi( pNew ); + goto done; + } + + Vec_IntForEachEntry( vArray, Fanin, k ) + { + iLitNew = Vec_IntEntry( vMfs2Gia, Fanin ); assert( iLitNew >= 0 ); + Vec_IntPush( vLeaves, iLitNew ); + } + if ( iGroup == -1 ) // internal node + { + assert( Sfm_NodeReadUsed(pNtk, iMfsId) ); + if ( Gia_ObjLutIsMux(p, Vec_IntEntry(vMfs2Old, iMfsId)) ) + { + int MapSize = Vec_IntSize(vMapping2); + int nVarsNew; + Abc_TtSimplify( pTruth, Vec_IntArray(vLeaves), Vec_IntSize(vLeaves), &nVarsNew ); + Vec_IntShrink( vLeaves, nVarsNew ); + Abc_TtFlipVar5( pTruth, Vec_IntSize(vLeaves) ); + iLitNew = Gia_ManFromIfLogicCreateLut( pNew, pTruth, vLeaves, vCover, vMapping, vMapping2 ); + Abc_TtFlipVar5( pTruth, Vec_IntSize(vLeaves) ); + if ( MapSize < Vec_IntSize(vMapping2) ) + { + assert( Vec_IntEntryLast(vMapping2) == Abc_Lit2Var(iLitNew) ); + Vec_IntWriteEntry(vMapping2, Vec_IntSize(vMapping2)-1, -Abc_Lit2Var(iLitNew) ); + } + } + else + { + Abc_TtFlipVar5( pTruth, Vec_IntSize(vLeaves) ); + iLitNew = Gia_ManFromIfLogicCreateLut( pNew, pTruth, vLeaves, vCover, vMapping, vMapping2 ); + Abc_TtFlipVar5( pTruth, Vec_IntSize(vLeaves) ); + } + } + else // internal CO + { + assert( pTruth[0] == uTruthVar || pTruth[0] == ~uTruthVar ); + iLitNew = Gia_ManAppendCo( pNew, Abc_LitNotCond(Vec_IntEntry(vLeaves, 0), pTruth[0] == ~uTruthVar) ); + //printf("Group = %d. po = %d\n", iGroup>>1, iMfsId ); + } +done: + Vec_IntWriteEntry( vMfs2Gia, iMfsId, iLitNew ); + } + Vec_IntFree( vCover ); + Vec_IntFree( vLeaves ); + + // map primary outputs + Gia_ManForEachCo( p, pObj, i ) + { + if ( i < Gia_ManCoNum(p) - nRealPos ) // internal COs + { + iMfsId = Gia_ObjCopyArray( p, Gia_ObjId(p, pObj) ); + iGroup = Vec_IntEntry( vGroupMap, iMfsId ); + if ( Vec_IntFind(vMfsTopo, iGroup) >= 0 ) + { + iLitNew = Vec_IntEntry( vMfs2Gia, iMfsId ); + if ( iLitNew < 0 ) + continue; + assert( iLitNew >= 0 ); + } + continue; + } + iLitNew = Vec_IntEntry( vMfs2Gia, Gia_ObjCopyArray(p, Gia_ObjFaninId0p(p, pObj)) ); + assert( iLitNew >= 0 ); + Gia_ManAppendCo( pNew, Abc_LitNotCond(iLitNew, Gia_ObjFaninC0(pObj)) ); + } + + // finish mapping + if ( Vec_IntSize(vMapping) > Gia_ManObjNum(pNew) ) + Vec_IntShrink( vMapping, Gia_ManObjNum(pNew) ); + else + Vec_IntFillExtra( vMapping, Gia_ManObjNum(pNew), 0 ); + assert( Vec_IntSize(vMapping) == Gia_ManObjNum(pNew) ); + Vec_IntForEachEntry( vMapping, iLitNew, i ) + if ( iLitNew > 0 ) + Vec_IntAddToEntry( vMapping, i, Gia_ManObjNum(pNew) ); + Vec_IntAppend( vMapping, vMapping2 ); + Vec_IntFree( vMapping2 ); + assert( pNew->vMapping == NULL ); + pNew->vMapping = vMapping; + + // create new timing manager and extra AIG + if ( pManTime ) + pNew->pManTime = Gia_ManUpdateTimMan2( p, vBoxesLeft, 0 ); + // update extra STG + if ( p->pAigExtra ) + pNew->pAigExtra = Gia_ManUpdateExtraAig2( p->pManTime, p->pAigExtra, vBoxesLeft ); + // duplicated flops + if ( p->vRegClasses ) + pNew->vRegClasses = Vec_IntDup( p->vRegClasses ); + // duplicated initial state + if ( p->vRegInits ) + pNew->vRegInits = Vec_IntDup( p->vRegInits ); + pNew->nAnd2Delay = p->nAnd2Delay; + + // cleanup + Vec_WecFree( vGroups ); + Vec_IntFree( vMfsTopo ); + Vec_IntFree( vGroupMap ); + Vec_IntFree( vMfs2Gia ); + Vec_IntFree( vMfs2Old ); + Vec_IntFree( vBoxesLeft ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManPerformMfs( Gia_Man_t * p, Sfm_Par_t * pPars ) +{ + Sfm_Ntk_t * pNtk; + Gia_Man_t * pNew; + int nFaninMax, nNodes = 0; + assert( Gia_ManRegNum(p) == 0 ); + assert( p->vMapping != NULL ); + if ( p->pManTime != NULL && p->pAigExtra != NULL && Gia_ManCiNum(p->pAigExtra) > 15 ) + { + Abc_Print( 1, "Currently \"&mfs\" cannot process the network containing white-boxes with more than 15 inputs.\n" ); + return NULL; + } + // count fanouts + nFaninMax = Gia_ManLutSizeMax( p ); + if ( nFaninMax > 15 ) + { + Abc_Print( 1, "Currently \"&mfs\" cannot process the network containing nodes with more than 15 fanins.\n" ); + return NULL; + } + // collect information + pNtk = Gia_ManExtractMfs( p ); + if (pPars->fTestReimport) + goto reimport; + // perform optimization + nNodes = Sfm_NtkPerform( pNtk, pPars ); + if ( nNodes == 0 ) + { + if ( p->pManTime ) + Abc_Print( 1, "The network is not changed by \"&mfs\".\n" ); + pNew = Gia_ManDup( p ); + pNew->vMapping = Vec_IntDup( p->vMapping ); + Gia_ManTransferTiming( pNew, p ); + } + else + { + reimport: + pNew = Gia_ManInsertMfs( p, pNtk, pPars->fAllBoxes ); + if( pPars->fVerbose ) + Abc_Print( 1, "The network has %d nodes changed by \"&mfs\".\n", nNodes ); + // check integrity + //Gia_ManCheckIntegrityWithBoxes( pNew ); + } + Sfm_NtkFree( pNtk ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaMinLut.c b/yosys/abc/src/aig/gia/giaMinLut.c new file mode 100644 index 00000000000..e08ebec56e7 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaMinLut.c @@ -0,0 +1,1058 @@ +/**CFile**************************************************************** + + FileName [giaMinLut.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Collapsing AIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaMinLut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "giaAig.h" +#include "base/main/mainInt.h" +#include "opt/sfm/sfm.h" + +#ifdef ABC_USE_CUDD +#include "bdd/extrab/extraBdd.h" +#include "bdd/dsd/dsd.h" +#endif + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Vec_WrdReadLayerText( char * pFileName, int * pnIns, int * pnOuts ) +{ + char * pThis, pLine[1000]; + Vec_Wec_t * vRes; int iLine; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return NULL; + } + vRes = Vec_WecAlloc(100); + for ( iLine = 0; fgets( pLine, 1000, pFile ); iLine++ ) + { + if ( iLine == 0 ) + { + pThis = strstr( pLine, "[" ); + *pnIns = atoi( pThis+1 ) + 1; + pThis = strstr( pThis+1, "[" ); + *pnOuts = atoi( pThis+1 ) + 1; + } + else + { + Vec_Int_t * vLevel = NULL; + for ( pThis = pLine; (pThis = strstr(pThis, "M0[")); pThis++ ) + { + if ( vLevel == NULL ) + vLevel = Vec_WecPushLevel( vRes ); + Vec_IntPush( vLevel, atoi( pThis+3 ) ); + } + if ( vLevel ) + Vec_IntReverseOrder( vLevel ); + } + } + fclose( pFile ); + //Vec_WecPrint( vRes, 0 ); + return vRes; +} +int Vec_WrdReadTruthTextOne( char * pFileName, int nIns, int nOuts, word * pRes ) +{ + int i, nWords = Abc_TtWordNum( nIns ); + char * pStart, * pBuffer = Extra_FileReadContents( pFileName ); + if ( pBuffer == NULL ) + { + printf( "Cannot read file \"%s\".\n", pFileName ); + return 0; + } + pStart = pBuffer; + for ( i = 0; i < nOuts; i++ ) + { + pStart = strstr( pStart + 1, "0x" ); + if ( !Extra_ReadHex( (unsigned *)(pRes + i*nWords), pStart + 2, nWords*16 ) ) + { + printf( "Cannot read truth table %d (out of %d) in file \"%s\".\n", i, nOuts, pFileName ); + ABC_FREE( pBuffer ); + return 0; + } + } + ABC_FREE( pBuffer ); + return 1; +} +word * Vec_WrdReadTruthText( char * pFileName, int nIns, int nOuts, int nFiles ) +{ + char FileName[1000]; + int i, nWords = Abc_TtWordNum( nIns ); + word * pRes = ABC_CALLOC( word, nOuts*nFiles*nWords ); + for ( i = 0; i < nFiles; i++ ) + { + assert( strlen(pFileName) < 900 ); + strcpy( FileName, pFileName ); + sprintf( FileName + strlen(FileName) - 2, "_N%d.bench", i ); + if ( !Vec_WrdReadTruthTextOne( FileName, nIns, nOuts, pRes + i*nOuts*nWords ) ) + { + ABC_FREE( pRes ); + return NULL; + } + } + return pRes; +} +Gia_Man_t * Vec_WrdReadTest( char * pFileName ) +{ + extern int Gia_ManPerformLNetOpt_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ); + extern Gia_Man_t * Gia_TryPermOptCare( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ); + Gia_Man_t * pPart, * pNew = NULL; Gia_Obj_t * pObj; + int i, k, nIns, nOuts, iLit; + Vec_Wec_t * vRes = Vec_WrdReadLayerText( pFileName, &nIns, &nOuts ); + int nBitsI = vRes ? Vec_WecMaxLevelSize(vRes) : 0; + int nBitsO = vRes ? nOuts / Vec_WecSize(vRes) : 0; + int nWords = Abc_TtWordNum(nBitsI); + word * pFuncs = vRes ? Vec_WrdReadTruthText( pFileName, nBitsI, nBitsO, Vec_WecSize(vRes) ) : NULL; + Vec_Int_t * vPart, * vLits = Vec_IntAlloc( nOuts ); + if ( vRes == NULL || pFuncs == NULL ) + { + Vec_WecFreeP( &vRes ); + Vec_IntFreeP( &vLits ); + ABC_FREE( pFuncs ); + return NULL; + } + assert( nOuts % Vec_WecSize(vRes) == 0 ); + pNew = Gia_ManStart( 10000 ); + pNew->pName = Abc_UtilStrsav( pFileName ); + pNew->pSpec = NULL; + for ( i = 0; i < nIns; i++ ) + Gia_ManAppendCi(pNew); + Gia_ManHashStart( pNew ); + Vec_WecForEachLevel( vRes, vPart, i ) + { + assert( Vec_IntSize(vPart) <= nBitsI ); + pPart = Gia_TryPermOptCare( pFuncs + i * nBitsO * nWords, nBitsI, nBitsO, nWords, 20, 0 ); + Gia_ManFillValue( pPart ); + Gia_ManConst0(pPart)->Value = 0; + Gia_ManForEachCi( pPart, pObj, k ) + pObj->Value = Abc_Var2Lit( 1+Vec_IntEntry(vPart, k), 0 ); + Gia_ManForEachCo( pPart, pObj, k ) + { + Gia_ManPerformLNetOpt_rec( pNew, pPart, Gia_ObjFanin0(pObj) ); + Vec_IntPush( vLits, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManStop( pPart ); + } + Gia_ManHashStop( pNew ); + Vec_IntForEachEntry( vLits, iLit, i ) + Gia_ManAppendCo( pNew, iLit ); + ABC_FREE( pFuncs ); + Vec_WecFree( vRes ); + Vec_IntFree( vLits ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Vec_WrdReadText( char * pFileName, Vec_Wrd_t ** pvSimI, Vec_Wrd_t ** pvSimO, int nIns, int nOuts ) +{ + int i, nSize, iLine, nLines, nWords; + char pLine[2000]; + Vec_Wrd_t * vSimI, * vSimO; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return; + } + fseek( pFile, 0, SEEK_END ); + nSize = ftell( pFile ); + if ( nSize % (nIns + nOuts + 1) > 0 ) + { + printf( "Cannot read file with simulation data that is not aligned at 8 bytes (remainder = %d).\n", nSize % (nIns + nOuts + 1) ); + fclose( pFile ); + return; + } + rewind( pFile ); + nLines = nSize / (nIns + nOuts + 1); + nWords = (nLines + 63)/64; + vSimI = Vec_WrdStart( nIns *nWords ); + vSimO = Vec_WrdStart( nOuts*nWords ); + for ( iLine = 0; fgets( pLine, 2000, pFile ); iLine++ ) + { + for ( i = 0; i < nIns; i++ ) + if ( pLine[nIns-1-i] == '1' ) + Abc_TtXorBit( Vec_WrdArray(vSimI) + i*nWords, iLine ); + else assert( pLine[nIns-1-i] == '0' ); + for ( i = 0; i < nOuts; i++ ) + if ( pLine[nIns+nOuts-1-i] == '1' ) + Abc_TtXorBit( Vec_WrdArray(vSimO) + i*nWords, iLine ); + else assert( pLine[nIns+nOuts-1-i] == '0' ); + } + fclose( pFile ); + *pvSimI = vSimI; + *pvSimO = vSimO; + printf( "Read %d words of simulation data for %d inputs and %d outputs (padded %d zero-patterns).\n", nWords, nIns, nOuts, nWords*64-nLines ); +} +int Vec_WrdReadText2( char * pFileName, Vec_Wrd_t ** pvSimI ) +{ + int i, nSize, iLine, nLines, nWords, nIns; + char pLine[2000]; + Vec_Wrd_t * vSimI; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return 0; + } + if ( !fgets(pLine, 2000, pFile) || (nIns = strlen(pLine)-1) < 1 ) + { + printf( "Cannot find the number of inputs in file \"%s\".\n", pFileName ); + fclose( pFile ); + return 0; + } + fseek( pFile, 0, SEEK_END ); + nSize = ftell( pFile ); + if ( nSize % (nIns + 1) > 0 ) + { + printf( "Cannot read file with simulation data that is not aligned at 8 bytes (remainder = %d).\n", nSize % (nIns + 1) ); + fclose( pFile ); + return 0; + } + rewind( pFile ); + nLines = nSize / (nIns + 1); + nWords = (nLines + 63)/64; + vSimI = Vec_WrdStart( nIns *nWords ); + for ( iLine = 0; fgets( pLine, 2000, pFile ); iLine++ ) + { + for ( i = 0; i < nIns; i++ ) + if ( pLine[nIns-1-i] == '1' ) + Abc_TtXorBit( Vec_WrdArray(vSimI) + i*nWords, iLine ); + else assert( pLine[nIns-1-i] == '0' ); + } + fclose( pFile ); + *pvSimI = vSimI; + printf( "Read %d words of simulation data for %d inputs (padded to 64-bit boundary with %d zero-patterns).\n", nWords, nIns, nWords*64-nLines ); + return nIns; +} +Vec_Int_t * Vec_WrdReadNumsOut( char * pFileName, int fVerbose ) +{ + char pLine[1000]; + Vec_Int_t * vNums; int iLine; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return NULL; + } + vNums = Vec_IntAlloc( 1000 ); + for ( iLine = 0; fgets( pLine, 1000, pFile ); iLine++ ) + Vec_IntPush( vNums, atoi(pLine) ); + fclose( pFile ); + if ( fVerbose ) + printf( "Finished reading %d output values from file \"%s\".\n", Vec_IntSize(vNums), pFileName ); + return vNums; +} +Vec_Wrd_t * Vec_WrdReadTextOut( char * pFileName, int nOuts ) +{ + int i, iLine, nLines, nWords; + Vec_Wrd_t * vSimO; + Vec_Int_t * vNums = Vec_WrdReadNumsOut( pFileName, 1 ); + if ( vNums == NULL ) + return NULL; + nLines = Vec_IntSize(vNums); + nWords = (nLines + 63)/64; + vSimO = Vec_WrdStart( nOuts*nWords ); + Vec_IntForEachEntry( vNums, i, iLine ) + Abc_TtXorBit( Vec_WrdArray(vSimO) + i*nWords, iLine ); + Vec_IntFree( vNums ); + printf( "Read %d words of simulation data for %d outputs (padded %d zero-patterns).\n", nWords, nOuts, nWords*64-nLines ); + return vSimO; +} +void Gia_ManReadSimInfoInputs( char * pFileName, char * pFileOut1, int fVerbose ) +{ + Vec_Wrd_t * vSimI; + Vec_WrdReadText2( pFileName, &vSimI ); + Vec_WrdDumpBin( pFileOut1, vSimI, fVerbose ); + Vec_WrdFree( vSimI ); +} +void Gia_ManReadSimInfoOutputs( char * pFileName, char * pFileOut, int nOuts ) +{ + Vec_Wrd_t * vSimO = Vec_WrdReadTextOut( pFileName, nOuts ); + Vec_WrdDumpBin( pFileOut, vSimO, 1 ); + Vec_WrdFree( vSimO ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wrd_t * Vec_WrdZoneExtract( int ZoneSize, Vec_Wrd_t * p, int iWord, int nWords ) +{ + int z, nZones = Vec_WrdSize(p)/ZoneSize; + int w, Limit = Abc_MinInt( nWords, ZoneSize-iWord ); + Vec_Wrd_t * pNew = Vec_WrdStart( nZones*nWords ); + for ( z = 0; z < nZones; z++ ) + for ( w = 0; w < Limit; w++ ) + Vec_WrdWriteEntry( pNew, z*nWords + w, Vec_WrdEntry(p, z*ZoneSize + iWord + w) ); + return pNew; +} +void Vec_WrdZoneInsert( Vec_Wrd_t * pNew, int ZoneSize, Vec_Wrd_t * p, int iWord, int nWords ) +{ + int z, nZones = Vec_WrdSize(pNew)/ZoneSize; + int w, Limit = Abc_MinInt( nWords, ZoneSize-iWord ); + for ( z = 0; z < nZones; z++ ) + for ( w = 0; w < Limit; w++ ) + Vec_WrdWriteEntry( pNew, z*ZoneSize + iWord + w, Vec_WrdEntry(p, z*nWords + w) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimInfoPrintOne( Gia_Man_t * p, Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nWords, int nPats ) +{ + int Id, i, k; + for ( k = 0; k < nPats; k++ ) + { + Gia_ManForEachCiId( p, Id, i ) + // printf( "%d", Vec_WrdEntry(p->vSims, p->nSimWords*Id) & 1 ); + printf( "%d", (int)(Vec_WrdEntry(vSimsIn, nWords*i) >> k) & 1 ); + printf( " " ); + Gia_ManForEachCoId( p, Id, i ) + // printf( "%d", Vec_WrdEntry(p->vSims, p->nSimWords*Id) & 1 ); + printf( "%d", (int)(Vec_WrdEntry(vSimsOut, nWords*i) >> k) & 1 ); + printf( "\n" ); + } +} +Vec_Wrd_t * Gia_ManSimInfoTryOne( Gia_Man_t * p, Vec_Wrd_t * vSimI, int fPrint ) +{ + extern Vec_Wrd_t * Gia_ManSimulateWordsOut( Gia_Man_t * p, Vec_Wrd_t * vSimsIn ); + Vec_Wrd_t * vSimsOut = Gia_ManSimulateWordsOut( p, vSimI ); + int nWords = Vec_WrdSize(vSimI) / Gia_ManCiNum(p); + assert( Vec_WrdSize(vSimI) % Gia_ManCiNum(p) == 0 ); + if ( fPrint ) + Gia_ManSimInfoPrintOne( p, vSimI, vSimsOut, nWords, 6 ); + return vSimsOut; +} +int Gia_ManSimEvalOne( Gia_Man_t * p, Vec_Wrd_t * vSimO, Vec_Wrd_t * vSimO_new ) +{ + int i, Count = 0, nWords = Vec_WrdSize(vSimO) / Gia_ManCoNum(p); + word * pSim0 = ABC_CALLOC( word, nWords ); + assert( Vec_WrdSize(vSimO) == Vec_WrdSize(vSimO_new) ); + for ( i = 0; i < Gia_ManCoNum(p); i++ ) + { + word * pSimGold = Vec_WrdEntryP( vSimO, i * nWords ); + word * pSimImpl = Vec_WrdEntryP( vSimO_new, i * nWords ); + Abc_TtOrXor( pSim0, pSimImpl, pSimGold, nWords ); + } + Count = Abc_TtCountOnesVec( pSim0, nWords ); + printf( "Number of failed patterns is %d (%8.4f %% of %d). The first one is %d.\n", + Count, 100.0*Count/(64*nWords), 64*nWords, Abc_TtFindFirstBit2(pSim0, nWords) ); + ABC_FREE( pSim0 ); + return Count; +} +int Gia_ManSimEvalOne2( Gia_Man_t * p, Vec_Wrd_t * vSimO, Vec_Wrd_t * vSimO_new ) +{ + int i, Count = 0, nWords = Vec_WrdSize(vSimO) / Gia_ManCoNum(p); + word * pSim0 = ABC_CALLOC( word, nWords ); + assert( Vec_WrdSize(vSimO) == Vec_WrdSize(vSimO_new) ); + for ( i = 0; i < Gia_ManCoNum(p); i++ ) + { + word * pSimGold = Vec_WrdEntryP( vSimO, i * nWords ); + word * pSimImpl = Vec_WrdEntryP( vSimO_new, i * nWords ); + Abc_TtXor( pSim0, pSimImpl, pSimGold, nWords, 0 ); + Count += Abc_TtCountOnesVec( pSim0, nWords ); + } + printf( "Number of failed patterns is %d (%8.4f %% of %d). The first one is %d.\n", + Count, 100.0*Count/(64*nWords*Gia_ManCoNum(p)), 64*nWords*Gia_ManCoNum(p), Abc_TtFindFirstBit2(pSim0, nWords) ); + ABC_FREE( pSim0 ); + return Count; +} +int Gia_ManSimEvalMaxValue( Vec_Wrd_t * vSimO, int nWords, int nOuts, int nBits, int iPat ) +{ + int o, ValueMax = -1, OutMax = -1; + for ( o = 0; o < nOuts; o++ ) + { + int i, Value = 0; + for ( i = 0; i < nBits; i++ ) + { + word * pSim = Vec_WrdEntryP( vSimO, (o*nBits+i) * nWords ); + if ( Abc_TtGetBit(pSim, iPat) ) + Value |= 1 << i; + } + if ( ValueMax <= Value ) + { + ValueMax = Value; + OutMax = o; + } + } + return OutMax; +} +int Gia_ManSimEvalOne3( Gia_Man_t * p, Vec_Wrd_t * vSimO, Vec_Int_t * vValues, int nBits ) +{ + int i, Value, nOuts = Gia_ManCoNum(p) / nBits; + int First = -1, Count = 0, nWords = Vec_WrdSize(vSimO) / Gia_ManCoNum(p); + assert( Gia_ManCoNum(p) % nBits == 0 ); + assert( 64*(nWords-1) < Vec_IntSize(vValues) && Vec_IntSize(vValues) <= 64*nWords ); + Vec_IntForEachEntry( vValues, Value, i ) + if ( Value == Gia_ManSimEvalMaxValue(vSimO, nWords, nOuts, nBits, i) ) + { + Count++; + if ( First == -1 ) + First = i; + } + printf( "The accuracy is %8.4f %% (%d out of %d output are correct, for example, output number %d).\n", + 100.0*Count/Vec_IntSize(vValues), Count, Vec_IntSize(vValues), First ); + if ( 0 ) + { + FILE * pTable = fopen( "stats.txt", "a+" ); + fprintf( pTable, "%0.2f \n", 100.0*Count/Vec_IntSize(vValues) ); + fclose( pTable ); + } + return Count; +} +Vec_Wrd_t * Gia_ManSimInfoTry( Gia_Man_t * p, Vec_Wrd_t * vSimI ) +{ + int nWords = Vec_WrdSize(vSimI) / Gia_ManCiNum(p); + int w, nWordsOne = 200, nWordBatches = (nWords + nWordsOne - 1)/nWordsOne; + Vec_Wrd_t * vSimO_new = Vec_WrdStart( nWords * Gia_ManCoNum(p) ); + for ( w = 0; w < nWordBatches; w++ ) + { + //int Value = printf( "%3d / %3d : ", w, nWordBatches ); + Vec_Wrd_t * vSimI_ = Vec_WrdZoneExtract( nWords, vSimI, w*nWordsOne, nWordsOne ); + Vec_Wrd_t * vSimO_ = Gia_ManSimInfoTryOne( p, vSimI_, 0 ); + Vec_WrdZoneInsert( vSimO_new, nWords, vSimO_, w*nWordsOne, nWordsOne ); + Vec_WrdFree( vSimI_ ); + Vec_WrdFree( vSimO_ ); + //Value = 0; + } + return vSimO_new; +} +int Gia_ManSimInfoEval_old( Gia_Man_t * p, Vec_Wrd_t * vSimO, Vec_Wrd_t * vSimO_new ) +{ + int nResult = Gia_ManSimEvalOne2(p, vSimO, vSimO_new); + //Vec_WrdDumpBin( "temp.simo", vSimO_new, 1 ); + printf( "Total errors = %d. ", nResult ); + printf( "Density of output patterns %8.4f.\n", (float)Abc_TtCountOnesVec(Vec_WrdArray(vSimO_new), Vec_WrdSize(vSimO_new))/(64*Vec_WrdSize(vSimO_new)) ); + return nResult; +} +void Gia_ManSimInfoPassTest( Gia_Man_t * p, char * pFileName, char * pFileName2, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Vec_Wrd_t * vSimI = Vec_WrdReadBin( pFileName, fVerbose ); + Vec_Wrd_t * vSimO = Gia_ManSimInfoTry( p, vSimI ); + if ( fVerbose ) + printf( "Density of input patterns %8.4f.\n", (float)Abc_TtCountOnesVec(Vec_WrdArray(vSimI), Vec_WrdSize(vSimI))/(64*Vec_WrdSize(vSimI)) ); + if ( fVerbose ) + printf( "Density of output patterns %8.4f.\n", (float)Abc_TtCountOnesVec(Vec_WrdArray(vSimO), Vec_WrdSize(vSimO))/(64*Vec_WrdSize(vSimO)) ); + Vec_WrdDumpBin( pFileName2, vSimO, fVerbose ); + Vec_WrdFree( vSimI ); + Vec_WrdFree( vSimO ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} +void Gia_ManSimInfoEval( Gia_Man_t * p, char * pFileName, char * pFileName2, int nOuts, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Vec_Wrd_t * vSim1 = Vec_WrdReadBin( pFileName, fVerbose ); + Vec_Int_t * vNums = Vec_WrdReadNumsOut( pFileName2, fVerbose ); + assert( nOuts > 0 ); + if ( fVerbose ) + printf( "Density of input patterns %8.4f.\n", (float)Abc_TtCountOnesVec(Vec_WrdArray(vSim1), Vec_WrdSize(vSim1))/(64*Vec_WrdSize(vSim1)) ); + Gia_ManSimEvalOne3( p, vSim1, vNums, nOuts ); + Vec_WrdFree( vSim1 ); + Vec_IntFree( vNums ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word * Gia_ManCountFraction( Gia_Man_t * p, Vec_Wrd_t * vSimI, Vec_Int_t * vSupp, int Thresh, int fVerbose, int * pCare ) +{ + Gia_Obj_t * pObj; + int i, k, nUsed = 0, nGood = 0; + int nWords = Vec_WrdSize(vSimI) / Gia_ManCiNum(p); + int nMints = 1 << Vec_IntSize(vSupp); + word ** pSims = ABC_ALLOC( word *, Vec_IntSize(vSupp) ); + word * pRes = ABC_CALLOC( word, Abc_Truth6WordNum(Vec_IntSize(vSupp)) ); + int * pCounts = ABC_CALLOC( int, nMints ); + Gia_ManForEachObjVec( vSupp, p, pObj, i ) + pSims[i] = Vec_WrdEntryP( vSimI, Gia_ObjCioId(pObj) * nWords ); + for ( k = 0; k < 64*nWords; k++ ) + { + int iMint = 0; + for ( i = 0; i < Vec_IntSize(vSupp); i++ ) + if ( Abc_TtGetBit(pSims[i], k) ) + iMint |= 1 << i; + assert( iMint < nMints ); + pCounts[iMint]++; + } + for ( k = 0; k < nMints; k++ ) + { + nUsed += (pCounts[k] > 0); + nGood += (pCounts[k] >= Thresh); + if ( pCounts[k] >= Thresh ) + Abc_TtXorBit( pRes, k ); + //printf( "%d ", pCounts[k] ); + } + if ( Vec_IntSize(vSupp) < 6 ) + pRes[0] = Abc_Tt6Stretch( pRes[0], Vec_IntSize(vSupp) ); + //printf( "\n" ); + if ( fVerbose ) + printf( "Used %4d and good %4d (out of %4d).\n", nUsed, nGood, nMints ); + ABC_FREE( pSims ); + ABC_FREE( pCounts ); + *pCare = nGood; + return pRes; +} +void Gia_ManPermuteSupp_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vLevels, Vec_Int_t * vCounts ) +{ + Gia_Obj_t * pObj; int n; + if ( !iObj || Gia_ObjIsTravIdCurrentId(p, iObj) ) + return; + Gia_ObjSetTravIdCurrentId(p, iObj); + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManPermuteSupp_rec( p, Gia_ObjFaninId0(pObj, iObj), vLevels, vCounts ); + Gia_ManPermuteSupp_rec( p, Gia_ObjFaninId1(pObj, iObj), vLevels, vCounts ); + for ( n = 0; n < 2; n++ ) + { + Gia_Obj_t * pFanin = n ? Gia_ObjFanin1(pObj) : Gia_ObjFanin0(pObj); + if ( !Gia_ObjIsCi(pFanin) ) + continue; + Vec_IntAddToEntry( vLevels, Gia_ObjCioId(pFanin), Gia_ObjLevel(p, pObj) ); + Vec_IntAddToEntry( vCounts, Gia_ObjCioId(pFanin), 1 ); + } +} +void Gia_ManPermuteSupp( Gia_Man_t * p, int iOut, int nOuts, Vec_Int_t * vSupp ) +{ + Vec_Int_t * vLevels = Vec_IntStart( Gia_ManCiNum(p) ); + Vec_Int_t * vCounts = Vec_IntStart( Gia_ManCiNum(p) ); + int i, * pCost = ABC_CALLOC( int, Gia_ManCiNum(p) ); + Gia_Obj_t * pObj; + Gia_ManIncrementTravId( p ); + for ( i = 0; i < nOuts; i++ ) + Gia_ManPermuteSupp_rec( p, Gia_ObjFaninId0p(p, Gia_ManCo(p, iOut+i)), vLevels, vCounts ); + Gia_ManForEachObjVec( vSupp, p, pObj, i ) + pCost[i] = 10000 * Vec_IntEntry(vLevels, Gia_ObjCioId(pObj)) / Abc_MaxInt(1, Vec_IntEntry(vCounts, Gia_ObjCioId(pObj))); + Vec_IntFree( vCounts ); + Vec_IntFree( vLevels ); + Vec_IntSelectSortCost2( Vec_IntArray(vSupp), Vec_IntSize(vSupp), pCost ); + assert( Vec_IntSize(vSupp) < 2 || pCost[0] <= pCost[1] ); + ABC_FREE( pCost ); +} +void Gia_ManCollectSupp_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vSupp ) +{ + Gia_Obj_t * pObj; + if ( !iObj || Gia_ObjIsTravIdCurrentId(p, iObj) ) + return; + Gia_ObjSetTravIdCurrentId(p, iObj); + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + { + //Vec_IntPush( vSupp, Gia_ObjCioId(pObj) ); + Vec_IntPush( vSupp, Gia_ObjId(p, pObj) ); + return; + } + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManCollectSupp_rec( p, Gia_ObjFaninId0(pObj, iObj), vSupp ); + Gia_ManCollectSupp_rec( p, Gia_ObjFaninId1(pObj, iObj), vSupp ); +} +Vec_Int_t * Gia_ManCollectSupp( Gia_Man_t * p, int iOut, int nOuts ) +{ + Vec_Int_t * vSupp = Vec_IntAlloc( 16 ); int i; + Gia_ManIncrementTravId( p ); + for ( i = 0; i < nOuts; i++ ) + Gia_ManCollectSupp_rec( p, Gia_ObjFaninId0p(p, Gia_ManCo(p, iOut+i)), vSupp ); + return vSupp; +} +Vec_Int_t * Gia_ManCollectSuppNew( Gia_Man_t * p, int iOut, int nOuts ) +{ + Vec_Int_t * vRes = Gia_ManCollectSupp( p, iOut, nOuts ); + Gia_ManPermuteSupp( p, iOut, nOuts, vRes ); + return vRes; +} +int Gia_ManPerformLNetOpt_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return pObj->Value; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManPerformLNetOpt_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManPerformLNetOpt_rec( pNew, p, Gia_ObjFanin1(pObj) ); + return pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManPerformLNetOpt( Gia_Man_t * p, int fTryNew, char * pFileName, int nIns, int nOuts, int Thresh, int nRounds, int fVerbose ) +{ + extern Gia_Man_t * Gia_TryPermOpt( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ); + extern Gia_Man_t * Gia_TryPermOptCare( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ); + extern int Kit_TruthToGia2( Gia_Man_t * p, unsigned * pTruth0, unsigned * pTruth1, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); + abctime clk = Abc_Clock(); + Gia_Man_t * pNew; Gia_Obj_t * pObj; + Vec_Int_t * vMemory = Vec_IntAlloc( 1 << 18 ); + Vec_Int_t * vLeaves = Vec_IntAlloc( nIns ); + Vec_Wrd_t * vSimI = pFileName ? Vec_WrdReadBin( pFileName, fVerbose ) : NULL; + word * pTruth0 = ABC_CALLOC( word, Abc_Truth6WordNum(nIns) ); + word * pTruth1 = ABC_CALLOC( word, Abc_Truth6WordNum(nIns) ); int g, k; float CareAve = 0; + word * pTruthsTry = ABC_CALLOC( word, 2*nOuts*Abc_Truth6WordNum(nIns) ); + if ( vSimI && fVerbose ) + { + //int nPats = 64*Vec_WrdSize(vSimI)/Gia_ManCiNum(p); + printf( "Density of input patterns %8.4f.\n", (float)Abc_TtCountOnesVec(Vec_WrdArray(vSimI), Vec_WrdSize(vSimI))/(64*Vec_WrdSize(vSimI)) ); + printf( "Using patterns with count %d and higher as cares.\n", Thresh ); + } + Gia_ManLevelNum( p ); + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, k ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ObjComputeTruthTableStart( p, nIns ); + Gia_ManHashStart( pNew ); + for ( g = 0; g < Gia_ManCoNum(p); g += nOuts ) + { + Vec_Int_t * vSupp = Gia_ManCollectSuppNew( p, g, nOuts ); + int Care = 1 << Vec_IntSize(vSupp), Temp = fVerbose ? printf( "Group %3d / %3d / %3d : Supp = %3d %s", g, nOuts, Gia_ManCoNum(p), Vec_IntSize(vSupp), vSimI ? "":"\n" ) : 0; + word * pCare = vSimI ? Gia_ManCountFraction( p, vSimI, vSupp, Thresh, fVerbose, &Care ) : ABC_FALLOC( word, Abc_Truth6WordNum(Vec_IntSize(vSupp)) ); + int nWords = Abc_Truth6WordNum( Vec_IntSize(vSupp) ); + CareAve += 100.0*Care/(1 << Vec_IntSize(vSupp)); + assert( Vec_IntSize(vSupp) <= nIns ); + Vec_IntClear( vLeaves ); + Gia_ManForEachObjVec( vSupp, p, pObj, k ) + Vec_IntPush( vLeaves, pObj->Value ); + for ( k = 0; k < nOuts; k++ ) + { + Gia_Obj_t * pObj = Gia_ManCo( p, g+k ); + word * pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ObjFanin0(pObj), vSupp ); + Abc_TtSharp( pTruth0, pCare, pTruth, nWords ); + Abc_TtAnd( pTruth1, pCare, pTruth, nWords, 0 ); + if ( vSimI ) + { + Abc_TtCopy( pTruthsTry + (2*k+0)*nWords, pTruth1, nWords, 0 ); + Abc_TtCopy( pTruthsTry + (2*k+1)*nWords, pTruth0, nWords, 0 ); + } + else + Abc_TtCopy( pTruthsTry + k*nWords, pTruth1, nWords, 0 ); + if ( !fTryNew ) + { + pObj->Value = Kit_TruthToGia2( pNew, (unsigned *)pTruth0, (unsigned *)pTruth1, Vec_IntSize(vLeaves), vMemory, vLeaves, 1 ); + pObj->Value ^= Gia_ObjFaninC0(pObj); + } + } + if ( fTryNew ) + { + Gia_Man_t * pMin; + if ( vSimI ) + pMin = Gia_TryPermOpt( pTruthsTry, Vec_IntSize(vSupp), 2*nOuts, nWords, nRounds, fVerbose ); + else + pMin = Gia_TryPermOptCare( pTruthsTry, Vec_IntSize(vSupp), nOuts, nWords, nRounds, fVerbose ); + Gia_ManFillValue( pMin ); + Gia_ManConst0(pMin)->Value = 0; + Gia_ManForEachCi( pMin, pObj, k ) + pObj->Value = Vec_IntEntry( vLeaves, k ); + for ( k = 0; k < nOuts; k++ ) + { + Gia_Obj_t * pObj = Gia_ManCo( p, g+k ); + Gia_Obj_t * pObj2 = Gia_ManCo( pMin, k ); + pObj->Value = Gia_ManPerformLNetOpt_rec( pNew, pMin, Gia_ObjFanin0(pObj2) ); + pObj->Value ^= Gia_ObjFaninC0(pObj2); + pObj->Value ^= Gia_ObjFaninC0(pObj); + } + Gia_ManStop( pMin ); + } + ABC_FREE( pCare ); + Vec_IntFree( vSupp ); + Temp = 0; + } + CareAve /= Gia_ManCoNum(p)/nOuts; + Gia_ManHashStop( pNew ); + Gia_ManForEachCo( p, pObj, k ) + pObj->Value = Gia_ManAppendCo( pNew, pObj->Value ); + Gia_ObjComputeTruthTableStop( p ); + ABC_FREE( pTruth0 ); + ABC_FREE( pTruth1 ); + Vec_IntFree( vLeaves ); + Vec_IntFree( vMemory ); + Vec_WrdFreeP( &vSimI ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + printf( "Using patterns with count %d and higher as cares. Average care set is %8.4f %%. ", Thresh, CareAve ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + if ( 0 ) + { + FILE * pTable = fopen( "stats.txt", "a+" ); + fprintf( pTable, "%0.2f ", CareAve ); + fclose( pTable ); + } + ABC_FREE( pTruthsTry ); + return pNew; +} +Gia_Man_t * Gia_ManPerformLNetOptNew( Gia_Man_t * p, char * pFileName, int nIns, int nOuts, int Thresh, int nRounds, int fVerbose ) +{ + extern Gia_Man_t * Gia_TryPermOptNew( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ); + abctime clk = Abc_Clock(); + Gia_Man_t * pNew, * pMin; Gia_Obj_t * pObj; + Vec_Int_t * vLeaves = Vec_IntAlloc( nIns ); + Vec_Wrd_t * vSimI = pFileName ? Vec_WrdReadBin( pFileName, fVerbose ) : NULL; + word * pTruthsTry = ABC_CALLOC( word, (nOuts+1)*Abc_Truth6WordNum(nIns) ); + int k, g; float CareAve = 0; + if ( vSimI && fVerbose ) + { + //int nPats = 64*Vec_WrdSize(vSimI)/Gia_ManCiNum(p); + printf( "Density of input patterns %8.4f.\n", (float)Abc_TtCountOnesVec(Vec_WrdArray(vSimI), Vec_WrdSize(vSimI))/(64*Vec_WrdSize(vSimI)) ); + printf( "Using patterns with count %d and higher as cares.\n", Thresh ); + } + Gia_ManLevelNum( p ); + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, k ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ObjComputeTruthTableStart( p, nIns ); + Gia_ManHashStart( pNew ); + for ( g = 0; g < Gia_ManCoNum(p); g += nOuts ) + { + for ( k = 0; k < nOuts; k++ ) + if ( Gia_ObjIsAnd(Gia_ObjFanin0(Gia_ManCo( p, g+k ))) ) + break; + if ( k == nOuts ) + { + for ( k = 0; k < nOuts; k++ ) + { + Gia_Obj_t * pObj = Gia_ManCo( p, g+k ); + pObj->Value = Gia_ObjFanin0Copy(pObj); + } + continue; + } + else + { + + Vec_Int_t * vSupp = Gia_ManCollectSuppNew( p, g, nOuts ); + int Care = 1 << Vec_IntSize(vSupp), Temp = fVerbose ? printf( "Group %3d / %3d / %3d : Supp = %3d %s", g, nOuts, Gia_ManCoNum(p), Vec_IntSize(vSupp), vSimI ? "":"\n" ) : 0; + word * pCare = vSimI ? Gia_ManCountFraction( p, vSimI, vSupp, Thresh, fVerbose, &Care ) : ABC_FALLOC( word, Abc_Truth6WordNum(Vec_IntSize(vSupp)) ); + int nWords = Abc_Truth6WordNum( Vec_IntSize(vSupp) ); + CareAve += 100.0*Care/(1 << Vec_IntSize(vSupp)); + assert( Vec_IntSize(vSupp) <= nIns ); + Vec_IntClear( vLeaves ); + Gia_ManForEachObjVec( vSupp, p, pObj, k ) + Vec_IntPush( vLeaves, pObj->Value ); + for ( k = 0; k < nOuts; k++ ) + { + Gia_Obj_t * pObj = Gia_ManCo( p, g+k ); + word * pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ObjFanin0(pObj), vSupp ); + Abc_TtCopy( pTruthsTry + k*nWords, pTruth, nWords, Gia_ObjFaninC0(pObj) ); + } + Abc_TtCopy( pTruthsTry + nOuts*nWords, pCare, nWords, 0 ); + ABC_FREE( pCare ); + pMin = Gia_TryPermOptNew( pTruthsTry, Vec_IntSize(vSupp), nOuts, nWords, nRounds, fVerbose ); + Gia_ManFillValue( pMin ); + Gia_ManConst0(pMin)->Value = 0; + Gia_ManForEachCi( pMin, pObj, k ) + pObj->Value = Vec_IntEntry( vLeaves, k ); + Gia_ManForEachCo( pMin, pObj, k ) + { + Gia_Obj_t * pObj0 = Gia_ManCo( p, g+k ); + pObj0->Value = Gia_ManPerformLNetOpt_rec( pNew, pMin, Gia_ObjFanin0(pObj) ); + pObj0->Value ^= Gia_ObjFaninC0(pObj); + } + Gia_ManStop( pMin ); + Vec_IntFree( vSupp ); + Temp = 0; + + } + } + CareAve /= Gia_ManCoNum(p)/nOuts; + Gia_ManHashStop( pNew ); + Gia_ManForEachCo( p, pObj, k ) + pObj->Value = Gia_ManAppendCo( pNew, pObj->Value ); + Gia_ObjComputeTruthTableStop( p ); + Vec_IntFree( vLeaves ); + Vec_WrdFreeP( &vSimI ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + printf( "Using patterns with count %d and higher as cares. Average care set is %8.4f %%. ", Thresh, CareAve ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + if ( 0 ) + { + FILE * pTable = fopen( "stats.txt", "a+" ); + fprintf( pTable, "%0.2f ", CareAve ); + fclose( pTable ); + } + ABC_FREE( pTruthsTry ); + return pNew; +} + +#ifdef ABC_USE_CUDD + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDoMuxMapping( Gia_Man_t * p ) +{ + extern Gia_Man_t * Gia_ManPerformMfs( Gia_Man_t * p, Sfm_Par_t * pPars ); + Gia_Man_t * pTemp, * pNew = Gia_ManDup( p ); + Jf_Par_t Pars, * pPars = &Pars; int c, nIters = 2; + Sfm_Par_t Pars2, * pPars2 = &Pars2; + Lf_ManSetDefaultPars( pPars ); + Sfm_ParSetDefault( pPars2 ); + pPars2->nTfoLevMax = 5; + pPars2->nDepthMax = 100; + pPars2->nWinSizeMax = 2000; + for ( c = 0; c < nIters; c++ ) + { + pNew = Lf_ManPerformMapping( pTemp = pNew, pPars ); + Gia_ManStop( pTemp ); + pNew = Gia_ManPerformMfs( pTemp = pNew, pPars2 ); + Gia_ManStop( pTemp ); + if ( c == nIters-1 ) + break; + pNew = (Gia_Man_t *)Dsm_ManDeriveGia( pTemp = pNew, 0 ); + Gia_ManStop( pTemp ); + } + return pNew; +} +Gia_Man_t * Gia_ManDoMuxTransform( Gia_Man_t * p, int fReorder ) +{ + extern Gia_Man_t * Abc_NtkStrashToGia( Abc_Ntk_t * pNtk ); + extern int Abc_NtkBddToMuxesPerformGlo( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, int Limit, int fReorder, int fUseAdd ); + Gia_Man_t * pRes = NULL; + Aig_Man_t * pMan = Gia_ManToAig( p, 0 ); + Abc_Ntk_t * pNtk = Abc_NtkFromAigPhase( pMan ); + Abc_Ntk_t * pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); + pNtk->pName = Extra_UtilStrsav( pMan->pName ); + Aig_ManStop( pMan ); + //pNtkNew = Abc_NtkBddToMuxes( pNtk, 1, 1000000, 1 ); + if ( Abc_NtkBddToMuxesPerformGlo( pNtk, pNtkNew, 1000000, fReorder, 0 ) ) + { + Abc_Ntk_t * pStrash = Abc_NtkStrash( pNtkNew, 1, 1, 0 ); + pRes = Abc_NtkStrashToGia( pStrash ); + Abc_NtkDelete( pStrash ); + } + Abc_NtkDelete( pNtkNew ); + Abc_NtkDelete( pNtk ); + return pRes; +} +int Gia_ManDoTest1( Gia_Man_t * p, int fReorder ) +{ + Gia_Man_t * pTemp, * pNew; int Res; + pNew = Gia_ManDoMuxTransform( p, fReorder ); + pNew = Gia_ManDoMuxMapping( pTemp = pNew ); + Gia_ManStop( pTemp ); + Res = Gia_ManLutNum( pNew ); + Gia_ManStop( pNew ); + return Res; +} +Abc_Ntk_t * Gia_ManDoTest2( Gia_Man_t * p, int fReorder, int fTryNew ) +{ + extern Abc_Ntk_t * Abc_NtkFromMappedGia( Gia_Man_t * p, int fFindEnables, int fUseBuffs ); + Abc_Ntk_t * pNtkNew; + Gia_Man_t * pTemp, * pNew; + pNew = fTryNew ? Gia_ManDup(p) : Gia_ManDoMuxTransform( p, fReorder ); + pNew = Gia_ManDoMuxMapping( pTemp = pNew ); + Gia_ManStop( pTemp ); + pNtkNew = Abc_NtkFromMappedGia( pNew, 0, 0 ); + pNtkNew->pName = Extra_UtilStrsav(p->pName); + Gia_ManStop( pNew ); + Abc_NtkToSop( pNtkNew, 1, ABC_INFINITY ); + return pNtkNew; +} +Abc_Ntk_t * Abc_NtkMapTransform( Gia_Man_t * p, int nOuts, int fUseFixed, int fTryNew, int fVerbose ) +{ + extern Abc_Ntk_t * Abc_NtkSpecialMapping( Abc_Ntk_t * pNtk, int fVerbose ); + int i, k, g, nGroups = Gia_ManCoNum(p) / nOuts, CountsAll[3] = {0}; + Abc_Obj_t * pObjNew, * pFaninNew; Gia_Obj_t * pObj; + Abc_Ntk_t * pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); + assert( Gia_ManCoNum(p) % nOuts == 0 ); + pNtkNew->pName = Extra_UtilStrsav(p->pName); + pNtkNew->pSpec = Extra_UtilStrsav(p->pSpec); + Gia_ManFillValue( p ); + Gia_ManForEachPi( p, pObj, i ) + Abc_NtkCreatePi( pNtkNew ); + Gia_ManForEachPo( p, pObj, i ) + Abc_NtkCreatePo( pNtkNew ); + assert( nOuts <= 64 ); + for ( g = 0; g < nGroups; g++ ) + { + Gia_Man_t * pNew; Aig_Man_t * pMan; + Abc_Ntk_t * pNtk, * pNtkRes, * pNtkMap; + int pPos[64], Counter = 0, Counts[3] = {0}; + for ( i = 0; i < nOuts; i++ ) + pPos[i] = g*nOuts+i; + pNew = Gia_ManDupCones( p, pPos, nOuts, 1 ); + if ( !fUseFixed ) + pNtkMap = Gia_ManDoTest2( pNew, 1, fTryNew ); + else + { + pMan = Gia_ManToAig( pNew, 0 ); + pNtk = Abc_NtkFromAigPhase( pMan ); + Aig_ManStop( pMan ); + pNtkRes = Abc_NtkBddToMuxes( pNtk, 1, 1000000, 1 ); + Abc_NtkDelete( pNtk ); + pNtkMap = Abc_NtkSpecialMapping( pNtkRes, 0 ); + Abc_NtkDelete( pNtkRes ); + } + Gia_ManStop( pNew ); + Gia_ManForEachCi( p, pObj, i ) + if ( ~pObj->Value ) + Abc_NtkCi(pNtkMap, Counter++)->pCopy = Abc_NtkCi(pNtkNew, i); + assert( Counter == Abc_NtkCiNum(pNtkMap) ); + Abc_NtkForEachNode( pNtkMap, pObjNew, i ) + { + pObjNew->pCopy = Abc_NtkDupObj( pNtkNew, pObjNew, 0 ); + pObjNew->pCopy->fPersist = pObjNew->fPersist; + if ( pObjNew->fPersist ) + Counts[1]++; + else + Counts[0]++; + Abc_ObjForEachFanin( pObjNew, pFaninNew, k ) + Abc_ObjAddFanin( pObjNew->pCopy, pFaninNew->pCopy ); + } + Abc_NtkForEachCo( pNtkMap, pObjNew, i ) + Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, g*nOuts+i), Abc_ObjFanin0(pObjNew)->pCopy ); + Abc_NtkDelete( pNtkMap ); + + if ( fVerbose ) + { + printf( "%3d / %3d : ", g, nGroups ); + printf( "Test = %4d ", Counts[0] ); + printf( "MarkA = %4d ", Counts[1] ); + printf( "MarkB = %4d ", Counts[2] ); + printf( "\n" ); + } + + CountsAll[0] += Counts[0]; + CountsAll[1] += Counts[1]; + CountsAll[2] += Counts[2]; + } + if ( fVerbose ) + printf( "Total LUT count = %5d. MarkA = %5d. MarkB = %5d.\n", CountsAll[0], CountsAll[1], CountsAll[2] ); + // create names + Abc_NtkAddDummyPiNames( pNtkNew ); + Abc_NtkAddDummyPoNames( pNtkNew ); + Abc_NtkAddDummyBoxNames( pNtkNew ); + // check the resulting AIG + if ( !Abc_NtkCheck( pNtkNew ) ) + Abc_Print( 1, "Abc_NtkFromMappedGia(): Network check has failed.\n" ); + return pNtkNew; +} + +Abc_Ntk_t * Gia_ManPerformLNetMap( Gia_Man_t * p, int GroupSize, int fUseFixed, int fTryNew, int fVerbose ) +{ + int fPrintOnly = 0; + int Res1, Res2, Result = 0; + int g, nGroups = Gia_ManCoNum(p) / GroupSize; + assert( Gia_ManCoNum(p) % GroupSize == 0 ); + assert( GroupSize <= 64 ); + if ( fPrintOnly ) + { + for ( g = 0; g < nGroups; g++ ) + { + Gia_Man_t * pNew; + int o, pPos[64]; + for ( o = 0; o < GroupSize; o++ ) + pPos[o] = g*GroupSize+o; + pNew = Gia_ManDupCones( p, pPos, GroupSize, 0 ); + printf( "%3d / %3d : ", g, nGroups ); + printf( "Test1 = %4d ", Res1 = Gia_ManDoTest1(pNew, 0) ); + printf( "Test2 = %4d ", Res2 = Gia_ManDoTest1(pNew, 1) ); + printf( "Test = %4d ", Abc_MinInt(Res1, Res2) ); + printf( "\n" ); + Result += Abc_MinInt(Res1, Res2); + //Gia_ManPrintStats( pNew, NULL ); + Gia_ManStop( pNew ); + } + printf( "Total LUT count = %d.\n", Result ); + return NULL; + + } + return Abc_NtkMapTransform( p, GroupSize, fUseFixed, fTryNew, fVerbose ); +} + +#else + +Abc_Ntk_t * Gia_ManPerformLNetMap( Gia_Man_t * p, int GroupSize, int fUseFixed, int fTryNew, int fVerbose ) +{ + return NULL; +} + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaMinLut2.c b/yosys/abc/src/aig/gia/giaMinLut2.c new file mode 100644 index 00000000000..85cae0d2772 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaMinLut2.c @@ -0,0 +1,1372 @@ +/**CFile**************************************************************** + + FileName [giaMinLut.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Collapsing AIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaMinLut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "giaAig.h" +#include "base/main/mainInt.h" +#include "opt/sfm/sfm.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define TREE_MAX_VARS 16 + +typedef struct Tree_Sto_t_ Tree_Sto_t; +struct Tree_Sto_t_ +{ + int nIns; + int nOuts; + int pTried[TREE_MAX_VARS]; + int pPerm[TREE_MAX_VARS]; + int pIPerm[TREE_MAX_VARS]; + int nNodes[TREE_MAX_VARS]; + Vec_Int_t vCofs[TREE_MAX_VARS]; + word * pMem; +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Tree_Sto_t * Gia_ManTreeDup( Tree_Sto_t * p ) +{ + Tree_Sto_t * pSto = ABC_CALLOC( Tree_Sto_t, 1 ); + int i, k, Obj; + *pSto = *p; + pSto->pMem = Abc_TtDup( pSto->pMem, p->nOuts*Abc_TtWordNum(p->nIns), 0 ); + memset( pSto->vCofs, 0, sizeof(Vec_Int_t)*TREE_MAX_VARS ); + for ( i = 0; i < TREE_MAX_VARS; i++ ) + Vec_IntForEachEntry( p->vCofs+i, Obj, k ) + Vec_IntPush( pSto->vCofs+i, Obj ); + return pSto; +} +void Gia_ManTreeFree( Tree_Sto_t * p ) +{ + int i; + for ( i = 0; i < TREE_MAX_VARS; i++ ) + ABC_FREE( p->vCofs[i].pArray ); + ABC_FREE( p->pMem ); + ABC_FREE( p ); +} +int Gia_ManTreeCountNodes( Tree_Sto_t * p ) +{ + int i, nNodes = 0; + for ( i = 0; i < TREE_MAX_VARS; i++ ) + nNodes += p->nNodes[i]; + return nNodes; +} +void Gia_ManTreePrint( Tree_Sto_t * p ) +{ + int i; + printf( "Tree with %d nodes:\n", Gia_ManTreeCountNodes(p) ); + for ( i = p->nIns-1; i >= 0; i-- ) + printf( "Level %2d Var %2d : %s Nodes = %3d Cofs = %3d\n", + i, p->pIPerm[i], p->pTried[i]?"*":" ", p->nNodes[i], Vec_IntSize(p->vCofs+i) ); +// for ( i = p->nIns-1; i >= 0; i-- ) +// printf( "Var %2d Level %2d\n", i, p->pPerm[i] ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManFindOrAddNode( Tree_Sto_t * pSto, int iVar, int Truth, word * pCof ) +{ + int k, Obj; + if ( iVar > 5 ) + { + int nWords = Abc_TtWordNum(iVar); + Vec_IntForEachEntry( pSto->vCofs+iVar, Obj, k ) + if ( Abc_TtEqual( pSto->pMem + Obj, pCof, nWords ) ) + return 1; + Vec_IntPush( pSto->vCofs+iVar, pCof - pSto->pMem ); + } + else + { + Vec_IntForEachEntry( pSto->vCofs+iVar, Obj, k ) + if ( Obj == Truth ) + return 1; + Vec_IntPush( pSto->vCofs+iVar, Truth ); + } + return 0; +} +int Gia_ManProcessLevel( Tree_Sto_t * pSto, int iVar ) +{ + int k, Obj, nNodes = 0; + //Vec_IntPrint( pSto->vCofs+iVar ); + Vec_IntClear( pSto->vCofs+iVar ); + if ( iVar > 5 ) + { + int nWords = Abc_TtWordNum(iVar); + Vec_IntForEachEntry( pSto->vCofs+iVar+1, Obj, k ) + { + word * pCof0 = pSto->pMem + Obj; + word * pCof1 = pCof0 + nWords; + Gia_ManFindOrAddNode( pSto, iVar, -1, pCof0 ); + if ( Abc_TtEqual( pCof0, pCof1, nWords ) ) + continue; + Gia_ManFindOrAddNode( pSto, iVar, -1, pCof1 ); + nNodes++; + } + } + else + { + Vec_IntForEachEntry( pSto->vCofs+iVar+1, Obj, k ) + { + unsigned Cof0 = iVar < 5 ? Abc_Tt5Cofactor0( Obj, iVar ) : (unsigned) pSto->pMem[Obj]; + unsigned Cof1 = iVar < 5 ? Abc_Tt5Cofactor1( Obj, iVar ) : (unsigned)(pSto->pMem[Obj] >> 32); + Gia_ManFindOrAddNode( pSto, iVar, Cof0, NULL ); + if ( Cof0 == Cof1 ) + continue; + Gia_ManFindOrAddNode( pSto, iVar, Cof1, NULL ); + nNodes++; + } + } + //printf( "Level %2d : Nodes = %3d Cofs = %3d\n", iVar, nNodes, Vec_IntSize(pSto->vCofs+iVar) ); + //Vec_IntPrint( pSto->vCofs+iVar ); + //printf( "\n" ); + return nNodes; +} +Tree_Sto_t * Gia_ManContructTree( word * pTruths, int nIns, int nOuts, int nWords ) +{ + Tree_Sto_t * pSto = ABC_CALLOC( Tree_Sto_t, 1 ); int i; + assert( Abc_TtWordNum(nIns) == nWords ); + assert( nIns+1 <= TREE_MAX_VARS ); + pSto->pMem = Abc_TtDup(pTruths, nOuts*nWords, 0); + pSto->nIns = nIns; + pSto->nOuts = nOuts; + for ( i = 0; i < nIns; i++ ) + pSto->pPerm[i] = pSto->pIPerm[i] = i; + for ( i = 0; i < nOuts; i++ ) + Gia_ManFindOrAddNode( pSto, nIns, (unsigned)pSto->pMem[i], pSto->pMem + i*nWords ); + for ( i = nIns-1; i >= 0; i-- ) + pSto->nNodes[i] = Gia_ManProcessLevel( pSto, i ); + return pSto; +} +void Gia_ManContructTreeTest( word * pTruths, int nIns, int nOuts, int nWords ) +{ + Tree_Sto_t * pSto = Gia_ManContructTree( pTruths, nIns, nOuts, nWords ); + printf( "Total nodes = %d.\n", Gia_ManTreeCountNodes(pSto) ); + Gia_ManTreeFree( pSto ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSwapTree( Tree_Sto_t * pSto, int i ) +{ + int nNodes = pSto->nNodes[i+1] + pSto->nNodes[i]; + int v, o, nWords = Abc_TtWordNum(pSto->nIns); + //printf( "Swapping %2d and %2d ", i, i+1 ); + assert( i >= 0 && i < pSto->nIns-1 ); + for ( o = 0; o < pSto->nOuts; o++ ) + Abc_TtSwapAdjacent( pSto->pMem + o*nWords, nWords, i ); + for ( v = 5; v > i+1; v-- ) + pSto->nNodes[v] = Gia_ManProcessLevel( pSto, v ); + pSto->nNodes[i+1] = Gia_ManProcessLevel( pSto, i+1 ); + pSto->nNodes[i] = Gia_ManProcessLevel( pSto, i ); + ABC_SWAP( int, pSto->pTried[i], pSto->pTried[i+1] ); + ABC_SWAP( int, pSto->pIPerm[i], pSto->pIPerm[i+1] ); + pSto->pPerm[pSto->pIPerm[i+1]] = i+1; + pSto->pPerm[pSto->pIPerm[i]] = i; + return pSto->nNodes[i+1] + pSto->nNodes[i] - nNodes; +} +int Gia_ManFindBestPosition( word * pTruths, int nIns, int nOuts, int nWords, word * pStore, int fMoveMore, int * pnNodesMin, int fVerbose ) +{ + Tree_Sto_t * pSto = Gia_ManContructTree( pTruths, nIns, nOuts, nWords ); + //int v, vBest = nIns-1, nNodesCur = Gia_ManTreeCountNodes(pSto), nNodesMin = nNodesCur; + int v, vBest = -1, nNodesCur = Gia_ManTreeCountNodes(pSto), nNodesMin = ABC_INFINITY; + if ( fVerbose ) + Gia_ManTreePrint( pSto ); + Abc_TtCopy( pStore+(nIns-1)*nOuts*nWords, pSto->pMem, nOuts*nWords, 0 ); + for ( v = nIns-2; v >= 0; v-- ) + { + nNodesCur += Gia_ManSwapTree( pSto, v ); + if ( fMoveMore ? nNodesMin >= nNodesCur : nNodesMin > nNodesCur ) + { + nNodesMin = nNodesCur; + vBest = v; + } + if ( fVerbose ) + printf( "Level %2d -> %2d : Nodes = %4d. ", v+1, v, nNodesCur ); + Abc_TtCopy( pStore+v*nOuts*nWords, pSto->pMem, nOuts*nWords, 0 ); + if ( fVerbose ) + Gia_ManContructTreeTest( pSto->pMem, nIns, nOuts, nWords ); + } + assert( vBest != nIns-1 ); + Gia_ManTreeFree( pSto ); + if ( fVerbose ) + printf( "Best level = %d. Best nodes = %d.\n", vBest, nNodesMin ); + if ( pnNodesMin ) + *pnNodesMin = nNodesMin; + return vBest; +} +void Gia_ManPermStats( int nIns, int * pIPerm, int * pTried ) +{ + int v; + for ( v = nIns-1; v >= 0; v-- ) + printf( "Level = %2d : Var = %2d Tried = %2d\n", v, pIPerm[v], pTried[v] ); + printf( "\n" ); +} +int Gia_ManPermuteTreeOne( word * pTruths, int nIns, int nOuts, int nWords, int fRandom, int * pIPermOut, int fVeryVerbose, int fVerbose ) +{ + extern void Gia_ManDumpMuxes( Tree_Sto_t * p, char * pFileName, int * pIPerm ); + word * pStore = ABC_ALLOC( word, nIns*nOuts*nWords ); + int pTried[TREE_MAX_VARS] = {0}; + int pIPerm[TREE_MAX_VARS] = {0}; + int v, r, Pos, nNodesPrev = -1, nNodesMin = 0, nNoChange = 0; + int nNodesBeg, nNodesEnd; + Tree_Sto_t * pSto; + for ( v = 0; v < nIns; v++ ) + pIPerm[v] = v; + pSto = Gia_ManContructTree( pTruths, nIns, nOuts, nWords ); + nNodesBeg = Gia_ManTreeCountNodes(pSto); + //Gia_ManDumpMuxes( pSto, "from_tt1.aig", pIPerm ); + Gia_ManTreeFree( pSto ); + if ( fRandom ) + for ( v = 0; v < nIns; v++ ) + { + //int o, vRand = rand() % nIns; + int o, vRand = Gia_ManRandom(0) % nIns; + for ( o = 0; o < nOuts; o++ ) + Abc_TtSwapVars( pTruths + o*nWords, nIns, v, vRand ); + ABC_SWAP( int, pIPerm[vRand], pIPerm[v] ); + } + for ( r = 0; r < 10*nIns; r++ ) + { + nNodesPrev = nNodesMin; + if ( fVeryVerbose ) + printf( "\nRound %d:\n", r ); + Pos = Gia_ManFindBestPosition( pTruths, nIns, nOuts, nWords, pStore, r&1, &nNodesMin, fVeryVerbose ); + Abc_TtCopy( pTruths, pStore+Pos*nOuts*nWords, nOuts*nWords, 0 ); + pTried[nIns-1]++; + for ( v = nIns-2; v >= Pos; v-- ) + { + ABC_SWAP( int, pTried[v+1], pTried[v] ); + ABC_SWAP( int, pIPerm[v+1], pIPerm[v] ); + } + if ( fVeryVerbose ) + Gia_ManPermStats( nIns, pIPerm, pTried ); + nNoChange = nNodesPrev == nNodesMin ? nNoChange + 1 : 0; + if ( nNoChange == 4 ) + break; + } + pSto = Gia_ManContructTree( pTruths, nIns, nOuts, nWords ); + nNodesEnd = Gia_ManTreeCountNodes(pSto); + //Gia_ManDumpMuxes( pSto, "from_tt2.aig", pIPerm ); + if ( fVerbose ) + printf( "Nodes %5d -> %5d. ", nNodesBeg, nNodesEnd ); + Gia_ManTreeFree( pSto ); + ABC_FREE( pStore ); + if ( pIPermOut ) + memcpy( pIPermOut, pIPerm, sizeof(int)*nIns ); + return nNodesEnd; +} +void Gia_ManPermuteTree( word * pTruths, int nIns, int nOuts, int nWords, int fRandom, int fVerbose ) +{ + abctime clk = Abc_Clock(); + word * pTruthDup = Abc_TtDup( pTruths, nOuts*nWords, 0 ); + int r; + //srand( time(NULL) ); + Gia_ManRandom(1); + for ( r = 0; r < 100; r++ ) + { + Gia_ManPermuteTreeOne( pTruthDup, nIns, nOuts, nWords, fRandom, NULL, 0, fVerbose ); + Abc_TtCopy( pTruthDup, pTruths, nOuts*nWords, 0 ); + } + ABC_FREE( pTruthDup ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +#define TT_UNDEF ABC_CONST(0x1234567887654321) + +static inline word Abc_Tt6Min_rec( word uF, word uR, int nVars, Vec_Wrd_t * vNodes ) +{ + word uF0, uF1, uR0, uR1, uRes0, uRes1, uRes2; int i, Var; + assert( nVars <= 6 ); + assert( (uF & uR) == 0 ); + if ( !uF && !uR ) + return TT_UNDEF; + if ( !uF && !~uR ) + return 0; + if ( !~uF && !uR ) + return ~(word)0; + assert( nVars > 0 ); + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Abc_Tt6HasVar( uF, Var ) || Abc_Tt6HasVar( uR, Var ) ) + break; + assert( Var >= 0 ); + if ( 1 && vNodes ) + Vec_WrdForEachEntry( vNodes, uRes2, i ) + if ( !(uF & ~uRes2) && !(uRes2 & uR) ) + return uRes2; +// else if ( !(uF & uRes2) && !(~uRes2 & uR) ) +// return ~uRes2; + uF0 = Abc_Tt6Cofactor0( uF, Var ); + uF1 = Abc_Tt6Cofactor1( uF, Var ); + uR0 = Abc_Tt6Cofactor0( uR, Var ); + uR1 = Abc_Tt6Cofactor1( uR, Var ); + uRes0 = Abc_Tt6Min_rec( uF0, uR0, Var, vNodes ); + uRes1 = Abc_Tt6Min_rec( uF1, uR1, Var, vNodes ); + if ( uRes0 == TT_UNDEF && uRes1 == TT_UNDEF ) + return TT_UNDEF; + if ( uRes0 == TT_UNDEF ) + return uRes1; + if ( uRes1 == TT_UNDEF ) + return uRes0; + if ( uRes0 == uRes1 ) + return uRes0; +// if ( (uRes0 & ~uRes1) == 0 ) +// printf( "0" ); +// else if ( (~uRes0 & uRes1) == 0 ) +// printf( "1" ); +// else +// printf( "*" ); + uRes2 = (uRes0 & s_Truths6Neg[Var]) | (uRes1 & s_Truths6[Var]); + assert( !(uF & ~uRes2) ); + assert( !(uRes2 & uR) ); + if ( vNodes ) + Vec_WrdPush( vNodes, uRes2 ); + return uRes2; +} +word * Abc_TtMin_rec( word * pF, word * pR, int nVars, Vec_Wrd_t * vMemory, Vec_Wrd_t * vNodes, Vec_Wec_t * vNodes2 ) +{ + int i, Entry, nWords = Abc_TtWordNum(nVars); + word * pRes0, * pRes1, * pRes2 = Vec_WrdFetch( vMemory, nWords ); + if ( nVars <= 6 ) + { + pRes2[0] = Abc_Tt6Min_rec( pF[0], pR[0], nVars, vNodes ); + return pRes2; + } + assert( !Abc_TtIntersect(pF, pR, nWords, 0) ); + if ( Abc_TtIsConst0(pF, nWords) && Abc_TtIsConst0(pR, nWords) ) + return NULL; + if ( Abc_TtIsConst0(pF, nWords) && Abc_TtIsConst1(pR, nWords) ) + { + Abc_TtClear( pRes2, nWords ); + return pRes2; + } + if ( Abc_TtIsConst1(pF, nWords) && Abc_TtIsConst0(pR, nWords) ) + { + Abc_TtFill( pRes2, nWords ); + return pRes2; + } + nWords >>= 1; + if ( !Abc_TtHasVar( pF, nVars, nVars-1 ) && !Abc_TtHasVar( pR, nVars, nVars-1 ) ) + { + pRes0 = Abc_TtMin_rec( pF, pR, nVars-1, vMemory, vNodes, vNodes2 ); + Abc_TtCopy( pRes2, pRes0, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes0, nWords, 0 ); + return pRes2; + } + if ( 1 && vNodes2 ) + { + Vec_Int_t * vLayer = Vec_WecEntry( vNodes2, nVars ); + Vec_IntForEachEntry( vLayer, Entry, i ) + { + word * pTemp = Vec_WrdEntryP( vMemory, Entry ); + if ( !Abc_TtIntersect(pTemp, pF, 2*nWords, 1) && !Abc_TtIntersect(pTemp, pR, 2*nWords, 0) ) + return pTemp; +/* + if ( !Abc_TtIntersect(pTemp, pF, 2*nWords, 0) && !Abc_TtIntersect(pTemp, pR, 2*nWords, 1) ) + { + Abc_TtCopy( pRes2, pTemp, 2*nWords, 1 ); + return pRes2; + } +*/ + } + } + assert( nVars > 6 ); + pRes0 = Abc_TtMin_rec( pF, pR, nVars-1, vMemory, vNodes, vNodes2 ); + pRes1 = Abc_TtMin_rec( pF + nWords, pR + nWords, nVars-1, vMemory, vNodes, vNodes2 ); + if ( pRes0 == NULL && pRes1 == NULL ) + return NULL; + if ( pRes0 == NULL || pRes1 == NULL || Abc_TtEqual(pRes0, pRes1, nWords) ) + { + Abc_TtCopy( pRes2, pRes0 ? pRes0 : pRes1, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes0 ? pRes0 : pRes1, nWords, 0 ); + return pRes2; + } + Abc_TtCopy( pRes2, pRes0, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes1, nWords, 0 ); + assert( !Abc_TtIntersect(pRes2, pF, 2*nWords, 1) ); // assert( !(uF & ~uRes2) ); + assert( !Abc_TtIntersect(pRes2, pR, 2*nWords, 0) ); // assert( !(uRes2 & uR) ); + if ( vNodes2 ) + Vec_WecPush( vNodes2, nVars, pRes2 - Vec_WrdArray(vMemory) ); + return pRes2; +} +word * Abc_TtMin( word * pF, word * pR, int nVars, Vec_Wrd_t * vMemory, Vec_Wrd_t * vNodes, Vec_Wec_t * vNodes2 ) +{ + word * pResult; + int i, nWords = Abc_TtWordNum(nVars); + assert( nVars >= 0 && nVars <= 16 ); + for ( i = nVars; i < 6; i++ ) + assert( !Abc_Tt6HasVar(pF[0], i) && !Abc_Tt6HasVar(pR[0], i) ); + Vec_WrdClear( vMemory ); + Vec_WrdGrow( vMemory, 1 << 20 ); + pResult = Abc_TtMin_rec( pF, pR, nVars, vMemory, vNodes, vNodes2 ); + if ( pResult == NULL ) + { + Vec_WrdFill( vMemory, nWords, 0 ); + return Vec_WrdArray( vMemory ); + } + //printf( "Memory %d (Truth table %d)\n", Vec_WrdSize(vMemory), nWords ); + Abc_TtCopy( Vec_WrdArray(vMemory), pResult, nWords, 0 ); + Vec_WrdShrink( vMemory, nWords ); + return Vec_WrdArray(vMemory); +} +word * Abc_TtMinArray( word * p, int nOuts, int nVars, int * pnNodes, int fVerbose ) +{ + int o, i, nWords = Abc_TtWordNum(nVars); + word * pRes, * pResult = ABC_ALLOC( word, nOuts*nWords/2 ); + Vec_Wrd_t * vMemory = Vec_WrdAlloc( 100 ); + Vec_Wrd_t * vNodes = Vec_WrdAlloc( 100 ); + Vec_Wec_t * vNodes2 = Vec_WecStart( nVars+1 ); + Vec_WrdGrow( vMemory, 1 << 20 ); + for ( o = 0; o < nOuts/2; o++ ) + { + word * pF = p + (2*o+0)*nWords; + word * pR = p + (2*o+1)*nWords; + for ( i = nVars; i < 6; i++ ) + assert( !Abc_Tt6HasVar(pF[0], i) && !Abc_Tt6HasVar(pR[0], i) ); + pRes = Abc_TtMin_rec( pF, pR, nVars, vMemory, vNodes, vNodes2 ); + if ( pResult == NULL ) + Abc_TtClear( pResult + o*nWords, nWords ); + else + Abc_TtCopy( pResult + o*nWords, pRes, nWords, 0 ); + } + if ( fVerbose ) + printf( "Nodes = %5d. Nodes2 = %5d. Total = %5d. ", + Vec_WrdSize(vNodes), Vec_WecSizeSize(vNodes2), Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2) ); + //printf( "Memory %d (Truth table %d)\n", Vec_WrdSize(vMemory), nWords ); + if ( pnNodes ) + *pnNodes = Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2); + Vec_WrdFree( vMemory ); + Vec_WrdFree( vNodes ); + Vec_WecFree( vNodes2 ); + return pResult; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline word Abc_TtSimple6Min_rec( Gia_Man_t * p, word uF, word uC, int nVars, Vec_Wrd_t * vNodes, int * piLit, int * pPerm ) +{ + word uF0, uF1, uC0, uC1, uRes0, uRes1, uRes2; int i, Var, iLit0, iLit1; + word uFC = uF & uC; + word uRC = ~uF & uC; + assert( nVars <= 6 ); + *piLit = 0; + if ( !uFC ) + { + *piLit = 0; + return 0; + } + if ( !uRC ) + { + *piLit = 1; + return ~(word)0; + } + assert( nVars > 0 ); + if ( 1 && vNodes ) + { + int iLit; + Vec_WrdForEachEntryDouble( vNodes, uRes2, iLit, i ) + if ( !((uF ^ uRes2) & uC) ) + { + *piLit = (unsigned)iLit; + return uRes2; + } + else if ( !((uF ^ ~uRes2) & uC) ) + { + *piLit = Abc_LitNot( (unsigned)iLit ); + return ~uRes2; + } + } + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Abc_Tt6HasVar( uF, Var ) ) + break; + else + uC = Abc_Tt6Cofactor0(uC, Var) | Abc_Tt6Cofactor1(uC, Var); + assert( Var >= 0 ); + uF0 = Abc_Tt6Cofactor0( uF, Var ); + uF1 = Abc_Tt6Cofactor1( uF, Var ); + uC0 = Abc_Tt6Cofactor0( uC, Var ); + uC1 = Abc_Tt6Cofactor1( uC, Var ); + uRes0 = Abc_TtSimple6Min_rec( p, uF0, uC0, Var, vNodes, &iLit0, pPerm ); + uRes1 = Abc_TtSimple6Min_rec( p, uF1, uC1, Var, vNodes, &iLit1, pPerm ); + if ( uRes0 == uRes1 ) + { + *piLit = iLit0; + return uRes0; + } + uRes2 = (uRes0 & s_Truths6Neg[Var]) | (uRes1 & s_Truths6[Var]); + Var = pPerm ? pPerm[Var] : Var; + //if ( !(uRes0 & ~uRes1 & uC1) ) + if ( !(uRes0 & ~uRes1) ) + *piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 0), iLit1), iLit0 ); + //else if ( !(uRes1 & ~uRes0 & uC0) ) + else if ( !(uRes1 & ~uRes0) ) + *piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 1), iLit0), iLit1 ); + else + *piLit = Gia_ManHashMux( p, Abc_Var2Lit(1+Var, 0), iLit1, iLit0 ); + assert( !(uFC & ~uRes2) ); + assert( !(uRes2 & uRC) ); + if ( vNodes ) + Vec_WrdPushTwo( vNodes, uRes2, (word)*piLit ); + return uRes2; +} +word * Abc_TtSimpleMin_rec( Gia_Man_t * p, word * pF, word * pC, int nVars, Vec_Wrd_t * vMemory, Vec_Wrd_t * vNodes, Vec_Wec_t * vNodes2, int * piLit, int * pPerm ) +{ + int i, Entry, Var, iLit0, iLit1, nWords = Abc_TtWordNum(nVars); + word * pRes0, * pRes1, * pRes2 = Vec_WrdFetch( vMemory, nWords ); + *piLit = 0; + if ( nVars <= 6 ) + { + pRes2[0] = Abc_TtSimple6Min_rec( p, pF[0], pC[0], nVars, vNodes, piLit, pPerm ); + return pRes2; + } + if ( !Abc_TtIntersect(pF, pC, nWords, 0) ) + { + *piLit = 0; + Abc_TtClear( pRes2, nWords ); + return pRes2; + } + if ( !Abc_TtIntersect(pF, pC, nWords, 1) ) + { + *piLit = 1; + Abc_TtFill( pRes2, nWords ); + return pRes2; + } + nWords >>= 1; + if ( !Abc_TtHasVar( pF, nVars, nVars-1 ) ) + { + word * pCn = Vec_WrdFetch( vMemory, nWords ); + Abc_TtOr( pCn, pC, pC + nWords, nWords ); + pRes0 = Abc_TtSimpleMin_rec( p, pF, pCn, nVars-1, vMemory, vNodes, vNodes2, piLit, pPerm ); + Abc_TtCopy( pRes2, pRes0, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes0, nWords, 0 ); + return pRes2; + } + if ( 1 && vNodes2 ) + { + Vec_Int_t * vLayer = Vec_WecEntry( vNodes2, nVars ); int iLit; + Vec_IntForEachEntryDouble( vLayer, Entry, iLit, i ) + { + word * pTemp = Vec_WrdEntryP( vMemory, Entry ); + if ( Abc_TtEqualCare(pTemp, pF, pC, 0, 2*nWords) ) + { + *piLit = iLit; + return pTemp; + } + else if ( Abc_TtEqualCare(pTemp, pF, pC, 1, 2*nWords) ) + { + *piLit = Abc_LitNot(iLit); + Abc_TtCopy( pRes2, pTemp, 2*nWords, 1 ); + return pRes2; + } + } + } + assert( nVars > 6 ); + pRes0 = Abc_TtSimpleMin_rec( p, pF, pC, nVars-1, vMemory, vNodes, vNodes2, &iLit0, pPerm ); + pRes1 = Abc_TtSimpleMin_rec( p, pF + nWords, pC + nWords, nVars-1, vMemory, vNodes, vNodes2, &iLit1, pPerm ); + if ( Abc_TtEqual(pRes0, pRes1, nWords) ) + { + *piLit = iLit0; + Abc_TtCopy( pRes2, pRes0, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes0, nWords, 0 ); + return pRes2; + } + Abc_TtCopy( pRes2, pRes0, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes1, nWords, 0 ); + Var = pPerm ? pPerm[nVars-1] : nVars-1; + //if ( !Abc_TtIntersectCare(pRes1, pRes0, pC + nWords, nWords, 1) ) + if ( !Abc_TtIntersect(pRes1, pRes0, nWords, 1) ) + *piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 0), iLit1), iLit0 ); + //else if ( !Abc_TtIntersectCare(pRes0, pRes1, pC, nWords, 1) ) + else if ( !Abc_TtIntersect(pRes0, pRes1, nWords, 1) ) + *piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 1), iLit0), iLit1 ); + else + *piLit = Gia_ManHashMux( p, Abc_Var2Lit(1+Var, 0), iLit1, iLit0 ); + assert( Abc_TtEqualCare(pRes2, pF, pC, 0, 2*nWords) ); + if ( vNodes2 ) + { + Vec_Int_t * vLayer = Vec_WecEntry( vNodes2, nVars ); + Vec_IntPushTwo( vLayer, pRes2 - Vec_WrdArray(vMemory), *piLit ); + } + return pRes2; +} +Gia_Man_t * Abc_TtSimpleMinArrayNew( word * p, int nVars, int nOuts, int * pnNodes, int fVerbose, int * pIPerm ) +{ + Gia_Man_t * pNew, * pTemp; + int o, i, iLit, nWords = Abc_TtWordNum(nVars); + word * pF = ABC_ALLOC( word, nWords ); + word * pR = ABC_ALLOC( word, nWords ); + Vec_Wrd_t * vMemory = Vec_WrdAlloc( 100 ); + Vec_Wrd_t * vNodes = Vec_WrdAlloc( 100 ); + Vec_Wec_t * vNodes2 = Vec_WecStart( nVars+1 ); + Vec_WrdGrow( vMemory, 1 << 20 ); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "muxes" ); + for ( i = 0; i < nVars; i++ ) + Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + + for ( o = 0; o < nOuts; o++ ) + { + word * pCare = p + nOuts*nWords; + word * pTruth = p + o*nWords; + for ( i = nVars; i < 6; i++ ) + assert( !Abc_Tt6HasVar(pTruth[0], i) && !Abc_Tt6HasVar(pCare[0], i) ); + Abc_TtSimpleMin_rec( pNew, pTruth, pCare, nVars, vMemory, vNodes, vNodes2, &iLit, pIPerm ); + Gia_ManAppendCo( pNew, iLit ); + } + if ( fVerbose ) + printf( "Nodes = %5d. Nodes2 = %5d. Total = %5d. ", + Vec_WrdSize(vNodes), Vec_WecSizeSize(vNodes2), Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2) ); + //printf( "Memory %d (Truth table %d)\n", Vec_WrdSize(vMemory), nWords ); + if ( pnNodes ) + *pnNodes = Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2); + Vec_WrdFree( vMemory ); + Vec_WrdFree( vNodes ); + Vec_WecFree( vNodes2 ); + ABC_FREE( pF ); + ABC_FREE( pR ); + + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline word Abc_TtGia6Min_rec( Gia_Man_t * p, word uF, word uR, int nVars, Vec_Wrd_t * vNodes, int * piLit, int * pPerm ) +{ + word uF0, uF1, uR0, uR1, uRes0, uRes1, uRes2; int i, Var, iLit0, iLit1; + assert( nVars <= 6 ); + assert( (uF & uR) == 0 ); + *piLit = 0; + if ( !uF && !uR ) + return TT_UNDEF; + if ( !uF && !~uR ) + { + *piLit = 0; + return 0; + } + if ( !~uF && !uR ) + { + *piLit = 1; + return ~(word)0; + } + assert( nVars > 0 ); + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Abc_Tt6HasVar( uF, Var ) || Abc_Tt6HasVar( uR, Var ) ) + break; + assert( Var >= 0 ); + if ( 1 && vNodes ) + { + int iLit; + Vec_WrdForEachEntryDouble( vNodes, uRes2, iLit, i ) + if ( !(uF & ~uRes2) && !(uRes2 & uR) ) + { + *piLit = (unsigned)iLit; + return uRes2; + } + else if ( !(uF & uRes2) && !(~uRes2 & uR) ) + { + *piLit = Abc_LitNot( (unsigned)iLit ); + return ~uRes2; + } + } + uF0 = Abc_Tt6Cofactor0( uF, Var ); + uF1 = Abc_Tt6Cofactor1( uF, Var ); + uR0 = Abc_Tt6Cofactor0( uR, Var ); + uR1 = Abc_Tt6Cofactor1( uR, Var ); + uRes0 = Abc_TtGia6Min_rec( p, uF0, uR0, Var, vNodes, &iLit0, pPerm ); + uRes1 = Abc_TtGia6Min_rec( p, uF1, uR1, Var, vNodes, &iLit1, pPerm ); + if ( uRes0 == TT_UNDEF && uRes1 == TT_UNDEF ) + return TT_UNDEF; + if ( uRes0 == TT_UNDEF ) + { + *piLit = iLit1; + return uRes1; + } + if ( uRes1 == TT_UNDEF || uRes0 == uRes1 ) + { + *piLit = iLit0; + return uRes0; + } +// if ( (uRes0 & ~uRes1) == 0 ) +// printf( "0" ); +// else if ( (~uRes0 & uRes1) == 0 ) +// printf( "1" ); +// else +// printf( "*" ); + uRes2 = (uRes0 & s_Truths6Neg[Var]) | (uRes1 & s_Truths6[Var]); + Var = pPerm ? pPerm[Var] : Var; + if ( !(uRes0 & ~uRes1) ) + *piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 0), iLit1), iLit0 ); + else if ( !(uRes1 & ~uRes0) ) + *piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 1), iLit0), iLit1 ); + else + *piLit = Gia_ManHashMux( p, Abc_Var2Lit(1+Var, 0), iLit1, iLit0 ); + assert( !(uF & ~uRes2) ); + assert( !(uRes2 & uR) ); + if ( vNodes ) + Vec_WrdPushTwo( vNodes, uRes2, (word)*piLit ); + return uRes2; +} +word * Abc_TtGiaMin_rec( Gia_Man_t * p, word * pF, word * pR, int nVars, Vec_Wrd_t * vMemory, Vec_Wrd_t * vNodes, Vec_Wec_t * vNodes2, int * piLit, int * pPerm ) +{ + int i, Entry, Var, iLit0, iLit1, nWords = Abc_TtWordNum(nVars); + word * pRes0, * pRes1, * pRes2 = Vec_WrdFetch( vMemory, nWords ); + *piLit = 0; + if ( nVars <= 6 ) + { + pRes2[0] = Abc_TtGia6Min_rec( p, pF[0], pR[0], nVars, vNodes, piLit, pPerm ); + return pRes2; + } + assert( !Abc_TtIntersect(pF, pR, nWords, 0) ); + if ( Abc_TtIsConst0(pF, nWords) && Abc_TtIsConst0(pR, nWords) ) + return NULL; + if ( Abc_TtIsConst0(pF, nWords) && Abc_TtIsConst1(pR, nWords) ) + { + *piLit = 0; + Abc_TtClear( pRes2, nWords ); + return pRes2; + } + if ( Abc_TtIsConst1(pF, nWords) && Abc_TtIsConst0(pR, nWords) ) + { + *piLit = 1; + Abc_TtFill( pRes2, nWords ); + return pRes2; + } + nWords >>= 1; + if ( !Abc_TtHasVar( pF, nVars, nVars-1 ) && !Abc_TtHasVar( pR, nVars, nVars-1 ) ) + { + pRes0 = Abc_TtGiaMin_rec( p, pF, pR, nVars-1, vMemory, vNodes, vNodes2, piLit, pPerm ); + Abc_TtCopy( pRes2, pRes0, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes0, nWords, 0 ); + return pRes2; + } + if ( 1 && vNodes2 ) + { + Vec_Int_t * vLayer = Vec_WecEntry( vNodes2, nVars ); int iLit; + Vec_IntForEachEntryDouble( vLayer, Entry, iLit, i ) + { + word * pTemp = Vec_WrdEntryP( vMemory, Entry ); + if ( !Abc_TtIntersect(pTemp, pF, 2*nWords, 1) && !Abc_TtIntersect(pTemp, pR, 2*nWords, 0) ) + { + *piLit = iLit; + return pTemp; + } + else if ( !Abc_TtIntersect(pTemp, pF, 2*nWords, 0) && !Abc_TtIntersect(pTemp, pR, 2*nWords, 1) ) + { + *piLit = Abc_LitNot(iLit); + Abc_TtCopy( pRes2, pTemp, 2*nWords, 1 ); + return pRes2; + } + } +/* + if ( nVars > 7 ) + { + vLayer = Vec_WecEntry( vNodes2, nVars-1 ); + Vec_IntForEachEntryDouble( vLayer, Entry, iLit, i ) + { + word * pTemp = Vec_WrdEntryP( vMemory, Entry ); + if ( !Abc_TtIntersect(pTemp, pF, 2*nWords, 1) && !Abc_TtIntersect(pTemp, pR, 2*nWords, 0) ) + { + *piLit = iLit; + return pTemp; + } + else if ( !Abc_TtIntersect(pTemp, pF, 2*nWords, 0) && !Abc_TtIntersect(pTemp, pR, 2*nWords, 1) ) + { + *piLit = Abc_LitNot(iLit); + Abc_TtCopy( pRes2, pTemp, 2*nWords, 1 ); + return pRes2; + } + } + } +*/ + } + assert( nVars > 6 ); + pRes0 = Abc_TtGiaMin_rec( p, pF, pR, nVars-1, vMemory, vNodes, vNodes2, &iLit0, pPerm ); + pRes1 = Abc_TtGiaMin_rec( p, pF + nWords, pR + nWords, nVars-1, vMemory, vNodes, vNodes2, &iLit1, pPerm ); + if ( pRes0 == NULL && pRes1 == NULL ) + return NULL; + if ( pRes0 == NULL || pRes1 == NULL || Abc_TtEqual(pRes0, pRes1, nWords) ) + { + *piLit = pRes0 ? iLit0 : iLit1; + Abc_TtCopy( pRes2, pRes0 ? pRes0 : pRes1, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes0 ? pRes0 : pRes1, nWords, 0 ); + return pRes2; + } + Abc_TtCopy( pRes2, pRes0, nWords, 0 ); + Abc_TtCopy( pRes2 + nWords, pRes1, nWords, 0 ); + Var = pPerm ? pPerm[nVars-1] : nVars-1; + if ( !Abc_TtIntersect(pRes1, pRes0, nWords, 1) ) + *piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 0), iLit1), iLit0 ); + else if ( !Abc_TtIntersect(pRes0, pRes1, nWords, 1) ) + *piLit = Gia_ManHashOr( p, Gia_ManHashAnd(p, Abc_Var2Lit(1+Var, 1), iLit0), iLit1 ); + else + *piLit = Gia_ManHashMux( p, Abc_Var2Lit(1+Var, 0), iLit1, iLit0 ); + assert( !Abc_TtIntersect(pRes2, pF, 2*nWords, 1) ); // assert( !(uF & ~uRes2) ); + assert( !Abc_TtIntersect(pRes2, pR, 2*nWords, 0) ); // assert( !(uRes2 & uR) ); + if ( vNodes2 ) + { + Vec_Int_t * vLayer = Vec_WecEntry( vNodes2, nVars ); + Vec_IntPushTwo( vLayer, pRes2 - Vec_WrdArray(vMemory), *piLit ); + } + return pRes2; +} +Gia_Man_t * Abc_TtGiaMinArray( word * p, int nVars, int nOuts, int * pnNodes, int fVerbose, int * pIPerm ) +{ + Gia_Man_t * pNew, * pTemp; + int o, i, iLit, nWords = Abc_TtWordNum(nVars); + word * pRes, * pResult = ABC_ALLOC( word, nOuts*nWords/2 ); + Vec_Wrd_t * vMemory = Vec_WrdAlloc( 100 ); + Vec_Wrd_t * vNodes = Vec_WrdAlloc( 100 ); + Vec_Wec_t * vNodes2 = Vec_WecStart( nVars+1 ); + Vec_WrdGrow( vMemory, 1 << 20 ); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "muxes" ); + for ( i = 0; i < nVars; i++ ) + Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + + for ( o = 0; o < nOuts/2; o++ ) + { + word * pF = p + (2*o+0)*nWords; + word * pR = p + (2*o+1)*nWords; + for ( i = nVars; i < 6; i++ ) + assert( !Abc_Tt6HasVar(pF[0], i) && !Abc_Tt6HasVar(pR[0], i) ); + pRes = Abc_TtGiaMin_rec( pNew, pF, pR, nVars, vMemory, vNodes, vNodes2, &iLit, pIPerm ); + if ( pResult == NULL ) + { + Abc_TtClear( pResult + o*nWords, nWords ); + Gia_ManAppendCo( pNew, 0 ); + } + else + { + Abc_TtCopy( pResult + o*nWords, pRes, nWords, 0 ); + Gia_ManAppendCo( pNew, iLit ); + } + } + if ( fVerbose ) + printf( "Nodes = %5d. Nodes2 = %5d. Total = %5d. ", + Vec_WrdSize(vNodes), Vec_WecSizeSize(vNodes2), Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2) ); + //printf( "Memory %d (Truth table %d)\n", Vec_WrdSize(vMemory), nWords ); + if ( pnNodes ) + *pnNodes = Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2); + Vec_WrdFree( vMemory ); + Vec_WrdFree( vNodes ); + Vec_WecFree( vNodes2 ); + ABC_FREE( pResult ); + + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} +Gia_Man_t * Abc_TtGiaMinArrayNew( word * p, int nVars, int nOuts, int * pnNodes, int fVerbose, int * pIPerm ) +{ + Gia_Man_t * pNew, * pTemp; + int o, i, iLit, nWords = Abc_TtWordNum(nVars); + word * pF = ABC_ALLOC( word, nWords ); + word * pR = ABC_ALLOC( word, nWords ); + Vec_Wrd_t * vMemory = Vec_WrdAlloc( 100 ); + Vec_Wrd_t * vNodes = Vec_WrdAlloc( 100 ); + Vec_Wec_t * vNodes2 = Vec_WecStart( nVars+1 ); + Vec_WrdGrow( vMemory, 1 << 20 ); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "muxes" ); + for ( i = 0; i < nVars; i++ ) + Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + + for ( o = 0; o < nOuts; o++ ) + { + word * pCare = p + nOuts*nWords; + word * pTruth = p + o*nWords; + Abc_TtAnd( pF, pCare, pTruth, nWords, 0 ); + Abc_TtSharp( pR, pCare, pTruth, nWords ); + for ( i = nVars; i < 6; i++ ) + assert( !Abc_Tt6HasVar(pF[0], i) && !Abc_Tt6HasVar(pR[0], i) ); + Abc_TtGiaMin_rec( pNew, pF, pR, nVars, vMemory, vNodes, vNodes2, &iLit, pIPerm ); + Gia_ManAppendCo( pNew, iLit ); + } + if ( fVerbose ) + printf( "Nodes = %5d. Nodes2 = %5d. Total = %5d. ", + Vec_WrdSize(vNodes), Vec_WecSizeSize(vNodes2), Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2) ); + //printf( "Memory %d (Truth table %d)\n", Vec_WrdSize(vMemory), nWords ); + if ( pnNodes ) + *pnNodes = Vec_WrdSize(vNodes) + Vec_WecSizeSize(vNodes2); + Vec_WrdFree( vMemory ); + Vec_WrdFree( vNodes ); + Vec_WecFree( vNodes2 ); + ABC_FREE( pF ); + ABC_FREE( pR ); + + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManBuildMuxes6_rec( Gia_Man_t * p, word t, int nVars, int * pPerm ) +{ + int iLit0, iLit1, Var; + assert( nVars <= 6 ); + if ( t == 0 ) + return 0; + if ( ~t == 0 ) + return 1; + assert( nVars > 0 ); + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Abc_Tt6HasVar( t, Var ) ) + break; + assert( Var >= 0 ); + iLit0 = Gia_ManBuildMuxes6_rec( p, Abc_Tt6Cofactor0(t, Var), Var, pPerm ); + iLit1 = Gia_ManBuildMuxes6_rec( p, Abc_Tt6Cofactor1(t, Var), Var, pPerm ); + Var = pPerm ? pPerm[Var] : Var; + return Gia_ManAppendMux( p, Abc_Var2Lit(1+Var, 0), iLit1, iLit0 ); +} +int Gia_ManBuildMuxes_rec( Gia_Man_t * p, word * pTruth, int nVars, int * pPerm ) +{ + int iLit0, iLit1, Var, nWords = Abc_TtWordNum(nVars); + if ( nVars <= 6 ) + return Gia_ManBuildMuxes6_rec( p, pTruth[0], nVars, pPerm ); + if ( Abc_TtIsConst0(pTruth, nWords) ) + return 0; + if ( Abc_TtIsConst1(pTruth, nWords) ) + return 1; +/* + assert( nVars > 0 ); + if ( !Abc_TtHasVar( pTruth, nVars, nVars-1 ) ) + return Gia_ManBuildMuxes_rec( p, pTruth, nVars-1 ); + assert( nVars > 6 ); + iLit0 = Gia_ManBuildMuxes_rec( p, pTruth, nVars-1 ); + iLit1 = Gia_ManBuildMuxes_rec( p, pTruth+nWords/2, nVars-1 ); +*/ + assert( nVars > 0 ); + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Abc_TtHasVar( pTruth, nVars, Var ) ) + break; + assert( Var >= 0 ); + if ( Var < 6 ) + return Gia_ManBuildMuxes6_rec( p, pTruth[0], Var+1, pPerm ); + iLit0 = Gia_ManBuildMuxes_rec( p, pTruth, Var, pPerm ); + iLit1 = Gia_ManBuildMuxes_rec( p, pTruth+Abc_TtWordNum(Var), Var, pPerm ); + Var = pPerm ? pPerm[Var] : Var; + return Gia_ManAppendMux( p, Abc_Var2Lit(1+Var, 0), iLit1, iLit0 ); +} +Gia_Man_t * Gia_ManBuildMuxesTest( word * pTruth, int nIns, int nOuts, int * pPerm ) +{ + Gia_Man_t * pNew, * pTemp; + int i, nWords = Abc_TtWordNum(nIns); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "muxes" ); + for ( i = 0; i < nIns; i++ ) + Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + for ( i = 0; i < nOuts; i++ ) + Gia_ManAppendCo( pNew, Gia_ManBuildMuxes_rec( pNew, pTruth+i*nWords, nIns, pPerm ) ); + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} +Gia_Man_t * Gia_ManBuildMuxes( Tree_Sto_t * p, int * pIPerm ) +{ + return Gia_ManBuildMuxesTest( p->pMem, p->nIns, p->nOuts, pIPerm ? pIPerm : p->pIPerm ); +} +void Gia_ManDumpMuxes( Tree_Sto_t * p, char * pFileName, int * pIPerm ) +{ + Gia_Man_t * pNew = Gia_ManBuildMuxes( p, pIPerm ); + Gia_AigerWrite( pNew, pFileName, 0, 0, 0 ); + Gia_ManStop( pNew ); + printf( "Finished dumping tree into AIG file \"%s\".\n", pFileName ); +} +Gia_Man_t * Gia_ManCreateMuxGia( word * pTruths, int nIns, int nOuts, int nWords, int * pIPerm ) +{ + Tree_Sto_t * pSto = Gia_ManContructTree( pTruths, nIns, nOuts, nWords ); + Gia_Man_t * pNew = Gia_ManBuildMuxes( pSto, pIPerm ); + //printf( "Internal nodes = %5d.\n", Gia_ManTreeCountNodes(pSto) ); + Gia_ManTreeFree( pSto ); + return pNew; +} +void Gia_ManDumpMuxGia( word * pTruths, int nIns, int nOuts, int nWords, int * pIPerm, char * pFileName ) +{ + Tree_Sto_t * pSto = Gia_ManContructTree( pTruths, nIns, nOuts, nWords ); + Gia_ManDumpMuxes( pSto, pFileName, pIPerm ); + Gia_ManTreeFree( pSto ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_TryPermOptCare( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Gia_Man_t * pNew; + word * pTruthDup = Abc_TtDup( pTruths, nOuts*nWords, 0 ); + word * pTruthBest = ABC_FALLOC( word, (nOuts+1)*nWords ); + int pIPermBest[TREE_MAX_VARS] = {0}; + int pIPerm[TREE_MAX_VARS] = {0}; + int r, rBest = -1, nNodes = -1, nNodesBest = ABC_INFINITY; + //Gia_ManDumpMuxGia( pTruths, nIns, nOuts, nWords, NULL, "tt_beg.aig" ); + //srand( time(NULL) ); + Gia_ManRandom(1); + for ( r = 0; r < nRounds; r++ ) + { + nNodes = Gia_ManPermuteTreeOne( pTruthDup, nIns, nOuts, nWords, r>0, pIPerm, 0, fVerbose ); + if ( nNodesBest > nNodes ) + { + nNodesBest = nNodes; + memcpy( pIPermBest, pIPerm, sizeof(int)*nIns ); + Abc_TtCopy( pTruthBest, pTruthDup, nOuts*nWords, 0 ); + rBest = r; + } + Abc_TtCopy( pTruthDup, pTruths, nOuts*nWords, 0 ); + if ( fVerbose ) + printf( "\n" ); + } + if ( fVerbose ) + printf( "Best round %3d. Best nodes %5d. ", rBest, nNodesBest ); + ABC_FREE( pTruthDup ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + //pNew = Gia_ManCreateMuxGia( pTruthBest, nIns, nOuts, nWords, pIPermBest ); + pNew = Abc_TtSimpleMinArrayNew( pTruthBest, nIns, nOuts, NULL, 0, pIPermBest ); + //Gia_ManDumpMuxGia( pTruthBest, nIns, nOuts, nWords, pIPermBest, "tt_end.aig" ); + ABC_FREE( pTruthBest ); + return pNew; +} +Gia_Man_t * Gia_TryPermOpt2( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Gia_Man_t * pNew; + word * pRes, * pTruthDup = Abc_TtDup( pTruths, nOuts*nWords, 0 ); + word * pTruthBest = ABC_ALLOC( word, nOuts*nWords/2 ); + int pIPermBest[TREE_MAX_VARS] = {0}; + int pIPerm[TREE_MAX_VARS] = {0}; + int r, rBest = -1, nNodes = -1, nNodesBest = ABC_INFINITY; + assert( nOuts % 2 == 0 ); + // collect onsets + //for ( r = 0; r < nOuts/2; r++ ) + // Abc_TtCopy( pTruthBest+r*nWords, pTruths+2*r*nWords, nWords, 0 ); + //Gia_ManDumpMuxGia( pTruthBest, nIns, nOuts/2, nWords, NULL, "tt_beg.aig" ); + //srand( time(NULL) ); + Gia_ManRandom(1); + for ( r = 0; r < nRounds; r++ ) + { + int nNodesAll = Gia_ManPermuteTreeOne( pTruthDup, nIns, nOuts, nWords, r>0, pIPerm, 0, fVerbose ); + pRes = Abc_TtMinArray( pTruthDup, nOuts, nIns, &nNodes, fVerbose ); + if ( nNodesBest > nNodes ) + { + nNodesBest = nNodes; + memcpy( pIPermBest, pIPerm, sizeof(int)*nIns ); + Abc_TtCopy( pTruthBest, pRes, nOuts*nWords/2, 0 ); + rBest = r; + } + ABC_FREE( pRes ); + Abc_TtCopy( pTruthDup, pTruths, nOuts*nWords, 0 ); + if ( fVerbose ) + printf( "\n" ); + nNodesAll = 0; + } + if ( fVerbose ) + printf( "Best round %3d. Best nodes %5d. ", rBest, nNodesBest ); + ABC_FREE( pTruthDup ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + pNew = Gia_ManCreateMuxGia( pTruthBest, nIns, nOuts/2, nWords, pIPermBest ); + //Gia_ManDumpMuxGia( pTruthBest, nIns, nOuts/2, nWords, pIPermBest, "tt_end.aig" ); + ABC_FREE( pTruthBest ); + return pNew; +} +Gia_Man_t * Gia_TryPermOpt( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Gia_Man_t * pBest = NULL; + word * pTruthDup = Abc_TtDup( pTruths, nOuts*nWords, 0 ); + int pIPermBest[TREE_MAX_VARS] = {0}; + int pIPerm[TREE_MAX_VARS] = {0}; + int r, rBest = -1, nNodes2 = -1, nNodesBest = ABC_INFINITY; + assert( nOuts % 2 == 0 ); + //srand( time(NULL) ); + Gia_ManRandom(1); + for ( r = 0; r < nRounds; r++ ) + { + int nNodesAll = Gia_ManPermuteTreeOne( pTruthDup, nIns, nOuts, nWords, r>0, pIPerm, 0, fVerbose ); + Gia_Man_t * pTemp = Abc_TtGiaMinArray( pTruthDup, nIns, nOuts, NULL, 0, pIPerm ); + nNodes2 = Gia_ManAndNum(pTemp); + if ( nNodesBest > nNodes2 ) + { + nNodesBest = nNodes2; + memcpy( pIPermBest, pIPerm, sizeof(int)*nIns ); + rBest = r; + + Gia_ManStopP( &pBest ); + pBest = pTemp; + pTemp = NULL; + } + Gia_ManStopP( &pTemp ); + Abc_TtCopy( pTruthDup, pTruths, nOuts*nWords, 0 ); + if ( fVerbose ) + printf( "Permuted = %5d. AIG = %5d.\n", nNodesAll, nNodes2 ); + nNodesAll = 0; + } + if ( fVerbose ) + printf( "Best round %3d. Best nodes %5d. ", rBest, nNodesBest ); + ABC_FREE( pTruthDup ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return pBest; +} +Gia_Man_t * Gia_TryPermOptNew( word * pTruths, int nIns, int nOuts, int nWords, int nRounds, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Gia_Man_t * pTemp, * pBest = NULL; + word * pTruthDup = Abc_TtDup( pTruths, (nOuts+1)*nWords, 0 ); + int pIPermBest[TREE_MAX_VARS] = {0}; + int pIPerm[TREE_MAX_VARS] = {0}; + int r, rBest = -1, nNodes2 = -1, nNodesBest = ABC_INFINITY; + //srand( time(NULL) ); + Gia_ManRandom(1); + for ( r = 0; r < nRounds; r++ ) + { + int nNodesAll = Gia_ManPermuteTreeOne( pTruthDup, nIns, nOuts, nWords, r>0, pIPerm, 0, fVerbose ); + Abc_TtPermute( pTruthDup + nOuts*nWords, pIPerm, nIns ); + //pTemp = Abc_TtGiaMinArrayNew( pTruthDup, nIns, nOuts, NULL, 0, pIPerm ); + pTemp = Abc_TtSimpleMinArrayNew( pTruthDup, nIns, nOuts, NULL, 0, pIPerm ); + nNodes2 = Gia_ManAndNum(pTemp); + if ( nNodesBest > nNodes2 ) + { + nNodesBest = nNodes2; + memcpy( pIPermBest, pIPerm, sizeof(int)*nIns ); + rBest = r; + + Gia_ManStopP( &pBest ); + pBest = pTemp; + pTemp = NULL; + } + Gia_ManStopP( &pTemp ); +/* + for ( i = 0; i <= nOuts; i++ ) + { + Abc_TtUnpermute( pTruthDup + i*nWords, pIPerm, nIns ); + if ( !Abc_TtEqual(pTruthDup + i*nWords, pTruths + i*nWords, nWords) ) + printf( "Verification failed for output %d (out of %d).\n", i, nOuts ); + } +*/ + Abc_TtCopy( pTruthDup, pTruths, (nOuts+1)*nWords, 0 ); + if ( fVerbose ) + printf( "Permuted = %5d. AIG = %5d.\n", nNodesAll, nNodes2 ); + nNodesAll = 0; + } + if ( fVerbose ) + printf( "Best round %3d. Best nodes %5d. ", rBest, nNodesBest ); + ABC_FREE( pTruthDup ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return pBest; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_Tt6MinTest3( Gia_Man_t * p ) +{ + word f = ABC_CONST(0x513B00000819050F); + //word r = ABC_CONST(0xA000571507200000); + word r = ~f; + Vec_Wrd_t * vNodes = Vec_WrdAlloc( 100 ); + word Res = Abc_Tt6Min_rec( f, r, 6, vNodes ); + printf( "Nodes = %d.\n", Vec_WrdSize(vNodes) ); + if ( Res == f ) + printf( "Verification successful.\n" ); + else + printf( "Verification FAILED.\n" ); + Vec_WrdFree( vNodes ); +} +void Abc_Tt6MinTest2( Gia_Man_t * p ) +{ + int fVerbose = 0; + int i, nWords = Abc_TtWordNum(Gia_ManCiNum(p)); + word * pTruth = ABC_ALLOC( word, 3*nWords ); + word * pRes = NULL, * pTruths[3] = { pTruth, pTruth+nWords, pTruth+2*nWords }; + + Vec_Int_t * vSupp = Vec_IntAlloc( 100 ); + Vec_Wrd_t * vNodes = Vec_WrdAlloc( 100 ); + Vec_Wec_t * vNodes2 = Vec_WecAlloc( 100 ); + Vec_Wrd_t * vMemory = Vec_WrdAlloc( 0 ); + + Gia_Obj_t * pObj; + Gia_ManForEachCi( p, pObj, i ) + Vec_IntPush( vSupp, Gia_ObjId(p, pObj) ); + + Gia_ObjComputeTruthTableStart( p, Gia_ManCiNum(p) ); + assert( Gia_ManCoNum(p) == 3 ); + Gia_ManForEachCo( p, pObj, i ) + { + word * pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ObjFanin0(pObj), vSupp ); + Abc_TtCopy( pTruths[i], pTruth, nWords, Gia_ObjFaninC0(pObj) ); + } + Gia_ObjComputeTruthTableStop( p ); + + + //Abc_TtSharp( pTruths[0], pTruths[0], pTruths[1], nWords ); + Abc_TtReverseVars( pTruths[0], Gia_ManCiNum(p) ); + Abc_TtCopy( pTruths[1], pTruths[0], nWords, 1 ); + + pRes = Abc_TtMin( pTruths[0], pTruths[1], Gia_ManCiNum(p), vMemory, vNodes, vNodes2 ); + printf( "Nodes = %d.\n", Vec_WrdSize(vNodes) ); + printf( "Nodes2 = %d.\n", Vec_WecSizeSize(vNodes2) ); + if ( Abc_TtEqual(pRes, pTruths[0], nWords) ) + printf( "Verification successful.\n" ); + else + printf( "Verification FAILED.\n" ); + + //printf( "Printing the tree:\n" ); +// Gia_ManPermuteTree( pTruths[0], Gia_ManCiNum(p), 1, nWords, fVerbose ); + Gia_ManPermuteTree( pTruth, Gia_ManCiNum(p), 3, nWords, 0, fVerbose ); + + +/* + Abc_TtReverseVars( pTruths[0], Gia_ManCiNum(p) ); + Abc_TtReverseVars( pTruths[1], Gia_ManCiNum(p) ); + Abc_TtReverseVars( pTruths[2], Gia_ManCiNum(p) ); + printf( "Printing the tree:\n" ); + Gia_ManContructTree( pTruth, Gia_ManCiNum(p), 3, nWords ); +*/ + +/* + pNew = Gia_ManBuildMuxesTest( pTruth, Gia_ManCiNum(p), Gia_ManCoNum(p), NULL ); + Gia_AigerWrite( pNew, "from_tt.aig", 0, 0, 0 ); + printf( "Dumping file \"%s\".\n", "from_tt.aig" ); + Gia_ManStop( pNew ); +*/ + + Vec_WrdFree( vMemory ); + Vec_WrdFree( vNodes ); + Vec_WecFree( vNodes2 ); + Vec_IntFree( vSupp ); + ABC_FREE( pTruth ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaMini.c b/yosys/abc/src/aig/gia/giaMini.c new file mode 100644 index 00000000000..5ebedfb785a --- /dev/null +++ b/yosys/abc/src/aig/gia/giaMini.c @@ -0,0 +1,1392 @@ +/**CFile**************************************************************** + + FileName [giaMini.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Reader/writer for MiniAIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaMini.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "opt/dau/dau.h" +#include "base/main/mainInt.h" +#include "misc/util/utilTruth.h" +#include "aig/miniaig/miniaig.h" +#include "aig/miniaig/minilut.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Converts MiniAIG into GIA.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ObjFromMiniFanin0Copy( Gia_Man_t * pGia, Vec_Int_t * vCopies, Mini_Aig_t * p, int Id ) +{ + int Lit = Mini_AigNodeFanin0( p, Id ); + return Abc_LitNotCond( Vec_IntEntry(vCopies, Abc_Lit2Var(Lit)), Abc_LitIsCompl(Lit) ); +} +int Gia_ObjFromMiniFanin1Copy( Gia_Man_t * pGia, Vec_Int_t * vCopies, Mini_Aig_t * p, int Id ) +{ + int Lit = Mini_AigNodeFanin1( p, Id ); + return Abc_LitNotCond( Vec_IntEntry(vCopies, Abc_Lit2Var(Lit)), Abc_LitIsCompl(Lit) ); +} +Gia_Man_t * Gia_ManFromMiniAig( Mini_Aig_t * p, Vec_Int_t ** pvCopies, int fGiaSimple ) +{ + Gia_Man_t * pGia, * pTemp; + Vec_Int_t * vCopies; + int i, iGiaLit = 0, nNodes; + // get the number of nodes + nNodes = Mini_AigNodeNum(p); + // create ABC network + pGia = Gia_ManStart( nNodes ); + pGia->pName = Abc_UtilStrsav( "MiniAig" ); + // create mapping from MiniAIG objects into ABC objects + vCopies = Vec_IntAlloc( nNodes ); + Vec_IntPush( vCopies, 0 ); + // iterate through the objects + if ( fGiaSimple ) + pGia->fGiaSimple = fGiaSimple; + else + Gia_ManHashAlloc( pGia ); + for ( i = 1; i < nNodes; i++ ) + { + if ( Mini_AigNodeIsPi( p, i ) ) + iGiaLit = Gia_ManAppendCi(pGia); + else if ( Mini_AigNodeIsPo( p, i ) ) + iGiaLit = Gia_ManAppendCo(pGia, Gia_ObjFromMiniFanin0Copy(pGia, vCopies, p, i)); + else if ( Mini_AigNodeIsAnd( p, i ) ) + iGiaLit = Gia_ManHashAnd(pGia, Gia_ObjFromMiniFanin0Copy(pGia, vCopies, p, i), Gia_ObjFromMiniFanin1Copy(pGia, vCopies, p, i)); + else assert( 0 ); + Vec_IntPush( vCopies, iGiaLit ); + } + assert( Vec_IntSize(vCopies) == nNodes ); + if ( pvCopies ) + *pvCopies = vCopies; + else + Vec_IntFree( vCopies ); + Gia_ManSetRegNum( pGia, Mini_AigRegNum(p) ); + if ( !fGiaSimple ) + { + pGia = Gia_ManCleanup( pTemp = pGia ); + if ( pvCopies ) + Gia_ManDupRemapLiterals( *pvCopies, pTemp ); + Gia_ManStop( pTemp ); + } + return pGia; +} + +/**Function************************************************************* + + Synopsis [Converts GIA into MiniAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mini_Aig_t * Gia_ManToMiniAig( Gia_Man_t * pGia ) +{ + Mini_Aig_t * p; + Gia_Obj_t * pObj; + int i; + // create the manager + p = Mini_AigStart(); + Gia_ManConst0(pGia)->Value = Mini_AigLitConst0(); + // create primary inputs + Gia_ManForEachCi( pGia, pObj, i ) + pObj->Value = Mini_AigCreatePi(p); + // create internal nodes + Gia_ManForEachAnd( pGia, pObj, i ) + pObj->Value = Mini_AigAnd( p, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + // create primary outputs + Gia_ManForEachCo( pGia, pObj, i ) + pObj->Value = Mini_AigCreatePo( p, Gia_ObjFanin0Copy(pObj) ); + // set registers + Mini_AigSetRegNum( p, Gia_ManRegNum(pGia) ); + return p; +} + +/**Function************************************************************* + + Synopsis [Procedures to input/output MiniAIG into/from internal GIA.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameGiaInputMiniAig( Abc_Frame_t * pAbc, void * p ) +{ + Gia_Man_t * pGia; + if ( pAbc == NULL ) + printf( "ABC framework is not initialized by calling Abc_Start()\n" ); + Gia_ManStopP( &pAbc->pGiaMiniAig ); + Vec_IntFreeP( &pAbc->vCopyMiniAig ); + pGia = Gia_ManFromMiniAig( (Mini_Aig_t *)p, &pAbc->vCopyMiniAig, 0 ); + Abc_FrameUpdateGia( pAbc, pGia ); + pAbc->pGiaMiniAig = Gia_ManDup( pGia ); +// Gia_ManDelete( pGia ); +} +void * Abc_FrameGiaOutputMiniAig( Abc_Frame_t * pAbc ) +{ + Gia_Man_t * pGia; + if ( pAbc == NULL ) + printf( "ABC framework is not initialized by calling Abc_Start()\n" ); + pGia = Abc_FrameReadGia( pAbc ); + if ( pGia == NULL ) + printf( "Current network in ABC framework is not defined.\n" ); + return Gia_ManToMiniAig( pGia ); +} + +/**Function************************************************************* + + Synopsis [Procedures to read/write GIA to/from MiniAIG file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManReadMiniAigNames( char * pFileName, Gia_Man_t * pGia ) +{ + char * filename3 = Abc_UtilStrsavTwo( pFileName, ".ilo" ); + FILE * pFile = fopen( filename3, "rb" ); + if ( pFile ) + { + char Buffer[5000], * pName; int i, iLines = 0; + Vec_Ptr_t * vTemp = Vec_PtrAlloc( Gia_ManRegNum(pGia) ); + assert( pGia->vNamesIn == NULL ); + pGia->vNamesIn = Vec_PtrAlloc( Gia_ManCiNum(pGia) ); + assert( pGia->vNamesOut == NULL ); + pGia->vNamesOut = Vec_PtrAlloc( Gia_ManCoNum(pGia) ); + while ( fgets(Buffer, 5000, pFile) ) + { + if ( Buffer[strlen(Buffer)-1] == '\n' ) + Buffer[strlen(Buffer)-1] = 0; + if ( iLines < Gia_ManPiNum(pGia) ) + Vec_PtrPush( pGia->vNamesIn, Abc_UtilStrsav(Buffer) ); + else if ( iLines < Gia_ManCiNum(pGia) ) + Vec_PtrPush( vTemp, Abc_UtilStrsav(Buffer) ); + else + Vec_PtrPush( pGia->vNamesOut, Abc_UtilStrsav(Buffer) ); + iLines++; + } + Vec_PtrForEachEntry( char *, vTemp, pName, i ) + { + Vec_PtrPush( pGia->vNamesIn, Abc_UtilStrsav(pName) ); + Vec_PtrPush( pGia->vNamesOut, Abc_UtilStrsavTwo(pName, "_in") ); + } + Vec_PtrFreeFree( vTemp ); + fclose( pFile ); + printf( "Read ILO names into file \"%s\".\n", filename3 ); + } + ABC_FREE( filename3 ); +} +Gia_Man_t * Gia_ManReadMiniAig( char * pFileName, int fGiaSimple ) +{ + Mini_Aig_t * p = Mini_AigLoad( pFileName ); + Gia_Man_t * pTemp, * pGia = Gia_ManFromMiniAig( p, NULL, fGiaSimple ); + ABC_FREE( pGia->pName ); + pGia->pName = Extra_FileNameGeneric( pFileName ); + Mini_AigStop( p ); + Gia_ManReadMiniAigNames( pFileName, pGia ); + if ( !Gia_ManIsNormalized(pGia) ) + { + pGia = Gia_ManDupNormalize( pTemp = pGia, 0 ); + ABC_SWAP( Vec_Ptr_t *, pTemp->vNamesIn, pGia->vNamesIn ); + ABC_SWAP( Vec_Ptr_t *, pTemp->vNamesOut, pGia->vNamesOut ); + Gia_ManStop( pTemp ); + } + return pGia; +} +void Gia_ManWriteMiniAig( Gia_Man_t * pGia, char * pFileName ) +{ + Mini_Aig_t * p = Gia_ManToMiniAig( pGia ); + Mini_AigDump( p, pFileName ); + //Mini_AigDumpVerilog( "test_miniaig.v", "top", p ); + Mini_AigStop( p ); +} + + + + +/**Function************************************************************* + + Synopsis [Converts MiniLUT into GIA.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManFromMiniLut( Mini_Lut_t * p, Vec_Int_t ** pvCopies ) +{ + Gia_Man_t * pGia, * pTemp; + Vec_Int_t * vCopies; + Vec_Int_t * vCover = Vec_IntAlloc( 1000 ); + Vec_Int_t * vLits = Vec_IntAlloc( 100 ); + int i, k, Fan, iGiaLit, nNodes; + int LutSize = Abc_MaxInt( 2, Mini_LutSize(p) ); + // get the number of nodes + nNodes = Mini_LutNodeNum(p); + // create ABC network + pGia = Gia_ManStart( 3 * nNodes ); + pGia->pName = Abc_UtilStrsav( "MiniLut" ); + // create mapping from MiniLUT objects into ABC objects + vCopies = Vec_IntAlloc( nNodes ); + Vec_IntPush( vCopies, 0 ); + Vec_IntPush( vCopies, 1 ); + // iterate through the objects + Gia_ManHashAlloc( pGia ); + for ( i = 2; i < nNodes; i++ ) + { + if ( Mini_LutNodeIsPi( p, i ) ) + iGiaLit = Gia_ManAppendCi(pGia); + else if ( Mini_LutNodeIsPo( p, i ) ) + iGiaLit = Gia_ManAppendCo(pGia, Vec_IntEntry(vCopies, Mini_LutNodeFanin(p, i, 0))); + else if ( Mini_LutNodeIsNode( p, i ) ) + { + unsigned * puTruth = Mini_LutNodeTruth( p, i ); + word Truth = ((word)*puTruth << 32) | (word)*puTruth; + word * pTruth = LutSize < 6 ? &Truth : (word *)puTruth; + Vec_IntClear( vLits ); + Mini_LutForEachFanin( p, i, Fan, k ) + Vec_IntPush( vLits, Vec_IntEntry(vCopies, Fan) ); + iGiaLit = Dsm_ManTruthToGia( pGia, pTruth, vLits, vCover ); + } + else assert( 0 ); + Vec_IntPush( vCopies, iGiaLit ); + } + Vec_IntFree( vCover ); + Vec_IntFree( vLits ); + Gia_ManHashStop( pGia ); + assert( Vec_IntSize(vCopies) == nNodes ); + if ( pvCopies ) + *pvCopies = vCopies; + else + Vec_IntFree( vCopies ); + Gia_ManSetRegNum( pGia, Mini_LutRegNum(p) ); + pGia = Gia_ManCleanup( pTemp = pGia ); + if ( pvCopies ) + Gia_ManDupRemapLiterals( *pvCopies, pTemp ); + Gia_ManStop( pTemp ); + return pGia; +} + + +/**Function************************************************************* + + Synopsis [Converts MiniLUT into GIA.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManFromMiniLut2( Mini_Lut_t * p, Vec_Int_t ** pvCopies ) +{ + Gia_Man_t * pGia; + Vec_Int_t * vCopies; + Vec_Int_t * vCover = Vec_IntAlloc( 1000 ); + Vec_Int_t * vLits = Vec_IntAlloc( 100 ); + int i, k, Fan, iGiaLit, nNodes; + // get the number of nodes + nNodes = Mini_LutNodeNum(p); + // create ABC network + pGia = Gia_ManStart( 3 * nNodes ); + pGia->pName = Abc_UtilStrsav( "MiniLut" ); + // create mapping from MiniLUT objects into ABC objects + vCopies = Vec_IntAlloc( nNodes ); + Vec_IntPush( vCopies, 0 ); + Vec_IntPush( vCopies, 1 ); + // iterate through the objects + pGia->fGiaSimple = 1; + for ( i = 2; i < nNodes; i++ ) + { + if ( Mini_LutNodeIsPi( p, i ) ) + iGiaLit = Gia_ManAppendCi(pGia); + else if ( Mini_LutNodeIsPo( p, i ) ) + iGiaLit = Gia_ManAppendCo(pGia, Vec_IntEntry(vCopies, Mini_LutNodeFanin(p, i, 0))); + else if ( Mini_LutNodeIsNode( p, i ) ) + { + unsigned * puTruth = Mini_LutNodeTruth( p, i ); + Vec_IntClear( vLits ); + Mini_LutForEachFanin( p, i, Fan, k ) + Vec_IntPush( vLits, Vec_IntEntry(vCopies, Fan) ); + iGiaLit = Kit_TruthToGia( pGia, puTruth, Vec_IntSize(vLits), vCover, vLits, 0 ); + } + else assert( 0 ); + Vec_IntPush( vCopies, iGiaLit ); + } + Vec_IntFree( vCover ); + Vec_IntFree( vLits ); + assert( Vec_IntSize(vCopies) == nNodes ); + if ( pvCopies ) + *pvCopies = vCopies; + else + Vec_IntFree( vCopies ); + Gia_ManSetRegNum( pGia, Mini_LutRegNum(p) ); + return pGia; +} + + +/**Function************************************************************* + + Synopsis [Marks LUTs that should be complemented.] + + Description [These are LUTs whose all PO fanouts require them + in negative polarity. Other fanouts may require them in + positive polarity.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Bit_t * Gia_ManFindComplLuts( Gia_Man_t * pGia ) +{ + Gia_Obj_t * pObj; int i; + // mark objects pointed by COs in negative polarity + Vec_Bit_t * vMarks = Vec_BitStart( Gia_ManObjNum(pGia) ); + Gia_ManForEachCo( pGia, pObj, i ) + if ( Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) && Gia_ObjFaninC0(pObj) ) + Vec_BitWriteEntry( vMarks, Gia_ObjFaninId0p(pGia, pObj), 1 ); + // unmark objects pointed by COs in positive polarity + Gia_ManForEachCo( pGia, pObj, i ) + if ( Gia_ObjIsAnd(Gia_ObjFanin0(pObj)) && !Gia_ObjFaninC0(pObj) ) + Vec_BitWriteEntry( vMarks, Gia_ObjFaninId0p(pGia, pObj), 0 ); + return vMarks; +} + +/**Function************************************************************* + + Synopsis [Converts GIA into MiniLUT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mini_Lut_t * Gia_ManToMiniLut( Gia_Man_t * pGia ) +{ + Mini_Lut_t * p; + Vec_Bit_t * vMarks; + Gia_Obj_t * pObj, * pFanin; + Vec_Int_t * vLeaves = Vec_IntAlloc( 16 ); + Vec_Int_t * vInvMap = Vec_IntStart( Gia_ManObjNum(pGia) ); + int i, k, iFanin, LutSize, nWords, Count = 0, pVars[16]; + word * pTruth; + assert( Gia_ManHasMapping(pGia) ); + LutSize = Gia_ManLutSizeMax( pGia ); + LutSize = Abc_MaxInt( LutSize, 2 ); + nWords = Abc_Truth6WordNum( LutSize ); + assert( LutSize >= 2 ); + // create the manager + p = Mini_LutStart( LutSize ); + // create primary inputs + Gia_ManFillValue( pGia ); + Gia_ManConst0(pGia)->Value = 0; + Gia_ManForEachCi( pGia, pObj, i ) + pObj->Value = Mini_LutCreatePi(p); + // create internal nodes + vMarks = Gia_ManFindComplLuts( pGia ); + Gia_ObjComputeTruthTableStart( pGia, LutSize ); + Gia_ManForEachLut( pGia, i ) + { + Vec_IntClear( vLeaves ); + Gia_LutForEachFanin( pGia, i, iFanin, k ) + Vec_IntPush( vLeaves, iFanin ); + if ( Vec_IntSize(vLeaves) > 6 ) + { + int Extra = Vec_IntSize(vLeaves) - 7; + for ( k = Extra; k >= 0; k-- ) + Vec_IntPush( vLeaves, Vec_IntEntry(vLeaves, k) ); + for ( k = Extra; k >= 0; k-- ) + Vec_IntDrop( vLeaves, k ); + assert( Vec_IntSize(vLeaves) == Gia_ObjLutSize(pGia, i) ); + } + Gia_ManForEachObjVec( vLeaves, pGia, pFanin, k ) + pVars[k] = pFanin->Value; + pObj = Gia_ManObj( pGia, i ); + pTruth = Gia_ObjComputeTruthTableCut( pGia, pObj, vLeaves ); + if ( Vec_BitEntry(vMarks, i) ) + Abc_TtNot( pTruth, nWords ); + Vec_IntForEachEntry( vLeaves, iFanin, k ) + if ( Vec_BitEntry(vMarks, iFanin) ) + Abc_TtFlip( pTruth, nWords, k ); + pObj->Value = Mini_LutCreateNode( p, Gia_ObjLutSize(pGia, i), pVars, (unsigned *)pTruth ); + } + Vec_IntFree( vLeaves ); + // create inverter truth table + Vec_WrdClear( pGia->vTtMemory ); + for ( i = 0; i < nWords; i++ ) + Vec_WrdPush( pGia->vTtMemory, ABC_CONST(0x5555555555555555) ); + pTruth = Vec_WrdArray( pGia->vTtMemory ); + // create primary outputs + Gia_ManForEachCo( pGia, pObj, i ) + { + if ( Gia_ObjFanin0(pObj) == Gia_ManConst0(pGia) ) + pObj->Value = Mini_LutCreatePo( p, Gia_ObjFaninC0(pObj) ); + else if ( Gia_ObjFaninC0(pObj) == Vec_BitEntry(vMarks, Gia_ObjFaninId0p(pGia, pObj)) ) + pObj->Value = Mini_LutCreatePo( p, Gia_ObjFanin0(pObj)->Value ); + else // add inverter LUT + { + int LutInv, Fanin = Gia_ObjFanin0(pObj)->Value; + if ( (LutInv = Vec_IntEntry(vInvMap, Fanin)) == 0 ) + { + LutInv = Mini_LutCreateNode( p, 1, &Fanin, (unsigned *)pTruth ); + Vec_IntWriteEntry( vInvMap, Fanin, LutInv ); + Count++; + } + pObj->Value = Mini_LutCreatePo( p, LutInv ); + } + } + Vec_IntFree( vInvMap ); + Vec_BitFree( vMarks ); + Gia_ObjComputeTruthTableStop( pGia ); + // set registers + Mini_LutSetRegNum( p, Gia_ManRegNum(pGia) ); + //Mini_LutPrintStats( p ); + //printf( "Added %d inverters.\n", Count ); + return p; +} +char * Gia_ManToMiniLutAttr( Gia_Man_t * pGia, void * pMiniLut ) +{ + Mini_Lut_t * p = (Mini_Lut_t *)pMiniLut; int i; + char * pAttrs = ABC_CALLOC( char, Mini_LutNodeNum(p) ); + Gia_ManForEachLut( pGia, i ) + if ( Gia_ObjLutIsMux(pGia, i) ) + pAttrs[Gia_ManObj(pGia, i)->Value] = 1; + return pAttrs; +} + +/**Function************************************************************* + + Synopsis [Procedures to input/output MiniAIG into/from internal GIA.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameGiaInputMiniLut( Abc_Frame_t * pAbc, void * p ) +{ + Gia_Man_t * pGia; + if ( pAbc == NULL ) + printf( "ABC framework is not initialized by calling Abc_Start()\n" ); + pGia = Gia_ManFromMiniLut( (Mini_Lut_t *)p, NULL ); + Abc_FrameUpdateGia( pAbc, pGia ); +// Gia_ManDelete( pGia ); +} +void Abc_FrameGiaInputMiniLut2( Abc_Frame_t * pAbc, void * p ) +{ + if ( pAbc == NULL ) + printf( "ABC framework is not initialized by calling Abc_Start()\n" ); + Vec_IntFreeP( &pAbc->vCopyMiniLut ); + Gia_ManStopP( &pAbc->pGiaMiniLut ); + pAbc->pGiaMiniLut = Gia_ManFromMiniLut2( (Mini_Lut_t *)p, &pAbc->vCopyMiniLut ); +// Abc_FrameUpdateGia( pAbc, pGia ); +} +void * Abc_FrameGiaOutputMiniLut( Abc_Frame_t * pAbc ) +{ + Mini_Lut_t * pRes = NULL; + Gia_Man_t * pGia; + if ( pAbc == NULL ) + printf( "ABC framework is not initialized by calling Abc_Start()\n" ); + Gia_ManStopP( &pAbc->pGiaMiniLut ); + Vec_IntFreeP( &pAbc->vCopyMiniLut ); + pGia = Abc_FrameReadGia( pAbc ); + if ( pGia == NULL ) + printf( "Current network in ABC framework is not defined.\n" ); + pRes = Gia_ManToMiniLut( pGia ); + pAbc->pGiaMiniLut = Gia_ManFromMiniLut( pRes, &pAbc->vCopyMiniLut ); + return pRes; +} +char * Abc_FrameGiaOutputMiniLutAttr( Abc_Frame_t * pAbc, void * pMiniLut ) +{ + Gia_Man_t * pGia; + if ( pAbc == NULL ) + printf( "ABC framework is not initialized by calling Abc_Start()\n" ); + pGia = Abc_FrameReadGia( pAbc ); + if ( pGia == NULL ) + printf( "Current network in ABC framework is not defined.\n" ); + return Gia_ManToMiniLutAttr( pGia, pMiniLut ); +} +int * Abc_FrameGiaOutputMiniLutObj( Abc_Frame_t * pAbc ) +{ + int * pRes = NULL; + if ( pAbc == NULL ) + printf( "ABC framework is not initialized by calling Abc_Start()\n" ); + if ( pAbc->vMiniLutObjs == NULL ) + printf( "MiniLut objects are not defined.\n" ); + pRes = Vec_IntReleaseArray( pAbc->vMiniLutObjs ); + Vec_IntFreeP( &pAbc->vMiniLutObjs ); + return pRes; +} +void Abc_FrameSetObjDelays( Abc_Frame_t * pAbc, int * pDelays, int nDelays ) +{ + Vec_IntFreeP( &pAbc->vObjDelays ); + pAbc->vObjDelays = Vec_IntAllocArrayCopy( pDelays, nDelays ); +} + + +/**Function************************************************************* + + Synopsis [Procedures to read/write GIA to/from MiniAIG file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManReadMiniLut( char * pFileName ) +{ + Mini_Lut_t * p = Mini_LutLoad( pFileName ); + Gia_Man_t * pGia = Gia_ManFromMiniLut( p, NULL ); + ABC_FREE( pGia->pName ); + pGia->pName = Extra_FileNameGeneric( pFileName ); + Mini_LutStop( p ); + return pGia; +} +void Gia_ManWriteMiniLut( Gia_Man_t * pGia, char * pFileName ) +{ + Mini_Lut_t * p = Gia_ManToMiniLut( pGia ); + Mini_LutDump( p, pFileName ); + Mini_LutStop( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Gia_ManMapMiniLut2MiniAig( Gia_Man_t * p, Gia_Man_t * p1, Gia_Man_t * p2, Vec_Int_t * vMap1, Vec_Int_t * vMap2 ) +{ + int * pRes = ABC_FALLOC( int, Vec_IntSize(vMap2) ); + Vec_Int_t * vMap = Vec_IntStartFull( Gia_ManObjNum(p) ); + int i, Entry, iRepr, fCompl, iLit; + Gia_Obj_t * pObj; + Gia_ManSetPhase( p1 ); + Gia_ManSetPhase( p2 ); + Vec_IntForEachEntry( vMap1, Entry, i ) + { + if ( Entry == -1 ) + continue; + pObj = Gia_ManObj( p1, Abc_Lit2Var(Entry) ); + if ( ~pObj->Value == 0 ) + continue; + fCompl = Abc_LitIsCompl(Entry) ^ pObj->fPhase; + iRepr = Gia_ObjReprSelf(p, Abc_Lit2Var(pObj->Value)); + Vec_IntWriteEntry( vMap, iRepr, Abc_Var2Lit(i, fCompl) ); + } + Vec_IntForEachEntry( vMap2, Entry, i ) + { + if ( Entry == -1 ) + continue; + pObj = Gia_ManObj( p2, Abc_Lit2Var(Entry) ); + if ( ~pObj->Value == 0 ) + continue; + fCompl = Abc_LitIsCompl(Entry) ^ pObj->fPhase; + iRepr = Gia_ObjReprSelf(p, Abc_Lit2Var(pObj->Value)); + if ( (iLit = Vec_IntEntry(vMap, iRepr)) == -1 ) + continue; + pRes[i] = Abc_LitNotCond( iLit, fCompl ); + } + Vec_IntFill( vMap, Gia_ManCoNum(p1), -1 ); + Vec_IntForEachEntry( vMap1, Entry, i ) + { + if ( Entry == -1 ) + continue; + pObj = Gia_ManObj( p1, Abc_Lit2Var(Entry) ); + if ( !Gia_ObjIsCo(pObj) ) + continue; + Vec_IntWriteEntry( vMap, Gia_ObjCioId(pObj), i ); + } + Vec_IntForEachEntry( vMap2, Entry, i ) + { + if ( Entry == -1 ) + continue; + pObj = Gia_ManObj( p2, Abc_Lit2Var(Entry) ); + if ( !Gia_ObjIsCo(pObj) ) + continue; + assert( pRes[i] == -1 ); + pRes[i] = Abc_Var2Lit( Vec_IntEntry(vMap, Gia_ObjCioId(pObj)), 0 ); + assert( pRes[i] != -1 ); + } + Vec_IntFree( vMap ); + return pRes; +} +void Gia_ManNameMapVerify( Gia_Man_t * p, Gia_Man_t * p1, Gia_Man_t * p2, Vec_Int_t * vMap1, Vec_Int_t * vMap2, int * pMap ) +{ + int iLut, iObj1, iObj2, nSize = Vec_IntSize(vMap2); + Gia_Obj_t * pObjAig, * pObjLut; + Gia_ManSetPhase( p1 ); + Gia_ManSetPhase( p2 ); + for ( iLut = 0; iLut < nSize; iLut++ ) + if ( pMap[iLut] >= 0 ) + { + int iObj = Abc_Lit2Var( pMap[iLut] ); + int fCompl = Abc_LitIsCompl( pMap[iLut] ); + int iLitAig = Vec_IntEntry( vMap1, iObj ); + int iLitLut = Vec_IntEntry( vMap2, iLut ); + pObjAig = Gia_ManObj( p1, Abc_Lit2Var(iLitAig) ); + if ( Gia_ObjIsCo(pObjAig) ) + continue; + if ( ~pObjAig->Value == 0 ) + continue; + pObjLut = Gia_ManObj( p2, Abc_Lit2Var(iLitLut) ); + if ( ~pObjLut->Value == 0 ) + continue; + iObj1 = Gia_ObjReprSelf(p, Abc_Lit2Var(pObjAig->Value)); + iObj2 = Gia_ObjReprSelf(p, Abc_Lit2Var(pObjLut->Value)); + if ( iObj1 != iObj2 ) + printf( "Found functional mismatch for LutId %d and AigId %d.\n", iLut, iObj ); + if ( (pObjLut->fPhase ^ Abc_LitIsCompl(iLitLut)) != (pObjAig->fPhase ^ Abc_LitIsCompl(iLitAig) ^ fCompl) ) + printf( "Found phase mismatch for LutId %d and AigId %d.\n", iLut, iObj ); + } +} +int * Abc_FrameReadMiniLutNameMapping( Abc_Frame_t * pAbc ) +{ + int fVerbose = 0; + int nConfs = 1000; + Gia_Man_t * pGia, * pTemp; + int * pRes = NULL; + if ( pAbc->pGiaMiniAig == NULL ) + printf( "GIA derived from MiniAig is not available.\n" ); + if ( pAbc->pGiaMiniLut == NULL ) + printf( "GIA derived from MiniLut is not available.\n" ); + if ( pAbc->pGiaMiniAig == NULL || pAbc->pGiaMiniLut == NULL ) + return NULL; + pGia = Gia_ManDup2( pAbc->pGiaMiniAig, pAbc->pGiaMiniLut ); + //Gia_AigerWrite( pGia, "aig_m_lut.aig", 0, 0, 0 ); + // compute equivalences in this AIG + pTemp = Gia_ManComputeGiaEquivs( pGia, nConfs, fVerbose ); + Gia_ManStop( pTemp ); + //if ( fVerbose ) + // Abc_PrintTime( 1, "Equivalence computation time", Abc_Clock() - clk ); + //if ( fVerbose ) + // Gia_ManPrintStats( pGia, NULL ); + //Vec_IntPrint( pAbc->vCopyMiniAig ); + //Vec_IntPrint( pAbc->vCopyMiniLut ); + pRes = Gia_ManMapMiniLut2MiniAig( pGia, pAbc->pGiaMiniAig, pAbc->pGiaMiniLut, pAbc->vCopyMiniAig, pAbc->vCopyMiniLut ); + //Gia_ManNameMapVerify( pGia, pAbc->pGiaMiniAig, pAbc->pGiaMiniLut, pAbc->vCopyMiniAig, pAbc->vCopyMiniLut, pRes ); + Gia_ManStop( pGia ); + return pRes; +} +int * Abc_FrameReadMiniLutSwitching( Abc_Frame_t * pAbc ) +{ + Vec_Int_t * vSwitching; + int i, iObj, * pRes = NULL; + if ( pAbc->pGiaMiniLut == NULL ) + { + printf( "GIA derived from MiniLut is not available.\n" ); + return NULL; + } + vSwitching = Gia_ManComputeSwitchProbs( pAbc->pGiaMiniLut, 48, 16, 0 ); + pRes = ABC_CALLOC( int, Vec_IntSize(pAbc->vCopyMiniLut) ); + Vec_IntForEachEntry( pAbc->vCopyMiniLut, iObj, i ) + if ( iObj >= 0 ) + pRes[i] = (int)(10000*Vec_FltEntry( (Vec_Flt_t *)vSwitching, Abc_Lit2Var(iObj) )); + Vec_IntFree( vSwitching ); + return pRes; +} +int * Abc_FrameReadMiniLutSwitching2( Abc_Frame_t * pAbc, int fRandPiFactor ) +{ + Vec_Int_t * vSwitching; + int i, iObj, * pRes = NULL; + if ( pAbc->pGiaMiniLut == NULL ) + { + printf( "GIA derived from MiniLut is not available.\n" ); + return NULL; + } + vSwitching = Gia_ManComputeSwitchProbs2( pAbc->pGiaMiniLut, 48, 16, 0, fRandPiFactor ); + pRes = ABC_CALLOC( int, Vec_IntSize(pAbc->vCopyMiniLut) ); + Vec_IntForEachEntry( pAbc->vCopyMiniLut, iObj, i ) + if ( iObj >= 0 ) + pRes[i] = (int)(10000*Vec_FltEntry( (Vec_Flt_t *)vSwitching, Abc_Lit2Var(iObj) )); + Vec_IntFree( vSwitching ); + return pRes; +} +int * Abc_FrameReadMiniLutSwitchingPo( Abc_Frame_t * pAbc ) +{ + Vec_Int_t * vSwitching; + int i, iObj, * pRes = NULL; + if ( pAbc->pGiaMiniAig == NULL ) + { + printf( "GIA derived from MiniAIG is not available.\n" ); + return NULL; + } + vSwitching = Gia_ManComputeSwitchProbs( pAbc->pGiaMiniAig, 48, 16, 0 ); + pRes = ABC_CALLOC( int, Gia_ManCoNum(pAbc->pGiaMiniAig) ); + Gia_ManForEachCoDriverId( pAbc->pGiaMiniAig, iObj, i ) + pRes[i] = (int)(10000*Vec_FltEntry( (Vec_Flt_t *)vSwitching, iObj )); + Vec_IntFree( vSwitching ); + return pRes; +} + +/**Function************************************************************* + + Synopsis [Returns equivalences of MiniAig nodes.] + + Description [The resulting array contains as many entries as there are objects + in the initial MiniAIG. If the i-th entry of the array is equal to -1, it means + that the i-th MiniAIG object is not equivalent to any other object. Otherwise, + the i-th entry contains the literal of the representative of the equivalence + class of objects, to which the i-th object belongs. The representative is defined + as the first object belonging to the equivalence class in the current topological + order. It can be the constant 0 node, a flop output or an internal node. It is + the user's responsibility to free the resulting array when it is not needed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManMapEquivAfterScorr( Gia_Man_t * p, Vec_Int_t * vMap ) +{ + Vec_Int_t * vRes = Vec_IntStartFull( Vec_IntSize(vMap) ); + Vec_Int_t * vGia2Mini = Vec_IntStartFull( Gia_ManObjNum(p) ); + Gia_Obj_t * pObj, * pRepr; + int i, iObjLit, iReprLit, fCompl, iReprGia, iReprMini; + Vec_IntForEachEntry( vMap, iObjLit, i ) + { + if ( iObjLit == -1 ) + continue; +// if ( Gia_ObjHasRepr(p, Abc_Lit2Var(iObjLit)) && !Gia_ObjProved(p, Abc_Lit2Var(iObjLit)) ) +// continue; + iReprGia = Gia_ObjReprSelf( p, Abc_Lit2Var(iObjLit) ); + iReprMini = Vec_IntEntry( vGia2Mini, iReprGia ); + if ( iReprMini == -1 ) + { + Vec_IntWriteEntry( vGia2Mini, iReprGia, i ); + continue; + } + if ( iReprMini == i ) + continue; + assert( iReprMini < i ); + Vec_IntWriteEntry( vRes, i, iReprMini ); + } + Vec_IntFree( vGia2Mini ); + Gia_ManSetPhase( p ); + Vec_IntForEachEntry( vRes, iReprMini, i ) + { + if ( iReprMini == -1 ) + continue; + iObjLit = Vec_IntEntry(vMap, i); + iReprLit = Vec_IntEntry(vMap, iReprMini); + pObj = Gia_ManObj( p, Abc_Lit2Var(iObjLit) ); + pRepr = Gia_ManObj( p, Abc_Lit2Var(iReprLit) ); + fCompl = Abc_LitIsCompl(iObjLit) ^ Abc_LitIsCompl(iReprLit) ^ pObj->fPhase ^ pRepr->fPhase; + Vec_IntWriteEntry( vRes, i, Abc_Var2Lit(iReprMini, fCompl) ); + } + return vRes; +} +int * Abc_FrameReadMiniAigEquivClasses( Abc_Frame_t * pAbc ) +{ + Vec_Int_t * vRes; + int * pRes; + if ( pAbc->pGiaMiniAig == NULL ) + printf( "GIA derived from MiniAig is not available.\n" ); + if ( pAbc->vCopyMiniAig == NULL ) + printf( "Mapping of MiniAig nodes is not available.\n" ); + if ( pAbc->pGia2 == NULL ) + printf( "Internal GIA with equivalence classes is not available.\n" ); + if ( pAbc->pGia2->pReprs == NULL ) + { + printf( "Equivalence classes of internal GIA are not available.\n" ); + return NULL; + } + else if ( 0 ) + { + int i; + for ( i = 1; i < Gia_ManObjNum(pAbc->pGia2); i++ ) + if ( Gia_ObjHasRepr(pAbc->pGia2, i) ) + printf( "Obj %3d : Repr %3d Proved %d Failed %d\n", i, Gia_ObjRepr(pAbc->pGia2, i), Gia_ObjProved(pAbc->pGia2, i), Gia_ObjFailed(pAbc->pGia2, i) ); + } + if ( Gia_ManObjNum(pAbc->pGia2) != Gia_ManObjNum(pAbc->pGiaMiniAig) ) + printf( "Internal GIA with equivalence classes is not directly derived from MiniAig.\n" ); + // derive the set of equivalent node pairs + vRes = Gia_ManMapEquivAfterScorr( pAbc->pGia2, pAbc->vCopyMiniAig ); + pRes = Vec_IntReleaseArray( vRes ); + Vec_IntFree( vRes ); + return pRes; +} + +/**Function************************************************************* + + Synopsis [Verifies equivalences of MiniAig nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_MiniAigReduce( Mini_Aig_t * p, int * pEquivs ) +{ + Gia_Man_t * pGia, * pTemp; + Vec_Int_t * vCopies; + int i, iGiaLit = 0, nNodes; + // get the number of nodes + nNodes = Mini_AigNodeNum(p); + // create ABC network + pGia = Gia_ManStart( nNodes ); + pGia->pName = Abc_UtilStrsav( "MiniAig" ); + // create mapping from MiniAIG objects into ABC objects + vCopies = Vec_IntAlloc( nNodes ); + Vec_IntPush( vCopies, 0 ); + // iterate through the objects + Gia_ManHashAlloc( pGia ); + for ( i = 1; i < nNodes; i++ ) + { + if ( Mini_AigNodeIsPi( p, i ) ) + iGiaLit = Gia_ManAppendCi(pGia); + else if ( Mini_AigNodeIsPo( p, i ) ) + iGiaLit = Gia_ManAppendCo(pGia, Gia_ObjFromMiniFanin0Copy(pGia, vCopies, p, i)); + else if ( Mini_AigNodeIsAnd( p, i ) ) + iGiaLit = Gia_ManHashAnd(pGia, Gia_ObjFromMiniFanin0Copy(pGia, vCopies, p, i), Gia_ObjFromMiniFanin1Copy(pGia, vCopies, p, i)); + else assert( 0 ); + if ( pEquivs[i] != -1 ) + iGiaLit = Abc_LitNotCond( Vec_IntEntry(vCopies, Abc_Lit2Var(pEquivs[i])), Abc_LitIsCompl(pEquivs[i]) ); + Vec_IntPush( vCopies, iGiaLit ); + } + Gia_ManHashStop( pGia ); + assert( Vec_IntSize(vCopies) == nNodes ); + Vec_IntFree( vCopies ); + Gia_ManSetRegNum( pGia, Mini_AigRegNum(p) ); + pGia = Gia_ManSeqCleanup( pTemp = pGia ); + Gia_ManStop( pTemp ); + return pGia; +} +Gia_Man_t * Gia_MiniAigMiter( Mini_Aig_t * p, int * pEquivs ) +{ + Gia_Man_t * pGia, * pTemp; + Vec_Int_t * vCopies; + int i, iGiaLit = 0, iGiaLit2, nNodes, iPos = 0, nPos = 0, Temp; + // get the number of nodes + nNodes = Mini_AigNodeNum(p); + // create ABC network + pGia = Gia_ManStart( 2 * nNodes ); + pGia->pName = Abc_UtilStrsav( "MiniAig" ); + // create mapping from MiniAIG objects into ABC objects + vCopies = Vec_IntAlloc( nNodes ); + Vec_IntPush( vCopies, 0 ); + // iterate through the objects + Gia_ManHashAlloc( pGia ); + for ( i = 1; i < nNodes; i++ ) + { + if ( Mini_AigNodeIsPi( p, i ) ) + iGiaLit = Gia_ManAppendCi(pGia); + else if ( Mini_AigNodeIsPo( p, i ) ) + { + nPos++; + Vec_IntPush( vCopies, -1 ); + continue; + } + else if ( Mini_AigNodeIsAnd( p, i ) ) + iGiaLit = Gia_ManHashAnd(pGia, Gia_ObjFromMiniFanin0Copy(pGia, vCopies, p, i), Gia_ObjFromMiniFanin1Copy(pGia, vCopies, p, i)); + else assert( 0 ); + Vec_IntPush( vCopies, iGiaLit ); + } + assert( Vec_IntSize(vCopies) == nNodes ); + assert( nPos > Mini_AigRegNum(p) ); + // create miters for each equiv class + for ( i = 1; i < nNodes; i++ ) + { + if ( pEquivs[i] == -1 ) + continue; + iGiaLit = Vec_IntEntry(vCopies, i); + iGiaLit2 = Abc_LitNotCond( Vec_IntEntry(vCopies, Abc_Lit2Var(pEquivs[i])), Abc_LitIsCompl(pEquivs[i]) ); + Gia_ManAppendCo( pGia, Gia_ManHashXor(pGia, iGiaLit, iGiaLit2) ); + } + // create flop inputs + Temp = Gia_ManCoNum(pGia); + for ( i = 1; i < nNodes; i++ ) + { + if ( !Mini_AigNodeIsPo( p, i ) ) + continue; + if ( iPos++ >= nPos - Mini_AigRegNum(p) ) + Gia_ManAppendCo(pGia, Gia_ObjFromMiniFanin0Copy(pGia, vCopies, p, i)); + } + assert( iPos == nPos ); + assert( Mini_AigRegNum(p) == Gia_ManCoNum(pGia) - Temp ); + Gia_ManSetRegNum( pGia, Mini_AigRegNum(p) ); + Gia_ManHashStop( pGia ); + Vec_IntFree( vCopies ); + pGia = Gia_ManCleanup( pTemp = pGia ); + Gia_ManStop( pTemp ); + return pGia; +} +void Gia_MiniAigVerify( Abc_Frame_t * pAbc, char * pFileName ) +{ + int * pEquivs; + Gia_Man_t * pGia; + char * pFileMiter = "mini_aig_miter.aig"; + char * pFileReduced = "mini_aig_reduced.aig"; + Mini_Aig_t * p = Mini_AigLoad( pFileName ); + Abc_FrameGiaInputMiniAig( pAbc, p ); + Cmd_CommandExecute( pAbc, "&ps; &scorr; &ps" ); + pEquivs = Abc_FrameReadMiniAigEquivClasses( pAbc ); + // dump miter for verification + pGia = Gia_MiniAigMiter( p, pEquivs ); + Gia_AigerWrite( pGia, pFileMiter, 0, 0, 0 ); + printf( "Dumped miter AIG in file \"%s\".\n", pFileMiter ); + Gia_ManStop( pGia ); + // dump reduced AIG + pGia = Gia_MiniAigReduce( p, pEquivs ); + Gia_AigerWrite( pGia, pFileReduced, 0, 0, 0 ); + printf( "Dumped reduced AIG in file \"%s\".\n", pFileReduced ); + Gia_ManStop( pGia ); + // cleanup + ABC_FREE( pEquivs ); + Mini_AigStop( p ); +} + +/**Function************************************************************* + + Synopsis [Collects supergate for the outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_MiniAigSuperGates_rec( Mini_Aig_t * p, int iObj, Vec_Int_t * vRes, Vec_Int_t * vMap ) +{ + int iFan0, iFan1; + if ( Mini_AigNodeIsPi(p, iObj) ) + { + assert( Vec_IntEntry(vMap, iObj) >= 0 ); + Vec_IntPush( vRes, Vec_IntEntry(vMap, iObj) ); + return; + } + iFan0 = Mini_AigNodeFanin0( p, iObj ); + iFan1 = Mini_AigNodeFanin1( p, iObj ); + assert( !Abc_LitIsCompl(iFan0) ); + assert( !Abc_LitIsCompl(iFan1) ); + Gia_MiniAigSuperGates_rec( p, Abc_Lit2Var(iFan0), vRes, vMap ); + Gia_MiniAigSuperGates_rec( p, Abc_Lit2Var(iFan1), vRes, vMap ); +} +Vec_Wec_t * Gia_MiniAigSuperGates( Mini_Aig_t * p ) +{ + Vec_Wec_t * vRes = Vec_WecStart( Mini_AigPoNum(p) ); + Vec_Int_t * vMap = Vec_IntStartFull( Mini_AigNodeNum(p) ); + int i, Index = 0; + Mini_AigForEachPi( p, i ) + Vec_IntWriteEntry( vMap, i, Index++ ); + assert( Index == Mini_AigPiNum(p) ); + Index = 0; + Mini_AigForEachPo( p, i ) + { + int iFan0 = Mini_AigNodeFanin0( p, i ); + assert( !Abc_LitIsCompl(iFan0) ); + Gia_MiniAigSuperGates_rec( p, Abc_Lit2Var(iFan0), Vec_WecEntry(vRes, Index++), vMap ); + } + assert( Index == Mini_AigPoNum(p) ); + Vec_IntFree( vMap ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [Transform.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_MiniAigSuperPrintDouble( Vec_Int_t * p, int nPis ) +{ + int i, Entry; + printf( "\n" ); + Vec_IntForEachEntry( p, Entry, i ) + printf( "%d(%d) ", Entry%nPis, Entry/nPis ); + printf( " Total = %d\n", Vec_IntSize(p) ); +} +int Gia_MiniAigSuperMerge( Vec_Int_t * p, int nPis ) +{ + int i, k = 0, This, Prev = -1, fChange = 0; + Vec_IntForEachEntry( p, This, i ) + { + if ( Prev == This ) + { + Vec_IntWriteEntry( p, k++, (This/nPis+1)*nPis + This%nPis ); + Prev = -1; + fChange = 1; + } + else + { + if ( Prev != -1 ) + Vec_IntWriteEntry( p, k++, Prev ); + Prev = This; + } + } + if ( Prev != -1 ) + Vec_IntWriteEntry( p, k++, Prev ); + Vec_IntShrink( p, k ); + return fChange; +} +int Gia_MiniAigSuperPreprocess( Mini_Aig_t * p, Vec_Wec_t * vSuper, int nPis, int fVerbose ) +{ + Vec_Int_t * vRes; + int i, nIters, Multi = 1; + Vec_WecForEachLevel( vSuper, vRes, i ) + { + Vec_IntSort( vRes, 0 ); + if ( fVerbose ) + printf( "\nOutput %d\n", i ); + if ( fVerbose ) + Gia_MiniAigSuperPrintDouble( vRes, nPis ); + for ( nIters = 1; Gia_MiniAigSuperMerge(vRes, nPis); nIters++ ) + { + if ( fVerbose ) + Gia_MiniAigSuperPrintDouble( vRes, nPis ); + } + Multi = Abc_MaxInt( Multi, nIters ); + } + if ( fVerbose ) + printf( "Multi = %d.\n", Multi ); + return Multi; +} + +/**Function************************************************************* + + Synopsis [Derive AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_MiniAigSuperDeriveGia( Vec_Wec_t * p, int nPis, int Multi ) +{ + Gia_Man_t * pNew; + Vec_Int_t * vTemp, * vLits = Vec_IntAlloc( 100 ); + Vec_Int_t * vDrivers = Vec_IntAlloc(100); + int i, k, iObj, iLit, nInputs = nPis*Multi; + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( "tree" ); + for ( i = 0; i < nInputs; i++ ) + Gia_ManAppendCi( pNew ); + Gia_ManHashAlloc( pNew ); + Vec_WecForEachLevel( p, vTemp, i ) + { + Vec_IntClear( vLits ); + Vec_IntForEachEntry( vTemp, iObj, k ) + { + assert( iObj < nInputs ); + Vec_IntPush( vLits, 2+2*((iObj%nPis)*Multi+iObj/nPis) ); + } + Vec_IntPush( vDrivers, Gia_ManHashAndMulti2(pNew, vLits) ); + } + Gia_ManHashStop( pNew ); + Vec_IntFree( vLits ); + Vec_IntForEachEntry( vDrivers, iLit, i ) + Gia_ManAppendCo( pNew, iLit ); + Vec_IntFree( vDrivers ); + return pNew; +} +Gia_Man_t * Gia_MiniAigSuperDerive( char * pFileName, int fVerbose ) +{ + Mini_Aig_t * p = Mini_AigLoad( pFileName ); + Vec_Wec_t * vSuper = Gia_MiniAigSuperGates( p ); + int Multi = Gia_MiniAigSuperPreprocess( p, vSuper, Mini_AigPiNum(p), fVerbose ); + Gia_Man_t * pNew = Gia_MiniAigSuperDeriveGia( vSuper, Mini_AigPiNum(p), Multi ); + Vec_WecFree( vSuper ); + Mini_AigStop( p ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Process file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_MiniAigProcessFile() +{ + Vec_Int_t * vTriples = Vec_IntAlloc( 100 ); + char * pFileName = "test.txt"; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + printf( "Cannot open the file.\n" ); + else + { + int nLines = 0, nLinesAll = 0; + char * pToken; + char Buffer[1000]; + while ( fgets( Buffer, 1000, pFile ) != NULL ) + { + nLinesAll++; + if ( Buffer[0] != '#' ) + continue; + //printf( "%s", Buffer ); + nLines++; + pToken = strtok( Buffer+3, " \r\n\r+=" ); + while ( pToken ) + { + Vec_IntPush( vTriples, atoi(pToken) ); + pToken = strtok( NULL, " \r\n\r+=" ); + } + } + fclose( pFile ); + printf( "Collected %d (out of %d) lines.\n", nLines, nLinesAll ); + printf( "Entries = %d\n", Vec_IntSize(vTriples) ); + } + return vTriples; +} +void Gia_MiniAigGenerate_rec( Mini_Aig_t * p, Vec_Int_t * vTriples, int iObj, Vec_Int_t * vDefs, Vec_Int_t * vMap ) +{ + int Index, Entry0, Entry1, Entry2, Value; + if ( Vec_IntEntry(vMap, iObj) >= 0 ) + return; + Index = Vec_IntEntry( vDefs, iObj ); + Entry0 = Vec_IntEntry( vTriples, 3*Index+0 ); + Entry1 = Vec_IntEntry( vTriples, 3*Index+1 ); + Entry2 = Vec_IntEntry( vTriples, 3*Index+2 ); + Gia_MiniAigGenerate_rec( p, vTriples, Entry1, vDefs, vMap ); + Gia_MiniAigGenerate_rec( p, vTriples, Entry2, vDefs, vMap ); + assert( Vec_IntEntry(vMap, Entry1) >= 0 ); + assert( Vec_IntEntry(vMap, Entry2) >= 0 ); + Value = Mini_AigAnd( p, Vec_IntEntry(vMap, Entry1), Vec_IntEntry(vMap, Entry2) ); + Vec_IntWriteEntry( vMap, Entry0, Value ); +} +void Gia_MiniAigGenerateFromFile() +{ + Mini_Aig_t * p = Mini_AigStart(); + Vec_Int_t * vTriples = Gia_MiniAigProcessFile(); + Vec_Int_t * vDefs = Vec_IntStartFull( Vec_IntSize(vTriples) ); + Vec_Int_t * vMap = Vec_IntStartFull( Vec_IntSize(vTriples) ); + Vec_Int_t * vMapIn = Vec_IntStart( Vec_IntSize(vTriples) ); + Vec_Int_t * vMapOut = Vec_IntStart( Vec_IntSize(vTriples) ); + Vec_Int_t * vPis = Vec_IntAlloc( 100 ); + Vec_Int_t * vPos = Vec_IntAlloc( 100 ); + int i, ObjOut, ObjIn; + assert( Vec_IntSize(vTriples) % 3 == 0 ); + for ( i = 0; i < Vec_IntSize(vTriples)/3; i++ ) + { + int Entry0 = Vec_IntEntry(vTriples, 3*i+0); + int Entry1 = Vec_IntEntry(vTriples, 3*i+1); + int Entry2 = Vec_IntEntry(vTriples, 3*i+2); + Vec_IntWriteEntry( vDefs, Entry0, i ); + Vec_IntAddToEntry( vMapOut, Entry0, 1 ); + Vec_IntAddToEntry( vMapIn, Entry1, 1 ); + Vec_IntAddToEntry( vMapIn, Entry2, 1 ); + } + Vec_IntForEachEntryTwo( vMapOut, vMapIn, ObjOut, ObjIn, i ) + if ( !ObjOut && ObjIn ) + Vec_IntPush( vPis, i ); + else if ( ObjOut && !ObjIn ) + Vec_IntPush( vPos, i ); + Vec_IntForEachEntry( vPis, ObjIn, i ) + Vec_IntWriteEntry( vMap, ObjIn, Mini_AigCreatePi(p) ); + Vec_IntForEachEntry( vPos, ObjOut, i ) + Gia_MiniAigGenerate_rec( p, vTriples, ObjOut, vDefs, vMap ); + Vec_IntForEachEntry( vPos, ObjOut, i ) + { + assert( Vec_IntEntry(vMap, ObjOut) >= 0 ); + Mini_AigCreatePo( p, Vec_IntEntry(vMap, ObjOut) ); + } + Vec_IntFree( vTriples ); + Vec_IntFree( vDefs ); + Vec_IntFree( vMap ); + Vec_IntFree( vMapIn ); + Vec_IntFree( vMapOut ); + Vec_IntFree( vPis ); + Vec_IntFree( vPos ); + Mini_AigDump( p, "test.miniaig" ); + Mini_AigStop( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Str_t * Gia_ManRetimableF( Gia_Man_t * p, int * pRst, int * pSet, int * pEna ) +{ + Vec_Str_t * vStops = Vec_StrStart( Gia_ManObjNum(p) ); + Vec_Int_t * vTemps = Vec_IntStartFull( 3*Gia_ManObjNum(p) ); + Gia_Obj_t * pObj, * pObjRi, * pObjRo; int i; + char * pStops = Vec_StrArray(vStops); + assert( Gia_ManRegNum(p) > 0 ); + Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) { + Vec_IntWriteEntry( vTemps, 3*Gia_ObjId(p, pObjRo) + 0, pRst[i] ); + Vec_IntWriteEntry( vTemps, 3*Gia_ObjId(p, pObjRo) + 1, pSet[i] ); + Vec_IntWriteEntry( vTemps, 3*Gia_ObjId(p, pObjRo) + 2, pEna[i] ); + } + Gia_ManForEachAnd( p, pObj, i ) { + int * pFan0 = Vec_IntEntryP( vTemps, 3*Gia_ObjFaninId0(pObj, i) ); + int * pFan1 = Vec_IntEntryP( vTemps, 3*Gia_ObjFaninId1(pObj, i) ); + int * pNode = Vec_IntEntryP( vTemps, 3*i ); + pStops[i] = (char)1; + if ( pFan0[0] != -1 && pFan0[0] == pFan1[0] && pFan0[1] == pFan1[1] && pFan0[2] == pFan1[2] ) + pStops[i] = (char)0, pNode[0] = pFan0[0], pNode[1] = pFan0[1], pNode[2] = pFan0[2]; + } + Vec_IntFree( vTemps ); + return vStops; +} +Vec_Str_t * Gia_ManRetimableB( Gia_Man_t * p, int * pRst, int * pSet, int * pEna ) +{ + Vec_Str_t * vStops = Vec_StrStart( Gia_ManObjNum(p) ); + Vec_Int_t * vTemps = Vec_IntStartFull( 3*Gia_ManObjNum(p) ); + Gia_Obj_t * pObj, * pObjRi, * pObjRo; int i, n, iFanout; + char * pStops = Vec_StrArray(vStops); + assert( Gia_ManRegNum(p) > 0 ); + Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) { + Vec_IntWriteEntry( vTemps, 3*Gia_ObjId(p, pObjRi) + 0, pRst[i] ); + Vec_IntWriteEntry( vTemps, 3*Gia_ObjId(p, pObjRi) + 1, pSet[i] ); + Vec_IntWriteEntry( vTemps, 3*Gia_ObjId(p, pObjRi) + 2, pEna[i] ); + } + Gia_ManStaticFanoutStart( p ); + Gia_ManForEachAndReverse( p, pObj, i ) { + int * pFan0 = Vec_IntEntryP( vTemps, 3*Gia_ObjFanoutId(p, i, 0) ); + int * pNode = Vec_IntEntryP( vTemps, 3*i ); + pStops[i] = (char)1; + if ( pFan0[0] == -1 ) + continue; + Gia_ObjForEachFanoutStaticId( p, i, iFanout, n ) { + int * pFan1 = Vec_IntEntryP( vTemps, 3*iFanout ); + if ( pFan1[0] == -1 || pFan0[0] != pFan1[0] || pFan0[1] != pFan1[1] || pFan0[2] != pFan1[2] ) + break; + } + if ( n < Gia_ObjFanoutNum(p, pObj) ) + continue; + pStops[i] = (char)0, pNode[0] = pFan0[0], pNode[1] = pFan0[1], pNode[2] = pFan0[2]; + } + Gia_ManStaticFanoutStop( p ); + Vec_IntFree( vTemps ); + Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) { + if ( Gia_ObjIsAnd(Gia_ManObj(p, Abc_Lit2Var(pRst[i]))) ) pStops[Abc_Lit2Var(pRst[i])] = 1; + if ( Gia_ObjIsAnd(Gia_ManObj(p, Abc_Lit2Var(pSet[i]))) ) pStops[Abc_Lit2Var(pSet[i])] = 1; + if ( Gia_ObjIsAnd(Gia_ManObj(p, Abc_Lit2Var(pEna[i]))) ) pStops[Abc_Lit2Var(pEna[i])] = 1; + } + return vStops; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameRemapLits( int * pLits, int nLits, Vec_Int_t * vMap ) +{ + for ( int i = 0; i < nLits; i++ ) + pLits[i] = Abc_Lit2LitL( Vec_IntArray(vMap), pLits[i] ); +} +void Abc_FrameSetRetimingData( Abc_Frame_t * pAbc, int * pRst, int * pSet, int * pEna, int nRegs ) +{ + Gia_Man_t * pGia; + int * pRstNew = ABC_CALLOC( int, nRegs ); + int * pSetNew = ABC_CALLOC( int, nRegs ); + int * pEnaNew = ABC_CALLOC( int, nRegs ); + if ( pAbc == NULL ) + printf( "ABC framework is not initialized by calling Abc_Start()\n" ); + pGia = Abc_FrameReadGia( pAbc ); + if ( pGia == NULL ) + printf( "Current network in ABC framework is not defined.\n" ); + else { + assert( nRegs == Gia_ManRegNum(pGia) ); + memmove( pRstNew, pRst, sizeof(int)*nRegs ); + memmove( pSetNew, pSet, sizeof(int)*nRegs ); + memmove( pEnaNew, pEna, sizeof(int)*nRegs ); + } + if ( pAbc->vCopyMiniAig == NULL ) + printf( "Mapping of MiniAig nodes is not available.\n" ); + else { + Abc_FrameRemapLits( pRstNew, nRegs, pAbc->vCopyMiniAig ); + Abc_FrameRemapLits( pSetNew, nRegs, pAbc->vCopyMiniAig ); + Abc_FrameRemapLits( pEnaNew, nRegs, pAbc->vCopyMiniAig ); + } + assert( pGia->vStopsF == NULL ); + assert( pGia->vStopsB == NULL ); + pGia->vStopsF = Gia_ManRetimableF( pGia, pRstNew, pSetNew, pEnaNew ); + pGia->vStopsB = Gia_ManRetimableB( pGia, pRstNew, pSetNew, pEnaNew ); + ABC_FREE( pRstNew ); + ABC_FREE( pSetNew ); + ABC_FREE( pEnaNew ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaMulFind.c b/yosys/abc/src/aig/gia/giaMulFind.c new file mode 100644 index 00000000000..b7bc0b0b6b0 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaMulFind.c @@ -0,0 +1,881 @@ +/**CFile**************************************************************** + + FileName [giaMulFind.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Multiplier detection.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaMulFind.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManMulFindXors2_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vXor ) +{ + if ( !Gia_ObjIsAnd(pObj) ) + return; + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( !pObj->fMark0 ) + { + if ( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) + && Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) >= 4 + && Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) >= 4 ) + Vec_IntPushTwo( vXor, Gia_ObjFaninId0p(p, pObj), Gia_ObjFaninId1p(p, pObj) ); + return; + } + Gia_Obj_t * pFan0, * pFan1; + int RetValue = Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1); + assert( RetValue ); + Gia_ManMulFindXors2_rec( p, Gia_Regular(pFan0), vXor ); + Gia_ManMulFindXors2_rec( p, Gia_Regular(pFan1), vXor ); +} +Vec_Wec_t * Gia_ManMulFindXors2( Gia_Man_t * p ) +{ + Vec_Wec_t * vXors = Vec_WecAlloc( 100 ); + Vec_Int_t * vTemp = Vec_IntAlloc( 100 ); + Gia_Obj_t * pObj, * pFan0, * pFan1; int i; + Gia_ManCreateRefs( p ); + Gia_ManCleanMark01( p ); + Gia_ManForEachAnd( p, pObj, i ) { + if ( !Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) ) + continue; + Gia_Regular(pFan0)->fMark1 = 1; + Gia_Regular(pFan1)->fMark1 = 1; + pObj->fMark0 = 1; + } + Gia_ManForEachAnd( p, pObj, i ) { + if ( pObj->fMark0 && !pObj->fMark1 ) { + Gia_ManIncrementTravId( p ); + Vec_IntClear( vTemp ); + Gia_ManMulFindXors2_rec( p, pObj, vTemp ); + if ( Vec_IntSize(vTemp) > 0 ) + Vec_IntAppend( Vec_WecPushLevel(vXors), vTemp ); + } + } + Vec_IntFree( vTemp ); + return vXors; +} +int Gia_ManMulFindMaxSize( Vec_Wec_t * vXors, Vec_Int_t * vUsed ) +{ + Vec_Int_t * vLevel; int i, iBest = -1, nBestSize = 0; + Vec_WecForEachLevel( vXors, vLevel, i ) + if ( !Vec_IntEntry(vUsed, i) && nBestSize < Vec_IntSize(vLevel) ) + nBestSize = Vec_IntSize(vLevel), iBest = i; + return iBest; +} +int Gia_ManMulFindGetOverlap( Vec_Int_t * p1, Vec_Int_t * p2 ) +{ + int i, k, ObjI, ObjK, Counter = 0; + Vec_IntForEachEntry( p1, ObjI, i ) + Vec_IntForEachEntry( p2, ObjK, k ) + if ( ObjI == ObjK ) + Counter++; + return Counter; +} +int Gia_ManMulFindGetOverlap2( Vec_Int_t * p1, Vec_Int_t * p2 ) +{ + int i, k, ObjI, ObjK, Counter = 0; + Vec_IntForEachEntryStart( p1, ObjI, i, 1 ) + Vec_IntForEachEntry( p2, ObjK, k ) + if ( ObjI == ObjK ) + Counter++; + return Counter; +} +int Gia_ManMulFindMaxOverlap( Vec_Wec_t * vXors, Vec_Int_t * vUsed, Vec_Int_t * vFound ) +{ + Vec_Int_t * vLevel; int i, iBest = -1, nThisSize, nBestSize = 0; + Vec_WecForEachLevel( vXors, vLevel, i ) + if ( !Vec_IntEntry(vUsed, i) && nBestSize < (nThisSize = Gia_ManMulFindGetOverlap(vFound, vLevel)) ) + nBestSize = nThisSize, iBest = i; + return iBest; +} +Vec_Wec_t * Gia_ManMulFindSets( Gia_Man_t * p, Vec_Wec_t * vXors ) +{ + Vec_Wec_t * vSets = Vec_WecAlloc( 100 ); + Vec_Int_t * vUsed = Vec_IntStart( Vec_WecSize(vXors) ); + Vec_Int_t * vFound = Vec_IntAlloc( 100 ); int Item, k, Obj; + while ( (Item = Gia_ManMulFindMaxSize(vXors, vUsed)) != -1 ) { + Vec_Int_t * vTemp = Vec_WecEntry(vXors, Item); + Vec_Int_t * vNew = Vec_WecPushLevel( vSets ); + Vec_IntPush( vNew, Item ); + Vec_IntWriteEntry( vUsed, Item, 1 ); + Vec_IntClear( vFound ); + Vec_IntAppend( vFound, vTemp ); + while ( (Item = Gia_ManMulFindMaxOverlap(vXors, vUsed, vFound)) != -1 ) { + Vec_IntPush( vNew, Item ); + Vec_IntWriteEntry( vUsed, Item, 1 ); + vTemp = Vec_WecEntry(vXors, Item); + Vec_IntForEachEntry( vTemp, Obj, k ) + Vec_IntPushUnique( vFound, Obj ); + } + } + Vec_IntFree( vUsed ); + Vec_IntFree( vFound ); + return vSets; +} +int Gia_ManMulFindOne( Gia_Man_t * p, Vec_Wec_t * vXors, Vec_Int_t * vSet, Vec_Int_t * vMap, Vec_Int_t * vA, Vec_Int_t * vB, int fVerbose ) +{ + Vec_Int_t * vObjs = Vec_IntAlloc( 100 ); int i, j, Obj, Obj1, Obj2; + Vec_IntForEachEntry( vSet, Obj, i ) + Vec_IntAppend( vObjs, Vec_WecEntry(vXors, Obj) ); + Vec_IntForEachEntry( vObjs, Obj, i ) + Vec_IntAddToEntry( vMap, Obj, 1 ); + Vec_IntForEachEntry( vSet, Obj, i ) { + Vec_Int_t * vTemp = Vec_WecEntry(vXors, Obj); int k = 0; + Vec_IntForEachEntryDouble( vTemp, Obj1, Obj2, j ) + if ( Vec_IntEntry(vMap, Obj1) > 1 || Vec_IntEntry(vMap, Obj2) > 1 ) + Vec_IntWriteEntry(vTemp, k++, Obj1), Vec_IntWriteEntry(vTemp, k++, Obj2); + Vec_IntShrink( vTemp, k ); + } + Vec_IntForEachEntry( vObjs, Obj, i ) + Vec_IntWriteEntry( vMap, Obj, 0 ); + Vec_IntClear( vObjs ); + Vec_IntForEachEntry( vSet, Obj, i ) + Vec_IntAppend( vObjs, Vec_WecEntry(vXors, Obj) ); + if ( Vec_IntSize(vObjs) == 0 ) { + Vec_IntFree(vObjs); + return 0; + } + + Vec_IntClear( vA ); + Vec_IntClear( vB ); + Vec_IntPush( vA, Vec_IntPop(vObjs) ); + Vec_IntPush( vB, Vec_IntPop(vObjs) ); + while ( Vec_IntSize(vObjs) > 0 ) { + int k = 0; + Vec_IntForEachEntryDouble( vObjs, Obj1, Obj2, j ) { + if ( Vec_IntFind(vA, Obj1) >= 0 ) + Vec_IntPushUnique(vB, Obj2); + else if ( Vec_IntFind(vA, Obj2) >= 0 ) + Vec_IntPushUnique(vB, Obj1); + else if ( Vec_IntFind(vB, Obj1) >= 0 ) + Vec_IntPushUnique(vA, Obj2); + else if ( Vec_IntFind(vB, Obj2) >= 0 ) + Vec_IntPushUnique(vA, Obj1); + else { + Vec_IntWriteEntry(vObjs, k++, Obj1); + Vec_IntWriteEntry(vObjs, k++, Obj2); + } + } + Vec_IntShrink( vObjs, k ); + } + Vec_IntSort( vA, 0 ); + Vec_IntSort( vB, 0 ); + Vec_IntClear( vObjs ); + Vec_IntForEachEntry( vSet, Obj, i ) + Vec_IntAppend( vObjs, Vec_WecEntry(vXors, Obj) ); + Vec_IntForEachEntryDouble( vObjs, Obj1, Obj2, j ) + if ( !((Vec_IntFind(vA, Obj1) >= 0 && Vec_IntFind(vB, Obj2) >= 0) || + (Vec_IntFind(vA, Obj2) >= 0 && Vec_IntFind(vB, Obj1) >= 0)) ) { + if ( fVerbose ) + printf( "Internal verification failed.\n" ); + Vec_IntFree( vObjs ); + Vec_IntClear( vA ); + Vec_IntClear( vB ); + return 0; + } + if ( fVerbose ) + printf( "Generated system with %d+%d+%d=%d variables and %d equations.\n", + Vec_IntSize(vA),Vec_IntSize(vB),Vec_IntSize(vSet), + Vec_IntSize(vA)+Vec_IntSize(vB)+Vec_IntSize(vSet), Vec_IntSize(vObjs)/2 ); + Vec_IntFree( vObjs ); + return 1; +} +Vec_Wec_t * Gia_ManMulFindAInputs2( Gia_Man_t * p, int fVerbose ) +{ + Vec_Wec_t * vMuls = Vec_WecAlloc( 10 ); + Vec_Wec_t * vXors = Gia_ManMulFindXors2( p ); + Vec_Wec_t * vSets = Gia_ManMulFindSets( p, vXors ); + Vec_Int_t * vMap = Vec_IntStart( Gia_ManObjNum(p) ); + Vec_Int_t * vA = Vec_IntAlloc( 100 ); + Vec_Int_t * vB = Vec_IntAlloc( 100 ); + Vec_Int_t * vSet; int i; + Vec_WecForEachLevel( vSets, vSet, i ) + { + if ( !Gia_ManMulFindOne(p, vXors, vSet, vMap, vA, vB, fVerbose) ) + continue; + Vec_IntAppend( Vec_WecPushLevel(vMuls), vA ); + Vec_IntAppend( Vec_WecPushLevel(vMuls), vB ); + Vec_WecPushLevel(vMuls); + } + Vec_WecFree( vXors ); + Vec_WecFree( vSets ); + Vec_IntFree( vMap ); + Vec_IntFree( vA ); + Vec_IntFree( vB ); + return vMuls; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManMulFindAddEntry1( Vec_Int_t * vPairs, int Obj ) +{ + int Entry, Sum, k; + Vec_IntForEachEntryDouble( vPairs, Entry, Sum, k ) + if ( Obj == Entry ) { + Vec_IntAddToEntry( vPairs, k+1, 1 ); + break; + } + if ( k == Vec_IntSize(vPairs) ) + Vec_IntPushTwo( vPairs, Obj, 1 ); +} +Vec_Int_t * Gia_ManMulFindCounts( Vec_Wec_t * vCuts4, Vec_Int_t * vSet ) +{ + Vec_Int_t * vCounts = Vec_IntAlloc( 10 ); + int i, k, Obj, Item; + Vec_IntForEachEntry( vSet, Item, i ) { + Vec_Int_t * vCut = Vec_WecEntry(vCuts4, Item); + Vec_IntForEachEntryStart( vCut, Obj, k, 1 ) + Gia_ManMulFindAddEntry1( vCounts, Obj ); + } + return vCounts; +} +int Gia_ManMulFindNextEntry( Vec_Wec_t * vCuts4, Vec_Int_t * vSet, int Entry ) +{ + int i, Item; + Vec_IntForEachEntry( vSet, Item, i ) { + Vec_Int_t * vCut = Vec_WecEntry(vCuts4, Item); + if ( Vec_IntSize(vCut) == 0 ) + continue; + assert( Vec_IntSize(vCut) == 3 ); + int RetValue = -1; + if ( Vec_IntEntry(vCut, 1) == Entry ) + RetValue = Vec_IntEntry(vCut, 2); + if ( Vec_IntEntry(vCut, 2) == Entry ) + RetValue = Vec_IntEntry(vCut, 1); + if ( RetValue == -1 ) + continue; + Vec_IntClear( vCut ); + return RetValue; + } + return -1; +} +void Gia_ManMulFindArg1( Vec_Wec_t * vCuts4, Vec_Int_t * vSet, Vec_Int_t * vArg1 ) +{ + Vec_Int_t * vCounts = Gia_ManMulFindCounts( vCuts4, vSet ); + int Entry = -1, Sum, k; + Vec_IntClear( vArg1 ); + Vec_IntForEachEntryDouble( vCounts, Entry, Sum, k ) + if ( Sum == 1 ) { + Vec_IntPush( vArg1, Entry ); + break; + } + assert( Entry != -1 ); + while ( (Entry = Gia_ManMulFindNextEntry(vCuts4, vSet, Entry)) != -1 ) + Vec_IntPush( vArg1, Entry ); + Vec_IntFree( vCounts ); +} +int Gia_ManMulFindNextEntryCount( Vec_Int_t * vCounts, int Entry0 ) +{ + int Entry, Sum, k; + Vec_IntForEachEntryDouble( vCounts, Entry, Sum, k ) + if ( Entry == Entry0 ) + return Sum; + return -1; +} +int Gia_ManMulFindNextEntry2( Vec_Wec_t * vCuts4, Vec_Int_t * vSet, int Entry, Vec_Int_t * vCounts, int * pEntry0, int * pEntry1 ) +{ + int i, Item; + Vec_IntForEachEntry( vSet, Item, i ) { + Vec_Int_t * vCut = Vec_WecEntry(vCuts4, Item); + if ( Vec_IntSize(vCut) == 0 ) + continue; + assert( Vec_IntSize(vCut) == 4 ); + int Entry0, Entry1, iPlace = Vec_IntFind( vCut, Entry ); + if ( iPlace == -1 ) + continue; + if ( iPlace == 1 ) + Entry0 = Vec_IntEntry(vCut, 2), Entry1 = Vec_IntEntry(vCut, 3); + else if ( iPlace == 2 ) + Entry0 = Vec_IntEntry(vCut, 1), Entry1 = Vec_IntEntry(vCut, 3); + else if ( iPlace == 3 ) + Entry0 = Vec_IntEntry(vCut, 1), Entry1 = Vec_IntEntry(vCut, 2); + else assert( 0 ); + int Count0 = Gia_ManMulFindNextEntryCount(vCounts, Entry0); + int Count1 = Gia_ManMulFindNextEntryCount(vCounts, Entry1); + *pEntry0 = Count0 <= Count1 ? Entry0 : Entry1; + *pEntry1 = Count0 <= Count1 ? Entry1 : Entry0; + // remove entries + Vec_IntForEachEntry( vSet, Item, i ) { + Vec_Int_t * vCut = Vec_WecEntry(vCuts4, Item); + if ( Vec_IntSize(vCut) == 0 ) + continue; + if ( Vec_IntFind( vCut, Entry ) >= 0 ) + Vec_IntClear( vCut ); + } + return 1; + } + return 0; +} +void Gia_ManMulFindArg2( Vec_Wec_t * vCuts5, Vec_Int_t * vSet, Vec_Int_t * vArg2, int Entry0, int Entry1 ) +{ + Vec_Int_t * vCounts = Gia_ManMulFindCounts( vCuts5, vSet ); + int Entry, Sum, k, SumMin = ABC_INFINITY, SumMax = 0; + Vec_IntForEachEntryDouble( vCounts, Entry, Sum, k ) { + SumMin = Abc_MinInt( SumMin, Sum ); + SumMax = Abc_MaxInt( SumMax, Sum ); + } + Vec_IntClear( vArg2 ); + Vec_IntForEachEntryDouble( vCounts, Entry, Sum, k ) + if ( Entry == Entry0 || Entry == Entry1 ) { + Vec_IntPush( vArg2, Entry == Entry0 ? Entry1 : Entry0 ); + Vec_IntPush( vArg2, Entry ); + break; + } + Entry = Vec_IntEntry(vArg2, 1); + while ( Gia_ManMulFindNextEntry2(vCuts5, vSet, Entry, vCounts, &Entry0, &Entry1) ) + Vec_IntPushTwo( vArg2, Entry0, Entry1 ), Entry = Entry1; + Vec_IntFree( vCounts ); +} +void Gia_ManMulFindAddEntry( Vec_Int_t * vPairs, int Obj0, int Obj1 ) +{ + int Entry0, Entry1, Sum, k; + Vec_IntForEachEntryTriple( vPairs, Entry0, Entry1, Sum, k ) + if ( Obj0 == Entry0 && Obj1 == Entry1 ) { + Vec_IntAddToEntry( vPairs, k+2, 1 ); + break; + } + if ( k == Vec_IntSize(vPairs) ) + Vec_IntPushThree( vPairs, Obj0, Obj1, 1 ); +} +Vec_Wec_t * Gia_ManMulFindBInputs2( Gia_Man_t * p, Vec_Wec_t * vCuts4, Vec_Wec_t * vCuts5, int fVerbose ) +{ + Vec_Wec_t * vRes = Vec_WecAlloc( 10 ); + Vec_Int_t * vPairs = Vec_IntAlloc( 1000 ); + Vec_Int_t * vSet = Vec_IntAlloc( 100 ); + Vec_Int_t * vCut, * vArg1, * vArg2; + int i, j, k, n, Entry0, Entry1, Sum, Obj0, Obj1; + Vec_WecForEachLevel( vCuts4, vCut, i ) + Vec_IntForEachEntryStart( vCut, Obj0, j, 1 ) + Vec_IntForEachEntryStart( vCut, Obj1, k, j+1 ) + Gia_ManMulFindAddEntry( vPairs, Obj0, Obj1 ); + Vec_IntForEachEntryTriple( vPairs, Entry0, Entry1, Sum, n ) { + if ( Sum < 3 ) + continue; + Vec_IntClear( vSet ); + Vec_WecForEachLevel( vCuts4, vCut, i ) + Vec_IntForEachEntryStart( vCut, Obj0, j, 1 ) + Vec_IntForEachEntryStart( vCut, Obj1, k, j+1 ) + if ( Obj0 == Entry0 && Obj1 == Entry1 ) { + Vec_IntPush( vSet, i ); + Vec_IntDrop( vCut, k ); + Vec_IntDrop( vCut, j ); + j = k = Vec_IntSize(vCut); + } + vArg1 = Vec_WecPushLevel(vRes); + vArg2 = Vec_WecPushLevel(vRes); + Vec_WecPushLevel(vRes); + Gia_ManMulFindArg1( vCuts4, vSet, vArg1 ); + // find overlapping with arg1 and remove nodes in arg1 + Vec_IntClear( vSet ); + Vec_WecForEachLevel( vCuts5, vCut, i ) + if ( Gia_ManMulFindGetOverlap2(vCut, vArg1) ) { + k = 1; + Vec_IntForEachEntryStart( vCut, Obj0, j, 1 ) + if ( Vec_IntFind(vArg1, Obj0) == -1 ) + Vec_IntWriteEntry( vCut, k++, Obj0 ); + Vec_IntShrink( vCut, k ); + Vec_IntPush( vSet, i ); + } + Gia_ManMulFindArg2( vCuts5, vSet, vArg2, Entry0, Entry1 ); + } + Vec_IntFree( vSet ); + Vec_IntFree( vPairs ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManMulFindOverlap( Vec_Int_t * p1, Vec_Int_t * p2 ) +{ + int i, k, ObjI, ObjK, Counter = 0; + Vec_IntForEachEntry( p1, ObjI, i ) + Vec_IntForEachEntry( p2, ObjK, k ) + if ( ObjI == ObjK ) + Counter++; + return Counter; +} +void Gia_ManMulFindAssignGroup( Vec_Int_t * vTemp, int iGroup, Vec_Int_t * vMap ) +{ + int k, Obj; + Vec_IntForEachEntry( vTemp, Obj, k ) { + //assert( Vec_IntEntry(vMap, Obj) == -1 || Vec_IntEntry(vMap, Obj) == iGroup ); + Vec_IntWriteEntry(vMap, Obj, iGroup); + } + Vec_IntPush( vTemp, iGroup ); +} +Vec_Int_t * Gia_ManMulFindGroups( Vec_Wec_t * p, int nObjs, int fUseMap ) +{ + Vec_Int_t * vIndex = Vec_IntAlloc( 100 ), * vTemp; + Vec_Int_t * vMap = Vec_IntStartFull( nObjs ); int i, Counter, nGroups = 0; + Vec_Int_t * vUngrouped = Vec_IntStartNatural( Vec_WecSize(p) ); + while ( Vec_IntSize(vUngrouped) ) { + int k, Obj, Item = Vec_IntPop(vUngrouped); + vTemp = Vec_WecEntry(p, Item); + Gia_ManMulFindAssignGroup( vTemp, nGroups, vMap ); + int fChanges = 1; + while ( fChanges ) { + fChanges = 0; + Vec_IntForEachEntry( vUngrouped, Item, i ) { + vTemp = Vec_WecEntry(p, Item); + Counter = 0; + Vec_IntForEachEntry( vTemp, Obj, k ) + if ( Vec_IntEntry(vMap, Obj) >= 0 ) + Counter++; + if ( Counter < 1 ) + continue; + Gia_ManMulFindAssignGroup( vTemp, nGroups, vMap ); + Vec_IntDrop( vUngrouped, i-- ); + fChanges = 1; + } + } + nGroups++; + } + Vec_IntFree( vUngrouped ); + Vec_IntFree( vMap ); + if ( fUseMap ) + Vec_WecForEachLevel( p, vTemp, i ) + Vec_IntPushTwo( vTemp, i, Vec_IntPop(vTemp) ); + Vec_WecSortByLastInt( p, 0 ); + Counter = 0; + Vec_IntPush( vIndex, 0 ); + Vec_WecForEachLevel( p, vTemp, i ) + if ( Vec_IntPop(vTemp) != Counter ) + Vec_IntPush( vIndex, i ), Counter++; + Vec_IntPush( vIndex, Vec_WecSize(p) ); + assert( Vec_WecSize(p) == 0 || Vec_IntSize(vIndex) == nGroups + 1 ); + return vIndex; +} +Vec_Wec_t * Gia_ManMulFindXors( Gia_Man_t * p, Vec_Wec_t * vCuts3, int fVerbose ) +{ + Vec_Wec_t * vXors = Vec_WecAlloc( 10 ); + Vec_Int_t * vIndex = Gia_ManMulFindGroups( vCuts3, Gia_ManObjNum(p), 0 ); + Vec_Int_t * vAll = Vec_IntAlloc( 100 ); + Vec_Bit_t * vSigs[2] = { Vec_BitStart(Gia_ManObjNum(p)), Vec_BitStart(Gia_ManObjNum(p)) }; + Vec_Int_t * vTemp; int g, c, k, Obj, Start; + Vec_IntForEachEntryStop( vIndex, Start, g, Vec_IntSize(vIndex)-1 ) { + Vec_WecForEachLevelStartStop( vCuts3, vTemp, c, Start, Vec_IntEntry(vIndex, g+1) ) + Vec_IntForEachEntry( vTemp, Obj, k ) + if ( !Vec_BitEntry(vSigs[k==0], Obj) ) { + Vec_BitWriteEntry( vSigs[k==0], Obj, 1 ); + Vec_IntPush( vAll, Obj ); + } + Vec_Int_t * vIns = Vec_WecPushLevel( vXors ); + Vec_Int_t * vOuts = Vec_WecPushLevel( vXors ); + Vec_IntForEachEntry( vAll, Obj, k ) { + if ( Vec_BitEntry(vSigs[0], Obj) && !Vec_BitEntry(vSigs[1], Obj) ) + Vec_IntPush( vIns, Obj ); + if ( !Vec_BitEntry(vSigs[0], Obj) && Vec_BitEntry(vSigs[1], Obj) ) + Vec_IntPush( vOuts, Obj ); + Vec_BitWriteEntry( vSigs[0], Obj, 0 ); + Vec_BitWriteEntry( vSigs[1], Obj, 0 ); + } + Vec_IntClear( vAll ); + } + return vXors; +} +Vec_Int_t * Gia_ManFindMulDetectOrder( Vec_Wec_t * vAll, int iStart, int iStop ) +{ + Vec_Int_t * vOrder = Vec_IntAlloc( iStop - iStart ); + Vec_Int_t * vUsed = Vec_IntStart( iStop ), * vTemp; + int i, nMatches = 0, iNext = -1; + Vec_WecForEachLevelStartStop( vAll, vTemp, i, iStart, iStop ) + if ( Vec_IntSize(vTemp) == 2 ) + nMatches++, iNext = i; + if ( nMatches == 1 ) { + while ( Vec_IntSize(vOrder) < iStop - iStart ) { + Vec_IntPush( vOrder, iNext ); + Vec_IntWriteEntry( vUsed, iNext, 1 ); + nMatches = 0; + Vec_WecForEachLevelStartStop( vAll, vTemp, i, iStart, iStop ) { + if ( Vec_IntEntry(vUsed, i) ) + continue; + Vec_Int_t * vLast = Vec_WecEntry(vAll, Vec_IntEntryLast(vOrder)); + if ( Gia_ManMulFindOverlap(vTemp, vLast) == Vec_IntSize(vLast) && Vec_IntSize(vTemp) == Vec_IntSize(vLast) + 2 ) + nMatches++, iNext = i; + } + if ( nMatches != 1 ) + break; + } + } + Vec_IntFree( vUsed ); + if ( Vec_IntSize(vOrder) == 0 ) + Vec_IntFreeP( &vOrder ); + return vOrder; +} +Vec_Wec_t * Gia_ManMulFindAInputs( Gia_Man_t * p, Vec_Wec_t * vXors, int fVerbose ) +{ + Vec_Wec_t * vRes = Vec_WecAlloc( 10 ); + Vec_Wec_t * vAll = Vec_WecAlloc( Vec_WecSize(vXors)/2 ); + Gia_Obj_t * pObj; Vec_Int_t * vIns, * vOuts, * vTemp, * vIndex, * vOrder; int i, k, g, Start, Entry, Entry0, Entry1; + Gia_ManCreateRefs( p ); + Vec_WecForEachLevelDouble( vXors, vIns, vOuts, i ) { + vTemp = Vec_WecPushLevel( vAll ); + Gia_ManForEachObjVec( vIns, p, pObj, k ) + if ( Gia_ObjIsAnd(pObj) + && !Gia_ObjFaninC0(pObj) && Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) >= 4 + && !Gia_ObjFaninC1(pObj) && Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) >= 4 ) + Vec_IntPushTwo( vTemp, Gia_ObjFaninId0p(p, pObj), Gia_ObjFaninId1p(p, pObj) ); + if ( Vec_IntSize(vTemp) == 0 ) + Vec_WecShrink(vAll, Vec_WecSize(vAll)-1); + } + vIndex = Gia_ManMulFindGroups( vAll, Gia_ManObjNum(p), 0 ); + Vec_IntForEachEntryStop( vIndex, Start, g, Vec_IntSize(vIndex)-1 ) { + vOrder = Gia_ManFindMulDetectOrder( vAll, Start, Vec_IntEntry(vIndex, g+1) ); + if ( vOrder == NULL ) + continue; + Vec_Int_t * vIn0 = Vec_WecPushLevel( vRes ); + Vec_Int_t * vIn1 = Vec_WecPushLevel( vRes ); + Vec_Int_t * vOut = Vec_WecPushLevel( vRes ); + vTemp = Vec_WecEntry( vAll, Vec_IntEntry(vOrder, 0) ); + assert( Vec_IntSize(vTemp) == 2 ); + Vec_IntPush( vIn0, Vec_IntEntry(vTemp, 0) ); + Vec_IntPush( vIn1, Vec_IntEntry(vTemp, 1) ); + Vec_IntForEachEntryStart( vOrder, Entry, i, 1 ) { + vTemp = Vec_WecEntry( vAll, Entry ); + Vec_IntForEachEntryDouble( vTemp, Entry0, Entry1, k ) { + if ( Vec_IntFind(vIn0, Entry0) >= 0 && Vec_IntFind(vIn1, Entry1) == -1 ) + Vec_IntPush( vIn1, Entry1 ); + else if ( Vec_IntFind(vIn0, Entry0) == -1 && Vec_IntFind(vIn1, Entry1) >= 0 ) + Vec_IntPush( vIn0, Entry0 ); + else + assert( (Vec_IntFind(vIn0, Entry0) >= 0 && Vec_IntFind(vIn1, Entry1) >= 0) || + (Vec_IntFind(vIn0, Entry1) >= 0 && Vec_IntFind(vIn1, Entry0) >= 0) ); + } + } + Vec_IntReverseOrder( vIn0 ); + Vec_IntReverseOrder( vIn1 ); + vOut = NULL; + } + Vec_IntFree( vIndex ); + Vec_WecFree( vAll ); + return vRes; +} +Vec_Wec_t * Gia_ManMulFindBInputs( Gia_Man_t * p, Vec_Wec_t * vCuts4, Vec_Wec_t * vCuts5, int fVerbose ) +{ + Vec_Wec_t * vRes = Vec_WecAlloc( 10 ); Vec_Int_t * vTemp; int g, c, k, Obj, Start; + Vec_Int_t * vIndex = Gia_ManMulFindGroups( vCuts4, Gia_ManObjNum(p), 0 ); + Vec_IntForEachEntryStop( vIndex, Start, g, Vec_IntSize(vIndex)-1 ) { + Vec_Int_t * vAll = Vec_IntAlloc ( 100 ); + Vec_WecForEachLevelStartStop( vCuts4, vTemp, c, Start, Vec_IntEntry(vIndex, g+1) ) + Vec_IntForEachEntryStart( vTemp, Obj, k, 1 ) + Vec_IntPush( vAll, Obj ); + Vec_IntUniqify( vAll ); + int GroupSize = Vec_IntEntry(vIndex, g+1) - Start; + Vec_Int_t * vCnt = Vec_IntStart( Vec_IntSize(vAll) ); + Vec_WecForEachLevelStartStop( vCuts4, vTemp, c, Start, Vec_IntEntry(vIndex, g+1) ) + Vec_IntForEachEntryStart( vTemp, Obj, k, 1 ) + Vec_IntAddToEntry( vCnt, Vec_IntFind(vAll, Obj), 1 ); + if ( Vec_IntCountEntry(vCnt, 1) != 2 || Vec_IntCountEntry(vCnt, 2) != GroupSize-1 || Vec_IntCountEntry(vCnt, GroupSize) != 2 ) { + printf( "Detection of group %d failed.\n", g ); + continue; + } + Vec_Int_t * vIn1 = Vec_WecPushLevel( vRes ); + Vec_Int_t * vIn2 = Vec_WecPushLevel( vRes ); + Vec_Int_t * vOut = Vec_WecPushLevel( vRes ); + Vec_IntForEachEntry( vAll, Obj, k ) + if ( Vec_IntEntry(vCnt, k) <= 2 ) + Vec_IntPush( vIn1, Obj ); + else + Vec_IntPush( vIn2, Obj ); + Vec_IntSort( vIn1, 0 ); + Vec_IntSort( vIn2, 0 ); + // TODO: check chain in[i] -> in[i+1] + Vec_WecForEachLevel( vCuts5, vTemp, c ) { + Vec_IntShift( vTemp, 1 ); + if ( Gia_ManMulFindOverlap(vTemp, vIn1) >= 2 ) + Vec_IntForEachEntryStart( vTemp, Obj, k, 1 ) + if ( Vec_IntFind(vIn1, Obj) == -1 ) { + Vec_IntPushUnique(vIn2, Obj); + } + Vec_IntShift( vTemp, -1 ); + } + Vec_IntSort( vIn2, 0 ); + vOut = NULL; + } + Vec_IntFree( vIndex ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManMulFindTfo( Gia_Man_t * p, Vec_Int_t * vIn0, Vec_Int_t * vIn1 ) +{ + Vec_Int_t * vTfo = Vec_IntAlloc( 100 ); + Gia_Obj_t * pObj; int i, Obj; + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vIn0, Obj, i ) + Gia_ObjSetTravIdCurrentId( p, Obj ); + Vec_IntForEachEntry( vIn1, Obj, i ) + Gia_ObjSetTravIdCurrentId( p, Obj ); + Gia_ManForEachAnd( p, pObj, i ) { + if ( Gia_ObjIsTravIdCurrentId(p, i) ) + continue; + if ( Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId0(pObj, i)) && Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId1(pObj, i)) ) + Gia_ObjSetTravIdCurrentId( p, i ), Vec_IntPush( vTfo, i ); + } + return vTfo; +} +Vec_Wrd_t * Gia_ManMulFindSimCone( Gia_Man_t * p, Vec_Int_t * vIn0, Vec_Int_t * vIn1, Vec_Wrd_t * vSim0, Vec_Wrd_t * vSim1, Vec_Int_t * vTfo ) +{ + Vec_Wrd_t * vRes = Vec_WrdAlloc( Vec_IntSize(vTfo) ); + Vec_Wrd_t * vSims = Vec_WrdStart( Gia_ManObjNum(p) ); + Gia_Obj_t * pObj; int i, Obj; + Vec_IntForEachEntry( vIn0, Obj, i ) + Vec_WrdWriteEntry( vSims, Obj, Vec_WrdEntry(vSim0, i) ); + Vec_IntForEachEntry( vIn1, Obj, i ) + Vec_WrdWriteEntry( vSims, Obj, Vec_WrdEntry(vSim1, i) ); + Gia_ManForEachObjVec( vTfo, p, pObj, i ) { + word Sim0 = Vec_WrdEntry(vSims, Gia_ObjFaninId0p(p, pObj) ); + word Sim1 = Vec_WrdEntry(vSims, Gia_ObjFaninId1p(p, pObj) ); + Vec_WrdWriteEntry( vSims, Gia_ObjId(p, pObj), (Gia_ObjFaninC0(pObj) ? ~Sim0 : Sim0) & (Gia_ObjFaninC1(pObj) ? ~Sim1 : Sim1) ); + } + Vec_IntForEachEntry( vTfo, Obj, i ) + Vec_WrdPush( vRes, Vec_WrdEntry(vSims, Obj) ); + Vec_WrdFree( vSims ); + return vRes; +} +int Gia_ManMulFindGetArg( Vec_Wrd_t * vSim, int i, int fSigned ) +{ + int w, Res = 0; word Word = 0; + Vec_WrdForEachEntry( vSim, Word, w ) + if ( (Word >> i) & 1 ) + Res |= (1 << w); + if ( fSigned && ((Word >> i) & 1) ) + Res |= ~0 << Vec_WrdSize(vSim); + return Res; +} +void Gia_ManMulFindSetArg( Vec_Wrd_t * vSim, int i, int iNum ) +{ + int w; word * pWords = Vec_WrdArray(vSim); + for ( w = 0; w < Vec_WrdSize(vSim); w++ ) + if ( (iNum >> w) & 1 ) + pWords[w] |= (word)1 << i; +} +Vec_Wrd_t * Gia_ManMulFindSim( Vec_Wrd_t * vSim0, Vec_Wrd_t * vSim1, int fSigned ) +{ + assert( Vec_WrdSize(vSim0) + Vec_WrdSize(vSim1) <= 30 ); + Vec_Wrd_t * vRes = Vec_WrdStart( Vec_WrdSize(vSim0) + Vec_WrdSize(vSim1) ); + for ( int i = 0; i < 64; i++ ) + { + int a = Gia_ManMulFindGetArg( vSim0, i, fSigned ); + int b = Gia_ManMulFindGetArg( vSim1, i, fSigned ); + Gia_ManMulFindSetArg( vRes, i, a * b ); + } + return vRes; +} +void Gia_ManMulFindOutputs( Gia_Man_t * p, Vec_Wec_t * vTerms, int fVerbose ) +{ + Abc_Random(1); + for ( int m = 0; m < Vec_WecSize(vTerms)/3; m++ ) { + Vec_Int_t * vIn0 = Vec_WecEntry(vTerms, 3*m+0); + Vec_Int_t * vIn1 = Vec_WecEntry(vTerms, 3*m+1); + Vec_Int_t * vOut = Vec_WecEntry(vTerms, 3*m+2); + Vec_Wrd_t * vSim0 = Vec_WrdStartRandom( Vec_IntSize(vIn0) ); + Vec_Wrd_t * vSim1 = Vec_WrdStartRandom( Vec_IntSize(vIn1) ); + Vec_Wrd_t * vSimU = Gia_ManMulFindSim( vSim0, vSim1, 0 ); + Vec_Wrd_t * vSimS = Gia_ManMulFindSim( vSim0, vSim1, 1 ); + Vec_Int_t * vTfo = Gia_ManMulFindTfo( p, vIn0, vIn1 ); + Vec_Wrd_t * vSims = Gia_ManMulFindSimCone( p, vIn0, vIn1, vSim0, vSim1, vTfo ); + Vec_Int_t * vOutU = Vec_IntAlloc( 100 ); + Vec_Int_t * vOutS = Vec_IntAlloc( 100 ); + word Word; int w, iPlace; + Vec_WrdForEachEntry( vSimU, Word, w ) { + if ( (iPlace = Vec_WrdFind(vSims, Word)) >= 0 ) + Vec_IntPush( vOutU, Abc_Var2Lit(Vec_IntEntry(vTfo, iPlace), 0) ); + else if ( (iPlace = Vec_WrdFind(vSims, ~Word)) >= 0 ) + Vec_IntPush( vOutU, Abc_Var2Lit(Vec_IntEntry(vTfo, iPlace), 1) ); + else + Vec_IntPush( vOutU, -1 ); + } + Vec_WrdForEachEntry( vSimS, Word, w ) { + if ( (iPlace = Vec_WrdFind(vSims, Word)) >= 0 ) + Vec_IntPush( vOutS, Abc_Var2Lit(Vec_IntEntry(vTfo, iPlace), 0) ); + else if ( (iPlace = Vec_WrdFind(vSims, ~Word)) >= 0 ) + Vec_IntPush( vOutS, Abc_Var2Lit(Vec_IntEntry(vTfo, iPlace), 1) ); + else + Vec_IntPush( vOutS, -1 ); + } + assert( Vec_IntSize(vOut) == 0 ); + if ( Vec_IntCountEntry(vOutU, -1) < Vec_IntSize(vOutU) || + Vec_IntCountEntry(vOutS, -1) < Vec_IntSize(vOutS) ) + { + if ( Vec_IntCountEntry(vOutU, -1) < Vec_IntCountEntry(vOutS, -1) ) + Vec_IntAppend( vOut, vOutU ), Vec_IntPush(vOut, 0); + else + Vec_IntAppend( vOut, vOutS ), Vec_IntPush(vOut, 1); + } + else + { + Vec_IntClear(vIn0); + Vec_IntClear(vIn1); + } + Vec_WrdFree( vSim0 ); + Vec_WrdFree( vSim1 ); + Vec_WrdFree( vSimU ); + Vec_WrdFree( vSimS ); + Vec_WrdFree( vSims ); + Vec_IntFree( vTfo ); + Vec_IntFree( vOutU ); + Vec_IntFree( vOutS ); + } + Vec_WecRemoveEmpty( vTerms ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Gia_ManMulFindCuts( Gia_Man_t * p, int nCutNum, int fVerbose ) +{ + extern Vec_Mem_t * Dau_CollectNpnFunctions( word * p, int nVars, int fVerbose ); + extern Vec_Ptr_t * Gia_ManMatchCutsArray( Vec_Ptr_t * vTtMems, Gia_Man_t * pGia, int nCutSize, int nCutNum, int fVerbose ); + word pTruths[3] = { ABC_CONST(0x6969696969696969), ABC_CONST(0x35C035C035C035C0), ABC_CONST(0xF335ACC0F335ACC0) }; + Vec_Ptr_t * vTtMems = Vec_PtrAlloc( 3 ); Vec_Mem_t * vTtMem; int i; + for ( i = 0; i < 3; i++ ) + Vec_PtrPush( vTtMems, Dau_CollectNpnFunctions( pTruths+i, i+3, fVerbose ) ); + Vec_Ptr_t * vAll = Gia_ManMatchCutsArray( vTtMems, p, 5, nCutNum, fVerbose ); + Vec_PtrForEachEntry( Vec_Mem_t *, vTtMems, vTtMem, i ) + Vec_MemHashFree( vTtMem ), Vec_MemFree( vTtMem ); + Vec_PtrFree( vTtMems ); + return vAll; +} +Vec_Wec_t * Gia_ManMulFindA( Gia_Man_t * p, Vec_Wec_t * vCuts3, int fVerbose ) +{ + Vec_Wec_t * vXors = Gia_ManMulFindXors( p, vCuts3, fVerbose ); + Vec_Wec_t * vTerms = Gia_ManMulFindAInputs2( p, fVerbose ); + if ( Vec_WecSize(vTerms) ) + Gia_ManMulFindOutputs( p, vTerms, fVerbose ); + Vec_WecFree( vXors ); + return vTerms; +} +Vec_Wec_t * Gia_ManMulFindB( Gia_Man_t * p, Vec_Wec_t * vCuts4, Vec_Wec_t * vCuts5, int fVerbose ) +{ + Vec_Wec_t * vTerms = Vec_WecAlloc( 12 ); + if ( Vec_WecSize(vCuts4) && Vec_WecSize(vCuts5) ) + vTerms = Gia_ManMulFindBInputs2( p, vCuts4, vCuts5, fVerbose ); + if ( Vec_WecSize(vTerms) ) + Gia_ManMulFindOutputs( p, vTerms, fVerbose ); + return vTerms; +} +void Gia_ManMulFindPrintSet( Vec_Int_t * vSet, int fLit, int fSkipLast ) +{ + int i, Temp, Limit = Vec_IntSize(vSet) - fSkipLast; + printf( "{" ); + Vec_IntForEachEntryStop( vSet, Temp, i, Limit ) { + if ( Temp == -1 ) + printf( "n/a%s", i < Limit-1 ? " ":"" ); + else + printf( "%s%d%s", (fLit & Abc_LitIsCompl(Temp)) ? "~":"", fLit ? Abc_Lit2Var(Temp) : Temp, i < Limit-1 ? " ":"" ); + } + printf( "}" ); +} +void Gia_ManMulFindPrintOne( Vec_Wec_t * vTerms, int m, int fBooth ) +{ + Vec_Int_t * vIn0 = Vec_WecEntry(vTerms, 3*m+0); + Vec_Int_t * vIn1 = Vec_WecEntry(vTerms, 3*m+1); + Vec_Int_t * vOut = Vec_WecEntry(vTerms, 3*m+2); + printf( "%sooth %ssigned %d x %d: ", fBooth ? "B" : "Non-b", Vec_IntEntryLast(vOut) ? "" : "un", Vec_IntSize(vIn0), Vec_IntSize(vIn1) ); + Gia_ManMulFindPrintSet( vIn0, 0, 0 ); + printf( " * " ); + Gia_ManMulFindPrintSet( vIn1, 0, 0 ); + printf( " = " ); + Gia_ManMulFindPrintSet( vOut, 1, 1 ); + printf( "\n" ); +} +void Gia_ManMulFind( Gia_Man_t * p, int nCutNum, int fVerbose ) +{ + Vec_Ptr_t * vAll = Gia_ManMulFindCuts( p, nCutNum, fVerbose ); int m; + Vec_Wec_t * vCuts3 = (Vec_Wec_t *)Vec_PtrEntry(vAll, 0); + Vec_Wec_t * vCuts4 = (Vec_Wec_t *)Vec_PtrEntry(vAll, 1); + Vec_Wec_t * vCuts5 = (Vec_Wec_t *)Vec_PtrEntry(vAll, 2); + Vec_Wec_t * vTermsB = Gia_ManMulFindB( p, vCuts4, vCuts5, fVerbose ); + Vec_Wec_t * vTermsA = Gia_ManMulFindA( p, vCuts3, fVerbose ); + printf( "Detected %d booth and %d non-booth multipliers.\n", Vec_WecSize(vTermsB)/3, Vec_WecSize(vTermsA)/3 ); + for ( m = 0; m < Vec_WecSize(vTermsA)/3; m++ ) + Gia_ManMulFindPrintOne( vTermsA, m, 0 ); + for ( m = 0; m < Vec_WecSize(vTermsB)/3; m++ ) + Gia_ManMulFindPrintOne( vTermsB, m, 1 ); + Vec_WecFree( vTermsB ); + Vec_WecFree( vTermsA ); + Vec_WecFree( vCuts3 ); + Vec_WecFree( vCuts4 ); + Vec_WecFree( vCuts5 ); + Vec_PtrFree( vAll ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaMuxes.c b/yosys/abc/src/aig/gia/giaMuxes.c new file mode 100644 index 00000000000..ff542c30539 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaMuxes.c @@ -0,0 +1,1237 @@ +/**CFile**************************************************************** + + FileName [giaMuxes.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Multiplexer profiling algorithm.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaMuxes.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/util/utilNam.h" +#include "misc/util/utilTruth.h" +#include "misc/vec/vecWec.h" +#include "misc/vec/vecHsh.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Counts XORs and MUXes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCountMuxXor( Gia_Man_t * p, int * pnMuxes, int * pnXors ) +{ + Gia_Obj_t * pObj, * pFan0, * pFan1; int i; + *pnMuxes = *pnXors = 0; + Gia_ManForEachAnd( p, pObj, i ) + { + if ( !Gia_ObjIsMuxType(pObj) ) + continue; + if ( Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) ) + (*pnXors)++; + else + (*pnMuxes)++; + } +} +void Gia_ManPrintMuxStats( Gia_Man_t * p ) +{ + int nAnds, nMuxes, nXors, nTotal; + if ( p->pMuxes ) + { + nAnds = Gia_ManAndNotBufNum(p)-Gia_ManXorNum(p)-Gia_ManMuxNum(p); + nXors = Gia_ManXorNum(p); + nMuxes = Gia_ManMuxNum(p); + nTotal = nAnds + 3*nXors + 3*nMuxes; + } + else + { + Gia_ManCountMuxXor( p, &nMuxes, &nXors ); + nAnds = Gia_ManAndNotBufNum(p) - 3*nMuxes - 3*nXors; + nTotal = Gia_ManAndNotBufNum(p); + } + Abc_Print( 1, "stats: " ); + Abc_Print( 1, "xor =%8d %6.2f %% ", nXors, 300.0*nXors/nTotal ); + Abc_Print( 1, "mux =%8d %6.2f %% ", nMuxes, 300.0*nMuxes/nTotal ); + Abc_Print( 1, "and =%8d %6.2f %% ", nAnds, 100.0*nAnds/nTotal ); + Abc_Print( 1, "obj =%8d ", Gia_ManAndNotBufNum(p) ); + fflush( stdout ); +} + +/**Function************************************************************* + + Synopsis [Derives GIA with MUXes.] + + Description [Create MUX if the sum of fanin references does not exceed limit.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupMuxes( Gia_Man_t * p, int Limit ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pFan0, * pFan1, * pFanC, * pSiblNew, * pObjNew; + int i; + assert( p->pMuxes == NULL ); + assert( Limit >= 0 ); // allows to create AIG with XORs without MUXes + ABC_FREE( p->pRefs ); + Gia_ManCreateRefs( p ); + // start the new manager + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc ); + if ( Gia_ManHasChoices(p) ) + pNew->pSibls = ABC_CALLOC( int, pNew->nObjsAlloc ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashStart( pNew ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsBuf(pObj) ) + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( !Gia_ObjIsMuxType(pObj) || Gia_ObjSibl(p, Gia_ObjFaninId0(pObj, i)) || Gia_ObjSibl(p, Gia_ObjFaninId1(pObj, i)) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) ) + pObj->Value = Gia_ManHashXorReal( pNew, Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan0)), Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan1)) ); + else if ( Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) + Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) > Limit ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else + { + pFanC = Gia_ObjRecognizeMux( pObj, &pFan1, &pFan0 ); + pObj->Value = Gia_ManHashMuxReal( pNew, Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFanC)), Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan1)), Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan0)) ); + } + if ( !Gia_ObjSibl(p, i) ) + continue; + pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) ); + pSiblNew = Gia_ManObj( pNew, Abc_Lit2Var(Gia_ObjSiblObj(p, i)->Value) ); + if ( Gia_ObjIsAnd(pObjNew) && Gia_ObjIsAnd(pSiblNew) && Gia_ObjId(pNew, pObjNew) > Gia_ObjId(pNew, pSiblNew) ) + pNew->pSibls[Gia_ObjId(pNew, pObjNew)] = Gia_ObjId(pNew, pSiblNew); + } + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + // perform cleanup + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Creates AIG with XORs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManCreateXors( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; Gia_Obj_t * pObj, * pFan0, * pFan1; + Vec_Int_t * vRefs = Vec_IntStart( Gia_ManObjNum(p) ); + int i, iLit0, iLit1, nXors = 0, nObjs = 0; + Gia_ManForEachObj( p, pObj, i ) + pObj->fMark0 = 0; + Gia_ManForEachAnd( p, pObj, i ) + { + if ( Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) ) + { + Vec_IntAddToEntry( vRefs, Gia_ObjId(p, Gia_Regular(pFan0)), 1 ); + Vec_IntAddToEntry( vRefs, Gia_ObjId(p, Gia_Regular(pFan1)), 1 ); + pObj->fMark0 = 1; + nXors++; + } + else + { + Vec_IntAddToEntry( vRefs, Gia_ObjFaninId0(pObj, i), 1 ); + Vec_IntAddToEntry( vRefs, Gia_ObjFaninId1(pObj, i), 1 ); + } + } + Gia_ManForEachCo( p, pObj, i ) + Vec_IntAddToEntry( vRefs, Gia_ObjFaninId0p(p, pObj), 1 ); + Gia_ManForEachAnd( p, pObj, i ) + nObjs += Vec_IntEntry(vRefs, i) > 0; + pNew = Gia_ManStart( 1 + Gia_ManCiNum(p) + Gia_ManCoNum(p) + nObjs ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsBuf(pObj) ) + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( pObj->fMark0 ) + { + Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1); + iLit0 = Abc_LitNotCond( Gia_Regular(pFan0)->Value, Gia_IsComplement(pFan0) ); + iLit1 = Abc_LitNotCond( Gia_Regular(pFan1)->Value, Gia_IsComplement(pFan1) ); + pObj->Value = Gia_ManAppendXorReal( pNew, iLit0, iLit1 ); + } + else if ( Vec_IntEntry(vRefs, i) > 0 ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + assert( pNew->nObjs == pNew->nObjsAlloc ); + pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjs ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + Vec_IntFree( vRefs ); + //printf( "Created %d XORs.\n", nXors ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Derives GIA without MUXes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupNoMuxes( Gia_Man_t * p, int fSkipBufs ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i; + assert( p->pMuxes != NULL || Gia_ManXorNum(p) ); + // start the new manager + pNew = Gia_ManStart( 5000 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashStart( pNew ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsBuf(pObj) ) + pObj->Value = fSkipBufs ? Gia_ObjFanin0Copy(pObj) : Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsMuxId(p, i) ) + pObj->Value = Gia_ManHashMux( pNew, Gia_ObjFanin2Copy(p, pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsXor(pObj) ) + pObj->Value = Gia_ManHashXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + // perform cleanup + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Test these procedures.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupMuxesTest( Gia_Man_t * p ) +{ + Gia_Man_t * pNew, * pNew2; + pNew = Gia_ManDupMuxes( p, 2 ); + pNew2 = Gia_ManDupNoMuxes( pNew, 0 ); + Gia_ManPrintStats( p, NULL ); + Gia_ManPrintStats( pNew, NULL ); + Gia_ManPrintStats( pNew2, NULL ); + Gia_ManStop( pNew ); +// Gia_ManStop( pNew2 ); + return pNew2; +} + + +/**Function************************************************************* + + Synopsis [Test these procedures.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManMuxRestructure( Gia_Man_t * p ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, nNodes = 0; + Vec_Bit_t * vUsed = Vec_BitStart( Gia_ManObjNum(p) ); + assert( !Gia_ManHasChoices(p) ); + assert( !Gia_ManHasMapping(p) ); + assert( p->pMuxes != NULL ); + ABC_FREE( p->pRefs ); + Gia_ManCreateRefs( p ); + // start the new manager + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashStart( pNew ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsBuf(pObj) ) + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsMuxId(p, i) && + Gia_ObjIsMuxId(p, Gia_ObjFaninId0(pObj, i)) && !Vec_BitEntry(vUsed, Gia_ObjFaninId0(pObj, i)) && + Gia_ObjIsMuxId(p, Gia_ObjFaninId1(pObj, i)) && !Vec_BitEntry(vUsed, Gia_ObjFaninId1(pObj, i)) && + Gia_ObjFaninId2(p, Gia_ObjFaninId0(pObj, i)) == Gia_ObjFaninId2(p, Gia_ObjFaninId1(pObj, i)) ) + { + Gia_Obj_t * pFan1 = Gia_ObjFanin1(pObj); + int Value0 = Gia_ManHashMux( pNew, Gia_ObjFanin2Copy(p, pObj), Gia_ObjFanin2Copy(p, pFan1), Gia_ObjFanin0Copy(pObj) ); + int Value1 = Gia_ManHashMux( pNew, Value0, Gia_ObjFanin1Copy(pFan1), Gia_ObjFanin0Copy(pFan1) ); + pObj->Value = Gia_ManHashMux( pNew, Gia_ObjFanin2Copy(p, pObj), Value1, Value0 ); + Vec_BitWriteEntry( vUsed, Gia_ObjFaninId0(pObj, i), 1 ); + Vec_BitWriteEntry( vUsed, Gia_ObjFaninId1(pObj, i), 1 ); + Vec_BitWriteEntry( vUsed, i, 1 ); + nNodes++; + } + else if ( Gia_ObjIsMuxId(p, i) ) + pObj->Value = Gia_ManHashMux( pNew, Gia_ObjFanin2Copy(p, pObj), Gia_ObjFanin1Copy(pObj), Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsXor(pObj) ) + pObj->Value = Gia_ManHashXor( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + Vec_BitFree( vUsed ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + // perform cleanup + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} +Gia_Man_t * Gia_ManDupMuxRestructure( Gia_Man_t * p ) +{ + Gia_Man_t * pTemp, * pNew = Gia_ManDupMuxes( p, 2 ); + pNew = Gia_ManMuxRestructure( pTemp = pNew ); Gia_ManStop( pTemp ); + pNew = Gia_ManDupNoMuxes( pTemp = pNew, 0 ); Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Returns the size of MUX structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_MuxRef_rec( Gia_Man_t * p, int iObj ) +{ + Gia_Obj_t * pObj; + if ( !Gia_ObjIsMuxId(p, iObj) ) + return 0; + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjRefInc(p, pObj) ) + return 0; + return Gia_MuxRef_rec( p, Gia_ObjFaninId0p(p, pObj) ) + + Gia_MuxRef_rec( p, Gia_ObjFaninId1p(p, pObj) ) + + Gia_MuxRef_rec( p, Gia_ObjFaninId2p(p, pObj) ) + 1; +} +int Gia_MuxRef( Gia_Man_t * p, int iObj ) +{ + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + assert( Gia_ObjIsMuxId(p, iObj) ); + return Gia_MuxRef_rec( p, Gia_ObjFaninId0p(p, pObj) ) + + Gia_MuxRef_rec( p, Gia_ObjFaninId1p(p, pObj) ) + + Gia_MuxRef_rec( p, Gia_ObjFaninId2p(p, pObj) ) + 1; +} +int Gia_MuxDeref_rec( Gia_Man_t * p, int iObj ) +{ + Gia_Obj_t * pObj; + if ( !Gia_ObjIsMuxId(p, iObj) ) + return 0; + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjRefDec(p, pObj) ) + return 0; + return Gia_MuxDeref_rec( p, Gia_ObjFaninId0p(p, pObj) ) + + Gia_MuxDeref_rec( p, Gia_ObjFaninId1p(p, pObj) ) + + Gia_MuxDeref_rec( p, Gia_ObjFaninId2p(p, pObj) ) + 1; +} +int Gia_MuxDeref( Gia_Man_t * p, int iObj ) +{ + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + assert( Gia_ObjIsMuxId(p, iObj) ); + return Gia_MuxDeref_rec( p, Gia_ObjFaninId0p(p, pObj) ) + + Gia_MuxDeref_rec( p, Gia_ObjFaninId1p(p, pObj) ) + + Gia_MuxDeref_rec( p, Gia_ObjFaninId2p(p, pObj) ) + 1; +} +int Gia_MuxMffcSize( Gia_Man_t * p, int iObj ) +{ + int Count1, Count2; + if ( !Gia_ObjIsMuxId(p, iObj) ) + return 0; + Count1 = Gia_MuxDeref( p, iObj ); + Count2 = Gia_MuxRef( p, iObj ); + assert( Count1 == Count2 ); + return Count1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_MuxStructPrint_rec( Gia_Man_t * p, int iObj, int fFirst ) +{ + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + int iCtrl; + if ( !fFirst && (!Gia_ObjIsMuxId(p, iObj) || Gia_ObjRefNumId(p, iObj) > 0) ) + { +// printf( "%d", iObj ); + printf( "<%02d>", Gia_ObjLevelId(p, iObj) ); + return; + } + iCtrl = Gia_ObjFaninId2p(p, pObj); + printf( " [(" ); + if ( Gia_ObjIsMuxId(p, iCtrl) && Gia_ObjRefNumId(p, iCtrl) == 0 ) + Gia_MuxStructPrint_rec( p, iCtrl, 0 ); + else + { + printf( "%d", iCtrl ); + printf( "<%d>", Gia_ObjLevelId(p, iCtrl) ); + } + printf( ")" ); + if ( Gia_ObjFaninC2(p, pObj) ) + { + Gia_MuxStructPrint_rec( p, Gia_ObjFaninId0p(p, pObj), 0 ); + printf( "|" ); + Gia_MuxStructPrint_rec( p, Gia_ObjFaninId1p(p, pObj), 0 ); + printf( "]" ); + } + else + { + Gia_MuxStructPrint_rec( p, Gia_ObjFaninId1p(p, pObj), 0 ); + printf( "|" ); + Gia_MuxStructPrint_rec( p, Gia_ObjFaninId0p(p, pObj), 0 ); + printf( "]" ); + } +} +void Gia_MuxStructPrint( Gia_Man_t * p, int iObj ) +{ + int Count1, Count2; + assert( Gia_ObjIsMuxId(p, iObj) ); + Count1 = Gia_MuxDeref( p, iObj ); + Gia_MuxStructPrint_rec( p, iObj, 1 ); + Count2 = Gia_MuxRef( p, iObj ); + assert( Count1 == Count2 ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_MuxStructDump_rec( Gia_Man_t * p, int iObj, int fFirst, Vec_Str_t * vStr, int nDigitsId ) +{ + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + int iCtrl; + if ( !fFirst && (!Gia_ObjIsMuxId(p, iObj) || Gia_ObjRefNumId(p, iObj) > 0) ) + return; + iCtrl = Gia_ObjFaninId2p(p, pObj); + Vec_StrPush( vStr, '[' ); + Vec_StrPush( vStr, '(' ); + if ( Gia_ObjIsMuxId(p, iCtrl) && Gia_ObjRefNumId(p, iCtrl) == 0 ) + Gia_MuxStructDump_rec( p, iCtrl, 0, vStr, nDigitsId ); + else + Vec_StrPrintNumStar( vStr, iCtrl, nDigitsId ); + Vec_StrPush( vStr, ')' ); + if ( Gia_ObjFaninC2(p, pObj) ) + { + Gia_MuxStructDump_rec( p, Gia_ObjFaninId0p(p, pObj), 0, vStr, nDigitsId ); + Vec_StrPush( vStr, '|' ); + Gia_MuxStructDump_rec( p, Gia_ObjFaninId1p(p, pObj), 0, vStr, nDigitsId ); + Vec_StrPush( vStr, ']' ); + } + else + { + Gia_MuxStructDump_rec( p, Gia_ObjFaninId1p(p, pObj), 0, vStr, nDigitsId ); + Vec_StrPush( vStr, '|' ); + Gia_MuxStructDump_rec( p, Gia_ObjFaninId0p(p, pObj), 0, vStr, nDigitsId ); + Vec_StrPush( vStr, ']' ); + } +} +int Gia_MuxStructDump( Gia_Man_t * p, int iObj, Vec_Str_t * vStr, int nDigitsNum, int nDigitsId ) +{ + int Count1, Count2; + assert( Gia_ObjIsMuxId(p, iObj) ); + Count1 = Gia_MuxDeref( p, iObj ); + Vec_StrClear( vStr ); + Vec_StrPrintNumStar( vStr, Count1, nDigitsNum ); + Gia_MuxStructDump_rec( p, iObj, 1, vStr, nDigitsId ); + Vec_StrPush( vStr, '\0' ); + Count2 = Gia_MuxRef( p, iObj ); + assert( Count1 == Count2 ); + return Count1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManMuxCompare( char ** pp1, char ** pp2 ) +{ + int Diff = strcmp( *pp1, *pp2 ); + if ( Diff < 0 ) + return 1; + if ( Diff > 0) + return -1; + return 0; +} +int Gia_ManMuxCountOne( char * p ) +{ + int Count = 0; + for ( ; *p; p++ ) + Count += (*p == '['); + return Count; +} + +typedef struct Mux_Man_t_ Mux_Man_t; +struct Mux_Man_t_ +{ + Gia_Man_t * pGia; // manager + Abc_Nam_t * pNames; // hashing name into ID + Vec_Wec_t * vTops; // top nodes for each struct +}; + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Mux_Man_t * Mux_ManAlloc( Gia_Man_t * pGia ) +{ + Mux_Man_t * p; + p = ABC_CALLOC( Mux_Man_t, 1 ); + p->pGia = pGia; + p->pNames = Abc_NamStart( 10000, 50 ); + p->vTops = Vec_WecAlloc( 1000 ); + Vec_WecPushLevel( p->vTops ); + return p; +} +void Mux_ManFree( Mux_Man_t * p ) +{ + Abc_NamStop( p->pNames ); + Vec_WecFree( p->vTops ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManMuxProfile( Mux_Man_t * p, int fWidth ) +{ + int i, Entry, Counter, Total; + Vec_Int_t * vVec, * vCounts; + vCounts = Vec_IntStart( 1000 ); + if ( fWidth ) + { + Vec_WecForEachLevelStart( p->vTops, vVec, i, 1 ) + Vec_IntAddToEntry( vCounts, Abc_MinInt(Vec_IntSize(vVec), 999), 1 ); + } + else + { + for ( i = 1; i < Vec_WecSize(p->vTops); i++ ) + Vec_IntAddToEntry( vCounts, Abc_MinInt(atoi(Abc_NamStr(p->pNames, i)), 999), 1 ); + } + Total = Vec_IntCountPositive(vCounts); + if ( Total == 0 ) + return 0; + printf( "The distribution of MUX tree %s:\n", fWidth ? "widths" : "sizes" ); + Counter = 0; + Vec_IntForEachEntry( vCounts, Entry, i ) + { + if ( !Entry ) continue; + if ( ++Counter == 12 ) + printf( "\n" ), Counter = 0; + printf( " %d=%d", i, Entry ); + } + printf( "\nSummary: " ); + printf( "Max = %d ", Vec_IntFindMax(vCounts) ); + printf( "Ave = %.2f", 1.0*Vec_IntSum(vCounts)/Total ); + printf( "\n" ); + Vec_IntFree( vCounts ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManMuxProfiling( Gia_Man_t * p ) +{ + Mux_Man_t * pMan; + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + Vec_Str_t * vStr; + Vec_Int_t * vFans, * vVec; + int i, Counter, fFound, iStructId, nDigitsId; + abctime clk = Abc_Clock(); + + pNew = Gia_ManDupMuxes( p, 2 ); + nDigitsId = Abc_Base10Log( Gia_ManObjNum(pNew) ); + + pMan = Mux_ManAlloc( pNew ); + + Gia_ManLevelNum( pNew ); + Gia_ManCreateRefs( pNew ); + Gia_ManForEachCo( pNew, pObj, i ) + Gia_ObjRefFanin0Inc( pNew, pObj ); + + vStr = Vec_StrAlloc( 1000 ); + vFans = Gia_ManFirstFanouts( pNew ); + Gia_ManForEachMux( pNew, pObj, i ) + { + // skip MUXes in the middle of the tree (which have only one MUX fanout) + if ( Gia_ObjRefNumId(pNew, i) == 1 && Gia_ObjIsMuxId(pNew, Vec_IntEntry(vFans, i)) ) + continue; + // this node is the root of the MUX structure - create hash key + Counter = Gia_MuxStructDump( pNew, i, vStr, 3, nDigitsId ); + if ( Counter == 1 ) + continue; + iStructId = Abc_NamStrFindOrAdd( pMan->pNames, Vec_StrArray(vStr), &fFound ); + if ( !fFound ) + Vec_WecPushLevel( pMan->vTops ); + assert( Abc_NamObjNumMax(pMan->pNames) == Vec_WecSize(pMan->vTops) ); + Vec_IntPush( Vec_WecEntry(pMan->vTops, iStructId), i ); + } + Vec_StrFree( vStr ); + Vec_IntFree( vFans ); + + printf( "MUX structure profile for AIG \"%s\":\n", p->pName ); + printf( "Total MUXes = %d. Total trees = %d. Unique trees = %d. Memory = %.2f MB ", + Gia_ManMuxNum(pNew), Vec_WecSizeSize(pMan->vTops), Vec_WecSize(pMan->vTops)-1, + 1.0*Abc_NamMemUsed(pMan->pNames)/(1<<20) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + + if ( Gia_ManMuxProfile(pMan, 0) ) + { + Gia_ManMuxProfile( pMan, 1 ); + + // short the first ones + printf( "The first %d structures: \n", 10 ); + Vec_WecForEachLevelStartStop( pMan->vTops, vVec, i, 1, Abc_MinInt(Vec_WecSize(pMan->vTops), 10) ) + { + char * pTemp = Abc_NamStr(pMan->pNames, i); + printf( "%5d : ", i ); + printf( "Occur = %4d ", Vec_IntSize(vVec) ); + printf( "Size = %4d ", atoi(pTemp) ); + printf( "%s\n", pTemp ); + } + + // print trees for the first one + Counter = 0; + Vec_WecForEachLevelStart( pMan->vTops, vVec, i, 1 ) + { + char * pTemp = Abc_NamStr(pMan->pNames, i); + if ( Vec_IntSize(vVec) > 5 && atoi(pTemp) > 5 ) + { + int k, Entry; + printf( "For example, structure %d has %d MUXes and bit-width %d:\n", i, atoi(pTemp), Vec_IntSize(vVec) ); + Vec_IntForEachEntry( vVec, Entry, k ) + Gia_MuxStructPrint( pNew, Entry ); + if ( ++Counter == 5 ) + break; + } + } + } + + Mux_ManFree( pMan ); + Gia_ManStop( pNew ); +} + + +/**Function************************************************************* + + Synopsis [Compute one-level TFI/TFO structural signatures.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +// these are object/fanin/fanout attributes +// http://stackoverflow.com/questions/9907160/how-to-convert-enum-names-to-string-in-c +#define GIA_FOREACH_ITEM(ITEM) \ + ITEM(C0) \ + ITEM(PO) \ + ITEM(PI) \ + ITEM(FF) \ + ITEM(XOR) \ + ITEM(MUX) \ + ITEM(AND) \ + ITEM(iC0) \ + ITEM(iC1) \ + ITEM(iPI) \ + ITEM(iFF) \ + ITEM(iXOR) \ + ITEM(iMUX) \ + ITEM(iAND) \ + ITEM(iANDn) \ + ITEM(iANDp) \ + ITEM(oPO) \ + ITEM(oFF) \ + ITEM(oXOR) \ + ITEM(oMUXc) \ + ITEM(oMUXd) \ + ITEM(oAND) \ + ITEM(oANDn) \ + ITEM(oANDp) \ + ITEM(GIA_END) + +#define GENERATE_ENUM(ENUM) ENUM, +typedef enum { GIA_FOREACH_ITEM(GENERATE_ENUM) } Gia_ObjType_t; + +#define GENERATE_STRING(STRING) #STRING, +static const char * GIA_TYPE_STRINGS[] = { GIA_FOREACH_ITEM(GENERATE_STRING) }; + +void Gia_ManProfileStructuresTest( Gia_Man_t * p ) +{ + int i; + for ( i = 0; i < GIA_END; i++ ) + printf( "%d = %s\n", i, GIA_TYPE_STRINGS[i] ); +} + + + +// find object code +int Gia_ManEncodeObj( Gia_Man_t * p, int i ) +{ + Gia_Obj_t * pObj = Gia_ManObj( p, i ); + assert( !Gia_ObjIsRi(p, pObj) ); + if ( Gia_ObjIsConst0(pObj) ) + return C0; + if ( Gia_ObjIsPo(p, pObj) ) + return PO; + if ( Gia_ObjIsPi(p, pObj) ) + return PI; + if ( Gia_ObjIsCi(pObj) ) + return FF; + if ( Gia_ObjIsXor(pObj) ) + return XOR; + if ( Gia_ObjIsMux(p, pObj) ) + return MUX; + assert( Gia_ObjIsAnd(pObj) ); + return AND; +} +// find fanin code +int Gia_ManEncodeFanin( Gia_Man_t * p, int iLit ) +{ + Gia_Obj_t * pObj = Gia_ManObj( p, Abc_Lit2Var(iLit) ); + if ( Gia_ObjIsConst0(pObj) ) + return iC0; + if ( Gia_ObjIsPi(p, pObj) ) + return iPI; + if ( Gia_ObjIsCi(pObj) ) + return iFF; + if ( Gia_ObjIsXor(pObj) ) + return iXOR; + if ( Gia_ObjIsMux(p, pObj) ) + return iMUX; + assert( Gia_ObjIsAnd(pObj) ); + return iAND; +// if ( Abc_LitIsCompl(iLit) ) +// return iANDn; +// else +// return iANDp; +} +// find fanout code +Gia_ObjType_t Gia_ManEncodeFanout( Gia_Man_t * p, Gia_Obj_t * pObj, int i ) +{ +// int iLit; + if ( Gia_ObjIsPo(p, pObj) ) + return oPO; + if ( Gia_ObjIsCo(pObj) ) + return oFF; + if ( Gia_ObjIsXor(pObj) ) + return oXOR; + if ( Gia_ObjIsMux(p, pObj) ) + return i == 2 ? oMUXc : oMUXd; + assert( Gia_ObjIsAnd(pObj) ); + return oAND; +// iLit = i ? Gia_ObjFaninLit1p(p, pObj) : Gia_ObjFaninLit0p(p, pObj); +// if ( Abc_LitIsCompl(iLit) ) +// return oANDn; +// else +// return oANDp; +} + +void Gia_ManProfileCollect( Gia_Man_t * p, int i, Vec_Int_t * vCode, Vec_Int_t * vCodeOffsets, Vec_Int_t * vArray ) +{ + int k; + Vec_IntClear( vArray ); + for ( k = Vec_IntEntry(vCodeOffsets, i); k < Vec_IntEntry(vCodeOffsets, i+1); k++ ) + Vec_IntPush( vArray, Vec_IntEntry(vCode, k) ); +} + +void Gia_ManProfilePrintOne( Gia_Man_t * p, int i, Vec_Int_t * vArray ) +{ + Gia_Obj_t * pObj = Gia_ManObj( p, i ); + int k, nFanins, nFanouts; + if ( Gia_ObjIsRi(p, pObj) ) + return; + nFanins = Gia_ObjIsRo(p, pObj) ? 1 : Gia_ObjFaninNum(p, pObj); + nFanouts = Gia_ObjFanoutNum(p, pObj); + + printf( "%6d : ", i ); + for ( k = 0; k < nFanins; k++ ) + printf( " %5s", GIA_TYPE_STRINGS[Vec_IntEntry(vArray, k + 1)] ); + for ( ; k < 3; k++ ) + printf( " %5s", "" ); + printf( " ->" ); + printf( " %5s", GIA_TYPE_STRINGS[Vec_IntEntry(vArray, 0)] ); + printf( " ->" ); + if ( nFanouts > 0 ) + { + int Count = 1, Prev = Vec_IntEntry(vArray, 1 + nFanins); + for ( k = 1; k < nFanouts; k++ ) + { + if ( Prev != Vec_IntEntry(vArray, k + 1 + nFanins) ) + { + printf( " %d x %s", Count, GIA_TYPE_STRINGS[Prev] ); + Prev = Vec_IntEntry(vArray, k + 1 + nFanins); + Count = 0; + } + Count++; + } + printf( " %d x %s", Count, GIA_TYPE_STRINGS[Prev] ); + } + printf( "\n" ); +} + +Vec_Int_t * Gia_ManProfileHash( Gia_Man_t * p, Vec_Int_t * vCode, Vec_Int_t * vCodeOffsets ) +{ + Hsh_VecMan_t * pHash; + Vec_Int_t * vRes, * vArray; + Gia_Obj_t * pObj; + int i; + vRes = Vec_IntAlloc( Gia_ManObjNum(p) ); + pHash = Hsh_VecManStart( Gia_ManObjNum(p) ); + // add empty entry + vArray = Vec_IntAlloc( 100 ); + Hsh_VecManAdd( pHash, vArray ); + // iterate through the entries + Gia_ManForEachObj( p, pObj, i ) + { + Gia_ManProfileCollect( p, i, vCode, vCodeOffsets, vArray ); + Vec_IntPush( vRes, Hsh_VecManAdd( pHash, vArray ) ); + } + Hsh_VecManStop( pHash ); + Vec_IntFree( vArray ); + assert( Vec_IntSize(vRes) == Gia_ManObjNum(p) ); + return vRes; +} + + +void Gia_ManProfileStructuresInt( Gia_Man_t * p, int nLimit, int fVerbose ) +{ + Vec_Int_t * vRes, * vCount, * vFirst; + Vec_Int_t * vCode, * vCodeOffsets, * vArray; + Gia_Obj_t * pObj, * pFanout; + int i, k, nFanins, nFanouts, * pPerm, nClasses; + assert( p->pMuxes ); + Gia_ManStaticFanoutStart( p ); + // create fanout codes + vArray = Vec_IntAlloc( 100 ); + vCode = Vec_IntAlloc( 5 * Gia_ManObjNum(p) ); + vCodeOffsets = Vec_IntAlloc( Gia_ManObjNum(p) ); + Gia_ManForEachObj( p, pObj, i ) + { + Vec_IntPush( vCodeOffsets, Vec_IntSize(vCode) ); + if ( Gia_ObjIsRi(p, pObj) ) + continue; + nFanins = Gia_ObjFaninNum(p, pObj); + nFanouts = Gia_ObjFanoutNum(p, pObj); + Vec_IntPush( vCode, Gia_ManEncodeObj(p, i) ); + if ( nFanins == 3 ) + { + int iLit = Gia_ObjFaninLit2p(p, pObj); + Vec_IntPush( vCode, Gia_ManEncodeFanin(p, Abc_LitRegular(iLit)) ); + if ( Abc_LitIsCompl(iLit) ) + { + Vec_IntPush( vCode, Gia_ManEncodeFanin(p, Gia_ObjFaninLit0p(p, pObj)) ); + Vec_IntPush( vCode, Gia_ManEncodeFanin(p, Gia_ObjFaninLit1p(p, pObj)) ); + } + else + { + Vec_IntPush( vCode, Gia_ManEncodeFanin(p, Gia_ObjFaninLit1p(p, pObj)) ); + Vec_IntPush( vCode, Gia_ManEncodeFanin(p, Gia_ObjFaninLit0p(p, pObj)) ); + } + } + else if ( nFanins == 2 ) + { + int Code0 = Gia_ManEncodeFanin(p, Gia_ObjFaninLit0p(p, pObj)); + int Code1 = Gia_ManEncodeFanin(p, Gia_ObjFaninLit1p(p, pObj)); + Vec_IntPush( vCode, Code0 < Code1 ? Code0 : Code1 ); + Vec_IntPush( vCode, Code0 < Code1 ? Code1 : Code0 ); + } + else if ( nFanins == 1 ) + Vec_IntPush( vCode, Gia_ManEncodeFanin(p, Gia_ObjFaninLit0p(p, pObj)) ); + else if ( Gia_ObjIsRo(p, pObj) ) + Vec_IntPush( vCode, Gia_ManEncodeFanin(p, Gia_ObjFaninLit0p(p, Gia_ObjRoToRi(p, pObj))) ); + + // add fanouts + Vec_IntClear( vArray ); + Gia_ObjForEachFanoutStatic( p, pObj, pFanout, k ) + { + int Index = Gia_ObjWhatFanin( p, pFanout, pObj ); + Gia_ObjType_t Type = Gia_ManEncodeFanout( p, pFanout, Index ); + Vec_IntPush( vArray, Type ); + } + Vec_IntSort( vArray, 0 ); + Vec_IntAppend( vCode, vArray ); + } + assert( Vec_IntSize(vCodeOffsets) == Gia_ManObjNum(p) ); + Vec_IntPush( vCodeOffsets, Vec_IntSize(vCode) ); + // print the results + if ( fVerbose ) + { + printf( "Showing TFI/node/TFO structures for all nodes:\n" ); + Gia_ManForEachObj( p, pObj, i ) + { + Gia_ManProfileCollect( p, i, vCode, vCodeOffsets, vArray ); + Gia_ManProfilePrintOne( p, i, vArray ); + } + } + + // collect statistics + vRes = Gia_ManProfileHash( p, vCode, vCodeOffsets ); + //Vec_IntPrint( vRes ); + + // count how many times each class appears + nClasses = Vec_IntFindMax(vRes) + 1; + vCount = Vec_IntStart( nClasses ); + vFirst = Vec_IntStart( nClasses ); + Gia_ManForEachObj( p, pObj, i ) + { + int Entry = Vec_IntEntry( vRes, i ); + if ( Gia_ObjIsRi(p, pObj) ) + continue; + if ( Vec_IntEntry(vCount, Entry) == 0 ) + Vec_IntWriteEntry( vFirst, Entry, i ); + Vec_IntAddToEntry( vCount, Entry, -1 ); + } + // sort the counts + pPerm = Abc_MergeSortCost( Vec_IntArray(vCount), Vec_IntSize(vCount) ); + printf( "Showing TFI/node/TFO structures that appear more than %d times.\n", nLimit ); + for ( i = 0; i < nClasses-1; i++ ) + { + if ( nLimit > -Vec_IntEntry(vCount, pPerm[i]) ) + break; + printf( "%6d : ", i ); + printf( "%6d : ", pPerm[i] ); + printf( "Weight =%6d ", -Vec_IntEntry(vCount, pPerm[i]) ); + printf( "First obj =" ); + // print the object + Gia_ManProfileCollect( p, Vec_IntEntry(vFirst, pPerm[i]), vCode, vCodeOffsets, vArray ); + Gia_ManProfilePrintOne( p, Vec_IntEntry(vFirst, pPerm[i]), vArray ); + } + + // cleanup + ABC_FREE( pPerm ); + Vec_IntFree( vRes ); + Vec_IntFree( vCount ); + Vec_IntFree( vFirst ); + + Vec_IntFree( vArray ); + Vec_IntFree( vCode ); + Vec_IntFree( vCodeOffsets ); + Gia_ManStaticFanoutStop( p ); +} +void Gia_ManProfileStructures( Gia_Man_t * p, int nLimit, int fVerbose ) +{ + if ( p->pMuxes ) + Gia_ManProfileStructuresInt( p, nLimit, fVerbose ); + else + { + Gia_Man_t * pNew = Gia_ManDupMuxes( p, 2 ); + Gia_ManProfileStructuresInt( pNew, nLimit, fVerbose ); + Gia_ManStop( pNew ); + } +} + +/**Function************************************************************* + + Synopsis [Circuit restructuring.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManMarkTfi_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( !Gia_ObjIsAnd(pObj) ) + return; + Gia_ManMarkTfi_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ManMarkTfi_rec( p, Gia_ObjFanin1(pObj) ); +} +Vec_Int_t * Gia_ManFindSharedInputs( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj, * pObj2; int i, k, Value; + Vec_Int_t * vRes = Vec_IntStart( Gia_ManCiNum(p) ); + Gia_ManForEachCo( p, pObj, i ) + { + Gia_ManIncrementTravId( p ); + Gia_ManMarkTfi_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachCi( p, pObj2, k ) + if ( Gia_ObjIsTravIdCurrent(p, pObj2) ) + Vec_IntAddToEntry( vRes, k, 1 ); + } + k = 0; + Vec_IntForEachEntry( vRes, Value, i ) + if ( Value == Gia_ManCoNum(p) ) + Vec_IntWriteEntry( vRes, k++, i ); + Vec_IntShrink( vRes, k ); + //printf( "Found %d candidate inputs.\n", Vec_IntSize(vRes) ); + if ( Vec_IntSize(vRes) == 0 || Vec_IntSize(vRes) > 10 ) + Vec_IntFreeP(&vRes); + return vRes; +} +Vec_Wec_t * Gia_ManFindCofs( Gia_Man_t * p, Vec_Int_t * vRes, Gia_Man_t ** ppNew ) +{ + Gia_Obj_t * pObj; + Vec_Wec_t * vCofs = Vec_WecStart( 1 << Vec_IntSize(vRes) ); + int Value, i, m, nMints = 1 << Vec_IntSize(vRes); + Gia_Man_t * pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + Gia_ManHashAlloc( pNew ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + assert( Vec_IntSize(vRes) < Gia_ManCiNum(p) ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + for ( m = 0; m < nMints; m++ ) + { + Vec_Int_t * vLayer = Vec_WecEntry( vCofs, m ); + Vec_IntForEachEntry( vRes, Value, i ) + Gia_ManCi(p, Value)->Value = (unsigned)((m >> i) & 1); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + Vec_IntPush( vLayer, Gia_ObjFanin0Copy(pObj) ); + assert( Vec_IntSize(vLayer) == Gia_ManCoNum(p) ); + //printf( "%3d : ", m ); Vec_IntPrint( vLayer ); + } + if ( ppNew != NULL ) + *ppNew = pNew; + return vCofs; +} +Vec_Int_t * Gia_ManFindEquivClasses( Vec_Wec_t * vCofs ) +{ + Vec_Int_t * vVec; int i, k, Lev; + Vec_Int_t * vMap = Vec_IntAlloc( Vec_WecSize(vCofs) ); + Vec_Int_t * vUnique = Vec_IntAlloc( Vec_WecSize(vCofs) ); + Vec_WecForEachLevel( vCofs, vVec, i ) + { + Vec_IntForEachEntry( vUnique, Lev, k ) + if ( Vec_IntEqual(vVec, Vec_WecEntry(vCofs, Lev)) ) + break; + Vec_IntPush( vMap, k ); + if ( k == Vec_IntSize(vUnique) ) + Vec_IntPush( vUnique, i ); + } + //printf( "Found %d equiv clasess.\n", Vec_IntSize(vUnique) ); + //Vec_IntPrint( vUnique ); + Vec_IntFree( vUnique ); + assert( Vec_IntSize(vMap) == Vec_WecSize(vCofs) ); + //Vec_IntPrint( vMap ); + return vMap; +} +int Gia_ManFindMuxTree_rec( Gia_Man_t * pNew, int * pCtrl, int nCtrl, Vec_Int_t * vData, int Shift ) +{ + int iLit0, iLit1; + if ( nCtrl-- == 0 ) + return Vec_IntEntry( vData, Shift ); + iLit0 = Gia_ManFindMuxTree_rec( pNew, pCtrl, nCtrl, vData, Shift ); + iLit1 = Gia_ManFindMuxTree_rec( pNew, pCtrl, nCtrl, vData, Shift + (1<> i) & 1 ) + Abc_TtSetBit( pTruth, k ); + if ( nBits < 6 ) + pTruth[0] = Abc_Tt6Stretch( pTruth[0], Vec_IntSize(vIns) ); + Vec_IntPush( vBits, Kit_TruthToGia(pNew, (unsigned*)pTruth, Vec_IntSize(vIns), vMemory, vLeaves, 1) ); + //printf( "Bit %d : ", i ); Dau_DsdPrintFromTruth( pTruth, Vec_IntSize(vIns) ); + } + for ( i = 0; i < nValues; i++ ) + { + int Cof = Vec_IntFind(vMap, i); + assert( Cof >= 0 && Cof < Vec_WecSize(vCofs) ); + Vec_IntWriteEntry( vUsed, Cof, 1 ); + } + for ( i = 0; i < nOuts; i++ ) + { + Vec_Int_t * vLevel; + Vec_IntClear( vData ); + Vec_WecForEachLevel( vCofs, vLevel, k ) + if ( Vec_IntEntry(vUsed, k) ) + Vec_IntPush( vData, Vec_IntEntry(vLevel, i) ); + while ( Vec_IntSize(vData) < (1 << nBits) ) + Vec_IntPush( vData, 0 ); + assert( Vec_IntSize(vData) == (1 << nBits) ); + assert( Vec_IntSize(vBits) == nBits ); + Value = Gia_ManFindMuxTree_rec( pNew, Vec_IntArray(vBits), Vec_IntSize(vBits), vData, 0 ); + Gia_ManAppendCo( pNew, Value ); + } + ABC_FREE( pTruth ); + Vec_IntFree( vUsed ); + Vec_IntFree( vBits ); + Vec_IntFree( vData ); + Vec_IntFree( vLeaves ); + Vec_IntFree( vMemory ); +} +Gia_Man_t * Gia_ManCofStructure( Gia_Man_t * p ) +{ + Gia_Man_t * pNew = NULL; + Vec_Int_t * vIns = Gia_ManFindSharedInputs( p ); + Vec_Wec_t * vCfs = vIns ? Gia_ManFindCofs( p, vIns, &pNew ) : NULL; + Vec_Int_t * vMap = vCfs ? Gia_ManFindEquivClasses( vCfs ) : NULL; + if ( vMap && Abc_Base2Log(Vec_IntFindMax(vMap)+1) < Vec_IntSize(vIns) ) + { + Gia_Man_t * pTemp; + Gia_ManFindDerive( pNew, Gia_ManCoNum(p), vIns, vCfs, vMap ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + } + else + Gia_ManStopP( &pNew ); + Vec_WecFreeP( &vCfs ); + Vec_IntFreeP( &vMap ); + Vec_IntFreeP( &vIns ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaNewBdd.h b/yosys/abc/src/aig/gia/giaNewBdd.h new file mode 100644 index 00000000000..5f2b0702167 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaNewBdd.h @@ -0,0 +1,869 @@ +/**CFile**************************************************************** + + FileName [giaNewBdd.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Implementation of transduction method.] + + Author [Yukio Miyasaka] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 2023.] + + Revision [$Id: giaNewBdd.h,v 1.00 2023/05/10 00:00:00 Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__gia__giaNewBdd_h +#define ABC__aig__gia__giaNewBdd_h + +#include +#include +#include +#include +#include +#include + +ABC_NAMESPACE_CXX_HEADER_START + +namespace NewBdd { + + typedef unsigned short var; + typedef int bvar; + typedef unsigned lit; + typedef unsigned short ref; + typedef unsigned long long size; + typedef unsigned edge; + typedef unsigned uniq; + typedef unsigned cac; + static inline var VarMax() { return std::numeric_limits::max(); } + static inline bvar BvarMax() { return std::numeric_limits::max(); } + static inline lit LitMax() { return std::numeric_limits::max(); } + static inline ref RefMax() { return std::numeric_limits::max(); } + static inline size SizeMax() { return std::numeric_limits::max(); } + static inline uniq UniqHash(lit Arg0, lit Arg1) { return Arg0 + 4256249 * Arg1; } + static inline cac CacHash(lit Arg0, lit Arg1) { return Arg0 + 4256249 * Arg1; } + + static inline void fatal_error(const char* message) { + std::cerr << message << std::endl; + std::abort(); + } + + class Cache { + private: + cac nSize; + cac nMax; + cac Mask; + size nLookups; + size nHits; + size nThold; + double HitRate; + int nVerbose; + std::vector vCache; + + public: + Cache(int nCacheSizeLog, int nCacheMaxLog, int nVerbose): nVerbose(nVerbose) { + if(nCacheMaxLog < nCacheSizeLog) + fatal_error("nCacheMax must not be smaller than nCacheSize"); + nMax = (cac)1 << nCacheMaxLog; + if(!(nMax << 1)) + fatal_error("Memout (nCacheMax) in init"); + nSize = (cac)1 << nCacheSizeLog; + if(nVerbose) + std::cout << "Allocating " << nSize << " cache entries" << std::endl; + vCache.resize(nSize * 3); + Mask = nSize - 1; + nLookups = 0; + nHits = 0; + nThold = (nSize == nMax)? SizeMax(): nSize; + HitRate = 1; + } + ~Cache() { + if(nVerbose) + std::cout << "Free " << nSize << " cache entries" << std::endl; + } + inline lit Lookup(lit x, lit y) { + nLookups++; + if(nLookups > nThold) { + double NewHitRate = (double)nHits / nLookups; + if(nVerbose >= 2) + std::cout << "Cache Hits: " << std::setw(10) << nHits << ", " + << "Lookups: " << std::setw(10) << nLookups << ", " + << "Rate: " << std::setw(10) << NewHitRate + << std::endl; + if(NewHitRate > HitRate) + Resize(); + if(nSize == nMax) + nThold = SizeMax(); + else { + nThold <<= 1; + if(!nThold) + nThold = SizeMax(); + } + HitRate = NewHitRate; + } + cac i = (CacHash(x, y) & Mask) * 3; + if(vCache[i] == x && vCache[i + 1] == y) { + if(nVerbose >= 3) + std::cout << "Cache hit: " + << "x = " << std::setw(10) << x << ", " + << "y = " << std::setw(10) << y << ", " + << "z = " << std::setw(10) << vCache[i + 2] << ", " + << "hash = " << std::hex << (CacHash(x, y) & Mask) << std::dec + << std::endl; + nHits++; + return vCache[i + 2]; + } + return LitMax(); + } + inline void Insert(lit x, lit y, lit z) { + cac i = (CacHash(x, y) & Mask) * 3; + vCache[i] = x; + vCache[i + 1] = y; + vCache[i + 2] = z; + if(nVerbose >= 3) + std::cout << "Cache ent: " + << "x = " << std::setw(10) << x << ", " + << "y = " << std::setw(10) << y << ", " + << "z = " << std::setw(10) << z << ", " + << "hash = " << std::hex << (CacHash(x, y) & Mask) << std::dec + << std::endl; + } + inline void Clear() { + std::fill(vCache.begin(), vCache.end(), 0); + } + void Resize() { + cac nSizeOld = nSize; + nSize <<= 1; + if(nVerbose >= 2) + std::cout << "Reallocating " << nSize << " cache entries" << std::endl; + vCache.resize(nSize * 3); + Mask = nSize - 1; + for(cac j = 0; j < nSizeOld; j++) { + cac i = j * 3; + if(vCache[i] || vCache[i + 1]) { + cac hash = (CacHash(vCache[i], vCache[i + 1]) & Mask) * 3; + vCache[hash] = vCache[i]; + vCache[hash + 1] = vCache[i + 1]; + vCache[hash + 2] = vCache[i + 2]; + if(nVerbose >= 3) + std::cout << "Cache mov: " + << "x = " << std::setw(10) << vCache[i] << ", " + << "y = " << std::setw(10) << vCache[i + 1] << ", " + << "z = " << std::setw(10) << vCache[i + 2] << ", " + << "hash = " << std::hex << (CacHash(vCache[i], vCache[i + 1]) & Mask) << std::dec + << std::endl; + } + } + } + }; + + struct Param { + int nObjsAllocLog; + int nObjsMaxLog; + int nUniqueSizeLog; + double UniqueDensity; + int nCacheSizeLog; + int nCacheMaxLog; + int nCacheVerbose; + bool fCountOnes; + int nGbc; + bvar nReo; + double MaxGrowth; + bool fReoVerbose; + int nVerbose; + std::vector *pVar2Level; + Param() { + nObjsAllocLog = 20; + nObjsMaxLog = 25; + nUniqueSizeLog = 10; + UniqueDensity = 4; + nCacheSizeLog = 15; + nCacheMaxLog = 20; + nCacheVerbose = 0; + fCountOnes = false; + nGbc = 0; + nReo = BvarMax(); + MaxGrowth = 1.2; + fReoVerbose = false; + nVerbose = 0; + pVar2Level = NULL; + } + }; + + class Man { + private: + var nVars; + bvar nObjs; + bvar nObjsAlloc; + bvar nObjsMax; + bvar RemovedHead; + int nGbc; + bvar nReo; + double MaxGrowth; + bool fReoVerbose; + int nVerbose; + std::vector vVars; + std::vector Var2Level; + std::vector Level2Var; + std::vector vObjs; + std::vector vNexts; + std::vector vMarks; + std::vector vRefs; + std::vector vEdges; + std::vector vOneCounts; + std::vector vUniqueMasks; + std::vector vUniqueCounts; + std::vector vUniqueTholds; + std::vector > vvUnique; + Cache *cache; + + public: + inline lit Bvar2Lit(bvar a) const { return (lit)a << 1; } + inline lit Bvar2Lit(bvar a, bool c) const { return ((lit)a << 1) ^ (lit)c; } + inline bvar Lit2Bvar(lit x) const { return (bvar)(x >> 1); } + inline var VarOfBvar(bvar a) const { return vVars[a]; } + inline lit ThenOfBvar(bvar a) const { return vObjs[Bvar2Lit(a)]; } + inline lit ElseOfBvar(bvar a) const { return vObjs[Bvar2Lit(a, true)]; } + inline ref RefOfBvar(bvar a) const { return vRefs[a]; } + inline lit Const0() const { return (lit)0; } + inline lit Const1() const { return (lit)1; } + inline bool IsConst0(lit x) const { return x == Const0(); } + inline bool IsConst1(lit x) const { return x == Const1(); } + inline lit IthVar(var v) const { return Bvar2Lit((bvar)v + 1); } + inline lit LitRegular(lit x) const { return x & ~(lit)1; } + inline lit LitIrregular(lit x) const { return x | (lit)1; } + inline lit LitNot(lit x) const { return x ^ (lit)1; } + inline lit LitNotCond(lit x, bool c) const { return x ^ (lit)c; } + inline bool LitIsCompl(lit x) const { return x & (lit)1; } + inline bool LitIsEq(lit x, lit y) const { return x == y; } + inline var Var(lit x) const { return vVars[Lit2Bvar(x)]; } + inline var Level(lit x) const { return Var2Level[Var(x)]; } + inline lit Then(lit x) const { return LitNotCond(vObjs[LitRegular(x)], LitIsCompl(x)); } + inline lit Else(lit x) const { return LitNotCond(vObjs[LitIrregular(x)], LitIsCompl(x)); } + inline ref Ref(lit x) const { return vRefs[Lit2Bvar(x)]; } + inline double OneCount(lit x) const { + if(vOneCounts.empty()) + fatal_error("fCountOnes was not set"); + if(LitIsCompl(x)) + return std::pow(2.0, nVars) - vOneCounts[Lit2Bvar(x)]; + return vOneCounts[Lit2Bvar(x)]; + } + + public: + inline void IncRef(lit x) { if(!vRefs.empty() && Ref(x) != RefMax()) vRefs[Lit2Bvar(x)]++; } + inline void DecRef(lit x) { if(!vRefs.empty() && Ref(x) != RefMax()) vRefs[Lit2Bvar(x)]--; } + + private: + inline bool Mark(lit x) const { return vMarks[Lit2Bvar(x)]; } + inline edge Edge(lit x) const { return vEdges[Lit2Bvar(x)]; } + inline void SetMark(lit x) { vMarks[Lit2Bvar(x)] = true; } + inline void ResetMark(lit x) { vMarks[Lit2Bvar(x)] = false; } + inline void IncEdge(lit x) { vEdges[Lit2Bvar(x)]++; } + inline void DecEdge(lit x) { vEdges[Lit2Bvar(x)]--; } + inline bool MarkOfBvar(bvar a) const { return vMarks[a]; } + inline edge EdgeOfBvar(bvar a) const { return vEdges[a]; } + inline void SetVarOfBvar(bvar a, var v) { vVars[a] = v; } + inline void SetThenOfBvar(bvar a, lit x) { vObjs[Bvar2Lit(a)] = x; } + inline void SetElseOfBvar(bvar a, lit x) { vObjs[Bvar2Lit(a, true)] = x; } + inline void SetMarkOfBvar(bvar a) { vMarks[a] = true; } + inline void ResetMarkOfBvar(bvar a) { vMarks[a] = false; } + inline void RemoveBvar(bvar a) { + var v = VarOfBvar(a); + SetVarOfBvar(a, VarMax()); + std::vector::iterator q = vvUnique[v].begin() + (UniqHash(ThenOfBvar(a), ElseOfBvar(a)) & vUniqueMasks[v]); + for(; *q; q = vNexts.begin() + *q) + if(*q == a) + break; + bvar next = vNexts[*q]; + vNexts[*q] = RemovedHead; + RemovedHead = *q; + *q = next; + vUniqueCounts[v]--; + } + + private: + void SetMark_rec(lit x) { + if(x < 2 || Mark(x)) + return; + SetMark(x); + SetMark_rec(Then(x)); + SetMark_rec(Else(x)); + } + void ResetMark_rec(lit x) { + if(x < 2 || !Mark(x)) + return; + ResetMark(x); + ResetMark_rec(Then(x)); + ResetMark_rec(Else(x)); + } + bvar CountNodes_rec(lit x) { + if(x < 2 || Mark(x)) + return 0; + SetMark(x); + return 1 + CountNodes_rec(Then(x)) + CountNodes_rec(Else(x)); + } + void CountEdges_rec(lit x) { + if(x < 2) + return; + IncEdge(x); + if(Mark(x)) + return; + SetMark(x); + CountEdges_rec(Then(x)); + CountEdges_rec(Else(x)); + } + void CountEdges() { + vEdges.resize(nObjsAlloc); + for(bvar a = (bvar)nVars + 1; a < nObjs; a++) + if(RefOfBvar(a)) + CountEdges_rec(Bvar2Lit(a)); + for(bvar a = 1; a <= (bvar)nVars; a++) + vEdges[a]++; + for(bvar a = (bvar)nVars + 1; a < nObjs; a++) + if(RefOfBvar(a)) + ResetMark_rec(Bvar2Lit(a)); + } + + public: + bool Resize() { + if(nObjsAlloc == nObjsMax) + return false; + lit nObjsAllocLit = (lit)nObjsAlloc << 1; + if(nObjsAllocLit > (lit)BvarMax()) + nObjsAlloc = BvarMax(); + else + nObjsAlloc = (bvar)nObjsAllocLit; + if(nVerbose >= 2) + std::cout << "Reallocating " << nObjsAlloc << " nodes" << std::endl; + vVars.resize(nObjsAlloc); + vObjs.resize((lit)nObjsAlloc * 2); + vNexts.resize(nObjsAlloc); + vMarks.resize(nObjsAlloc); + if(!vRefs.empty()) + vRefs.resize(nObjsAlloc); + if(!vEdges.empty()) + vEdges.resize(nObjsAlloc); + if(!vOneCounts.empty()) + vOneCounts.resize(nObjsAlloc); + return true; + } + void ResizeUnique(var v) { + uniq nUniqueSize, nUniqueSizeOld; + nUniqueSize = nUniqueSizeOld = vvUnique[v].size(); + nUniqueSize <<= 1; + if(!nUniqueSize) { + vUniqueTholds[v] = BvarMax(); + return; + } + if(nVerbose >= 2) + std::cout << "Reallocating " << nUniqueSize << " unique table entries for Var " << v << std::endl; + vvUnique[v].resize(nUniqueSize); + vUniqueMasks[v] = nUniqueSize - 1; + for(uniq i = 0; i < nUniqueSizeOld; i++) { + std::vector::iterator q, tail, tail1, tail2; + q = tail1 = vvUnique[v].begin() + i; + tail2 = q + nUniqueSizeOld; + while(*q) { + uniq hash = UniqHash(ThenOfBvar(*q), ElseOfBvar(*q)) & vUniqueMasks[v]; + if(hash == i) + tail = tail1; + else + tail = tail2; + if(tail != q) + *tail = *q, *q = 0; + q = vNexts.begin() + *tail; + if(tail == tail1) + tail1 = q; + else + tail2 = q; + } + } + vUniqueTholds[v] <<= 1; + if((lit)vUniqueTholds[v] > (lit)BvarMax()) + vUniqueTholds[v] = BvarMax(); + } + bool Gbc() { + if(nVerbose >= 2) + std::cout << "Garbage collect" << std::endl; + if(!vEdges.empty()) { + for(bvar a = (bvar)nVars + 1; a < nObjs; a++) + if(!EdgeOfBvar(a) && VarOfBvar(a) != VarMax()) + RemoveBvar(a); + } else { + for(bvar a = (bvar)nVars + 1; a < nObjs; a++) + if(RefOfBvar(a)) + SetMark_rec(Bvar2Lit(a)); + for(bvar a = (bvar)nVars + 1; a < nObjs; a++) + if(!MarkOfBvar(a) && VarOfBvar(a) != VarMax()) + RemoveBvar(a); + for(bvar a = (bvar)nVars + 1; a < nObjs; a++) + if(RefOfBvar(a)) + ResetMark_rec(Bvar2Lit(a)); + } + cache->Clear(); + return RemovedHead; + } + + private: + inline lit UniqueCreateInt(var v, lit x1, lit x0) { + std::vector::iterator p, q; + p = q = vvUnique[v].begin() + (UniqHash(x1, x0) & vUniqueMasks[v]); + for(; *q; q = vNexts.begin() + *q) + if(VarOfBvar(*q) == v && ThenOfBvar(*q) == x1 && ElseOfBvar(*q) == x0) + return Bvar2Lit(*q); + bvar next = *p; + if(nObjs < nObjsAlloc) + *p = nObjs++; + else if(RemovedHead) + *p = RemovedHead, RemovedHead = vNexts[*p]; + else + return LitMax(); + SetVarOfBvar(*p, v); + SetThenOfBvar(*p, x1); + SetElseOfBvar(*p, x0); + vNexts[*p] = next; + if(!vOneCounts.empty()) + vOneCounts[*p] = OneCount(x1) / 2 + OneCount(x0) / 2; + if(nVerbose >= 3) { + std::cout << "Create node " << std::setw(10) << *p << ": " + << "Var = " << std::setw(6) << v << ", " + << "Then = " << std::setw(10) << x1 << ", " + << "Else = " << std::setw(10) << x0; + if(!vOneCounts.empty()) + std::cout << ", Ones = " << std::setw(10) << vOneCounts[*q]; + std::cout << std::endl; + } + vUniqueCounts[v]++; + if(vUniqueCounts[v] > vUniqueTholds[v]) { + bvar a = *p; + ResizeUnique(v); + return Bvar2Lit(a); + } + return Bvar2Lit(*p); + } + inline lit UniqueCreate(var v, lit x1, lit x0) { + if(x1 == x0) + return x1; + lit x; + while(true) { + if(!LitIsCompl(x0)) + x = UniqueCreateInt(v, x1, x0); + else + x = UniqueCreateInt(v, LitNot(x1), LitNot(x0)); + if(x == LitMax()) { + bool fRemoved = false; + if(nGbc > 1) + fRemoved = Gbc(); + if(!Resize() && !fRemoved && (nGbc != 1 || !Gbc())) + fatal_error("Memout (node)"); + } else + break; + } + return LitIsCompl(x0)? LitNot(x): x; + } + lit And_rec(lit x, lit y) { + if(x == 0 || y == 1) + return x; + if(x == 1 || y == 0) + return y; + if(Lit2Bvar(x) == Lit2Bvar(y)) + return (x == y)? x: 0; + if(x > y) + std::swap(x, y); + lit z = cache->Lookup(x, y); + if(z != LitMax()) + return z; + var v; + lit x0, x1, y0, y1; + if(Level(x) < Level(y)) + v = Var(x), x1 = Then(x), x0 = Else(x), y0 = y1 = y; + else if(Level(x) > Level(y)) + v = Var(y), x0 = x1 = x, y1 = Then(y), y0 = Else(y); + else + v = Var(x), x1 = Then(x), x0 = Else(x), y1 = Then(y), y0 = Else(y); + lit z1 = And_rec(x1, y1); + IncRef(z1); + lit z0 = And_rec(x0, y0); + IncRef(z0); + z = UniqueCreate(v, z1, z0); + DecRef(z1); + DecRef(z0); + cache->Insert(x, y, z); + return z; + } + + private: + bvar Swap(var i) { + var v1 = Level2Var[i]; + var v2 = Level2Var[i + 1]; + bvar f = 0; + bvar diff = 0; + for(std::vector::iterator p = vvUnique[v1].begin(); p != vvUnique[v1].end(); p++) { + std::vector::iterator q = p; + while(*q) { + if(!EdgeOfBvar(*q)) { + SetVarOfBvar(*q, VarMax()); + bvar next = vNexts[*q]; + vNexts[*q] = RemovedHead; + RemovedHead = *q; + *q = next; + vUniqueCounts[v1]--; + continue; + } + lit f1 = ThenOfBvar(*q); + lit f0 = ElseOfBvar(*q); + if(Var(f1) == v2 || Var(f0) == v2) { + DecEdge(f1); + if(Var(f1) == v2 && !Edge(f1)) + DecEdge(Then(f1)), DecEdge(Else(f1)), diff--; + DecEdge(f0); + if(Var(f0) == v2 && !Edge(f0)) + DecEdge(Then(f0)), DecEdge(Else(f0)), diff--; + bvar next = vNexts[*q]; + vNexts[*q] = f; + f = *q; + *q = next; + vUniqueCounts[v1]--; + continue; + } + q = vNexts.begin() + *q; + } + } + while(f) { + lit f1 = ThenOfBvar(f); + lit f0 = ElseOfBvar(f); + lit f00, f01, f10, f11; + if(Var(f1) == v2) + f11 = Then(f1), f10 = Else(f1); + else + f10 = f11 = f1; + if(Var(f0) == v2) + f01 = Then(f0), f00 = Else(f0); + else + f00 = f01 = f0; + if(f11 == f01) + f1 = f11; + else { + f1 = UniqueCreate(v1, f11, f01); + if(!Edge(f1)) + IncEdge(f11), IncEdge(f01), diff++; + } + IncEdge(f1); + IncRef(f1); + if(f10 == f00) + f0 = f10; + else { + f0 = UniqueCreate(v1, f10, f00); + if(!Edge(f0)) + IncEdge(f10), IncEdge(f00), diff++; + } + IncEdge(f0); + DecRef(f1); + SetVarOfBvar(f, v2); + SetThenOfBvar(f, f1); + SetElseOfBvar(f, f0); + std::vector::iterator q = vvUnique[v2].begin() + (UniqHash(f1, f0) & vUniqueMasks[v2]); + lit next = vNexts[f]; + vNexts[f] = *q; + *q = f; + vUniqueCounts[v2]++; + f = next; + } + Var2Level[v1] = i + 1; + Var2Level[v2] = i; + Level2Var[i] = v2; + Level2Var[i + 1] = v1; + return diff; + } + void Sift() { + bvar count = CountNodes(); + std::vector sift_order(nVars); + for(var v = 0; v < nVars; v++) + sift_order[v] = v; + for(var i = 0; i < nVars; i++) { + var max_j = i; + for(var j = i + 1; j < nVars; j++) + if(vUniqueCounts[sift_order[j]] > vUniqueCounts[sift_order[max_j]]) + max_j = j; + if(max_j != i) + std::swap(sift_order[max_j], sift_order[i]); + } + for(var v = 0; v < nVars; v++) { + bvar lev = Var2Level[sift_order[v]]; + bool UpFirst = lev < (bvar)(nVars / 2); + bvar min_lev = lev; + bvar min_diff = 0; + bvar diff = 0; + bvar thold = count * (MaxGrowth - 1); + if(fReoVerbose) + std::cout << "Sift " << sift_order[v] << " : Level = " << lev << " Count = " << count << " Thold = " << thold << std::endl; + if(UpFirst) { + lev--; + for(; lev >= 0; lev--) { + diff += Swap(lev); + if(fReoVerbose) + std::cout << "\tSwap " << lev << " : Diff = " << diff << " Thold = " << thold << std::endl; + if(diff < min_diff) + min_lev = lev, min_diff = diff, thold = (count + diff) * (MaxGrowth - 1); + else if(diff > thold) { + lev--; + break; + } + } + lev++; + } + for(; lev < (bvar)nVars - 1; lev++) { + diff += Swap(lev); + if(fReoVerbose) + std::cout << "\tSwap " << lev << " : Diff = " << diff << " Thold = " << thold << std::endl; + if(diff <= min_diff) + min_lev = lev + 1, min_diff = diff, thold = (count + diff) * (MaxGrowth - 1); + else if(diff > thold) { + lev++; + break; + } + } + lev--; + if(UpFirst) { + for(; lev >= min_lev; lev--) { + diff += Swap(lev); + if(fReoVerbose) + std::cout << "\tSwap " << lev << " : Diff = " << diff << " Thold = " << thold << std::endl; + } + } else { + for(; lev >= 0; lev--) { + diff += Swap(lev); + if(fReoVerbose) + std::cout << "\tSwap " << lev << " : Diff = " << diff << " Thold = " << thold << std::endl; + if(diff <= min_diff) + min_lev = lev, min_diff = diff, thold = (count + diff) * (MaxGrowth - 1); + else if(diff > thold) { + lev--; + break; + } + } + lev++; + for(; lev < min_lev; lev++) { + diff += Swap(lev); + if(fReoVerbose) + std::cout << "\tSwap " << lev << " : Diff = " << diff << " Thold = " << thold << std::endl; + } + } + count += min_diff; + if(fReoVerbose) + std::cout << "Sifted " << sift_order[v] << " : Level = " << min_lev << " Count = " << count << " Thold = " << thold << std::endl; + } + } + + public: + Man(int nVars_, Param p) { + nVerbose = p.nVerbose; + // parameter sanity check + if(p.nObjsMaxLog < p.nObjsAllocLog) + fatal_error("nObjsMax must not be smaller than nObjsAlloc"); + if(nVars_ >= (int)VarMax()) + fatal_error("Memout (nVars) in init"); + nVars = nVars_; + lit nObjsMaxLit = (lit)1 << p.nObjsMaxLog; + if(!nObjsMaxLit) + fatal_error("Memout (nObjsMax) in init"); + if(nObjsMaxLit > (lit)BvarMax()) + nObjsMax = BvarMax(); + else + nObjsMax = (bvar)nObjsMaxLit; + lit nObjsAllocLit = (lit)1 << p.nObjsAllocLog; + if(!nObjsAllocLit) + fatal_error("Memout (nObjsAlloc) in init"); + if(nObjsAllocLit > (lit)BvarMax()) + nObjsAlloc = BvarMax(); + else + nObjsAlloc = (bvar)nObjsAllocLit; + if(nObjsAlloc <= (bvar)nVars) + fatal_error("nObjsAlloc must be larger than nVars"); + uniq nUniqueSize = (uniq)1 << p.nUniqueSizeLog; + if(!nUniqueSize) + fatal_error("Memout (nUniqueSize) in init"); + // allocation + if(nVerbose) + std::cout << "Allocating " << nObjsAlloc << " nodes and " << nVars << " x " << nUniqueSize << " unique table entries" << std::endl; + vVars.resize(nObjsAlloc); + vObjs.resize((lit)nObjsAlloc * 2); + vNexts.resize(nObjsAlloc); + vMarks.resize(nObjsAlloc); + vvUnique.resize(nVars); + vUniqueMasks.resize(nVars); + vUniqueCounts.resize(nVars); + vUniqueTholds.resize(nVars); + for(var v = 0; v < nVars; v++) { + vvUnique[v].resize(nUniqueSize); + vUniqueMasks[v] = nUniqueSize - 1; + if((lit)(nUniqueSize * p.UniqueDensity) > (lit)BvarMax()) + vUniqueTholds[v] = BvarMax(); + else + vUniqueTholds[v] = (bvar)(nUniqueSize * p.UniqueDensity); + } + if(p.fCountOnes) { + if(nVars > 1023) + fatal_error("nVars must be less than 1024 to count ones"); + vOneCounts.resize(nObjsAlloc); + } + // set up cache + cache = new Cache(p.nCacheSizeLog, p.nCacheMaxLog, p.nCacheVerbose); + // create nodes for variables + nObjs = 1; + vVars[0] = VarMax(); + for(var v = 0; v < nVars; v++) + UniqueCreateInt(v, 1, 0); + // set up variable order + Var2Level.resize(nVars); + Level2Var.resize(nVars); + for(var v = 0; v < nVars; v++) { + if(p.pVar2Level) + Var2Level[v] = (*p.pVar2Level)[v]; + else + Var2Level[v] = v; + Level2Var[Var2Level[v]] = v; + } + // set other parameters + RemovedHead = 0; + nGbc = p.nGbc; + nReo = p.nReo; + MaxGrowth = p.MaxGrowth; + fReoVerbose = p.fReoVerbose; + if(nGbc || nReo != BvarMax()) + vRefs.resize(nObjsAlloc); + } + ~Man() { + if(nVerbose) { + std::cout << "Free " << nObjsAlloc << " nodes (" << nObjs << " live nodes)" << std::endl; + std::cout << "Free {"; + std::string delim; + for(var v = 0; v < nVars; v++) { + std::cout << delim << vvUnique[v].size(); + delim = ", "; + } + std::cout << "} unique table entries" << std::endl; + if(!vRefs.empty()) + std::cout << "Free " << vRefs.size() << " refs" << std::endl; + } + delete cache; + } + void Reorder() { + if(nVerbose >= 2) + std::cout << "Reorder" << std::endl; + int nGbc_ = nGbc; + nGbc = 0; + CountEdges(); + Sift(); + vEdges.clear(); + cache->Clear(); + nGbc = nGbc_; + } + inline lit And(lit x, lit y) { + if(nObjs > nReo) { + Reorder(); + while(nReo < nObjs) { + nReo <<= 1; + if((lit)nReo > (lit)BvarMax()) + nReo = BvarMax(); + } + } + return And_rec(x, y); + } + inline lit Or(lit x, lit y) { + return LitNot(And(LitNot(x), LitNot(y))); + } + + public: + void SetRef(std::vector const &vLits) { + vRefs.clear(); + vRefs.resize(nObjsAlloc); + for(size_t i = 0; i < vLits.size(); i++) + IncRef(vLits[i]); + } + void RemoveRefIfUnused() { + if(!nGbc && nReo == BvarMax()) + vRefs.clear(); + } + void TurnOnReo(int nReo_ = 0, std::vector const *vLits = NULL) { + if(nReo_) + nReo = nReo_; + else + nReo = nObjs << 1; + if((lit)nReo > (lit)BvarMax()) + nReo = BvarMax(); + if(vRefs.empty()) { + if(vLits) + SetRef(*vLits); + else + vRefs.resize(nObjsAlloc); + } + } + void TurnOffReo() { + nReo = BvarMax(); + } + var GetNumVars() const { + return nVars; + } + void GetOrdering(std::vector &Var2Level_) { + Var2Level_.resize(nVars); + for(var v = 0; v < nVars; v++) + Var2Level_[v] = Var2Level[v]; + } + bvar CountNodes() { + bvar count = 1; + if(!vEdges.empty()) { + for(bvar a = 1; a < nObjs; a++) + if(EdgeOfBvar(a)) + count++; + return count; + } + for(bvar a = 1; a <= (bvar)nVars; a++) { + count++; + SetMarkOfBvar(a); + } + for(bvar a = (bvar)nVars + 1; a < nObjs; a++) + if(RefOfBvar(a)) + count += CountNodes_rec(Bvar2Lit(a)); + for(bvar a = 1; a <= (bvar)nVars; a++) + ResetMarkOfBvar(a); + for(bvar a = (bvar)nVars + 1; a < nObjs; a++) + if(RefOfBvar(a)) + ResetMark_rec(Bvar2Lit(a)); + return count; + } + bvar CountNodes(std::vector const &vLits) { + bvar count = 1; + for(size_t i = 0; i < vLits.size(); i++) + count += CountNodes_rec(vLits[i]); + for(size_t i = 0; i < vLits.size(); i++) + ResetMark_rec(vLits[i]); + return count; + } + void PrintStats() { + bvar nRemoved = 0; + bvar a = RemovedHead; + while(a) + a = vNexts[a], nRemoved++; + bvar nLive = 1; + for(var v = 0; v < nVars; v++) + nLive += vUniqueCounts[v]; + std::cout << "ref: " << std::setw(10) << (vRefs.empty()? 0: CountNodes()) << ", " + << "used: " << std::setw(10) << nObjs << ", " + << "live: " << std::setw(10) << nLive << ", " + << "dead: " << std::setw(10) << nRemoved << ", " + << "alloc: " << std::setw(10) << nObjsAlloc + << std::endl; + } + }; + +} + +ABC_NAMESPACE_CXX_HEADER_END + +#endif diff --git a/yosys/abc/src/aig/gia/giaNewTt.h b/yosys/abc/src/aig/gia/giaNewTt.h new file mode 100644 index 00000000000..e5aaabf37a9 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaNewTt.h @@ -0,0 +1,292 @@ +/**CFile**************************************************************** + + FileName [giaNewTt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Implementation of transduction method.] + + Author [Yukio Miyasaka] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 2023.] + + Revision [$Id: giaNewTt.h,v 1.00 2023/05/10 00:00:00 Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__gia__giaNewTt_h +#define ABC__aig__gia__giaNewTt_h + +#include +#include +#include +#include +#include +#include + +ABC_NAMESPACE_CXX_HEADER_START + +namespace NewTt { + + typedef int bvar; + typedef unsigned lit; + typedef unsigned short ref; + typedef unsigned long long size; + + static inline bvar BvarMax() { return std::numeric_limits::max(); } + static inline lit LitMax() { return std::numeric_limits::max(); } + static inline ref RefMax() { return std::numeric_limits::max(); } + static inline size SizeMax() { return std::numeric_limits::max(); } + + static void fatal_error(const char* message) { + std::cerr << message << std::endl; + std::abort(); + } + + struct Param { + int nObjsAllocLog; + int nObjsMaxLog; + int nVerbose; + bool fCountOnes; + int nGbc; + int nReo; // dummy + std::vector *pVar2Level; // dummy + Param() { + nObjsAllocLog = 15; + nObjsMaxLog = 20; + nVerbose = 0; + fCountOnes = false; + nGbc = 0; + nReo = BvarMax(); + } + }; + + class Man { + private: + typedef unsigned long long word; + typedef std::bitset<64> bsw; + static inline int ww() { return 64; } // word width + static inline int lww() { return 6; } // log word width + static inline word one() {return 0xffffffffffffffffull; } + static inline word vars(int i) { + static const word vars[] = {0xaaaaaaaaaaaaaaaaull, + 0xccccccccccccccccull, + 0xf0f0f0f0f0f0f0f0ull, + 0xff00ff00ff00ff00ull, + 0xffff0000ffff0000ull, + 0xffffffff00000000ull}; + return vars[i]; + } + static inline word ones(int i) { + static const word ones[] = {0x0000000000000001ull, + 0x0000000000000003ull, + 0x000000000000000full, + 0x00000000000000ffull, + 0x000000000000ffffull, + 0x00000000ffffffffull, + 0xffffffffffffffffull}; + return ones[i]; + } + + private: + int nVars; + bvar nObjs; + bvar nObjsAlloc; + bvar nObjsMax; + size nSize; + size nTotalSize; + std::vector vVals; + std::vector vDeads; + std::vector vRefs; + int nGbc; + int nVerbose; + + public: + inline lit Bvar2Lit(bvar a) const { return (lit)a << 1; } + inline bvar Lit2Bvar(lit x) const { return (bvar)(x >> 1); } + inline lit IthVar(int v) const { return ((lit)v + 1) << 1; } + inline lit LitNot(lit x) const { return x ^ (lit)1; } + inline lit LitNotCond(lit x, bool c) const { return x ^ (lit)c; } + inline bool LitIsCompl(lit x) const { return x & (lit)1; } + inline ref Ref(lit x) const { return vRefs[Lit2Bvar(x)]; } + inline lit Const0() const { return (lit)0; } + inline lit Const1() const { return (lit)1; } + inline bool IsConst0(lit x) const { + bvar a = Lit2Bvar(x); + word c = LitIsCompl(x)? one(): 0; + for(size j = 0; j < nSize; j++) + if(vVals[nSize * a + j] ^ c) + return false; + return true; + } + inline bool IsConst1(lit x) const { + bvar a = Lit2Bvar(x); + word c = LitIsCompl(x)? one(): 0; + for(size j = 0; j < nSize; j++) + if(~(vVals[nSize * a + j] ^ c)) + return false; + return true; + } + inline bool LitIsEq(lit x, lit y) const { + if(x == y) + return true; + if(x == LitMax() || y == LitMax()) + return false; + bvar xvar = Lit2Bvar(x); + bvar yvar = Lit2Bvar(y); + word c = LitIsCompl(x) ^ LitIsCompl(y)? one(): 0; + for(size j = 0; j < nSize; j++) + if(vVals[nSize * xvar + j] ^ vVals[nSize * yvar + j] ^ c) + return false; + return true; + } + inline size OneCount(lit x) const { + bvar a = Lit2Bvar(x); + size count = 0; + if(nVars > 6) { + for(size j = 0; j < nSize; j++) + count += bsw(vVals[nSize * a + j]).count(); + } else + count = bsw(vVals[nSize * a] & ones(nVars)).count(); + return LitIsCompl(x)? ((size)1 << nVars) - count: count; + } + + public: + inline void IncRef(lit x) { if(!vRefs.empty() && Ref(x) != RefMax()) vRefs[Lit2Bvar(x)]++; } + inline void DecRef(lit x) { if(!vRefs.empty() && Ref(x) != RefMax()) vRefs[Lit2Bvar(x)]--; } + + public: + bool Resize() { + if(nObjsAlloc == nObjsMax) + return false; + lit nObjsAllocLit = (lit)nObjsAlloc << 1; + if(nObjsAllocLit > (lit)BvarMax()) + nObjsAlloc = BvarMax(); + else + nObjsAlloc = (bvar)nObjsAllocLit; + nTotalSize = nTotalSize << 1; + if(nVerbose >= 2) + std::cout << "Reallocating " << nObjsAlloc << " nodes" << std::endl; + vVals.resize(nTotalSize); + if(!vRefs.empty()) + vRefs.resize(nObjsAlloc); + return true; + } + bool Gbc() { + if(nVerbose >= 2) + std::cout << "Garbage collect" << std::endl; + for(bvar a = nVars + 1; a < nObjs; a++) + if(!vRefs[a]) + vDeads.push_back(a); + return vDeads.size(); + } + + public: + Man(int nVars, Param p): nVars(nVars) { + if(p.nObjsMaxLog < p.nObjsAllocLog) + fatal_error("nObjsMax must not be smaller than nObjsAlloc"); + if(nVars >= lww()) + nSize = 1ull << (nVars - lww()); + else + nSize = 1; + if(!nSize) + fatal_error("Memout (nVars) in init"); + if(!(nSize << p.nObjsMaxLog)) + fatal_error("Memout (nObjsMax) in init"); + lit nObjsMaxLit = (lit)1 << p.nObjsMaxLog; + if(!nObjsMaxLit) + fatal_error("Memout (nObjsMax) in init"); + if(nObjsMaxLit > (lit)BvarMax()) + nObjsMax = BvarMax(); + else + nObjsMax = (bvar)nObjsMaxLit; + lit nObjsAllocLit = (lit)1 << p.nObjsAllocLog; + if(!nObjsAllocLit) + fatal_error("Memout (nObjsAlloc) in init"); + if(nObjsAllocLit > (lit)BvarMax()) + nObjsAlloc = BvarMax(); + else + nObjsAlloc = (bvar)nObjsAllocLit; + if(nObjsAlloc <= (bvar)nVars) + fatal_error("nObjsAlloc must be larger than nVars"); + nTotalSize = nSize << p.nObjsAllocLog; + vVals.resize(nTotalSize); + if(p.fCountOnes && nVars > 63) + fatal_error("nVars must be less than 64 to count ones"); + nObjs = 1; + for(int i = 0; i < 6 && i < nVars; i++) { + for(size j = 0; j < nSize; j++) + vVals[nSize * nObjs + j] = vars(i); + nObjs++; + } + for(int i = 0; i < nVars - 6; i++) { + for(size j = 0; j < nSize; j += (2ull << i)) + for(size k = 0; k < (1ull << i); k++) + vVals[nSize * nObjs + j + k] = one(); + nObjs++; + } + nVerbose = p.nVerbose; + nGbc = p.nGbc; + if(nGbc || p.nReo != BvarMax()) + vRefs.resize(nObjsAlloc); + } + inline lit And(lit x, lit y) { + bvar xvar = Lit2Bvar(x); + bvar yvar = Lit2Bvar(y); + word xcompl = LitIsCompl(x)? one(): 0; + word ycompl = LitIsCompl(y)? one(): 0; + unsigned j; + if(nObjs >= nObjsAlloc && vDeads.empty()) { + bool fRemoved = false; + if(nGbc > 1) + fRemoved = Gbc(); + if(!Resize() && !fRemoved && (nGbc != 1 || !Gbc())) + fatal_error("Memout (node)"); + } + bvar zvar; + if(nObjs < nObjsAlloc) + zvar = nObjs++; + else + zvar = vDeads.back(), vDeads.resize(vDeads.size() - 1); + for(j = 0; j < nSize; j++) + vVals[nSize * zvar + j] = (vVals[nSize * xvar + j] ^ xcompl) & (vVals[nSize * yvar + j] ^ ycompl); + return zvar << 1; + } + inline lit Or(lit x, lit y) { + return LitNot(And(LitNot(x), LitNot(y))); + } + void Reorder() {} // dummy + + public: + void SetRef(std::vector const &vLits) { + vRefs.clear(); + vRefs.resize(nObjsAlloc); + for(size_t i = 0; i < vLits.size(); i++) + IncRef(vLits[i]); + } + void RemoveRefIfUnused() { + if(!nGbc) + vRefs.clear(); + } + void TurnOffReo() {} + int GetNumVars() const { + return nVars; + } + void PrintNode(lit x) const { + bvar a = Lit2Bvar(x); + word c = LitIsCompl(x)? one(): 0; + for(size j = 0; j < nSize; j++) + std::cout << bsw(vVals[nSize * a + j] ^ c); + std::cout << std::endl; + } + }; + +} + +ABC_NAMESPACE_CXX_HEADER_END + +#endif diff --git a/yosys/abc/src/aig/gia/giaNf.c b/yosys/abc/src/aig/gia/giaNf.c new file mode 100644 index 00000000000..8bcf76b333b --- /dev/null +++ b/yosys/abc/src/aig/gia/giaNf.c @@ -0,0 +1,2692 @@ +/**CFile**************************************************************** + + FileName [giaNf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Standard-cell mapper.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaNf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include "gia.h" +#include "misc/st/st.h" +#include "map/mio/mio.h" +#include "misc/util/utilTruth.h" +#include "misc/extra/extra.h" +#include "base/main/main.h" +#include "misc/vec/vecMem.h" +#include "misc/vec/vecWec.h" +#include "opt/dau/dau.h" +#include "misc/util/utilNam.h" +#include "map/scl/sclCon.h" +#include "misc/tim/tim.h" + +#ifdef _MSC_VER +# include +# define __builtin_popcount __popcnt +#endif + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define NF_LEAF_MAX 6 +#define NF_CUT_MAX 32 +#define NF_NO_LEAF 31 +#define NF_NO_FUNC 0x3FFFFFF +#define NF_EPSILON 0.001 + +typedef struct Nf_Cut_t_ Nf_Cut_t; +struct Nf_Cut_t_ +{ + word Sign; // signature + int Delay; // delay + float Flow; // flow + unsigned iFunc : 26; // function (NF_NO_FUNC) + unsigned Useless : 1; // function + unsigned nLeaves : 5; // leaf number (NF_NO_LEAF) + int pLeaves[NF_LEAF_MAX+1]; // leaves +}; +typedef struct Nf_Cfg_t_ Nf_Cfg_t; +struct Nf_Cfg_t_ +{ + unsigned fCompl : 1; // complemented + unsigned Phase : 7; // match phase + unsigned Perm : 24; // match permutation +}; +typedef struct Nf_Mat_t_ Nf_Mat_t; +struct Nf_Mat_t_ +{ + unsigned Gate : 20; // gate + unsigned CutH : 10; // cut handle + unsigned fCompl : 1; // complemented + unsigned fBest : 1; // best cut + Nf_Cfg_t Cfg; // input literals + int D; // delay + float F; // area +}; +typedef struct Nf_Obj_t_ Nf_Obj_t; +struct Nf_Obj_t_ +{ + Nf_Mat_t M[2][2]; // del/area (2x) +}; +typedef struct Nf_Man_t_ Nf_Man_t; +struct Nf_Man_t_ +{ + // user data + Gia_Man_t * pGia; // derived manager + Tim_Man_t * pManTim; // timing manager + Jf_Par_t * pPars; // parameters + // matching + Vec_Mem_t * vTtMem; // truth tables + Vec_Wec_t * vTt2Match; // matches for truth tables + Mio_Cell2_t * pCells; // library gates + int nCells; // library gate count + // cut data + Nf_Obj_t * pNfObjs; // best cuts + Vec_Ptr_t vPages; // cut memory + Vec_Int_t vCutSets; // cut offsets + Vec_Int_t vMapRefs; // mapping refs (2x) + Vec_Flt_t vFlowRefs; // flow refs (2x) + Vec_Int_t vRequired; // required times (2x) + Vec_Flt_t vCutFlows; // temporary cut area + Vec_Int_t vCutDelays; // temporary cut delay + Vec_Int_t vBackup; // backup literals + int iCur; // current position + int Iter; // mapping iterations + int fUseEla; // use exact area + int nInvs; // the inverter count + int InvDelayI; // inverter delay + word InvAreaW; // inverter delay + float InvAreaF; // inverter area + // statistics + abctime clkStart; // starting time + double CutCount[6]; // cut counts + int nCutUseAll; // objects with useful cuts +}; + +static inline int Nf_Cfg2Int( Nf_Cfg_t Mat ) { union { int x; Nf_Cfg_t y; } v; v.y = Mat; return v.x; } +static inline Nf_Cfg_t Nf_Int2Cfg( int Int ) { union { int x; Nf_Cfg_t y; } v; v.x = Int; return v.y; } + +static inline Nf_Obj_t * Nf_ManObj( Nf_Man_t * p, int i ) { return p->pNfObjs + i; } +static inline Mio_Cell2_t* Nf_ManCell( Nf_Man_t * p, int i ) { return p->pCells + i; } +static inline int * Nf_ManCutSet( Nf_Man_t * p, int i ) { return (int *)Vec_PtrEntry(&p->vPages, i >> 16) + (i & 0xFFFF); } +static inline int Nf_ObjCutSetId( Nf_Man_t * p, int i ) { return Vec_IntEntry( &p->vCutSets, i ); } +static inline int * Nf_ObjCutSet( Nf_Man_t * p, int i ) { return Nf_ManCutSet(p, Nf_ObjCutSetId(p, i)); } +static inline int Nf_ObjHasCuts( Nf_Man_t * p, int i ) { return (int)(Vec_IntEntry(&p->vCutSets, i) > 0); } +static inline int * Nf_ObjCutBest( Nf_Man_t * p, int i ) { return NULL; } +static inline int Nf_ObjCutUseless( Nf_Man_t * p, int TruthId ) { return (int)(TruthId >= Vec_WecSize(p->vTt2Match)); } + +static inline float Nf_ObjCutFlow( Nf_Man_t * p, int i ) { return Vec_FltEntry(&p->vCutFlows, i); } +static inline int Nf_ObjCutDelay( Nf_Man_t * p, int i ) { return Vec_IntEntry(&p->vCutDelays, i); } +static inline void Nf_ObjSetCutFlow( Nf_Man_t * p, int i, float a ) { Vec_FltWriteEntry(&p->vCutFlows, i, a); } +static inline void Nf_ObjSetCutDelay( Nf_Man_t * p, int i, int d ) { Vec_IntWriteEntry(&p->vCutDelays, i, d); } + +static inline int Nf_ObjMapRefNum( Nf_Man_t * p, int i, int c ) { return Vec_IntEntry(&p->vMapRefs, Abc_Var2Lit(i,c)); } +static inline int Nf_ObjMapRefInc( Nf_Man_t * p, int i, int c ) { return (*Vec_IntEntryP(&p->vMapRefs, Abc_Var2Lit(i,c)))++; } +static inline int Nf_ObjMapRefDec( Nf_Man_t * p, int i, int c ) { return --(*Vec_IntEntryP(&p->vMapRefs, Abc_Var2Lit(i,c))); } +static inline float Nf_ObjFlowRefs( Nf_Man_t * p, int i, int c ) { return Vec_FltEntry(&p->vFlowRefs, Abc_Var2Lit(i,c)); } +static inline int Nf_ObjRequired( Nf_Man_t * p, int i, int c ) { return Vec_IntEntry(&p->vRequired, Abc_Var2Lit(i,c)); } +static inline void Nf_ObjSetRequired( Nf_Man_t * p,int i, int c, int f ) { Vec_IntWriteEntry(&p->vRequired, Abc_Var2Lit(i,c), f); } +static inline void Nf_ObjUpdateRequired( Nf_Man_t * p,int i, int c, int f ) { if (Nf_ObjRequired(p, i, c) > f) Nf_ObjSetRequired(p, i, c, f); } + +static inline Nf_Mat_t * Nf_ObjMatchD( Nf_Man_t * p, int i, int c ) { return &Nf_ManObj(p, i)->M[c][0]; } +static inline Nf_Mat_t * Nf_ObjMatchA( Nf_Man_t * p, int i, int c ) { return &Nf_ManObj(p, i)->M[c][1]; } + +static inline int Nf_CutSize( int * pCut ) { return pCut[0] & NF_NO_LEAF; } +static inline int Nf_CutFunc( int * pCut ) { return ((unsigned)pCut[0] >> 5); } +static inline int * Nf_CutLeaves( int * pCut ) { return pCut + 1; } +static inline int Nf_CutSetBoth( int n, int f ) { return n | (f << 5); } +static inline int Nf_CutIsTriv( int * pCut, int i ) { return Nf_CutSize(pCut) == 1 && pCut[1] == i; } +static inline int Nf_CutHandle( int * pCutSet, int * pCut ) { assert( pCut > pCutSet ); return pCut - pCutSet; } +static inline int * Nf_CutFromHandle( int * pCutSet, int h ) { assert( h > 0 ); return pCutSet + h; } + +static inline int Nf_CfgVar( Nf_Cfg_t Cfg, int i ) { return (Cfg.Perm >> (i<<2)) & 15; } +static inline int Nf_CfgCompl( Nf_Cfg_t Cfg, int i ) { return (Cfg.Phase >> i) & 1; } + +#define Nf_SetForEachCut( pList, pCut, i ) for ( i = 0, pCut = pList + 1; i < pList[0]; i++, pCut += Nf_CutSize(pCut) + 1 ) +#define Nf_CutForEachVarCompl( pCut, Cfg, iVar, fCompl, i ) for ( i = 0; i < Nf_CutSize(pCut) && (iVar = Nf_CutLeaves(pCut)[Nf_CfgVar(Cfg, i)]) && ((fCompl = Nf_CfgCompl(Cfg, i)), 1); i++ ) +#define Nf_CfgForEachVarCompl( Cfg, Size, iVar, fCompl, i ) for ( i = 0; i < Size && ((iVar = Nf_CfgVar(Cfg, i)), 1) && ((fCompl = Nf_CfgCompl(Cfg, i)), 1); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Nf_StoCellIsDominated( Mio_Cell2_t * pCell, int * pFans, int * pProf ) +{ + int k; + if ( pCell->AreaF + NF_EPSILON < Abc_Int2Float(pProf[0]) ) + return 0; + for ( k = 0; k < (int)pCell->nFanins; k++ ) + if ( pCell->iDelays[Abc_Lit2Var(pFans[k])] < pProf[k+1] ) + return 0; + return 1; // pCell is dominated +} +void Nf_StoCreateGateAdd( Vec_Mem_t * vTtMem, Vec_Wec_t * vTt2Match, Mio_Cell2_t * pCell, word uTruth, int * pFans, int nFans, Vec_Wec_t * vProfs, Vec_Int_t * vStore, int fPinFilter, int fPinPerm, int fPinQuick ) +{ + Vec_Int_t * vArray, * vArrayProfs = NULL; + int i, k, GateId, Entry, fCompl = (int)(uTruth & 1); + word uFunc = fCompl ? ~uTruth : uTruth; + int iFunc = Vec_MemHashInsert( vTtMem, &uFunc ); + Nf_Cfg_t Mat = Nf_Int2Cfg(0); + // get match array + if ( iFunc == Vec_WecSize(vTt2Match) ) + Vec_WecPushLevel( vTt2Match ); + vArray = Vec_WecEntry( vTt2Match, iFunc ); + // create match + Mat.fCompl = fCompl; + assert( nFans == (int)pCell->nFanins ); + for ( i = 0; i < nFans; i++ ) + { + Mat.Perm |= (unsigned)(i << (Abc_Lit2Var(pFans[i]) << 2)); + Mat.Phase |= (unsigned)(Abc_LitIsCompl(pFans[i]) << Abc_Lit2Var(pFans[i])); + } + // check other profiles + if ( fPinFilter ) + { + // get profile array + assert( Vec_WecSize(vTt2Match) == Vec_WecSize(vProfs) ); + if ( iFunc == Vec_WecSize(vProfs) ) + Vec_WecPushLevel( vProfs ); + vArrayProfs = Vec_WecEntry( vProfs, iFunc ); + assert( Vec_IntSize(vArray) == 2 * Vec_IntSize(vArrayProfs) ); + // skip dominated matches + Vec_IntForEachEntryDouble( vArray, GateId, Entry, i ) + if ( Nf_Int2Cfg(Entry).Phase == Mat.Phase && Nf_Int2Cfg(Entry).fCompl == Mat.fCompl ) + { + int Offset = Vec_IntEntry(vArrayProfs, i/2); + int * pProf = Vec_IntEntryP(vStore, Offset); + if ( Nf_StoCellIsDominated(pCell, pFans, pProf) ) + return; + } + } + // check pin permutation + if ( !fPinPerm ) // do not use pin-permutation (improves delay when pin-delays differ) + { + if ( fPinQuick ) // reduce the number of matches agressively + { + Vec_IntForEachEntryDouble( vArray, GateId, Entry, i ) + if ( GateId == (int)pCell->Id && __builtin_popcount( Nf_Int2Cfg(Entry).Phase & 0xff ) == __builtin_popcount( Mat.Phase & 0xff ) ) + return; + } + else // reduce the number of matches less agressively + { + Vec_IntForEachEntryDouble( vArray, GateId, Entry, i ) + if ( GateId == (int)pCell->Id && Nf_Int2Cfg(Entry).Phase == Mat.Phase ) + return; + } + } + // save data and profile + Vec_IntPush( vArray, pCell->Id ); + Vec_IntPush( vArray, Nf_Cfg2Int(Mat) ); + // add delay profile + if ( fPinFilter ) + { + Vec_IntPush( vArrayProfs, Vec_IntSize(vStore) ); + Vec_IntPush( vStore, Abc_Float2Int(pCell->AreaF) ); + for ( k = 0; k < nFans; k++ ) + Vec_IntPush( vStore, pCell->iDelays[Abc_Lit2Var(pFans[k])] ); + } +} +void Nf_StoCreateGateMaches( Vec_Mem_t * vTtMem, Vec_Wec_t * vTt2Match, Mio_Cell2_t * pCell, int ** pComp, int ** pPerm, int * pnPerms, Vec_Wec_t * vProfs, Vec_Int_t * vStore, int fPinFilter, int fPinPerm, int fPinQuick ) +{ + int Perm[NF_LEAF_MAX], * Perm1, * Perm2; + int nPerms = pnPerms[pCell->nFanins]; + int nMints = (1 << pCell->nFanins); + word tCur, tTemp1, tTemp2; + int i, p, c; + assert( pCell->nFanins <= 6 ); + for ( i = 0; i < (int)pCell->nFanins; i++ ) + Perm[i] = Abc_Var2Lit( i, 0 ); + tCur = tTemp1 = pCell->uTruth; + for ( p = 0; p < nPerms; p++ ) + { + tTemp2 = tCur; + for ( c = 0; c < nMints; c++ ) + { + Nf_StoCreateGateAdd( vTtMem, vTt2Match, pCell, tCur, Perm, pCell->nFanins, vProfs, vStore, fPinFilter, fPinPerm, fPinQuick ); + // update + tCur = Abc_Tt6Flip( tCur, pComp[pCell->nFanins][c] ); + Perm1 = Perm + pComp[pCell->nFanins][c]; + *Perm1 = Abc_LitNot( *Perm1 ); + } + assert( tTemp2 == tCur ); + if ( nPerms == 1 ) + continue; + // update + tCur = Abc_Tt6SwapAdjacent( tCur, pPerm[pCell->nFanins][p] ); + Perm1 = Perm + pPerm[pCell->nFanins][p]; + Perm2 = Perm1 + 1; + ABC_SWAP( int, *Perm1, *Perm2 ); + } + assert( tTemp1 == tCur ); +} +Mio_Cell2_t * Nf_StoDeriveMatches( Vec_Mem_t * vTtMem, Vec_Wec_t * vTt2Match, int * pnCells, int fPinFilter, int fPinPerm, int fPinQuick ) +{ + int fVerbose = 0; + //abctime clk = Abc_Clock(); + Vec_Wec_t * vProfs = Vec_WecAlloc( 1000 ); + Vec_Int_t * vStore = Vec_IntAlloc( 10000 ); + int * pComp[7], * pPerm[7], nPerms[7], i; + Mio_Cell2_t * pCells; + Vec_WecPushLevel( vProfs ); + Vec_WecPushLevel( vProfs ); + for ( i = 1; i <= 6; i++ ) + pComp[i] = Extra_GreyCodeSchedule( i ); + for ( i = 1; i <= 6; i++ ) + pPerm[i] = Extra_PermSchedule( i ); + for ( i = 1; i <= 6; i++ ) + nPerms[i] = Extra_Factorial( i ); + pCells = Mio_CollectRootsNewDefault2( 6, pnCells, fVerbose ); + if ( pCells != NULL ) + for ( i = 2; i < *pnCells; i++ ) + Nf_StoCreateGateMaches( vTtMem, vTt2Match, pCells+i, pComp, pPerm, nPerms, vProfs, vStore, fPinFilter, fPinPerm, fPinQuick ); + for ( i = 1; i <= 6; i++ ) + ABC_FREE( pComp[i] ); + for ( i = 1; i <= 6; i++ ) + ABC_FREE( pPerm[i] ); + Vec_WecFree( vProfs ); + Vec_IntFree( vStore ); + //Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return pCells; +} +void Nf_StoPrintOne( Nf_Man_t * p, int Count, int t, int i, int GateId, Nf_Cfg_t Mat ) +{ + Mio_Cell2_t * pC = p->pCells + GateId; + word * pTruth = Vec_MemReadEntry(p->vTtMem, t); + int k, nSuppSize = Abc_TtSupportSize(pTruth, 6); + printf( "%6d : ", Count ); + printf( "%6d : ", t ); + printf( "%6d : ", i ); + printf( "Gate %16s ", pC->pName ); + printf( "Area =%8.2f ", pC->AreaF ); + printf( "In = %d ", pC->nFanins ); + if ( Mat.fCompl ) + printf( " compl " ); + else + printf( " " ); + for ( k = 0; k < (int)pC->nFanins; k++ ) + { + int fComplF = (Mat.Phase >> k) & 1; + int iFanin = (Mat.Perm >> (3*k)) & 7; + printf( "%c", 'a' + iFanin - fComplF * ('a' - 'A') ); + } + printf( " " ); + Dau_DsdPrintFromTruth( pTruth, nSuppSize ); +} +void Nf_StoPrint( Nf_Man_t * p, int fVerbose ) +{ + int t, i, GateId, Entry, Count = 0; + for ( t = 2; t < Vec_WecSize(p->vTt2Match); t++ ) + { + Vec_Int_t * vArr = Vec_WecEntry( p->vTt2Match, t ); + Vec_IntForEachEntryDouble( vArr, GateId, Entry, i ) + { + Count++; + if ( !fVerbose ) + continue; + //if ( t < 10 ) + // Nf_StoPrintOne( p, Count, t, i/2, GateId, Pf_Int2Mat(Entry) ); + } + } + printf( "Gates = %d. Truths = %d. Matches = %d.\n", + p->nCells, Vec_MemEntryNum(p->vTtMem), Count ); +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Nf_Man_t * Nf_StoCreate( Gia_Man_t * pGia, Jf_Par_t * pPars ) +{ + extern void Mf_ManSetFlowRefs( Gia_Man_t * p, Vec_Int_t * vRefs ); + Vec_Int_t * vFlowRefs; + Nf_Man_t * p; + int i, Entry; + assert( pPars->nCutNum > 1 && pPars->nCutNum <= NF_CUT_MAX ); + assert( pPars->nLutSize > 1 && pPars->nLutSize <= NF_LEAF_MAX ); + ABC_FREE( pGia->pRefs ); + Vec_IntFreeP( &pGia->vCellMapping ); + if ( Gia_ManHasChoices(pGia) ) + Gia_ManSetPhase(pGia); + // create + p = ABC_CALLOC( Nf_Man_t, 1 ); + p->clkStart = Abc_Clock(); + p->pGia = pGia; + p->pManTim = (Tim_Man_t *)pGia->pManTime; + p->pPars = pPars; + p->pNfObjs = ABC_CALLOC( Nf_Obj_t, Gia_ManObjNum(pGia) ); + p->iCur = 2; + // other + Vec_PtrGrow( &p->vPages, 256 ); // cut memory + Vec_IntFill( &p->vMapRefs, 2*Gia_ManObjNum(pGia), 0 ); // mapping refs (2x) + Vec_FltFill( &p->vFlowRefs, 2*Gia_ManObjNum(pGia), 0 ); // flow refs (2x) + Vec_IntFill( &p->vRequired, 2*Gia_ManObjNum(pGia), SCL_INFINITY ); // required times (2x) + Vec_IntFill( &p->vCutSets, Gia_ManObjNum(pGia), 0 ); // cut offsets + Vec_FltFill( &p->vCutFlows, Gia_ManObjNum(pGia), 0 ); // cut area + Vec_IntFill( &p->vCutDelays,Gia_ManObjNum(pGia), 0 ); // cut delay + Vec_IntGrow( &p->vBackup, 1000 ); + // references + vFlowRefs = Vec_IntAlloc(0); + Mf_ManSetFlowRefs( pGia, vFlowRefs ); + Vec_IntForEachEntry( vFlowRefs, Entry, i ) + { + Vec_FltWriteEntry( &p->vFlowRefs, 2*i, /*0.5* */Entry ); + Vec_FltWriteEntry( &p->vFlowRefs, 2*i+1, /*0.5* */Entry ); + } + Vec_IntFree(vFlowRefs); + // matching + Mio_LibraryMatchesFetch( (Mio_Library_t *)Abc_FrameReadLibGen(), &p->vTtMem, &p->vTt2Match, &p->pCells, &p->nCells, p->pPars->fPinFilter, p->pPars->fPinPerm, p->pPars->fPinQuick ); + if ( p->pCells == NULL ) + return NULL; + p->InvDelayI = p->pCells[3].iDelays[0]; + p->InvAreaW = p->pCells[3].AreaW; + p->InvAreaF = p->pCells[3].AreaF; + Nf_ObjMatchD(p, 0, 0)->Gate = 0; + Nf_ObjMatchD(p, 0, 1)->Gate = 1; + // prepare cuts + return p; +} +void Nf_StoDelete( Nf_Man_t * p ) +{ + Vec_PtrFreeData( &p->vPages ); + ABC_FREE( p->vPages.pArray ); + ABC_FREE( p->vMapRefs.pArray ); + ABC_FREE( p->vFlowRefs.pArray ); + ABC_FREE( p->vRequired.pArray ); + ABC_FREE( p->vCutSets.pArray ); + ABC_FREE( p->vCutFlows.pArray ); + ABC_FREE( p->vCutDelays.pArray ); + ABC_FREE( p->vBackup.pArray ); + ABC_FREE( p->pNfObjs ); + ABC_FREE( p ); +} + + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Nf_CutComputeTruth6( Nf_Man_t * p, Nf_Cut_t * pCut0, Nf_Cut_t * pCut1, int fCompl0, int fCompl1, Nf_Cut_t * pCutR, int fIsXor ) +{ +// extern int Nf_ManTruthCanonicize( word * t, int nVars ); + int nOldSupp = pCutR->nLeaves, truthId, fCompl; word t; + word t0 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut0->iFunc)); + word t1 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut1->iFunc)); + if ( Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ) t0 = ~t0; + if ( Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ) t1 = ~t1; + t0 = Abc_Tt6Expand( t0, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + t1 = Abc_Tt6Expand( t1, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + t = fIsXor ? t0 ^ t1 : t0 & t1; + if ( (fCompl = (int)(t & 1)) ) t = ~t; + pCutR->nLeaves = Abc_Tt6MinBase( &t, pCutR->pLeaves, pCutR->nLeaves ); + assert( (int)(t & 1) == 0 ); + truthId = Vec_MemHashInsert(p->vTtMem, &t); + pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); + pCutR->Useless = Nf_ObjCutUseless( p, truthId ); + assert( (int)pCutR->nLeaves <= nOldSupp ); + return (int)pCutR->nLeaves < nOldSupp; +} +static inline int Nf_CutComputeTruthMux6( Nf_Man_t * p, Nf_Cut_t * pCut0, Nf_Cut_t * pCut1, Nf_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, Nf_Cut_t * pCutR ) +{ + int nOldSupp = pCutR->nLeaves, truthId, fCompl; word t; + word t0 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut0->iFunc)); + word t1 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut1->iFunc)); + word tC = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCutC->iFunc)); + if ( Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ) t0 = ~t0; + if ( Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ) t1 = ~t1; + if ( Abc_LitIsCompl(pCutC->iFunc) ^ fComplC ) tC = ~tC; + t0 = Abc_Tt6Expand( t0, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + t1 = Abc_Tt6Expand( t1, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + tC = Abc_Tt6Expand( tC, pCutC->pLeaves, pCutC->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + t = (tC & t1) | (~tC & t0); + if ( (fCompl = (int)(t & 1)) ) t = ~t; + pCutR->nLeaves = Abc_Tt6MinBase( &t, pCutR->pLeaves, pCutR->nLeaves ); + assert( (int)(t & 1) == 0 ); + truthId = Vec_MemHashInsert(p->vTtMem, &t); + pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); + pCutR->Useless = Nf_ObjCutUseless( p, truthId ); + assert( (int)pCutR->nLeaves <= nOldSupp ); + return (int)pCutR->nLeaves < nOldSupp; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Nf_CutCountBits( word i ) +{ + i = i - ((i >> 1) & 0x5555555555555555); + i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333); + i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F); + return (i*(0x0101010101010101))>>56; +} +static inline word Nf_CutGetSign( int * pLeaves, int nLeaves ) +{ + word Sign = 0; int i; + for ( i = 0; i < nLeaves; i++ ) + Sign |= ((word)1) << (pLeaves[i] & 0x3F); + return Sign; +} +static inline int Nf_CutCreateUnit( Nf_Cut_t * p, int i ) +{ + p->Delay = 0; + p->Flow = 0; + p->iFunc = 2; + p->nLeaves = 1; + p->pLeaves[0] = i; + p->Sign = ((word)1) << (i & 0x3F); + return 1; +} +static inline void Nf_CutPrint( Nf_Man_t * p, Nf_Cut_t * pCut ) +{ + int i, nDigits = Abc_Base10Log(Gia_ManObjNum(p->pGia)); + printf( "%d {", pCut->nLeaves ); + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + printf( " %*d", nDigits, pCut->pLeaves[i] ); + for ( ; i < (int)p->pPars->nLutSize; i++ ) + printf( " %*s", nDigits, " " ); + printf( " } Useless = %d. D = %4d A = %9.4f F = %6d ", + pCut->Useless, pCut->Delay, pCut->Flow, pCut->iFunc ); + if ( p->vTtMem ) + Dau_DsdPrintFromTruth( Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut->iFunc)), pCut->nLeaves ); + else + printf( "\n" ); +} +static inline int Nf_ManPrepareCuts( Nf_Cut_t * pCuts, Nf_Man_t * p, int iObj, int fAddUnit ) +{ + if ( Nf_ObjHasCuts(p, iObj) ) + { + Nf_Cut_t * pMfCut = pCuts; + int i, * pCut, * pList = Nf_ObjCutSet(p, iObj); + Nf_SetForEachCut( pList, pCut, i ) + { + pMfCut->Delay = 0; + pMfCut->Flow = 0; + pMfCut->iFunc = Nf_CutFunc( pCut ); + pMfCut->nLeaves = Nf_CutSize( pCut ); + pMfCut->Sign = Nf_CutGetSign( pCut+1, Nf_CutSize(pCut) ); + pMfCut->Useless = Nf_ObjCutUseless( p, Abc_Lit2Var(pMfCut->iFunc) ); + memcpy( pMfCut->pLeaves, pCut+1, sizeof(int) * Nf_CutSize(pCut) ); + pMfCut++; + } + if ( fAddUnit && pCuts->nLeaves > 1 ) + return pList[0] + Nf_CutCreateUnit( pMfCut, iObj ); + return pList[0]; + } + return Nf_CutCreateUnit( pCuts, iObj ); +} +static inline int Nf_ManSaveCuts( Nf_Man_t * p, Nf_Cut_t ** pCuts, int nCuts, int fUseful ) +{ + int i, * pPlace, iCur, nInts = 1, nCutsNew = 0; + for ( i = 0; i < nCuts; i++ ) + if ( !fUseful || !pCuts[i]->Useless ) + nInts += pCuts[i]->nLeaves + 1, nCutsNew++; + if ( (p->iCur & 0xFFFF) + nInts > 0xFFFF ) + p->iCur = ((p->iCur >> 16) + 1) << 16; + if ( Vec_PtrSize(&p->vPages) == (p->iCur >> 16) ) + Vec_PtrPush( &p->vPages, ABC_ALLOC(int, (1<<16)) ); + iCur = p->iCur; p->iCur += nInts; + pPlace = Nf_ManCutSet( p, iCur ); + *pPlace++ = nCutsNew; + for ( i = 0; i < nCuts; i++ ) + if ( !fUseful || !pCuts[i]->Useless ) + { + *pPlace++ = Nf_CutSetBoth( pCuts[i]->nLeaves, pCuts[i]->iFunc ); + memcpy( pPlace, pCuts[i]->pLeaves, sizeof(int) * pCuts[i]->nLeaves ); + pPlace += pCuts[i]->nLeaves; + } + return iCur; +} +static inline int Nf_ManCountUseful( Nf_Cut_t ** pCuts, int nCuts ) +{ + int i, Count = 0; + for ( i = 0; i < nCuts; i++ ) + Count += !pCuts[i]->Useless; + return Count; +} +static inline int Nf_ManCountMatches( Nf_Man_t * p, Nf_Cut_t ** pCuts, int nCuts ) +{ + int i, Count = 0; + for ( i = 0; i < nCuts; i++ ) + if ( !pCuts[i]->Useless ) + Count += Vec_IntSize(Vec_WecEntry(p->vTt2Match, Abc_Lit2Var(pCuts[i]->iFunc))) / 2; + return Count; +} + +/**Function************************************************************* + + Synopsis [Check correctness of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Nf_CutCheck( Nf_Cut_t * pBase, Nf_Cut_t * pCut ) // check if pCut is contained in pBase +{ + int nSizeB = pBase->nLeaves; + int nSizeC = pCut->nLeaves; + int i, * pB = pBase->pLeaves; + int k, * pC = pCut->pLeaves; + for ( i = 0; i < nSizeC; i++ ) + { + for ( k = 0; k < nSizeB; k++ ) + if ( pC[i] == pB[k] ) + break; + if ( k == nSizeB ) + return 0; + } + return 1; +} +static inline int Nf_SetCheckArray( Nf_Cut_t ** ppCuts, int nCuts ) +{ + Nf_Cut_t * pCut0, * pCut1; + int i, k, m, n, Value; + assert( nCuts > 0 ); + for ( i = 0; i < nCuts; i++ ) + { + pCut0 = ppCuts[i]; + assert( pCut0->nLeaves <= NF_LEAF_MAX ); + assert( pCut0->Sign == Nf_CutGetSign(pCut0->pLeaves, pCut0->nLeaves) ); + // check duplicates + for ( m = 0; m < (int)pCut0->nLeaves; m++ ) + for ( n = m + 1; n < (int)pCut0->nLeaves; n++ ) + assert( pCut0->pLeaves[m] < pCut0->pLeaves[n] ); + // check pairs + for ( k = 0; k < nCuts; k++ ) + { + pCut1 = ppCuts[k]; + if ( pCut0 == pCut1 ) + continue; + // check containments + Value = Nf_CutCheck( pCut0, pCut1 ); + assert( Value == 0 ); + } + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Nf_CutMergeOrder( Nf_Cut_t * pCut0, Nf_Cut_t * pCut1, Nf_Cut_t * pCut, int nLutSize ) +{ + int nSize0 = pCut0->nLeaves; + int nSize1 = pCut1->nLeaves; + int i, * pC0 = pCut0->pLeaves; + int k, * pC1 = pCut1->pLeaves; + int c, * pC = pCut->pLeaves; + // the case of the largest cut sizes + if ( nSize0 == nLutSize && nSize1 == nLutSize ) + { + for ( i = 0; i < nSize0; i++ ) + { + if ( pC0[i] != pC1[i] ) return 0; + pC[i] = pC0[i]; + } + pCut->nLeaves = nLutSize; + pCut->iFunc = NF_NO_FUNC; + pCut->Sign = pCut0->Sign | pCut1->Sign; + return 1; + } + // compare two cuts with different numbers + i = k = c = 0; + if ( nSize0 == 0 ) goto FlushCut1; + if ( nSize1 == 0 ) goto FlushCut0; + while ( 1 ) + { + if ( c == nLutSize ) return 0; + if ( pC0[i] < pC1[k] ) + { + pC[c++] = pC0[i++]; + if ( i >= nSize0 ) goto FlushCut1; + } + else if ( pC0[i] > pC1[k] ) + { + pC[c++] = pC1[k++]; + if ( k >= nSize1 ) goto FlushCut0; + } + else + { + pC[c++] = pC0[i++]; k++; + if ( i >= nSize0 ) goto FlushCut1; + if ( k >= nSize1 ) goto FlushCut0; + } + } + +FlushCut0: + if ( c + nSize0 > nLutSize + i ) return 0; + while ( i < nSize0 ) + pC[c++] = pC0[i++]; + pCut->nLeaves = c; + pCut->iFunc = NF_NO_FUNC; + pCut->Sign = pCut0->Sign | pCut1->Sign; + return 1; + +FlushCut1: + if ( c + nSize1 > nLutSize + k ) return 0; + while ( k < nSize1 ) + pC[c++] = pC1[k++]; + pCut->nLeaves = c; + pCut->iFunc = NF_NO_FUNC; + pCut->Sign = pCut0->Sign | pCut1->Sign; + return 1; +} +static inline int Nf_CutMergeOrderMux( Nf_Cut_t * pCut0, Nf_Cut_t * pCut1, Nf_Cut_t * pCut2, Nf_Cut_t * pCut, int nLutSize ) +{ + int x0, i0 = 0, nSize0 = pCut0->nLeaves, * pC0 = pCut0->pLeaves; + int x1, i1 = 0, nSize1 = pCut1->nLeaves, * pC1 = pCut1->pLeaves; + int x2, i2 = 0, nSize2 = pCut2->nLeaves, * pC2 = pCut2->pLeaves; + int xMin, c = 0, * pC = pCut->pLeaves; + while ( 1 ) + { + x0 = (i0 == nSize0) ? ABC_INFINITY : pC0[i0]; + x1 = (i1 == nSize1) ? ABC_INFINITY : pC1[i1]; + x2 = (i2 == nSize2) ? ABC_INFINITY : pC2[i2]; + xMin = Abc_MinInt( Abc_MinInt(x0, x1), x2 ); + if ( xMin == ABC_INFINITY ) break; + if ( c == nLutSize ) return 0; + pC[c++] = xMin; + if (x0 == xMin) i0++; + if (x1 == xMin) i1++; + if (x2 == xMin) i2++; + } + pCut->nLeaves = c; + pCut->iFunc = NF_NO_FUNC; + pCut->Sign = pCut0->Sign | pCut1->Sign | pCut2->Sign; + return 1; +} +static inline int Nf_SetCutIsContainedOrder( Nf_Cut_t * pBase, Nf_Cut_t * pCut ) // check if pCut is contained in pBase +{ + int i, nSizeB = pBase->nLeaves; + int k, nSizeC = pCut->nLeaves; + if ( nSizeB == nSizeC ) + { + for ( i = 0; i < nSizeB; i++ ) + if ( pBase->pLeaves[i] != pCut->pLeaves[i] ) + return 0; + return 1; + } + assert( nSizeB > nSizeC ); + if ( nSizeC == 0 ) + return 1; + for ( i = k = 0; i < nSizeB; i++ ) + { + if ( pBase->pLeaves[i] > pCut->pLeaves[k] ) + return 0; + if ( pBase->pLeaves[i] == pCut->pLeaves[k] ) + { + if ( ++k == nSizeC ) + return 1; + } + } + return 0; +} +static inline int Nf_SetLastCutIsContained( Nf_Cut_t ** pCuts, int nCuts ) +{ + int i; + for ( i = 0; i < nCuts; i++ ) + if ( pCuts[i]->nLeaves <= pCuts[nCuts]->nLeaves && (pCuts[i]->Sign & pCuts[nCuts]->Sign) == pCuts[i]->Sign && Nf_SetCutIsContainedOrder(pCuts[nCuts], pCuts[i]) ) + return 1; + return 0; +} +static inline int Nf_SetLastCutContainsArea( Nf_Cut_t ** pCuts, int nCuts ) +{ + int i, k, fChanges = 0; + for ( i = 0; i < nCuts; i++ ) + if ( pCuts[nCuts]->nLeaves < pCuts[i]->nLeaves && (pCuts[nCuts]->Sign & pCuts[i]->Sign) == pCuts[nCuts]->Sign && Nf_SetCutIsContainedOrder(pCuts[i], pCuts[nCuts]) ) + pCuts[i]->nLeaves = NF_NO_LEAF, fChanges = 1; + if ( !fChanges ) + return nCuts; + for ( i = k = 0; i <= nCuts; i++ ) + { + if ( pCuts[i]->nLeaves == NF_NO_LEAF ) + continue; + if ( k < i ) + ABC_SWAP( Nf_Cut_t *, pCuts[k], pCuts[i] ); + k++; + } + return k - 1; +} +static inline int Nf_CutCompareArea( Nf_Cut_t * pCut0, Nf_Cut_t * pCut1 ) +{ + if ( pCut0->Useless < pCut1->Useless ) return -1; + if ( pCut0->Useless > pCut1->Useless ) return 1; + if ( pCut0->Flow < pCut1->Flow - NF_EPSILON ) return -1; + if ( pCut0->Flow > pCut1->Flow + NF_EPSILON ) return 1; + if ( pCut0->Delay < pCut1->Delay ) return -1; + if ( pCut0->Delay > pCut1->Delay ) return 1; + if ( pCut0->nLeaves < pCut1->nLeaves ) return -1; + if ( pCut0->nLeaves > pCut1->nLeaves ) return 1; + return 0; +} +static inline void Nf_SetSortByArea( Nf_Cut_t ** pCuts, int nCuts ) +{ + int i; + for ( i = nCuts; i > 0; i-- ) + { + if ( Nf_CutCompareArea(pCuts[i - 1], pCuts[i]) < 0 )//!= 1 ) + return; + ABC_SWAP( Nf_Cut_t *, pCuts[i - 1], pCuts[i] ); + } +} +static inline int Nf_SetAddCut( Nf_Cut_t ** pCuts, int nCuts, int nCutNum ) +{ + if ( nCuts == 0 ) + return 1; + nCuts = Nf_SetLastCutContainsArea(pCuts, nCuts); + Nf_SetSortByArea( pCuts, nCuts ); + return Abc_MinInt( nCuts + 1, nCutNum - 1 ); +} +static inline int Nf_CutArea( Nf_Man_t * p, int nLeaves ) +{ + if ( nLeaves < 2 ) + return 0; + return nLeaves + p->pPars->nAreaTuner; +} +static inline void Nf_CutParams( Nf_Man_t * p, Nf_Cut_t * pCut, float FlowRefs ) +{ + int i, nLeaves = pCut->nLeaves; + assert( nLeaves <= p->pPars->nLutSize ); + pCut->Delay = 0; + pCut->Flow = 0; + for ( i = 0; i < nLeaves; i++ ) + { + pCut->Delay = Abc_MaxInt( pCut->Delay, Nf_ObjCutDelay(p, pCut->pLeaves[i]) ); + pCut->Flow += Nf_ObjCutFlow(p, pCut->pLeaves[i]); + } + pCut->Delay += (int)(nLeaves > 1); + pCut->Flow = (pCut->Flow + Nf_CutArea(p, nLeaves)) / FlowRefs; +} +void Nf_ObjMergeOrder( Nf_Man_t * p, int iObj ) +{ + Nf_Cut_t pCuts0[NF_CUT_MAX], pCuts1[NF_CUT_MAX], pCuts[NF_CUT_MAX], * pCutsR[NF_CUT_MAX]; + Gia_Obj_t * pObj = Gia_ManObj(p->pGia, iObj); + //Nf_Obj_t * pBest = Nf_ManObj(p, iObj); + float dFlowRefs = Nf_ObjFlowRefs(p, iObj, 0) + Nf_ObjFlowRefs(p, iObj, 1); + int nLutSize = p->pPars->nLutSize; + int nCutNum = p->pPars->nCutNum; + int nCuts0 = Nf_ManPrepareCuts(pCuts0, p, Gia_ObjFaninId0(pObj, iObj), 1); + int nCuts1 = Nf_ManPrepareCuts(pCuts1, p, Gia_ObjFaninId1(pObj, iObj), 1); + int fComp0 = Gia_ObjFaninC0(pObj); + int fComp1 = Gia_ObjFaninC1(pObj); + int iSibl = Gia_ObjSibl(p->pGia, iObj); + Nf_Cut_t * pCut0, * pCut1, * pCut0Lim = pCuts0 + nCuts0, * pCut1Lim = pCuts1 + nCuts1; + int i, nCutsUse, nCutsR = 0; + assert( !Gia_ObjIsBuf(pObj) ); + for ( i = 0; i < nCutNum; i++ ) + pCutsR[i] = pCuts + i; + if ( iSibl ) + { + Nf_Cut_t pCuts2[NF_CUT_MAX]; + Gia_Obj_t * pObjE = Gia_ObjSiblObj(p->pGia, iObj); + int fCompE = Gia_ObjPhase(pObj) ^ Gia_ObjPhase(pObjE); + int nCuts2 = Nf_ManPrepareCuts(pCuts2, p, iSibl, 0); + Nf_Cut_t * pCut2, * pCut2Lim = pCuts2 + nCuts2; + for ( pCut2 = pCuts2; pCut2 < pCut2Lim; pCut2++ ) + { + *pCutsR[nCutsR] = *pCut2; + pCutsR[nCutsR]->iFunc = Abc_LitNotCond( pCutsR[nCutsR]->iFunc, fCompE ); + Nf_CutParams( p, pCutsR[nCutsR], dFlowRefs ); + nCutsR = Nf_SetAddCut( pCutsR, nCutsR, nCutNum ); + } + } + if ( Gia_ObjIsMuxId(p->pGia, iObj) ) + { + Nf_Cut_t pCuts2[NF_CUT_MAX]; + int nCuts2 = Nf_ManPrepareCuts(pCuts2, p, Gia_ObjFaninId2(p->pGia, iObj), 1); + int fComp2 = Gia_ObjFaninC2(p->pGia, pObj); + Nf_Cut_t * pCut2, * pCut2Lim = pCuts2 + nCuts2; + p->CutCount[0] += nCuts0 * nCuts1 * nCuts2; + for ( pCut0 = pCuts0; pCut0 < pCut0Lim; pCut0++ ) + for ( pCut1 = pCuts1; pCut1 < pCut1Lim; pCut1++ ) + for ( pCut2 = pCuts2; pCut2 < pCut2Lim; pCut2++ ) + { + if ( Nf_CutCountBits(pCut0->Sign | pCut1->Sign | pCut2->Sign) > nLutSize ) + continue; + p->CutCount[1]++; + if ( !Nf_CutMergeOrderMux(pCut0, pCut1, pCut2, pCutsR[nCutsR], nLutSize) ) + continue; + if ( Nf_SetLastCutIsContained(pCutsR, nCutsR) ) + continue; + p->CutCount[2]++; + if ( Nf_CutComputeTruthMux6(p, pCut0, pCut1, pCut2, fComp0, fComp1, fComp2, pCutsR[nCutsR]) ) + pCutsR[nCutsR]->Sign = Nf_CutGetSign(pCutsR[nCutsR]->pLeaves, pCutsR[nCutsR]->nLeaves); + Nf_CutParams( p, pCutsR[nCutsR], dFlowRefs ); + nCutsR = Nf_SetAddCut( pCutsR, nCutsR, nCutNum ); + } + } + else + { + int fIsXor = Gia_ObjIsXor(pObj); + p->CutCount[0] += nCuts0 * nCuts1; + for ( pCut0 = pCuts0; pCut0 < pCut0Lim; pCut0++ ) + for ( pCut1 = pCuts1; pCut1 < pCut1Lim; pCut1++ ) + { + if ( (int)(pCut0->nLeaves + pCut1->nLeaves) > nLutSize && Nf_CutCountBits(pCut0->Sign | pCut1->Sign) > nLutSize ) + continue; + p->CutCount[1]++; + if ( !Nf_CutMergeOrder(pCut0, pCut1, pCutsR[nCutsR], nLutSize) ) + continue; + if ( Nf_SetLastCutIsContained(pCutsR, nCutsR) ) + continue; + p->CutCount[2]++; + if ( Nf_CutComputeTruth6(p, pCut0, pCut1, fComp0, fComp1, pCutsR[nCutsR], fIsXor) ) + pCutsR[nCutsR]->Sign = Nf_CutGetSign(pCutsR[nCutsR]->pLeaves, pCutsR[nCutsR]->nLeaves); + Nf_CutParams( p, pCutsR[nCutsR], dFlowRefs ); + nCutsR = Nf_SetAddCut( pCutsR, nCutsR, nCutNum ); + } + } + // debug printout + if ( 0 ) +// if ( iObj % 10000 == 0 ) +// if ( iObj == 1090 ) + { + printf( "*** Obj = %d Useful = %d\n", iObj, Nf_ManCountUseful(pCutsR, nCutsR) ); + for ( i = 0; i < nCutsR; i++ ) + Nf_CutPrint( p, pCutsR[i] ); + printf( "\n" ); + } + // verify + assert( nCutsR > 0 && nCutsR < nCutNum ); +// assert( Nf_SetCheckArray(pCutsR, nCutsR) ); + // store the cutset + Nf_ObjSetCutFlow( p, iObj, pCutsR[0]->Flow ); + Nf_ObjSetCutDelay( p, iObj, pCutsR[0]->Delay ); + *Vec_IntEntryP(&p->vCutSets, iObj) = Nf_ManSaveCuts(p, pCutsR, nCutsR, 0); + p->CutCount[3] += nCutsR; + nCutsUse = Nf_ManCountUseful(pCutsR, nCutsR); + p->CutCount[4] += nCutsUse; + p->nCutUseAll += nCutsUse == nCutsR; + p->CutCount[5] += Nf_ManCountMatches(p, pCutsR, nCutsR); +} +void Nf_ManComputeCuts( Nf_Man_t * p ) +{ + Gia_Obj_t * pObj; int i, iFanin, arrTime; + float CutFlow = 0, CutFlowAve = 0; int fFirstCi = 0, nCutFlow = 0; + if ( p->pManTim ) + Tim_ManIncrementTravId( p->pManTim ); + Gia_ManForEachObjWithBoxes( p->pGia, pObj, i ) + if ( Gia_ObjIsBuf(pObj) ) + { + iFanin = Gia_ObjFaninId0(pObj, i); + Nf_ObjSetCutFlow( p, i, Nf_ObjCutFlow(p, iFanin) ); + Nf_ObjSetCutDelay( p, i, Nf_ObjCutDelay(p, iFanin) ); + } + else if ( Gia_ObjIsAnd(pObj) ) + Nf_ObjMergeOrder( p, i ); + else if ( Gia_ObjIsCi(pObj) ) + { + if ( fFirstCi ) { + CutFlowAve = CutFlow / nCutFlow; + CutFlow = 0; + nCutFlow = 0; + fFirstCi = 0; + } + arrTime = Tim_ManGetCiArrival( p->pManTim, Gia_ObjCioId(pObj) ); + Nf_ObjSetCutFlow( p, i, CutFlowAve ); // approximation! + Nf_ObjSetCutDelay( p, i, arrTime ); + } + else if ( Gia_ObjIsCo(pObj) ) + { + iFanin = Gia_ObjFaninId0(pObj, i); + CutFlow += Nf_ObjCutFlow(p, iFanin); + arrTime = Nf_ObjCutDelay(p, iFanin); + Tim_ManSetCoArrival( p->pManTim, Gia_ObjCioId(pObj), arrTime ); + nCutFlow++; + fFirstCi = 1; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nf_ManPrintStats( Nf_Man_t * p, char * pTitle ) +{ + if ( !p->pPars->fVerbose ) + return; + printf( "%s : ", pTitle ); + printf( "Delay =%8.2f ", Scl_Int2Flt(p->pPars->MapDelay) ); + printf( "Area =%12.2f ", p->pPars->MapAreaF ); + printf( "Gate =%6d ", (int)p->pPars->Area ); + printf( "Inv =%6d ", (int)p->nInvs ); + printf( "Edge =%7d ", (int)p->pPars->Edge ); + Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); + fflush( stdout ); +} +void Nf_ManPrintInit( Nf_Man_t * p ) +{ + int nChoices; + if ( !p->pPars->fVerbose ) + return; + printf( "LutSize = %d ", p->pPars->nLutSize ); + printf( "CutNum = %d ", p->pPars->nCutNum ); + printf( "Iter = %d ", p->pPars->nRounds );//+ p->pPars->nRoundsEla ); + printf( "Coarse = %d ", p->pPars->fCoarsen ); + printf( "Cells = %d ", p->nCells ); + printf( "Funcs = %d ", Vec_MemEntryNum(p->vTtMem) ); + printf( "Matches = %d ", Vec_WecSizeSize(p->vTt2Match)/2 ); + printf( "And = %d ", Gia_ManAndNum(p->pGia) ); + nChoices = Gia_ManChoiceNum( p->pGia ); + if ( nChoices ) + printf( "Choices = %d ", nChoices ); + printf( "\n" ); + printf( "Computing cuts...\r" ); + fflush( stdout ); +} +void Nf_ManPrintQuit( Nf_Man_t * p ) +{ + float MemGia = Gia_ManMemory(p->pGia) / (1<<20); + float MemMan =(1.0 * sizeof(Nf_Obj_t) + 8.0 * sizeof(int)) * Gia_ManObjNum(p->pGia) / (1<<20); + float MemCuts = 1.0 * sizeof(int) * (1 << 16) * Vec_PtrSize(&p->vPages) / (1<<20); + float MemTt = p->vTtMem ? Vec_MemMemory(p->vTtMem) / (1<<20) : 0; + if ( p->CutCount[0] == 0 ) + p->CutCount[0] = 1; + if ( !p->pPars->fVerbose ) + return; + printf( "CutPair = %.0f ", p->CutCount[0] ); + printf( "Merge = %.0f (%.1f) ", p->CutCount[1], 1.0*p->CutCount[1]/Gia_ManAndNum(p->pGia) ); + printf( "Eval = %.0f (%.1f) ", p->CutCount[2], 1.0*p->CutCount[2]/Gia_ManAndNum(p->pGia) ); + printf( "Cut = %.0f (%.1f) ", p->CutCount[3], 1.0*p->CutCount[3]/Gia_ManAndNum(p->pGia) ); + printf( "Use = %.0f (%.1f) ", p->CutCount[4], 1.0*p->CutCount[4]/Gia_ManAndNum(p->pGia) ); + printf( "Mat = %.0f (%.1f) ", p->CutCount[5], 1.0*p->CutCount[5]/Gia_ManAndNum(p->pGia) ); +// printf( "Equ = %d (%.2f %%) ", p->nCutUseAll, 100.0*p->nCutUseAll /p->CutCount[0] ); + printf( "\n" ); + printf( "Gia = %.2f MB ", MemGia ); + printf( "Man = %.2f MB ", MemMan ); + printf( "Cut = %.2f MB ", MemCuts ); + printf( "TT = %.2f MB ", MemTt ); + printf( "Total = %.2f MB ", MemGia + MemMan + MemCuts + MemTt ); +// printf( "\n" ); + Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); + fflush( stdout ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nf_ManCutMatchPrint( Nf_Man_t * p, int iObj, char * pStr, Nf_Mat_t * pM ) +{ + Mio_Cell2_t * pCell; + int i, * pCut; + printf( "%5d %s : ", iObj, pStr ); + if ( pM->CutH == 0 ) + { + printf( "Unassigned\n" ); + return; + } + pCell = Nf_ManCell( p, pM->Gate ); + pCut = Nf_CutFromHandle( Nf_ObjCutSet(p, iObj), pM->CutH ); + printf( "D =%6.2f ", Scl_Int2Flt(pM->D) ); + printf( "A =%6.2f ", pM->F ); + printf( "C = %d ", pM->fCompl ); +// printf( "B = %d ", pM->fBest ); + printf( " " ); + printf( "Cut = {" ); + for ( i = 0; i < (int)pCell->nFanins; i++ ) + printf( "%4d ", Nf_CutLeaves(pCut)[i] ); + for ( ; i < 6; i++ ) + printf( " " ); + printf( "} " ); + printf( "%10s ", pCell->pName ); + printf( "%d ", pCell->nFanins ); + printf( "{" ); + for ( i = 0; i < (int)pCell->nFanins; i++ ) + printf( "%6.2f ", Scl_Int2Flt(pCell->iDelays[i]) ); + for ( ; i < 6; i++ ) + printf( " " ); + printf( " } " ); + for ( i = 0; i < (int)pCell->nFanins; i++ ) + printf( "%s%d ", Nf_CfgCompl(pM->Cfg, i) ? "!":" ", Nf_CfgVar(pM->Cfg, i) ); + for ( ; i < 6; i++ ) + printf( " " ); + Dau_DsdPrintFromTruth( &pCell->uTruth, pCell->nFanins ); +} +void Nf_ManCutMatchOne( Nf_Man_t * p, int iObj, int * pCut, int * pCutSet ) +{ + Nf_Obj_t * pBest = Nf_ManObj(p, iObj); + int * pFans = Nf_CutLeaves(pCut); + int nFans = Nf_CutSize(pCut); + int iFuncLit = Nf_CutFunc(pCut); + int fComplExt = Abc_LitIsCompl(iFuncLit); + Vec_Int_t * vArr = Vec_WecEntry( p->vTt2Match, Abc_Lit2Var(iFuncLit) ); + int i, k, c, Info, Offset, iFanin, fComplF; + int ArrivalD, ArrivalA; + Nf_Mat_t * pD, * pA; + // assign fanins matches + Nf_Obj_t * pBestF[NF_LEAF_MAX]; + for ( i = 0; i < nFans; i++ ) + pBestF[i] = Nf_ManObj( p, pFans[i] ); + // special cases + if ( nFans == 0 ) + { + int Const = (iFuncLit == 1); + assert( iFuncLit == 0 || iFuncLit == 1 ); + for ( c = 0; c < 2; c++ ) + { + pD = Nf_ObjMatchD( p, iObj, c ); + pA = Nf_ObjMatchA( p, iObj, c ); + pD->D = pA->D = 0; + pD->F = pA->F = p->pCells[c ^ Const].AreaF; + pD->CutH = pA->CutH = Nf_CutHandle(pCutSet, pCut); + pD->Gate = pA->Gate = c ^ Const; +// pD->Conf = pA->Conf = 0; + pD->Cfg = pA->Cfg = Nf_Int2Cfg(0); + } + return; + } + // consider matches of this function + Vec_IntForEachEntryDouble( vArr, Info, Offset, i ) + { + Nf_Cfg_t Cfg = Nf_Int2Cfg(Offset); + Mio_Cell2_t*pC = Nf_ManCell( p, Info ); + int fCompl = Cfg.fCompl ^ fComplExt; + int Required = Nf_ObjRequired( p, iObj, fCompl ), Delay = 0; + Nf_Mat_t * pD = &pBest->M[fCompl][0]; + Nf_Mat_t * pA = &pBest->M[fCompl][1]; + float AreaF = pC->AreaF; + assert( nFans == (int)pC->nFanins ); + Nf_CfgForEachVarCompl( Cfg, nFans, iFanin, fComplF, k ) + { + ArrivalD = pBestF[iFanin]->M[fComplF][0].D; + ArrivalA = pBestF[iFanin]->M[fComplF][1].D; + if ( ArrivalA + pC->iDelays[k] <= Required && Required != SCL_INFINITY ) + { + Delay = Abc_MaxInt( Delay, ArrivalA + pC->iDelays[k] ); + if ( AreaF >= (float)1e32 || pBestF[iFanin]->M[fComplF][1].F >= (float)1e32 ) + AreaF = (float)1e32; + else + AreaF += pBestF[iFanin]->M[fComplF][1].F; + } + else + { + if ( pD->D < SCL_INFINITY && pA->D < SCL_INFINITY && ArrivalD + pC->iDelays[k] > Required ) + break; + Delay = Abc_MaxInt( Delay, ArrivalD + pC->iDelays[k] ); + //AreaF += pBestF[iFanin]->M[fComplF][0].F; + if ( AreaF >= (float)1e32 || pBestF[iFanin]->M[fComplF][0].F >= (float)1e32 ) + AreaF = (float)1e32; + else + AreaF += pBestF[iFanin]->M[fComplF][0].F; + } + } + if ( k < nFans ) + continue; + // select best Cfgch + if ( pD->D > Delay ) + { + pD->D = Delay; + pD->F = AreaF; + pD->CutH = Nf_CutHandle(pCutSet, pCut); + pD->Gate = pC->Id; + pD->Cfg = Cfg; + pD->Cfg.fCompl = 0; + } + + if ( pA->F > AreaF + NF_EPSILON ) + { + pA->D = Delay; + pA->F = AreaF; + pA->CutH = Nf_CutHandle(pCutSet, pCut); + pA->Gate = pC->Id; + pA->Cfg = Cfg; + pA->Cfg.fCompl = 0; + } + } +} +static inline void Nf_ObjPrepareCi( Nf_Man_t * p, int iObj, int Time ) +{ + Nf_Mat_t * pD0 = Nf_ObjMatchD( p, iObj, 0 ); + Nf_Mat_t * pA0 = Nf_ObjMatchA( p, iObj, 0 ); + Nf_Mat_t * pD = Nf_ObjMatchD( p, iObj, 1 ); + Nf_Mat_t * pA = Nf_ObjMatchA( p, iObj, 1 ); + pD0->D = pA0->D = pD->D = pA->D = Time; + pD->fCompl = 1; + pD->D += p->InvDelayI; + pD->F = p->InvAreaF; + pA->fCompl = 1; + pA->D += p->InvDelayI; + pA->F = p->InvAreaF; + Nf_ObjMatchD( p, iObj, 0 )->fBest = 1; + Nf_ObjMatchD( p, iObj, 1 )->fBest = 1; +} +static inline void Nf_ObjPrepareBuf( Nf_Man_t * p, Gia_Obj_t * pObj ) +{ + // get fanin info + int iObj = Gia_ObjId( p->pGia, pObj ); + int iFanin = Gia_ObjFaninId0( pObj, iObj ); + Nf_Mat_t * pDf = Nf_ObjMatchD( p, iFanin, Gia_ObjFaninC0(pObj) ); + //Nf_Mat_t * pAf = Nf_ObjMatchA( p, iFanin, Gia_ObjFaninC0(pObj) ); + // set the direct phase + Nf_Mat_t * pDp = Nf_ObjMatchD( p, iObj, 0 ); + Nf_Mat_t * pAp = Nf_ObjMatchA( p, iObj, 0 ); + Nf_Mat_t * pDn = Nf_ObjMatchD( p, iObj, 1 ); + Nf_Mat_t * pAn = Nf_ObjMatchA( p, iObj, 1 ); + assert( Gia_ObjIsBuf(pObj) ); + memset( Nf_ManObj(p, iObj), 0, sizeof(Nf_Obj_t) ); + // set the direct phase + pDp->D = pAp->D = pDf->D; + pDp->F = pAp->F = pDf->F; // do not pass flow??? + pDp->fBest = 1; + // set the inverted phase + pDn->D = pAn->D = pDf->D + p->InvDelayI; + pDn->F = pAn->F = pDf->F + p->InvAreaF; + pDn->fCompl = pAn->fCompl = 1; + pDn->fBest = 1; +} +static inline int Nf_CutRequired( Nf_Man_t * p, Nf_Mat_t * pM, int * pCutSet ) +{ + Mio_Cell2_t * pCell = Nf_ManCell( p, pM->Gate ); + int * pCut = Nf_CutFromHandle( pCutSet, pM->CutH ); + int i, iVar, fCompl; + int Arr, Req, Arrival = 0, Required = 0; + Nf_CutForEachVarCompl( pCut, pM->Cfg, iVar, fCompl, i ) + { + Arr = Nf_ManObj(p, iVar)->M[fCompl][0].D + pCell->iDelays[i]; + Req = Nf_ObjRequired(p, iVar, fCompl); + Arrival = Abc_MaxInt( Arrival, Arr ); + if ( Req < SCL_INFINITY ) + Required = Abc_MaxInt( Required, Req + pCell->iDelays[i] ); + } + return Abc_MaxInt( Required + p->pPars->nReqTimeFlex*p->InvDelayI, Arrival ); +} +static inline void Nf_ObjComputeRequired( Nf_Man_t * p, int iObj ) +{ + Nf_Obj_t * pBest = Nf_ManObj(p, iObj); + int c, * pCutSet = Nf_ObjCutSet( p, iObj ); + for ( c = 0; c < 2; c++ ) + if ( Nf_ObjRequired(p, iObj, c) == SCL_INFINITY ) + Nf_ObjSetRequired( p, iObj, c, Nf_CutRequired(p, &pBest->M[c][0], pCutSet) ); +} +void Nf_ManCutMatch( Nf_Man_t * p, int iObj ) +{ + Nf_Obj_t * pBest = Nf_ManObj(p, iObj); + Nf_Mat_t * pDp = &pBest->M[0][0]; + Nf_Mat_t * pDn = &pBest->M[1][0]; + Nf_Mat_t * pAp = &pBest->M[0][1]; + Nf_Mat_t * pAn = &pBest->M[1][1]; + float FlowRefPf = Nf_ObjFlowRefs(p, iObj, 0); + float FlowRefNf = Nf_ObjFlowRefs(p, iObj, 1); + int i, * pCut, * pCutSet = Nf_ObjCutSet( p, iObj ); + int Required[2] = {0}; + if ( p->Iter ) + { + Nf_ObjComputeRequired( p, iObj ); + Required[0] = Nf_ObjRequired( p, iObj, 0 ); + Required[1] = Nf_ObjRequired( p, iObj, 1 ); + } + memset( pBest, 0, sizeof(Nf_Obj_t) ); + pDp->D = SCL_INFINITY; pDp->F = FLT_MAX; + pDn->D = SCL_INFINITY; pDn->F = FLT_MAX; + pAp->D = SCL_INFINITY; pAp->F = FLT_MAX; + pAn->D = SCL_INFINITY; pAn->F = FLT_MAX; + Nf_SetForEachCut( pCutSet, pCut, i ) + { + if ( Abc_Lit2Var(Nf_CutFunc(pCut)) >= Vec_WecSize(p->vTt2Match) ) + continue; + assert( !Nf_CutIsTriv(pCut, iObj) ); + assert( Nf_CutSize(pCut) <= p->pPars->nLutSize ); + assert( Abc_Lit2Var(Nf_CutFunc(pCut)) < Vec_WecSize(p->vTt2Match) ); + Nf_ManCutMatchOne( p, iObj, pCut, pCutSet ); + } + +/* + if ( 461 == iObj && p->Iter == 0 ) + { + printf( "\nObj %6d (%.2f %.2f):\n", iObj, Scl_Int2Flt(Required[0]), Scl_Int2Flt(Required[1]) ); + Nf_ManCutMatchPrint( p, iObj, "Dp", &pBest->M[0][0] ); + Nf_ManCutMatchPrint( p, iObj, "Dn", &pBest->M[1][0] ); + Nf_ManCutMatchPrint( p, iObj, "Ap", &pBest->M[0][1] ); + Nf_ManCutMatchPrint( p, iObj, "An", &pBest->M[1][1] ); + printf( "\n" ); + } +*/ + // divide by ref count + pDp->F = pDp->F / FlowRefPf; + pAp->F = pAp->F / FlowRefPf; + pDn->F = pDn->F / FlowRefNf; + pAn->F = pAn->F / FlowRefNf; + + // add the inverters + assert( pDp->D < SCL_INFINITY || pDn->D < SCL_INFINITY ); + if ( pDp->D > pDn->D + p->InvDelayI ) + { + *pDp = *pDn; + pDp->D += p->InvDelayI; + pDp->F += p->InvAreaF; + pDp->fCompl = 1; + if ( pAp->D == SCL_INFINITY ) + *pAp = *pDp; + //printf( "Using inverter to improve delay at node %d in phase %d.\n", iObj, 1 ); + } + else if ( pDn->D > pDp->D + p->InvDelayI ) + { + *pDn = *pDp; + pDn->D += p->InvDelayI; + pDn->F += p->InvAreaF; + pDn->fCompl = 1; + if ( pAn->D == SCL_INFINITY ) + *pAn = *pDn; + //printf( "Using inverter to improve delay at node %d in phase %d.\n", iObj, 0 ); + } + //assert( pAp->F < FLT_MAX || pAn->F < FLT_MAX ); + // try replacing pos with neg + if ( pAp->D == SCL_INFINITY || (pAp->F > pAn->F + p->InvAreaF + NF_EPSILON && pAn->D + p->InvDelayI <= Required[0]) ) + { + assert( p->Iter > 0 ); + *pAp = *pAn; + pAp->D += p->InvDelayI; + pAp->F += p->InvAreaF; + pAp->fCompl = 1; + if ( pDp->D == SCL_INFINITY ) + *pDp = *pAp; + //printf( "Using inverter to improve area at node %d in phase %d.\n", iObj, 1 ); + } + // try replacing neg with pos + else if ( pAn->D == SCL_INFINITY || (pAn->F > pAp->F + p->InvAreaF + NF_EPSILON && pAp->D + p->InvDelayI <= Required[1]) ) + { + assert( p->Iter > 0 ); + *pAn = *pAp; + pAn->D += p->InvDelayI; + pAn->F += p->InvAreaF; + pAn->fCompl = 1; + if ( pDn->D == SCL_INFINITY ) + *pDn = *pAn; + //printf( "Using inverter to improve area at node %d in phase %d.\n", iObj, 0 ); + } + + if ( pDp->D == SCL_INFINITY ) + printf( "Object %d has pDp unassigned.\n", iObj ); + if ( pDn->D == SCL_INFINITY ) + printf( "Object %d has pDn unassigned.\n", iObj ); + if ( pAp->D == SCL_INFINITY ) + printf( "Object %d has pAp unassigned.\n", iObj ); + if ( pAn->D == SCL_INFINITY ) + printf( "Object %d has pAn unassigned.\n", iObj ); +/* + pDp->F = Abc_MinFloat( pDp->F, FLT_MAX/SCL_NUM ); + pDn->F = Abc_MinFloat( pDn->F, FLT_MAX/SCL_NUM ); + pAp->F = Abc_MinFloat( pAp->F, FLT_MAX/SCL_NUM ); + pAn->F = Abc_MinFloat( pAn->F, FLT_MAX/SCL_NUM ); +*/ + assert( pDp->D < SCL_INFINITY ); + assert( pDn->D < SCL_INFINITY ); + assert( pAp->D < SCL_INFINITY ); + assert( pAn->D < SCL_INFINITY ); + + assert( pDp->F < FLT_MAX ); + assert( pDn->F < FLT_MAX ); + assert( pAp->F < FLT_MAX ); + assert( pAn->F < FLT_MAX ); + +/* + if ( p->Iter && (pDp->D > Required[0] || pDn->D > Required[1]) ) + { + printf( "%5d : ", iObj ); + printf( "Dp = %6.2f ", Scl_Int2Flt(pDp->D) ); + printf( "Dn = %6.2f ", Scl_Int2Flt(pDn->D) ); + printf( " " ); + printf( "Ap = %6.2f ", Scl_Int2Flt(pAp->D) ); + printf( "An = %6.2f ", Scl_Int2Flt(pAn->D) ); + printf( " " ); + printf( "Rp = %6.2f ", Scl_Int2Flt(Required[0]) ); + printf( "Rn = %6.2f ", Scl_Int2Flt(Required[1]) ); + printf( "\n" ); + } +*/ +} +static inline Nf_Mat_t * Nf_ObjMatchBest( Nf_Man_t * p, int i, int c ) +{ + Nf_Mat_t * pD = Nf_ObjMatchD(p, i, c); + Nf_Mat_t * pA = Nf_ObjMatchA(p, i, c); + assert( pD->fBest != pA->fBest ); + //assert( Nf_ObjMapRefNum(p, i, c) > 0 ); + if ( pA->fBest ) + return pA; + if ( pD->fBest ) + return pD; + return NULL; +} +void Nf_ManComputeMapping( Nf_Man_t * p ) +{ + Gia_Obj_t * pObj; int i, arrTime; + if ( p->pManTim ) + Tim_ManIncrementTravId( p->pManTim ); + Gia_ManForEachObjWithBoxes( p->pGia, pObj, i ) + if ( Gia_ObjIsBuf(pObj) ) + Nf_ObjPrepareBuf( p, pObj ); + else if ( Gia_ObjIsAnd(pObj) ) + Nf_ManCutMatch( p, i ); + else if ( Gia_ObjIsCi(pObj) ) { + arrTime = Tim_ManGetCiArrival( p->pManTim, Gia_ObjCioId(pObj) ); + Nf_ObjPrepareCi( p, i, arrTime ); + } + else if ( Gia_ObjIsCo(pObj) ) { + arrTime = Nf_ObjMatchD( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj) )->D; + Tim_ManSetCoArrival( p->pManTim, Gia_ObjCioId(pObj), arrTime ); + } +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nf_ManSetOutputRequireds( Nf_Man_t * p, int fPropCompl ) +{ + Gia_Obj_t * pObj; + int Required = 0, MapDelayOld = p->pPars->MapDelay; + int fUseConMan = Scl_ConIsRunning() && Scl_ConHasOutReqs(); + int i, iObj, fCompl, nLits = 2*Gia_ManObjNum(p->pGia); + Vec_IntFill( &p->vRequired, nLits, SCL_INFINITY ); + // compute delay + p->pPars->MapDelay = 0; + Gia_ManForEachCoWithBoxes( p->pGia, pObj, i ) + { + Required = Nf_ObjMatchD( p, Gia_ObjFaninId0p(p->pGia, pObj), Gia_ObjFaninC0(pObj) )->D; + p->pPars->MapDelay = Abc_MaxInt( p->pPars->MapDelay, Required ); + } + if ( p->Iter && MapDelayOld < p->pPars->MapDelay && p->pGia->vOutReqs == NULL ) + printf( "******** Critical delay violation %.2f -> %.2f ********\n", Scl_Int2Flt(MapDelayOld), Scl_Int2Flt(p->pPars->MapDelay) ); + p->pPars->MapDelay = Abc_MaxInt( p->pPars->MapDelay, MapDelayOld ); + // check delay target + if ( p->pPars->MapDelayTarget == 0 && p->pPars->nRelaxRatio ) + p->pPars->MapDelayTarget = p->pPars->MapDelay * (100 + p->pPars->nRelaxRatio) / 100; + if ( p->pPars->MapDelayTarget > 0 ) + { + if ( p->pPars->MapDelay < p->pPars->MapDelayTarget ) + p->pPars->MapDelay = p->pPars->MapDelayTarget; + else if ( p->pPars->nRelaxRatio == 0 ) + Abc_Print( 0, "Relaxing user-specified delay target from %.2f to %.2f.\n", Scl_Int2Flt(p->pPars->MapDelayTarget), Scl_Int2Flt(p->pPars->MapDelay) ); + } + //assert( p->pPars->MapDelayTarget == 0 ); + // set required times + if ( p->pManTim ) + Tim_ManIncrementTravId( p->pManTim ); + Gia_ManForEachCoWithBoxes( p->pGia, pObj, i ) + { + iObj = Gia_ObjFaninId0p(p->pGia, pObj); + fCompl = Gia_ObjFaninC0(pObj); + Required = Nf_ObjMatchD(p, iObj, fCompl)->D; + Required = p->pPars->fDoAverage ? Required * (100 + p->pPars->nRelaxRatio) / 100 : p->pPars->MapDelay; + // if external required time can be achieved, use it + if ( fUseConMan ) + { + if ( Scl_ConGetOutReq(i) > 0 && Required <= Scl_ConGetOutReq(i) ) + Required = Scl_ConGetOutReq(i); + } + else if ( p->pGia->vOutReqs ) + { + int NewRequired = Scl_Flt2Int(Vec_FltEntry(p->pGia->vOutReqs, i)); + if ( NewRequired > 0 && Required <= NewRequired ) + Required = Abc_MinInt( 2*Required, NewRequired ); + } + // if external required cannot be achieved, set the earliest possible arrival time +// else if ( p->pGia->vOutReqs && Vec_FltEntry(p->pGia->vOutReqs, i) > 0 && Required > Vec_FltEntry(p->pGia->vOutReqs, i) ) +// ptTime->Rise = ptTime->Fall = ptTime->Worst = Required; + // otherwise, set the global required time + Nf_ObjUpdateRequired( p, iObj, fCompl, Required ); + if ( fPropCompl && iObj > 0 && Nf_ObjMatchBest(p, iObj, fCompl)->fCompl ) + Nf_ObjUpdateRequired( p, iObj, !fCompl, Required - p->InvDelayI ); + + if ( p->pManTim == NULL ) + continue; + if ( fPropCompl && iObj > 0 && Nf_ObjMatchBest(p, iObj, fCompl)->fCompl ) + Tim_ManSetCoRequired( p->pManTim, Gia_ObjCioId(pObj), Required - p->InvDelayI ); + else + Tim_ManSetCoRequired( p->pManTim, Gia_ObjCioId(pObj), Required ); + //Nf_ObjMapRefInc( p, Gia_ObjFaninId0p(p->pGia, pObj), Gia_ObjFaninC0(pObj)); + } +} +void Nf_ManSetMapRefsGate( Nf_Man_t * p, int iObj, int Required, Nf_Mat_t * pM ) +{ + int k, iVar, fCompl; + Mio_Cell2_t * pCell = Nf_ManCell( p, pM->Gate ); + int * pCut = Nf_CutFromHandle( Nf_ObjCutSet(p, iObj), pM->CutH ); + Nf_CutForEachVarCompl( pCut, pM->Cfg, iVar, fCompl, k ) + { + Nf_ObjMapRefInc( p, iVar, fCompl ); + Nf_ObjUpdateRequired( p, iVar, fCompl, Required - pCell->iDelays[k] ); + } + assert( Nf_CutSize(pCut) == (int)pCell->nFanins ); + // update global stats + p->pPars->MapAreaF += pCell->AreaF; + p->pPars->Edge += Nf_CutSize(pCut); + p->pPars->Area++; + // update status of the gate + assert( pM->fBest == 0 ); + pM->fBest = 1; +} +void Nf_ManPrintMatches( Nf_Man_t * p ) +{ + Gia_Obj_t * pObj; int i; + Gia_ManForEachAnd( p->pGia, pObj, i ) + { + Nf_Mat_t * pDp = Nf_ObjMatchD( p, i, 0 ); + Nf_Mat_t * pAp = Nf_ObjMatchA( p, i, 0 ); + Nf_Mat_t * pDn = Nf_ObjMatchD( p, i, 1 ); + Nf_Mat_t * pAn = Nf_ObjMatchA( p, i, 1 ); + + printf( "%5d : ", i ); + printf( "Dp = %6.2f ", Scl_Int2Flt(pDp->D) ); + printf( "Dn = %6.2f ", Scl_Int2Flt(pDn->D) ); + printf( " " ); + printf( "Ap = %6.2f ", Scl_Int2Flt(pAp->D) ); + printf( "An = %6.2f ", Scl_Int2Flt(pAn->D) ); + printf( " " ); + printf( "Dp = %8s ", Nf_ManCell(p, pDp->Gate)->pName ); + printf( "Dn = %8s ", Nf_ManCell(p, pDn->Gate)->pName ); + printf( "Ap = %8s ", Nf_ManCell(p, pAp->Gate)->pName ); + printf( "An = %8s ", Nf_ManCell(p, pAn->Gate)->pName ); + printf( "\n" ); + + } +} +int Nf_ManSetMapRefs( Nf_Man_t * p ) +{ + float Coef = 1.0 / (1.0 + (p->Iter + 1) * (p->Iter + 1)); + float * pFlowRefs = Vec_FltArray( &p->vFlowRefs ); + int * pMapRefs = Vec_IntArray( &p->vMapRefs ); + int nLits = 2*Gia_ManObjNum(p->pGia); + int i, c, Id, nRefs[2], reqTime; + Gia_Obj_t * pObj; + Nf_Mat_t * pD, * pA, * pM; + Nf_Mat_t * pDs[2], * pAs[2], * pMs[2]; + int Required = 0, Requireds[2]; + assert( !p->fUseEla ); +// if ( p->Iter == 0 ) +// Nf_ManPrintMatches( p ); + Nf_ManSetOutputRequireds( p, 0 ); + // set output references + memset( pMapRefs, 0, sizeof(int) * nLits ); + Gia_ManForEachCo( p->pGia, pObj, i ) + Nf_ObjMapRefInc( p, Gia_ObjFaninId0p(p->pGia, pObj), Gia_ObjFaninC0(pObj)); + + // compute area and edges + p->nInvs = 0; + p->pPars->MapAreaF = 0; + p->pPars->Area = p->pPars->Edge = 0; + Gia_ManForEachObjReverseWithBoxes( p->pGia, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + { + if ( Nf_ObjMapRefNum(p, i, 1) ) + { + Nf_ObjMapRefInc( p, i, 0 ); + Nf_ObjUpdateRequired( p, i, 0, Nf_ObjRequired(p, i, 1) - p->InvDelayI ); + p->pPars->MapAreaF += p->InvAreaF; + p->pPars->Edge++; + p->pPars->Area++; + p->nInvs++; + } + Nf_ObjUpdateRequired( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj), Nf_ObjRequired(p, i, 0) ); + Nf_ObjMapRefInc( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj)); + continue; + } + if ( Gia_ObjIsCi(pObj) ) + { + if ( Nf_ObjMapRefNum(p, i, 1) ) + { + Nf_ObjMapRefInc( p, i, 0 ); + Nf_ObjUpdateRequired( p, i, 0, Nf_ObjRequired(p, i, 1) - p->InvDelayI ); + p->pPars->MapAreaF += p->InvAreaF; + p->pPars->Edge++; + p->pPars->Area++; + p->nInvs++; + } + Tim_ManSetCiRequired( p->pManTim, Gia_ObjCioId(pObj), Nf_ObjRequired(p, i, 0) ); + continue; + } + if ( Gia_ObjIsCo(pObj) ) + { + reqTime = Tim_ManGetCoRequired( p->pManTim, Gia_ObjCioId(pObj) ); + Nf_ObjUpdateRequired( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj), reqTime ); + Nf_ObjMapRefInc( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj)); + continue; + } + // skip if this node is not used + for ( c = 0; c < 2; c++ ) + nRefs[c] = Nf_ObjMapRefNum(p, i, c); + if ( !nRefs[0] && !nRefs[1] ) + continue; + + // consider two cases + if ( nRefs[0] && nRefs[1] ) + { + // find best matches for both phases + for ( c = 0; c < 2; c++ ) + { + Requireds[c] = Nf_ObjRequired( p, i, c ); + //assert( Requireds[c] < SCL_INFINITY ); + pDs[c] = Nf_ObjMatchD( p, i, c ); + pAs[c] = Nf_ObjMatchA( p, i, c ); + pMs[c] = (pAs[c]->D <= Requireds[c]) ? pAs[c] : pDs[c]; + } + // swap complemented matches + if ( pMs[0]->fCompl && pMs[1]->fCompl ) + { +// pMs[0]->fCompl = pMs[1]->fCompl = 0; +// ABC_SWAP( Nf_Mat_t *, pMs[0], pMs[1] ); + // find best matches for both phases + pMs[0] = Nf_ObjMatchD( p, i, 0 ); + pMs[1] = Nf_ObjMatchD( p, i, 1 ); + assert( !pMs[0]->fCompl || !pMs[1]->fCompl ); + } + // check if intervers are involved + if ( !pMs[0]->fCompl && !pMs[1]->fCompl ) // no inverters + { + for ( c = 0; c < 2; c++ ) + Nf_ManSetMapRefsGate( p, i, Requireds[c], pMs[c] ); + } + else + { + // one interver + assert( !pMs[0]->fCompl || !pMs[1]->fCompl ); + c = pMs[1]->fCompl; + assert( pMs[c]->fCompl && !pMs[!c]->fCompl ); + //printf( "Using inverter at node %d in phase %d\n", i, c ); + // update this phase + pM = pMs[c]; + pM->fBest = 1; + Required = Requireds[c]; + // update opposite phase + Nf_ObjMapRefInc( p, i, !c ); + Nf_ObjUpdateRequired( p, i, !c, Required - p->InvDelayI ); + // select opposite phase + Required = Nf_ObjRequired( p, i, !c ); + //assert( Required < SCL_INFINITY ); + pD = Nf_ObjMatchD( p, i, !c ); + pA = Nf_ObjMatchA( p, i, !c ); + pM = (pA->D <= Required) ? pA : pD; + assert( !pM->fCompl ); + // create gate + Nf_ManSetMapRefsGate( p, i, Required, pM ); + // account for the inverter + p->pPars->MapAreaF += p->InvAreaF; + p->pPars->Edge++; + p->pPars->Area++; + p->nInvs++; + } + } + else + { + c = (int)(nRefs[1] > 0); + assert( nRefs[c] && !nRefs[!c] ); + // consider this phase + Required = Nf_ObjRequired( p, i, c ); + //assert( Required < SCL_INFINITY ); + pD = Nf_ObjMatchD( p, i, c ); + pA = Nf_ObjMatchA( p, i, c ); + pM = (pA->D <= Required) ? pA : pD; + if ( pM->fCompl ) // use inverter + { + p->nInvs++; + //printf( "Using inverter at node %d in phase %d\n", i, c ); + pM->fBest = 1; + // update opposite phase + Nf_ObjMapRefInc( p, i, !c ); + Nf_ObjUpdateRequired( p, i, !c, Required - p->InvDelayI ); + // select opposite phase + Required = Nf_ObjRequired( p, i, !c ); + //assert( Required < SCL_INFINITY ); + pD = Nf_ObjMatchD( p, i, !c ); + pA = Nf_ObjMatchA( p, i, !c ); + pM = (pA->D <= Required) ? pA : pD; + assert( !pM->fCompl ); + // account for the inverter + p->pPars->MapAreaF += p->InvAreaF; + p->pPars->Edge++; + p->pPars->Area++; + } + // create gate + Nf_ManSetMapRefsGate( p, i, Required, pM ); + } + // the result of this: + // - only one phase can be implemented as inverter of the other phase + // - required times are propagated correctly + // - references are set correctly + } + Gia_ManForEachCiIdWithBoxes( p->pGia, Id, i ) + if ( Nf_ObjMapRefNum(p, Id, 1) ) + { + Nf_ObjMapRefInc( p, Id, 0 ); + Nf_ObjUpdateRequired( p, Id, 0, Required - p->InvDelayI ); + p->pPars->MapAreaF += p->InvAreaF; + p->pPars->Edge++; + p->pPars->Area++; + p->nInvs++; + } + // blend references + for ( i = 0; i < nLits; i++ ) + pFlowRefs[i] = Abc_MaxFloat(1.0, Coef * pFlowRefs[i] + (1.0 - Coef) * Abc_MaxFloat(1, pMapRefs[i])); +// pFlowRefs[i] = 0.2 * pFlowRefs[i] + 0.8 * Abc_MaxFloat(1, pMapRefs[i]); + return p->pPars->Area; +} + + + +/**Function************************************************************* + + Synopsis [Area recovery.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word Nf_MatchDeref_rec( Nf_Man_t * p, int i, int c, Nf_Mat_t * pM ) +{ + word Area = 0; + int k, iVar, fCompl, * pCut; + assert( pM->fBest ); + if ( pM->fCompl ) + { + assert( Nf_ObjMapRefNum(p, i, !c) > 0 ); + if ( !Nf_ObjMapRefDec(p, i, !c) ) + Area += Nf_MatchDeref_rec( p, i, !c, Nf_ObjMatchD(p, i, !c) ); + return Area + p->InvAreaW; + } + if ( Nf_ObjCutSetId(p, i) == 0 ) + return 0; + pCut = Nf_CutFromHandle( Nf_ObjCutSet(p, i), pM->CutH ); + Nf_CutForEachVarCompl( pCut, pM->Cfg, iVar, fCompl, k ) + { + assert( Nf_ObjMapRefNum(p, iVar, fCompl) > 0 ); + if ( !Nf_ObjMapRefDec(p, iVar, fCompl) ) + Area += Nf_MatchDeref_rec( p, iVar, fCompl, Nf_ObjMatchD(p, iVar, fCompl) ); + } + return Area + Nf_ManCell(p, pM->Gate)->AreaW; +} +word Nf_MatchRef_rec( Nf_Man_t * p, int i, int c, Nf_Mat_t * pM, int Required, Vec_Int_t * vBackup ) +{ + word Area = 0; + int ReqFanin; + int k, iVar, fCompl, * pCut; + assert( pM->fBest ); + assert( pM->D <= Required ); + if ( pM->fCompl ) + { + ReqFanin = Required - p->InvDelayI; + if ( vBackup ) + Vec_IntPush( vBackup, Abc_Var2Lit(i, !c) ); + assert( Nf_ObjMapRefNum(p, i, !c) >= 0 ); + if ( !Nf_ObjMapRefInc(p, i, !c) ) + Area += Nf_MatchRef_rec( p, i, !c, Nf_ObjMatchD(p, i, !c), ReqFanin, vBackup ); + return Area + p->InvAreaW; + } + if ( Nf_ObjCutSetId(p, i) == 0 ) + return 0; + pCut = Nf_CutFromHandle( Nf_ObjCutSet(p, i), pM->CutH ); + Nf_CutForEachVarCompl( pCut, pM->Cfg, iVar, fCompl, k ) + { + ReqFanin = Required - Nf_ManCell(p, pM->Gate)->iDelays[k]; + if ( vBackup ) + Vec_IntPush( vBackup, Abc_Var2Lit(iVar, fCompl) ); + assert( Nf_ObjMapRefNum(p, iVar, fCompl) >= 0 ); + if ( !Nf_ObjMapRefInc(p, iVar, fCompl) ) + Area += Nf_MatchRef_rec( p, iVar, fCompl, Nf_ObjMatchD(p, iVar, fCompl), ReqFanin, vBackup ); + } + return Area + Nf_ManCell(p, pM->Gate)->AreaW; +} +word Nf_MatchRefArea( Nf_Man_t * p, int i, int c, Nf_Mat_t * pM, int Required ) +{ + word Area; int iLit, k; + Vec_IntClear( &p->vBackup ); + Area = Nf_MatchRef_rec( p, i, c, pM, Required, &p->vBackup ); + Vec_IntForEachEntry( &p->vBackup, iLit, k ) + { + assert( Nf_ObjMapRefNum(p, Abc_Lit2Var(iLit), Abc_LitIsCompl(iLit)) > 0 ); + Nf_ObjMapRefDec( p, Abc_Lit2Var(iLit), Abc_LitIsCompl(iLit) ); + } + return Area; +} +void Nf_ManElaBestMatchOne( Nf_Man_t * p, int iObj, int c, int * pCut, int * pCutSet, Nf_Mat_t * pRes, int Required ) +{ + Nf_Mat_t Mb,*pMb = &Mb, * pMd; + int * pFans = Nf_CutLeaves(pCut); + int nFans = Nf_CutSize(pCut); + int iFuncLit = Nf_CutFunc(pCut); + int fComplExt = Abc_LitIsCompl(iFuncLit); + Vec_Int_t * vArr = Vec_WecEntry( p->vTt2Match, Abc_Lit2Var(iFuncLit) ); + int i, k, Info, Offset, iFanin, fComplF; + // assign fanins matches + Nf_Obj_t * pBestF[NF_LEAF_MAX]; + for ( i = 0; i < nFans; i++ ) + pBestF[i] = Nf_ManObj( p, pFans[i] ); + // consider matches of this function + memset( pMb, 0, sizeof(Nf_Mat_t) ); + pMb->D = SCL_INFINITY; pMb->F = FLT_MAX; + // special cases + if ( nFans == 0 ) + { + int Const = (iFuncLit == 1); + //printf( "Node %d(%d) is const\n", iObj, c ); + assert( iFuncLit == 0 || iFuncLit == 1 ); + pMb->D = 0; + pMb->F = p->pCells[c ^ Const].AreaF; + pMb->CutH = Nf_CutHandle(pCutSet, pCut); + pMb->Gate = c ^ Const; +// pMb->Conf = 0; + pMb->Cfg = Nf_Int2Cfg(0); + pMb->fBest = 1; + // compare + if ( pRes->F > pMb->F + NF_EPSILON || (pRes->F > pMb->F - NF_EPSILON && pRes->D > pMb->D) ) + *pRes = *pMb; + return; + } + // consider matches of this function + Vec_IntForEachEntryDouble( vArr, Info, Offset, i ) + { + Nf_Cfg_t Cfg = Nf_Int2Cfg(Offset); + Mio_Cell2_t*pC = Nf_ManCell( p, Info ); + int fCompl = Cfg.fCompl ^ fComplExt; + int Delay = 0; + assert( nFans == (int)pC->nFanins ); + if ( fCompl != c ) + continue; + Nf_CfgForEachVarCompl( Cfg, nFans, iFanin, fComplF, k ) + { + pMd = &pBestF[iFanin]->M[fComplF][0]; + assert( pMd->fBest ); + Delay = Abc_MaxInt( Delay, pMd->D + pC->iDelays[k] ); + if ( Delay > Required ) + break; + } + if ( k < nFans ) + continue; + // create match + pMb->D = Delay; + pMb->F = FLT_MAX; + pMb->fBest = 1; + pMb->fCompl = 0; + pMb->CutH = Nf_CutHandle(pCutSet, pCut); + pMb->Gate = pC->Id; + pMb->Cfg = Cfg; + pMb->Cfg.fCompl = 0; + // compute area + pMb->F = Scl_Int2Flt((int)Nf_MatchRefArea(p, iObj, c, pMb, Required)); + // compare + if ( pRes->F > pMb->F + NF_EPSILON || (pRes->F > pMb->F - NF_EPSILON && pRes->D > pMb->D) ) + *pRes = *pMb; + } +} +void Nf_ManElaBestMatch( Nf_Man_t * p, int iObj, int c, Nf_Mat_t * pRes, int Required ) +{ + int k, * pCut, * pCutSet = Nf_ObjCutSet( p, iObj ); + memset( pRes, 0, sizeof(Nf_Mat_t) ); + pRes->D = SCL_INFINITY; pRes->F = FLT_MAX; + Nf_SetForEachCut( pCutSet, pCut, k ) + { + if ( Abc_Lit2Var(Nf_CutFunc(pCut)) >= Vec_WecSize(p->vTt2Match) ) + continue; + Nf_ManElaBestMatchOne( p, iObj, c, pCut, pCutSet, pRes, Required ); + } +} +int Nf_ManComputeArrival( Nf_Man_t * p, Nf_Mat_t * pM, int * pCutSet ) +{ + int Delay = 0; + Nf_Mat_t * pMfan; + int iVar, fCompl, k; + Mio_Cell2_t * pCell = Nf_ManCell( p, pM->Gate ); + int * pCut = Nf_CutFromHandle( pCutSet, pM->CutH ); + assert( !pM->fCompl ); + Nf_CutForEachVarCompl( pCut, pM->Cfg, iVar, fCompl, k ) + { + pMfan = Nf_ObjMatchBest( p, iVar, fCompl ); + Delay = Abc_MaxInt( Delay, pMfan->D + pCell->iDelays[k] ); + } + //if ( pM->fCompl ) Delay += p->InvDelayI; + return Delay; +} +void Nf_ManResetMatches( Nf_Man_t * p, int Round ) +{ + Gia_Obj_t * pObj; + Nf_Mat_t * pDc, * pAc, * pMfan, * pM[2]; + int i, c, Arrival; + // go through matches in the topo order + if ( p->pManTim ) + Tim_ManIncrementTravId( p->pManTim ); + Gia_ManForEachObjWithBoxes( p->pGia, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + { + pMfan = Nf_ObjMatchBest( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj) ); + for ( c = 0; c < 2; c++ ) + { + pDc = Nf_ObjMatchD( p, i, c ); + pAc = Nf_ObjMatchA( p, i, c ); + pDc->F = pAc->F = 0; + pDc->D = pMfan->D + (c ? p->InvDelayI : 0); + assert( pDc->fBest ); + assert( !pAc->fBest ); + assert( c==0 || pDc->fCompl ); + } + continue; + } + if ( Gia_ObjIsCi(pObj) ) + { + Arrival = Tim_ManGetCiArrival( p->pManTim, Gia_ObjCioId(pObj) ); + Nf_ObjPrepareCi( p, i, Arrival ); + continue; + } + if ( Gia_ObjIsCo(pObj) ) + { + Arrival = Nf_ObjMatchD( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj) )->D; + Tim_ManSetCoArrival( p->pManTim, Gia_ObjCioId(pObj), Arrival ); + continue; + } + // select the best match for each phase + for ( c = 0; c < 2; c++ ) + { + pDc = Nf_ObjMatchD( p, i, c ); + pAc = Nf_ObjMatchA( p, i, c ); + pDc->F = pAc->F = 0; + if ( Nf_ObjMapRefNum(p, i, c) ) + { + assert( pDc->fBest != pAc->fBest ); + if ( pAc->fBest ) + ABC_SWAP( Nf_Mat_t, *pDc, *pAc ); + assert( pDc->fBest ); + assert( !pAc->fBest ); + } + else + { + assert( Round > 0 || (!pDc->fBest && !pAc->fBest) ); +// if ( (p->pPars->fAreaOnly || (Round & 1)) && !pAc->fCompl ) + if ( (Round & 1) && !pAc->fCompl ) + ABC_SWAP( Nf_Mat_t, *pDc, *pAc ); + pDc->fBest = 1; + pAc->fBest = 0; + } + } + // consider best matches of both phases + pM[0] = Nf_ObjMatchD( p, i, 0 ); + pM[1] = Nf_ObjMatchD( p, i, 1 ); + assert( pM[0]->fBest && pM[1]->fBest ); + // swap complemented matches + if ( pM[0]->fCompl && pM[1]->fCompl ) + { +// pM[0]->fCompl = pM[1]->fCompl = 0; +// ABC_SWAP( Nf_Mat_t *, pM[0], pM[1] ); + assert( 0 ); + } + if ( !pM[0]->fCompl && !pM[1]->fCompl ) + { + for ( c = 0; c < 2; c++ ) + { + Arrival = Nf_ManComputeArrival( p, pM[c], Nf_ObjCutSet(p, i) ); + //if ( Nf_ObjMapRefNum(p, i, c) ) + // assert( Round || Arrival <= pM[c]->D ); + pM[c]->D = Arrival; + } + } + else + { + // consider non-complemented match + c = !pM[1]->fCompl; + assert( !pM[c]->fCompl ); + assert( pM[!c]->fCompl ); + Arrival = Nf_ManComputeArrival( p, pM[c], Nf_ObjCutSet(p, i) ); + //if ( Nf_ObjMapRefNum(p, i, c) ) + // assert( Round || Arrival <= pM[c]->D ); + pM[c]->D = Arrival; + // consider complemented match + Arrival = pM[!c]->D; + *pM[!c] = *pM[c]; + pM[!c]->D += p->InvDelayI; + pM[!c]->fCompl = 1; + //if ( Nf_ObjMapRefNum(p, i, !c) ) + // assert( Round || pM[!c]->D <= Arrival ); + } + } +} +void Nf_ManComputeMappingEla( Nf_Man_t * p ) +{ + int fVerbose = 0; + Gia_Obj_t * pObj; + Mio_Cell2_t * pCell; + Nf_Mat_t Mb, * pMb = &Mb, * pM; + word AreaBef, AreaAft, Gain = 0; + int i, c, iVar, Id, fCompl, k, * pCut, Required; + Nf_ManResetMatches( p, p->Iter - p->pPars->nRounds ); + Nf_ManSetOutputRequireds( p, 1 ); + Gia_ManForEachObjReverseWithBoxes( p->pGia, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + { + if ( Nf_ObjMapRefNum(p, i, 1) ) + Nf_ObjUpdateRequired( p, i, 0, Nf_ObjRequired(p, i, 1) - p->InvDelayI ); + int reqTime = Nf_ObjRequired(p, i, 0); + int iObj = Gia_ObjFaninId0p(p->pGia, pObj); + int fCompl = Gia_ObjFaninC0(pObj); + Nf_ObjUpdateRequired( p, iObj, fCompl, reqTime ); + if ( iObj > 0 && Nf_ObjMatchBest(p, iObj, fCompl)->fCompl ) + Nf_ObjUpdateRequired( p, iObj, !fCompl, reqTime - p->InvDelayI ); + continue; + } + if ( Gia_ObjIsCi(pObj) ) + { + if ( Nf_ObjMapRefNum(p, i, 1) ) + Nf_ObjUpdateRequired( p, i, 0, Nf_ObjRequired(p, i, 1) - p->InvDelayI ); + Tim_ManSetCiRequired( p->pManTim, Gia_ObjCioId(pObj), Nf_ObjRequired(p, i, 0) ); + continue; + } + if ( Gia_ObjIsCo(pObj) ) + { + int reqTime = Tim_ManGetCoRequired( p->pManTim, Gia_ObjCioId(pObj) ); + int iObj = Gia_ObjFaninId0p(p->pGia, pObj); + int fCompl = Gia_ObjFaninC0(pObj); + Nf_ObjUpdateRequired( p, iObj, fCompl, reqTime ); + if ( iObj > 0 && Nf_ObjMatchBest(p, iObj, fCompl)->fCompl ) + Nf_ObjUpdateRequired( p, iObj, !fCompl, reqTime - p->InvDelayI ); + continue; + } + for ( c = 0; c < 2; c++ ) + if ( Nf_ObjMapRefNum(p, i, c) ) + { + pM = Nf_ObjMatchBest( p, i, c ); + Required = Nf_ObjRequired( p, i, c ); + assert( pM->D <= Required ); + if ( pM->fCompl ) + continue; + // search for a better match + assert( !pM->fCompl ); + AreaBef = Nf_MatchDeref_rec( p, i, c, pM ); + assert( pM->fBest ); + Nf_ManElaBestMatch( p, i, c, pMb, Required ); + AreaAft = Nf_MatchRef_rec( p, i, c, pMb, Required, NULL ); + Gain += AreaBef - AreaAft; + // print area recover progress + if ( fVerbose && Nf_ManCell(p, pM->Gate)->pName != Nf_ManCell(p, pMb->Gate)->pName ) + { + printf( "%4d (%d) ", i, c ); + printf( "%8s ->%8s ", Nf_ManCell(p, pM->Gate)->pName, Nf_ManCell(p, pMb->Gate)->pName ); + printf( "%d -> %d ", Nf_ManCell(p, pM->Gate)->nFanins, Nf_ManCell(p, pMb->Gate)->nFanins ); + printf( "D: %7.2f -> %7.2f ", Scl_Int2Flt(pM->D), Scl_Int2Flt(pMb->D) ); + printf( "R: %7.2f ", Required == SCL_INFINITY ? 9999.99 : Scl_Int2Flt(Required) ); + printf( "A: %7.2f -> %7.2f ", Scl_Int2Flt((int)AreaBef), Scl_Int2Flt((int)AreaAft) ); + printf( "G: %7.2f (%7.2f) ", Scl_Int2Flt((int)AreaBef - (int)AreaAft), Scl_Int2Flt((int)Gain) ); + printf( "\n" ); + } + // set best match + assert( pMb->fBest ); + assert( pMb->D <= Required ); + //assert( Scl_Flt2Int(pMb->F) == (int)AreaAft ); + //assert( AreaBef >= AreaAft ); + *pM = *pMb; + // update timing + pCell = Nf_ManCell( p, pMb->Gate ); + pCut = Nf_CutFromHandle( Nf_ObjCutSet(p, i), pMb->CutH ); + Nf_CutForEachVarCompl( pCut, pMb->Cfg, iVar, fCompl, k ) + { + pM = Nf_ObjMatchBest( p, iVar, fCompl ); + assert( pM->D <= Required - pCell->iDelays[k] ); + Nf_ObjUpdateRequired( p, iVar, fCompl, Required - pCell->iDelays[k] ); + if ( pM->fCompl ) + { + pM = Nf_ObjMatchBest( p, iVar, !fCompl ); + assert( pM->D <= Required - pCell->iDelays[k] - p->InvDelayI ); + Nf_ObjUpdateRequired( p, iVar, !fCompl, Required - pCell->iDelays[k] - p->InvDelayI ); + } + } + } + } + Gia_ManForEachCiIdWithBoxes( p->pGia, Id, i ) + if ( Nf_ObjMapRefNum(p, Id, 1) ) + { + Required = Nf_ObjRequired( p, i, 1 ); + Nf_ObjUpdateRequired( p, Id, 0, Required - p->InvDelayI ); + } +} +void Nf_ManFixPoDrivers( Nf_Man_t * p ) +{ + Gia_Obj_t * pObj; + Nf_Mat_t * pM, * pMc; + int i, iDriver, Count = 0; + Gia_ManForEachCo( p->pGia, pObj, i ) + { + iDriver = Gia_ObjFaninId0p(p->pGia, pObj); + if ( !Gia_ObjIsAnd(Gia_ManObj(p->pGia, iDriver)) ) + continue; + // skip unless both are used + if ( !Nf_ObjMapRefNum(p, iDriver, 0) || !Nf_ObjMapRefNum(p, iDriver, 1) ) + continue; + pM = Nf_ObjMatchD( p, iDriver, Gia_ObjFaninC0(pObj) ); + pMc = Nf_ObjMatchD( p, iDriver, !Gia_ObjFaninC0(pObj) ); + // skip unless both are non-complemented + if ( pM->fCompl || pMc->fCompl ) + continue; + // skip if arrival time exceeds the required time + if ( pMc->D + p->InvDelayI > p->pPars->MapDelay ) + continue; + // update references + Nf_MatchDeref_rec( p, iDriver, Gia_ObjFaninC0(pObj), pM ); + Nf_ObjMapRefInc( p, iDriver, !Gia_ObjFaninC0(pObj) ); + // add inverter + *pM = *pMc; + pM->D += p->InvDelayI; + pM->fCompl = 1; + pM->fBest = 1; + pMc->fBest = 1; + Count++; + } + //printf( "Fixed %d PO drivers.\n", Count ); +} + +/**Function************************************************************* + + Synopsis [Deriving mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Nf_ManDeriveMapping( Nf_Man_t * p ) +{ + Vec_Int_t * vMapping; + Nf_Mat_t * pM; + int i, k, c, Id, iVar, fCompl, * pCut; + assert( p->pGia->vCellMapping == NULL ); + vMapping = Vec_IntAlloc( 2*Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + (int)p->pPars->Area * 2 ); + Vec_IntFill( vMapping, 2*Gia_ManObjNum(p->pGia), 0 ); + // create CI inverters + Gia_ManForEachCiId( p->pGia, Id, i ) + if ( Nf_ObjMapRefNum(p, Id, 1) ) + Vec_IntWriteEntry( vMapping, Abc_Var2Lit(Id, 1), -1 ); + // create internal nodes + Gia_ManForEachAndId( p->pGia, i ) + { + Gia_Obj_t * pObj = Gia_ManObj(p->pGia, i); + if ( Gia_ObjIsBuf(pObj) ) + { + if ( Nf_ObjMapRefNum(p, i, 1) ) + Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, 1), -1 ); + Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, 0), -2 ); + continue; + } + for ( c = 0; c < 2; c++ ) + if ( Nf_ObjMapRefNum(p, i, c) ) + { + pM = Nf_ObjMatchBest( p, i, c ); + // remember inverter + if ( pM->fCompl ) + { + Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, c), -1 ); + continue; + } + // Nf_ManCutMatchPrint( p, i, c, pM ); + pCut = Nf_CutFromHandle( Nf_ObjCutSet(p, i), pM->CutH ); + Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, c), Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, Nf_CutSize(pCut) ); + Nf_CutForEachVarCompl( pCut, pM->Cfg, iVar, fCompl, k ) + Vec_IntPush( vMapping, Abc_Var2Lit(iVar, fCompl) ); + Vec_IntPush( vMapping, pM->Gate ); + } + } +// assert( Vec_IntCap(vMapping) == 16 || Vec_IntSize(vMapping) == Vec_IntCap(vMapping) ); + p->pGia->vCellMapping = vMapping; + return p->pGia; +} +void Nf_ManUpdateStats( Nf_Man_t * p ) +{ + Nf_Mat_t * pM; + Gia_Obj_t * pObj; + Mio_Cell2_t * pCell; + int i, c, Id, * pCut; + p->pPars->MapAreaF = 0; p->nInvs = 0; + p->pPars->Area = p->pPars->Edge = 0; + Gia_ManForEachAndReverse( p->pGia, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + { + if ( Nf_ObjMapRefNum(p, i, 1) ) + { + p->pPars->MapAreaF += p->InvAreaF; + p->pPars->Edge++; + p->pPars->Area++; + p->nInvs++; + } + continue; + } + for ( c = 0; c < 2; c++ ) + if ( Nf_ObjMapRefNum(p, i, c) ) + { + pM = Nf_ObjMatchBest( p, i, c ); + if ( pM->fCompl ) + { + p->pPars->MapAreaF += p->InvAreaF; + p->pPars->Edge++; + p->pPars->Area++; + p->nInvs++; + continue; + } + pCut = Nf_CutFromHandle( Nf_ObjCutSet(p, i), pM->CutH ); + pCell = Nf_ManCell( p, pM->Gate ); + assert( Nf_CutSize(pCut) == (int)pCell->nFanins ); + p->pPars->MapAreaF += pCell->AreaF; + p->pPars->Edge += Nf_CutSize(pCut); + p->pPars->Area++; + //printf( "%5d (%d) : Gate = %7s \n", i, c, pCell->pName ); + } + } + Gia_ManForEachCiId( p->pGia, Id, i ) + if ( Nf_ObjMapRefNum(p, Id, 1) ) + { + p->pPars->MapAreaF += p->InvAreaF; + p->pPars->Edge++; + p->pPars->Area++; + p->nInvs++; + } +} + +/**Function************************************************************* + + Synopsis [Extract window.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +/* + int nInputs; // the number of inputs + int nObjs; // number of all objects + Vec_Int_t * vRoots; // output drivers to be mapped (root -> obj lit) + Vec_Wec_t * vCuts; // cuts (cut -> obj lit + fanin lits) + Vec_Wec_t * vObjCuts; // cuts (obj lit -> obj lit + cut lits) + Vec_Int_t * vSolCuts; // current solution (index -> cut) + Vec_Int_t * vCutGates; // gates (cut -> gate) +*/ + +int Nf_ManExtractWindow( void * pMan, Vec_Int_t * vRoots, Vec_Wec_t * vCuts, Vec_Wec_t * vObjCuts, Vec_Int_t * vSolCuts, Vec_Int_t * vCutGates, Vec_Wrd_t * vCutAreas, word * pInvArea, int StartVar, int nVars ) +{ + Nf_Man_t * p = (Nf_Man_t *)pMan; + int nInputs = Gia_ManCiNum(p->pGia); + int LitShift = 2*nInputs+2; + Gia_Obj_t * pObj; + int c, iObj; + if ( 2*Gia_ManAndNum(p->pGia) + Gia_ManCiNum(p->pGia) > nVars ) + { + printf( "The number of variables is too large: 2*%d + %d = %d > %d.\n", Gia_ManAndNum(p->pGia), Gia_ManCiNum(p->pGia), 2*Gia_ManAndNum(p->pGia) + Gia_ManCiNum(p->pGia), nVars ); + return 0; + } + *pInvArea = p->InvAreaW; + // save roots + Vec_IntClear( vRoots ); + Gia_ManForEachCo( p->pGia, pObj, c ) + { + assert( !Gia_ObjIsCi(Gia_ObjFanin0(pObj)) ); + Vec_IntPush( vRoots, Gia_ObjFaninLit0p(p->pGia, pObj)-LitShift ); + } + // prepare + Vec_WecClear( vCuts ); + Vec_WecClear( vObjCuts ); + Vec_IntClear( vSolCuts ); + Vec_IntClear( vCutGates ); + Vec_WrdClear( vCutAreas ); + // collect cuts for each node + Gia_ManForEachAndId( p->pGia, iObj ) + { + Vec_Int_t * vObj[2], * vCutOne; + int iCut, * pCut, * pCutSet; + int iCutInv[2] = {-1, -1}; + // get matches + Nf_Mat_t * pM[2] = {NULL, NULL}; + for ( c = 0; c < 2; c++ ) + { + if ( Nf_ObjMapRefNum(p, iObj, c) == 0 ) + continue; + if ( Nf_ObjMatchBest(p, iObj, c)->fCompl ) + { + assert( iCutInv[c] == -1 ); + iCutInv[c] = Vec_IntSize(vSolCuts); + Vec_IntPush( vSolCuts, -1 ); + continue; + } + pM[c] = Nf_ObjMatchBest(p, iObj, c); + } + // start collecting cuts of pos-obj and neg-obj + assert( Vec_WecSize(vObjCuts) == 2*iObj-LitShift ); + for ( c = 0; c < 2; c++ ) + { + vObj[c] = Vec_WecPushLevel( vObjCuts ); + Vec_IntPush( vObj[c], Abc_Var2Lit(Abc_Var2Lit(iObj, c)-LitShift, 1) ); + } + // enumerate cuts + pCutSet = Nf_ObjCutSet( p, iObj ); + Nf_SetForEachCut( pCutSet, pCut, iCut ) + { + assert( !Nf_CutIsTriv(pCut, iObj) ); + assert( Nf_CutSize(pCut) <= p->pPars->nLutSize ); + if ( Abc_Lit2Var(Nf_CutFunc(pCut)) < Vec_WecSize(p->vTt2Match) ) + { + int * pFans = Nf_CutLeaves(pCut); + int nFans = Nf_CutSize(pCut); + int iFuncLit = Nf_CutFunc(pCut); + int fComplExt = Abc_LitIsCompl(iFuncLit); + Vec_Int_t * vArr = Vec_WecEntry( p->vTt2Match, Abc_Lit2Var(iFuncLit) ); + int i, k, c, Info, Offset, iFanin, fComplF, iCutLit; + Vec_IntForEachEntryDouble( vArr, Info, Offset, i ) + { + Nf_Cfg_t Cfg = Nf_Int2Cfg(Offset); + int fCompl = Cfg.fCompl ^ fComplExt; + Mio_Cell2_t*pC = Nf_ManCell( p, Info ); + assert( nFans == (int)pC->nFanins ); + Vec_IntPush( vCutGates, Info ); + Vec_WrdPush( vCutAreas, pC->AreaW ); + // to make comparison possible + Cfg.fCompl = 0; + // add solution cut + for ( c = 0; c < 2; c++ ) + { + if ( pM[c] == NULL ) + continue; + if ( (int)pM[c]->CutH == Nf_CutHandle(pCutSet, pCut) && (int)pM[c]->Gate == Info && Nf_Cfg2Int(pM[c]->Cfg) == Nf_Cfg2Int(Cfg) ) + { + Vec_IntPush( vSolCuts, Vec_WecSize(vCuts) ); + //printf( "adding solution for %d\n", Abc_Var2Lit(iObj, c)-LitShift ); + } + } + // add new cut + iCutLit = Abc_Var2Lit( StartVar + Vec_WecSize(vCuts), 0 ); + vCutOne = Vec_WecPushLevel( vCuts ); + // add literals + Vec_IntPush( vCutOne, Abc_Var2Lit(iObj, fCompl) ); + Vec_IntPush( vObj[fCompl], iCutLit ); + Nf_CfgForEachVarCompl( Cfg, nFans, iFanin, fComplF, k ) + if ( pFans[iFanin] >= nInputs + 1 ) // internal node + { + Vec_IntPush( vCutOne, Abc_Var2Lit(pFans[iFanin], fComplF) ); + //Vec_IntPush( Vec_WecEntry(vObjCuts, Abc_Var2Lit(pFans[iFanin], fComplF)-LitShift), iCutLit ); + } + else if ( fComplF ) // complemented primary input + Vec_IntPush( vCutOne, Abc_Var2Lit(pFans[iFanin], 1) ); + } + } + } + assert( iCutInv[0] == -1 || iCutInv[1] == -1 ); + // add inverter cut + for ( c = 0; c < 2; c++ ) + { + if ( iCutInv[c] != -1 ) + Vec_IntWriteEntry( vSolCuts, iCutInv[c], Vec_WecSize(vCuts) ); + // the obj-lit implies its cut + Vec_IntPush( Vec_WecEntry(vObjCuts, Abc_Var2Lit(iObj, c)-LitShift), Abc_Var2Lit(StartVar + Vec_WecSize(vCuts), 0) ); + // the cut includes both literals + vCutOne = Vec_WecPushLevel( vCuts ); + Vec_IntPush( vCutOne, Abc_Var2Lit(iObj, c) ); + Vec_IntPush( vCutOne, Abc_Var2Lit(iObj, !c) ); + Vec_IntPush( vCutGates, 3 ); + Vec_WrdPush( vCutAreas, p->InvAreaW ); + } + } +// for ( c = 0; c < p->nCells; c++ ) +// printf( "%d=%s ", c, p->pCells[c].pName ); +// printf( "\n" ); + // add complemented inputs + Gia_ManForEachCiId( p->pGia, iObj, c ) + if ( Nf_ObjMapRefNum(p, iObj, 1) ) + Vec_IntPush( vSolCuts, -(2*Gia_ManAndNum(p->pGia)+c) ); + assert( Vec_WecSize(vCuts) == Vec_IntSize(vCutGates) ); + assert( Vec_WecSize(vCuts) == Vec_WrdSize(vCutAreas) ); + assert( Vec_WecSize(vObjCuts) == 2*Gia_ManAndNum(p->pGia) ); + return nInputs; +} + +/**Function************************************************************* + + Synopsis [Technology mappping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Nf_ManSetDefaultPars( Jf_Par_t * pPars ) +{ + memset( pPars, 0, sizeof(Jf_Par_t) ); + pPars->nLutSize = 6; + pPars->nCutNum = 16; + pPars->nProcNum = 0; + pPars->nRounds = 4; + pPars->nRoundsEla = 2; + pPars->nRelaxRatio = 0; + pPars->nCoarseLimit = 3; + pPars->nAreaTuner = 0; + pPars->nReqTimeFlex = 0; + pPars->nVerbLimit = 5; + pPars->DelayTarget = -1; + pPars->fAreaOnly = 0; + pPars->fPinPerm = 0; + pPars->fPinQuick = 0; + pPars->fPinFilter = 0; + pPars->fOptEdge = 1; + pPars->fCoarsen = 0; + pPars->fCutMin = 1; + pPars->fGenCnf = 0; + pPars->fPureAig = 0; + pPars->fVerbose = 0; + pPars->fVeryVerbose = 0; + pPars->nLutSizeMax = NF_LEAF_MAX; + pPars->nCutNumMax = NF_CUT_MAX; + pPars->MapDelayTarget = 0; +} +Gia_Man_t * Nf_ManPerformMappingInt( Gia_Man_t * pGia, Jf_Par_t * pPars ) +{ + Gia_Man_t * pNew = NULL, * pCls; + Nf_Man_t * p; int i, Id; + if ( Gia_ManHasChoices(pGia) || pGia->pManTime ) + pPars->fCoarsen = 0; + pCls = pPars->fCoarsen ? Gia_ManDupMuxes(pGia, pPars->nCoarseLimit) : pGia; + p = Nf_StoCreate( pCls, pPars ); + if ( p == NULL ) + return NULL; +// if ( p->pManTim ) Tim_ManPrint( p->pManTim ); + p->pGia->iFirstNonPiId = p->pManTim ? Tim_ManPiNum(p->pManTim) : Gia_ManCiNum(p->pGia); + p->pGia->iFirstPoId = p->pManTim ? Gia_ManCoNum(p->pGia) - Tim_ManPoNum(p->pManTim) : 0; + p->pGia->iFirstAndObj = 1 + p->pGia->iFirstNonPiId; + p->pGia->iFirstPoObj = Gia_ManObjNum(p->pGia) - Gia_ManCoNum(p->pGia) + p->pGia->iFirstPoId; +// if ( pPars->fVeryVerbose ) +// Nf_StoPrint( p, pPars->fVeryVerbose ); + if ( pPars->fVerbose && pPars->fCoarsen ) + { + printf( "Initial " ); Gia_ManPrintMuxStats( pGia ); printf( "\n" ); + printf( "Derived " ); Gia_ManPrintMuxStats( pCls ); printf( "\n" ); + } + Nf_ManPrintInit( p ); + Nf_ManComputeCuts( p ); + Nf_ManPrintQuit( p ); + if ( Scl_ConIsRunning() ) + { + Gia_ManForEachCiIdWithBoxes( p->pGia, Id, i ) + Nf_ObjPrepareCi( p, Id, Scl_ConGetInArr(i) ); + } + else + { + Gia_ManForEachCiIdWithBoxes( p->pGia, Id, i ) +// Nf_ObjPrepareCi( p, Id, Scl_Flt2Int(p->pGia->vInArrs ? Abc_MaxFloat(0.0, Vec_FltEntry(p->pGia->vInArrs, i)) : 0.0) ); + Nf_ObjPrepareCi( p, Id, Scl_Flt2Int(p->pGia->vInArrs ? Vec_FltEntry(p->pGia->vInArrs, i) : 0.0) ); + } + for ( p->Iter = 0; p->Iter < p->pPars->nRounds; p->Iter++ ) + { + Nf_ManComputeMapping( p ); + Nf_ManSetMapRefs( p ); + Nf_ManPrintStats( p, (char *)(p->Iter ? "Area " : "Delay") ); + } + + p->fUseEla = 1; + for ( ; p->Iter < p->pPars->nRounds + pPars->nRoundsEla; p->Iter++ ) + { + Nf_ManComputeMappingEla( p ); + Nf_ManUpdateStats( p ); + Nf_ManPrintStats( p, "Ela " ); + } + Nf_ManFixPoDrivers( p ); + pNew = Nf_ManDeriveMapping( p ); +/* + if ( pPars->fAreaOnly ) + { + int Sbm_ManTestSat( void * pMan ); + Sbm_ManTestSat( p ); + } +*/ + Nf_StoDelete( p ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCellMappingVerify_rec( Gia_Man_t * p, int iLit ) +{ + int iFanLit, k, Result = 1; + if ( Abc_LitIsCompl(iLit) && Gia_ObjIsTravIdCurrentId(p, Abc_Lit2Var(iLit)) ) + return 1; + if ( !Abc_LitIsCompl(iLit) && Gia_ObjIsTravIdPreviousId(p, Abc_Lit2Var(iLit)) ) + return 1; + if ( Abc_LitIsCompl(iLit) ) + Gia_ObjSetTravIdCurrentId(p, Abc_Lit2Var(iLit)); + else + Gia_ObjSetTravIdPreviousId(p, Abc_Lit2Var(iLit)); + if ( !Gia_ObjIsAndNotBuf(Gia_ManObj(p, Abc_Lit2Var(iLit))) ) + return 1; + if ( !Gia_ObjIsCell(p, iLit) ) + { + Abc_Print( -1, "Gia_ManCellMappingVerify: Internal literal %d does not have mapping.\n", iLit ); + return 0; + } + if ( Gia_ObjIsCellBuf(p, iLit) ) + return Gia_ManCellMappingVerify_rec( p, Gia_ObjFaninLit0p(p, Gia_ManObj(p, Abc_Lit2Var(iLit))) ); + if ( Gia_ObjIsCellInv(p, iLit) ) + return Gia_ManCellMappingVerify_rec( p, Abc_LitNot(iLit) ); + Gia_CellForEachFanin( p, iLit, iFanLit, k ) + if ( Result ) + Result &= Gia_ManCellMappingVerify_rec( p, iFanLit ); + return Result; +} +void Gia_ManCellMappingVerify( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, iLit, Result = 1; + assert( Gia_ManHasCellMapping(p) ); + Gia_ManIncrementTravId( p ); + Gia_ManIncrementTravId( p ); + Gia_ManForEachBuf( p, pObj, i ) + { + if ( !Gia_ObjIsAndNotBuf(Gia_ObjFanin0(pObj)) ) + continue; + iLit = Gia_ObjFaninLit0p(p, pObj); + if ( !Gia_ObjIsCell(p, iLit) ) + { + Abc_Print( -1, "Gia_ManCellMappingVerify: Buffer driver %d does not have mapping.\n", Gia_ObjFaninId0p(p, pObj) ); + Result = 0; + continue; + } + Result &= Gia_ManCellMappingVerify_rec( p, iLit ); + } + Gia_ManForEachCo( p, pObj, i ) + { + if ( !Gia_ObjIsAndNotBuf(Gia_ObjFanin0(pObj)) ) + continue; + iLit = Gia_ObjFaninLit0p(p, pObj); + if ( !Gia_ObjIsCell(p, iLit) ) + { + Abc_Print( -1, "Gia_ManCellMappingVerify: CO driver %d does not have mapping.\n", Gia_ObjFaninId0p(p, pObj) ); + Result = 0; + continue; + } + Result &= Gia_ManCellMappingVerify_rec( p, iLit ); + } +// if ( Result ) +// Abc_Print( 1, "Mapping verified correctly.\n" ); +} + +void Gia_ManTransferCellMapping( Gia_Man_t * p, Gia_Man_t * pGia ) +{ + int iLit, iLitNew, k, iFanLit, iPlace; + if ( !Gia_ManHasCellMapping(pGia) ) + return; + Gia_ManCellMappingVerify( pGia ); + Vec_IntFreeP( &p->vCellMapping ); + p->vCellMapping = Vec_IntAlloc( 4 * Gia_ManObjNum(p) ); + Vec_IntFill( p->vCellMapping, 2 * Gia_ManObjNum(p), 0 ); + Gia_ManForEachCell( pGia, iLit ) + { + Gia_Obj_t * pObj = Gia_ManObj(pGia, Abc_Lit2Var(iLit)); + if ( Gia_ObjValue(pObj) == ~0 ) // handle dangling LUT + continue; + assert( !Abc_LitIsCompl( Gia_ObjValue(pObj) ) ); + iLitNew = Abc_LitNotCond( Gia_ObjValue(pObj), Abc_LitIsCompl(iLit) ); + if ( Gia_ObjIsCellInv(pGia, iLit) ) { + Vec_IntWriteEntry( p->vCellMapping, iLitNew, -1 ); + continue; + } + if ( Gia_ObjIsCellBuf(pGia, iLit) ) { + Vec_IntWriteEntry( p->vCellMapping, iLitNew, -2 ); + continue; + } + Vec_IntWriteEntry( p->vCellMapping, iLitNew, Vec_IntSize(p->vCellMapping) ); + iPlace = Vec_IntSize( p->vCellMapping ); + Vec_IntPush( p->vCellMapping, Gia_ObjCellSize(pGia, iLit) ); + Gia_CellForEachFanin( pGia, iLit, iFanLit, k ) + { + int iFanLitNew = Gia_ObjValue( Gia_ManObj(pGia, Abc_Lit2Var(iFanLit)) ); + if ( iFanLitNew == ~0 ) // handle dangling LUT fanin + Vec_IntAddToEntry( p->vCellMapping, iPlace, -1 ); + else + Vec_IntPush( p->vCellMapping, Abc_LitNotCond(iFanLitNew, Abc_LitIsCompl(iFanLit)) ); + } + Vec_IntPush( p->vCellMapping, Gia_ObjCellId(pGia, iLit) ); + } + Gia_ManCellMappingVerify( p ); +} +Gia_Man_t * Nf_ManPerformMapping( Gia_Man_t * p, Jf_Par_t * pPars ) +{ + Gia_Man_t * pNew; + if ( p->pManTime && Tim_ManBoxNum((Tim_Man_t*)p->pManTime) && Gia_ManIsNormalized(p) ) + { + pNew = Gia_ManDupUnnormalize( p ); + if ( pNew == NULL ) + return NULL; + Gia_ManTransferTiming( pNew, p ); + p = pNew; + // mapping + pNew = Nf_ManPerformMappingInt( p, pPars ); + if ( pNew != p ) + { + Gia_ManTransferTiming( pNew, p ); + Gia_ManStop( p ); + } + // normalize + pNew = Gia_ManDupNormalize( p = pNew, 0 ); + Gia_ManTransferCellMapping( pNew, p ); + Gia_ManTransferTiming( pNew, p ); + Gia_ManStop( p ); + assert( Gia_ManIsNormalized(pNew) ); + } + else + { + pNew = Nf_ManPerformMappingInt( p, pPars ); + Gia_ManTransferTiming( pNew, p ); + //Gia_ManCellMappingVerify( pNew ); + // remove choices after mapping + ABC_FREE( pNew->pReprs ); + ABC_FREE( pNew->pNexts ); + } + //pNew->MappedDelay = (int)((If_Par_t *)pp)->FinalDelay; + //pNew->MappedArea = (int)((If_Par_t *)pp)->FinalArea; + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaOf.c b/yosys/abc/src/aig/gia/giaOf.c new file mode 100644 index 00000000000..dca13ae6a26 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaOf.c @@ -0,0 +1,1866 @@ +/**CFile**************************************************************** + + FileName [giaOf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [LUT structure mapper.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaOf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/st/st.h" +#include "map/mio/mio.h" +#include "misc/util/utilTruth.h" +#include "misc/extra/extra.h" +#include "base/main/main.h" +#include "misc/vec/vecMem.h" +#include "misc/vec/vecWec.h" +#include "opt/dau/dau.h" +#include "sat/bsat/satStore.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define OF_LEAF_MAX 6 +#define OF_CUT_MAX 32 +#define OF_NO_LEAF 31 +#define OF_NO_FUNC 0x7FFFFFF +#define OF_CUT_EXTRA 4 // size; delay1, delay2; area + +typedef struct Of_Cut_t_ Of_Cut_t; +struct Of_Cut_t_ +{ + word Sign; // signature + int Delay; // delay + int Flow; // flow + unsigned iFunc : 27; // function (OF_NO_FUNC) + unsigned nLeaves : 5; // leaf number (OF_NO_LEAF) + int pLeaves[OF_LEAF_MAX+1]; // leaves +}; +typedef struct Of_Obj_t_ Of_Obj_t; +struct Of_Obj_t_ +{ + int iCutH; // best cut + int iCutH2; // best cut + int Delay1; // arrival time + int Delay2; // arrival time + int Required; // required + int nRefs; // references + int Flow; // area flow + int Temp; // unused +}; +typedef struct Of_Man_t_ Of_Man_t; +struct Of_Man_t_ +{ + // user data + Gia_Man_t * pGia; // derived manager + Jf_Par_t * pPars; // parameters + // cut data + Vec_Mem_t * vTtMem; // truth tables + Vec_Ptr_t vPages; // cut memory + Vec_Int_t vCutSets; // cut offsets + Vec_Int_t vCutFlows; // temporary cut area + Vec_Int_t vCutDelays; // temporary cut delay + Vec_Int_t vCutRefs; // temporary cut referebces + int iCur; // current position + int Iter; // mapping iterations + // object data + Of_Obj_t * pObjs; + // statistics + abctime clkStart; // starting time + double CutCount[6]; // cut counts +}; + +#define OF_NUM 10 +#define OF_NUMINV 0.1 + +static inline int Of_Flt2Int( float f ) { return (int)(OF_NUM*f); } +static inline float Of_Int2Flt( int i ) { return OF_NUMINV*i; } + +static inline int * Of_ManCutSet( Of_Man_t * p, int i ) { return (int *)Vec_PtrEntry(&p->vPages, i >> 16) + (i & 0xFFFF); } +static inline int Of_ObjCutSetId( Of_Man_t * p, int i ) { return Vec_IntEntry( &p->vCutSets, i ); } +static inline int * Of_ObjCutSet( Of_Man_t * p, int i ) { return Of_ManCutSet(p, Of_ObjCutSetId(p, i)); } +static inline int Of_ObjHasCuts( Of_Man_t * p, int i ) { return (int)(Vec_IntEntry(&p->vCutSets, i) > 0); } + +static inline int Of_ObjCutFlow( Of_Man_t * p, int i ) { return Vec_IntEntry(&p->vCutFlows, i); } +static inline int Of_ObjCutDelay( Of_Man_t * p, int i ) { return Vec_IntEntry(&p->vCutDelays, i); } +static inline void Of_ObjSetCutFlow( Of_Man_t * p, int i, int a ) { Vec_IntWriteEntry(&p->vCutFlows, i, a); } +static inline void Of_ObjSetCutDelay( Of_Man_t * p, int i, int d ) { Vec_IntWriteEntry(&p->vCutDelays, i, d); } + +static inline int Of_CutSize( int * pCut ) { return pCut[0] & OF_NO_LEAF; } +static inline int Of_CutFunc( int * pCut ) { return ((unsigned)pCut[0] >> 5); } +static inline int * Of_CutLeaves( int * pCut ) { return pCut + 1; } +static inline int Of_CutSetBoth( int n, int f ) { return n | (f << 5); } +static inline int Of_CutHandle( int * pCutSet, int * pCut ) { assert( pCut > pCutSet ); return pCut - pCutSet; } +static inline int * Of_CutFromHandle( int * pCutSet, int h ) { assert( h > 0 ); return pCutSet + h; } + +static inline int Of_CutDelay1( int * pCut ) { return pCut[1 + Of_CutSize(pCut)]; } +static inline int Of_CutDelay2( int * pCut ) { return pCut[2 + Of_CutSize(pCut)]; } +static inline int Of_CutAreaFlow( int * pCut ) { return pCut[3 + Of_CutSize(pCut)]; } +static inline void Of_CutSetDelay1( int * pCut, int d ) { pCut[1 + Of_CutSize(pCut)] = d; } +static inline void Of_CutSetDelay2( int * pCut, int d ) { pCut[2 + Of_CutSize(pCut)] = d; } +static inline void Of_CutSetAreaFlow( int * pCut, int d ) { pCut[3 + Of_CutSize(pCut)] = d; } + +static inline int Of_CutVar( int * pCut, int v ) { return Abc_Lit2Var(Of_CutLeaves(pCut)[v]); } +static inline int Of_CutFlag( int * pCut, int v ) { return Abc_LitIsCompl(Of_CutLeaves(pCut)[v]); } +static inline void Of_CutCleanFlag( int * pCut, int v ) { Of_CutLeaves(pCut)[v] = Abc_LitRegular(Of_CutLeaves(pCut)[v]); } +static inline void Of_CutSetFlag( int * pCut, int v, int x ) { Of_CutLeaves(pCut)[v] = Abc_Var2Lit(Of_CutVar(pCut, v), x); } + +static inline Of_Obj_t * Of_ObjData( Of_Man_t * p, int i ) { return p->pObjs + i; } + +static inline int Of_ObjCutBest( Of_Man_t * p, int i ) { return Of_ObjData(p, i)->iCutH; } +static inline int Of_ObjCutBest2( Of_Man_t * p, int i ) { return Of_ObjData(p, i)->iCutH2; } +static inline int Of_ObjDelay1( Of_Man_t * p, int i ) { return Of_ObjData(p, i)->Delay1; } +static inline int Of_ObjDelay2( Of_Man_t * p, int i ) { return Of_ObjData(p, i)->Delay2; } +static inline int Of_ObjRequired( Of_Man_t * p, int i ) { return Of_ObjData(p, i)->Required; } +static inline int Of_ObjRefNum( Of_Man_t * p, int i ) { return Of_ObjData(p, i)->nRefs; } +static inline int Of_ObjFlow( Of_Man_t * p, int i ) { return Of_ObjData(p, i)->Flow; } + +static inline void Of_ObjSetCutBest( Of_Man_t * p, int i, int x ) { Of_ObjData(p, i)->iCutH = x; } +static inline void Of_ObjSetCutBest2( Of_Man_t * p, int i, int x ) { Of_ObjData(p, i)->iCutH2 = x; } +static inline void Of_ObjSetDelay1( Of_Man_t * p, int i, int x ) { Of_ObjData(p, i)->Delay1 = x; } +static inline void Of_ObjSetDelay2( Of_Man_t * p, int i, int x ) { Of_ObjData(p, i)->Delay2 = x; } +static inline void Of_ObjSetRequired( Of_Man_t * p, int i, int x ) { Of_ObjData(p, i)->Required = x; } +static inline void Of_ObjSetRefNum( Of_Man_t * p, int i, int x ) { Of_ObjData(p, i)->nRefs = x; } +static inline void Of_ObjSetFlow( Of_Man_t * p, int i, int x ) { Of_ObjData(p, i)->Flow = x; } +static inline void Of_ObjUpdateRequired( Of_Man_t * p,int i, int x ) { if ( Of_ObjRequired(p, i) > x ) Of_ObjSetRequired(p, i, x); } +static inline int Of_ObjRefInc( Of_Man_t * p, int i ) { return Of_ObjData(p, i)->nRefs++; } +static inline int Of_ObjRefDec( Of_Man_t * p, int i ) { return --Of_ObjData(p, i)->nRefs; } + +static inline int * Of_ObjCutBestP( Of_Man_t * p, int iObj ) { assert(iObj>0 && iObjpGia));return Of_ManCutSet( p, Of_ObjCutBest(p, iObj) ); } +static inline void Of_ObjSetCutBestP( Of_Man_t * p, int * pCutSet, int iObj, int * pCut ) { Of_ObjSetCutBest( p, iObj, Of_ObjCutSetId(p, iObj) + Of_CutHandle(pCutSet, pCut) ); } + +static inline int * Of_ObjCutBestP2( Of_Man_t * p, int iObj ) { assert(iObj>0 && iObjpGia));return Of_ManCutSet( p, Of_ObjCutBest2(p, iObj) ); } +static inline void Of_ObjSetCutBestP2( Of_Man_t * p, int * pCutSet, int iObj, int * pCut ) { Of_ObjSetCutBest2( p, iObj, Of_ObjCutSetId(p, iObj) + Of_CutHandle(pCutSet, pCut) ); } + +#define Of_SetForEachCut( pList, pCut, i ) for ( i = 0, pCut = pList + 1; i < pList[0]; i++, pCut += Of_CutSize(pCut) + OF_CUT_EXTRA ) +#define Of_ObjForEachCut( pCuts, i, nCuts ) for ( i = 0, i < nCuts; i++ ) +#define Of_CutForEachVar( pCut, iVar, i ) for ( i = 0; i < Of_CutSize(pCut) && (iVar = Of_CutVar(pCut,i)); i++ ) +#define Of_CutForEachVarFlag( pCut, iVar, Flag, i ) for ( i = 0; i < Of_CutSize(pCut) && (iVar = Of_CutVar(pCut,i)) && ((Flag = Of_CutFlag(pCut,i)), 1); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Area flow.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Of_ManAreaFlow( Of_Man_t * p ) +{ + int AreaUnit = 1000; + int i, Id, Total = 0; + Gia_Obj_t * pObj; + assert( p->pGia->pRefs == NULL ); + Gia_ManCreateRefs( p->pGia ); + Of_ObjSetFlow( p, 0, 0 ); + Gia_ManForEachCiId( p->pGia, Id, i ) + Of_ObjSetFlow( p, Id, 0 ); + Gia_ManForEachAnd( p->pGia, pObj, Id ) + Of_ObjSetFlow( p, Id, (Gia_ObjFanin0(pObj)->Value + Gia_ObjFanin1(pObj)->Value + AreaUnit) / Gia_ObjRefNum(p->pGia, pObj) ); + Gia_ManForEachCo( p->pGia, pObj, i ) + Total += Gia_ObjFanin0(pObj)->Value; + ABC_FREE( p->pGia->pRefs ); + if ( 1 ) + return; + printf( "CI = %5d. ", Gia_ManCiNum(p->pGia) ); + printf( "CO = %5d. ", Gia_ManCoNum(p->pGia) ); + printf( "And = %8d. ", Gia_ManAndNum(p->pGia) ); + printf( "Area = %8d. ", Total/AreaUnit ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Of_Man_t * Of_StoCreate( Gia_Man_t * pGia, Jf_Par_t * pPars ) +{ + extern void Mf_ManSetFlowRefs( Gia_Man_t * p, Vec_Int_t * vRefs ); + Of_Man_t * p; + Vec_Int_t * vFlowRefs; + int * pRefs = NULL; + assert( pPars->nCutNum > 1 && pPars->nCutNum <= OF_CUT_MAX ); + assert( pPars->nLutSize > 1 && pPars->nLutSize <= OF_LEAF_MAX ); + ABC_FREE( pGia->pRefs ); + Vec_IntFreeP( &pGia->vCellMapping ); + if ( Gia_ManHasChoices(pGia) ) + Gia_ManSetPhase(pGia); + // create references + ABC_FREE( pGia->pRefs ); + vFlowRefs = Vec_IntAlloc(0); + Mf_ManSetFlowRefs( pGia, vFlowRefs ); + pGia->pRefs= Vec_IntReleaseArray(vFlowRefs); + Vec_IntFree(vFlowRefs); + // create + p = ABC_CALLOC( Of_Man_t, 1 ); + p->clkStart = Abc_Clock(); + p->pGia = pGia; + p->pPars = pPars; + p->pObjs = ABC_CALLOC( Of_Obj_t, Gia_ManObjNum(pGia) ); + p->iCur = 2; + // other + Vec_PtrGrow( &p->vPages, 256 ); // cut memory + Vec_IntFill( &p->vCutSets, Gia_ManObjNum(pGia), 0 ); // cut offsets + Vec_IntFill( &p->vCutFlows, Gia_ManObjNum(pGia), 0 ); // cut area + Vec_IntFill( &p->vCutDelays,Gia_ManObjNum(pGia), 0 ); // cut delay + Vec_IntGrow( &p->vCutRefs, 1000 ); // cut references + if ( pPars->fCutMin ) + p->vTtMem = Vec_MemAllocForTT( 6, 0 ); + // compute area flow + pRefs = pGia->pRefs; pGia->pRefs = NULL; + Of_ManAreaFlow( p ); + pGia->pRefs = pRefs; + return p; +} +void Of_StoDelete( Of_Man_t * p ) +{ + Vec_PtrFreeData( &p->vPages ); + Vec_PtrErase( &p->vPages ); + Vec_IntErase( &p->vCutSets ); + Vec_IntErase( &p->vCutFlows ); + Vec_IntErase( &p->vCutDelays ); + Vec_IntErase( &p->vCutRefs ); + ABC_FREE( p->pObjs ); + // matching + if ( p->pPars->fCutMin ) + Vec_MemHashFree( p->vTtMem ); + if ( p->pPars->fCutMin ) + Vec_MemFree( p->vTtMem ); + ABC_FREE( p ); +} + + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Of_CutComputeTruth6( Of_Man_t * p, Of_Cut_t * pCut0, Of_Cut_t * pCut1, int fCompl0, int fCompl1, Of_Cut_t * pCutR, int fIsXor ) +{ +// extern int Of_ManTruthCanonicize( word * t, int nVars ); + int nOldSupp = pCutR->nLeaves, truthId, fCompl; word t; + word t0 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut0->iFunc)); + word t1 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut1->iFunc)); + if ( Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ) t0 = ~t0; + if ( Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ) t1 = ~t1; + t0 = Abc_Tt6Expand( t0, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + t1 = Abc_Tt6Expand( t1, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + t = fIsXor ? t0 ^ t1 : t0 & t1; + if ( (fCompl = (int)(t & 1)) ) t = ~t; + pCutR->nLeaves = Abc_Tt6MinBase( &t, pCutR->pLeaves, pCutR->nLeaves ); + assert( (int)(t & 1) == 0 ); + truthId = Vec_MemHashInsert(p->vTtMem, &t); + pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); + assert( (int)pCutR->nLeaves <= nOldSupp ); + return (int)pCutR->nLeaves < nOldSupp; +} +static inline int Of_CutComputeTruthMux6( Of_Man_t * p, Of_Cut_t * pCut0, Of_Cut_t * pCut1, Of_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, Of_Cut_t * pCutR ) +{ + int nOldSupp = pCutR->nLeaves, truthId, fCompl; word t; + word t0 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut0->iFunc)); + word t1 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut1->iFunc)); + word tC = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCutC->iFunc)); + if ( Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ) t0 = ~t0; + if ( Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ) t1 = ~t1; + if ( Abc_LitIsCompl(pCutC->iFunc) ^ fComplC ) tC = ~tC; + t0 = Abc_Tt6Expand( t0, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + t1 = Abc_Tt6Expand( t1, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + tC = Abc_Tt6Expand( tC, pCutC->pLeaves, pCutC->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + t = (tC & t1) | (~tC & t0); + if ( (fCompl = (int)(t & 1)) ) t = ~t; + pCutR->nLeaves = Abc_Tt6MinBase( &t, pCutR->pLeaves, pCutR->nLeaves ); + assert( (int)(t & 1) == 0 ); + truthId = Vec_MemHashInsert(p->vTtMem, &t); + pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); + assert( (int)pCutR->nLeaves <= nOldSupp ); + return (int)pCutR->nLeaves < nOldSupp; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Of_CutCountBits( word i ) +{ + i = i - ((i >> 1) & 0x5555555555555555); + i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333); + i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F); + return (i*(0x0101010101010101))>>56; +} +static inline word Of_CutGetSign( int * pLeaves, int nLeaves ) +{ + word Sign = 0; int i; + for ( i = 0; i < nLeaves; i++ ) + Sign |= ((word)1) << (pLeaves[i] & 0x3F); + return Sign; +} +static inline int Of_CutCreateUnit( Of_Cut_t * p, int i ) +{ + p->Delay = 0; + p->Flow = 0; + p->iFunc = 2; + p->nLeaves = 1; + p->pLeaves[0] = i; + p->Sign = ((word)1) << (i & 0x3F); + return 1; +} +static inline void Of_Cutprintf( Of_Man_t * p, Of_Cut_t * pCut ) +{ + int i, nDigits = Abc_Base10Log(Gia_ManObjNum(p->pGia)); + printf( "%d {", pCut->nLeaves ); + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + printf( " %*d", nDigits, pCut->pLeaves[i] ); + for ( ; i < (int)p->pPars->nLutSize; i++ ) + printf( " %*s", nDigits, " " ); + printf( " } D = %4d A = %9d F = %6d ", + pCut->Delay, pCut->Flow, pCut->iFunc ); + if ( p->vTtMem ) + Dau_DsdPrintFromTruth( Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut->iFunc)), pCut->nLeaves ); + else + printf( "\n" ); +} +static inline int Of_ManPrepareCuts( Of_Cut_t * pCuts, Of_Man_t * p, int iObj, int fAddUnit ) +{ + if ( Of_ObjHasCuts(p, iObj) ) + { + Of_Cut_t * pMfCut = pCuts; + int i, * pCut, * pList = Of_ObjCutSet(p, iObj); + Of_SetForEachCut( pList, pCut, i ) + { + pMfCut->Delay = 0; + pMfCut->Flow = 0; + pMfCut->iFunc = Of_CutFunc( pCut ); + pMfCut->nLeaves = Of_CutSize( pCut ); + pMfCut->Sign = Of_CutGetSign( pCut+1, Of_CutSize(pCut) ); + memcpy( pMfCut->pLeaves, pCut+1, sizeof(int) * Of_CutSize(pCut) ); + pMfCut++; + } + if ( fAddUnit && pCuts->nLeaves > 1 ) + return pList[0] + Of_CutCreateUnit( pMfCut, iObj ); + return pList[0]; + } + return Of_CutCreateUnit( pCuts, iObj ); +} +static inline int Of_ManSaveCuts( Of_Man_t * p, Of_Cut_t ** pCuts, int nCuts ) +{ + int i, * pPlace, iCur, nInts = 1, nCutsNew = 0; + for ( i = 0; i < nCuts; i++ ) + nInts += pCuts[i]->nLeaves + OF_CUT_EXTRA, nCutsNew++; + if ( (p->iCur & 0xFFFF) + nInts > 0xFFFF ) + p->iCur = ((p->iCur >> 16) + 1) << 16; + if ( Vec_PtrSize(&p->vPages) == (p->iCur >> 16) ) + Vec_PtrPush( &p->vPages, ABC_CALLOC(int, (1<<16)) ); + iCur = p->iCur; p->iCur += nInts; + pPlace = Of_ManCutSet( p, iCur ); + *pPlace++ = nCutsNew; + for ( i = 0; i < nCuts; i++ ) + { + *pPlace++ = Of_CutSetBoth( pCuts[i]->nLeaves, pCuts[i]->iFunc ); + memcpy( pPlace, pCuts[i]->pLeaves, sizeof(int) * pCuts[i]->nLeaves ); + pPlace += pCuts[i]->nLeaves; + memset( pPlace, 0xFF, sizeof(int) * (OF_CUT_EXTRA - 1) ); + pPlace += OF_CUT_EXTRA - 1; + } + return iCur; +} +static inline void Of_ManLiftCuts( Of_Man_t * p, int iObj ) +{ + int i, k, * pCut, * pList = Of_ObjCutSet(p, iObj); + assert( Of_ObjHasCuts(p, iObj) ); + Of_SetForEachCut( pList, pCut, i ) + { + for ( k = 1; k <= Of_CutSize(pCut); k++ ) + pCut[k] = Abc_Var2Lit(pCut[k], 0); + } +} +static inline void Of_CutPrint( int * pCut ) +{ + int k, iVar; + printf( "Cut with %d inputs and function %3d : { ", Of_CutSize(pCut), Of_CutFunc(pCut) == OF_NO_FUNC ? 0 : Of_CutFunc(pCut) ); + Of_CutForEachVar( pCut, iVar, k ) + printf( "%d ", iVar ); + printf( "}\n" ); +} + +/**Function************************************************************* + + Synopsis [Check correctness of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Of_CutCheck( Of_Cut_t * pBase, Of_Cut_t * pCut ) // check if pCut is contained in pBase +{ + int nSizeB = pBase->nLeaves; + int nSizeC = pCut->nLeaves; + int i, * pB = pBase->pLeaves; + int k, * pC = pCut->pLeaves; + for ( i = 0; i < nSizeC; i++ ) + { + for ( k = 0; k < nSizeB; k++ ) + if ( pC[i] == pB[k] ) + break; + if ( k == nSizeB ) + return 0; + } + return 1; +} +static inline int Of_SetCheckArray( Of_Cut_t ** ppCuts, int nCuts ) +{ + Of_Cut_t * pCut0, * pCut1; + int i, k, m, n, Value; + assert( nCuts > 0 ); + for ( i = 0; i < nCuts; i++ ) + { + pCut0 = ppCuts[i]; + assert( pCut0->nLeaves <= OF_LEAF_MAX ); + assert( pCut0->Sign == Of_CutGetSign(pCut0->pLeaves, pCut0->nLeaves) ); + // check duplicates + for ( m = 0; m < (int)pCut0->nLeaves; m++ ) + for ( n = m + 1; n < (int)pCut0->nLeaves; n++ ) + assert( pCut0->pLeaves[m] < pCut0->pLeaves[n] ); + // check pairs + for ( k = 0; k < nCuts; k++ ) + { + pCut1 = ppCuts[k]; + if ( pCut0 == pCut1 ) + continue; + // check containments + Value = Of_CutCheck( pCut0, pCut1 ); + assert( Value == 0 ); + } + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Of_CutMergeOrder( Of_Cut_t * pCut0, Of_Cut_t * pCut1, Of_Cut_t * pCut, int nLutSize ) +{ + int nSize0 = pCut0->nLeaves; + int nSize1 = pCut1->nLeaves; + int i, * pC0 = pCut0->pLeaves; + int k, * pC1 = pCut1->pLeaves; + int c, * pC = pCut->pLeaves; + // the case of the largest cut sizes + if ( nSize0 == nLutSize && nSize1 == nLutSize ) + { + for ( i = 0; i < nSize0; i++ ) + { + if ( pC0[i] != pC1[i] ) return 0; + pC[i] = pC0[i]; + } + pCut->nLeaves = nLutSize; + pCut->iFunc = OF_NO_FUNC; + pCut->Sign = pCut0->Sign | pCut1->Sign; + return 1; + } + // compare two cuts with different numbers + i = k = c = 0; + if ( nSize0 == 0 ) goto FlushCut1; + if ( nSize1 == 0 ) goto FlushCut0; + while ( 1 ) + { + if ( c == nLutSize ) return 0; + if ( pC0[i] < pC1[k] ) + { + pC[c++] = pC0[i++]; + if ( i >= nSize0 ) goto FlushCut1; + } + else if ( pC0[i] > pC1[k] ) + { + pC[c++] = pC1[k++]; + if ( k >= nSize1 ) goto FlushCut0; + } + else + { + pC[c++] = pC0[i++]; k++; + if ( i >= nSize0 ) goto FlushCut1; + if ( k >= nSize1 ) goto FlushCut0; + } + } + +FlushCut0: + if ( c + nSize0 > nLutSize + i ) return 0; + while ( i < nSize0 ) + pC[c++] = pC0[i++]; + pCut->nLeaves = c; + pCut->iFunc = OF_NO_FUNC; + pCut->Sign = pCut0->Sign | pCut1->Sign; + return 1; + +FlushCut1: + if ( c + nSize1 > nLutSize + k ) return 0; + while ( k < nSize1 ) + pC[c++] = pC1[k++]; + pCut->nLeaves = c; + pCut->iFunc = OF_NO_FUNC; + pCut->Sign = pCut0->Sign | pCut1->Sign; + return 1; +} +static inline int Of_CutMergeOrderMux( Of_Cut_t * pCut0, Of_Cut_t * pCut1, Of_Cut_t * pCut2, Of_Cut_t * pCut, int nLutSize ) +{ + int x0, i0 = 0, nSize0 = pCut0->nLeaves, * pC0 = pCut0->pLeaves; + int x1, i1 = 0, nSize1 = pCut1->nLeaves, * pC1 = pCut1->pLeaves; + int x2, i2 = 0, nSize2 = pCut2->nLeaves, * pC2 = pCut2->pLeaves; + int xMin, c = 0, * pC = pCut->pLeaves; + while ( 1 ) + { + x0 = (i0 == nSize0) ? ABC_INFINITY : pC0[i0]; + x1 = (i1 == nSize1) ? ABC_INFINITY : pC1[i1]; + x2 = (i2 == nSize2) ? ABC_INFINITY : pC2[i2]; + xMin = Abc_MinInt( Abc_MinInt(x0, x1), x2 ); + if ( xMin == ABC_INFINITY ) break; + if ( c == nLutSize ) return 0; + pC[c++] = xMin; + if (x0 == xMin) i0++; + if (x1 == xMin) i1++; + if (x2 == xMin) i2++; + } + pCut->nLeaves = c; + pCut->iFunc = OF_NO_FUNC; + pCut->Sign = pCut0->Sign | pCut1->Sign | pCut2->Sign; + return 1; +} +static inline int Of_SetCutIsContainedOrder( Of_Cut_t * pBase, Of_Cut_t * pCut ) // check if pCut is contained in pBase +{ + int i, nSizeB = pBase->nLeaves; + int k, nSizeC = pCut->nLeaves; + if ( nSizeB == nSizeC ) + { + for ( i = 0; i < nSizeB; i++ ) + if ( pBase->pLeaves[i] != pCut->pLeaves[i] ) + return 0; + return 1; + } + assert( nSizeB > nSizeC ); + if ( nSizeC == 0 ) + return 1; + for ( i = k = 0; i < nSizeB; i++ ) + { + if ( pBase->pLeaves[i] > pCut->pLeaves[k] ) + return 0; + if ( pBase->pLeaves[i] == pCut->pLeaves[k] ) + { + if ( ++k == nSizeC ) + return 1; + } + } + return 0; +} +static inline int Of_SetLastCutIsContained( Of_Cut_t ** pCuts, int nCuts ) +{ + int i; + for ( i = 0; i < nCuts; i++ ) + if ( pCuts[i]->nLeaves <= pCuts[nCuts]->nLeaves && (pCuts[i]->Sign & pCuts[nCuts]->Sign) == pCuts[i]->Sign && Of_SetCutIsContainedOrder(pCuts[nCuts], pCuts[i]) ) + return 1; + return 0; +} +static inline int Of_SetLastCutContainsArea( Of_Cut_t ** pCuts, int nCuts ) +{ + int i, k, fChanges = 0; + for ( i = 0; i < nCuts; i++ ) + if ( pCuts[nCuts]->nLeaves < pCuts[i]->nLeaves && (pCuts[nCuts]->Sign & pCuts[i]->Sign) == pCuts[nCuts]->Sign && Of_SetCutIsContainedOrder(pCuts[i], pCuts[nCuts]) ) + pCuts[i]->nLeaves = OF_NO_LEAF, fChanges = 1; + if ( !fChanges ) + return nCuts; + for ( i = k = 0; i <= nCuts; i++ ) + { + if ( pCuts[i]->nLeaves == OF_NO_LEAF ) + continue; + if ( k < i ) + ABC_SWAP( Of_Cut_t *, pCuts[k], pCuts[i] ); + k++; + } + return k - 1; +} +static inline int Of_CutCompareArea( Of_Cut_t * pCut0, Of_Cut_t * pCut1 ) +{ + if ( pCut0->Delay < pCut1->Delay ) return -1; + if ( pCut0->Delay > pCut1->Delay ) return 1; + if ( pCut0->Flow < pCut1->Flow ) return -1; + if ( pCut0->Flow > pCut1->Flow ) return 1; + if ( pCut0->nLeaves < pCut1->nLeaves ) return -1; + if ( pCut0->nLeaves > pCut1->nLeaves ) return 1; + return 0; +} +static inline void Of_SetSortByArea( Of_Cut_t ** pCuts, int nCuts ) +{ + int i; + for ( i = nCuts; i > 0; i-- ) + { + if ( Of_CutCompareArea(pCuts[i - 1], pCuts[i]) < 0 )//!= 1 ) + return; + ABC_SWAP( Of_Cut_t *, pCuts[i - 1], pCuts[i] ); + } +} +static inline int Of_SetAddCut( Of_Cut_t ** pCuts, int nCuts, int nCutNum ) +{ + if ( nCuts == 0 ) + return 1; + nCuts = Of_SetLastCutContainsArea(pCuts, nCuts); + Of_SetSortByArea( pCuts, nCuts ); + return Abc_MinInt( nCuts + 1, nCutNum - 1 ); +} +static inline int Of_CutArea( Of_Man_t * p, int nLeaves ) +{ + if ( nLeaves < 2 ) + return 0; + return nLeaves + p->pPars->nAreaTuner; +} +static inline void Of_CutParams( Of_Man_t * p, Of_Cut_t * pCut, int nGiaRefs ) +{ + int i, nLeaves = pCut->nLeaves; + assert( nLeaves <= p->pPars->nLutSize ); + pCut->Delay = 0; + pCut->Flow = 0; + for ( i = 0; i < nLeaves; i++ ) + { + pCut->Delay = Abc_MaxInt( pCut->Delay, Of_ObjCutDelay(p, pCut->pLeaves[i]) ); + pCut->Flow += Of_ObjCutFlow(p, pCut->pLeaves[i]); + } + pCut->Delay += (int)(nLeaves > 1); + pCut->Flow = (pCut->Flow + 100 * Of_CutArea(p, nLeaves)) / (nGiaRefs ? nGiaRefs : 1); +} +void Of_ObjMergeOrder( Of_Man_t * p, int iObj ) +{ + Of_Cut_t pCuts0[OF_CUT_MAX], pCuts1[OF_CUT_MAX], pCuts[OF_CUT_MAX], * pCutsR[OF_CUT_MAX]; + Gia_Obj_t * pObj = Gia_ManObj(p->pGia, iObj); + int nGiaRefs = 2*Gia_ObjRefNumId(p->pGia, iObj); + int nLutSize = p->pPars->nLutSize; + int nCutNum = p->pPars->nCutNum; + int nCuts0 = Of_ManPrepareCuts(pCuts0, p, Gia_ObjFaninId0(pObj, iObj), 1); + int nCuts1 = Of_ManPrepareCuts(pCuts1, p, Gia_ObjFaninId1(pObj, iObj), 1); + int fComp0 = Gia_ObjFaninC0(pObj); + int fComp1 = Gia_ObjFaninC1(pObj); + int iSibl = Gia_ObjSibl(p->pGia, iObj); + Of_Cut_t * pCut0, * pCut1, * pCut0Lim = pCuts0 + nCuts0, * pCut1Lim = pCuts1 + nCuts1; + int i, nCutsR = 0; + assert( !Gia_ObjIsBuf(pObj) ); + for ( i = 0; i < nCutNum; i++ ) + pCutsR[i] = pCuts + i; + if ( iSibl ) + { + Of_Cut_t pCuts2[OF_CUT_MAX]; + Gia_Obj_t * pObjE = Gia_ObjSiblObj(p->pGia, iObj); + int fCompE = Gia_ObjPhase(pObj) ^ Gia_ObjPhase(pObjE); + int nCuts2 = Of_ManPrepareCuts(pCuts2, p, iSibl, 0); + Of_Cut_t * pCut2, * pCut2Lim = pCuts2 + nCuts2; + for ( pCut2 = pCuts2; pCut2 < pCut2Lim; pCut2++ ) + { + *pCutsR[nCutsR] = *pCut2; + if ( p->pPars->fCutMin ) + pCutsR[nCutsR]->iFunc = Abc_LitNotCond( pCutsR[nCutsR]->iFunc, fCompE ); + Of_CutParams( p, pCutsR[nCutsR], nGiaRefs ); + nCutsR = Of_SetAddCut( pCutsR, nCutsR, nCutNum ); + } + } + if ( Gia_ObjIsMuxId(p->pGia, iObj) ) + { + Of_Cut_t pCuts2[OF_CUT_MAX]; + int nCuts2 = Of_ManPrepareCuts(pCuts2, p, Gia_ObjFaninId2(p->pGia, iObj), 1); + int fComp2 = Gia_ObjFaninC2(p->pGia, pObj); + Of_Cut_t * pCut2, * pCut2Lim = pCuts2 + nCuts2; + p->CutCount[0] += nCuts0 * nCuts1 * nCuts2; + for ( pCut0 = pCuts0; pCut0 < pCut0Lim; pCut0++ ) + for ( pCut1 = pCuts1; pCut1 < pCut1Lim; pCut1++ ) + for ( pCut2 = pCuts2; pCut2 < pCut2Lim; pCut2++ ) + { + if ( Of_CutCountBits(pCut0->Sign | pCut1->Sign | pCut2->Sign) > nLutSize ) + continue; + p->CutCount[1]++; + if ( !Of_CutMergeOrderMux(pCut0, pCut1, pCut2, pCutsR[nCutsR], nLutSize) ) + continue; + if ( Of_SetLastCutIsContained(pCutsR, nCutsR) ) + continue; + p->CutCount[2]++; + if ( p->pPars->fCutMin && Of_CutComputeTruthMux6(p, pCut0, pCut1, pCut2, fComp0, fComp1, fComp2, pCutsR[nCutsR]) ) + pCutsR[nCutsR]->Sign = Of_CutGetSign(pCutsR[nCutsR]->pLeaves, pCutsR[nCutsR]->nLeaves); + Of_CutParams( p, pCutsR[nCutsR], nGiaRefs ); + nCutsR = Of_SetAddCut( pCutsR, nCutsR, nCutNum ); + } + } + else + { + int fIsXor = Gia_ObjIsXor(pObj); + p->CutCount[0] += nCuts0 * nCuts1; + for ( pCut0 = pCuts0; pCut0 < pCut0Lim; pCut0++ ) + for ( pCut1 = pCuts1; pCut1 < pCut1Lim; pCut1++ ) + { + if ( (int)(pCut0->nLeaves + pCut1->nLeaves) > nLutSize && Of_CutCountBits(pCut0->Sign | pCut1->Sign) > nLutSize ) + continue; + p->CutCount[1]++; + if ( !Of_CutMergeOrder(pCut0, pCut1, pCutsR[nCutsR], nLutSize) ) + continue; + if ( Of_SetLastCutIsContained(pCutsR, nCutsR) ) + continue; + p->CutCount[2]++; + if ( p->pPars->fCutMin && Of_CutComputeTruth6(p, pCut0, pCut1, fComp0, fComp1, pCutsR[nCutsR], fIsXor) ) + pCutsR[nCutsR]->Sign = Of_CutGetSign(pCutsR[nCutsR]->pLeaves, pCutsR[nCutsR]->nLeaves); + Of_CutParams( p, pCutsR[nCutsR], nGiaRefs ); + nCutsR = Of_SetAddCut( pCutsR, nCutsR, nCutNum ); + } + } + // debug printout + if ( 0 ) + { + printf( "*** Obj = %d\n", iObj ); + for ( i = 0; i < nCutsR; i++ ) + Of_Cutprintf( p, pCutsR[i] ); + printf( "\n" ); + } + // verify + assert( nCutsR > 0 && nCutsR < nCutNum ); + //assert( Of_SetCheckArray(pCutsR, nCutsR) ); + // store the cutset + Of_ObjSetCutFlow( p, iObj, pCutsR[0]->Flow ); + Of_ObjSetCutDelay( p, iObj, pCutsR[0]->Delay ); + *Vec_IntEntryP(&p->vCutSets, iObj) = Of_ManSaveCuts(p, pCutsR, nCutsR); + p->CutCount[3] += nCutsR; +} +void Of_ManComputeCuts( Of_Man_t * p ) +{ + Gia_Obj_t * pObj; int i, iFanin; + Gia_ManForEachAnd( p->pGia, pObj, i ) + if ( Gia_ObjIsBuf(pObj) ) + { + iFanin = Gia_ObjFaninId0(pObj, i); + Of_ObjSetCutFlow( p, i, Of_ObjCutFlow(p, iFanin) ); + Of_ObjSetCutDelay( p, i, Of_ObjCutDelay(p, iFanin) ); + } + else + Of_ObjMergeOrder( p, i ); + Gia_ManForEachAnd( p->pGia, pObj, i ) + if ( !Gia_ObjIsBuf(pObj) ) + Of_ManLiftCuts( p, i ); +} + + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Of_ManPrintStats( Of_Man_t * p, char * pTitle ) +{ + if ( !p->pPars->fVerbose ) + return; + printf( "%s : ", pTitle ); + printf( "Delay =%8.2f ", Of_Int2Flt((int)p->pPars->Delay) ); + printf( "Area =%8d ", (int)p->pPars->Area ); + printf( "Edge =%9d ", (int)p->pPars->Edge ); + Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); + fflush( stdout ); +} +void Of_ManPrintInit( Of_Man_t * p ) +{ + int nChoices; + if ( !p->pPars->fVerbose ) + return; + printf( "LutSize = %d ", p->pPars->nLutSize ); + printf( "CutNum = %d ", p->pPars->nCutNum ); + printf( "Iter = %d ", p->pPars->nRounds + p->pPars->nRoundsEla ); + printf( "Coarse = %d ", p->pPars->fCoarsen ); + if ( p->pPars->fCutMin ) + printf( "Funcs = %d ", Vec_MemEntryNum(p->vTtMem) ); + nChoices = Gia_ManChoiceNum( p->pGia ); + if ( nChoices ) + printf( "Choices = %d ", nChoices ); + printf( "\n" ); + printf( "Computing cuts...\r" ); + fflush( stdout ); +} +void Of_ManPrintQuit( Of_Man_t * p ) +{ + float MemGia = Gia_ManMemory(p->pGia) / (1<<20); + float MemMan = 1.0 * sizeof(Of_Obj_t) * Gia_ManObjNum(p->pGia) / (1<<20); + float MemCuts = 1.0 * sizeof(int) * (1 << 16) * Vec_PtrSize(&p->vPages) / (1<<20); + float MemTt = p->vTtMem ? Vec_MemMemory(p->vTtMem) / (1<<20) : 0; + if ( p->CutCount[0] == 0 ) + p->CutCount[0] = 1; + if ( !p->pPars->fVerbose ) + return; + printf( "CutPair = %.0f ", p->CutCount[0] ); + printf( "Merge = %.0f (%.1f) ", p->CutCount[1], 1.0*p->CutCount[1]/Gia_ManAndNum(p->pGia) ); + printf( "Eval = %.0f (%.1f) ", p->CutCount[2], 1.0*p->CutCount[2]/Gia_ManAndNum(p->pGia) ); + printf( "Cut = %.0f (%.1f) ", p->CutCount[3], 1.0*p->CutCount[3]/Gia_ManAndNum(p->pGia) ); +// printf( "Use = %.0f (%.1f) ", p->CutCount[4], 1.0*p->CutCount[4]/Gia_ManAndNum(p->pGia) ); +// printf( "Mat = %.0f (%.1f) ", p->CutCount[5], 1.0*p->CutCount[5]/Gia_ManAndNum(p->pGia) ); +// printf( "Equ = %d (%.2f %%) ", p->nCutUseAll, 100.0*p->nCutUseAll /p->CutCount[0] ); + printf( "\n" ); + printf( "Gia = %.2f MB ", MemGia ); + printf( "Man = %.2f MB ", MemMan ); + printf( "Cut = %.2f MB ", MemCuts ); + if ( p->pPars->fCutMin ) + printf( "TT = %.2f MB ", MemTt ); + printf( "Total = %.2f MB ", MemGia + MemMan + MemCuts + MemTt ); +// printf( "\n" ); + Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); + fflush( stdout ); +} + + +/**Function************************************************************* + + Synopsis [Technology mappping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +/* +static inline int Of_ManComputeForwardCut( Of_Man_t * p, int iObj, int * pCut ) +{ + int k, iVar, Delay = 0, Area = Of_CutArea(p, Of_CutSize(pCut)); + int DelayLut1 = p->pPars->nDelayLut1; + Of_CutForEachVar( pCut, iVar, k ) + { + Delay = Abc_MaxInt( Delay, Of_ObjDelay1(p, iVar) + DelayLut1 ); + if ( p->Iter ) + Area += Of_ObjRefNum(p, iVar) ? 0 : Of_ObjFlow(p, iVar); + } + Of_CutSetDelay1( pCut, Delay ); + if ( p->Iter ) + Of_CutSetAreaFlow( pCut, Area ); + return Delay; +} +static inline void Of_ManComputeForwardObj( Of_Man_t * p, int iObj ) +{ + int Delay1 = ABC_INFINITY, Area1 = ABC_INFINITY; + int * pList = Of_ObjCutSet(p, iObj); + int i, * pCut, * pCutMin = NULL, * pCutMin2 = NULL; + // compute cut arrivals + Of_SetForEachCut( pList, pCut, i ) + { + int Delay1This = Of_ManComputeForwardCut(p, iObj, pCut); + if ( Delay1 > Delay1This ) + { + Delay1 = Delay1This; + pCutMin = pCut; + } + if ( p->Iter && Area1 > Of_CutAreaFlow(pCut) ) + { + Area1 = Of_CutAreaFlow(pCut); + pCutMin2 = pCut; + } + } + // if mapping is present, set object arrival equal to cut arrival + if ( Of_ObjRefNum(p, iObj) ) + { + pCutMin = Of_ObjCutBestP(p, iObj); + Delay1 = Of_CutDelay1( pCutMin ); + Of_ObjSetDelay1( p, iObj, Delay1 ); + if ( p->Iter ) + Of_ObjSetFlow( p, iObj, Of_CutAreaFlow(pCutMin) ); + } + else + { + if ( p->Iter == 0 ) + { + Of_ObjSetCutBestP( p, pList, iObj, pCutMin ); + Of_ObjSetDelay1( p, iObj, Delay1 ); + } + else + { + Of_ObjSetCutBestP( p, pList, iObj, pCutMin2 ); + Of_ObjSetDelay1( p, iObj, Of_CutDelay1(pCutMin2) ); + Of_ObjSetFlow( p, iObj, Of_CutAreaFlow(pCutMin2) ); + } + } +} +*/ + +/* +int * Of_CutReferChooseCut( Of_Man_t * p, int Var, int Required, int fSetBest ) +{ + int i, CostMin = ABC_INFINITY; + int * pCutMin = NULL, * pList = Of_ObjCutSet(p, Var); + int * pCut = Of_ObjCutBestP(p, Var); + assert( Of_CutDelay1(pCut) <= Required ); +// return pCut; + // choose cut with smaller area + Of_SetForEachCut( pList, pCut, i ) + { + if ( Of_CutDelay1(pCut) > Required ) + continue; + if ( CostMin > Of_CutAreaFlow(pCut) ) + { + CostMin = Of_CutAreaFlow(pCut); + pCutMin = pCut; + } + } + assert( pCutMin != NULL ); + assert( Of_CutDelay1(pCutMin) <= Required ); + if ( fSetBest ) + Of_ObjSetCutBestP( p, pList, Var, pCutMin ); + return pCutMin; +} +int Of_CutRef2_rec( Of_Man_t * p, int * pCut, int Required, int fSetBest ) +{ + int i, Var, Count = Of_CutArea(p, Of_CutSize(pCut)); + assert( Of_CutDelay1(pCut) <= Required ); + Required -= p->pPars->nDelayLut1; + Of_CutForEachVar( pCut, Var, i ) + { + if ( !Of_ObjCutBest(p, Var) ) + continue; + if ( !fSetBest ) + Vec_IntPush( &p->vCutRefs, Var ); + if ( Of_ObjRefInc(p, Var) ) + continue; + Count += Of_CutRef2_rec( p, Of_CutReferChooseCut(p, Var, Required, fSetBest), Required, fSetBest ); + } + return Count; +} +static inline int Of_CutAreaDerefed2( Of_Man_t * p, int * pCut, int Required ) +{ + int Ela1, i, iObj; + assert( Vec_IntSize(&p->vCutRefs) == 0 ); + Ela1 = Of_CutRef2_rec( p, pCut, Required, 0 ); + Vec_IntForEachEntry( &p->vCutRefs, iObj, i ) + Of_ObjRefDec(p, iObj); + Vec_IntClear( &p->vCutRefs ); + return Ela1; +} +*/ + + +static inline int Of_ManComputeForwardCut( Of_Man_t * p, int iObj, int * pCut ) +{ + int k, iVar, Delay = 0; + int DelayLut1 = p->pPars->nDelayLut1; + Of_CutForEachVar( pCut, iVar, k ) + Delay = Abc_MaxInt( Delay, Of_ObjDelay1(p, iVar) + DelayLut1 ); + Of_CutSetDelay1( pCut, Delay ); + return Delay; +} +static inline int Of_ManComputeForwardCutArea( Of_Man_t * p, int iObj, int * pCut ) +{ + int k, iVar, Area = 100 * Of_CutArea(p, Of_CutSize(pCut)); + Of_CutForEachVar( pCut, iVar, k ) + Area += Of_ObjFlow(p, iVar); + return Area / Abc_MaxInt(1, Of_ObjRefNum(p, iObj)); +} +static inline void Of_ManComputeForwardObj( Of_Man_t * p, int iObj ) +{ + int Delay1 = ABC_INFINITY; + int i, * pCut, * pCutMin = NULL, * pList = Of_ObjCutSet(p, iObj); + // compute cut arrivals + Of_SetForEachCut( pList, pCut, i ) + { + int Delay1This = Of_ManComputeForwardCut(p, iObj, pCut); + if ( Delay1 > Delay1This ) + { + Delay1 = Delay1This; + pCutMin = pCut; + } + } + // if mapping is present, set object arrival equal to cut arrival + if ( Of_ObjRefNum(p, iObj) ) + pCutMin = Of_ObjCutBestP(p, iObj); + Of_ObjSetCutBestP( p, pList, iObj, pCutMin ); + Of_ObjSetDelay1( p, iObj, Of_CutDelay1(pCutMin) ); + if ( p->Iter ) + Of_ObjSetFlow( p, iObj, Of_ManComputeForwardCutArea(p, iObj, pCutMin) ); +} +void Of_ManComputeForward1( Of_Man_t * p ) +{ + Gia_Obj_t * pObj; int i; + Gia_ManForEachAnd( p->pGia, pObj, i ) + if ( Gia_ObjIsBuf(pObj) ) + Of_ObjSetDelay1( p, i, Of_ObjDelay1(p, Gia_ObjFaninId0(pObj, i)) ); + else + Of_ManComputeForwardObj( p, i ); +} + + +int Of_CutRef_rec( Of_Man_t * p, int * pCut ) +{ + int i, Var, Count = (p->Iter & 1) ? 1 : Of_CutArea(p, Of_CutSize(pCut)); + Of_CutForEachVar( pCut, Var, i ) + if ( Of_ObjCutBest(p, Var) && !Of_ObjRefInc(p, Var) ) + Count += Of_CutRef_rec( p, Of_ObjCutBestP(p, Var) ); + return Count; +} +int Of_CutDeref_rec( Of_Man_t * p, int * pCut ) +{ + int i, Var, Count = (p->Iter & 1) ? 1 : Of_CutArea(p, Of_CutSize(pCut)); + Of_CutForEachVar( pCut, Var, i ) + if ( Of_ObjCutBest(p, Var) && !Of_ObjRefDec(p, Var) ) + Count += Of_CutDeref_rec( p, Of_ObjCutBestP(p, Var) ); + return Count; +} +static inline int Of_CutAreaDerefed( Of_Man_t * p, int * pCut ) +{ + int Ela1 = Of_CutRef_rec( p, pCut ); + int Ela2 = Of_CutDeref_rec( p, pCut ); + assert( Ela1 == Ela2 ); + return Ela1; +} + +int Of_CutRef2_rec( Of_Man_t * p, int * pCut ) +{ + int i, Var, Count = (p->Iter & 1) ? 1 : Of_CutArea(p, Of_CutSize(pCut)); + Of_CutForEachVar( pCut, Var, i ) + { + if ( !Of_ObjCutBest(p, Var) ) + continue; + Vec_IntPush( &p->vCutRefs, Var ); + if ( Of_ObjRefInc(p, Var) ) + continue; + Count += Of_CutRef2_rec( p, Of_ObjCutBestP(p, Var) ); + } + return Count; +} +static inline int Of_CutAreaDerefed2( Of_Man_t * p, int * pCut ) +{ + int Ela1, i, iObj; + assert( Vec_IntSize(&p->vCutRefs) == 0 ); + Ela1 = Of_CutRef2_rec( p, pCut ); + Vec_IntForEachEntry( &p->vCutRefs, iObj, i ) + Of_ObjRefDec(p, iObj); + Vec_IntClear( &p->vCutRefs ); + return Ela1; +} + + +static inline void Of_ManComputeForwardObj2( Of_Man_t * p, int iObj ) +{ + int Delay, Required = Of_ObjRequired(p, iObj); + int AreaBef = 0, AreaAft = 0, Area, AreaMin = ABC_INFINITY; + int k, * pCut, * pCutMin = NULL, * pList = Of_ObjCutSet(p, iObj); + if ( Of_ObjRefNum(p, iObj) ) + AreaBef = Of_CutDeref_rec( p, Of_ObjCutBestP(p, iObj) ); + Of_SetForEachCut( pList, pCut, k ) + { + Delay = Of_ManComputeForwardCut(p, iObj, pCut); + if ( Delay > Required ) + continue; + Area = Of_CutAreaDerefed2( p, pCut ); + if ( AreaMin > Area ) + { + AreaMin = Area; + pCutMin = pCut; + } + } + assert( pCutMin != NULL ); + Of_ObjSetCutBestP( p, pList, iObj, pCutMin ); + if ( Of_ObjRefNum(p, iObj) ) + AreaAft = Of_CutRef_rec( p, pCutMin ); + assert( AreaAft <= AreaBef ); + Delay = Of_CutDelay1(pCutMin); + assert( Delay <= Required ); + Of_ObjSetDelay1( p, iObj, Delay ); +} +void Of_ManComputeForward2( Of_Man_t * p ) +{ + Gia_Obj_t * pObj; int i; + Gia_ManForEachAnd( p->pGia, pObj, i ) + if ( Gia_ObjIsBuf(pObj) ) + Of_ObjSetDelay1( p, i, Of_ObjDelay1(p, Gia_ObjFaninId0(pObj, i)) ); + else + Of_ManComputeForwardObj2( p, i ); +} + + +static inline int Of_ManComputeOutputRequired( Of_Man_t * p, int fCleanRefs ) +{ + int i, Id, Delay = 0; + for ( i = 0; i < Gia_ManObjNum(p->pGia); i++ ) + { + Of_ObjSetRequired( p, i, ABC_INFINITY ); + if ( fCleanRefs ) + Of_ObjSetRefNum( p, i, 0 ); + } + Gia_ManForEachCoDriverId( p->pGia, Id, i ) + Delay = Abc_MaxInt( Delay, Of_ObjDelay1(p, Id) ); + Gia_ManForEachCoDriverId( p->pGia, Id, i ) + { + Of_ObjUpdateRequired( p, Id, Delay ); + if ( fCleanRefs ) + Of_ObjRefInc( p, Id ); + } + if ( p->pPars->Delay && p->pPars->Delay < Delay ) + printf( "Error: Delay violation.\n" ); + p->pPars->Delay = Delay; + return Delay; +} +static inline int Of_ManComputeBackwardCut( Of_Man_t * p, int * pCut ) +{ + int k, iVar, Cost = 0; + Of_CutForEachVar( pCut, iVar, k ) + if ( !Of_ObjRefNum(p, iVar) ) + Cost += Of_ObjFlow( p, iVar ); + return Cost; +} +void Of_ManComputeBackward1( Of_Man_t * p ) +{ + Gia_Obj_t * pObj; + int DelayLut1 = p->pPars->nDelayLut1; + int i, k, iVar, * pList, * pCut, * pCutMin; + Of_ManComputeOutputRequired( p, 1 ); + // compute area and edges + p->pPars->Area = p->pPars->Edge = 0; + Gia_ManForEachAndReverse( p->pGia, pObj, i ) + { + int CostMin, Cost, Required = Of_ObjRequired(p, i); + if ( Gia_ObjIsBuf(pObj) ) + { + int FaninId = Gia_ObjFaninId0(pObj, i); + Of_ObjUpdateRequired( p, FaninId, Required ); + Of_ObjRefInc( p, FaninId ); + continue; + } + if ( !Of_ObjRefNum(p, i) ) + continue; + // select the best cut + pCutMin = NULL; + CostMin = ABC_INFINITY; + pList = Of_ObjCutSet( p, i ); + Of_SetForEachCut( pList, pCut, k ) + { + if ( Of_CutDelay1(pCut) > Required ) + continue; + Cost = Of_ManComputeBackwardCut( p, pCut ); + if ( CostMin > Cost ) + { + CostMin = Cost; + pCutMin = pCut; + } + } + // the cut is selected + assert( pCutMin != NULL ); + Of_ObjSetCutBestP( p, pList, i, pCutMin ); + Of_CutForEachVar( pCutMin, iVar, k ) + { + Of_ObjUpdateRequired( p, iVar, Required - DelayLut1 ); + Of_ObjRefInc( p, iVar ); + } + // update parameters + p->pPars->Edge += Of_CutSize(pCutMin); + p->pPars->Area++; + } +} +void Of_ManComputeBackward2( Of_Man_t * p ) +{ + Gia_Obj_t * pObj; + int DelayLut1 = p->pPars->nDelayLut1; + int i, k, iVar, * pCutMin; + Of_ManComputeOutputRequired( p, 0 ); + // compute area and edges + p->pPars->Area = p->pPars->Edge = 0; + Gia_ManForEachAndReverse( p->pGia, pObj, i ) + { + int Required = Of_ObjRequired(p, i); + if ( Gia_ObjIsBuf(pObj) ) + { + int FaninId = Gia_ObjFaninId0(pObj, i); + Of_ObjUpdateRequired( p, FaninId, Required ); + continue; + } + if ( !Of_ObjRefNum(p, i) ) + continue; + // lookup for the cut + pCutMin = Of_ObjCutBestP( p, i ); + Of_CutForEachVar( pCutMin, iVar, k ) + Of_ObjUpdateRequired( p, iVar, Required - DelayLut1 ); + // update parameters + p->pPars->Edge += Of_CutSize(pCutMin); + p->pPars->Area++; + } +} +void Of_ManComputeBackward3( Of_Man_t * p ) +{ + Gia_Obj_t * pObj; + int DelayLut1 = p->pPars->nDelayLut1; + int i, k, iVar, * pList, * pCut, * pCutMin; + int AreaBef = 0, AreaAft = 0; + Of_ManComputeOutputRequired( p, 0 ); + // compute area and edges + p->pPars->Area = p->pPars->Edge = 0; + Gia_ManForEachAndReverse( p->pGia, pObj, i ) + { + int CostMin, Cost, Required = Of_ObjRequired(p, i); + if ( Gia_ObjIsBuf(pObj) ) + { + int FaninId = Gia_ObjFaninId0(pObj, i); + Of_ObjUpdateRequired( p, FaninId, Required ); + continue; + } + if ( !Of_ObjRefNum(p, i) ) + continue; + // deref best cut + AreaBef = Of_CutDeref_rec( p, Of_ObjCutBestP(p, i) ); + // select the best cut + pCutMin = NULL; + CostMin = ABC_INFINITY; + pList = Of_ObjCutSet( p, i ); + Of_SetForEachCut( pList, pCut, k ) + { + if ( Of_CutDelay1(pCut) > Required ) + continue; + Cost = Of_CutAreaDerefed2( p, pCut ); + if ( CostMin > Cost ) + { + CostMin = Cost; + pCutMin = pCut; + } + } + // the cut is selected + assert( pCutMin != NULL ); + Of_ObjSetCutBestP( p, pList, i, pCutMin ); + Of_CutForEachVar( pCutMin, iVar, k ) + Of_ObjUpdateRequired( p, iVar, Required - DelayLut1 ); + // ref best cut + AreaAft = Of_CutRef_rec( p, pCutMin ); + assert( AreaAft <= AreaBef ); + // update parameters + p->pPars->Edge += Of_CutSize(pCutMin); + p->pPars->Area++; + } +} + +/**Function************************************************************* + + Synopsis [Technology mappping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Of_ManComputeForwardDirconCut( Of_Man_t * p, int iObj, int * pCut, int * pDelay1, int * pDelay2 ) +{ + // Delay1 - main delay; Delay2 - precomputed LUT delay in terms of Delay1 for the fanins + int Delays[6], Perm[6] = {0, 1, 2, 3, 4, 5}; + int DelayLut1 = p->pPars->nDelayLut1; + int DelayLut2 = p->pPars->nDelayLut2; + int nSize = Of_CutSize(pCut); + int k, iVar, Flag, SlowCon, Delay, DelayAfter, fDirConWorks; + Of_CutForEachVar( pCut, iVar, k ) + { + Delays[k] = Of_ObjDelay1(p, iVar) + DelayLut1; +// printf( "%3d%s ", iVar, Flag ? "*" : " " ); + } + for ( ; k < p->pPars->nLutSize; k++ ) + { + Delays[k] = -ABC_INFINITY; +// printf( " " ); + } + Vec_IntSelectSortCost2Reverse( Perm, nSize, Delays ); + assert( nSize < 2 || Delays[0] >= Delays[nSize-1] ); + assert( Delays[0] >= 0 && Delays[nSize-1] >= 0 ); + // consider speedup due to dircons + fDirConWorks = 1; + *pDelay1 = *pDelay2 = 0; + SlowCon = p->pPars->nFastEdges < nSize ? Delays[p->pPars->nFastEdges] : 0; + for ( k = 0; k < nSize; k++ ) + { + // use dircon if the following is true + // - the input is eligible for dircon (does not exceed the limit) + // - there is an expected gain in delay, compared the largest delay without dircon + // - the dircon delay is indeed lower than the largest delay without dircon + // - all previous dircons worked out well + // - the node is an AND-gate + iVar = Of_CutVar( pCut, Perm[k] ); + assert( Delays[k] == Of_ObjDelay1(p, iVar) + DelayLut1 ); + DelayAfter = Of_ObjDelay2(p, iVar) + DelayLut2; + if ( k < p->pPars->nFastEdges && Delays[k] > SlowCon && DelayAfter < Delays[k] && fDirConWorks && Gia_ObjIsAndNotBuf(Gia_ManObj(p->pGia, iVar)) ) + { + Delay = DelayAfter; + Of_CutSetFlag( pCut, Perm[k], 1 ); + } + else + { + Delay = Delays[k];// + DelayLut2; + Of_CutSetFlag( pCut, Perm[k], 0 ); + fDirConWorks = 0; + } + *pDelay1 = Abc_MaxInt( *pDelay1, Delay ); + *pDelay2 = Abc_MaxInt( *pDelay2, Delays[k] ); + } +// printf( " %5.2f", Of_Int2Flt(*pDelay1) ); +// printf( " %5.2f\n", Of_Int2Flt(*pDelay2) ); + // do not use the structure if simple LUT is better + if ( *pDelay1 > *pDelay2 ) + { + for ( k = 0; k < nSize; k++ ) + Of_CutSetFlag( pCut, k, 0 ); + *pDelay1 = *pDelay2; + } + assert( *pDelay1 <= *pDelay2 ); + Of_CutSetDelay1( pCut, *pDelay1 ); + Of_CutSetDelay2( pCut, *pDelay2 ); + // verify + Of_CutForEachVarFlag( pCut, iVar, Flag, k ) + { + if ( Flag ) + assert( Of_ObjDelay2(p, iVar) + DelayLut2 <= *pDelay1 ); + else + assert( Of_ObjDelay1(p, iVar) + DelayLut1 <= *pDelay1 ); + assert( Of_ObjDelay1(p, iVar) + DelayLut1 <= *pDelay2 ); + } +} +int Of_ManComputeForwardDirconObj( Of_Man_t * p, int iObj ) +{ + int Delay1 = ABC_INFINITY, Delay2 = ABC_INFINITY; + int i, * pCut, * pCutMin = NULL, * pCutMin2 = NULL, * pList = Of_ObjCutSet(p, iObj); + Of_SetForEachCut( pList, pCut, i ) + { + int Delay1This, Delay2This; + Of_ManComputeForwardDirconCut( p, iObj, pCut, &Delay1This, &Delay2This ); + if ( Delay1 > Delay1This ) + pCutMin = pCut; + if ( Delay2 > Delay2This ) + pCutMin2 = pCut; + Delay1 = Abc_MinInt( Delay1, Delay1This ); + Delay2 = Abc_MinInt( Delay2, Delay2This ); + } + Of_ObjSetDelay1( p, iObj, Delay1 ); + Of_ObjSetDelay2( p, iObj, Delay2 ); + Of_ObjSetCutBestP( p, pList, iObj, pCutMin ); + Of_ObjSetCutBestP2( p, pList, iObj, pCutMin2 ); + return Delay1; +} +void Of_ManComputeForwardDircon1( Of_Man_t * p ) +{ + Gia_Obj_t * pObj; int i; + Gia_ManForEachAnd( p->pGia, pObj, i ) + if ( Gia_ObjIsBuf(pObj) ) + { + Of_ObjSetDelay1( p, i, Of_ObjDelay1(p, Gia_ObjFaninId0(pObj, i)) ); + Of_ObjSetDelay2( p, i, Of_ObjDelay2(p, Gia_ObjFaninId0(pObj, i)) ); + } + else + Of_ManComputeForwardDirconObj( p, i ); +} +void Of_ManComputeBackwardDircon1( Of_Man_t * p ) +{ + Gia_Obj_t * pObj; + Vec_Bit_t * vPointed; + int DelayLut1 = p->pPars->nDelayLut1; + int DelayLut2 = p->pPars->nDelayLut2; + int i, k, iVar, Flag, * pList, * pCutMin; + int CountNodes = 0, CountEdges = 0; + Of_ManComputeOutputRequired( p, 1 ); + printf( "Global delay =%8.2f\n", Of_Int2Flt((int)p->pPars->Delay) ); + //return; + // compute area and edges + vPointed = Vec_BitStart( Gia_ManObjNum(p->pGia) ); + p->pPars->Area = p->pPars->Edge = 0; + Gia_ManForEachAndReverse( p->pGia, pObj, i ) + { + int CostMin, fPointed, Required = Of_ObjRequired(p, i); + if ( Gia_ObjIsBuf(pObj) ) + { + int FaninId = Gia_ObjFaninId0(pObj, i); + Of_ObjUpdateRequired( p, FaninId, Required ); + Of_ObjRefInc( p, FaninId ); + continue; + } + if ( !Of_ObjRefNum(p, i) ) + continue; + // check if the LUT is has an outgoing dircon edge + fPointed = Vec_BitEntry(vPointed, i); + CountNodes += fPointed; + +/* + // select the best cut + { + int * pCut; + pCutMin = NULL; + CostMin = ABC_INFINITY; + pList = Of_ObjCutSet( p, i ); + Of_SetForEachCut( pList, pCut, k ) + { + int Cost; + if ( (fPointed ? Of_CutDelay2(pCut) : Of_CutDelay1(pCut)) > Required ) + continue; + Cost = Of_ManComputeBackwardCut( p, pCut ); + if ( CostMin > Cost ) + { + CostMin = Cost; + pCutMin = pCut; + } + } + } +*/ + + if ( fPointed ) + { + pCutMin = Of_ObjCutBestP2( p, i ); + CostMin = Of_CutDelay2(pCutMin); + //assert( Of_CutDelay2(pCutMin) <= Required ); + } + else + { + pCutMin = Of_ObjCutBestP( p, i ); + CostMin = Of_CutDelay1(pCutMin); + //assert( Of_CutDelay1(pCutMin) <= Required ); + } + + // remove dircon markers + //if ( fPointed ) + // Of_CutForEachVarFlag( pCutMin, iVar, Flag, k ) + // Of_CutSetFlag( pCutMin, k, 0 ); + + // the cut is selected + assert( pCutMin != NULL ); + pList = Of_ObjCutSet( p, i ); + Of_ObjSetCutBestP( p, pList, i, pCutMin ); ///// SET THE BEST CUT + Of_CutForEachVarFlag( pCutMin, iVar, Flag, k ) + { + Of_ObjUpdateRequired( p, iVar, Required - ((Flag && !fPointed) ? DelayLut2 : DelayLut1) ); + Of_ObjRefInc( p, iVar ); + if ( Flag && !fPointed ) + { + Vec_BitWriteEntry( vPointed, iVar, 1 ); + CountEdges++; + } + } + // update parameters + p->pPars->Edge += Of_CutSize(pCutMin); + p->pPars->Area++; + } + Vec_BitFree( vPointed ); + //printf( "Dircon nodes = %d. Dircon edges = %d.\n", CountNodes, CountEdges ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Of_ManCreateSat( Of_Man_t * p, int nCutsAll, Vec_Int_t * vFirst, Vec_Int_t * vCutNum, Vec_Int_t * vBestNode, Vec_Int_t * vBestCut ) +{ + extern void Cnf_AddCardinConstrPairWise( sat_solver * p, Vec_Int_t * vVars, int K, int fStrict ); + + Gia_Obj_t * pObj, * pVar; + int * pCutSet, * pCut; + int i, k, v, c, Var, Lit, pLits[2], status, RetValue, nCutCount, nClauses; + Vec_Int_t * vLits = Vec_IntAlloc( 100 ); + abctime clk = Abc_Clock(); + + // start solver + sat_solver * pSat = sat_solver_new(); + sat_solver_setnvars( pSat, Gia_ManAndNum(p->pGia) + nCutsAll ); + + // set polarity + Vec_IntAppend( vBestNode, vBestCut ); + //Vec_IntPrint( vBestNode ); + sat_solver_set_polarity( pSat, Vec_IntArray(vBestNode), Vec_IntSize(vBestNode) ); + Vec_IntShrink( vBestNode, Vec_IntSize(vBestNode) - Vec_IntSize(vBestCut) ); + + // add clauses for nodes + Gia_ManForEachAnd( p->pGia, pObj, i ) + { + int iFirst = Vec_IntEntry(vFirst, i); + int nCuts = Vec_IntEntry(vCutNum, i); + Vec_IntClear( vLits ); + Vec_IntPush( vLits, Abc_Var2Lit(pObj->Value, 1) ); + for ( c = 0; c < nCuts; c++ ) + Vec_IntPush( vLits, Abc_Var2Lit(iFirst + c, 0) ); + RetValue = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits) ); + assert( RetValue ); + } + + // add clauses for cuts + nCutCount = 0; + Gia_ManForEachAnd( p->pGia, pObj, i ) + { + pCutSet = Of_ObjCutSet(p, i); + Of_SetForEachCut( pCutSet, pCut, k ) + { + pLits[0] = Abc_Var2Lit( Gia_ManAndNum(p->pGia) + nCutCount, 1 ); + pLits[1] = Abc_Var2Lit( pObj->Value, 0 ); + RetValue = sat_solver_addclause( pSat, pLits, pLits+2 ); + assert( RetValue ); + Of_CutForEachVar( pCut, Var, v ) + { + pVar = Gia_ManObj(p->pGia, Var); + if ( !Gia_ObjIsAnd(pVar) ) + continue; + pLits[1] = Abc_Var2Lit( pVar->Value, 0 ); + RetValue = sat_solver_addclause( pSat, pLits, pLits+2 ); + assert( RetValue ); + } + nCutCount++; + } + } + assert( nCutCount == nCutsAll ); + + // mark CO drivers + Gia_ManForEachCo( p->pGia, pObj, i ) + Gia_ObjFanin0(pObj)->fMark0 = 1; + // set used nodes to 1 + Gia_ManForEachAnd( p->pGia, pObj, i ) + if ( pObj->fMark0 ) + { + Lit = Abc_Var2Lit( pObj->Value, 0 ); + RetValue = sat_solver_addclause( pSat, &Lit, &Lit + 1 ); + assert( RetValue ); + } + // unmark CO drivers + Gia_ManForEachCo( p->pGia, pObj, i ) + Gia_ObjFanin0(pObj)->fMark0 = 0; + +// Sat_SolverWriteDimacs( pSat, "temp.cnf", NULL, NULL, 0 ); + + // add cardinality constraint + nClauses = pSat->stats.clauses; + Vec_IntClear( vLits ); + Vec_IntFillNatural( vLits, Gia_ManAndNum(p->pGia) ); + Cnf_AddCardinConstrPairWise( pSat, vLits, Vec_IntSize(vBestNode)-2, 0 ); + printf( "Problem clauses = %d. Cardinality clauses = %d.\n", nClauses, pSat->stats.clauses - nClauses ); + + // solve the problem + status = sat_solver_solve( pSat, NULL, NULL, 1000000, 0, 0, 0 ); + if ( status == l_Undef ) + printf( "Undecided. " ); + if ( status == l_True ) + printf( "Satisfiable. " ); + if ( status == l_False ) + printf( "Unsatisfiable. " ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + Sat_SolverPrintStats( stdout, pSat ); + if ( status == l_True ) + { + int nOnes = 0; + for ( v = 0; v < Gia_ManAndNum(p->pGia); v++ ) + { + printf( "%d", sat_solver_var_value(pSat, v) ); + nOnes += sat_solver_var_value(pSat, v); + } + printf( " Nodes = %d\n", nOnes ); + + nOnes = 0; + for ( ; v < Gia_ManAndNum(p->pGia) + nCutsAll; v++ ) + { + printf( "%d", sat_solver_var_value(pSat, v) ); + nOnes += sat_solver_var_value(pSat, v); + } + printf( " LUTs = %d\n", nOnes ); + } + + // cleanup + sat_solver_delete( pSat ); + Vec_IntFree( vLits ); +} +void Of_ManPrintCuts( Of_Man_t * p ) +{ + int fVerbose = 0; + Gia_Obj_t * pObj; + int * pCutSet, * pCut, * pCutBest; + int i, k, v, Var, nCuts; + Vec_Int_t * vFirst = Vec_IntStartFull( Gia_ManObjNum(p->pGia) ); + Vec_Int_t * vCutNum = Vec_IntStartFull( Gia_ManObjNum(p->pGia) ); + Vec_Int_t * vBestNode = Vec_IntAlloc( 100 ); + Vec_Int_t * vBestCut = Vec_IntAlloc( 100 ); + int nAndsAll = 0, nCutsAll = 0, Shift = Gia_ManAndNum(p->pGia); + Gia_ManFillValue( p->pGia ); + Gia_ManForEachAnd( p->pGia, pObj, i ) + { + // get the best cut + pCutBest = NULL; + if ( Of_ObjRefNum(p, i) ) + { + Vec_IntPush( vBestNode, nAndsAll ); + pCutBest = Of_ObjCutBestP( p, i ); + } + pObj->Value = nAndsAll++; + // get the cutset + pCutSet = Of_ObjCutSet(p, i); + // count cuts + nCuts = 0; + Of_SetForEachCut( pCutSet, pCut, k ) + nCuts++; + // save + Vec_IntWriteEntry( vFirst, i, Shift + nCutsAll ); + Vec_IntWriteEntry( vCutNum, i, nCuts ); + // print cuts + if ( fVerbose ) + printf( "Node %d. Cuts %d.\n", i, nCuts ); + Of_SetForEachCut( pCutSet, pCut, k ) + { + if ( fVerbose ) + { + printf( "{ " ); + Of_CutForEachVar( pCut, Var, v ) + printf( "%d ", Var ); + printf( "} %s\n", pCutBest == pCut ? "best" :"" ); + } + if ( pCutBest == pCut ) + Vec_IntPush( vBestCut, Shift + nCutsAll ); + nCutsAll++; + } + } + assert( nAndsAll == Shift ); + printf( "Total: Ands = %d. Luts = %d. Cuts = %d.\n", nAndsAll, Vec_IntSize(vBestNode), nCutsAll ); + + // create SAT problem + Of_ManCreateSat( p, nCutsAll, vFirst, vCutNum, vBestNode, vBestCut ); + + Vec_IntFree( vFirst ); + Vec_IntFree( vCutNum ); + Vec_IntFree( vBestNode ); + Vec_IntFree( vBestCut ); +} + +/**Function************************************************************* + + Synopsis [Technology mappping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Of_ManSetDefaultPars( Jf_Par_t * pPars ) +{ + memset( pPars, 0, sizeof(Jf_Par_t) ); + pPars->nLutSize = 4; + pPars->nCutNum = 16; + pPars->nProcNum = 0; + pPars->nRounds = 3; + pPars->nRoundsEla = 4; + pPars->nRelaxRatio = 0; + pPars->nCoarseLimit = 3; + pPars->nAreaTuner = 10; + pPars->DelayTarget = -1; + pPars->nDelayLut1 = 10; + pPars->nDelayLut2 = 2; + pPars->nFastEdges = 0; // + pPars->fAreaOnly = 0; + pPars->fOptEdge = 1; + pPars->fCoarsen = 0; + pPars->fCutMin = 0; + pPars->fGenCnf = 0; + pPars->fPureAig = 0; + pPars->fVerbose = 0; + pPars->fVeryVerbose = 0; + pPars->nLutSizeMax = OF_LEAF_MAX; + pPars->nCutNumMax = OF_CUT_MAX; + pPars->MapDelayTarget = -1; +} +Gia_Man_t * Of_ManDeriveMapping( Of_Man_t * p ) +{ + Vec_Int_t * vMapping, * vPacking = NULL; + Vec_Bit_t * vPointed; + int i, k, iVar, * pCut, Place, Flag; + assert( !p->pPars->fCutMin && p->pGia->vMapping == NULL ); + vMapping = Vec_IntAlloc( Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + (int)p->pPars->Area * 2 ); + Vec_IntFill( vMapping, Gia_ManObjNum(p->pGia), 0 ); + if ( p->pPars->nFastEdges ) + { + vPacking = Vec_IntAlloc( 1000 ); + Vec_IntPush( vPacking, 0 ); + } + vPointed = Vec_BitStart( Gia_ManObjNum(p->pGia) ); + Gia_ManForEachAndId( p->pGia, i ) + { + if ( !Of_ObjRefNum(p, i) ) + continue; + assert( !Gia_ObjIsBuf(Gia_ManObj(p->pGia,i)) ); + pCut = Of_ObjCutBestP( p, i ); + Vec_IntWriteEntry( vMapping, i, Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, Of_CutSize(pCut) ); + Of_CutForEachVar( pCut, iVar, k ) + Vec_IntPush( vMapping, iVar ); + Vec_IntPush( vMapping, i ); + if ( vPacking == NULL || Vec_BitEntry(vPointed, i) ) + continue; + Place = Vec_IntSize( vPacking ); + Vec_IntPush( vPacking, 0 ); + Vec_IntPush( vPacking, i ); + Of_CutForEachVarFlag( pCut, iVar, Flag, k ) + if ( Flag ) + { + Vec_IntPush( vPacking, iVar ); + Vec_BitWriteEntry( vPointed, iVar, 1 ); + } + Vec_IntAddToEntry( vPacking, Place, Vec_IntSize(vPacking)-Place-1 ); + Vec_IntAddToEntry( vPacking, 0, 1 ); + } + assert( Vec_IntCap(vMapping) == 16 || Vec_IntSize(vMapping) == Vec_IntCap(vMapping) ); + p->pGia->vMapping = vMapping; + p->pGia->vPacking = vPacking; + Vec_BitFree( vPointed ); + return p->pGia; +} +Gia_Man_t * Of_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ) +{ + Gia_Man_t * pNew = NULL, * pCls; + Of_Man_t * p; int i, Id; + if ( Gia_ManHasChoices(pGia) ) + pPars->fCoarsen = 0, pPars->fCutMin = 1; + pCls = pPars->fCoarsen ? Gia_ManDupMuxes(pGia, pPars->nCoarseLimit) : pGia; + p = Of_StoCreate( pCls, pPars ); + if ( pPars->fVerbose && pPars->fCoarsen ) + { + printf( "Initial " ); Gia_ManPrintMuxStats( pGia ); printf( "\n" ); + printf( "Derived " ); Gia_ManPrintMuxStats( pCls ); printf( "\n" ); + } + Of_ManPrintInit( p ); + Of_ManComputeCuts( p ); + Of_ManPrintQuit( p ); + + Gia_ManForEachCiId( p->pGia, Id, i ) + { + int Time = Of_Flt2Int(p->pGia->vInArrs ? Abc_MaxFloat(0.0, Vec_FltEntry(p->pGia->vInArrs, i)) : 0.0); + Of_ObjSetDelay1( p, Id, Time ); + Of_ObjSetDelay2( p, Id, Time ); + } + + if ( p->pPars->nFastEdges ) + { + p->pPars->nRounds = 1; + for ( p->Iter = 0; p->Iter < p->pPars->nRounds; p->Iter++ ) + { + if ( p->Iter == 0 ) + { + Of_ManComputeForwardDircon1( p ); + Of_ManComputeBackwardDircon1( p ); + Of_ManPrintStats( p, "Delay" ); + } + else + { + Of_ManComputeForwardDircon1( p ); + Of_ManComputeBackwardDircon1( p ); + Of_ManPrintStats( p, "Flow " ); + } + } + } + else + { + for ( p->Iter = 0; p->Iter < p->pPars->nRounds; p->Iter++ ) + { + if ( p->Iter == 0 ) + { + Of_ManComputeForward1( p ); + Of_ManComputeBackward1( p ); + Of_ManPrintStats( p, "Delay" ); + } + else + { + Of_ManComputeForward1( p ); + Of_ManComputeBackward1( p ); + Of_ManPrintStats( p, "Flow " ); + } + } + for ( ; p->Iter < p->pPars->nRounds + p->pPars->nRoundsEla; p->Iter++ ) + { + if ( p->Iter < p->pPars->nRounds + p->pPars->nRoundsEla - 1 ) + { + Of_ManComputeForward2( p ); + Of_ManComputeBackward3( p ); + Of_ManPrintStats( p, "Area " ); + } + else + { + Of_ManComputeForward1( p ); + Of_ManComputeBackward3( p ); + Of_ManPrintStats( p, "Area " ); + } + } + } + + pNew = Of_ManDeriveMapping( p ); + Gia_ManMappingVerify( pNew ); + if ( pNew->vPacking ) + Gia_ManConvertPackingToEdges( pNew ); + //Of_ManPrintCuts( p ); + Of_StoDelete( p ); + if ( pCls != pGia ) + Gia_ManStop( pCls ); + if ( pNew == NULL ) + return Gia_ManDup( pGia ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaPack.c b/yosys/abc/src/aig/gia/giaPack.c new file mode 100644 index 00000000000..0cbf96d89e1 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaPack.c @@ -0,0 +1,207 @@ +/**CFile**************************************************************** + + FileName [giaPack.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [LUT packing.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaPack.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Collects LUT nodes in the increasing order of distance from COs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManLutCollect2( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + Vec_Int_t * vOrder; + int i, k, Id, iFan; + vOrder = Vec_IntAlloc( Gia_ManLutNum(p) ); + Gia_ManIncrementTravId( p ); + Gia_ManForEachCoDriver( p, pObj, i ) + { + if ( !Gia_ObjIsAnd(pObj) ) + continue; + Id = Gia_ObjId( p, pObj ); + assert( Gia_ObjIsLut(p, Id) ); + if ( Gia_ObjIsTravIdCurrentId(p, Id) ) + continue; + Gia_ObjSetTravIdCurrentId(p, Id); + Vec_IntPush( vOrder, Id ); + } + Vec_IntForEachEntry( vOrder, Id, i ) + { + Gia_LutForEachFanin( p, Id, iFan, k ) + { + if ( !Gia_ObjIsAnd(Gia_ManObj(p, iFan)) ) + continue; + assert( Gia_ObjIsLut(p, iFan) ); + if ( Gia_ObjIsTravIdCurrentId(p, iFan) ) + continue; + Gia_ObjSetTravIdCurrentId(p, iFan); + Vec_IntPush( vOrder, iFan ); + } + } + assert( Vec_IntCap(vOrder) == 16 || Vec_IntSize(vOrder) == Vec_IntCap(vOrder) ); + Vec_IntReverseOrder( vOrder ); + return vOrder; +} +Vec_Int_t * Gia_ManLutCollect( Gia_Man_t * p ) +{ + Vec_Int_t * vLuts, * vDist, * vOrder; + int i, k, Id, iFan, * pPerm; + // collect LUTs + vLuts = Vec_IntAlloc( Gia_ManAndNum(p) ); + Gia_ManForEachLut( p, Id ) + Vec_IntPush( vLuts, Id ); + // propagate distance + vDist = Vec_IntStart( Gia_ManObjNum(p) ); + Gia_ManForEachCoDriverId( p, Id, i ) + Vec_IntWriteEntry( vDist, Id, 1 ); + Vec_IntForEachEntryReverse( vLuts, Id, i ) + { + int Dist = 1 + Vec_IntEntry(vDist, Id); + Gia_LutForEachFanin( p, Id, iFan, k ) + Vec_IntUpdateEntry( vDist, iFan, Dist ); + } + // sort LUTs by distance + k = 0; + Vec_IntForEachEntry( vLuts, Id, i ) + Vec_IntWriteEntry( vDist, k++, -Vec_IntEntry(vDist, Id) ); + Vec_IntShrink( vDist, k ); + pPerm = Abc_MergeSortCost( Vec_IntArray(vDist), Vec_IntSize(vDist) ); + // collect + vOrder = Vec_IntAlloc( Vec_IntSize(vLuts) ); + for ( i = 0; i < Vec_IntSize(vLuts); i++ ) + Vec_IntPush( vOrder, Vec_IntEntry(vLuts, pPerm[i]) ); + Vec_IntFree( vDist ); + Vec_IntFree( vLuts ); + ABC_FREE( pPerm ); + return vOrder; +} + +/**Function************************************************************* + + Synopsis [LUT packing algorithm.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManLutPacking( Gia_Man_t * p, int nBlockSize, int DelayRoute, int DelayDir, int fVerbose ) +{ + int Delays[32], Perm[32]; + Vec_Int_t * vPacking, * vStarts; + Vec_Int_t * vOrder = Gia_ManLutCollect( p ); + Vec_Int_t * vDelay = Vec_IntStart( Gia_ManObjNum(p) ); + Vec_Int_t * vBlock = Vec_IntStart( Gia_ManObjNum(p) ); + Vec_Int_t * vBSize = Vec_IntAlloc( 2 * Vec_IntSize(vOrder) / nBlockSize ); + int i, k, Id, iFan, nSize, iBlock, Delay, DelayMax = 0; + // create blocks + Vec_IntForEachEntry( vOrder, Id, i ) + { + nSize = Gia_ObjLutSize( p, Id ); + assert( nSize <= 32 ); + Gia_LutForEachFanin( p, Id, iFan, k ) + { + Delays[k] = Vec_IntEntry(vDelay, iFan); + Perm[k] = iFan; + } + Vec_IntSelectSortCost2Reverse( Perm, nSize, Delays ); + assert( nSize < 2 || Delays[0] >= Delays[nSize-1] ); + assert( Delays[0] >= 0 && Delays[nSize-1] >= 0 ); + // check if we can reduce delay by adding it to the same bin as the latest one + iBlock = Vec_IntEntry( vBlock, Perm[0] ); + if ( Delays[0] > 0 && Delays[0] > Delays[1] && Vec_IntEntry(vBSize, iBlock) < nBlockSize ) + { + Delay = Delays[0] + DelayDir; + Vec_IntWriteEntry( vBlock, Id, iBlock ); + Vec_IntAddToEntry( vBSize, iBlock, 1 ); + } + else // clean new block + { + Delay = Delays[0] + DelayRoute; + Vec_IntWriteEntry( vBlock, Id, Vec_IntSize(vBSize) ); + Vec_IntPush( vBSize, 1 ); + } + // calculate delay + for ( k = 1; k < nSize; k++ ) + Delay = Abc_MaxInt( Delay, Delays[k] + DelayRoute ); + Vec_IntWriteEntry( vDelay, Id, Delay ); + DelayMax = Abc_MaxInt( DelayMax, Delay ); + } + assert( Vec_IntSum(vBSize) == Vec_IntSize(vOrder) ); + // create packing info + vPacking = Vec_IntAlloc( Vec_IntSize(vBSize) + Vec_IntSize(vOrder) + 1 ); + Vec_IntPush( vPacking, Vec_IntSize(vBSize) ); + // create starting places for each block + vStarts = Vec_IntAlloc( Vec_IntSize(vBSize) ); + Vec_IntForEachEntry( vBSize, nSize, i ) + { + Vec_IntPush( vPacking, nSize ); + Vec_IntPush( vStarts, Vec_IntSize(vPacking) ); + Vec_IntFillExtra( vPacking, Vec_IntSize(vPacking) + nSize, -1 ); + } + assert( Vec_IntCap(vPacking) == 16 || Vec_IntSize(vPacking) == Vec_IntCap(vPacking) ); + // collect LUTs from the block + Vec_IntForEachEntryReverse( vOrder, Id, i ) + { + int Block = Vec_IntEntry( vBlock, Id ); + int Start = Vec_IntEntry( vStarts, Block ); + assert( Vec_IntEntry(vPacking, Start) == -1 ); + Vec_IntWriteEntry( vPacking, Start, Id ); + Vec_IntAddToEntry( vStarts, Block, 1 ); + } + assert( Vec_IntCountEntry(vPacking, -1) == 0 ); + // cleanup + Vec_IntFree( vOrder ); + Vec_IntFree( vDelay ); + Vec_IntFree( vBlock ); + Vec_IntFree( vBSize ); + Vec_IntFree( vStarts ); + Vec_IntFreeP( &p->vPacking ); + p->vPacking = vPacking; + printf( "Global delay = %d.\n", DelayMax ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaPat.c b/yosys/abc/src/aig/gia/giaPat.c new file mode 100644 index 00000000000..124f5e0bb22 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaPat.c @@ -0,0 +1,135 @@ +/**CFile**************************************************************** + + FileName [gia.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Sat_ObjXValue( Gia_Obj_t * pObj ) { return (pObj->fMark1 << 1) | pObj->fMark0; } +static inline void Sat_ObjSetXValue( Gia_Obj_t * pObj, int v) { pObj->fMark0 = (v & 1); pObj->fMark1 = ((v >> 1) & 1); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Collects nodes in the cone and initialized them to x.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_SatCollectCone_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vVisit ) +{ + if ( Sat_ObjXValue(pObj) == GIA_UND ) + return; + if ( Gia_ObjIsAnd(pObj) ) + { + Gia_SatCollectCone_rec( p, Gia_ObjFanin0(pObj), vVisit ); + Gia_SatCollectCone_rec( p, Gia_ObjFanin1(pObj), vVisit ); + } + assert( Sat_ObjXValue(pObj) == 0 ); + Sat_ObjSetXValue( pObj, GIA_UND ); + Vec_IntPush( vVisit, Gia_ObjId(p, pObj) ); +} + +/**Function************************************************************* + + Synopsis [Collects nodes in the cone and initialized them to x.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_SatCollectCone( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vVisit ) +{ + assert( !Gia_IsComplement(pObj) ); + assert( !Gia_ObjIsConst0(pObj) ); + assert( Sat_ObjXValue(pObj) == 0 ); + Vec_IntClear( vVisit ); + Gia_SatCollectCone_rec( p, pObj, vVisit ); +} + +/**Function************************************************************* + + Synopsis [Checks if the counter-examples asserts the output.] + + Description [Assumes that fMark0 and fMark1 are clean. Leaves them clean.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_SatVerifyPattern( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vCex, Vec_Int_t * vVisit ) +{ + Gia_Obj_t * pObj; + int i, Entry, Value, Value0, Value1; + assert( Gia_ObjIsCo(pRoot) ); + assert( !Gia_ObjIsConst0(Gia_ObjFanin0(pRoot)) ); + // collect nodes and initialized them to x + Gia_SatCollectCone( p, Gia_ObjFanin0(pRoot), vVisit ); + // set binary values to nodes in the counter-example + Vec_IntForEachEntry( vCex, Entry, i ) +// Sat_ObjSetXValue( Gia_ManObj(p, Abc_Lit2Var(Entry)), Abc_LitIsCompl(Entry)? GIA_ZER : GIA_ONE ); + Sat_ObjSetXValue( Gia_ManCi(p, Abc_Lit2Var(Entry)), Abc_LitIsCompl(Entry)? GIA_ZER : GIA_ONE ); + // simulate + Gia_ManForEachObjVec( vVisit, p, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + continue; + assert( Gia_ObjIsAnd(pObj) ); + Value0 = Sat_ObjXValue( Gia_ObjFanin0(pObj) ); + Value1 = Sat_ObjXValue( Gia_ObjFanin1(pObj) ); + Value = Gia_XsimAndCond( Value0, Gia_ObjFaninC0(pObj), Value1, Gia_ObjFaninC1(pObj) ); + Sat_ObjSetXValue( pObj, Value ); + } + Value = Sat_ObjXValue( Gia_ObjFanin0(pRoot) ); + Value = Gia_XsimNotCond( Value, Gia_ObjFaninC0(pRoot) ); + if ( Value != GIA_ONE ) + printf( "Gia_SatVerifyPattern(): Verification FAILED.\n" ); +// else +// printf( "Gia_SatVerifyPattern(): Verification succeeded.\n" ); +// assert( Value == GIA_ONE ); + // clean the nodes + Gia_ManForEachObjVec( vVisit, p, pObj, i ) + Sat_ObjSetXValue( pObj, 0 ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaPat2.c b/yosys/abc/src/aig/gia/giaPat2.c new file mode 100644 index 00000000000..b0839f5d434 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaPat2.c @@ -0,0 +1,1506 @@ +/**CFile**************************************************************** + + FileName [giaPat2.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Pattern generation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaPat2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/vec/vecHsh.h" +#include "sat/cnf/cnf.h" +#include "sat/bsat/satStore.h" +#include "misc/util/utilTruth.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Min_Man_t_ Min_Man_t; +struct Min_Man_t_ +{ + int nCis; + int nCos; + int FirstAndLit; + int FirstCoLit; + Vec_Int_t vFans; + Vec_Str_t vValsN; + Vec_Str_t vValsL; + Vec_Int_t vVis; + Vec_Int_t vPat; +}; + +static inline int Min_ManCiNum( Min_Man_t * p ) { return p->nCis; } +static inline int Min_ManCoNum( Min_Man_t * p ) { return p->nCos; } +static inline int Min_ManObjNum( Min_Man_t * p ) { return Vec_IntSize(&p->vFans) >> 1; } +static inline int Min_ManAndNum( Min_Man_t * p ) { return Min_ManObjNum(p) - p->nCis - p->nCos - 1; } + +static inline int Min_ManCi( Min_Man_t * p, int i ) { return 1 + i; } +static inline int Min_ManCo( Min_Man_t * p, int i ) { return Min_ManObjNum(p) - Min_ManCoNum(p) + i; } + +static inline int Min_ObjIsCi( Min_Man_t * p, int i ) { return i > 0 && i <= Min_ManCiNum(p); } +static inline int Min_ObjIsNode( Min_Man_t * p, int i ) { return i > Min_ManCiNum(p) && i < Min_ManObjNum(p) - Min_ManCoNum(p); } +static inline int Min_ObjIsAnd( Min_Man_t * p, int i ) { return Min_ObjIsNode(p, i) && Vec_IntEntry(&p->vFans, 2*i) < Vec_IntEntry(&p->vFans, 2*i+1); } +static inline int Min_ObjIsXor( Min_Man_t * p, int i ) { return Min_ObjIsNode(p, i) && Vec_IntEntry(&p->vFans, 2*i) > Vec_IntEntry(&p->vFans, 2*i+1); } +static inline int Min_ObjIsBuf( Min_Man_t * p, int i ) { return Min_ObjIsNode(p, i) && Vec_IntEntry(&p->vFans, 2*i) ==Vec_IntEntry(&p->vFans, 2*i+1); } +static inline int Min_ObjIsCo( Min_Man_t * p, int i ) { return i >= Min_ManObjNum(p) - Min_ManCoNum(p) && i < Min_ManObjNum(p); } + +static inline int Min_ObjLit( Min_Man_t * p, int i, int n ) { return Vec_IntEntry(&p->vFans, i + i + n); } +static inline int Min_ObjLit0( Min_Man_t * p, int i ) { return Vec_IntEntry(&p->vFans, i + i + 0); } +static inline int Min_ObjLit1( Min_Man_t * p, int i ) { return Vec_IntEntry(&p->vFans, i + i + 1); } +static inline int Min_ObjCioId( Min_Man_t * p, int i ) { assert( i && !Min_ObjIsNode(p, i) ); return Min_ObjLit1(p, i); } + +static inline int Min_ObjFan0( Min_Man_t * p, int i ) { return Abc_Lit2Var( Min_ObjLit0(p, i) ); } +static inline int Min_ObjFan1( Min_Man_t * p, int i ) { return Abc_Lit2Var( Min_ObjLit1(p, i) ); } + +static inline int Min_ObjFanC0( Min_Man_t * p, int i ) { return Abc_LitIsCompl( Min_ObjLit0(p, i) ); } +static inline int Min_ObjFanC1( Min_Man_t * p, int i ) { return Abc_LitIsCompl( Min_ObjLit1(p, i) ); } + +static inline char Min_ObjValN( Min_Man_t * p, int i ) { return Vec_StrEntry(&p->vValsN, i); } +static inline void Min_ObjSetValN( Min_Man_t * p, int i, char v ){ Vec_StrWriteEntry(&p->vValsN, i, v); } + +static inline char Min_LitValL( Min_Man_t * p, int i ) { return Vec_StrEntry(&p->vValsL, i); } +static inline void Min_LitSetValL( Min_Man_t * p, int i, char v ){ assert(v==0 || v==1); Vec_StrWriteEntry(&p->vValsL, i, v); Vec_StrWriteEntry(&p->vValsL, i^1, (char)!v); Vec_IntPush(&p->vVis, Abc_Lit2Var(i)); } +static inline void Min_ObjCleanValL( Min_Man_t * p, int i ) { ((short *)Vec_StrArray(&p->vValsL))[i] = 0x0202; } +static inline void Min_ObjMarkValL( Min_Man_t * p, int i ) { ((short *)Vec_StrArray(&p->vValsL))[i] |= 0x0404; } +static inline void Min_ObjMark2ValL( Min_Man_t * p, int i ) { ((short *)Vec_StrArray(&p->vValsL))[i] |= 0x0808; } +static inline void Min_ObjUnmark2ValL( Min_Man_t * p, int i ) { ((short *)Vec_StrArray(&p->vValsL))[i] &= 0xF7F7; } + +static inline int Min_LitIsCi( Min_Man_t * p, int v ) { return v > 1 && v < p->FirstAndLit; } +static inline int Min_LitIsNode( Min_Man_t * p, int v ) { return v >= p->FirstAndLit && v < p->FirstCoLit; } +static inline int Min_LitIsCo( Min_Man_t * p, int v ) { return v >= p->FirstCoLit; } + +static inline int Min_LitIsAnd( int v, int v0, int v1 ) { return Abc_LitIsCompl(v) ^ (v0 < v1); } +static inline int Min_LitIsXor( int v, int v0, int v1 ) { return Abc_LitIsCompl(v) ^ (v0 > v1); } +static inline int Min_LitIsBuf( int v, int v0, int v1 ) { return v0 == v1; } + +static inline int Min_LitFan( Min_Man_t * p, int v ) { return Vec_IntEntry(&p->vFans, v); } +static inline int Min_LitFanC( Min_Man_t * p, int v ) { return Abc_LitIsCompl( Min_LitFan(p, v) ); } + +static inline void Min_ManStartValsN( Min_Man_t * p ) { Vec_StrGrow(&p->vValsN, Vec_IntCap(&p->vFans)/2); Vec_StrFill(&p->vValsN, Min_ManObjNum(p), 2); } +static inline void Min_ManStartValsL( Min_Man_t * p ) { Vec_StrGrow(&p->vValsL, Vec_IntCap(&p->vFans)); Vec_StrFill(&p->vValsL, Vec_IntSize(&p->vFans), 2); } +static inline int Min_ManCheckCleanValsL( Min_Man_t * p ) { int i; char c; Vec_StrForEachEntry( &p->vValsL, c, i ) if ( c != 2 ) return 0; return 1; } +static inline void Min_ManCleanVisitedValL( Min_Man_t * p ) { int i, iObj; Vec_IntForEachEntry(&p->vVis, iObj, i) Min_ObjCleanValL(p, iObj); Vec_IntClear(&p->vVis); } + + +#define Min_ManForEachObj( p, i ) \ + for ( i = 0; i < Min_ManObjNum(p); i++ ) +#define Min_ManForEachCi( p, i ) \ + for ( i = 1; i <= Min_ManCiNum(p); i++ ) +#define Min_ManForEachCo( p, i ) \ + for ( i = Min_ManObjNum(p) - Min_ManCoNum(p); i < Min_ManObjNum(p); i++ ) +#define Min_ManForEachAnd( p, i ) \ + for ( i = 1 + Min_ManCiNum(p); i < Min_ManObjNum(p) - Min_ManCoNum(p); i++ ) + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Min_Man_t * Min_ManStart( int nObjMax ) +{ + Min_Man_t * p = ABC_CALLOC( Min_Man_t, 1 ); + Vec_IntGrow( &p->vFans, nObjMax ); + Vec_IntPushTwo( &p->vFans, -1, -1 ); + return p; +} +static inline void Min_ManStop( Min_Man_t * p ) +{ + Vec_IntErase( &p->vFans ); + Vec_StrErase( &p->vValsN ); + Vec_StrErase( &p->vValsL ); + Vec_IntErase( &p->vVis ); + Vec_IntErase( &p->vPat ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Min_ManAppendObj( Min_Man_t * p, int iLit0, int iLit1 ) +{ + int iLit = Vec_IntSize(&p->vFans); + Vec_IntPushTwo( &p->vFans, iLit0, iLit1 ); + return iLit; +} +static inline int Min_ManAppendCi( Min_Man_t * p ) +{ + p->nCis++; + p->FirstAndLit = Vec_IntSize(&p->vFans) + 2; + return Min_ManAppendObj( p, 0, p->nCis-1 ); +} +static inline int Min_ManAppendCo( Min_Man_t * p, int iLit0 ) +{ + p->nCos++; + if ( p->FirstCoLit == 0 ) + p->FirstCoLit = Vec_IntSize(&p->vFans); + return Min_ManAppendObj( p, iLit0, p->nCos-1 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Min_ManFromGia_rec( Min_Man_t * pNew, Gia_Man_t * p, int iObj ) +{ + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); int iLit0, iLit1; + if ( ~pObj->Value ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Min_ManFromGia_rec( pNew, p, Gia_ObjFaninId0(pObj, iObj) ); + Min_ManFromGia_rec( pNew, p, Gia_ObjFaninId1(pObj, iObj) ); + iLit0 = Gia_ObjFanin0Copy(pObj); + iLit1 = Gia_ObjFanin1Copy(pObj); + pObj->Value = Min_ManAppendObj( pNew, Abc_MinInt(iLit0, iLit1), Abc_MaxInt(iLit0, iLit1) ); +} +Min_Man_t * Min_ManFromGia( Gia_Man_t * p, Vec_Int_t * vOuts ) +{ + Gia_Obj_t * pObj; int i; + Min_Man_t * pNew = Min_ManStart( Gia_ManObjNum(p) ); + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Min_ManAppendCi( pNew ); + if ( vOuts == NULL ) + { + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Min_ManAppendObj( pNew, Gia_ObjFaninLit0(pObj, i), Gia_ObjFaninLit1(pObj, i) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Min_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + else + { + Gia_ManForEachCoVec( vOuts, p, pObj, i ) + Min_ManFromGia_rec( pNew, p, Gia_ObjFaninId0p(p, pObj) ); + Gia_ManForEachCoVec( vOuts, p, pObj, i ) + Min_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + return pNew; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline char Min_XsimNot( char Val ) +{ + if ( Val < 2 ) + return Val ^ 1; + return 2; +} +static inline char Min_XsimXor( char Val0, char Val1 ) +{ + if ( Val0 < 2 && Val1 < 2 ) + return Val0 ^ Val1; + return 2; +} +static inline char Min_XsimAnd( char Val0, char Val1 ) +{ + if ( Val0 == 0 || Val1 == 0 ) + return 0; + if ( Val0 == 1 && Val1 == 1 ) + return 1; + return 2; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char Min_LitVerify_rec( Min_Man_t * p, int iLit ) +{ + char Val = Min_LitValL(p, iLit); + if ( Val == 2 && Min_LitIsNode(p, iLit) ) // unassigned + { + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitVerify_rec( p, iLit0 ); + char Val1 = Min_LitVerify_rec( p, iLit1 ); + assert( Val0 < 3 && Val1 < 3 ); + if ( Min_LitIsXor(iLit, iLit0, iLit1) ) + Val = Min_XsimXor( Val0, Val1 ); + else + Val = Min_XsimAnd( Val0, Val1 ); + if ( Val < 2 ) + { + Val ^= Abc_LitIsCompl(iLit); + Min_LitSetValL( p, iLit, Val ); + } + else + Vec_IntPush( &p->vVis, Abc_Lit2Var(iLit) ); + Min_ObjMark2ValL( p, Abc_Lit2Var(iLit) ); + } + return Val&3; +} +char Min_LitVerify( Min_Man_t * p, int iLit, Vec_Int_t * vLits ) +{ + int i, Entry; char Res; + if ( iLit < 2 ) return 1; + assert( !Min_LitIsCo(p, iLit) ); + //assert( Min_ManCheckCleanValsL(p) ); + assert( Vec_IntSize(&p->vVis) == 0 ); + Vec_IntForEachEntry( vLits, Entry, i ) + Min_LitSetValL( p, Entry, 1 ); // ms notation + Res = Min_LitVerify_rec( p, iLit ); + Min_ManCleanVisitedValL( p ); + return Res; +} + +void Min_LitMinimize( Min_Man_t * p, int iLit, Vec_Int_t * vLits ) +{ + int i, iObj, iTemp; char Res; + Vec_IntClear( &p->vPat ); + if ( iLit < 2 ) return; + assert( !Min_LitIsCo(p, iLit) ); + //assert( Min_ManCheckCleanValsL(p) ); + assert( Vec_IntSize(&p->vVis) == 0 ); + Vec_IntForEachEntry( vLits, iTemp, i ) + Min_LitSetValL( p, iTemp, 1 ); // ms notation + Res = Min_LitVerify_rec( p, iLit ); + assert( Res == 1 ); + Min_ObjMarkValL( p, Abc_Lit2Var(iLit) ); + Vec_IntForEachEntryReverse( &p->vVis, iObj, i ) + { + int iLit = Abc_Var2Lit( iObj, 0 ); + int Value = 7 & Min_LitValL(p, iLit); + if ( Value >= 4 ) + { + if ( Min_LitIsCi(p, iLit) ) + Vec_IntPush( &p->vPat, Abc_LitNotCond(iLit, !(Value&1)) ); + else + { + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitValL( p, iLit0 ); + char Val1 = Min_LitValL( p, iLit1 ); + if ( Value&1 ) // value == 1 + { + assert( (Val0&1) && (Val1&1) ); + Min_ObjMarkValL( p, Abc_Lit2Var(iLit0) ); + Min_ObjMarkValL( p, Abc_Lit2Var(iLit1) ); + } + else // value == 0 + { + int Zero0 = !(Val0&3); + int Zero1 = !(Val1&3); + assert( Zero0 || Zero1 ); + if ( Zero0 && !Zero1 ) + Min_ObjMarkValL( p, Abc_Lit2Var(iLit0) ); + else if ( !Zero0 && Zero1 ) + Min_ObjMarkValL( p, Abc_Lit2Var(iLit1) ); + else if ( Val0 == 4 && Val1 != 4 ) + Min_ObjMarkValL( p, Abc_Lit2Var(iLit0) ); + else if ( Val1 == 4 && Val0 != 4 ) + Min_ObjMarkValL( p, Abc_Lit2Var(iLit1) ); + else if ( Abc_Random(0) & 1 ) + Min_ObjMarkValL( p, Abc_Lit2Var(iLit0) ); + else + Min_ObjMarkValL( p, Abc_Lit2Var(iLit1) ); + } + } + } + Min_ObjCleanValL( p, Abc_Lit2Var(iLit) ); + } + Vec_IntClear( &p->vVis ); + //Min_ManCleanVisitedValL( p ); + //assert( Min_LitVerify(p, iLit, &p->vPat) == 1 ); + assert( Vec_IntSize(&p->vPat) <= Vec_IntSize(vLits) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline char Min_LitIsImplied1( Min_Man_t * p, int iLit ) +{ + char Val = 2; + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitValL(p, iLit0); + char Val1 = Min_LitValL(p, iLit1); + assert( Min_LitIsNode(p, iLit) ); // internal node + assert( Min_LitValL(p, iLit) == 2 ); // unassigned + if ( Min_LitIsXor(iLit, iLit0, iLit1) ) + Val = Min_XsimXor( Val0, Val1 ); + else + Val = Min_XsimAnd( Val0, Val1 ); + if ( Val < 2 ) + { + Val ^= Abc_LitIsCompl(iLit); + Min_LitSetValL( p, iLit, Val ); + } + return Val; +} +static inline char Min_LitIsImplied2( Min_Man_t * p, int iLit ) +{ + char Val = 2; + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitValL(p, iLit0); + char Val1 = Min_LitValL(p, iLit1); + assert( Min_LitIsNode(p, iLit) ); // internal node + assert( Min_LitValL(p, iLit) == 2 ); // unassigned + if ( Val0 == 2 && Min_LitIsNode(p, iLit0) ) { + Val0 = Min_LitIsImplied1(p, iLit0); + Val1 = Min_LitValL(p, iLit1); + } + if ( Val1 == 2 && Min_LitIsNode(p, iLit1) ) + Val1 = Min_LitIsImplied1(p, iLit1); + if ( Min_LitIsXor(iLit, iLit0, iLit1) ) + Val = Min_XsimXor( Val0, Val1 ); + else + Val = Min_XsimAnd( Val0, Val1 ); + if ( Val < 2 ) + { + Val ^= Abc_LitIsCompl(iLit); + Min_LitSetValL( p, iLit, Val ); + } + return Val; +} +static inline char Min_LitIsImplied3( Min_Man_t * p, int iLit ) +{ + char Val = 2; + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitValL(p, iLit0); + char Val1 = Min_LitValL(p, iLit1); + assert( Min_LitIsNode(p, iLit) ); // internal node + assert( Min_LitValL(p, iLit) == 2 ); // unassigned + if ( Val0 == 2 && Min_LitIsNode(p, iLit0) ) { + Val0 = Min_LitIsImplied2(p, iLit0); + Val1 = Min_LitValL(p, iLit1); + } + if ( Val1 == 2 && Min_LitIsNode(p, iLit1) ) + Val1 = Min_LitIsImplied2(p, iLit1); + if ( Min_LitIsXor(iLit, iLit0, iLit1) ) + Val = Min_XsimXor( Val0, Val1 ); + else + Val = Min_XsimAnd( Val0, Val1 ); + if ( Val < 2 ) + { + Val ^= Abc_LitIsCompl(iLit); + Min_LitSetValL( p, iLit, Val ); + } + return Val; +} +static inline char Min_LitIsImplied4( Min_Man_t * p, int iLit ) +{ + char Val = 2; + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitValL(p, iLit0); + char Val1 = Min_LitValL(p, iLit1); + assert( Min_LitIsNode(p, iLit) ); // internal node + assert( Min_LitValL(p, iLit) == 2 ); // unassigned + if ( Val0 == 2 && Min_LitIsNode(p, iLit0) ) { + Val0 = Min_LitIsImplied3(p, iLit0); + Val1 = Min_LitValL(p, iLit1); + } + if ( Val1 == 2 && Min_LitIsNode(p, iLit1) ) + Val1 = Min_LitIsImplied3(p, iLit1); + if ( Min_LitIsXor(iLit, iLit0, iLit1) ) + Val = Min_XsimXor( Val0, Val1 ); + else + Val = Min_XsimAnd( Val0, Val1 ); + if ( Val < 2 ) + { + Val ^= Abc_LitIsCompl(iLit); + Min_LitSetValL( p, iLit, Val ); + } + return Val; +} +static inline char Min_LitIsImplied5( Min_Man_t * p, int iLit ) +{ + char Val = 2; + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitValL(p, iLit0); + char Val1 = Min_LitValL(p, iLit1); + assert( Min_LitIsNode(p, iLit) ); // internal node + assert( Min_LitValL(p, iLit) == 2 ); // unassigned + if ( Val0 == 2 && Min_LitIsNode(p, iLit0) ) { + Val0 = Min_LitIsImplied4(p, iLit0); + Val1 = Min_LitValL(p, iLit1); + } + if ( Val1 == 2 && Min_LitIsNode(p, iLit1) ) + Val1 = Min_LitIsImplied4(p, iLit1); + if ( Min_LitIsXor(iLit, iLit0, iLit1) ) + Val = Min_XsimXor( Val0, Val1 ); + else + Val = Min_XsimAnd( Val0, Val1 ); + if ( Val < 2 ) + { + Val ^= Abc_LitIsCompl(iLit); + Min_LitSetValL( p, iLit, Val ); + } + return Val; +} + +// this recursive procedure is about 10% slower +char Min_LitIsImplied_rec( Min_Man_t * p, int iLit, int Depth ) +{ + char Val = 2; + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitValL(p, iLit0); + char Val1 = Min_LitValL(p, iLit1); + assert( Depth > 0 ); + assert( Min_LitIsNode(p, iLit) ); // internal node + assert( Min_LitValL(p, iLit) == 2 ); // unassigned + if ( Depth > 1 && Val0 == 2 && Min_LitIsNode(p, iLit0) ) + { + Val0 = Min_LitIsImplied_rec(p, iLit0, Depth-1); + Val1 = Min_LitValL(p, iLit1); + } + if ( Depth > 1 && Val1 == 2 && Min_LitIsNode(p, iLit1) ) + { + Val1 = Min_LitIsImplied_rec(p, iLit1, Depth-1); + Val0 = Min_LitValL(p, iLit0); + } + if ( Min_LitIsXor(iLit, iLit0, iLit1) ) + Val = Min_XsimXor( Val0, Val1 ); + else + Val = Min_XsimAnd( Val0, Val1 ); + if ( Val < 2 ) + { + Val ^= Abc_LitIsCompl(iLit); + Min_LitSetValL( p, iLit, Val ); + } + return Val; +} +int Min_LitJustify_rec( Min_Man_t * p, int iLit ) +{ + int Res = 1, LitValue = !Abc_LitIsCompl(iLit); + int Val = (int)Min_LitValL(p, iLit); + if ( Val < 2 ) // assigned + return Val == LitValue; + // unassigned + if ( Min_LitIsCi(p, iLit) ) + Vec_IntPush( &p->vPat, iLit ); // ms notation + else + { + int iLit0 = Min_LitFan(p, iLit); + int iLit1 = Min_LitFan(p, iLit^1); + char Val0 = Min_LitValL(p, iLit0); + char Val1 = Min_LitValL(p, iLit1); + if ( Min_LitIsXor(iLit, iLit0, iLit1) ) + { + if ( Val0 < 2 && Val1 < 2 ) + Res = LitValue == (Val0 ^ Val1); + else if ( Val0 < 2 ) + Res = Min_LitJustify_rec(p, iLit1^Val0^!LitValue); + else if ( Val1 < 2 ) + Res = Min_LitJustify_rec(p, iLit0^Val1^!LitValue); + else if ( Abc_Random(0) & 1 ) + Res = Min_LitJustify_rec(p, iLit0) && Min_LitJustify_rec(p, iLit1^ LitValue); + else + Res = Min_LitJustify_rec(p, iLit0^1) && Min_LitJustify_rec(p, iLit1^!LitValue); + assert( !Res || LitValue == Min_XsimXor(Min_LitValL(p, iLit0), Min_LitValL(p, iLit1)) ); + } + else if ( LitValue ) // value 1 + { + if ( Val0 == 0 || Val1 == 0 ) + Res = 0; + else if ( Val0 == 1 && Val1 == 1 ) + Res = 1; + else if ( Val0 == 1 ) + Res = Min_LitJustify_rec(p, iLit1); + else if ( Val1 == 1 ) + Res = Min_LitJustify_rec(p, iLit0); + else + Res = Min_LitJustify_rec(p, iLit0) && Min_LitJustify_rec(p, iLit1); + assert( !Res || 1 == Min_XsimAnd(Min_LitValL(p, iLit0), Min_LitValL(p, iLit1)) ); + } + else // value 0 + { +/* + int Depth = 3; + if ( Val0 == 2 && Min_LitIsNode(p, iLit0) ) + { + Val0 = Min_LitIsImplied_rec(p, iLit0, Depth); + Val1 = Min_LitValL(p, iLit1); + } + if ( Val1 == 2 && Min_LitIsNode(p, iLit1) ) + { + Val1 = Min_LitIsImplied_rec(p, iLit1, Depth); + Val0 = Min_LitValL(p, iLit0); + } +*/ + if ( Val0 == 2 && Min_LitIsNode(p, iLit0) ) + { + Val0 = Min_LitIsImplied3(p, iLit0); + Val1 = Min_LitValL(p, iLit1); + } + if ( Val1 == 2 && Min_LitIsNode(p, iLit1) ) + { + Val1 = Min_LitIsImplied3(p, iLit1); + Val0 = Min_LitValL(p, iLit0); + } + if ( Val0 == 0 || Val1 == 0 ) + Res = 1; + else if ( Val0 == 1 && Val1 == 1 ) + Res = 0; + else if ( Val0 == 1 ) + Res = Min_LitJustify_rec(p, iLit1^1); + else if ( Val1 == 1 ) + Res = Min_LitJustify_rec(p, iLit0^1); + else if ( Abc_Random(0) & 1 ) + //else if ( (p->Random >> (iLit & 0x1F)) & 1 ) + Res = Min_LitJustify_rec(p, iLit0^1); + else + Res = Min_LitJustify_rec(p, iLit1^1); + //Val0 = Min_LitValL(p, iLit0); + //Val1 = Min_LitValL(p, iLit1); + assert( !Res || 0 == Min_XsimAnd(Min_LitValL(p, iLit0), Min_LitValL(p, iLit1)) ); + } + } + if ( Res ) + Min_LitSetValL( p, iLit, 1 ); + return Res; +} +int Min_LitJustify( Min_Man_t * p, int iLit ) +{ + int Res, fCheck = 0; + Vec_IntClear( &p->vPat ); + if ( iLit < 2 ) return 1; + assert( !Min_LitIsCo(p, iLit) ); + //assert( Min_ManCheckCleanValsL(p) ); + assert( Vec_IntSize(&p->vVis) == 0 ); + //p->Random = Abc_Random(0); + Res = Min_LitJustify_rec( p, iLit ); + Min_ManCleanVisitedValL( p ); + if ( Res ) + { + if ( fCheck && Min_LitVerify(p, iLit, &p->vPat) != 1 ) + printf( "Verification FAILED for literal %d.\n", iLit ); + //else + // printf( "Verification succeeded for literal %d.\n", iLit ); + } + //else + // printf( "Could not justify literal %d.\n", iLit ); + return Res; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Min_TargGenerateCexes( Min_Man_t * p, Vec_Int_t * vCoErrs, int nCexes, int nCexesStop, int * pnComputed, int fVerbose ) +{ + abctime clk = Abc_Clock(); + int t, iObj, Count = 0, CountPos = 0, CountPosSat = 0, nRuns[2] = {0}, nCountCexes[2] = {0}; + Vec_Int_t * vPats = Vec_IntAlloc( 1000 ); + Vec_Int_t * vPatBest = Vec_IntAlloc( Min_ManCiNum(p) ); + Hsh_VecMan_t * pHash = Hsh_VecManStart( 10000 ); + Min_ManForEachCo( p, iObj ) if ( Min_ObjLit0(p, iObj) > 1 ) + { + int nCexesGenSim0 = 0; + int nCexesGenSim = 0; + int nCexesGenSat = 0; + if ( vCoErrs && Vec_IntEntry(vCoErrs, Min_ObjCioId(p, iObj)) >= nCexesStop ) + continue; + //printf( "%d ", i ); + for ( t = 0; t < nCexes; t++ ) + { + nRuns[0]++; + if ( Min_LitJustify( p, Min_ObjLit0(p, iObj) ) ) + { + int Before, After; + assert( Vec_IntSize(&p->vPat) > 0 ); + //printf( "%d ", Vec_IntSize(vPat) ); + Vec_IntClear( vPatBest ); + if ( 1 ) // no minimization + Vec_IntAppend( vPatBest, &p->vPat ); + else + { +/* + for ( k = 0; k < 10; k++ ) + { + Vec_IntClear( vPat2 ); + Gia_ManIncrementTravId( p ); + Cexes_MinimizePattern_rec( p, Gia_ObjFanin0(pObj), !Gia_ObjFaninC0(pObj), vPat2 ); + assert( Vec_IntSize(vPat2) <= Vec_IntSize(vPat) ); + if ( Vec_IntSize(vPatBest) == 0 || Vec_IntSize(vPatBest) > Vec_IntSize(vPat2) ) + { + Vec_IntClear( vPatBest ); + Vec_IntAppend( vPatBest, vPat2 ); + } + //printf( "%d ", Vec_IntSize(vPat2) ); + } +*/ + } + + //Gia_CexVerify( p, Gia_ObjFaninId0p(p, pObj), !Gia_ObjFaninC0(pObj), vPatBest ); + //printf( "\n" ); + Before = Hsh_VecSize( pHash ); + Vec_IntSort( vPatBest, 0 ); + Hsh_VecManAdd( pHash, vPatBest ); + After = Hsh_VecSize( pHash ); + if ( Before != After ) + { + Vec_IntPush( vPats, Min_ObjCioId(p, iObj) ); + Vec_IntPush( vPats, Vec_IntSize(vPatBest) ); + Vec_IntAppend( vPats, vPatBest ); + nCexesGenSim++; + } + nCexesGenSim0++; + if ( nCexesGenSim0 > nCexesGenSim*10 ) + { + printf( "**** Skipping output %d (out of %d)\n", Min_ObjCioId(p, iObj), Min_ManCoNum(p) ); + break; + } + } + if ( nCexesGenSim == nCexesStop ) + break; + } + //printf( "(%d %d) ", nCexesGenSim0, nCexesGenSim ); + //printf( "%d ", t/nCexesGenSim ); + + //printf( "The number of CEXes = %d\n", nCexesGen ); + //if ( fVerbose ) + // printf( "%d ", nCexesGen ); + nCountCexes[0] += nCexesGenSim; + nCountCexes[1] += nCexesGenSat; + Count += nCexesGenSim + nCexesGenSat; + CountPos++; + + if ( nCexesGenSim0 == 0 && t == nCexes ) + printf( "#### Output %d (out of %d)\n", Min_ObjCioId(p, iObj), Min_ManCoNum(p) ); + } + //printf( "\n" ); + if ( fVerbose ) + printf( "\n" ); + if ( fVerbose ) + printf( "Got %d unique CEXes using %d sim (%d) and %d SAT (%d) runs (ave size %.1f). PO = %d ErrPO = %d SatPO = %d ", + Count, nRuns[0], nCountCexes[0], nRuns[1], nCountCexes[1], + 1.0*Vec_IntSize(vPats)/Abc_MaxInt(1, Count)-2, Min_ManCoNum(p), CountPos, CountPosSat ); + if ( fVerbose ) + Abc_PrintTime( 0, "Time", Abc_Clock() - clk ); + Hsh_VecManStop( pHash ); + Vec_IntFree( vPatBest ); + *pnComputed = Count; + return vPats; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Min_ManTest3( Gia_Man_t * p, Vec_Int_t * vCoErrs ) +{ + int fXor = 0; + int nComputed; + Vec_Int_t * vPats; + Gia_Man_t * pXor = fXor ? Gia_ManDupMuxes(p, 1) : NULL; + Min_Man_t * pNew = Min_ManFromGia( fXor ? pXor : p, NULL ); + Gia_ManStopP( &pXor ); + Min_ManStartValsL( pNew ); + //Vec_IntFill( vCoErrs, Vec_IntSize(vCoErrs), 0 ); + //vPats = Min_TargGenerateCexes( pNew, vCoErrs, 10000, 10, &nComputed, 1 ); + vPats = Min_TargGenerateCexes( pNew, vCoErrs, 10000, 10, &nComputed, 1 ); + Vec_IntFree( vPats ); + Min_ManStop( pNew ); +} +void Min_ManTest4( Gia_Man_t * p ) +{ + Vec_Int_t * vCoErrs = Vec_IntStartNatural( Gia_ManCoNum(p) ); + Min_ManTest3(p, vCoErrs); + Vec_IntFree( vCoErrs ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDupCones2CollectPis_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vMap ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjUpdateTravIdCurrentId(p, iObj) ) + return; + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ManDupCones2CollectPis_rec( p, Gia_ObjFaninId0(pObj, iObj), vMap ); + Gia_ManDupCones2CollectPis_rec( p, Gia_ObjFaninId1(pObj, iObj), vMap ); + } + else if ( Gia_ObjIsCi(pObj) ) + Vec_IntPush( vMap, iObj ); + else assert( 0 ); +} +void Gia_ManDupCones2_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( Gia_ObjIsCi(pObj) || Gia_ObjUpdateTravIdCurrent(p, pObj) ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManDupCones2_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManDupCones2_rec( pNew, p, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManDupCones2( Gia_Man_t * p, int * pOuts, int nOuts, Vec_Int_t * vMap ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; int i; + Vec_IntClear( vMap ); + Gia_ManIncrementTravId( p ); + for ( i = 0; i < nOuts; i++ ) + Gia_ManDupCones2CollectPis_rec( p, Gia_ManCoDriverId(p, pOuts[i]), vMap ); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObjVec( vMap, p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManIncrementTravId( p ); + for ( i = 0; i < nOuts; i++ ) + Gia_ManDupCones2_rec( pNew, p, Gia_ObjFanin0(Gia_ManCo(p, pOuts[i])) ); + for ( i = 0; i < nOuts; i++ ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManCo(p, pOuts[i])) ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Min_ManRemoveItem( Vec_Wec_t * vCexes, int iItem, int iFirst, int iLimit ) +{ + Vec_Int_t * vLevel = NULL, * vLevel0 = Vec_WecEntry(vCexes, iItem); int i; + assert( iFirst <= iItem && iItem < iLimit ); + Vec_WecForEachLevelReverseStartStop( vCexes, vLevel, i, iLimit, iFirst ) + if ( Vec_IntSize(vLevel) > 0 ) + break; + assert( iFirst <= i && iItem <= i ); + Vec_IntClear( vLevel0 ); + if ( iItem < i ) + ABC_SWAP( Vec_Int_t, *vLevel0, *vLevel ); + return -1; +} +int Min_ManAccumulate( Vec_Wec_t * vCexes, int iFirst, int iLimit, Vec_Int_t * vCex ) +{ + Vec_Int_t * vLevel; int i, nCommon, nDiff = 0; + Vec_WecForEachLevelStartStop( vCexes, vLevel, i, iFirst, iLimit ) + { + if ( Vec_IntSize(vLevel) == 0 ) + { + Vec_IntAppend(vLevel, vCex); + return nDiff+1; + } + nCommon = Vec_IntTwoCountCommon( vLevel, vCex ); + if ( nCommon == Vec_IntSize(vLevel) ) // ignore vCex + return nDiff; + if ( nCommon == Vec_IntSize(vCex) ) // remove vLevel + nDiff += Min_ManRemoveItem( vCexes, i, iFirst, iLimit ); + } + assert( 0 ); + return ABC_INFINITY; +} +int Min_ManCountSize( Vec_Wec_t * vCexes, int iFirst, int iLimit ) +{ + Vec_Int_t * vLevel; int i, nTotal = 0; + Vec_WecForEachLevelStartStop( vCexes, vLevel, i, iFirst, iLimit ) + nTotal += Vec_IntSize(vLevel) > 0; + return nTotal; +} +Vec_Wec_t * Min_ManComputeCexes( Gia_Man_t * p, Vec_Int_t * vOuts0, int nMaxTries, int nMinCexes, Vec_Int_t * vStats[3], int fUseSim, int fUseSat, int fVerbose ) +{ + int fUseSynthesis = 1; + abctime clkSim = Abc_Clock(), clkSat = Abc_Clock(); + Vec_Int_t * vOuts = vOuts0 ? vOuts0 : Vec_IntStartNatural( Gia_ManCoNum(p) ); + Min_Man_t * pNew = Min_ManFromGia( p, vOuts ); + Vec_Wec_t * vCexes = Vec_WecStart( Vec_IntSize(vOuts) * nMinCexes ); + Vec_Int_t * vPatBest = Vec_IntAlloc( 100 ); + Vec_Int_t * vLits = Vec_IntAlloc( 100 ); + Gia_Obj_t * pObj; int i, iObj, nOuts = 0, nSimOuts = 0, nSatOuts = 0; + vStats[0] = Vec_IntAlloc( Vec_IntSize(vOuts) ); // total calls + vStats[1] = Vec_IntAlloc( Vec_IntSize(vOuts) ); // successful calls + SAT runs + vStats[2] = Vec_IntAlloc( Vec_IntSize(vOuts) ); // results + Min_ManStartValsL( pNew ); + Min_ManForEachCo( pNew, iObj ) + { + int nAllCalls = 0; + int nGoodCalls = 0; + int nCurrCexes = 0; + if ( fUseSim && Min_ObjLit0(pNew, iObj) >= 2 ) + { + while ( nAllCalls++ < nMaxTries ) + { + if ( Min_LitJustify( pNew, Min_ObjLit0(pNew, iObj) ) ) + { + Vec_IntClearAppend( vLits, &pNew->vPat ); + Vec_IntClearAppend( vPatBest, &pNew->vPat ); + if ( 1 ) // minimization + { + //printf( "%d -> ", Vec_IntSize(vPatBest) ); + for ( i = 0; i < 20; i++ ) + { + Min_LitMinimize( pNew, Min_ObjLit0(pNew, iObj), vLits ); + if ( Vec_IntSize(vPatBest) > Vec_IntSize(&pNew->vPat) ) + Vec_IntClearAppend( vPatBest, &pNew->vPat ); + } + //printf( "%d ", Vec_IntSize(vPatBest) ); + } + assert( Vec_IntSize(vPatBest) > 0 ); + Vec_IntSort( vPatBest, 0 ); + nCurrCexes += Min_ManAccumulate( vCexes, nOuts*nMinCexes, (nOuts+1)*nMinCexes, vPatBest ); + nGoodCalls++; + } + if ( nCurrCexes == nMinCexes || nGoodCalls > 10*nCurrCexes ) + break; + } + nSimOuts++; + } + assert( nCurrCexes <= nMinCexes ); + assert( nCurrCexes == Min_ManCountSize(vCexes, nOuts*nMinCexes, (nOuts+1)*nMinCexes) ); + Vec_IntPush( vStats[0], nAllCalls ); + Vec_IntPush( vStats[1], nGoodCalls ); + Vec_IntPush( vStats[2], nCurrCexes ); + nOuts++; + } + assert( Vec_IntSize(vOuts) == nOuts ); + assert( Vec_IntSize(vOuts) == Vec_IntSize(vStats[0]) ); + assert( Vec_IntSize(vOuts) == Vec_IntSize(vStats[1]) ); + assert( Vec_IntSize(vOuts) == Vec_IntSize(vStats[2]) ); + clkSim = Abc_Clock() - clkSim; + + if ( fUseSat ) + Gia_ManForEachCoVec( vOuts, p, pObj, i ) + { + if ( Vec_IntEntry(vStats[2], i) >= nMinCexes || Vec_IntEntry(vStats[1], i) > 10*Vec_IntEntry(vStats[2], i) ) + continue; + { + assert( Gia_ObjIsCo(pObj) ); + if ( Gia_ObjFaninId0p(p, pObj) == 0 ) { + if ( fVerbose ) + printf( "Output %d is driven by constant %d.\n", Gia_ObjCioId(pObj), Gia_ObjFaninC0(pObj) ); + continue; + } + abctime clk = Abc_Clock(); + int iObj = Min_ManCo(pNew, i); + int Index = Gia_ObjCioId(pObj); + Vec_Int_t * vMap = Vec_IntAlloc( 100 ); + Gia_Man_t * pCon = Gia_ManDupCones2( p, &Index, 1, vMap ); + Gia_Man_t * pCon1= fUseSynthesis ? Gia_ManAigSyn2( pCon, 0, 1, 0, 100, 0, 0, 0 ) : NULL; + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( fUseSynthesis ? pCon1 : pCon, 8, 0, 0, 0, 0 ); + sat_solver* pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + int Lit = Abc_Var2Lit( 1, 0 ); + int status = sat_solver_addclause( pSat, &Lit, &Lit+1 ); + int nAllCalls = 0; + int nCurrCexes = Vec_IntEntry(vStats[2], i); + //Gia_AigerWrite( pCon, "temp_miter.aig", 0, 0, 0 ); + if ( status == l_True ) + { + nSatOuts++; + //printf( "Running SAT for output %d\n", i ); + if ( Min_ObjLit0(pNew, iObj) >= 2 ) + { + while ( nAllCalls++ < 100 ) + { + int v, iVar = pCnf->nVars - Gia_ManPiNum(pCon), nVars = Gia_ManPiNum(pCon); + if ( nAllCalls > 1 ) + sat_solver_randomize( pSat, iVar, nVars ); + status = sat_solver_solve( pSat, NULL, NULL, 0, 0, 0, 0 ); + if ( status != l_True ) + break; + assert( status == l_True ); + Vec_IntClear( vLits ); + for ( v = 0; v < nVars; v++ ) + Vec_IntPush( vLits, Abc_Var2Lit(Vec_IntEntry(vMap, v), !sat_solver_var_value(pSat, iVar + v)) ); + Min_LitMinimize( pNew, Min_ObjLit0(pNew, iObj), vLits ); + Vec_IntClearAppend( vPatBest, &pNew->vPat ); + if ( 1 ) // minimization + { + //printf( "%d -> ", Vec_IntSize(vPatBest) ); + for ( v = 0; v < 20; v++ ) + { + Min_LitMinimize( pNew, Min_ObjLit0(pNew, iObj), vLits ); + if ( Vec_IntSize(vPatBest) > Vec_IntSize(&pNew->vPat) ) + Vec_IntClearAppend( vPatBest, &pNew->vPat ); + } + //printf( "%d ", Vec_IntSize(vPatBest) ); + } + Vec_IntSort( vPatBest, 0 ); + nCurrCexes += Min_ManAccumulate( vCexes, i*nMinCexes, (i+1)*nMinCexes, vPatBest ); + if ( nCurrCexes == nMinCexes || nAllCalls > 10*nCurrCexes ) + break; + } + } + } + Vec_IntWriteEntry( vStats[0], i, nAllCalls*nMaxTries ); + Vec_IntWriteEntry( vStats[1], i, nAllCalls*nMaxTries ); + Vec_IntWriteEntry( vStats[2], i, nCurrCexes ); + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + Gia_ManStop( pCon ); + Gia_ManStopP( &pCon1 ); + Vec_IntFree( vMap ); + if ( fVerbose ) + { + printf( "SAT solving for output %3d (cexes = %5d) : ", i, nCurrCexes ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + } + } + clkSat = Abc_Clock() - clkSat - clkSim; + if ( fVerbose ) + printf( "Used simulation for %d and SAT for %d outputs (out of %d).\n", nSimOuts, nSatOuts, nOuts ); + if ( fVerbose ) + Abc_PrintTime( 1, "Simulation time ", clkSim ); + if ( fVerbose ) + Abc_PrintTime( 1, "SAT solving time ", clkSat ); + //Vec_WecPrint( vCexes, 0 ); + if ( vOuts != vOuts0 ) + Vec_IntFreeP( &vOuts ); + Min_ManStop( pNew ); + Vec_IntFree( vPatBest ); + Vec_IntFree( vLits ); + return vCexes; +} + +/**Function************************************************************* + + Synopsis [Bit-packing for selected patterns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Min_ManBitPackTry( Vec_Wrd_t * vSimsPi, int nWords, int iPat, Vec_Int_t * vLits ) +{ + int i, Lit; + assert( iPat >= 0 && iPat < 64 * nWords ); + Vec_IntForEachEntry( vLits, Lit, i ) + { + word * pInfo = Vec_WrdEntryP( vSimsPi, nWords * Abc_Lit2Var(Lit-2) ); // Lit is based on ObjId + word * pCare = pInfo + Vec_WrdSize(vSimsPi); + if ( Abc_InfoHasBit( (unsigned *)pCare, iPat ) && + Abc_InfoHasBit( (unsigned *)pInfo, iPat ) == Abc_LitIsCompl(Lit) ) // Lit is in ms notation + return 0; + } + Vec_IntForEachEntry( vLits, Lit, i ) + { + word * pInfo = Vec_WrdEntryP( vSimsPi, nWords * Abc_Lit2Var(Lit-2) ); // Lit is based on ObjId + word * pCare = pInfo + Vec_WrdSize(vSimsPi); + Abc_InfoSetBit( (unsigned *)pCare, iPat ); + if ( Abc_InfoHasBit( (unsigned *)pInfo, iPat ) == Abc_LitIsCompl(Lit) ) // Lit is in ms notation + Abc_InfoXorBit( (unsigned *)pInfo, iPat ); + } + return 1; +} +int Min_ManBitPackOne( Vec_Wrd_t * vSimsPi, int iPat0, int nWords, Vec_Int_t * vLits ) +{ + int iPat, nTotal = 64*nWords; + for ( iPat = iPat0 + 1; iPat != iPat0; iPat = (iPat + 1) % nTotal ) + if ( Min_ManBitPackTry( vSimsPi, nWords, iPat, vLits ) ) + break; + return iPat; +} +Vec_Ptr_t * Min_ReloadCexes( Vec_Wec_t * vCexes, int nMinCexes ) +{ + Vec_Ptr_t * vRes = Vec_PtrAlloc( Vec_WecSize(vCexes) ); + int i, c, nOuts = Vec_WecSize(vCexes)/nMinCexes; + for ( i = 0; i < nMinCexes; i++ ) + for ( c = 0; c < nOuts; c++ ) + { + Vec_Int_t * vLevel = Vec_WecEntry( vCexes, c*nMinCexes+i ); + if ( Vec_IntSize(vLevel) ) + Vec_PtrPush( vRes, vLevel ); + } + return vRes; +} + +Vec_Wrd_t * Min_ManBitPack( Gia_Man_t * p, int nWords0, Vec_Wec_t * vCexes, int fRandom, int nMinCexes, Vec_Int_t * vScores, int fVerbose ) +{ + abctime clk = Abc_Clock(); + //int fVeryVerbose = 0; + Vec_Wrd_t * vSimsPi = NULL; + Vec_Int_t * vLevel; + int w, nBits, nTotal = 0, fFailed = ABC_INFINITY; + Vec_Int_t * vOrder = NULL; + Vec_Ptr_t * vReload = NULL; + if ( 0 ) + { + vOrder = Vec_IntStartNatural( Vec_WecSize(vCexes)/nMinCexes ); + assert( Vec_IntSize(vOrder) == Vec_IntSize(vScores) ); + assert( Vec_WecSize(vCexes)%nMinCexes == 0 ); + Abc_MergeSortCost2Reverse( Vec_IntArray(vOrder), Vec_IntSize(vOrder), Vec_IntArray(vScores) ); + } + else + vReload = Min_ReloadCexes( vCexes, nMinCexes ); + if ( fVerbose ) + printf( "Packing: " ); + for ( w = nWords0 ? nWords0 : 1; nWords0 ? w <= nWords0 : fFailed > 0; w++ ) + { + int i, iPatUsed, iPat = 0; + //int k, iOut; + Vec_WrdFreeP( &vSimsPi ); + vSimsPi = fRandom ? Vec_WrdStartRandom(2 * Gia_ManCiNum(p) * w) : Vec_WrdStart(2 * Gia_ManCiNum(p) * w); + Vec_WrdShrink( vSimsPi, Vec_WrdSize(vSimsPi)/2 ); + Abc_TtClear( Vec_WrdLimit(vSimsPi), Vec_WrdSize(vSimsPi) ); + fFailed = nTotal = 0; + //Vec_IntForEachEntry( vOrder, iOut, k ) + //Vec_WecForEachLevelStartStop( vCexes, vLevel, i, iOut*nMinCexes, (iOut+1)*nMinCexes ) + Vec_PtrForEachEntry( Vec_Int_t *, vReload, vLevel, i ) + { + //if ( fVeryVerbose && i%nMinCexes == 0 ) + // printf( "\n" ); + if ( Vec_IntSize(vLevel) == 0 ) + continue; + iPatUsed = Min_ManBitPackOne( vSimsPi, iPat, w, vLevel ); + fFailed += iPatUsed == iPat; + iPat = (iPatUsed + 1) % (64*(w-1) - 1); + //if ( fVeryVerbose ) + //printf( "Adding output %3d cex %3d to pattern %3d ", i/nMinCexes, i%nMinCexes, iPatUsed ); + //if ( fVeryVerbose ) + //Vec_IntPrint( vLevel ); + nTotal++; + } + if ( fVerbose ) + printf( "W = %d (F = %d) ", w, fFailed ); +// printf( "Failed patterns = %d\n", fFailed ); + } + if ( fVerbose ) + printf( "Total = %d\n", nTotal ); + if ( fVerbose ) + { + nBits = Abc_TtCountOnesVec( Vec_WrdLimit(vSimsPi), Vec_WrdSize(vSimsPi) ); + printf( "Bit-packing is using %d words and %d bits. Density =%8.4f %%. ", + Vec_WrdSize(vSimsPi)/Gia_ManCiNum(p), nBits, 100.0*nBits/64/Vec_WrdSize(vSimsPi) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + Vec_IntFreeP( &vOrder ); + Vec_PtrFreeP( &vReload ); + return vSimsPi; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Patt_ManOutputErrorCoverage( Vec_Wrd_t * vErrors, int nOuts ) +{ + Vec_Int_t * vCounts = Vec_IntAlloc( nOuts ); + int i, nWords = Vec_WrdSize(vErrors)/nOuts; + assert( Vec_WrdSize(vErrors) == nOuts * nWords ); + for ( i = 0; i < nOuts; i++ ) + Vec_IntPush( vCounts, Abc_TtCountOnesVec(Vec_WrdEntryP(vErrors, nWords * i), nWords) ); + return vCounts; +} +Vec_Wrd_t * Patt_ManTransposeErrors( Vec_Wrd_t * vErrors, int nOuts ) +{ + extern void Extra_BitMatrixTransposeP( Vec_Wrd_t * vSimsIn, int nWordsIn, Vec_Wrd_t * vSimsOut, int nWordsOut ); + int nWordsIn = Vec_WrdSize(vErrors) / nOuts; + int nWordsOut = Abc_Bit6WordNum(nOuts); + Vec_Wrd_t * vSims1 = Vec_WrdStart( 64*nWordsIn*nWordsOut ); + Vec_Wrd_t * vSims2 = Vec_WrdStart( 64*nWordsIn*nWordsOut ); + assert( Vec_WrdSize(vErrors) == nWordsIn * nOuts ); + Abc_TtCopy( Vec_WrdArray(vSims1), Vec_WrdArray(vErrors), Vec_WrdSize(vErrors), 0 ); + Extra_BitMatrixTransposeP( vSims1, nWordsIn, vSims2, nWordsOut ); + Vec_WrdFree( vSims1 ); + return vSims2; +} +Vec_Int_t * Patt_ManPatternErrorCoverage( Vec_Wrd_t * vErrors, int nOuts ) +{ + int nWords = Vec_WrdSize(vErrors)/nOuts; + Vec_Wrd_t * vErrors2 = Patt_ManTransposeErrors( vErrors, nOuts ); + Vec_Int_t * vPatErrs = Patt_ManOutputErrorCoverage( vErrors2, 64*nWords ); + Vec_WrdFree( vErrors2 ); + return vPatErrs; +} + +#define ERR_REPT_SIZE 32 +void Patt_ManProfileErrors( Vec_Int_t * vOutErrs, Vec_Int_t * vPatErrs ) +{ + int nOuts = Vec_IntSize(vOutErrs); + int nPats = Vec_IntSize(vPatErrs); + int ErrOuts[ERR_REPT_SIZE+1] = {0}; + int ErrPats[ERR_REPT_SIZE+1] = {0}; + int i, Errs, nErrors1 = 0, nErrors2 = 0; + Vec_IntForEachEntry( vOutErrs, Errs, i ) + { + nErrors1 += Errs; + ErrOuts[Errs < ERR_REPT_SIZE ? Errs : ERR_REPT_SIZE]++; + } + Vec_IntForEachEntry( vPatErrs, Errs, i ) + { + nErrors2 += Errs; + ErrPats[Errs < ERR_REPT_SIZE ? Errs : ERR_REPT_SIZE]++; + } + assert( nErrors1 == nErrors2 ); + // errors/error_outputs/error_patterns + //printf( "\nError statistics:\n" ); + printf( "Errors =%6d ", nErrors1 ); + printf( "ErrPOs =%5d (Ave = %5.2f) ", nOuts-ErrOuts[0], 1.0*nErrors1/Abc_MaxInt(1, nOuts-ErrOuts[0]) ); + printf( "Patterns =%5d (Ave = %5.2f) ", nPats, 1.0*nErrors1/nPats ); + printf( "Density =%8.4f %%\n", 100.0*nErrors1/nPats/Abc_MaxInt(1, nOuts-ErrOuts[0]) ); + // how many times each output fails + printf( "Outputs: " ); + for ( i = 0; i <= ERR_REPT_SIZE; i++ ) + if ( ErrOuts[i] ) + printf( "%s%d=%d ", i == ERR_REPT_SIZE? ">" : "", i, ErrOuts[i] ); + printf( "\n" ); + // how many times each patterns fails an output + printf( "Patterns: " ); + for ( i = 0; i <= ERR_REPT_SIZE; i++ ) + if ( ErrPats[i] ) + printf( "%s%d=%d ", i == ERR_REPT_SIZE? ">" : "", i, ErrPats[i] ); + printf( "\n" ); +} +int Patt_ManProfileErrorsOne( Vec_Wrd_t * vErrors, int nOuts ) +{ + Vec_Int_t * vCoErrs = Patt_ManOutputErrorCoverage( vErrors, nOuts ); + Vec_Int_t * vPatErrs = Patt_ManPatternErrorCoverage( vErrors, nOuts ); + Patt_ManProfileErrors( vCoErrs, vPatErrs ); + Vec_IntFree( vPatErrs ); + Vec_IntFree( vCoErrs ); + return 1; +} + +Vec_Int_t * Min_ManGetUnsolved( Gia_Man_t * p ) +{ + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); + int i, Driver; + Gia_ManForEachCoDriverId( p, Driver, i ) + if ( Driver > 0 ) + Vec_IntPush( vRes, i ); + if ( Vec_IntSize(vRes) == 0 ) + Vec_IntFreeP( &vRes ); + return vRes; +} +Vec_Wrd_t * Min_ManRemapSims( int nInputs, Vec_Int_t * vMap, Vec_Wrd_t * vSimsPi ) +{ + int i, iObj, nWords = Vec_WrdSize(vSimsPi)/Vec_IntSize(vMap); + Vec_Wrd_t * vSimsNew = Vec_WrdStart( 2 * nInputs * nWords ); + //Vec_Wrd_t * vSimsNew = Vec_WrdStartRandom( nInputs * nWords ); + //Vec_WrdFillExtra( vSimsNew, 2 * nInputs * nWords, 0 ); + assert( Vec_WrdSize(vSimsPi)%Vec_IntSize(vMap) == 0 ); + Vec_WrdShrink( vSimsNew, Vec_WrdSize(vSimsNew)/2 ); + Vec_IntForEachEntry( vMap, iObj, i ) + { + Abc_TtCopy( Vec_WrdArray(vSimsNew) + (iObj-1)*nWords, Vec_WrdArray(vSimsPi) + i*nWords, nWords, 0 ); + Abc_TtCopy( Vec_WrdLimit(vSimsNew) + (iObj-1)*nWords, Vec_WrdLimit(vSimsPi) + i*nWords, nWords, 0 ); + } + return vSimsNew; +} +Vec_Wrd_t * Gia_ManCollectSims( Gia_Man_t * pSwp, int nWords, Vec_Int_t * vOuts, int nMaxTries, int nMinCexes, int fUseSim, int fUseSat, int fVerbose, int fVeryVerbose ) +{ + Vec_Int_t * vStats[3] = {0}; int i, iObj; + Vec_Int_t * vMap = Vec_IntAlloc( 100 ); + Gia_Man_t * pSwp2 = Gia_ManDupCones2( pSwp, Vec_IntArray(vOuts), Vec_IntSize(vOuts), vMap ); + Vec_Wec_t * vCexes = Min_ManComputeCexes( pSwp2, NULL, nMaxTries, nMinCexes, vStats, fUseSim, fUseSat, fVerbose ); + if ( Vec_IntSum(vStats[2]) == 0 ) + { + for ( i = 0; i < 3; i++ ) + Vec_IntFree( vStats[i] ); + Vec_IntFree( vMap ); + Gia_ManStop( pSwp2 ); + Vec_WecFree( vCexes ); + return NULL; + } + else + { + Vec_Wrd_t * vSimsPi = Min_ManBitPack( pSwp2, nWords, vCexes, 1, nMinCexes, vStats[0], fVerbose ); + Vec_Wrd_t * vSimsPo = Gia_ManSimPatSimOut( pSwp2, vSimsPi, 1 ); + Vec_Int_t * vCounts = Patt_ManOutputErrorCoverage( vSimsPo, Vec_IntSize(vOuts) ); + if ( fVerbose ) + Patt_ManProfileErrorsOne( vSimsPo, Vec_IntSize(vOuts) ); + if ( fVeryVerbose ) + { + printf( "Unsolved = %4d ", Vec_IntSize(vOuts) ); + Gia_ManPrintStats( pSwp2, NULL ); + Vec_IntForEachEntry( vOuts, iObj, i ) + { + printf( "%4d : ", i ); + printf( "Out = %5d ", Vec_IntEntry(vMap, i) ); + printf( "SimAll =%8d ", Vec_IntEntry(vStats[0], i) ); + printf( "SimGood =%8d ", Vec_IntEntry(vStats[1], i) ); + printf( "PatsAll =%8d ", Vec_IntEntry(vStats[2], i) ); + printf( "Count = %5d ", Vec_IntEntry(vCounts, i) ); + printf( "\n" ); + if ( i == 20 ) + break; + } + } + for ( i = 0; i < 3; i++ ) + Vec_IntFree( vStats[i] ); + Vec_IntFree( vCounts ); + Vec_WrdFree( vSimsPo ); + Vec_WecFree( vCexes ); + Gia_ManStop( pSwp2 ); + //printf( "Compressing inputs: %5d -> %5d\n", Gia_ManCiNum(pSwp), Vec_IntSize(vMap) ); + vSimsPi = Min_ManRemapSims( Gia_ManCiNum(pSwp), vMap, vSimsPo = vSimsPi ); + Vec_WrdFree( vSimsPo ); + Vec_IntFree( vMap ); + return vSimsPi; + } +} +Vec_Wrd_t * Min_ManCollect( Gia_Man_t * p, int nConf, int nConf2, int nMaxTries, int nMinCexes, int fUseSim, int fUseSat, int fVerbose, int fVeryVerbose ) +{ + abctime clk = Abc_Clock(); + extern Gia_Man_t * Cec4_ManSimulateTest4( Gia_Man_t * p, int nBTLimit, int nBTLimitPo, int fVerbose ); + Gia_Man_t * pSwp = Cec4_ManSimulateTest4( p, nConf, nConf2, 0 ); + abctime clkSweep = Abc_Clock() - clk; + int nArgs = fVerbose ? printf( "Generating patterns: Conf = %d (%d). Tries = %d. Pats = %d. Sim = %d. SAT = %d.\n", + nConf, nConf2, nMaxTries, nMinCexes, fUseSim, fUseSat ) : 0; + Vec_Int_t * vOuts = Min_ManGetUnsolved( pSwp ); + Vec_Wrd_t * vSimsPi = vOuts ? Gia_ManCollectSims( pSwp, 0, vOuts, nMaxTries, nMinCexes, fUseSim, fUseSat, fVerbose, fVeryVerbose ) : NULL; + if ( vOuts == NULL ) + printf( "There is no satisfiable outputs.\n" ); + if ( fVerbose ) + Abc_PrintTime( 1, "Sweep time", clkSweep ); + if ( fVerbose ) + Abc_PrintTime( 1, "Total time", Abc_Clock() - clk ); + Vec_IntFreeP( &vOuts ); + Gia_ManStop( pSwp ); + nArgs = 0; + return vSimsPi; +} +void Min_ManTest2( Gia_Man_t * p ) +{ + Vec_Wrd_t * vSimsPi = Min_ManCollect( p, 100000, 100000, 10000, 20, 1, 0, 1, 1 ); + Vec_WrdFreeP( &vSimsPi ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_GenerateCexesDumpBlif( char * pFileName, Gia_Man_t * p, Vec_Wec_t * vCexes ) +{ + extern Vec_Ptr_t * Gia_GetFakeNames( int nNames, int fCaps ); + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) { + printf( "Cannot open output file name \"%s\".\n", pFileName ); + return; + } + int fFakeIns = 0, fFakeOuts = 0; + if ( p->vNamesIn == NULL ) + p->vNamesIn = Gia_GetFakeNames( Gia_ManCiNum(p), 0 ), fFakeIns = 1; + if ( p->vNamesOut == NULL ) + p->vNamesOut = Gia_GetFakeNames( Gia_ManCoNum(p), 1 ), fFakeOuts = 1; + + Gia_Obj_t * pObj, * pObj2; + char * pLine = ABC_CALLOC( char, Gia_ManCiNum(p)+3 ); + int i, k, c, iLit, nOuts[2] = {0}, nCexes = Vec_WecSize(vCexes) / Gia_ManCoNum(p); + fprintf( pFile, "# Satisfying assignments for the primary outputs generated by ABC on %s\n", Gia_TimeStamp() ); + fprintf( pFile, ".model %s\n", p->pName ); + fprintf( pFile, ".inputs" ); + Gia_ManForEachCi( p, pObj, i ) + fprintf( pFile, " %s", Gia_ObjCiName(p, i) ); + fprintf( pFile, "\n.outputs" ); + Gia_ManForEachCo( p, pObj, i ) + fprintf( pFile, " %s", Gia_ObjCoName(p, i) ); + fprintf( pFile, "\n" ); + Gia_ManForEachCo( p, pObj, i ) { + if ( Gia_ObjFaninLit0p(p, pObj) == 0 ) { + fprintf( pFile, ".names %s\n", Gia_ObjCoName(p, i) ); + nOuts[0]++; + } + else if ( Gia_ObjFaninLit0p(p, pObj) == 1 ) { + fprintf( pFile, ".names %s\n 1\n", Gia_ObjCiName(p, i) ); + nOuts[1]++; + } + else { + fprintf( pFile, ".names" ); + Gia_ManForEachCi( p, pObj2, c ) + fprintf( pFile, " %s", Gia_ObjCiName(p, c) ); + fprintf( pFile, " %s\n", Gia_ObjCoName(p, i) ); + for ( c = 0; c < nCexes; c++ ) { + Vec_Int_t * vPat = Vec_WecEntry( vCexes, i*nCexes+c ); + memset(pLine, '-', Gia_ManCiNum(p) ); + Vec_IntForEachEntry( vPat, iLit, k ) + pLine[Abc_Lit2Var(iLit)-1] = '1' - Abc_LitIsCompl(iLit); + fprintf( pFile, "%s 1\n", pLine ); + } + nOuts[1]++; + } + } + fprintf( pFile, ".end\n\n" ); + fclose( pFile ); + printf( "Information about %d sat, %d unsat, and %d undecided primary outputs was written into BLIF file \"%s\".\n", + nOuts[1], nOuts[0], Gia_ManCoNum(p)-nOuts[1]-nOuts[0], pFileName ); + free( pLine ); + + if ( fFakeIns ) Vec_PtrFreeFree( p->vNamesIn ), p->vNamesIn = NULL; + if ( fFakeOuts ) Vec_PtrFreeFree( p->vNamesOut ), p->vNamesOut = NULL; +} +void Gia_GenerateCexesDumpFile( char * pFileName, Gia_Man_t * p, Vec_Wec_t * vCexes, int fShort ) +{ + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) { + printf( "Cannot open output file name \"%s\".\n", pFileName ); + return; + } + Gia_Obj_t * pObj; + char * pLine = ABC_CALLOC( char, Gia_ManCiNum(p)+3 ); + int i, k, c, iLit, nOuts[2] = {0}, nCexes = Vec_WecSize(vCexes) / Gia_ManCoNum(p); + Gia_ManForEachCo( p, pObj, i ) { + if ( Gia_ObjFaninLit0p(p, Gia_ManCo(p, i)) == 0 ) { + fprintf( pFile, "%d : unsat\n", i ); + nOuts[0]++; + } + else if ( fShort ) { + for ( c = 0; c < nCexes; c++ ) { + Vec_Int_t * vPat = Vec_WecEntry( vCexes, i*nCexes+c ); + fprintf( pFile, "%d :", i ); + if ( Vec_IntSize(vPat) == 0 ) + fprintf( pFile, " not available" ); + else + Vec_IntForEachEntry( vPat, iLit, k ) + fprintf( pFile, " %d", iLit ); + fprintf( pFile, "\n" ); + } + nOuts[1]++; + } + else { + for ( c = 0; c < nCexes; c++ ) { + Vec_Int_t * vPat = Vec_WecEntry( vCexes, i*nCexes+c ); + memset(pLine, '-', Gia_ManCiNum(p) ); + Vec_IntForEachEntry( vPat, iLit, k ) + pLine[Abc_Lit2Var(iLit)-1] = '1' - Abc_LitIsCompl(iLit); + fprintf( pFile, "%d : %s\n", i, pLine ); + } + nOuts[1]++; + } + } + printf( "Information about %d sat, %d unsat, and %d undecided primary outputs was written into file \"%s\".\n", + nOuts[1], nOuts[0], Gia_ManCoNum(p)-nOuts[1]-nOuts[0], pFileName ); + fclose( pFile ); + free( pLine ); +} +void Gia_GenerateCexes( char * pFileName, Gia_Man_t * p, int nMaxTries, int nMinCexes, int fUseSim, int fUseSat, int fShort, int fBlif, int fVerbose, int fVeryVerbose ) +{ + unsigned Start = Abc_Random(1); + Vec_Int_t * vStats[3] = {0}; int i; + Vec_Wec_t * vCexes = Min_ManComputeCexes( p, NULL, nMaxTries, nMinCexes, vStats, fUseSim, fUseSat, fVerbose ); + assert( Vec_WecSize(vCexes) == Gia_ManCoNum(p) * nMinCexes ); + if ( fBlif ) + Gia_GenerateCexesDumpBlif( pFileName, p, vCexes ); + else + Gia_GenerateCexesDumpFile( pFileName, p, vCexes, fShort ); + for ( i = 0; i < 3; i++ ) + Vec_IntFreeP( &vStats[i] ); + Vec_WecFree( vCexes ); + Start = 0; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaPf.c b/yosys/abc/src/aig/gia/giaPf.c new file mode 100644 index 00000000000..c453dc56af9 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaPf.c @@ -0,0 +1,1354 @@ +/**CFile**************************************************************** + + FileName [giaNf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Standard-cell mapper.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaNf.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include "gia.h" +#include "misc/st/st.h" +#include "map/mio/mio.h" +#include "misc/util/utilTruth.h" +#include "misc/extra/extra.h" +#include "base/main/main.h" +#include "misc/vec/vecMem.h" +#include "misc/vec/vecWec.h" +#include "opt/dau/dau.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define PF_LEAF_MAX 6 +#define PF_CUT_MAX 32 +#define PF_NO_LEAF 31 +#define PF_NO_FUNC 0x3FFFFFF +#define PF_INFINITY FLT_MAX + +typedef struct Pf_Cut_t_ Pf_Cut_t; +struct Pf_Cut_t_ +{ + word Sign; // signature + int Delay; // delay + float Flow; // flow + unsigned iFunc : 26; // function (PF_NO_FUNC) + unsigned Useless : 1; // function + unsigned nLeaves : 5; // leaf number (PF_NO_LEAF) + int pLeaves[PF_LEAF_MAX+1]; // leaves +}; +typedef struct Pf_Mat_t_ Pf_Mat_t; +struct Pf_Mat_t_ +{ + unsigned fCompl : 8; // complemented + unsigned Phase : 6; // match phase + unsigned Perm : 18; // match permutation +}; +typedef struct Pf_Obj_t_ Pf_Obj_t; +struct Pf_Obj_t_ +{ + float Area; + unsigned Gate : 7; // gate + unsigned nLeaves : 3; // fanin count + unsigned nRefs : 22; // ref count + int pLeaves[6]; // leaf literals +}; +typedef struct Pf_Man_t_ Pf_Man_t; +struct Pf_Man_t_ +{ + // user data + Gia_Man_t * pGia; // derived manager + Jf_Par_t * pPars; // parameters + // matching + Vec_Mem_t * vTtMem; // truth tables + Vec_Wec_t * vTt2Match; // matches for truth tables + Mio_Cell_t * pCells; // library gates + int nCells; // library gate count + // cut data + Pf_Obj_t * pPfObjs; // best cuts + Vec_Ptr_t vPages; // cut memory + Vec_Int_t vCutSets; // cut offsets + Vec_Flt_t vCutFlows; // temporary cut area + Vec_Int_t vCutDelays; // temporary cut delay + int iCur; // current position + int Iter; // mapping iterations + int fUseEla; // use exact area + int nInvs; // the inverter count + float InvDelay; // inverter delay + float InvArea; // inverter area + // statistics + abctime clkStart; // starting time + double CutCount[6]; // cut counts + int nCutUseAll; // objects with useful cuts +}; + +static inline int Pf_Mat2Int( Pf_Mat_t Mat ) { union { int x; Pf_Mat_t y; } v; v.y = Mat; return v.x; } +static inline Pf_Mat_t Pf_Int2Mat( int Int ) { union { int x; Pf_Mat_t y; } v; v.x = Int; return v.y; } + +static inline Pf_Obj_t * Pf_ManObj( Pf_Man_t * p, int i ) { return p->pPfObjs + i; } +static inline Mio_Cell_t* Pf_ManCell( Pf_Man_t * p, int i ) { return p->pCells + i; } +static inline int * Pf_ManCutSet( Pf_Man_t * p, int i ) { return (int *)Vec_PtrEntry(&p->vPages, i >> 16) + (i & 0xFFFF); } +static inline int Pf_ObjCutSetId( Pf_Man_t * p, int i ) { return Vec_IntEntry( &p->vCutSets, i ); } +static inline int * Pf_ObjCutSet( Pf_Man_t * p, int i ) { return Pf_ManCutSet(p, Pf_ObjCutSetId(p, i)); } +static inline int Pf_ObjHasCuts( Pf_Man_t * p, int i ) { return (int)(Vec_IntEntry(&p->vCutSets, i) > 0); } +static inline int Pf_ObjCutUseless( Pf_Man_t * p, int TruthId ) { return (int)(TruthId >= Vec_WecSize(p->vTt2Match)); } + +static inline float Pf_ObjCutFlow( Pf_Man_t * p, int i ) { return Vec_FltEntry(&p->vCutFlows, i); } +static inline int Pf_ObjCutDelay( Pf_Man_t * p, int i ) { return Vec_IntEntry(&p->vCutDelays, i); } +static inline void Pf_ObjSetCutFlow( Pf_Man_t * p, int i, float a ) { Vec_FltWriteEntry(&p->vCutFlows, i, a); } +static inline void Pf_ObjSetCutDelay( Pf_Man_t * p, int i, int d ) { Vec_IntWriteEntry(&p->vCutDelays, i, d); } + +static inline int Pf_CutSize( int * pCut ) { return pCut[0] & PF_NO_LEAF; } +static inline int Pf_CutFunc( int * pCut ) { return ((unsigned)pCut[0] >> 5); } +static inline int * Pf_CutLeaves( int * pCut ) { return pCut + 1; } +static inline int Pf_CutSetBoth( int n, int f ) { return n | (f << 5); } +static inline int Pf_CutIsTriv( int * pCut, int i ) { return Pf_CutSize(pCut) == 1 && pCut[1] == i; } +static inline int Pf_CutHandle( int * pCutSet, int * pCut ) { assert( pCut > pCutSet ); return pCut - pCutSet; } +static inline int * Pf_CutFromHandle( int * pCutSet, int h ) { assert( h > 0 ); return pCutSet + h; } +static inline int Pf_CutConfLit( int Conf, int i ) { return 15 & (Conf >> (i << 2)); } +static inline int Pf_CutConfVar( int Conf, int i ) { return Abc_Lit2Var( Pf_CutConfLit(Conf, i) ); } +static inline int Pf_CutConfC( int Conf, int i ) { return Abc_LitIsCompl( Pf_CutConfLit(Conf, i) ); } + +#define Pf_SetForEachCut( pList, pCut, i ) for ( i = 0, pCut = pList + 1; i < pList[0]; i++, pCut += Pf_CutSize(pCut) + 1 ) +#define Pf_ObjForEachCut( pCuts, i, nCuts ) for ( i = 0, i < nCuts; i++ ) +#define Pf_CutForEachLit( pCut, Conf, iLit, i ) for ( i = 0; i < Pf_CutSize(pCut) && (iLit = Abc_Lit2LitV(Pf_CutLeaves(pCut), Pf_CutConfLit(Conf, i))); i++ ) +#define Pf_CutForEachVar( pCut, Conf, iVar, c, i ) for ( i = 0; i < Pf_CutSize(pCut) && (iVar = Pf_CutLeaves(pCut)[Pf_CutConfVar(Conf, i)]) && ((c = Pf_CutConfC(Conf, i)), 1); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pf_StoCreateGateAdd( Pf_Man_t * pMan, word uTruth, int * pFans, int nFans, int CellId ) +{ + Vec_Int_t * vArray; + Pf_Mat_t Mat = Pf_Int2Mat(0); + int i, GateId, Entry, fCompl = (int)(uTruth & 1); + word uFunc = fCompl ? ~uTruth : uTruth; + int iFunc = Vec_MemHashInsert( pMan->vTtMem, &uFunc ); + if ( iFunc == Vec_WecSize(pMan->vTt2Match) ) + Vec_WecPushLevel( pMan->vTt2Match ); + vArray = Vec_WecEntry( pMan->vTt2Match, iFunc ); + Mat.fCompl = fCompl; + assert( nFans < 7 ); + for ( i = 0; i < nFans; i++ ) + { + Mat.Perm |= (unsigned)(Abc_Lit2Var(pFans[i]) << (3*i)); + Mat.Phase |= (unsigned)(Abc_LitIsCompl(pFans[i]) << i); + } + // check if the same one exists + Vec_IntForEachEntryDouble( vArray, GateId, Entry, i ) + if ( GateId == CellId && Pf_Int2Mat(Entry).Phase == Mat.Phase ) + break; + if ( i == Vec_IntSize(vArray) ) + { + Vec_IntPush( vArray, CellId ); + Vec_IntPush( vArray, Pf_Mat2Int(Mat) ); + } +} +void Pf_StoCreateGate( Pf_Man_t * pMan, Mio_Cell_t * pCell, int ** pComp, int ** pPerm, int * pnPerms ) +{ + int Perm[PF_LEAF_MAX], * Perm1, * Perm2; + int nPerms = pnPerms[pCell->nFanins]; + int nMints = (1 << pCell->nFanins); + word tCur, tTemp1, tTemp2; + int i, p, c; + for ( i = 0; i < (int)pCell->nFanins; i++ ) + Perm[i] = Abc_Var2Lit( i, 0 ); + tCur = tTemp1 = pCell->uTruth; + for ( p = 0; p < nPerms; p++ ) + { + tTemp2 = tCur; + for ( c = 0; c < nMints; c++ ) + { + Pf_StoCreateGateAdd( pMan, tCur, Perm, pCell->nFanins, pCell->Id ); + // update + tCur = Abc_Tt6Flip( tCur, pComp[pCell->nFanins][c] ); + Perm1 = Perm + pComp[pCell->nFanins][c]; + *Perm1 = Abc_LitNot( *Perm1 ); + } + assert( tTemp2 == tCur ); + // update + tCur = Abc_Tt6SwapAdjacent( tCur, pPerm[pCell->nFanins][p] ); + Perm1 = Perm + pPerm[pCell->nFanins][p]; + Perm2 = Perm1 + 1; + ABC_SWAP( int, *Perm1, *Perm2 ); + } + assert( tTemp1 == tCur ); +} +void Pf_StoDeriveMatches( Pf_Man_t * p, int fVerbose ) +{ +// abctime clk = Abc_Clock(); + int * pComp[7]; + int * pPerm[7]; + int nPerms[7], i; + for ( i = 2; i <= 6; i++ ) + pComp[i] = Extra_GreyCodeSchedule( i ); + for ( i = 2; i <= 6; i++ ) + pPerm[i] = Extra_PermSchedule( i ); + for ( i = 2; i <= 6; i++ ) + nPerms[i] = Extra_Factorial( i ); + p->pCells = Mio_CollectRootsNewDefault( 6, &p->nCells, fVerbose ); + for ( i = 4; i < p->nCells; i++ ) + Pf_StoCreateGate( p, p->pCells + i, pComp, pPerm, nPerms ); + for ( i = 2; i <= 6; i++ ) + ABC_FREE( pComp[i] ); + for ( i = 2; i <= 6; i++ ) + ABC_FREE( pPerm[i] ); +// Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} +void Pf_StoPrintOne( Pf_Man_t * p, int Count, int t, int i, int GateId, Pf_Mat_t Mat ) +{ + Mio_Cell_t * pC = p->pCells + GateId; + word * pTruth = Vec_MemReadEntry(p->vTtMem, t); + int k, nSuppSize = Abc_TtSupportSize(pTruth, 6); + printf( "%6d : ", Count ); + printf( "%6d : ", t ); + printf( "%6d : ", i ); + printf( "Gate %16s ", pC->pName ); + printf( "Area =%8.2f ", pC->Area ); + printf( "In = %d ", pC->nFanins ); + if ( Mat.fCompl ) + printf( " compl " ); + else + printf( " " ); + for ( k = 0; k < (int)pC->nFanins; k++ ) + { + int fComplF = (Mat.Phase >> k) & 1; + int iFanin = (Mat.Perm >> (3*k)) & 7; + printf( "%c", 'a' + iFanin - fComplF * ('a' - 'A') ); + } + printf( " " ); + Dau_DsdPrintFromTruth( pTruth, nSuppSize ); +} +void Pf_StoPrint( Pf_Man_t * p, int fVerbose ) +{ + int t, i, GateId, Entry, Count = 0; + for ( t = 2; t < Vec_WecSize(p->vTt2Match); t++ ) + { + Vec_Int_t * vArr = Vec_WecEntry( p->vTt2Match, t ); + Vec_IntForEachEntryDouble( vArr, GateId, Entry, i ) + { + Count++; + if ( !fVerbose ) + continue; + if ( t < 10 ) + Pf_StoPrintOne( p, Count, t, i/2, GateId, Pf_Int2Mat(Entry) ); + } + } + printf( "Gates = %d. Truths = %d. Matches = %d.\n", + p->nCells, Vec_MemEntryNum(p->vTtMem), Count ); +} +/* +void Pf_ManPrepareLibraryTest() +{ + int fVerbose = 0; + abctime clk = Abc_Clock(); + Pf_Man_t * p; + p = Pf_StoCreate( NULL, NULL, fVerbose ); + Pf_StoPrint( p, fVerbose ); + Pf_StoDelete(p); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} +*/ + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Pf_Man_t * Pf_StoCreate( Gia_Man_t * pGia, Jf_Par_t * pPars ) +{ + extern void Mf_ManSetFlowRefs( Gia_Man_t * p, Vec_Int_t * vRefs ); + Pf_Man_t * p; + Vec_Int_t * vFlowRefs; + assert( pPars->nCutNum > 1 && pPars->nCutNum <= PF_CUT_MAX ); + assert( pPars->nLutSize > 1 && pPars->nLutSize <= PF_LEAF_MAX ); + ABC_FREE( pGia->pRefs ); + Vec_IntFreeP( &pGia->vCellMapping ); + if ( Gia_ManHasChoices(pGia) ) + Gia_ManSetPhase(pGia); + // create references + ABC_FREE( pGia->pRefs ); + vFlowRefs = Vec_IntAlloc(0); + Mf_ManSetFlowRefs( pGia, vFlowRefs ); + pGia->pRefs= Vec_IntReleaseArray(vFlowRefs); + Vec_IntFree(vFlowRefs); + // create + p = ABC_CALLOC( Pf_Man_t, 1 ); + p->clkStart = Abc_Clock(); + p->pGia = pGia; + p->pPars = pPars; + p->pPfObjs = ABC_CALLOC( Pf_Obj_t, Gia_ManObjNum(pGia) ); + p->iCur = 2; + // other + Vec_PtrGrow( &p->vPages, 256 ); // cut memory + Vec_IntFill( &p->vCutSets, Gia_ManObjNum(pGia), 0 ); // cut offsets + Vec_FltFill( &p->vCutFlows, Gia_ManObjNum(pGia), 0 ); // cut area + Vec_IntFill( &p->vCutDelays,Gia_ManObjNum(pGia), 0 ); // cut delay + // matching + p->vTtMem = Vec_MemAllocForTT( 6, 0 ); + p->vTt2Match = Vec_WecAlloc( 1000 ); + Vec_WecPushLevel( p->vTt2Match ); + Vec_WecPushLevel( p->vTt2Match ); + assert( Vec_WecSize(p->vTt2Match) == Vec_MemEntryNum(p->vTtMem) ); + Pf_StoDeriveMatches( p, 0 );//pPars->fVerbose ); + p->InvDelay = p->pCells[3].Delays[0]; + p->InvArea = p->pCells[3].Area; + //Pf_ObjMatchD(p, 0, 0)->Gate = 0; + //Pf_ObjMatchD(p, 0, 1)->Gate = 1; + // prepare cuts + return p; +} +void Pf_StoDelete( Pf_Man_t * p ) +{ + Vec_PtrFreeData( &p->vPages ); + ABC_FREE( p->vPages.pArray ); + ABC_FREE( p->vCutSets.pArray ); + ABC_FREE( p->vCutFlows.pArray ); + ABC_FREE( p->vCutDelays.pArray ); + ABC_FREE( p->pPfObjs ); + // matching + Vec_WecFree( p->vTt2Match ); + Vec_MemHashFree( p->vTtMem ); + Vec_MemFree( p->vTtMem ); + ABC_FREE( p->pCells ); + ABC_FREE( p ); +} + + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Pf_CutComputeTruth6( Pf_Man_t * p, Pf_Cut_t * pCut0, Pf_Cut_t * pCut1, int fCompl0, int fCompl1, Pf_Cut_t * pCutR, int fIsXor ) +{ +// extern int Pf_ManTruthCanonicize( word * t, int nVars ); + int nOldSupp = pCutR->nLeaves, truthId, fCompl; word t; + word t0 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut0->iFunc)); + word t1 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut1->iFunc)); + if ( Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ) t0 = ~t0; + if ( Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ) t1 = ~t1; + t0 = Abc_Tt6Expand( t0, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + t1 = Abc_Tt6Expand( t1, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + t = fIsXor ? t0 ^ t1 : t0 & t1; + if ( (fCompl = (int)(t & 1)) ) t = ~t; + pCutR->nLeaves = Abc_Tt6MinBase( &t, pCutR->pLeaves, pCutR->nLeaves ); + assert( (int)(t & 1) == 0 ); + truthId = Vec_MemHashInsert(p->vTtMem, &t); + pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); + pCutR->Useless = Pf_ObjCutUseless( p, truthId ); + assert( (int)pCutR->nLeaves <= nOldSupp ); + return (int)pCutR->nLeaves < nOldSupp; +} +static inline int Pf_CutComputeTruthMux6( Pf_Man_t * p, Pf_Cut_t * pCut0, Pf_Cut_t * pCut1, Pf_Cut_t * pCutC, int fCompl0, int fCompl1, int fComplC, Pf_Cut_t * pCutR ) +{ + int nOldSupp = pCutR->nLeaves, truthId, fCompl; word t; + word t0 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut0->iFunc)); + word t1 = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut1->iFunc)); + word tC = *Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCutC->iFunc)); + if ( Abc_LitIsCompl(pCut0->iFunc) ^ fCompl0 ) t0 = ~t0; + if ( Abc_LitIsCompl(pCut1->iFunc) ^ fCompl1 ) t1 = ~t1; + if ( Abc_LitIsCompl(pCutC->iFunc) ^ fComplC ) tC = ~tC; + t0 = Abc_Tt6Expand( t0, pCut0->pLeaves, pCut0->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + t1 = Abc_Tt6Expand( t1, pCut1->pLeaves, pCut1->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + tC = Abc_Tt6Expand( tC, pCutC->pLeaves, pCutC->nLeaves, pCutR->pLeaves, pCutR->nLeaves ); + t = (tC & t1) | (~tC & t0); + if ( (fCompl = (int)(t & 1)) ) t = ~t; + pCutR->nLeaves = Abc_Tt6MinBase( &t, pCutR->pLeaves, pCutR->nLeaves ); + assert( (int)(t & 1) == 0 ); + truthId = Vec_MemHashInsert(p->vTtMem, &t); + pCutR->iFunc = Abc_Var2Lit( truthId, fCompl ); + pCutR->Useless = Pf_ObjCutUseless( p, truthId ); + assert( (int)pCutR->nLeaves <= nOldSupp ); + return (int)pCutR->nLeaves < nOldSupp; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Pf_CutCountBits( word i ) +{ + i = i - ((i >> 1) & 0x5555555555555555); + i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333); + i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F); + return (i*(0x0101010101010101))>>56; +} +static inline word Pf_CutGetSign( int * pLeaves, int nLeaves ) +{ + word Sign = 0; int i; + for ( i = 0; i < nLeaves; i++ ) + Sign |= ((word)1) << (pLeaves[i] & 0x3F); + return Sign; +} +static inline int Pf_CutCreateUnit( Pf_Cut_t * p, int i ) +{ + p->Delay = 0; + p->Flow = 0; + p->iFunc = 2; + p->nLeaves = 1; + p->pLeaves[0] = i; + p->Sign = ((word)1) << (i & 0x3F); + return 1; +} +static inline void Pf_Cutprintf( Pf_Man_t * p, Pf_Cut_t * pCut ) +{ + int i, nDigits = Abc_Base10Log(Gia_ManObjNum(p->pGia)); + printf( "%d {", pCut->nLeaves ); + for ( i = 0; i < (int)pCut->nLeaves; i++ ) + printf( " %*d", nDigits, pCut->pLeaves[i] ); + for ( ; i < (int)p->pPars->nLutSize; i++ ) + printf( " %*s", nDigits, " " ); + printf( " } Useless = %d. D = %4d A = %9.4f F = %6d ", + pCut->Useless, pCut->Delay, pCut->Flow, pCut->iFunc ); + if ( p->vTtMem ) + Dau_DsdPrintFromTruth( Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(pCut->iFunc)), pCut->nLeaves ); + else + printf( "\n" ); +} +static inline int Pf_ManPrepareCuts( Pf_Cut_t * pCuts, Pf_Man_t * p, int iObj, int fAddUnit ) +{ + if ( Pf_ObjHasCuts(p, iObj) ) + { + Pf_Cut_t * pMfCut = pCuts; + int i, * pCut, * pList = Pf_ObjCutSet(p, iObj); + Pf_SetForEachCut( pList, pCut, i ) + { + pMfCut->Delay = 0; + pMfCut->Flow = 0; + pMfCut->iFunc = Pf_CutFunc( pCut ); + pMfCut->nLeaves = Pf_CutSize( pCut ); + pMfCut->Sign = Pf_CutGetSign( pCut+1, Pf_CutSize(pCut) ); + pMfCut->Useless = Pf_ObjCutUseless( p, Abc_Lit2Var(pMfCut->iFunc) ); + memcpy( pMfCut->pLeaves, pCut+1, sizeof(int) * Pf_CutSize(pCut) ); + pMfCut++; + } + if ( fAddUnit && pCuts->nLeaves > 1 ) + return pList[0] + Pf_CutCreateUnit( pMfCut, iObj ); + return pList[0]; + } + return Pf_CutCreateUnit( pCuts, iObj ); +} +static inline int Pf_ManSaveCuts( Pf_Man_t * p, Pf_Cut_t ** pCuts, int nCuts, int fUseful ) +{ + int i, * pPlace, iCur, nInts = 1, nCutsNew = 0; + for ( i = 0; i < nCuts; i++ ) + if ( !fUseful || !pCuts[i]->Useless ) + nInts += pCuts[i]->nLeaves + 1, nCutsNew++; + if ( (p->iCur & 0xFFFF) + nInts > 0xFFFF ) + p->iCur = ((p->iCur >> 16) + 1) << 16; + if ( Vec_PtrSize(&p->vPages) == (p->iCur >> 16) ) + Vec_PtrPush( &p->vPages, ABC_ALLOC(int, (1<<16)) ); + iCur = p->iCur; p->iCur += nInts; + pPlace = Pf_ManCutSet( p, iCur ); + *pPlace++ = nCutsNew; + for ( i = 0; i < nCuts; i++ ) + if ( !fUseful || !pCuts[i]->Useless ) + { + *pPlace++ = Pf_CutSetBoth( pCuts[i]->nLeaves, pCuts[i]->iFunc ); + memcpy( pPlace, pCuts[i]->pLeaves, sizeof(int) * pCuts[i]->nLeaves ); + pPlace += pCuts[i]->nLeaves; + } + return iCur; +} +static inline int Pf_ManCountUseful( Pf_Cut_t ** pCuts, int nCuts ) +{ + int i, Count = 0; + for ( i = 0; i < nCuts; i++ ) + Count += !pCuts[i]->Useless; + return Count; +} +static inline int Pf_ManCountMatches( Pf_Man_t * p, Pf_Cut_t ** pCuts, int nCuts ) +{ + int i, Count = 0; + for ( i = 0; i < nCuts; i++ ) + if ( !pCuts[i]->Useless ) + Count += Vec_IntSize(Vec_WecEntry(p->vTt2Match, Abc_Lit2Var(pCuts[i]->iFunc))) / 2; + return Count; +} + +/**Function************************************************************* + + Synopsis [Check correctness of cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Pf_CutCheck( Pf_Cut_t * pBase, Pf_Cut_t * pCut ) // check if pCut is contained in pBase +{ + int nSizeB = pBase->nLeaves; + int nSizeC = pCut->nLeaves; + int i, * pB = pBase->pLeaves; + int k, * pC = pCut->pLeaves; + for ( i = 0; i < nSizeC; i++ ) + { + for ( k = 0; k < nSizeB; k++ ) + if ( pC[i] == pB[k] ) + break; + if ( k == nSizeB ) + return 0; + } + return 1; +} +static inline int Pf_SetCheckArray( Pf_Cut_t ** ppCuts, int nCuts ) +{ + Pf_Cut_t * pCut0, * pCut1; + int i, k, m, n, Value; + assert( nCuts > 0 ); + for ( i = 0; i < nCuts; i++ ) + { + pCut0 = ppCuts[i]; + assert( pCut0->nLeaves <= PF_LEAF_MAX ); + assert( pCut0->Sign == Pf_CutGetSign(pCut0->pLeaves, pCut0->nLeaves) ); + // check duplicates + for ( m = 0; m < (int)pCut0->nLeaves; m++ ) + for ( n = m + 1; n < (int)pCut0->nLeaves; n++ ) + assert( pCut0->pLeaves[m] < pCut0->pLeaves[n] ); + // check pairs + for ( k = 0; k < nCuts; k++ ) + { + pCut1 = ppCuts[k]; + if ( pCut0 == pCut1 ) + continue; + // check containments + Value = Pf_CutCheck( pCut0, pCut1 ); + assert( Value == 0 ); + } + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Pf_CutMergeOrder( Pf_Cut_t * pCut0, Pf_Cut_t * pCut1, Pf_Cut_t * pCut, int nLutSize ) +{ + int nSize0 = pCut0->nLeaves; + int nSize1 = pCut1->nLeaves; + int i, * pC0 = pCut0->pLeaves; + int k, * pC1 = pCut1->pLeaves; + int c, * pC = pCut->pLeaves; + // the case of the largest cut sizes + if ( nSize0 == nLutSize && nSize1 == nLutSize ) + { + for ( i = 0; i < nSize0; i++ ) + { + if ( pC0[i] != pC1[i] ) return 0; + pC[i] = pC0[i]; + } + pCut->nLeaves = nLutSize; + pCut->iFunc = PF_NO_FUNC; + pCut->Sign = pCut0->Sign | pCut1->Sign; + return 1; + } + // compare two cuts with different numbers + i = k = c = 0; + if ( nSize0 == 0 ) goto FlushCut1; + if ( nSize1 == 0 ) goto FlushCut0; + while ( 1 ) + { + if ( c == nLutSize ) return 0; + if ( pC0[i] < pC1[k] ) + { + pC[c++] = pC0[i++]; + if ( i >= nSize0 ) goto FlushCut1; + } + else if ( pC0[i] > pC1[k] ) + { + pC[c++] = pC1[k++]; + if ( k >= nSize1 ) goto FlushCut0; + } + else + { + pC[c++] = pC0[i++]; k++; + if ( i >= nSize0 ) goto FlushCut1; + if ( k >= nSize1 ) goto FlushCut0; + } + } + +FlushCut0: + if ( c + nSize0 > nLutSize + i ) return 0; + while ( i < nSize0 ) + pC[c++] = pC0[i++]; + pCut->nLeaves = c; + pCut->iFunc = PF_NO_FUNC; + pCut->Sign = pCut0->Sign | pCut1->Sign; + return 1; + +FlushCut1: + if ( c + nSize1 > nLutSize + k ) return 0; + while ( k < nSize1 ) + pC[c++] = pC1[k++]; + pCut->nLeaves = c; + pCut->iFunc = PF_NO_FUNC; + pCut->Sign = pCut0->Sign | pCut1->Sign; + return 1; +} +static inline int Pf_CutMergeOrderMux( Pf_Cut_t * pCut0, Pf_Cut_t * pCut1, Pf_Cut_t * pCut2, Pf_Cut_t * pCut, int nLutSize ) +{ + int x0, i0 = 0, nSize0 = pCut0->nLeaves, * pC0 = pCut0->pLeaves; + int x1, i1 = 0, nSize1 = pCut1->nLeaves, * pC1 = pCut1->pLeaves; + int x2, i2 = 0, nSize2 = pCut2->nLeaves, * pC2 = pCut2->pLeaves; + int xMin, c = 0, * pC = pCut->pLeaves; + while ( 1 ) + { + x0 = (i0 == nSize0) ? ABC_INFINITY : pC0[i0]; + x1 = (i1 == nSize1) ? ABC_INFINITY : pC1[i1]; + x2 = (i2 == nSize2) ? ABC_INFINITY : pC2[i2]; + xMin = Abc_MinInt( Abc_MinInt(x0, x1), x2 ); + if ( xMin == ABC_INFINITY ) break; + if ( c == nLutSize ) return 0; + pC[c++] = xMin; + if (x0 == xMin) i0++; + if (x1 == xMin) i1++; + if (x2 == xMin) i2++; + } + pCut->nLeaves = c; + pCut->iFunc = PF_NO_FUNC; + pCut->Sign = pCut0->Sign | pCut1->Sign | pCut2->Sign; + return 1; +} +static inline int Pf_SetCutIsContainedOrder( Pf_Cut_t * pBase, Pf_Cut_t * pCut ) // check if pCut is contained in pBase +{ + int i, nSizeB = pBase->nLeaves; + int k, nSizeC = pCut->nLeaves; + if ( nSizeB == nSizeC ) + { + for ( i = 0; i < nSizeB; i++ ) + if ( pBase->pLeaves[i] != pCut->pLeaves[i] ) + return 0; + return 1; + } + assert( nSizeB > nSizeC ); + if ( nSizeC == 0 ) + return 1; + for ( i = k = 0; i < nSizeB; i++ ) + { + if ( pBase->pLeaves[i] > pCut->pLeaves[k] ) + return 0; + if ( pBase->pLeaves[i] == pCut->pLeaves[k] ) + { + if ( ++k == nSizeC ) + return 1; + } + } + return 0; +} +static inline int Pf_SetLastCutIsContained( Pf_Cut_t ** pCuts, int nCuts ) +{ + int i; + for ( i = 0; i < nCuts; i++ ) + if ( pCuts[i]->nLeaves <= pCuts[nCuts]->nLeaves && (pCuts[i]->Sign & pCuts[nCuts]->Sign) == pCuts[i]->Sign && Pf_SetCutIsContainedOrder(pCuts[nCuts], pCuts[i]) ) + return 1; + return 0; +} +static inline int Pf_SetLastCutContainsArea( Pf_Cut_t ** pCuts, int nCuts ) +{ + int i, k, fChanges = 0; + for ( i = 0; i < nCuts; i++ ) + if ( pCuts[nCuts]->nLeaves < pCuts[i]->nLeaves && (pCuts[nCuts]->Sign & pCuts[i]->Sign) == pCuts[nCuts]->Sign && Pf_SetCutIsContainedOrder(pCuts[i], pCuts[nCuts]) ) + pCuts[i]->nLeaves = PF_NO_LEAF, fChanges = 1; + if ( !fChanges ) + return nCuts; + for ( i = k = 0; i <= nCuts; i++ ) + { + if ( pCuts[i]->nLeaves == PF_NO_LEAF ) + continue; + if ( k < i ) + ABC_SWAP( Pf_Cut_t *, pCuts[k], pCuts[i] ); + k++; + } + return k - 1; +} +static inline int Pf_CutCompareArea( Pf_Cut_t * pCut0, Pf_Cut_t * pCut1 ) +{ + if ( pCut0->Useless < pCut1->Useless ) return -1; + if ( pCut0->Useless > pCut1->Useless ) return 1; + if ( pCut0->Flow < pCut1->Flow ) return -1; + if ( pCut0->Flow > pCut1->Flow ) return 1; + if ( pCut0->Delay < pCut1->Delay ) return -1; + if ( pCut0->Delay > pCut1->Delay ) return 1; + if ( pCut0->nLeaves < pCut1->nLeaves ) return -1; + if ( pCut0->nLeaves > pCut1->nLeaves ) return 1; + return 0; +} +static inline void Pf_SetSortByArea( Pf_Cut_t ** pCuts, int nCuts ) +{ + int i; + for ( i = nCuts; i > 0; i-- ) + { + if ( Pf_CutCompareArea(pCuts[i - 1], pCuts[i]) < 0 )//!= 1 ) + return; + ABC_SWAP( Pf_Cut_t *, pCuts[i - 1], pCuts[i] ); + } +} +static inline int Pf_SetAddCut( Pf_Cut_t ** pCuts, int nCuts, int nCutNum ) +{ + if ( nCuts == 0 ) + return 1; + nCuts = Pf_SetLastCutContainsArea(pCuts, nCuts); + Pf_SetSortByArea( pCuts, nCuts ); + return Abc_MinInt( nCuts + 1, nCutNum - 1 ); +} +static inline int Pf_CutArea( Pf_Man_t * p, int nLeaves ) +{ + if ( nLeaves < 2 ) + return 0; + return nLeaves + p->pPars->nAreaTuner; +} +static inline void Pf_CutParams( Pf_Man_t * p, Pf_Cut_t * pCut, int nGiaRefs ) +{ + int i, nLeaves = pCut->nLeaves; + assert( nLeaves <= p->pPars->nLutSize ); + pCut->Delay = 0; + pCut->Flow = 0; + for ( i = 0; i < nLeaves; i++ ) + { + pCut->Delay = Abc_MaxInt( pCut->Delay, Pf_ObjCutDelay(p, pCut->pLeaves[i]) ); + pCut->Flow += Pf_ObjCutFlow(p, pCut->pLeaves[i]); + } + pCut->Delay += (int)(nLeaves > 1); + pCut->Flow = (pCut->Flow + Pf_CutArea(p, nLeaves)) / (nGiaRefs ? nGiaRefs : 1); +} +void Pf_ObjMergeOrder( Pf_Man_t * p, int iObj ) +{ + Pf_Cut_t pCuts0[PF_CUT_MAX], pCuts1[PF_CUT_MAX], pCuts[PF_CUT_MAX], * pCutsR[PF_CUT_MAX]; + Gia_Obj_t * pObj = Gia_ManObj(p->pGia, iObj); + int nGiaRefs = 2*Gia_ObjRefNumId(p->pGia, iObj); + int nLutSize = p->pPars->nLutSize; + int nCutNum = p->pPars->nCutNum; + int nCuts0 = Pf_ManPrepareCuts(pCuts0, p, Gia_ObjFaninId0(pObj, iObj), 1); + int nCuts1 = Pf_ManPrepareCuts(pCuts1, p, Gia_ObjFaninId1(pObj, iObj), 1); + int fComp0 = Gia_ObjFaninC0(pObj); + int fComp1 = Gia_ObjFaninC1(pObj); + int iSibl = Gia_ObjSibl(p->pGia, iObj); + Pf_Cut_t * pCut0, * pCut1, * pCut0Lim = pCuts0 + nCuts0, * pCut1Lim = pCuts1 + nCuts1; + int i, nCutsUse, nCutsR = 0; + assert( !Gia_ObjIsBuf(pObj) ); + for ( i = 0; i < nCutNum; i++ ) + pCutsR[i] = pCuts + i; + if ( iSibl ) + { + Pf_Cut_t pCuts2[PF_CUT_MAX]; + Gia_Obj_t * pObjE = Gia_ObjSiblObj(p->pGia, iObj); + int fCompE = Gia_ObjPhase(pObj) ^ Gia_ObjPhase(pObjE); + int nCuts2 = Pf_ManPrepareCuts(pCuts2, p, iSibl, 0); + Pf_Cut_t * pCut2, * pCut2Lim = pCuts2 + nCuts2; + for ( pCut2 = pCuts2; pCut2 < pCut2Lim; pCut2++ ) + { + *pCutsR[nCutsR] = *pCut2; + pCutsR[nCutsR]->iFunc = Abc_LitNotCond( pCutsR[nCutsR]->iFunc, fCompE ); + Pf_CutParams( p, pCutsR[nCutsR], nGiaRefs ); + nCutsR = Pf_SetAddCut( pCutsR, nCutsR, nCutNum ); + } + } + if ( Gia_ObjIsMuxId(p->pGia, iObj) ) + { + Pf_Cut_t pCuts2[PF_CUT_MAX]; + int nCuts2 = Pf_ManPrepareCuts(pCuts2, p, Gia_ObjFaninId2(p->pGia, iObj), 1); + int fComp2 = Gia_ObjFaninC2(p->pGia, pObj); + Pf_Cut_t * pCut2, * pCut2Lim = pCuts2 + nCuts2; + p->CutCount[0] += nCuts0 * nCuts1 * nCuts2; + for ( pCut0 = pCuts0; pCut0 < pCut0Lim; pCut0++ ) + for ( pCut1 = pCuts1; pCut1 < pCut1Lim; pCut1++ ) + for ( pCut2 = pCuts2; pCut2 < pCut2Lim; pCut2++ ) + { + if ( Pf_CutCountBits(pCut0->Sign | pCut1->Sign | pCut2->Sign) > nLutSize ) + continue; + p->CutCount[1]++; + if ( !Pf_CutMergeOrderMux(pCut0, pCut1, pCut2, pCutsR[nCutsR], nLutSize) ) + continue; + if ( Pf_SetLastCutIsContained(pCutsR, nCutsR) ) + continue; + p->CutCount[2]++; + if ( Pf_CutComputeTruthMux6(p, pCut0, pCut1, pCut2, fComp0, fComp1, fComp2, pCutsR[nCutsR]) ) + pCutsR[nCutsR]->Sign = Pf_CutGetSign(pCutsR[nCutsR]->pLeaves, pCutsR[nCutsR]->nLeaves); + Pf_CutParams( p, pCutsR[nCutsR], nGiaRefs ); + nCutsR = Pf_SetAddCut( pCutsR, nCutsR, nCutNum ); + } + } + else + { + int fIsXor = Gia_ObjIsXor(pObj); + p->CutCount[0] += nCuts0 * nCuts1; + for ( pCut0 = pCuts0; pCut0 < pCut0Lim; pCut0++ ) + for ( pCut1 = pCuts1; pCut1 < pCut1Lim; pCut1++ ) + { + if ( (int)(pCut0->nLeaves + pCut1->nLeaves) > nLutSize && Pf_CutCountBits(pCut0->Sign | pCut1->Sign) > nLutSize ) + continue; + p->CutCount[1]++; + if ( !Pf_CutMergeOrder(pCut0, pCut1, pCutsR[nCutsR], nLutSize) ) + continue; + if ( Pf_SetLastCutIsContained(pCutsR, nCutsR) ) + continue; + p->CutCount[2]++; + if ( Pf_CutComputeTruth6(p, pCut0, pCut1, fComp0, fComp1, pCutsR[nCutsR], fIsXor) ) + pCutsR[nCutsR]->Sign = Pf_CutGetSign(pCutsR[nCutsR]->pLeaves, pCutsR[nCutsR]->nLeaves); + Pf_CutParams( p, pCutsR[nCutsR], nGiaRefs ); + nCutsR = Pf_SetAddCut( pCutsR, nCutsR, nCutNum ); + } + } + // debug printout + if ( 0 ) +// if ( iObj % 10000 == 0 ) +// if ( iObj == 1090 ) + { + printf( "*** Obj = %d Useful = %d\n", iObj, Pf_ManCountUseful(pCutsR, nCutsR) ); + for ( i = 0; i < nCutsR; i++ ) + Pf_Cutprintf( p, pCutsR[i] ); + printf( "\n" ); + } + // verify + assert( nCutsR > 0 && nCutsR < nCutNum ); +// assert( Pf_SetCheckArray(pCutsR, nCutsR) ); + // store the cutset + Pf_ObjSetCutFlow( p, iObj, pCutsR[0]->Flow ); + Pf_ObjSetCutDelay( p, iObj, pCutsR[0]->Delay ); + *Vec_IntEntryP(&p->vCutSets, iObj) = Pf_ManSaveCuts(p, pCutsR, nCutsR, 0); + p->CutCount[3] += nCutsR; + nCutsUse = Pf_ManCountUseful(pCutsR, nCutsR); + p->CutCount[4] += nCutsUse; + p->nCutUseAll += nCutsUse == nCutsR; + p->CutCount[5] += Pf_ManCountMatches(p, pCutsR, nCutsR); +} +void Pf_ManComputeCuts( Pf_Man_t * p ) +{ + Gia_Obj_t * pObj; int i, iFanin; + Gia_ManForEachAnd( p->pGia, pObj, i ) + if ( Gia_ObjIsBuf(pObj) ) + { + iFanin = Gia_ObjFaninId0(pObj, i); + Pf_ObjSetCutFlow( p, i, Pf_ObjCutFlow(p, iFanin) ); + Pf_ObjSetCutDelay( p, i, Pf_ObjCutDelay(p, iFanin) ); + } + else + Pf_ObjMergeOrder( p, i ); +} + + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pf_ManPrintStats( Pf_Man_t * p, char * pTitle ) +{ + if ( !p->pPars->fVerbose ) + return; + printf( "%s : ", pTitle ); + printf( "Delay =%8.2f ", (float)p->pPars->MapDelay ); + printf( "Area =%12.2f ", p->pPars->MapArea ); + printf( "Gate =%6d ", (int)p->pPars->Area ); + printf( "Inv =%6d ", (int)p->nInvs ); + printf( "Edge =%7d ", (int)p->pPars->Edge ); + Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); + fflush( stdout ); +} +void Pf_ManPrintInit( Pf_Man_t * p ) +{ + int nChoices; + if ( !p->pPars->fVerbose ) + return; + printf( "LutSize = %d ", p->pPars->nLutSize ); + printf( "CutNum = %d ", p->pPars->nCutNum ); + printf( "Iter = %d ", p->pPars->nRounds + p->pPars->nRoundsEla ); + printf( "Coarse = %d ", p->pPars->fCoarsen ); + printf( "Cells = %d ", p->nCells ); + printf( "Funcs = %d ", Vec_MemEntryNum(p->vTtMem) ); + printf( "Matches = %d ", Vec_WecSizeSize(p->vTt2Match)/2 ); + nChoices = Gia_ManChoiceNum( p->pGia ); + if ( nChoices ) + printf( "Choices = %d ", nChoices ); + printf( "\n" ); + printf( "Computing cuts...\r" ); + fflush( stdout ); +} +void Pf_ManPrintQuit( Pf_Man_t * p ) +{ + float MemGia = Gia_ManMemory(p->pGia) / (1<<20); + float MemMan =(1.0 * sizeof(Pf_Obj_t) + 3.0 * sizeof(int)) * Gia_ManObjNum(p->pGia) / (1<<20); + float MemCuts = 1.0 * sizeof(int) * (1 << 16) * Vec_PtrSize(&p->vPages) / (1<<20); + float MemTt = p->vTtMem ? Vec_MemMemory(p->vTtMem) / (1<<20) : 0; + if ( p->CutCount[0] == 0 ) + p->CutCount[0] = 1; + if ( !p->pPars->fVerbose ) + return; + printf( "CutPair = %.0f ", p->CutCount[0] ); + printf( "Merge = %.0f (%.1f) ", p->CutCount[1], 1.0*p->CutCount[1]/Gia_ManAndNum(p->pGia) ); + printf( "Eval = %.0f (%.1f) ", p->CutCount[2], 1.0*p->CutCount[2]/Gia_ManAndNum(p->pGia) ); + printf( "Cut = %.0f (%.1f) ", p->CutCount[3], 1.0*p->CutCount[3]/Gia_ManAndNum(p->pGia) ); + printf( "Use = %.0f (%.1f) ", p->CutCount[4], 1.0*p->CutCount[4]/Gia_ManAndNum(p->pGia) ); + printf( "Mat = %.0f (%.1f) ", p->CutCount[5], 1.0*p->CutCount[5]/Gia_ManAndNum(p->pGia) ); +// printf( "Equ = %d (%.2f %%) ", p->nCutUseAll, 100.0*p->nCutUseAll /p->CutCount[0] ); + printf( "\n" ); + printf( "Gia = %.2f MB ", MemGia ); + printf( "Man = %.2f MB ", MemMan ); + printf( "Cut = %.2f MB ", MemCuts ); + printf( "TT = %.2f MB ", MemTt ); + printf( "Total = %.2f MB ", MemGia + MemMan + MemCuts + MemTt ); +// printf( "\n" ); + Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); + fflush( stdout ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +/* +void Pf_ManSetMapRefsGate( Pf_Man_t * p, int iObj, float Required, Pf_Mat_t * pM ) +{ + int k, iVar, fCompl; + Mio_Cell_t * pCell = Pf_ManCell( p, pM->Gate ); + int * pCut = Pf_CutFromHandle( Pf_ObjCutSet(p, iObj), pM->CutH ); + Pf_CutForEachVar( pCut, pM->Conf, iVar, fCompl, k ) + { + Pf_ObjMapRefInc( p, iVar, fCompl ); + Pf_ObjUpdateRequired( p, iVar, fCompl, Required - pCell->Delays[k] ); + } + assert( Pf_CutSize(pCut) == (int)pCell->nFanins ); + // update global stats + p->pPars->MapArea += pCell->Area; + p->pPars->Edge += Pf_CutSize(pCut); + p->pPars->Area++; + // update status of the gate + assert( pM->fBest == 0 ); + pM->fBest = 1; +} +int Pf_ManSetMapRefs( Pf_Man_t * p ) +{ + float Coef = 1.0 / (1.0 + (p->Iter + 1) * (p->Iter + 1)); + float * pFlowRefs = Vec_FltArray( &p->vFlowRefs ); + int * pMapRefs = Vec_IntArray( &p->vMapRefs ); + float Epsilon = p->pPars->Epsilon; + int nLits = 2*Gia_ManObjNum(p->pGia); + int i, c, Id, nRefs[2]; + Pf_Mat_t * pD, * pA, * pM; + Pf_Mat_t * pDs[2], * pAs[2], * pMs[2]; + Gia_Obj_t * pObj; + float Required = 0, Requireds[2]; + // check references + assert( !p->fUseEla ); + memset( pMapRefs, 0, sizeof(int) * nLits ); + Vec_FltFill( &p->vRequired, nLits, PF_INFINITY ); +// for ( i = 0; i < Gia_ManObjNum(p->pGia); i++ ) +// assert( !Pf_ObjMapRefNum(p, i, 0) && !Pf_ObjMapRefNum(p, i, 1) ); + // compute delay + p->pPars->MapDelay = 0; + Gia_ManForEachCo( p->pGia, pObj, i ) + { + Required = Pf_ObjMatchD( p, Gia_ObjFaninId0p(p->pGia, pObj), Gia_ObjFaninC0(pObj) )->D; + if ( Required == PF_INFINITY ) + { + Pf_ManCutMatchprintf( p, Gia_ObjFaninId0p(p->pGia, pObj), Gia_ObjFaninC0(pObj), Pf_ObjMatchD( p, Gia_ObjFaninId0p(p->pGia, pObj), Gia_ObjFaninC0(pObj) ) ); + } + p->pPars->MapDelay = Abc_MaxFloat( p->pPars->MapDelay, Required ); + } + // check delay target + if ( p->pPars->MapDelayTarget == -1 && p->pPars->nRelaxRatio ) + p->pPars->MapDelayTarget = (int)((float)p->pPars->MapDelay * (100.0 + p->pPars->nRelaxRatio) / 100.0); + if ( p->pPars->MapDelayTarget != -1 ) + { + if ( p->pPars->MapDelay < p->pPars->MapDelayTarget + Epsilon ) + p->pPars->MapDelay = p->pPars->MapDelayTarget; + else if ( p->pPars->nRelaxRatio == 0 ) + Abc_Print( 0, "Relaxing user-specified delay target from %.2f to %.2f.\n", p->pPars->MapDelayTarget, p->pPars->MapDelay ); + } + // set required times + Gia_ManForEachCo( p->pGia, pObj, i ) + { + Required = Pf_ObjMatchD( p, Gia_ObjFaninId0p(p->pGia, pObj), Gia_ObjFaninC0(pObj) )->D; + Required = p->pPars->fDoAverage ? Required * (100.0 + p->pPars->nRelaxRatio) / 100.0 : p->pPars->MapDelay; + Pf_ObjUpdateRequired( p, Gia_ObjFaninId0p(p->pGia, pObj), Gia_ObjFaninC0(pObj), Required ); + Pf_ObjMapRefInc( p, Gia_ObjFaninId0p(p->pGia, pObj), Gia_ObjFaninC0(pObj)); + } + // compute area and edges + p->nInvs = 0; + p->pPars->MapArea = 0; + p->pPars->Area = p->pPars->Edge = 0; + Gia_ManForEachAndReverse( p->pGia, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + { + if ( Pf_ObjMapRefNum(p, i, 1) ) + { + Pf_ObjMapRefInc( p, i, 0 ); + Pf_ObjUpdateRequired( p, i, 0, Pf_ObjRequired(p, i, 1) - p->InvDelay ); + p->pPars->MapArea += p->InvArea; + p->pPars->Edge++; + p->pPars->Area++; + p->nInvs++; + } + Pf_ObjUpdateRequired( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj), Pf_ObjRequired(p, i, 0) ); + Pf_ObjMapRefInc( p, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninC0(pObj)); + continue; + } + // skip if this node is not used + for ( c = 0; c < 2; c++ ) + { + nRefs[c] = Pf_ObjMapRefNum(p, i, c); + + //if ( Pf_ObjMatchD( p, i, c )->fCompl ) + // printf( "Match D of node %d has inv in phase %d.\n", i, c ); + //if ( Pf_ObjMatchA( p, i, c )->fCompl ) + // printf( "Match A of node %d has inv in phase %d.\n", i, c ); + } + if ( !nRefs[0] && !nRefs[1] ) + continue; + + // consider two cases + if ( nRefs[0] && nRefs[1] ) + { + // find best matches for both phases + for ( c = 0; c < 2; c++ ) + { + Requireds[c] = Pf_ObjRequired( p, i, c ); + //assert( Requireds[c] < PF_INFINITY ); + pDs[c] = Pf_ObjMatchD( p, i, c ); + pAs[c] = Pf_ObjMatchA( p, i, c ); + pMs[c] = (pAs[c]->D < Requireds[c] + Epsilon) ? pAs[c] : pDs[c]; + } + // swap complemented matches + if ( pMs[0]->fCompl && pMs[1]->fCompl ) + { + pMs[0]->fCompl = pMs[1]->fCompl = 0; + ABC_SWAP( Pf_Mat_t *, pMs[0], pMs[1] ); + } + // check if intervers are involved + if ( !pMs[0]->fCompl && !pMs[1]->fCompl ) + { + // no inverters + for ( c = 0; c < 2; c++ ) + Pf_ManSetMapRefsGate( p, i, Requireds[c], pMs[c] ); + } + else + { + // one interver + assert( !pMs[0]->fCompl || !pMs[1]->fCompl ); + c = pMs[1]->fCompl; + assert( pMs[c]->fCompl && !pMs[!c]->fCompl ); + //printf( "Using inverter at node %d in phase %d\n", i, c ); + + // update this phase phase + pM = pMs[c]; + pM->fBest = 1; + Required = Requireds[c]; + + // update opposite phase + Pf_ObjMapRefInc( p, i, !c ); + Pf_ObjUpdateRequired( p, i, !c, Required - p->InvDelay ); + + // select oppositve phase + Required = Pf_ObjRequired( p, i, !c ); + //assert( Required < PF_INFINITY ); + pD = Pf_ObjMatchD( p, i, !c ); + pA = Pf_ObjMatchA( p, i, !c ); + pM = (pA->D < Required + Epsilon) ? pA : pD; + assert( !pM->fCompl ); + + // account for the inverter + p->pPars->MapArea += p->InvArea; + p->pPars->Edge++; + p->pPars->Area++; + p->nInvs++; + + // create gate + Pf_ManSetMapRefsGate( p, i, Required, pM ); + } + } + else + { + c = (int)(nRefs[1] > 0); + assert( nRefs[c] && !nRefs[!c] ); + // consider this phase + Required = Pf_ObjRequired( p, i, c ); + //assert( Required < PF_INFINITY ); + pD = Pf_ObjMatchD( p, i, c ); + pA = Pf_ObjMatchA( p, i, c ); + pM = (pA->D < Required + Epsilon) ? pA : pD; + + if ( pM->fCompl ) // use inverter + { + p->nInvs++; + //printf( "Using inverter at node %d in phase %d\n", i, c ); + pM->fBest = 1; + // update opposite phase + Pf_ObjMapRefInc( p, i, !c ); + Pf_ObjUpdateRequired( p, i, !c, Required - p->InvDelay ); + // select oppositve phase + Required = Pf_ObjRequired( p, i, !c ); + //assert( Required < PF_INFINITY ); + pD = Pf_ObjMatchD( p, i, !c ); + pA = Pf_ObjMatchA( p, i, !c ); + pM = (pA->D < Required + Epsilon) ? pA : pD; + assert( !pM->fCompl ); + + // account for the inverter + p->pPars->MapArea += p->InvArea; + p->pPars->Edge++; + p->pPars->Area++; + } + + // create gate + Pf_ManSetMapRefsGate( p, i, Required, pM ); + } + + + // the result of this: + // - only one phase can be implemented as inverter of the other phase + // - required times are propagated correctly + // - references are set correctly + } + Gia_ManForEachCiId( p->pGia, Id, i ) + if ( Pf_ObjMapRefNum(p, Id, 1) ) + { + Pf_ObjMapRefInc( p, Id, 0 ); + Pf_ObjUpdateRequired( p, Id, 0, Required - p->InvDelay ); + p->pPars->MapArea += p->InvArea; + p->pPars->Edge++; + p->pPars->Area++; + p->nInvs++; + } + // blend references + for ( i = 0; i < nLits; i++ ) +// pFlowRefs[i] = Abc_MaxFloat(1.0, pMapRefs[i]); + pFlowRefs[i] = Abc_MaxFloat(1.0, Coef * pFlowRefs[i] + (1.0 - Coef) * Abc_MaxFloat(1, pMapRefs[i])); +// pFlowRefs[i] = 0.2 * pFlowRefs[i] + 0.8 * Abc_MaxFloat(1, pMapRefs[i]); +// memset( pMapRefs, 0, sizeof(int) * nLits ); + return p->pPars->Area; +} +Gia_Man_t * Pf_ManDeriveMapping( Pf_Man_t * p ) +{ + Vec_Int_t * vMapping; + Pf_Mat_t * pM; + int i, k, c, Id, iLit, * pCut; + assert( p->pGia->vCellMapping == NULL ); + vMapping = Vec_IntAlloc( 2*Gia_ManObjNum(p->pGia) + (int)p->pPars->Edge + (int)p->pPars->Area * 2 ); + Vec_IntFill( vMapping, 2*Gia_ManObjNum(p->pGia), 0 ); + // create CI inverters + Gia_ManForEachCiId( p->pGia, Id, i ) + if ( Pf_ObjMapRefNum(p, Id, 1) ) + Vec_IntWriteEntry( vMapping, Abc_Var2Lit(Id, 1), -1 ); + // create internal nodes + Gia_ManForEachAndId( p->pGia, i ) + { + Gia_Obj_t * pObj = Gia_ManObj(p->pGia, i); + if ( Gia_ObjIsBuf(pObj) ) + { + if ( Pf_ObjMapRefNum(p, i, 1) ) + Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, 1), -1 ); + Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, 0), -2 ); + continue; + } + for ( c = 0; c < 2; c++ ) + if ( Pf_ObjMapRefNum(p, i, c) ) + { + // printf( "Using %d %d\n", i, c ); + pM = Pf_ObjMatchBest( p, i, c ); + // remember inverter + if ( pM->fCompl ) + { + Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, c), -1 ); + continue; + } + // Pf_ManCutMatchprintf( p, i, c, pM ); + pCut = Pf_CutFromHandle( Pf_ObjCutSet(p, i), pM->CutH ); + // create mapping + Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, c), Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, Pf_CutSize(pCut) ); + Pf_CutForEachLit( pCut, pM->Conf, iLit, k ) + Vec_IntPush( vMapping, iLit ); + Vec_IntPush( vMapping, pM->Gate ); + } + } +// assert( Vec_IntCap(vMapping) == 16 || Vec_IntSize(vMapping) == Vec_IntCap(vMapping) ); + p->pGia->vCellMapping = vMapping; + return p->pGia; +} +*/ + + +/**Function************************************************************* + + Synopsis [Technology mappping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pf_ManComputeMapping( Pf_Man_t * p ) +{ +} + +/**Function************************************************************* + + Synopsis [Technology mappping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Pf_ManSetDefaultPars( Jf_Par_t * pPars ) +{ + memset( pPars, 0, sizeof(Jf_Par_t) ); + pPars->nLutSize = 6; + pPars->nCutNum = 16; + pPars->nProcNum = 0; + pPars->nRounds = 3; + pPars->nRoundsEla = 0; + pPars->nRelaxRatio = 0; + pPars->nCoarseLimit = 3; + pPars->nAreaTuner = 1; + pPars->nVerbLimit = 5; + pPars->DelayTarget = -1; + pPars->fAreaOnly = 0; + pPars->fOptEdge = 1; + pPars->fCoarsen = 0; + pPars->fCutMin = 1; + pPars->fGenCnf = 0; + pPars->fPureAig = 0; + pPars->fVerbose = 0; + pPars->fVeryVerbose = 0; + pPars->nLutSizeMax = PF_LEAF_MAX; + pPars->nCutNumMax = PF_CUT_MAX; + pPars->MapDelayTarget = -1; + pPars->Epsilon = (float)0.01; +} +Gia_Man_t * Pf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars ) +{ + Gia_Man_t * pNew = NULL, * pCls; + Pf_Man_t * p; + if ( Gia_ManHasChoices(pGia) ) + pPars->fCoarsen = 0; + pCls = pPars->fCoarsen ? Gia_ManDupMuxes(pGia, pPars->nCoarseLimit) : pGia; + p = Pf_StoCreate( pCls, pPars ); +// if ( pPars->fVeryVerbose ) + Pf_StoPrint( p, 1 ); + if ( pPars->fVerbose && pPars->fCoarsen ) + { + printf( "Initial " ); Gia_ManPrintMuxStats( pGia ); printf( "\n" ); + printf( "Derived " ); Gia_ManPrintMuxStats( pCls ); printf( "\n" ); + } + Pf_ManPrintInit( p ); + Pf_ManComputeCuts( p ); + Pf_ManPrintQuit( p ); +/* + Gia_ManForEachCiId( p->pGia, Id, i ) + Pf_ObjPrepareCi( p, Id ); + for ( p->Iter = 0; p->Iter < p->pPars->nRounds; p->Iter++ ) + { + Pf_ManComputeMapping( p ); + //Pf_ManSetMapRefs( p ); + Pf_ManPrintStats( p, p->Iter ? "Area " : "Delay" ); + } + p->fUseEla = 1; + for ( ; p->Iter < p->pPars->nRounds + pPars->nRoundsEla; p->Iter++ ) + { + Pf_ManComputeMapping( p ); + //Pf_ManUpdateStats( p ); + Pf_ManPrintStats( p, "Ela " ); + } +*/ + pNew = NULL; //Pf_ManDeriveMapping( p ); +// Gia_ManMappingVerify( pNew ); + Pf_StoDelete( p ); + if ( pCls != pGia ) + Gia_ManStop( pCls ); + if ( pNew == NULL ) + return Gia_ManDup( pGia ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaProp.c b/yosys/abc/src/aig/gia/giaProp.c new file mode 100644 index 00000000000..fee9aa400ce --- /dev/null +++ b/yosys/abc/src/aig/gia/giaProp.c @@ -0,0 +1,176 @@ +/**CFile**************************************************************** + + FileName [giaProp.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Constraint propagation on the AIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaProp.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define GIA_SAT_SHIFT 12 +#define GIA_ROOT_MASK +#define GIA_PATH00_MASK +#define GIA_PATH10_MASK +#define GIA_PATH20_MASK +#define GIA_PATH30_MASK +#define GIA_PATH00_MASK +#define GIA_PATH10_MASK +#define GIA_PATH20_MASK +#define GIA_PATH30_MASK + +static inline int Gia_SatObjIsRoot( Gia_Obj_t * p ) { return 0; } +static inline int Gia_SatObjXorRoot( Gia_Obj_t * p ) { return 0; } + + +static inline int Gia_SatObjIsAssigned( Gia_Obj_t * p ) { return 0; } +static inline int Gia_SatObjIsHeld( Gia_Obj_t * p ) { return 0; } +static inline int Gia_SatObjValue( Gia_Obj_t * p ) { return 0; } + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks if the give cut is satisfied.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_SatPathCheckCutSat_rec( Gia_Obj_t * p, int fCompl ) +{ + if ( Gia_SatObjIsRoot(p) ) + return Gia_ObjIsAssigned(p) && Gia_SatObjValue(p) == fCompl; + if ( Gia_SatObjPath0(p) && !Gia_SatPathCheckCutSat_rec( Gia_ObjFanin0(p), fCompl ^ Gia_ObjFaninC0(p) ) ) + return 0; + if ( Gia_SatObjPath1(p) && !Gia_SatPathCheckCutSat_rec( Gia_ObjFanin1(p), fCompl ^ Gia_ObjFaninC1(p) ) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks if the give cut is satisfied.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_SatPathCheckCutSat( Gia_Obj_t * p ) +{ + int RetValue; + assert( Gia_SatObjIsRoot(p) ); + Gia_SatObjXorRoot(p); + RetValue = Gia_SatPathCheckCutSat_rec( p ); + Gia_SatObjXorRoot(p); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Unbinds literals on the path.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_SatPathUnbind_rec( Gia_Obj_t * p ) +{ +} + +/**Function************************************************************* + + Synopsis [Creates a feasible path from the node to a terminal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_SatPathStart_rec( Gia_Obj_t * p, int fDiffs, int fCompl ) +{ + if ( Gia_SatObjIsRoot(p) ) + return fDiffs && (!Gia_ObjIsAssigned(p) || Gia_SatObjValue(p) != fCompl); + if ( fCompl == 0 ) + { + if ( Gia_SatPathStart_rec( Gia_ObjFanin0(p), fDiffs + !Gia_SatObjPath0(p), fCompl ^ Gia_ObjFaninC0(p) ) && + Gia_SatPathStart_rec( Gia_ObjFanin1(p), fDiffs + !Gia_SatObjPath1(p), fCompl ^ Gia_ObjFaninC1(p) ) ) + return Gia_ObjSetDraftPath0(p) + Gia_ObjSetDraftPath1(p); + } + else + { + if ( Gia_SatPathStart_rec( Gia_ObjFanin0(p), fDiffs + !Gia_SatObjPath0(p), fCompl ^ Gia_ObjFaninC0(p) ) ) + { + Gia_ObjUnsetDraftPath1(p); + return Gia_ObjSetDraftPath0(p); + } + if ( Gia_SatPathStart_rec( Gia_ObjFanin1(p), fDiffs + !Gia_SatObjPath1(p), fCompl ^ Gia_ObjFaninC1(p) ) ) + { + Gia_ObjUnsetDraftPath0(p); + return Gia_ObjSetDraftPath1(p); + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Creates a feasible path from the node to a terminal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_SatPathStart( Gia_Obj_t * p ) +{ + int RetValue; + assert( Gia_SatObjIsRoot(p) ); + Gia_SatObjXorRoot(p); + RetValue = Gia_SatPathStart_rec( p, 0, 0 ); + Gia_SatObjXorRoot(p); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaQbf.c b/yosys/abc/src/aig/gia/giaQbf.c new file mode 100644 index 00000000000..1525e7d8314 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaQbf.c @@ -0,0 +1,1250 @@ +/**CFile**************************************************************** + + FileName [giaQbf.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [QBF solver.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - October 18, 2014.] + + Revision [$Id: giaQbf.c,v 1.00 2014/10/18 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "sat/cnf/cnf.h" +#include "sat/bsat/satStore.h" +#include "misc/extra/extra.h" +#include "sat/glucose/AbcGlucose.h" +#include "misc/util/utilTruth.h" +#include "base/io/ioResub.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Qbf_Man_t_ Qbf_Man_t; +struct Qbf_Man_t_ +{ + Gia_Man_t * pGia; // original miter + int nPars; // parameter variables + int nVars; // functional variables + int fVerbose; // verbose flag + // internal variables + int iParVarBeg; // SAT var ID of the first par variable in the ver solver + sat_solver * pSatVer; // verification instance + sat_solver * pSatSyn; // synthesis instance + bmcg_sat_solver*pSatSynG; // synthesis instance + Vec_Int_t * vValues; // variable values + Vec_Int_t * vParMap; // parameter mapping + Vec_Int_t * vLits; // literals for the SAT solver + abctime clkStart; // global timeout + abctime clkSat; // SAT solver time +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Generating QBF miter to solve the induction problem.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_GenCollectFlopIndexes( char * pStr, int nLutNum, int nLutSize, int nFlops ) +{ + int nDups; + char * pTemp; + Vec_Int_t * vFlops; + assert( nLutSize * nLutNum <= nFlops ); + if ( pStr == NULL ) + return Vec_IntStartNatural( nLutNum * nLutSize ); + vFlops = Vec_IntAlloc( nLutNum * nLutSize ); + pTemp = strtok( pStr, ", " ); + while ( pTemp ) + { + int iFlop = atoi(pTemp); + if ( iFlop >= nFlops ) + { + printf( "Flop index (%d) exceeds the number of flops (%d).\n", iFlop, nFlops ); + break; + } + Vec_IntPush( vFlops, iFlop ); + pTemp = strtok( NULL, ", " ); + } + if ( Vec_IntSize(vFlops) != nLutNum * nLutSize ) + { + printf( "Gia_GenCollectFlopIndexes: Expecting %d flop indexes (instead of %d).\n", nLutNum * nLutSize, Vec_IntSize(vFlops) ); + Vec_IntFree( vFlops ); + return NULL; + } + nDups = Vec_IntCountDuplicates(vFlops); + if ( nDups ) + { + printf( "Gia_GenCollectFlopIndexes: There are %d duplicated flops in the list.\n", nDups ); + Vec_IntFree( vFlops ); + return NULL; + } + return vFlops; +} +int Gia_GenCreateMux_rec( Gia_Man_t * pNew, int * pCtrl, int nCtrl, Vec_Int_t * vData, int Shift ) +{ + int iLit0, iLit1; + if ( nCtrl == 0 ) + return Vec_IntEntry( vData, Shift ); + iLit0 = Gia_GenCreateMux_rec( pNew, pCtrl, nCtrl-1, vData, Shift ); + iLit1 = Gia_GenCreateMux_rec( pNew, pCtrl, nCtrl-1, vData, Shift + (1<<(nCtrl-1)) ); + return Gia_ManHashMux( pNew, pCtrl[nCtrl-1], iLit1, iLit0 ); +} +Vec_Int_t * Gia_GenCreateMuxes( Gia_Man_t * p, Gia_Man_t * pNew, Vec_Int_t * vFlops, int nLutNum, int nLutSize, Vec_Int_t * vParLits, int fUseRi ) +{ + Vec_Int_t * vLits = Vec_IntAlloc( nLutNum ); + int i, k, iMux, iFlop, pCtrl[16]; + // add MUXes for each group of flops + assert( Vec_IntSize(vFlops) == nLutNum * nLutSize ); + for ( i = 0; i < nLutNum; i++ ) + { + for ( k = 0; k < nLutSize; k++ ) + { + iFlop = Vec_IntEntry(vFlops, i * nLutSize + k); + assert( iFlop >= 0 && iFlop < Gia_ManRegNum(p) ); + if ( fUseRi ) + pCtrl[k] = Gia_ManRi(p, iFlop)->Value; + else + pCtrl[k] = Gia_ManRo(p, iFlop)->Value; + } + iMux = Gia_GenCreateMux_rec( pNew, pCtrl, nLutSize, vParLits, i * (1 << nLutSize) ); + Vec_IntPush( vLits, iMux ); + } + return vLits; +} +Gia_Man_t * Gia_GenQbfMiter( Gia_Man_t * p, int nFrames, int nLutNum, int nLutSize, char * pStr, int fUseOut, int fVerbose ) +{ + Gia_Obj_t * pObj; + Gia_Man_t * pTemp, * pNew; + int i, iMiter, iLut0, iLut1, nPars = nLutNum * (1 << nLutSize); + Vec_Int_t * vLits0, * vLits1, * vParLits; + Vec_Int_t * vFlops = Gia_GenCollectFlopIndexes( pStr, nLutNum, nLutSize, Gia_ManRegNum(p) ); + // collect parameter literals (data vars) + vParLits = Vec_IntAlloc( nPars ); + for ( i = 0; i < nPars; i++ ) + Vec_IntPush( vParLits, i ? Abc_Var2Lit(i+1, 0) : 1 ); + // create new manager + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManConst0(p)->Value = 0; + for ( i = 0; i < nPars; i++ ) + Gia_ManAppendCi( pNew ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + vLits0 = Gia_GenCreateMuxes( p, pNew, vFlops, nLutNum, nLutSize, vParLits, 0 ); + vLits1 = Gia_GenCreateMuxes( p, pNew, vFlops, nLutNum, nLutSize, vParLits, 1 ); + // create miter output + //iMiter = Gia_ManHashAnd( pNew, Vec_IntEntry(vLits0, 0), Abc_LitNot(Vec_IntEntry(vLits1, 0)) ); + /////////////////////////////////////////////////////////////////////////// + iLut0 = Vec_IntEntry(vLits0, 0); + iLut1 = Vec_IntEntry(vLits1, 0); + if ( fUseOut ) + { + Gia_Obj_t * pObjPoLast = Gia_ManPo( p, Gia_ManPoNum(p)-1 ); + int iOut = Abc_LitNotCond( Gia_ObjFanin0Copy(pObjPoLast), 0 ); + iLut1 = Gia_ManHashAnd( pNew, iLut1, Abc_LitNot(iOut) ); + } + iMiter = Gia_ManHashAnd( pNew, iLut0, Abc_LitNot(iLut1) ); + /////////////////////////////////////////////////////////////////////////// + iMiter = Gia_ManHashAnd( pNew, Abc_LitNot(iMiter), Abc_Var2Lit(1, 0) ); + Gia_ManAppendCo( pNew, iMiter ); + // cleanup + Vec_IntFree( vLits0 ); + Vec_IntFree( vLits1 ); + Vec_IntFree( vFlops ); + Vec_IntFree( vParLits ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Generate miter for the encoding problem.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_Gen2CreateMux_rec( Gia_Man_t * pNew, int * pCtrl, int nCtrl, Vec_Int_t * vData, int Shift ) +{ + int iLit0, iLit1; + if ( nCtrl == 0 ) + return Vec_IntEntry( vData, Shift ); + iLit0 = Gia_Gen2CreateMux_rec( pNew, pCtrl, nCtrl-1, vData, Shift ); + iLit1 = Gia_Gen2CreateMux_rec( pNew, pCtrl, nCtrl-1, vData, Shift + (1<<(nCtrl-1)) ); + return Gia_ManHashMux( pNew, pCtrl[nCtrl-1], iLit1, iLit0 ); +} +Vec_Int_t * Gia_Gen2CreateMuxes( Gia_Man_t * pNew, int nLutSize, int nLutNum, Vec_Int_t * vPLits, Vec_Int_t * vXLits ) +{ + Vec_Int_t * vLits = Vec_IntAlloc( nLutNum ); + int i, iMux; + // add MUXes for each group of flops + assert( Vec_IntSize(vPLits) == nLutNum * (1 << nLutSize) ); + assert( Vec_IntSize(vXLits) == nLutSize ); + for ( i = 0; i < nLutNum; i++ ) + { + iMux = Gia_Gen2CreateMux_rec( pNew, Vec_IntArray(vXLits), nLutSize, vPLits, i * (1 << nLutSize) ); + Vec_IntPush( vLits, iMux ); + } + return vLits; +} +Gia_Man_t * Gia_Gen2CreateMiter( int nLutSize, int nLutNum ) +{ + // |<-- PVars(0)-->|...|<-- PVars(nLutNum-1)-->|<-- XVars-->|<-- YVars-->| + Vec_Int_t * vPLits = Vec_IntAlloc( nLutNum * (1 << nLutSize) ); + Vec_Int_t * vXLits = Vec_IntAlloc( nLutSize ); + Vec_Int_t * vYLits = Vec_IntAlloc( nLutSize ); + Vec_Int_t * vXYLits = Vec_IntAlloc( nLutSize ); + Vec_Int_t * vXRes, * vYRes, * vXYRes; + Vec_Int_t * vXYRes2 = Vec_IntAlloc( 2 * nLutNum ); + Gia_Man_t * pTemp, * pNew = Gia_ManStart( 1000 ); int i, k, v, Cond, Res; + pNew->pName = Abc_UtilStrsav( "homoqbf" ); + Gia_ManHashAlloc( pNew ); + for ( i = 0; i < nLutNum * (1 << nLutSize); i++ ) + Vec_IntPush( vPLits, Gia_ManAppendCi(pNew) ); + for ( i = 0; i < nLutSize; i++ ) + Vec_IntPush( vXLits, Gia_ManAppendCi(pNew) ); + for ( i = 0; i < nLutSize; i++ ) + Vec_IntPush( vYLits, Gia_ManAppendCi(pNew) ); + for ( i = 0; i < nLutSize; i++ ) + Vec_IntPush( vXYLits, Abc_LitNot(Gia_ManHashAnd(pNew, Vec_IntEntry(vXLits, i), Vec_IntEntry(vYLits, i))) ); + vXRes = Gia_Gen2CreateMuxes( pNew, nLutSize, nLutNum, vPLits, vXLits ); + vYRes = Gia_Gen2CreateMuxes( pNew, nLutSize, nLutNum, vPLits, vYLits ); + vXYRes = Gia_Gen2CreateMuxes( pNew, nLutSize, nLutNum, vPLits, vXYLits ); + for ( i = 0; i < nLutNum; i++ ) + { + Vec_IntPush( vXYRes2, Vec_IntEntry(vXYRes, i) ); + Vec_IntPush( vXYRes2, Abc_LitNot(Gia_ManHashAnd(pNew, Vec_IntEntry(vXRes, i), Vec_IntEntry(vYRes, i))) ); + } + Res = Gia_ManHashDualMiter( pNew, vXYRes2 ); + // uniqueness of codes + for ( i = 0; i < (1 << nLutSize); i++ ) + { + Vec_Int_t * vCondA = Vec_IntAlloc( nLutNum ); + Vec_Int_t * vCondB = Vec_IntAlloc( nLutNum ); + for ( v = 0; v < nLutNum; v++ ) + Vec_IntPush( vCondA, Vec_IntEntry(vPLits, v*(1 << nLutSize)+i) ); + for ( k = i+1; k < (1 << nLutSize); k++ ) + { + Vec_IntClear( vCondB ); + for ( v = 0; v < nLutNum; v++ ) + { + Vec_IntPush( vCondB, Vec_IntEntry(vCondA, v) ); + Vec_IntPush( vCondB, Vec_IntEntry(vPLits, v*(1 << nLutSize)+k) ); + } + Cond = Gia_ManHashDualMiter( pNew, vCondB ); + Res = Gia_ManHashOr( pNew, Res, Abc_LitNot(Cond) ); + } + Vec_IntFree( vCondA ); + Vec_IntFree( vCondB ); + } + Gia_ManAppendCo( pNew, Abc_LitNot(Res) ); + Gia_ManHashStop( pNew ); + Vec_IntFree( vPLits ); + Vec_IntFree( vXLits ); + Vec_IntFree( vYLits ); + Vec_IntFree( vXYLits ); + Vec_IntFree( vXRes ); + Vec_IntFree( vYRes ); + Vec_IntFree( vXYRes ); + Vec_IntFree( vXYRes2 ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + printf( "Generated QBF miter with %d parameters, %d functional variables, and %d AIG nodes.\n", + nLutNum * (1 << nLutSize), 2*nLutSize, Gia_ManAndNum(pNew) ); + return pNew; +} +int Gia_Gen2CodeOne( int nLutSize, int nLutNum, Vec_Int_t * vCode, int x ) +{ + int k, Code = 0; + for ( k = 0; k < nLutNum; k++ ) + if ( Vec_IntEntry(vCode, k*(1 << nLutSize)+x) ) + Code |= (1 << k); + return Code; +} +word * Gia_Gen2CodeOneP( int nLutSize, int nLutNum, Vec_Int_t * vCode, int x ) +{ + word * pRes = ABC_CALLOC( word, Abc_Bit6WordNum(nLutNum) ); + int k; + for ( k = 0; k < nLutNum; k++ ) + if ( Vec_IntEntry(vCode, k*(1 << nLutSize)+x) ) + Abc_InfoSetBit( (unsigned *)pRes, k ); + return pRes; +} +void Gia_Gen2CodePrint( int nLutSize, int nLutNum, Vec_Int_t * vCode ) +{ + // |<-- PVars(0)-->|...|<-- PVars(nLutNum-1)-->| + int i, n, nPairs = 16; + printf( "%d-input %d-output code table:\n", nLutSize, nLutNum ); + for ( i = 0; i < (1 << nLutSize); i++ ) + { + word * CodeX = Gia_Gen2CodeOneP( nLutSize, nLutNum, vCode, i ); + printf( "%3d ", i ); + Extra_PrintBinary( stdout, (unsigned *)&i, nLutSize ); + printf( " --> " ); + if ( nLutNum <= 16 ) + printf( "%5d ", (int)CodeX[0] ); + Extra_PrintBinary( stdout, (unsigned *)CodeX, nLutNum ); + printf( "\n" ); + ABC_FREE( CodeX ); + } + // create several different pairs + srand( time(NULL) ); + printf( "Simulation of the encoding with %d random pairs:\n", nPairs ); + for ( n = 0; n < nPairs; n++ ) + { + unsigned MaskIn = Abc_InfoMask( nLutSize ); + int NumX = 0, NumY = 0, NumXY, nWords = Abc_Bit6WordNum(nLutNum); + word * CodeX, * CodeY, * CodeXY; + word * CodeXCodeY = ABC_CALLOC( word, nWords ); + while ( NumX == NumY ) + { + NumX = rand() % (1 << nLutSize); + NumY = rand() % (1 << nLutSize); + NumXY = MaskIn & ~(NumX & NumY); + } + CodeX = Gia_Gen2CodeOneP( nLutSize, nLutNum, vCode, NumX ); + CodeY = Gia_Gen2CodeOneP( nLutSize, nLutNum, vCode, NumY ); + CodeXY = Gia_Gen2CodeOneP( nLutSize, nLutNum, vCode, NumXY ); + Abc_TtAnd( CodeXCodeY, CodeX, CodeY, nWords, 1 ); + if ( nLutNum < 64*nWords ) + CodeXCodeY[nWords-1] &= Abc_Tt6Mask(nLutNum % 64); + + printf( "%2d :", n ); + printf( " x =%3d ", NumX ); + Extra_PrintBinary( stdout,(unsigned *) &NumX, nLutSize ); + printf( " y =%3d ", NumY ); + Extra_PrintBinary( stdout, (unsigned *)&NumY, nLutSize ); + printf( " nand =%3d ", NumXY ); + Extra_PrintBinary( stdout, (unsigned *)&NumXY, nLutSize ); + printf( " " ); + + printf( " c(x) = " ); + Extra_PrintBinary( stdout, (unsigned *)CodeX, nLutNum ); + printf( " c(y) = " ); + Extra_PrintBinary( stdout, (unsigned *)CodeY, nLutNum ); + printf( " c(nand) = " ); + Extra_PrintBinary( stdout, (unsigned *)CodeXY, nLutNum ); + printf( " nand(c(x),c(y)) = " ); + Extra_PrintBinary( stdout, (unsigned *)CodeXCodeY, nLutNum ); + printf( " " ); + + printf( "%s", Abc_TtEqual(CodeXCodeY, CodeXY, nWords) ? "yes" : "no" ); + printf( "\n" ); + + ABC_FREE( CodeX ); + ABC_FREE( CodeY ); + ABC_FREE( CodeXY ); + ABC_FREE( CodeXCodeY ); + } +} +void Gia_Gen2CodeTest() +{ + int i, nLutSize = 1, nLutNum = 2; + Vec_Int_t * vCode = Vec_IntAlloc( (1 << nLutSize) * nLutNum ); + srand( time(NULL) ); + for ( i = 0; i < (1 << nLutSize) * nLutNum; i++ ) + Vec_IntPush( vCode, rand() & 1 ); + Gia_Gen2CodePrint( nLutSize, nLutNum, vCode ); + Vec_IntFree( vCode ); +} + +/**Function************************************************************* + + Synopsis [Naive way to enumerate SAT assignments.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSatEnum( Gia_Man_t * pGia, int nConfLimit, int nTimeOut, int fVerbose ) +{ + Cnf_Dat_t * pCnf; + sat_solver * pSat; + Vec_Int_t * vLits; + int i, iLit, iParVarBeg, Iter; + int nSolutions = 0, RetValue = 0; + abctime clkStart = Abc_Clock(); + pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( pGia, 8, 0, 1, 0, 0 ); + pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + iParVarBeg = pCnf->nVars - Gia_ManPiNum(pGia);// - 1; + Cnf_DataFree( pCnf ); + // iterate through the SAT assignment + vLits = Vec_IntAlloc( Gia_ManPiNum(pGia) ); + for ( Iter = 1 ; ; Iter++ ) + { + int status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, 0, 0, 0 ); + if ( status == l_False ) { RetValue = 1; break; } + if ( status == l_Undef ) { RetValue = 0; break; } + nSolutions++; + // extract SAT assignment + Vec_IntClear( vLits ); + for ( i = 0; i < Gia_ManPiNum(pGia); i++ ) + Vec_IntPush( vLits, Abc_Var2Lit(iParVarBeg+i, sat_solver_var_value(pSat, iParVarBeg+i)) ); + if ( fVerbose ) + { + printf( "%5d : ", Iter ); + Vec_IntForEachEntry( vLits, iLit, i ) + printf( "%d", !Abc_LitIsCompl(iLit) ); + printf( "\n" ); + } + // add clause + if ( !sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ) ) + { RetValue = 1; break; } + if ( nTimeOut && (Abc_Clock() - clkStart)/CLOCKS_PER_SEC >= nTimeOut ) { RetValue = 0; break; } + } + sat_solver_delete( pSat ); + Vec_IntFree( vLits ); + if ( nTimeOut && (Abc_Clock() - clkStart)/CLOCKS_PER_SEC >= nTimeOut ) + printf( "Enumerated %d assignments when timeout (%d sec) was reached. ", nSolutions, nTimeOut ); + else if ( nConfLimit && !RetValue ) + printf( "Enumerated %d assignments when conflict limit (%d) was reached. ", nSolutions, nConfLimit ); + else + printf( "Enumerated the complete set of %d assignments. ", nSolutions ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Dumps the original problem in QDIMACS format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_QbfDumpFile( Gia_Man_t * pGia, int nPars ) +{ + // original problem: \exists p \forall x \exists y. M(p,x,y) + // negated problem: \forall p \exists x \exists y. !M(p,x,y) + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( pGia, 8, 0, 1, 0, 0 ); + Vec_Int_t * vVarMap, * vForAlls, * vExists; + Gia_Obj_t * pObj; + char * pFileName; + int i, Entry; + // create var map + vVarMap = Vec_IntStart( pCnf->nVars ); + Gia_ManForEachCi( pGia, pObj, i ) + if ( i < nPars ) + Vec_IntWriteEntry( vVarMap, pCnf->pVarNums[Gia_ManCiIdToId(pGia, i)], 1 ); + // create various maps + vForAlls = Vec_IntAlloc( nPars ); + vExists = Vec_IntAlloc( Gia_ManCiNum(pGia) - nPars ); + Vec_IntForEachEntry( vVarMap, Entry, i ) + if ( Entry ) + Vec_IntPush( vForAlls, i ); + else + Vec_IntPush( vExists, i ); + // generate CNF + pFileName = Extra_FileNameGenericAppend( pGia->pSpec, ".qdimacs" ); + Cnf_DataWriteIntoFile( pCnf, pFileName, 0, vForAlls, vExists ); + Cnf_DataFree( pCnf ); + Vec_IntFree( vForAlls ); + Vec_IntFree( vExists ); + Vec_IntFree( vVarMap ); + printf( "The 2QBF formula was written into file \"%s\".\n", pFileName ); +} +void Gia_QbfDumpFileInv( Gia_Man_t * pGia, int nPars ) +{ + // original problem: \exists p \forall x \exists y. M(p,x,y) + // negated problem: \forall p \exists x \exists y. !M(p,x,y) + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( pGia, 8, 0, 1, 0, 0 ); + Vec_Int_t * vVarMap, * vForAlls, * vExists1, * vExists2; + Gia_Obj_t * pObj; + char * pFileName; + int i, Entry; + // complement the last clause + //int * pLit = pCnf->pClauses[pCnf->nClauses] - 1; *pLit ^= 1; + // create var map + vVarMap = Vec_IntStart( pCnf->nVars ); + Gia_ManForEachCi( pGia, pObj, i ) + Vec_IntWriteEntry( vVarMap, pCnf->pVarNums[Gia_ManCiIdToId(pGia, i)], i < nPars ? 1 : 2 ); + // create various maps + vExists1 = Vec_IntAlloc( nPars ); + vForAlls = Vec_IntAlloc( Gia_ManCiNum(pGia) - nPars ); + vExists2 = Vec_IntAlloc( pCnf->nVars - Gia_ManCiNum(pGia) ); + Vec_IntForEachEntry( vVarMap, Entry, i ) + if ( Entry == 1 ) + Vec_IntPush( vExists1, i ); + else if ( Entry == 2 ) + Vec_IntPush( vForAlls, i ); + else + Vec_IntPush( vExists2, i ); + // generate CNF + pFileName = Extra_FileNameGenericAppend( pGia->pSpec, ".qdimacs" ); + Cnf_DataWriteIntoFileInv( pCnf, pFileName, 0, vExists1, vForAlls, vExists2 ); + Cnf_DataFree( pCnf ); + Vec_IntFree( vExists1 ); + Vec_IntFree( vForAlls ); + Vec_IntFree( vExists2 ); + Vec_IntFree( vVarMap ); + printf( "The 2QBF formula was written into file \"%s\".\n", pFileName ); +} + + + + +/**Function************************************************************* + + Synopsis [Generate one SAT assignment of the problem.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Qbf_Man_t * Gia_QbfAlloc( Gia_Man_t * pGia, int nPars, int fGlucose, int fVerbose ) +{ + Qbf_Man_t * p; + Cnf_Dat_t * pCnf; + Gia_ObjFlipFaninC0( Gia_ManPo(pGia, 0) ); + pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( pGia, 8, 0, 1, 0, 0 ); + Gia_ObjFlipFaninC0( Gia_ManPo(pGia, 0) ); + p = ABC_CALLOC( Qbf_Man_t, 1 ); + p->clkStart = Abc_Clock(); + p->pGia = pGia; + p->nPars = nPars; + p->nVars = Gia_ManPiNum(pGia) - nPars; + p->fVerbose = fVerbose; + p->iParVarBeg = pCnf->nVars - Gia_ManPiNum(pGia);// - 1; + p->pSatVer = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + p->pSatSyn = sat_solver_new(); + p->pSatSynG = fGlucose ? bmcg_sat_solver_start() : NULL; + p->vValues = Vec_IntAlloc( Gia_ManPiNum(pGia) ); + p->vParMap = Vec_IntStartFull( nPars ); + p->vLits = Vec_IntAlloc( nPars ); + sat_solver_setnvars( p->pSatSyn, nPars ); + if ( p->pSatSynG ) bmcg_sat_solver_set_nvars( p->pSatSynG, nPars ); + Cnf_DataFree( pCnf ); + return p; +} +void Gia_QbfFree( Qbf_Man_t * p ) +{ + sat_solver_delete( p->pSatVer ); + sat_solver_delete( p->pSatSyn ); + if ( p->pSatSynG ) bmcg_sat_solver_stop( p->pSatSynG ); + Vec_IntFree( p->vLits ); + Vec_IntFree( p->vValues ); + Vec_IntFree( p->vParMap ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Create and add one cofactor.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_QbfQuantifyOne( Gia_Man_t * p, int iVar, int fAndAll, int fOrAll ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + Vec_Int_t * vCofs; + int i, c; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManHashAlloc( pNew ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + // compute cofactors + vCofs = Vec_IntAlloc( 2 * Gia_ManPoNum(p) ); + for ( c = 0; c < 2; c++ ) + { + Gia_ManPi(p, iVar)->Value = c; + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachPo( p, pObj, i ) + Vec_IntPush( vCofs, Gia_ObjFanin0Copy(pObj) ); + } + if ( fAndAll ) + { + for ( i = 0; i < Gia_ManPoNum(p); i++ ) + Gia_ManAppendCo( pNew, Gia_ManHashAnd(pNew, Vec_IntEntry(vCofs, i), Vec_IntEntry(vCofs, Gia_ManPoNum(p)+i)) ); + } + else if ( fOrAll ) + { + for ( i = 0; i < Gia_ManPoNum(p); i++ ) + Gia_ManAppendCo( pNew, Gia_ManHashOr(pNew, Vec_IntEntry(vCofs, i), Vec_IntEntry(vCofs, Gia_ManPoNum(p)+i)) ); + } + else + { + Vec_IntForEachEntry( vCofs, c, i ) + Gia_ManAppendCo( pNew, c ); + } + Vec_IntFree( vCofs ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} +Gia_Man_t * Gia_QbfQuantifyAll( Gia_Man_t * p, int nPars, int fAndAll, int fOrAll ) +{ + Gia_Man_t * pNew, * pTemp; int v; + pNew = Gia_ManDup( p ); + for ( v = Gia_ManPiNum(p) - 1; v >= nPars; v-- ) + { + pNew = Gia_QbfQuantifyOne( pTemp = pNew, v, fAndAll, fOrAll ); + Gia_ManStop( pTemp ); + } + return pNew; +} + +/**Function************************************************************* + + Synopsis [Create and add one cofactor.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_QbfCofactor( Gia_Man_t * p, int nPars, Vec_Int_t * vValues, Vec_Int_t * vParMap ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; int i; + assert( Gia_ManPiNum(p) == nPars + Vec_IntSize(vValues) ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManHashAlloc( pNew ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachPi( p, pObj, i ) + if ( i < nPars ) + { + pObj->Value = Gia_ManAppendCi(pNew); + if ( Vec_IntEntry(vParMap, i) != -1 ) + pObj->Value = Vec_IntEntry(vParMap, i); + } + else + pObj->Value = Vec_IntEntry(vValues, i - nPars); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + assert( Gia_ManPiNum(pNew) == nPars ); + return pNew; +} +/* +int Gia_QbfAddCofactor( Qbf_Man_t * p, Gia_Man_t * pCof ) +{ + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( pCof, 8, 0, 1, 0, 0 ); + int i, iFirstVar = sat_solver_nvars(p->pSatSyn) + pCnf->nVars - Gia_ManPiNum(pCof);// - 1; + pCnf->pMan = NULL; + Cnf_DataLift( pCnf, sat_solver_nvars(p->pSatSyn) ); + for ( i = 0; i < pCnf->nClauses; i++ ) + if ( !sat_solver_addclause( p->pSatSyn, pCnf->pClauses[i], pCnf->pClauses[i+1] ) ) + { + Cnf_DataFree( pCnf ); + return 0; + } + Cnf_DataFree( pCnf ); + // add connection clauses + for ( i = 0; i < Gia_ManPiNum(p->pGia); i++ ) + if ( !sat_solver_add_buffer( p->pSatSyn, i, iFirstVar+i, 0 ) ) + return 0; + return 1; +} +*/ +void Cnf_SpecialDataLift( Cnf_Dat_t * p, int nVarsPlus, int firstPiVar, int lastPiVar) +{ + int v, var; + for ( v = 0; v < p->nLiterals; v++ ) + { + var = p->pClauses[0][v] / 2; + if (var < firstPiVar || var >= lastPiVar) + p->pClauses[0][v] += 2*nVarsPlus; + else + p->pClauses[0][v] -= 2*firstPiVar; + } +} + +int Gia_QbfAddCofactor( Qbf_Man_t * p, Gia_Man_t * pCof ) +{ + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( pCof, 8, 0, 1, 0, 0 ); + int i, useold = 0; + int iFirstVar = useold ? sat_solver_nvars(p->pSatSyn) + pCnf->nVars - Gia_ManPiNum(pCof) : pCnf->nVars - Gia_ManPiNum(pCof); //-1 + pCnf->pMan = NULL; + + if (useold) + Cnf_DataLift( pCnf, sat_solver_nvars(p->pSatSyn) ); + else + Cnf_SpecialDataLift( pCnf, sat_solver_nvars(p->pSatSyn), iFirstVar, iFirstVar + Gia_ManPiNum(p->pGia) ); + + for ( i = 0; i < pCnf->nClauses; i++ ) + if ( !sat_solver_addclause( p->pSatSyn, pCnf->pClauses[i], pCnf->pClauses[i+1] ) ) + { + Cnf_DataFree( pCnf ); + return 0; + } + Cnf_DataFree( pCnf ); + // add connection clauses + if (useold) + for ( i = 0; i < Gia_ManPiNum(p->pGia); i++ ) + if ( !sat_solver_add_buffer( p->pSatSyn, i, iFirstVar+i, 0 ) ) + return 0; + return 1; +} +int Gia_QbfAddCofactorG( Qbf_Man_t * p, Gia_Man_t * pCof ) +{ + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( pCof, 8, 0, 1, 0, 0 ); + int i, iFirstVar = pCnf->nVars - Gia_ManPiNum(pCof); //-1 + pCnf->pMan = NULL; + Cnf_SpecialDataLift( pCnf, bmcg_sat_solver_varnum(p->pSatSynG), iFirstVar, iFirstVar + Gia_ManPiNum(p->pGia) ); + for ( i = 0; i < pCnf->nClauses; i++ ) + if ( !bmcg_sat_solver_addclause( p->pSatSynG, pCnf->pClauses[i], pCnf->pClauses[i+1]-pCnf->pClauses[i] ) ) + { + Cnf_DataFree( pCnf ); + return 0; + } + Cnf_DataFree( pCnf ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Extract SAT assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_QbfOnePattern( Qbf_Man_t * p, Vec_Int_t * vValues ) +{ + int i; + Vec_IntClear( vValues ); + for ( i = 0; i < p->nPars; i++ ) + Vec_IntPush( vValues, p->pSatSynG ? bmcg_sat_solver_read_cex_varvalue(p->pSatSynG, i) : sat_solver_var_value(p->pSatSyn, i) ); +} +void Gia_QbfPrint( Qbf_Man_t * p, Vec_Int_t * vValues, int Iter ) +{ + printf( "%5d : ", Iter ); + assert( Vec_IntSize(vValues) == p->nVars ); + Vec_IntPrintBinary( vValues ); printf( " " ); + printf( "Var =%7d ", p->pSatSynG ? bmcg_sat_solver_varnum(p->pSatSynG) : sat_solver_nvars(p->pSatSyn) ); + printf( "Cla =%7d ", p->pSatSynG ? bmcg_sat_solver_clausenum(p->pSatSynG) : sat_solver_nclauses(p->pSatSyn) ); + printf( "Conf =%9d ", p->pSatSynG ? bmcg_sat_solver_conflictnum(p->pSatSynG) : sat_solver_nconflicts(p->pSatSyn) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); +} + +/**Function************************************************************* + + Synopsis [Generate one SAT assignment in terms of functional vars.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_QbfVerify( Qbf_Man_t * p, Vec_Int_t * vValues ) +{ + int i, Entry, RetValue; + assert( Vec_IntSize(vValues) == p->nPars ); + Vec_IntClear( p->vLits ); + Vec_IntForEachEntry( vValues, Entry, i ) + Vec_IntPush( p->vLits, Abc_Var2Lit(p->iParVarBeg+i, !Entry) ); + RetValue = sat_solver_solve( p->pSatVer, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits), 0, 0, 0, 0 ); + if ( RetValue == l_True ) + { + Vec_IntClear( vValues ); + for ( i = 0; i < p->nVars; i++ ) + Vec_IntPush( vValues, sat_solver_var_value(p->pSatVer, p->iParVarBeg+p->nPars+i) ); + } + return RetValue == l_True ? 1 : 0; +} + +/**Function************************************************************* + + Synopsis [Constraint learning.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_QbfAddSpecialConstr( Qbf_Man_t * p ) +{ + int i, status, Lits[2]; + for ( i = 0; i < 4*11; i++ ) + if ( i % 4 == 0 ) + { + assert( Vec_IntEntry(p->vParMap, i) == -1 ); + Vec_IntWriteEntry( p->vParMap, i, (i % 4) == 3 ); + Lits[0] = Abc_Var2Lit( i, (i % 4) != 3 ); + status = sat_solver_addclause( p->pSatSyn, Lits, Lits+1 ); + assert( status ); + } +} +void Gia_QbfLearnConstraint( Qbf_Man_t * p, Vec_Int_t * vValues ) +{ + int i, status, Entry, Lits[2]; + assert( Vec_IntSize(vValues) == p->nPars ); + printf( " Pattern " ); + Vec_IntPrintBinary( vValues ); + printf( "\n" ); + Vec_IntForEachEntry( vValues, Entry, i ) + { + Lits[0] = Abc_Var2Lit( i, Entry ); + status = sat_solver_solve( p->pSatSyn, Lits, Lits+1, 0, 0, 0, 0 ); + printf( " Var =%4d ", i ); + if ( status != l_True ) + { + printf( "UNSAT\n" ); + Lits[0] = Abc_LitNot(Lits[0]); + status = sat_solver_addclause( p->pSatSyn, Lits, Lits+1 ); + assert( status ); + continue; + } + Gia_QbfOnePattern( p, p->vLits ); + Vec_IntPrintBinary( p->vLits ); + printf( "\n" ); + } + assert( Vec_IntSize(vValues) == p->nPars ); +} + +/**Function************************************************************* + + Synopsis [Performs QBF solving using an improved algorithm.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_QbfSolve( Gia_Man_t * pGia, int nPars, int nIterLimit, int nConfLimit, int nTimeOut, int nEncVars, int fGlucose, int fVerbose ) +{ + Qbf_Man_t * p = Gia_QbfAlloc( pGia, nPars, fGlucose, fVerbose ); + Gia_Man_t * pCof; + int i, status, RetValue = 0; + abctime clk; +// Gia_QbfAddSpecialConstr( p ); + if ( fVerbose ) + printf( "Solving QBF for \"%s\" with %d parameters, %d variables and %d AIG nodes.\n", + Gia_ManName(pGia), p->nPars, p->nVars, Gia_ManAndNum(pGia) ); + assert( Gia_ManRegNum(pGia) == 0 ); + Vec_IntFill( p->vValues, nPars, 0 ); + for ( i = 0; Gia_QbfVerify(p, p->vValues); i++ ) + { + // generate next constraint + assert( Vec_IntSize(p->vValues) == p->nVars ); + pCof = Gia_QbfCofactor( pGia, nPars, p->vValues, p->vParMap ); + status = p->pSatSynG ? Gia_QbfAddCofactorG( p, pCof ) : Gia_QbfAddCofactor( p, pCof ); + Gia_ManStop( pCof ); + if ( status == 0 ) { RetValue = 1; break; } + // synthesize next assignment + clk = Abc_Clock(); + if ( p->pSatSynG ) + status = bmcg_sat_solver_solve( p->pSatSynG, NULL, 0 ); + else + status = sat_solver_solve( p->pSatSyn, NULL, NULL, (ABC_INT64_T)nConfLimit, 0, 0, 0 ); + p->clkSat += Abc_Clock() - clk; + if ( fVerbose ) + Gia_QbfPrint( p, p->vValues, i ); + if ( status == l_False ) { RetValue = 1; break; } + if ( status == l_Undef ) { RetValue = -1; break; } + // extract SAT assignment + Gia_QbfOnePattern( p, p->vValues ); + assert( Vec_IntSize(p->vValues) == p->nPars ); + // examine variables +// Gia_QbfLearnConstraint( p, p->vValues ); +// Vec_IntPrintBinary( p->vValues ); printf( "\n" ); + if ( nIterLimit && i+1 == nIterLimit ) { RetValue = -1; break; } + if ( nTimeOut && (Abc_Clock() - p->clkStart)/CLOCKS_PER_SEC >= nTimeOut ) { RetValue = -1; break; } + } + if ( RetValue == 0 ) + { + int nZeros = Vec_IntCountZero( p->vValues ); + printf( "Parameters: " ); + assert( Vec_IntSize(p->vValues) == nPars ); + Vec_IntPrintBinary( p->vValues ); + printf( " Statistics: 0=%d 1=%d\n", nZeros, Vec_IntSize(p->vValues) - nZeros ); + if ( nEncVars ) + { + int nBits = Vec_IntSize(p->vValues)/(1 << nEncVars); + assert( Vec_IntSize(p->vValues) == (1 << nEncVars) * nBits ); + Gia_Gen2CodePrint( nEncVars, nBits, p->vValues ); + } + } + if ( RetValue == -1 && nTimeOut && (Abc_Clock() - p->clkStart)/CLOCKS_PER_SEC >= nTimeOut ) + printf( "The problem timed out after %d sec. ", nTimeOut ); + else if ( RetValue == -1 && nConfLimit ) + printf( "The problem aborted after %d conflicts. ", nConfLimit ); + else if ( RetValue == -1 && nIterLimit ) + printf( "The problem aborted after %d iterations. ", nIterLimit ); + else if ( RetValue == 1 ) + printf( "The problem is UNSAT after %d iterations. ", i ); + else + printf( "The problem is SAT after %d iterations. ", i ); + if ( fVerbose ) + { + printf( "\n" ); + Abc_PrintTime( 1, "SAT ", p->clkSat ); + Abc_PrintTime( 1, "Other", Abc_Clock() - p->clkStart - p->clkSat ); + Abc_PrintTime( 1, "TOTAL", Abc_Clock() - p->clkStart ); + } + else + Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); + Gia_QbfFree( p ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Derive the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +sat_solver * Gia_ManGenSolver( Gia_Man_t * p, Vec_Int_t * vInsOuts, int nIns ) +{ + Gia_Obj_t * pObj; int i, nObjs = Gia_ManObjNum(p); + sat_solver * pSat = sat_solver_new(); + sat_solver_setnvars( pSat, 2 * nObjs ); + Gia_ManIncrementTravId(p); + Gia_ManForEachObjVecStart( vInsOuts, p, pObj, i, nIns ) + Gia_ObjSetTravIdCurrent(p, pObj); + Gia_ManForEachAnd( p, pObj, i ) + if ( !Gia_ObjIsTravIdCurrent(p, pObj) ) + sat_solver_add_and( pSat, i, Gia_ObjFaninId0(pObj, i), Gia_ObjFaninId1(pObj, i), Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); + Gia_ManForEachAnd( p, pObj, i ) + sat_solver_add_and( pSat, nObjs+i, nObjs+Gia_ObjFaninId0(pObj, i), nObjs+Gia_ObjFaninId1(pObj, i), Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj), 0 ); + Gia_ManForEachCi( p, pObj, i ) + if ( !Gia_ObjIsTravIdCurrent(p, pObj) ) + sat_solver_add_buffer( pSat, nObjs+Gia_ObjId(p, pObj), Gia_ObjId(p, pObj), 0 ); + Gia_ManForEachCo( p, pObj, i ) + if ( Gia_ObjFaninId0p(p, pObj) > 0 ) { + sat_solver_add_buffer( pSat, Gia_ObjId(p, pObj), Gia_ObjFaninId0p(p, pObj), Gia_ObjFaninC0(pObj) ); + sat_solver_add_buffer( pSat, nObjs+Gia_ObjId(p, pObj), nObjs+Gia_ObjFaninId0p(p, pObj), Gia_ObjFaninC0(pObj) ); + sat_solver_add_buffer( pSat, nObjs+Gia_ObjId(p, pObj), Gia_ObjId(p, pObj), 0 ); + } + return pSat; +} +Vec_Int_t * Gia_ManGenCombs( Gia_Man_t * p, Vec_Int_t * vInsOuts, int nIns, int fVerbose ) +{ + int nTimeOut = 600, nConfLimit = 1000000; + int i, iSatVar, Iter, Mask, nSolutions = 0, RetValue = 0; + abctime clkStart = Abc_Clock(); + sat_solver * pSat = Gia_ManGenSolver( p, vInsOuts, nIns ); + Vec_Int_t * vLits = Vec_IntAlloc( 100 ); + Vec_Int_t * vRes = Vec_IntAlloc( 1000 ); + for ( Iter = 0; Iter < 1000000; Iter++ ) + { + int status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, 0, 0, 0 ); + if ( status == l_False ) { RetValue = 1; break; } + if ( status == l_Undef ) { RetValue = 0; break; } + nSolutions++; + // extract SAT assignment + Mask = 0; + Vec_IntClear( vLits ); + Vec_IntForEachEntry( vInsOuts, iSatVar, i ) { + Vec_IntPush( vLits, Abc_Var2Lit(iSatVar, sat_solver_var_value(pSat, iSatVar)) ); + if ( sat_solver_var_value(pSat, iSatVar) ) + Mask |= 1 << (Vec_IntSize(vInsOuts)-1-i); + } + Vec_IntPush( vRes, Mask ); + if ( fVerbose ) + { + printf( "%5d : ", Iter ); + Vec_IntForEachEntry( vInsOuts, iSatVar, i ) { + if ( i == nIns ) printf( " " ); + printf( "%d", (Mask >> (Vec_IntSize(vInsOuts)-1-i)) & 1 ); + } + printf( "\n" ); + } + // add clause + if ( !sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ) ) + { RetValue = 1; break; } + if ( nTimeOut && (Abc_Clock() - clkStart)/CLOCKS_PER_SEC >= nTimeOut ) { RetValue = 0; break; } + } + Vec_IntSort( vRes, 0 ); + Vec_IntFree( vLits ); + sat_solver_delete( pSat ); + if ( RetValue == 0 ) + Vec_IntFreeP( &vRes ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); + return vRes; +} +void Gia_ManGenWriteRel( Vec_Int_t * vRes, int nIns, int nOuts, char * pFileName ) +{ + int i, k, Mask, nVars = nIns + nOuts; + Abc_RData_t * p2, * p = Abc_RDataStart( nIns, nOuts, Vec_IntSize(vRes) ); + Vec_IntForEachEntry( vRes, Mask, i ) { + for ( k = 0; k < nVars; k++ ) + if ( (Mask >> (nVars-1-k)) & 1 ) { // the bit is 1 + if ( k < nIns ) + Abc_RDataSetIn( p, k, i ); + else + Abc_RDataSetOut( p, 2*(k-nIns)+1, i ); + } + else { // the bit is zero + if ( k >= nIns ) + Abc_RDataSetOut( p, 2*(k-nIns), i ); + } + } + Abc_WritePla( p, pFileName, 0 ); + p2 = Abc_RData2Rel( p ); + Abc_WritePla( p2, Extra_FileNameGenericAppend(pFileName, "_rel.pla"), 1 ); + Abc_RDataStop( p2 ); + Abc_RDataStop( p ); +} +void Gia_ManGenRel2( Gia_Man_t * pGia, Vec_Int_t * vInsOuts, int nIns, char * pFileName, int fVerbose ) +{ + Vec_Int_t * vRes = Gia_ManGenCombs( pGia, vInsOuts, nIns, fVerbose ); + if ( vRes == NULL ) { + printf( "Enumerating solutions did not succeed.\n" ); + return; + } + Gia_ManGenWriteRel( vRes, nIns, Vec_IntSize(vInsOuts)-nIns, pFileName ); + Vec_IntFree( vRes ); +} + +/**Function************************************************************* + + Synopsis [Derive the SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManCollectNodeTfos( Gia_Man_t * p, int * pNodes, int nNodes ) +{ + Vec_Int_t * vTfo = Vec_IntAlloc( 100 ); + Gia_Obj_t * pObj; int i; + Gia_ManIncrementTravId( p ); + for ( i = 0; i < nNodes; i++ ) + Gia_ObjSetTravIdCurrentId( p, pNodes[i] ); + Gia_ManForEachAnd( p, pObj, i ) { + if ( Gia_ObjIsTravIdCurrentId(p, i) ) + continue; + if ( Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId0(pObj, i)) || Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId1(pObj, i)) ) + Gia_ObjSetTravIdCurrentId( p, i ), Vec_IntPush( vTfo, i ); + } + Gia_ManForEachCo( p, pObj, i ) + if ( Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId0p(p, pObj)) ) + Vec_IntPush( vTfo, Gia_ObjId(p, pObj) ); + return vTfo; +} +Vec_Int_t * Gia_ManCollectNodeTfis( Gia_Man_t * p, Vec_Int_t * vNodes ) +{ + Vec_Int_t * vTfi = Vec_IntAlloc( 100 ); + Gia_Obj_t * pObj; int i, Id; + Gia_ManIncrementTravId( p ); + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + if ( Gia_ObjIsCo(pObj) ) + Gia_ObjSetTravIdCurrentId( p, Gia_ObjFaninId0p(p, pObj) ); + Gia_ManForEachAndReverse( p, pObj, i ) { + if ( !Gia_ObjIsTravIdCurrentId(p, i) ) + continue; + Gia_ObjSetTravIdCurrentId(p, Gia_ObjFaninId0(pObj, i)); + Gia_ObjSetTravIdCurrentId(p, Gia_ObjFaninId1(pObj, i)); + } + Gia_ManForEachCiId( p, Id, i ) + if ( Gia_ObjIsTravIdCurrentId(p, Id) ) + Vec_IntPush( vTfi, Id ); + Gia_ManForEachAnd( p, pObj, i ) + if ( Gia_ObjIsTravIdCurrentId(p, i) ) + Vec_IntPush( vTfi, i ); + return vTfi; +} +Gia_Man_t * Gia_ManGenRelMiter( Gia_Man_t * pGia, Vec_Int_t * vInsOuts, int nIns ) +{ + Vec_Int_t * vTfo = Gia_ManCollectNodeTfos( pGia, Vec_IntEntryP(vInsOuts, nIns), Vec_IntSize(vInsOuts)-nIns ); + Vec_Int_t * vTfi = Gia_ManCollectNodeTfis( pGia, vTfo ); + Vec_Int_t * vInLits = Vec_IntAlloc( nIns ); + Vec_Int_t * vOutLits = Vec_IntAlloc( Vec_IntSize(vInsOuts) - nIns ); + Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, iLit = 0; + Gia_ManFillValue( pGia ); + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( pGia->pName ); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachObjVec( vTfi, pGia, pObj, i ) + if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi(pNew); + for ( i = 0; i < Vec_IntSize(vInsOuts)-nIns; i++ ) + Vec_IntPush( vInLits, Gia_ManAppendCi(pNew) ); + Gia_ManForEachObjVec( vTfi, pGia, pObj, i ) + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachObjVec( vTfo, pGia, pObj, i ) + if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + Gia_ManForEachObjVec( vInsOuts, pGia, pObj, i ) + if ( i < nIns ) + Vec_IntPush( vOutLits, pObj->Value ); + else + pObj->Value = Vec_IntEntry( vInLits, i-nIns ); + Gia_ManForEachObjVec( vTfo, pGia, pObj, i ) + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachObjVec( vTfo, pGia, pObj, i ) + if ( Gia_ObjIsCo(pObj) ) + iLit = Gia_ManHashOr( pNew, iLit, Gia_ManHashXor(pNew, Gia_ObjFanin0Copy(pObj), pObj->Value) ); + Gia_ManAppendCo( pNew, iLit ); + Vec_IntForEachEntry( vOutLits, iLit, i ) + Gia_ManAppendCo( pNew, iLit ); + Vec_IntFree( vTfo ); + Vec_IntFree( vTfi ); + Vec_IntFree( vInLits ); + Vec_IntFree( vOutLits ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia) ); + return pNew; +} +void Gia_ManPrintRelMinterm( int Mint, int nIns, int nVars ) +{ + for ( int i = 0; i < nVars; i++ ) + printf( "%s%d", i == nIns ? " ":"", (Mint >> (nVars-1-i)) & 1 ); + printf( "\n" ); +} +Vec_Int_t * Gia_ManGenIoCombs( Gia_Man_t * pGia, Vec_Int_t * vInsOuts, int nIns, int fVerbose ) +{ + abctime clkStart = Abc_Clock(); + int nTimeOut = 600, nConfLimit = 1000000; + int i, iNode, iSatVar, Iter, Mask, nSolutions = 0, RetValue = 0; + Gia_Man_t * pMiter = Gia_ManGenRelMiter( pGia, vInsOuts, nIns ); + Cnf_Dat_t * pCnf = (Cnf_Dat_t*)Mf_ManGenerateCnf( pMiter, 8, 0, 0, 0, 0 ); + sat_solver * pSat = (sat_solver*)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + int iLit = Abc_Var2Lit( 1, 0 ); // enumerating the care set (the miter output is 1) + int status = sat_solver_addclause( pSat, &iLit, &iLit + 1 ); assert( status ); + Vec_Int_t * vSatVars = Vec_IntAlloc( Vec_IntSize(vInsOuts) ); + Vec_IntForEachEntry( vInsOuts, iNode, i ) + Vec_IntPush( vSatVars, i < nIns ? 2+i : pCnf->nVars-Vec_IntSize(vInsOuts)+i ); + Vec_Int_t * vLits = Vec_IntAlloc( 100 ); + Vec_Int_t * vRes = Vec_IntAlloc( 1000 ); + for ( Iter = 0; Iter < 1000000; Iter++ ) + { + int status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, 0, 0, 0 ); + if ( status == l_False ) { RetValue = 1; break; } + if ( status == l_Undef ) { RetValue = 0; break; } + nSolutions++; + // extract SAT assignment + Mask = 0; + Vec_IntClear( vLits ); + Vec_IntForEachEntry( vSatVars, iSatVar, i ) { + Vec_IntPush( vLits, Abc_Var2Lit(iSatVar, sat_solver_var_value(pSat, iSatVar)) ); + if ( sat_solver_var_value(pSat, iSatVar) ) + Mask |= 1 << (Vec_IntSize(vInsOuts)-1-i); + } + Vec_IntPush( vRes, Mask ); + if ( 0 ) { + printf( "%5d : ", Iter ); + Gia_ManPrintRelMinterm( Mask, nIns, Vec_IntSize(vSatVars) ); + } + // add clause + if ( !sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ) ) + { RetValue = 1; break; } + if ( nTimeOut && (Abc_Clock() - clkStart)/CLOCKS_PER_SEC >= nTimeOut ) { RetValue = 0; break; } + } + // complement the set of input/output minterms + Vec_Int_t * vBits = Vec_IntStart( 1 << Vec_IntSize(vInsOuts) ); + Vec_IntForEachEntry( vRes, Mask, i ) + Vec_IntWriteEntry( vBits, Mask, 1 ); + Vec_IntClear( vRes ); + Vec_IntForEachEntry( vBits, Mask, i ) + if ( !Mask ) + Vec_IntPush( vRes, i ); + Vec_IntFree( vBits ); + // cleanup + Vec_IntFree( vLits ); + sat_solver_delete( pSat ); + Gia_ManStop( pMiter ); + Cnf_DataFree( pCnf ); + if ( RetValue == 0 ) + Vec_IntFreeP( &vRes ); + return vRes; +} +void Gia_ManGenRel( Gia_Man_t * pGia, Vec_Int_t * vInsOuts, int nIns, char * pFileName, int fVerbose ) +{ + abctime clkStart = Abc_Clock(); + Vec_Int_t * vRes = Gia_ManGenIoCombs( pGia, vInsOuts, nIns, fVerbose ); + if ( vRes == NULL ) { + printf( "Enumerating solutions did not succeed.\n" ); + return; + } + Gia_ManGenWriteRel( vRes, nIns, Vec_IntSize(vInsOuts)-nIns, pFileName ); + if ( fVerbose ) { + printf( "The resulting relation with %d input/output minterms is written into file \"%s\". ", Vec_IntSize(vRes), pFileName ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); + if ( 0 ) { + int i, Mint; + Vec_IntForEachEntry( vRes, Mint, i ) + Gia_ManPrintRelMinterm( Mint, nIns, Vec_IntSize(vInsOuts) ); + } + } + Vec_IntFree( vRes ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaReshape1.c b/yosys/abc/src/aig/gia/giaReshape1.c new file mode 100644 index 00000000000..52b40bdcf1f --- /dev/null +++ b/yosys/abc/src/aig/gia/giaReshape1.c @@ -0,0 +1,56 @@ +/**CFile**************************************************************** + + FileName [giaReshape.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManReshape1( Gia_Man_t * p, int fUseSimple, int fVerbose, int fVeryVerbose ) +{ + return NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaReshape2.c b/yosys/abc/src/aig/gia/giaReshape2.c new file mode 100644 index 00000000000..98a4d85594e --- /dev/null +++ b/yosys/abc/src/aig/gia/giaReshape2.c @@ -0,0 +1,55 @@ +/**CFile**************************************************************** + + FileName [giaReshape.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManReshape2( Gia_Man_t * p, int fUseSimple, int fVerbose, int fVeryVerbose ) +{ + return NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaResub.c b/yosys/abc/src/aig/gia/giaResub.c new file mode 100644 index 00000000000..a4141a050d0 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaResub.c @@ -0,0 +1,2159 @@ +/**CFile**************************************************************** + + FileName [giaResub.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Resubstitution.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaResub.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/vec/vecWec.h" +#include "misc/vec/vecQue.h" +#include "misc/vec/vecHsh.h" +#include "misc/util/utilTruth.h" +#include "base/io/ioResub.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes MFFCs of all qualifying nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ObjCheckMffc_rec( Gia_Man_t * p,Gia_Obj_t * pObj, int Limit, Vec_Int_t * vNodes ) +{ + int iFanin; + if ( Gia_ObjIsCi(pObj) ) + return 1; + assert( Gia_ObjIsAnd(pObj) ); + iFanin = Gia_ObjFaninId0p(p, pObj); + Vec_IntPush( vNodes, iFanin ); + if ( !Gia_ObjRefDecId(p, iFanin) && (Vec_IntSize(vNodes) > Limit || !Gia_ObjCheckMffc_rec(p, Gia_ObjFanin0(pObj), Limit, vNodes)) ) + return 0; + iFanin = Gia_ObjFaninId1p(p, pObj); + Vec_IntPush( vNodes, iFanin ); + if ( !Gia_ObjRefDecId(p, iFanin) && (Vec_IntSize(vNodes) > Limit || !Gia_ObjCheckMffc_rec(p, Gia_ObjFanin1(pObj), Limit, vNodes)) ) + return 0; + if ( !Gia_ObjIsMux(p, pObj) ) + return 1; + iFanin = Gia_ObjFaninId2p(p, pObj); + Vec_IntPush( vNodes, iFanin ); + if ( !Gia_ObjRefDecId(p, iFanin) && (Vec_IntSize(vNodes) > Limit || !Gia_ObjCheckMffc_rec(p, Gia_ObjFanin2(p, pObj), Limit, vNodes)) ) + return 0; + return 1; +} +int Gia_ObjCheckMffc( Gia_Man_t * p, Gia_Obj_t * pRoot, int Limit, Vec_Int_t * vNodes, Vec_Int_t * vLeaves, Vec_Int_t * vInners ) +{ + int RetValue, iObj, i; + Vec_IntClear( vNodes ); + RetValue = Gia_ObjCheckMffc_rec( p, pRoot, Limit, vNodes ); + if ( RetValue ) + { + Vec_IntClear( vLeaves ); + Vec_IntClear( vInners ); + Vec_IntSort( vNodes, 0 ); + Vec_IntForEachEntry( vNodes, iObj, i ) + if ( Gia_ObjRefNumId(p, iObj) > 0 || Gia_ObjIsCi(Gia_ManObj(p, iObj)) ) + { + if ( !Vec_IntSize(vLeaves) || Vec_IntEntryLast(vLeaves) != iObj ) + Vec_IntPush( vLeaves, iObj ); + } + else + { + if ( !Vec_IntSize(vInners) || Vec_IntEntryLast(vInners) != iObj ) + Vec_IntPush( vInners, iObj ); + } + Vec_IntPush( vInners, Gia_ObjId(p, pRoot) ); + } + Vec_IntForEachEntry( vNodes, iObj, i ) + Gia_ObjRefIncId( p, iObj ); + return RetValue; +} +Vec_Wec_t * Gia_ManComputeMffcs( Gia_Man_t * p, int LimitMin, int LimitMax, int SuppMax, int RatioBest ) +{ + Gia_Obj_t * pObj; + Vec_Wec_t * vMffcs; + Vec_Int_t * vNodes, * vLeaves, * vInners, * vMffc; + int i, iPivot; + assert( p->pMuxes ); + vNodes = Vec_IntAlloc( 2 * LimitMax ); + vLeaves = Vec_IntAlloc( 2 * LimitMax ); + vInners = Vec_IntAlloc( 2 * LimitMax ); + vMffcs = Vec_WecAlloc( 1000 ); + Gia_ManCreateRefs( p ); + Gia_ManForEachAnd( p, pObj, i ) + { + if ( !Gia_ObjRefNum(p, pObj) ) + continue; + if ( !Gia_ObjCheckMffc(p, pObj, LimitMax, vNodes, vLeaves, vInners) ) + continue; + if ( Vec_IntSize(vInners) < LimitMin ) + continue; + if ( Vec_IntSize(vLeaves) > SuppMax ) + continue; + // improve cut + // collect cut + vMffc = Vec_WecPushLevel( vMffcs ); + Vec_IntGrow( vMffc, Vec_IntSize(vLeaves) + Vec_IntSize(vInners) + 20 ); + Vec_IntPush( vMffc, i ); + Vec_IntPush( vMffc, Vec_IntSize(vLeaves) ); + Vec_IntPush( vMffc, Vec_IntSize(vInners) ); + Vec_IntAppend( vMffc, vLeaves ); +// Vec_IntAppend( vMffc, vInners ); + // add last entry equal to the ratio + Vec_IntPush( vMffc, 1000 * Vec_IntSize(vInners) / Vec_IntSize(vLeaves) ); + } + Vec_IntFree( vNodes ); + Vec_IntFree( vLeaves ); + Vec_IntFree( vInners ); + // sort MFFCs by their inner/leaf ratio + Vec_WecSortByLastInt( vMffcs, 1 ); + Vec_WecForEachLevel( vMffcs, vMffc, i ) + Vec_IntPop( vMffc ); + // remove those whose ratio is not good + iPivot = RatioBest * Vec_WecSize(vMffcs) / 100; + Vec_WecForEachLevelStart( vMffcs, vMffc, i, iPivot ) + Vec_IntErase( vMffc ); + assert( iPivot <= Vec_WecSize(vMffcs) ); + Vec_WecShrink( vMffcs, iPivot ); + return vMffcs; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintDivStats( Gia_Man_t * p, Vec_Wec_t * vMffcs, Vec_Wec_t * vPivots ) +{ + int fVerbose = 0; + Vec_Int_t * vMffc; + int i, nDivs, nDivsAll = 0, nDivs0 = 0; + Vec_WecForEachLevel( vMffcs, vMffc, i ) + { + nDivs = Vec_IntSize(vMffc) - 3 - Vec_IntEntry(vMffc, 1) - Vec_IntEntry(vMffc, 2); + nDivs0 += (nDivs == 0); + nDivsAll += nDivs; + if ( !fVerbose ) + continue; + printf( "%6d : ", Vec_IntEntry(vMffc, 0) ); + printf( "Leaf =%3d ", Vec_IntEntry(vMffc, 1) ); + printf( "Mffc =%4d ", Vec_IntEntry(vMffc, 2) ); + printf( "Divs =%4d ", nDivs ); + printf( "\n" ); + } + printf( "Collected %d (%.1f %%) MFFCs and %d (%.1f %%) have no divisors (div ave for others is %.2f).\n", + Vec_WecSize(vMffcs), 100.0 * Vec_WecSize(vMffcs) / Gia_ManAndNum(p), + nDivs0, 100.0 * nDivs0 / Gia_ManAndNum(p), + 1.0*nDivsAll/Abc_MaxInt(1, Vec_WecSize(vMffcs) - nDivs0) ); + printf( "Using %.2f MB for MFFCs and %.2f MB for pivots. ", + Vec_WecMemory(vMffcs)/(1<<20), Vec_WecMemory(vPivots)/(1<<20) ); +} + +/**Function************************************************************* + + Synopsis [Compute divisors and Boolean functions for the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManAddDivisors( Gia_Man_t * p, Vec_Wec_t * vMffcs ) +{ + Vec_Wec_t * vPivots; + Vec_Int_t * vMffc, * vPivot, * vPivot0, * vPivot1; + Vec_Int_t * vCommon, * vCommon2, * vMap; + Gia_Obj_t * pObj; + int i, k, iObj, iPivot, iMffc; +//abctime clkStart = Abc_Clock(); + // initialize pivots (mapping of nodes into MFFCs whose leaves they are) + vMap = Vec_IntStartFull( Gia_ManObjNum(p) ); + vPivots = Vec_WecStart( Gia_ManObjNum(p) ); + Vec_WecForEachLevel( vMffcs, vMffc, i ) + { + assert( Vec_IntSize(vMffc) == 3 + Vec_IntEntry(vMffc, 1) ); + iPivot = Vec_IntEntry( vMffc, 0 ); + Vec_IntWriteEntry( vMap, iPivot, i ); + // iterate through the MFFC leaves + Vec_IntForEachEntryStart( vMffc, iObj, k, 3 ) + { + vPivot = Vec_WecEntry( vPivots, iObj ); + if ( Vec_IntSize(vPivot) == 0 ) + Vec_IntGrow(vPivot, 4); + Vec_IntPush( vPivot, iPivot ); + } + } + Vec_WecForEachLevel( vPivots, vPivot, i ) + Vec_IntSort( vPivot, 0 ); + // create pivots for internal nodes while growing MFFCs + vCommon = Vec_IntAlloc( 100 ); + vCommon2 = Vec_IntAlloc( 100 ); + Gia_ManForEachAnd( p, pObj, i ) + { + // find commont pivots + // the slow down happens because some PIs have very large sets of pivots + vPivot0 = Vec_WecEntry( vPivots, Gia_ObjFaninId0(pObj, i) ); + vPivot1 = Vec_WecEntry( vPivots, Gia_ObjFaninId1(pObj, i) ); + Vec_IntTwoFindCommon( vPivot0, vPivot1, vCommon ); + if ( Gia_ObjIsMuxId(p, i) ) + { + vPivot = Vec_WecEntry( vPivots, Gia_ObjFaninId2(p, i) ); + Vec_IntTwoFindCommon( vPivot, vCommon, vCommon2 ); + ABC_SWAP( Vec_Int_t *, vCommon, vCommon2 ); + } + if ( Vec_IntSize(vCommon) == 0 ) + continue; + // add new pivots (this trick increased memory used in vPivots) + vPivot = Vec_WecEntry( vPivots, i ); + Vec_IntTwoMerge2( vPivot, vCommon, vCommon2 ); + ABC_SWAP( Vec_Int_t, *vPivot, *vCommon2 ); + // grow MFFCs + Vec_IntForEachEntry( vCommon, iObj, k ) + { + iMffc = Vec_IntEntry( vMap, iObj ); + assert( iMffc != -1 ); + vMffc = Vec_WecEntry( vMffcs, iMffc ); + Vec_IntPush( vMffc, i ); + } + } +//Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); + Vec_IntFree( vCommon ); + Vec_IntFree( vCommon2 ); + Vec_IntFree( vMap ); + Gia_ManPrintDivStats( p, vMffcs, vPivots ); + Vec_WecFree( vPivots ); + // returns the modified array of MFFCs +} +void Gia_ManResubTest( Gia_Man_t * p ) +{ + Vec_Wec_t * vMffcs; + Gia_Man_t * pNew = Gia_ManDupMuxes( p, 2 ); +abctime clkStart = Abc_Clock(); + vMffcs = Gia_ManComputeMffcs( pNew, 4, 100, 8, 100 ); + Gia_ManAddDivisors( pNew, vMffcs ); + Vec_WecFree( vMffcs ); +Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); + Gia_ManStop( pNew ); +} + + + + + +/**Function************************************************************* + + Synopsis [Resubstitution data-structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +typedef struct Gia_ResbMan_t_ Gia_ResbMan_t; +struct Gia_ResbMan_t_ +{ + int nWords; + int nLimit; + int nDivsMax; + int iChoice; + int fUseXor; + int fDebug; + int fVerbose; + int fVeryVerbose; + Vec_Ptr_t * vDivs; + Vec_Int_t * vGates; + Vec_Int_t * vUnateLits[2]; + Vec_Int_t * vNotUnateVars[2]; + Vec_Int_t * vUnatePairs[2]; + Vec_Int_t * vBinateVars; + Vec_Int_t * vUnateLitsW[2]; + Vec_Int_t * vUnatePairsW[2]; + Vec_Wec_t * vSorter; + word * pSets[2]; + word * pDivA; + word * pDivB; + Vec_Wrd_t * vSims; +}; +Gia_ResbMan_t * Gia_ResbAlloc( int nWords ) +{ + Gia_ResbMan_t * p = ABC_CALLOC( Gia_ResbMan_t, 1 ); + p->nWords = nWords; + p->vUnateLits[0] = Vec_IntAlloc( 100 ); + p->vUnateLits[1] = Vec_IntAlloc( 100 ); + p->vNotUnateVars[0] = Vec_IntAlloc( 100 ); + p->vNotUnateVars[1] = Vec_IntAlloc( 100 ); + p->vUnatePairs[0] = Vec_IntAlloc( 100 ); + p->vUnatePairs[1] = Vec_IntAlloc( 100 ); + p->vUnateLitsW[0] = Vec_IntAlloc( 100 ); + p->vUnateLitsW[1] = Vec_IntAlloc( 100 ); + p->vUnatePairsW[0] = Vec_IntAlloc( 100 ); + p->vUnatePairsW[1] = Vec_IntAlloc( 100 ); + p->vSorter = Vec_WecAlloc( nWords*64 ); + p->vBinateVars = Vec_IntAlloc( 100 ); + p->vGates = Vec_IntAlloc( 100 ); + p->vDivs = Vec_PtrAlloc( 100 ); + p->pSets[0] = ABC_CALLOC( word, nWords ); + p->pSets[1] = ABC_CALLOC( word, nWords ); + p->pDivA = ABC_CALLOC( word, nWords ); + p->pDivB = ABC_CALLOC( word, nWords ); + p->vSims = Vec_WrdAlloc( 100 ); + return p; +} +void Gia_ResbInit( Gia_ResbMan_t * p, Vec_Ptr_t * vDivs, int nWords, int nLimit, int nDivsMax, int iChoice, int fUseXor, int fDebug, int fVerbose, int fVeryVerbose ) +{ + assert( p->nWords == nWords ); + p->nLimit = nLimit; + p->nDivsMax = nDivsMax; + p->iChoice = iChoice; + p->fUseXor = fUseXor; + p->fDebug = fDebug; + p->fVerbose = fVerbose; + p->fVeryVerbose = fVeryVerbose; + Abc_TtCopy( p->pSets[0], (word *)Vec_PtrEntry(vDivs, 0), nWords, 0 ); + Abc_TtCopy( p->pSets[1], (word *)Vec_PtrEntry(vDivs, 1), nWords, 0 ); + Vec_PtrClear( p->vDivs ); + Vec_PtrAppend( p->vDivs, vDivs ); + Vec_IntClear( p->vGates ); + Vec_IntClear( p->vUnateLits[0] ); + Vec_IntClear( p->vUnateLits[1] ); + Vec_IntClear( p->vNotUnateVars[0] ); + Vec_IntClear( p->vNotUnateVars[1] ); + Vec_IntClear( p->vUnatePairs[0] ); + Vec_IntClear( p->vUnatePairs[1] ); + Vec_IntClear( p->vUnateLitsW[0] ); + Vec_IntClear( p->vUnateLitsW[1] ); + Vec_IntClear( p->vUnatePairsW[0] ); + Vec_IntClear( p->vUnatePairsW[1] ); + Vec_IntClear( p->vBinateVars ); +} +void Gia_ResbFree( Gia_ResbMan_t * p ) +{ + Vec_IntFree( p->vUnateLits[0] ); + Vec_IntFree( p->vUnateLits[1] ); + Vec_IntFree( p->vNotUnateVars[0] ); + Vec_IntFree( p->vNotUnateVars[1] ); + Vec_IntFree( p->vUnatePairs[0] ); + Vec_IntFree( p->vUnatePairs[1] ); + Vec_IntFree( p->vUnateLitsW[0] ); + Vec_IntFree( p->vUnateLitsW[1] ); + Vec_IntFree( p->vUnatePairsW[0] ); + Vec_IntFree( p->vUnatePairsW[1] ); + Vec_IntFree( p->vBinateVars ); + Vec_IntFree( p->vGates ); + Vec_WrdFree( p->vSims ); + Vec_PtrFree( p->vDivs ); + Vec_WecFree( p->vSorter ); + ABC_FREE( p->pSets[0] ); + ABC_FREE( p->pSets[1] ); + ABC_FREE( p->pDivA ); + ABC_FREE( p->pDivB ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Print resubstitution.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManResubPrintNode( Vec_Int_t * vRes, int nVars, int Node, int fCompl ) +{ + extern void Gia_ManResubPrintLit( Vec_Int_t * vRes, int nVars, int iLit ); + int iLit0 = Vec_IntEntry( vRes, 2*Node + 0 ); + int iLit1 = Vec_IntEntry( vRes, 2*Node + 1 ); + assert( iLit0 != iLit1 ); + if ( iLit0 > iLit1 && Abc_LitIsCompl(fCompl) ) // xor + { + printf( "~" ); + fCompl = 0; + } + printf( "(" ); + Gia_ManResubPrintLit( vRes, nVars, Abc_LitNotCond(iLit0, fCompl) ); + printf( " %c ", iLit0 > iLit1 ? '^' : (fCompl ? '|' : '&') ); + Gia_ManResubPrintLit( vRes, nVars, Abc_LitNotCond(iLit1, fCompl) ); + printf( ")" ); +} +void Gia_ManResubPrintLit( Vec_Int_t * vRes, int nVars, int iLit ) +{ + if ( Abc_Lit2Var(iLit) < nVars ) + { + if ( nVars < 26 ) + printf( "%s%c", Abc_LitIsCompl(iLit) ? "~":"", 'a' + Abc_Lit2Var(iLit)-2 ); + else + printf( "%si%d", Abc_LitIsCompl(iLit) ? "~":"", Abc_Lit2Var(iLit)-2 ); + } + else + Gia_ManResubPrintNode( vRes, nVars, Abc_Lit2Var(iLit) - nVars, Abc_LitIsCompl(iLit) ); +} +int Gia_ManResubPrint( Vec_Int_t * vRes, int nVars ) +{ + int iTopLit; + if ( Vec_IntSize(vRes) == 0 ) + return printf( "none" ); + assert( Vec_IntSize(vRes) % 2 == 1 ); + iTopLit = Vec_IntEntryLast(vRes); + if ( iTopLit == 0 ) + return printf( "const0" ); + if ( iTopLit == 1 ) + return printf( "const1" ); + Gia_ManResubPrintLit( vRes, nVars, iTopLit ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Verify resubstitution.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManResubVerify( Gia_ResbMan_t * p, word * pFunc ) +{ + int nVars = Vec_PtrSize(p->vDivs); + int iTopLit, RetValue; + word * pDivRes; + if ( Vec_IntSize(p->vGates) == 0 ) + return -1; + iTopLit = Vec_IntEntryLast(p->vGates); + assert( iTopLit >= 0 ); + if ( iTopLit == 0 ) + { + if ( pFunc ) Abc_TtClear( pFunc, p->nWords ); + return Abc_TtIsConst0( p->pSets[1], p->nWords ); + } + if ( iTopLit == 1 ) + { + if ( pFunc ) Abc_TtFill( pFunc, p->nWords ); + return Abc_TtIsConst0( p->pSets[0], p->nWords ); + } + if ( Abc_Lit2Var(iTopLit) < nVars ) + { + assert( Vec_IntSize(p->vGates) == 1 ); + pDivRes = (word *)Vec_PtrEntry( p->vDivs, Abc_Lit2Var(iTopLit) ); + } + else + { + int i, iLit0, iLit1; + assert( Vec_IntSize(p->vGates) > 1 ); + assert( Vec_IntSize(p->vGates) % 2 == 1 ); + assert( Abc_Lit2Var(iTopLit)-nVars == Vec_IntSize(p->vGates)/2-1 ); + Vec_WrdFill( p->vSims, p->nWords * Vec_IntSize(p->vGates)/2, 0 ); + Vec_IntForEachEntryDouble( p->vGates, iLit0, iLit1, i ) + { + int iVar0 = Abc_Lit2Var(iLit0); + int iVar1 = Abc_Lit2Var(iLit1); + word * pDiv0 = iVar0 < nVars ? (word *)Vec_PtrEntry(p->vDivs, iVar0) : Vec_WrdEntryP(p->vSims, p->nWords*(iVar0 - nVars)); + word * pDiv1 = iVar1 < nVars ? (word *)Vec_PtrEntry(p->vDivs, iVar1) : Vec_WrdEntryP(p->vSims, p->nWords*(iVar1 - nVars)); + word * pDiv = Vec_WrdEntryP(p->vSims, p->nWords*i/2); + if ( iVar0 < iVar1 ) + Abc_TtAndCompl( pDiv, pDiv0, Abc_LitIsCompl(iLit0), pDiv1, Abc_LitIsCompl(iLit1), p->nWords ); + else if ( iVar0 > iVar1 ) + { + assert( !Abc_LitIsCompl(iLit0) ); + assert( !Abc_LitIsCompl(iLit1) ); + Abc_TtXor( pDiv, pDiv0, pDiv1, p->nWords, 0 ); + } + else assert( 0 ); + } + pDivRes = Vec_WrdEntryP( p->vSims, p->nWords*(Vec_IntSize(p->vGates)/2-1) ); + } + if ( Abc_LitIsCompl(iTopLit) ) + RetValue = !Abc_TtIntersectOne(p->pSets[1], 0, pDivRes, 0, p->nWords) && !Abc_TtIntersectOne(p->pSets[0], 0, pDivRes, 1, p->nWords); + else + RetValue = !Abc_TtIntersectOne(p->pSets[0], 0, pDivRes, 0, p->nWords) && !Abc_TtIntersectOne(p->pSets[1], 0, pDivRes, 1, p->nWords); + if ( pFunc ) Abc_TtCopy( pFunc, pDivRes, p->nWords, Abc_LitIsCompl(iTopLit) ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Construct AIG manager from gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManConstructFromMap( Gia_Man_t * pNew, Vec_Int_t * vGates, int nVars, Vec_Int_t * vUsed, Vec_Int_t * vCopy, int fHash ) +{ + int i, iLit0, iLit1, iLitRes, iTopLit = Vec_IntEntryLast( vGates ); + assert( Vec_IntSize(vUsed) == nVars ); + assert( Vec_IntSize(vGates) > 1 ); + assert( Vec_IntSize(vGates) % 2 == 1 ); + assert( Abc_Lit2Var(iTopLit)-nVars == Vec_IntSize(vGates)/2-1 ); + Vec_IntClear( vCopy ); + Vec_IntForEachEntryDouble( vGates, iLit0, iLit1, i ) + { + int iVar0 = Abc_Lit2Var(iLit0); + int iVar1 = Abc_Lit2Var(iLit1); + int iRes0 = iVar0 < nVars ? Vec_IntEntry(vUsed, iVar0) : Vec_IntEntry(vCopy, iVar0 - nVars); + int iRes1 = iVar1 < nVars ? Vec_IntEntry(vUsed, iVar1) : Vec_IntEntry(vCopy, iVar1 - nVars); + if ( iVar0 < iVar1 ) + { + if ( fHash ) + iLitRes = Gia_ManHashAnd( pNew, Abc_LitNotCond(iRes0, Abc_LitIsCompl(iLit0)), Abc_LitNotCond(iRes1, Abc_LitIsCompl(iLit1)) ); + else + iLitRes = Gia_ManAppendAnd( pNew, Abc_LitNotCond(iRes0, Abc_LitIsCompl(iLit0)), Abc_LitNotCond(iRes1, Abc_LitIsCompl(iLit1)) ); + } + else if ( iVar0 > iVar1 ) + { + assert( !Abc_LitIsCompl(iLit0) ); + assert( !Abc_LitIsCompl(iLit1) ); + if ( fHash ) + iLitRes = Gia_ManHashXor( pNew, Abc_LitNotCond(iRes0, Abc_LitIsCompl(iLit0)), Abc_LitNotCond(iRes1, Abc_LitIsCompl(iLit1)) ); + else + iLitRes = Gia_ManAppendXor( pNew, Abc_LitNotCond(iRes0, Abc_LitIsCompl(iLit0)), Abc_LitNotCond(iRes1, Abc_LitIsCompl(iLit1)) ); + } + else assert( 0 ); + Vec_IntPush( vCopy, iLitRes ); + } + assert( Vec_IntSize(vCopy) == Vec_IntSize(vGates)/2 ); + iLitRes = Vec_IntEntry( vCopy, Vec_IntSize(vGates)/2-1 ); + return iLitRes; +} +Gia_Man_t * Gia_ManConstructFromGates( Vec_Wec_t * vFuncs, int nDivs ) +{ + Vec_Int_t * vGates; int i, k, iLit; + Vec_Int_t * vCopy = Vec_IntAlloc( 100 ); + Vec_Int_t * vUsed = Vec_IntStartFull( nDivs ); + Gia_Man_t * pNew = Gia_ManStart( 100 ); + pNew->pName = Abc_UtilStrsav( "resub" ); + Vec_WecForEachLevel( vFuncs, vGates, i ) + { + assert( Vec_IntSize(vGates) % 2 == 1 ); + Vec_IntForEachEntry( vGates, iLit, k ) + { + int iVar = Abc_Lit2Var(iLit); + if ( iVar > 0 && iVar < nDivs && Vec_IntEntry(vUsed, iVar) == -1 ) + Vec_IntWriteEntry( vUsed, iVar, Gia_ManAppendCi(pNew) ); + } + } + Vec_WecForEachLevel( vFuncs, vGates, i ) + { + int iLitRes, iTopLit = Vec_IntEntryLast( vGates ); + if ( Abc_Lit2Var(iTopLit) == 0 ) + iLitRes = 0; + else if ( Abc_Lit2Var(iTopLit) < nDivs ) + iLitRes = Vec_IntEntry( vUsed, Abc_Lit2Var(iTopLit) ); + else + iLitRes = Gia_ManConstructFromMap( pNew, vGates, nDivs, vUsed, vCopy, 0 ); + Gia_ManAppendCo( pNew, Abc_LitNotCond( iLitRes, Abc_LitIsCompl(iTopLit) ) ); + } + Vec_IntFree( vCopy ); + Vec_IntFree( vUsed ); + return pNew; +} +Gia_Man_t * Gia_ManConstructFromGates2( Vec_Wec_t * vFuncs, Vec_Wec_t * vDivs, int nObjs, Vec_Int_t ** pvSupp ) +{ + Vec_Int_t * vGates; int i, k, iVar, iLit; + Vec_Int_t * vSupp = Vec_IntAlloc( 100 ); + Vec_Int_t * vCopy = Vec_IntAlloc( 100 ); + Vec_Wec_t * vUseds = Vec_WecStart( Vec_WecSize(vDivs) ); + Vec_Int_t * vMap = Vec_IntStartFull( nObjs ); + Gia_Man_t * pNew = Gia_ManStart( 100 ); + pNew->pName = Abc_UtilStrsav( "resub" ); + assert( Vec_WecSize(vFuncs) == Vec_WecSize(vDivs) ); + Vec_WecForEachLevel( vFuncs, vGates, i ) + { + Vec_Int_t * vDiv = Vec_WecEntry( vDivs, i ); + assert( Vec_IntSize(vGates) % 2 == 1 ); + Vec_IntForEachEntry( vGates, iLit, k ) + { + int iVar = Abc_Lit2Var(iLit); + if ( iVar > 0 && iVar < Vec_IntSize(vDiv) && Vec_IntEntry(vMap, Vec_IntEntry(vDiv, iVar)) == -1 ) + Vec_IntWriteEntry( vMap, Vec_IntPushReturn(vSupp, Vec_IntEntry(vDiv, iVar)), 0 ); + } + } + Vec_IntSort( vSupp, 0 ); + Vec_IntForEachEntry( vSupp, iVar, k ) + Vec_IntWriteEntry( vMap, iVar, Gia_ManAppendCi(pNew) ); + Vec_WecForEachLevel( vFuncs, vGates, i ) + { + Vec_Int_t * vDiv = Vec_WecEntry( vDivs, i ); + Vec_Int_t * vUsed = Vec_WecEntry( vUseds, i ); + Vec_IntFill( vUsed, Vec_IntSize(vDiv), -1 ); + Vec_IntForEachEntry( vGates, iLit, k ) + { + int iVar = Abc_Lit2Var(iLit); + if ( iVar > 0 && iVar < Vec_IntSize(vDiv) ) + { + assert( Vec_IntEntry(vMap, Vec_IntEntry(vDiv, iVar)) > 0 ); + Vec_IntWriteEntry( vUsed, iVar, Vec_IntEntry(vMap, Vec_IntEntry(vDiv, iVar)) ); + } + } + } + Vec_WecForEachLevel( vFuncs, vGates, i ) + { + Vec_Int_t * vDiv = Vec_WecEntry( vDivs, i ); + Vec_Int_t * vUsed = Vec_WecEntry( vUseds, i ); + int iLitRes, iTopLit = Vec_IntEntryLast( vGates ); + if ( Abc_Lit2Var(iTopLit) == 0 ) + iLitRes = 0; + else if ( Abc_Lit2Var(iTopLit) < Vec_IntSize(vDiv) ) + iLitRes = Vec_IntEntry( vUsed, Abc_Lit2Var(iTopLit) ); + else + iLitRes = Gia_ManConstructFromMap( pNew, vGates, Vec_IntSize(vDiv), vUsed, vCopy, 0 ); + Gia_ManAppendCo( pNew, Abc_LitNotCond( iLitRes, Abc_LitIsCompl(iTopLit) ) ); + } + Vec_IntFree( vMap ); + Vec_IntFree( vCopy ); + Vec_WecFree( vUseds ); + if ( pvSupp ) + *pvSupp = vSupp; + else + Vec_IntFree( vSupp ); + return pNew; +} +Vec_Int_t * Gia_ManToGates( Gia_Man_t * p ) +{ + Vec_Int_t * vRes = Vec_IntAlloc( 2*Gia_ManAndNum(p) + 1 ); + Gia_Obj_t * pRoot = Gia_ManCo( p, 0 ); + int iRoot = Gia_ObjFaninId0p(p, pRoot) - 1; + int nVars = Gia_ManCiNum(p); + assert( Gia_ManCoNum(p) == 1 ); + if ( iRoot == -1 ) + Vec_IntPush( vRes, Gia_ObjFaninC0(pRoot) ); + else if ( iRoot < nVars ) + Vec_IntPush( vRes, 4 + Abc_Var2Lit(iRoot, Gia_ObjFaninC0(pRoot)) ); + else + { + Gia_Obj_t * pObj, * pLast = NULL; int i; + Gia_ManForEachCi( p, pObj, i ) + assert( Gia_ObjId(p, pObj) == i+1 ); + Gia_ManForEachAnd( p, pObj, i ) + { + int iLit0 = Abc_Var2Lit( Gia_ObjFaninId0(pObj, i) - 1, Gia_ObjFaninC0(pObj) ); + int iLit1 = Abc_Var2Lit( Gia_ObjFaninId1(pObj, i) - 1, Gia_ObjFaninC1(pObj) ); + if ( iLit0 > iLit1 ) + iLit0 ^= iLit1, iLit1 ^= iLit0, iLit0 ^= iLit1; + Vec_IntPushTwo( vRes, 4 + iLit0, 4 + iLit1 ); + pLast = pObj; + } + assert( pLast == Gia_ObjFanin0(pRoot) ); + Vec_IntPush( vRes, 4 + Abc_Var2Lit(iRoot, Gia_ObjFaninC0(pRoot)) ); + } + assert( Vec_IntSize(vRes) == 2*Gia_ManAndNum(p) + 1 ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [Construct AIG manager from gates.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManInsertOrder_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vObjs, Vec_Wec_t * vFuncs, Vec_Int_t * vNodes ) +{ + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + if ( iObj == 0 ) + return; + if ( pObj->fPhase ) + { + int nVars = Gia_ManObjNum(p); + int k, iLit, Index = Vec_IntFind( vObjs, iObj ); + Vec_Int_t * vGates = Vec_WecEntry( vFuncs, Index ); + assert( Gia_ObjIsCo(pObj) || Gia_ObjIsAnd(pObj) ); + Vec_IntForEachEntry( vGates, iLit, k ) + if ( Abc_Lit2Var(iLit) < nVars ) + Gia_ManInsertOrder_rec( p, Abc_Lit2Var(iLit), vObjs, vFuncs, vNodes ); + } + else if ( Gia_ObjIsCo(pObj) ) + Gia_ManInsertOrder_rec( p, Gia_ObjFaninId0p(p, pObj), vObjs, vFuncs, vNodes ); + else if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ManInsertOrder_rec( p, Gia_ObjFaninId0p(p, pObj), vObjs, vFuncs, vNodes ); + Gia_ManInsertOrder_rec( p, Gia_ObjFaninId1p(p, pObj), vObjs, vFuncs, vNodes ); + } + else assert( Gia_ObjIsCi(pObj) ); + if ( !Gia_ObjIsCi(pObj) ) + Vec_IntPush( vNodes, iObj ); +} +Vec_Int_t * Gia_ManInsertOrder( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Wec_t * vFuncs ) +{ + int i, Id; + Vec_Int_t * vNodes = Vec_IntAlloc( Gia_ManObjNum(p) ); + Gia_ManForEachCoId( p, Id, i ) + Gia_ManInsertOrder_rec( p, Id, vObjs, vFuncs, vNodes ); + return vNodes; +} +Gia_Man_t * Gia_ManInsertFromGates( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Wec_t * vFuncs ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, nVars = Gia_ManObjNum(p); + Vec_Int_t * vUsed = Vec_IntStartFull( nVars ); + Vec_Int_t * vNodes, * vCopy = Vec_IntAlloc(100); + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + pObj->fPhase = 1; + vNodes = Gia_ManInsertOrder( p, vObjs, vFuncs ); + pNew = Gia_ManStart( Gia_ManObjNum(p) + 1000 ); + Gia_ManHashStart( pNew ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + if ( !pObj->fPhase ) + { + if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + else if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else assert( 0 ); + } + else + { + int k, iLit, Index = Vec_IntFind( vObjs, Gia_ObjId(p, pObj) ); + Vec_Int_t * vGates = Vec_WecEntry( vFuncs, Index ); + int iLitRes, iTopLit = Vec_IntEntryLast( vGates ); + if ( Abc_Lit2Var(iTopLit) == 0 ) + iLitRes = 0; + else if ( Abc_Lit2Var(iTopLit) < nVars ) + iLitRes = Gia_ManObj(p, Abc_Lit2Var(iTopLit))->Value; + else + { + Vec_IntForEachEntry( vGates, iLit, k ) + Vec_IntWriteEntry( vUsed, Abc_Lit2Var(iLit), Gia_ManObj(p, Abc_Lit2Var(iLit))->Value ); + iLitRes = Gia_ManConstructFromMap( pNew, vGates, nVars, vUsed, vCopy, 1 ); + Vec_IntForEachEntry( vGates, iLit, k ) + Vec_IntWriteEntry( vUsed, Abc_Lit2Var(iLit), -1 ); + } + pObj->Value = Abc_LitNotCond( iLitRes, Abc_LitIsCompl(iTopLit) ); + } + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, pObj->Value ); + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + pObj->fPhase = 0; + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Vec_IntFree( vNodes ); + Vec_IntFree( vUsed ); + Vec_IntFree( vCopy ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Perform resubstitution.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManFindFirstCommonLit( Vec_Int_t * vArr1, Vec_Int_t * vArr2, int fVerbose ) +{ + int * pBeg1 = vArr1->pArray; + int * pBeg2 = vArr2->pArray; + int * pEnd1 = vArr1->pArray + vArr1->nSize; + int * pEnd2 = vArr2->pArray + vArr2->nSize; + int * pStart1 = vArr1->pArray; + int * pStart2 = vArr2->pArray; + int nRemoved = 0; + while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) + { + if ( Abc_Lit2Var(*pBeg1) == Abc_Lit2Var(*pBeg2) ) + { + if ( *pBeg1 != *pBeg2 ) + return *pBeg1; + else + pBeg1++, pBeg2++; + nRemoved++; + } + else if ( *pBeg1 < *pBeg2 ) + *pStart1++ = *pBeg1++; + else + *pStart2++ = *pBeg2++; + } + while ( pBeg1 < pEnd1 ) + *pStart1++ = *pBeg1++; + while ( pBeg2 < pEnd2 ) + *pStart2++ = *pBeg2++; + Vec_IntShrink( vArr1, pStart1 - vArr1->pArray ); + Vec_IntShrink( vArr2, pStart2 - vArr2->pArray ); + //if ( fVerbose ) printf( "Removed %d duplicated entries. Array1 = %d. Array2 = %d.\n", nRemoved, Vec_IntSize(vArr1), Vec_IntSize(vArr2) ); + return -1; +} + +void Gia_ManFindOneUnateInt( word * pOff, word * pOn, Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits, Vec_Int_t * vNotUnateVars ) +{ + word * pDiv; int i; + Vec_IntClear( vUnateLits ); + Vec_IntClear( vNotUnateVars ); + Vec_PtrForEachEntryStart( word *, vDivs, pDiv, i, 2 ) + if ( !Abc_TtIntersectOne( pOff, 0, pDiv, 0, nWords ) ) + Vec_IntPush( vUnateLits, Abc_Var2Lit(i, 0) ); + else if ( !Abc_TtIntersectOne( pOff, 0, pDiv, 1, nWords ) ) + Vec_IntPush( vUnateLits, Abc_Var2Lit(i, 1) ); + else + Vec_IntPush( vNotUnateVars, i ); +} +int Gia_ManFindOneUnate( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits[2], Vec_Int_t * vNotUnateVars[2], int fVerbose ) +{ + int n; + if ( fVerbose ) printf( " " ); + for ( n = 0; n < 2; n++ ) + { + Gia_ManFindOneUnateInt( pSets[n], pSets[!n], vDivs, nWords, vUnateLits[n], vNotUnateVars[n] ); + if ( fVerbose ) printf( "U%d =%4d ", n, Vec_IntSize(vUnateLits[n]) ); + } + return Gia_ManFindFirstCommonLit( vUnateLits[0], vUnateLits[1], fVerbose ); +} + +static inline int Gia_ManDivCover( word * pOff, word * pOn, word * pDivA, int ComplA, word * pDivB, int ComplB, int nWords ) +{ + //assert( !Abc_TtIntersectOne(pOff, 0, pDivA, ComplA, nWords) ); + //assert( !Abc_TtIntersectOne(pOff, 0, pDivB, ComplB, nWords) ); + return !Abc_TtIntersectTwo( pOn, 0, pDivA, !ComplA, pDivB, !ComplB, nWords ); +} +int Gia_ManFindTwoUnateInt( word * pOff, word * pOn, Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits, Vec_Int_t * vUnateLitsW, int * pnPairs ) +{ + int i, k, iDiv0_, iDiv1_, Cover0, Cover1; + int nTotal = Abc_TtCountOnesVec( pOn, nWords ); + (*pnPairs) = 0; + Vec_IntForEachEntryTwo( vUnateLits, vUnateLitsW, iDiv0_, Cover0, i ) + { + if ( 2*Cover0 < nTotal ) + break; + Vec_IntForEachEntryTwoStart( vUnateLits, vUnateLitsW, iDiv1_, Cover1, k, i+1 ) + { + int iDiv0 = Abc_MinInt( iDiv0_, iDiv1_ ); + int iDiv1 = Abc_MaxInt( iDiv0_, iDiv1_ ); + word * pDiv0 = (word *)Vec_PtrEntry(vDivs, Abc_Lit2Var(iDiv0)); + word * pDiv1 = (word *)Vec_PtrEntry(vDivs, Abc_Lit2Var(iDiv1)); + if ( Cover0 + Cover1 < nTotal ) + break; + (*pnPairs)++; + if ( Gia_ManDivCover(pOff, pOn, pDiv1, Abc_LitIsCompl(iDiv1), pDiv0, Abc_LitIsCompl(iDiv0), nWords) ) + return Abc_Var2Lit((Abc_LitNot(iDiv1) << 15) | Abc_LitNot(iDiv0), 1); + } + } + return -1; +} +int Gia_ManFindTwoUnate( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits[2], Vec_Int_t * vUnateLitsW[2], int fVerbose ) +{ + int n, iLit, nPairs; + if ( fVerbose ) printf( " " ); + for ( n = 0; n < 2; n++ ) + { + //int nPairsAll = Vec_IntSize(vUnateLits[n])*(Vec_IntSize(vUnateLits[n])-1)/2; + iLit = Gia_ManFindTwoUnateInt( pSets[n], pSets[!n], vDivs, nWords, vUnateLits[n], vUnateLitsW[n], &nPairs ); + if ( fVerbose ) printf( "UU%d =%5d ", n, nPairs ); + if ( iLit >= 0 ) + return Abc_LitNotCond(iLit, n); + } + return -1; +} + +void Gia_ManFindXorInt( word * pOff, word * pOn, Vec_Int_t * vBinate, Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnatePairs ) +{ + int i, k, iDiv0_, iDiv1_; + int Limit2 = Vec_IntSize(vBinate);//Abc_MinInt( Vec_IntSize(vBinate), 100 ); + Vec_IntForEachEntryStop( vBinate, iDiv1_, i, Limit2 ) + Vec_IntForEachEntryStop( vBinate, iDiv0_, k, i ) + { + int iDiv0 = Abc_MinInt( iDiv0_, iDiv1_ ); + int iDiv1 = Abc_MaxInt( iDiv0_, iDiv1_ ); + word * pDiv0 = (word *)Vec_PtrEntry(vDivs, iDiv0); + word * pDiv1 = (word *)Vec_PtrEntry(vDivs, iDiv1); + if ( !Abc_TtIntersectXor( pOff, 0, pDiv0, pDiv1, 0, nWords ) ) + Vec_IntPush( vUnatePairs, Abc_Var2Lit((Abc_Var2Lit(iDiv0, 0) << 15) | Abc_Var2Lit(iDiv1, 0), 0) ); + else if ( !Abc_TtIntersectXor( pOff, 0, pDiv0, pDiv1, 1, nWords ) ) + Vec_IntPush( vUnatePairs, Abc_Var2Lit((Abc_Var2Lit(iDiv0, 0) << 15) | Abc_Var2Lit(iDiv1, 0), 1) ); + } +} +int Gia_ManFindXor( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vBinateVars, Vec_Int_t * vUnatePairs[2], int fVerbose ) +{ + int n; + if ( fVerbose ) printf( " " ); + for ( n = 0; n < 2; n++ ) + { + Vec_IntClear( vUnatePairs[n] ); + Gia_ManFindXorInt( pSets[n], pSets[!n], vBinateVars, vDivs, nWords, vUnatePairs[n] ); + if ( fVerbose ) printf( "UX%d =%5d ", n, Vec_IntSize(vUnatePairs[n]) ); + } + return Gia_ManFindFirstCommonLit( vUnatePairs[0], vUnatePairs[1], fVerbose ); +} + +void Gia_ManFindUnatePairsInt( word * pOff, word * pOn, Vec_Int_t * vBinate, Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnatePairs ) +{ + int n, i, k, iDiv0_, iDiv1_; + int Limit2 = Vec_IntSize(vBinate);//Abc_MinInt( Vec_IntSize(vBinate), 100 ); + Vec_IntForEachEntryStop( vBinate, iDiv1_, i, Limit2 ) + Vec_IntForEachEntryStop( vBinate, iDiv0_, k, i ) + { + int iDiv0 = Abc_MinInt( iDiv0_, iDiv1_ ); + int iDiv1 = Abc_MaxInt( iDiv0_, iDiv1_ ); + word * pDiv0 = (word *)Vec_PtrEntry(vDivs, iDiv0); + word * pDiv1 = (word *)Vec_PtrEntry(vDivs, iDiv1); + for ( n = 0; n < 4; n++ ) + { + int iLit0 = Abc_Var2Lit( iDiv0, n&1 ); + int iLit1 = Abc_Var2Lit( iDiv1, n>>1 ); + //if ( !Abc_TtIntersectTwo( pOff, 0, pDiv1, n>>1, pDiv0, n&1, nWords ) ) + if ( !Abc_TtIntersectTwo( pOff, 0, pDiv1, n>>1, pDiv0, n&1, nWords ) && Abc_TtIntersectTwo( pOn, 0, pDiv1, n>>1, pDiv0, n&1, nWords ) ) + Vec_IntPush( vUnatePairs, Abc_Var2Lit((iLit1 << 15) | iLit0, 0) ); + } + } +} +void Gia_ManFindUnatePairs( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vBinateVars, Vec_Int_t * vUnatePairs[2], int fVerbose ) +{ + int n, RetValue; + if ( fVerbose ) printf( " " ); + for ( n = 0; n < 2; n++ ) + { + int nBefore = Vec_IntSize(vUnatePairs[n]); + Gia_ManFindUnatePairsInt( pSets[n], pSets[!n], vBinateVars, vDivs, nWords, vUnatePairs[n] ); + if ( fVerbose ) printf( "UP%d =%5d ", n, Vec_IntSize(vUnatePairs[n])-nBefore ); + } + RetValue = Gia_ManFindFirstCommonLit( vUnatePairs[0], vUnatePairs[1], fVerbose ); + assert( RetValue == -1 ); +} + +void Gia_ManDeriveDivPair( int iDiv, Vec_Ptr_t * vDivs, int nWords, word * pRes ) +{ + int fComp = Abc_LitIsCompl(iDiv); + int iDiv0 = Abc_Lit2Var(iDiv) & 0x7FFF; + int iDiv1 = Abc_Lit2Var(iDiv) >> 15; + word * pDiv0 = (word *)Vec_PtrEntry(vDivs, Abc_Lit2Var(iDiv0)); + word * pDiv1 = (word *)Vec_PtrEntry(vDivs, Abc_Lit2Var(iDiv1)); + if ( iDiv0 < iDiv1 ) + { + assert( !fComp ); + Abc_TtAndCompl( pRes, pDiv0, Abc_LitIsCompl(iDiv0), pDiv1, Abc_LitIsCompl(iDiv1), nWords ); + } + else + { + assert( !Abc_LitIsCompl(iDiv0) ); + assert( !Abc_LitIsCompl(iDiv1) ); + Abc_TtXor( pRes, pDiv0, pDiv1, nWords, 0 ); + } +} +int Gia_ManFindDivGateInt( word * pOff, word * pOn, Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits, Vec_Int_t * vUnatePairs, Vec_Int_t * vUnateLitsW, Vec_Int_t * vUnatePairsW, word * pDivTemp ) +{ + int i, k, iDiv0, iDiv1, Cover0, Cover1; + int nTotal = Abc_TtCountOnesVec( pOn, nWords ); + Vec_IntForEachEntryTwo( vUnateLits, vUnateLitsW, iDiv0, Cover0, i ) + { + word * pDiv0 = (word *)Vec_PtrEntry(vDivs, Abc_Lit2Var(iDiv0)); + if ( 2*Cover0 < nTotal ) + break; + Vec_IntForEachEntryTwo( vUnatePairs, vUnatePairsW, iDiv1, Cover1, k ) + { + int fComp1 = Abc_LitIsCompl(iDiv1); + if ( Cover0 + Cover1 < nTotal ) + break; + Gia_ManDeriveDivPair( iDiv1, vDivs, nWords, pDivTemp ); + if ( Gia_ManDivCover(pOff, pOn, pDiv0, Abc_LitIsCompl(iDiv0), pDivTemp, fComp1, nWords) ) + return Abc_Var2Lit((Abc_Var2Lit(k, 1) << 15) | Abc_LitNot(iDiv0), 1); + } + } + return -1; +} +int Gia_ManFindDivGate( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits[2], Vec_Int_t * vUnatePairs[2], Vec_Int_t * vUnateLitsW[2], Vec_Int_t * vUnatePairsW[2], word * pDivTemp ) +{ + int n, iLit; + for ( n = 0; n < 2; n++ ) + { + iLit = Gia_ManFindDivGateInt( pSets[n], pSets[!n], vDivs, nWords, vUnateLits[n], vUnatePairs[n], vUnateLitsW[n], vUnatePairsW[n], pDivTemp ); + if ( iLit >= 0 ) + return Abc_LitNotCond( iLit, n ); + } + return -1; +} + +int Gia_ManFindGateGateInt( word * pOff, word * pOn, Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnatePairs, Vec_Int_t * vUnatePairsW, word * pDivTempA, word * pDivTempB ) +{ + int i, k, iDiv0, iDiv1, Cover0, Cover1; + int nTotal = Abc_TtCountOnesVec( pOn, nWords ); + Vec_IntForEachEntryTwo( vUnatePairs, vUnatePairsW, iDiv0, Cover0, k ) + { + int fCompA = Abc_LitIsCompl(iDiv0); + if ( 2*Cover0 < nTotal ) + break; + Gia_ManDeriveDivPair( iDiv0, vDivs, nWords, pDivTempA ); + Vec_IntForEachEntryTwoStart( vUnatePairs, vUnatePairsW, iDiv1, Cover1, i, k+1 ) + { + int fCompB = Abc_LitIsCompl(iDiv1); + if ( Cover0 + Cover1 < nTotal ) + break; + Gia_ManDeriveDivPair( iDiv1, vDivs, nWords, pDivTempB ); + if ( Gia_ManDivCover(pOff, pOn, pDivTempA, fCompA, pDivTempB, fCompB, nWords) ) + return Abc_Var2Lit((Abc_Var2Lit(i, 1) << 15) | Abc_Var2Lit(k, 1), 1); + } + } + return -1; +} +int Gia_ManFindGateGate( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnatePairs[2], Vec_Int_t * vUnatePairsW[2], word * pDivTempA, word * pDivTempB ) +{ + int n, iLit; + for ( n = 0; n < 2; n++ ) + { + iLit = Gia_ManFindGateGateInt( pSets[n], pSets[!n], vDivs, nWords, vUnatePairs[n], vUnatePairsW[n], pDivTempA, pDivTempB ); + if ( iLit >= 0 ) + return Abc_LitNotCond( iLit, n ); + } + return -1; +} + +void Gia_ManSortUnatesInt( word * pOff, word * pOn, Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits, Vec_Int_t * vUnateLitsW, Vec_Wec_t * vSorter ) +{ + int i, k, iLit; + Vec_Int_t * vLevel; + Vec_WecInit( vSorter, nWords*64 ); + Vec_IntForEachEntry( vUnateLits, iLit, i ) + { + word * pDiv = (word *)Vec_PtrEntry(vDivs, Abc_Lit2Var(iLit)); + //assert( !Abc_TtIntersectOne( pOff, 0, pDiv, Abc_LitIsCompl(iLit), nWords ) ); + Vec_WecPush( vSorter, Abc_TtCountOnesVecMask(pDiv, pOn, nWords, Abc_LitIsCompl(iLit)), iLit ); + } + Vec_IntClear( vUnateLits ); + Vec_IntClear( vUnateLitsW ); + Vec_WecForEachLevelReverse( vSorter, vLevel, k ) + Vec_IntForEachEntry( vLevel, iLit, i ) + { + Vec_IntPush( vUnateLits, iLit ); + Vec_IntPush( vUnateLitsW, k ); + } + //Vec_IntPrint( Vec_WecEntry(vSorter, 0) ); + Vec_WecClear( vSorter ); +} +void Gia_ManSortUnates( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits[2], Vec_Int_t * vUnateLitsW[2], Vec_Wec_t * vSorter ) +{ + int n; + for ( n = 0; n < 2; n++ ) + Gia_ManSortUnatesInt( pSets[n], pSets[!n], vDivs, nWords, vUnateLits[n], vUnateLitsW[n], vSorter ); +} + +void Gia_ManSortPairsInt( word * pOff, word * pOn, Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnatePairs, Vec_Int_t * vUnatePairsW, Vec_Wec_t * vSorter ) +{ + int i, k, iPair; + Vec_Int_t * vLevel; + Vec_WecInit( vSorter, nWords*64 ); + Vec_IntForEachEntry( vUnatePairs, iPair, i ) + { + int fComp = Abc_LitIsCompl(iPair); + int iLit0 = Abc_Lit2Var(iPair) & 0x7FFF; + int iLit1 = Abc_Lit2Var(iPair) >> 15; + word * pDiv0 = (word *)Vec_PtrEntry( vDivs, Abc_Lit2Var(iLit0) ); + word * pDiv1 = (word *)Vec_PtrEntry( vDivs, Abc_Lit2Var(iLit1) ); + if ( iLit0 < iLit1 ) + { + assert( !fComp ); + //assert( !Abc_TtIntersectTwo( pOff, 0, pDiv0, Abc_LitIsCompl(iLit0), pDiv1, Abc_LitIsCompl(iLit1), nWords ) ); + Vec_WecPush( vSorter, Abc_TtCountOnesVecMask2(pDiv0, pDiv1, Abc_LitIsCompl(iLit0), Abc_LitIsCompl(iLit1), pOn, nWords), iPair ); + } + else + { + assert( !Abc_LitIsCompl(iLit0) ); + assert( !Abc_LitIsCompl(iLit1) ); + //assert( !Abc_TtIntersectXor( pOff, 0, pDiv0, pDiv1, fComp, nWords ) ); + Vec_WecPush( vSorter, Abc_TtCountOnesVecXorMask(pDiv0, pDiv1, fComp, pOn, nWords), iPair ); + } + } + Vec_IntClear( vUnatePairs ); + Vec_IntClear( vUnatePairsW ); + Vec_WecForEachLevelReverse( vSorter, vLevel, k ) + Vec_IntForEachEntry( vLevel, iPair, i ) + { + Vec_IntPush( vUnatePairs, iPair ); + Vec_IntPush( vUnatePairsW, k ); + } + //Vec_IntPrint( Vec_WecEntry(vSorter, 0) ); + Vec_WecClear( vSorter ); + +} +void Gia_ManSortPairs( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vUnateLits[2], Vec_Int_t * vUnateLitsW[2], Vec_Wec_t * vSorter ) +{ + int n; + for ( n = 0; n < 2; n++ ) + Gia_ManSortPairsInt( pSets[n], pSets[!n], vDivs, nWords, vUnateLits[n], vUnateLitsW[n], vSorter ); +} + +void Gia_ManSortBinate( word * pSets[2], Vec_Ptr_t * vDivs, int nWords, Vec_Int_t * vBinateVars, Vec_Wec_t * vSorter ) +{ + Vec_Int_t * vLevel; + int nMints[2] = { Abc_TtCountOnesVec(pSets[0], nWords), Abc_TtCountOnesVec(pSets[1], nWords) }; + word * pBig = nMints[0] > nMints[1] ? pSets[0] : pSets[1]; + word * pSmo = nMints[0] > nMints[1] ? pSets[1] : pSets[0]; + int Big = Abc_MaxInt( nMints[0], nMints[1] ); + int Smo = Abc_MinInt( nMints[0], nMints[1] ); + int i, k, iDiv, Gain; + + Vec_WecInit( vSorter, nWords*64 ); + Vec_IntForEachEntry( vBinateVars, iDiv, i ) + { + word * pDiv = (word *)Vec_PtrEntry( vDivs, iDiv ); + int nInter[2] = { Abc_TtCountOnesVecMask(pBig, pDiv, nWords, 0), Abc_TtCountOnesVecMask(pSmo, pDiv, nWords, 0) }; + if ( nInter[0] < Big/2 ) // complement the divisor + { + nInter[0] = Big - nInter[0]; + nInter[1] = Smo - nInter[1]; + } + assert( nInter[0] >= Big/2 ); + Gain = Abc_MaxInt( 0, nInter[0] - Big/2 + Smo/2 - nInter[1] ); + Vec_WecPush( vSorter, Gain, iDiv ); + } + + Vec_IntClear( vBinateVars ); + Vec_WecForEachLevelReverse( vSorter, vLevel, k ) + Vec_IntForEachEntry( vLevel, iDiv, i ) + Vec_IntPush( vBinateVars, iDiv ); + Vec_WecClear( vSorter ); + + if ( Vec_IntSize(vBinateVars) > 2000 ) + Vec_IntShrink( vBinateVars, 2000 ); +} + +/**Function************************************************************* + + Synopsis [Perform resubstitution.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManResubFindBestBinate( Gia_ResbMan_t * p ) +{ + int nMintsAll = Abc_TtCountOnesVec(p->pSets[0], p->nWords) + Abc_TtCountOnesVec(p->pSets[1], p->nWords); + int i, iDiv, iLitBest = -1, CostBest = -1; +//Vec_IntPrint( p->vBinateVars ); +//Dau_DsdPrintFromTruth( p->pSets[0], 6 ); +//Dau_DsdPrintFromTruth( p->pSets[1], 6 ); + Vec_IntForEachEntry( p->vBinateVars, iDiv, i ) + { + word * pDiv = (word *)Vec_PtrEntry(p->vDivs, iDiv); + int nMints0 = Abc_TtCountOnesVecMask( pDiv, p->pSets[0], p->nWords, 0 ); + int nMints1 = Abc_TtCountOnesVecMask( pDiv, p->pSets[1], p->nWords, 0 ); + if ( CostBest < nMints0 + nMints1 ) + { + CostBest = nMints0 + nMints1; + iLitBest = Abc_Var2Lit( iDiv, 0 ); + } + if ( CostBest < nMintsAll - nMints0 - nMints1 ) + { + CostBest = nMintsAll - nMints0 - nMints1; + iLitBest = Abc_Var2Lit( iDiv, 1 ); + } + } + return iLitBest; +} +int Gia_ManResubAddNode( Gia_ResbMan_t * p, int iLit0, int iLit1, int Type ) +{ + int iNode = Vec_PtrSize(p->vDivs) + Vec_IntSize(p->vGates)/2; + int fFlip = (Type == 2) ^ (iLit0 > iLit1); + int iFan0 = fFlip ? iLit1 : iLit0; + int iFan1 = fFlip ? iLit0 : iLit1; + assert( iLit0 != iLit1 ); + if ( Type == 2 ) + assert( iFan0 > iFan1 ); + else + assert( iFan0 < iFan1 ); + Vec_IntPushTwo( p->vGates, Abc_LitNotCond(iFan0, Type==1), Abc_LitNotCond(iFan1, Type==1) ); + return Abc_Var2Lit( iNode, Type==1 ); +} +int Gia_ManResubPerformMux_rec( Gia_ResbMan_t * p, int nLimit, int Depth ) +{ + extern int Gia_ManResubPerform_rec( Gia_ResbMan_t * p, int nLimit, int Depth ); + int iDivBest, iResLit0, iResLit1, nNodes; + word * pDiv, * pCopy[2]; + if ( Depth == 0 ) + return -1; + if ( nLimit < 3 ) + return -1; + iDivBest = Gia_ManResubFindBestBinate( p ); + if ( iDivBest == -1 ) + return -1; + pCopy[0] = ABC_CALLOC( word, p->nWords ); + pCopy[1] = ABC_CALLOC( word, p->nWords ); + Abc_TtCopy( pCopy[0], p->pSets[0], p->nWords, 0 ); + Abc_TtCopy( pCopy[1], p->pSets[1], p->nWords, 0 ); + pDiv = (word *)Vec_PtrEntry( p->vDivs, Abc_Lit2Var(iDivBest) ); + Abc_TtAndSharp( p->pSets[0], pCopy[0], pDiv, p->nWords, !Abc_LitIsCompl(iDivBest) ); + Abc_TtAndSharp( p->pSets[1], pCopy[1], pDiv, p->nWords, !Abc_LitIsCompl(iDivBest) ); + nNodes = Vec_IntSize(p->vGates)/2; + //iResLit0 = Gia_ManResubPerform_rec( p, nLimit-3 ); + iResLit0 = Gia_ManResubPerform_rec( p, nLimit, 0 ); + if ( iResLit0 == -1 ) + iResLit0 = Gia_ManResubPerformMux_rec( p, nLimit, Depth-1 ); + if ( iResLit0 == -1 ) + { + ABC_FREE( pCopy[0] ); + ABC_FREE( pCopy[1] ); + return -1; + } + Abc_TtAndSharp( p->pSets[0], pCopy[0], pDiv, p->nWords, Abc_LitIsCompl(iDivBest) ); + Abc_TtAndSharp( p->pSets[1], pCopy[1], pDiv, p->nWords, Abc_LitIsCompl(iDivBest) ); + ABC_FREE( pCopy[0] ); + ABC_FREE( pCopy[1] ); + nNodes = Vec_IntSize(p->vGates)/2 - nNodes; + if ( nLimit-nNodes < 3 ) + return -1; + //iResLit1 = Gia_ManResubPerform_rec( p, nLimit-3-nNodes ); + iResLit1 = Gia_ManResubPerform_rec( p, nLimit, 0 ); + if ( iResLit1 == -1 ) + iResLit1 = Gia_ManResubPerformMux_rec( p, nLimit, Depth-1 ); + if ( iResLit1 == -1 ) + return -1; + else + { + int iLit0 = Gia_ManResubAddNode( p, Abc_LitNot(iDivBest), iResLit0, 0 ); + int iLit1 = Gia_ManResubAddNode( p, iDivBest, iResLit1, 0 ); + return Gia_ManResubAddNode( p, iLit0, iLit1, 1 ); + } +} + +/**Function************************************************************* + + Synopsis [Perform resubstitution.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManResubPerform_rec( Gia_ResbMan_t * p, int nLimit, int Depth ) +{ + int TopOneW[2] = {0}, TopTwoW[2] = {0}, Max1, Max2, iResLit, nVars = Vec_PtrSize(p->vDivs); + if ( p->fVerbose ) + { + int nMints[2] = { Abc_TtCountOnesVec(p->pSets[0], p->nWords), Abc_TtCountOnesVec(p->pSets[1], p->nWords) }; + printf( " " ); + printf( "ISF: " ); + printf( "0=%5d (%5.2f %%) ", nMints[0], 100.0*nMints[0]/(64*p->nWords) ); + printf( "1=%5d (%5.2f %%) ", nMints[1], 100.0*nMints[1]/(64*p->nWords) ); + } + if ( Abc_TtIsConst0( p->pSets[1], p->nWords ) ) + return 0; + if ( Abc_TtIsConst0( p->pSets[0], p->nWords ) ) + return 1; + iResLit = Gia_ManFindOneUnate( p->pSets, p->vDivs, p->nWords, p->vUnateLits, p->vNotUnateVars, p->fVerbose ); + if ( iResLit >= 0 ) // buffer + return iResLit; + if ( nLimit == 0 ) + return -1; + Gia_ManSortUnates( p->pSets, p->vDivs, p->nWords, p->vUnateLits, p->vUnateLitsW, p->vSorter ); + iResLit = Gia_ManFindTwoUnate( p->pSets, p->vDivs, p->nWords, p->vUnateLits, p->vUnateLitsW, p->fVerbose ); + if ( iResLit >= 0 ) // and + { + int iNode = nVars + Vec_IntSize(p->vGates)/2; + int fComp = Abc_LitIsCompl(iResLit); + int iDiv0 = Abc_Lit2Var(iResLit) & 0x7FFF; + int iDiv1 = Abc_Lit2Var(iResLit) >> 15; + assert( iDiv0 < iDiv1 ); + Vec_IntPushTwo( p->vGates, iDiv0, iDiv1 ); + return Abc_Var2Lit( iNode, fComp ); + } + Vec_IntTwoFindCommon( p->vNotUnateVars[0], p->vNotUnateVars[1], p->vBinateVars ); + if ( Depth ) + return Gia_ManResubPerformMux_rec( p, nLimit, Depth ); + if ( Vec_IntSize(p->vBinateVars) > p->nDivsMax ) + Vec_IntShrink( p->vBinateVars, p->nDivsMax ); + if ( p->fVerbose ) printf( " B = %3d", Vec_IntSize(p->vBinateVars) ); + //Gia_ManSortBinate( p->pSets, p->vDivs, p->nWords, p->vBinateVars, p->vSorter ); + if ( p->fUseXor ) + { + iResLit = Gia_ManFindXor( p->pSets, p->vDivs, p->nWords, p->vBinateVars, p->vUnatePairs, p->fVerbose ); + if ( iResLit >= 0 ) // xor + { + int iNode = nVars + Vec_IntSize(p->vGates)/2; + int fComp = Abc_LitIsCompl(iResLit); + int iDiv0 = Abc_Lit2Var(iResLit) & 0x7FFF; + int iDiv1 = Abc_Lit2Var(iResLit) >> 15; + assert( !Abc_LitIsCompl(iDiv0) ); + assert( !Abc_LitIsCompl(iDiv1) ); + assert( iDiv0 > iDiv1 ); + Vec_IntPushTwo( p->vGates, iDiv0, iDiv1 ); + return Abc_Var2Lit( iNode, fComp ); + } + } + if ( nLimit == 1 ) + return -1; + Gia_ManFindUnatePairs( p->pSets, p->vDivs, p->nWords, p->vBinateVars, p->vUnatePairs, p->fVerbose ); + Gia_ManSortPairs( p->pSets, p->vDivs, p->nWords, p->vUnatePairs, p->vUnatePairsW, p->vSorter ); + iResLit = Gia_ManFindDivGate( p->pSets, p->vDivs, p->nWords, p->vUnateLits, p->vUnatePairs, p->vUnateLitsW, p->vUnatePairsW, p->pDivA ); + if ( iResLit >= 0 ) // and(div,pair) + { + int iNode = nVars + Vec_IntSize(p->vGates)/2; + + int fComp = Abc_LitIsCompl(iResLit); + int iDiv0 = Abc_Lit2Var(iResLit) & 0x7FFF; // div + int iDiv1 = Abc_Lit2Var(iResLit) >> 15; // pair + + int Div1 = Vec_IntEntry( p->vUnatePairs[!fComp], Abc_Lit2Var(iDiv1) ); + int fComp1 = Abc_LitIsCompl(Div1) ^ Abc_LitIsCompl(iDiv1); + int iDiv10 = Abc_Lit2Var(Div1) & 0x7FFF; + int iDiv11 = Abc_Lit2Var(Div1) >> 15; + + Vec_IntPushTwo( p->vGates, iDiv10, iDiv11 ); + Vec_IntPushTwo( p->vGates, iDiv0, Abc_Var2Lit(iNode, fComp1) ); + return Abc_Var2Lit( iNode+1, fComp ); + } +// if ( nLimit == 2 ) +// return -1; + if ( nLimit >= 3 ) + { + iResLit = Gia_ManFindGateGate( p->pSets, p->vDivs, p->nWords, p->vUnatePairs, p->vUnatePairsW, p->pDivA, p->pDivB ); + if ( iResLit >= 0 ) // and(pair,pair) + { + int iNode = nVars + Vec_IntSize(p->vGates)/2; + + int fComp = Abc_LitIsCompl(iResLit); + int iDiv0 = Abc_Lit2Var(iResLit) & 0x7FFF; // pair + int iDiv1 = Abc_Lit2Var(iResLit) >> 15; // pair + + int Div0 = Vec_IntEntry( p->vUnatePairs[!fComp], Abc_Lit2Var(iDiv0) ); + int fComp0 = Abc_LitIsCompl(Div0) ^ Abc_LitIsCompl(iDiv0); + int iDiv00 = Abc_Lit2Var(Div0) & 0x7FFF; + int iDiv01 = Abc_Lit2Var(Div0) >> 15; + + int Div1 = Vec_IntEntry( p->vUnatePairs[!fComp], Abc_Lit2Var(iDiv1) ); + int fComp1 = Abc_LitIsCompl(Div1) ^ Abc_LitIsCompl(iDiv1); + int iDiv10 = Abc_Lit2Var(Div1) & 0x7FFF; + int iDiv11 = Abc_Lit2Var(Div1) >> 15; + + Vec_IntPushTwo( p->vGates, iDiv00, iDiv01 ); + Vec_IntPushTwo( p->vGates, iDiv10, iDiv11 ); + Vec_IntPushTwo( p->vGates, Abc_Var2Lit(iNode, fComp0), Abc_Var2Lit(iNode+1, fComp1) ); + return Abc_Var2Lit( iNode+2, fComp ); + } + } +// if ( nLimit == 3 ) +// return -1; + if ( Vec_IntSize(p->vUnateLits[0]) + Vec_IntSize(p->vUnateLits[1]) + Vec_IntSize(p->vUnatePairs[0]) + Vec_IntSize(p->vUnatePairs[1]) == 0 ) + return -1; + + TopOneW[0] = Vec_IntSize(p->vUnateLitsW[0]) ? Vec_IntEntry(p->vUnateLitsW[0], 0) : 0; + TopOneW[1] = Vec_IntSize(p->vUnateLitsW[1]) ? Vec_IntEntry(p->vUnateLitsW[1], 0) : 0; + + TopTwoW[0] = Vec_IntSize(p->vUnatePairsW[0]) ? Vec_IntEntry(p->vUnatePairsW[0], 0) : 0; + TopTwoW[1] = Vec_IntSize(p->vUnatePairsW[1]) ? Vec_IntEntry(p->vUnatePairsW[1], 0) : 0; + + Max1 = Abc_MaxInt(TopOneW[0], TopOneW[1]); + Max2 = Abc_MaxInt(TopTwoW[0], TopTwoW[1]); + if ( Abc_MaxInt(Max1, Max2) == 0 ) + return -1; + + if ( Max1 > Max2/2 ) + { + if ( nLimit >= 2 && (Max1 == TopOneW[0] || Max1 == TopOneW[1]) ) + { + int fUseOr = Max1 == TopOneW[0]; + int iDiv = Vec_IntEntry( p->vUnateLits[!fUseOr], 0 ); + int fComp = Abc_LitIsCompl(iDiv); + word * pDiv = (word *)Vec_PtrEntry( p->vDivs, Abc_Lit2Var(iDiv) ); + Abc_TtAndSharp( p->pSets[fUseOr], p->pSets[fUseOr], pDiv, p->nWords, !fComp ); + if ( p->fVerbose ) + printf( "\n" ); + iResLit = Gia_ManResubPerform_rec( p, nLimit-1, Depth ); + if ( iResLit >= 0 ) + { + int iNode = nVars + Vec_IntSize(p->vGates)/2; + if ( iDiv < iResLit ) + Vec_IntPushTwo( p->vGates, Abc_LitNot(iDiv), Abc_LitNotCond(iResLit, fUseOr) ); + else + Vec_IntPushTwo( p->vGates, Abc_LitNotCond(iResLit, fUseOr), Abc_LitNot(iDiv) ); + return Abc_Var2Lit( iNode, fUseOr ); + } + } + if ( Max2 == 0 ) + return -1; +/* + if ( Max2 == TopTwoW[0] || Max2 == TopTwoW[1] ) + { + int fUseOr = Max2 == TopTwoW[0]; + int iDiv = Vec_IntEntry( p->vUnatePairs[!fUseOr], 0 ); + int fComp = Abc_LitIsCompl(iDiv); + Gia_ManDeriveDivPair( iDiv, p->vDivs, p->nWords, p->pDivA ); + Abc_TtAndSharp( p->pSets[fUseOr], p->pSets[fUseOr], p->pDivA, p->nWords, !fComp ); + if ( p->fVerbose ) + printf( "\n " ); + iResLit = Gia_ManResubPerform_rec( p, nLimit-2 ); + if ( iResLit >= 0 ) + { + int iNode = nVars + Vec_IntSize(p->vGates)/2; + int iDiv0 = Abc_Lit2Var(iDiv) & 0x7FFF; + int iDiv1 = Abc_Lit2Var(iDiv) >> 15; + Vec_IntPushTwo( p->vGates, iDiv0, iDiv1 ); + Vec_IntPushTwo( p->vGates, Abc_LitNotCond(iResLit, fUseOr), Abc_Var2Lit(iNode, !fComp) ); + return Abc_Var2Lit( iNode+1, fUseOr ); + } + } +*/ + } + else + { + if ( nLimit >= 3 && (Max2 == TopTwoW[0] || Max2 == TopTwoW[1]) ) + { + int fUseOr = Max2 == TopTwoW[0]; + int iDiv = Vec_IntEntry( p->vUnatePairs[!fUseOr], 0 ); + int fComp = Abc_LitIsCompl(iDiv); + Gia_ManDeriveDivPair( iDiv, p->vDivs, p->nWords, p->pDivA ); + Abc_TtAndSharp( p->pSets[fUseOr], p->pSets[fUseOr], p->pDivA, p->nWords, !fComp ); + if ( p->fVerbose ) + printf( "\n" ); + iResLit = Gia_ManResubPerform_rec( p, nLimit-2, Depth ); + if ( iResLit >= 0 ) + { + int iNode = nVars + Vec_IntSize(p->vGates)/2; + int iDiv0 = Abc_Lit2Var(iDiv) & 0x7FFF; + int iDiv1 = Abc_Lit2Var(iDiv) >> 15; + Vec_IntPushTwo( p->vGates, iDiv0, iDiv1 ); + Vec_IntPushTwo( p->vGates, Abc_LitNotCond(iResLit, fUseOr), Abc_Var2Lit(iNode, !fComp) ); + return Abc_Var2Lit( iNode+1, fUseOr ); + } + } + if ( Max1 == 0 ) + return -1; +/* + if ( Max1 == TopOneW[0] || Max1 == TopOneW[1] ) + { + int fUseOr = Max1 == TopOneW[0]; + int iDiv = Vec_IntEntry( p->vUnateLits[!fUseOr], 0 ); + int fComp = Abc_LitIsCompl(iDiv); + word * pDiv = (word *)Vec_PtrEntry( p->vDivs, Abc_Lit2Var(iDiv) ); + Abc_TtAndSharp( p->pSets[fUseOr], p->pSets[fUseOr], pDiv, p->nWords, !fComp ); + if ( p->fVerbose ) + printf( "\n " ); + iResLit = Gia_ManResubPerform_rec( p, nLimit-1 ); + if ( iResLit >= 0 ) + { + int iNode = nVars + Vec_IntSize(p->vGates)/2; + Vec_IntPushTwo( p->vGates, Abc_LitNot(iDiv), Abc_LitNotCond(iResLit, fUseOr) ); + return Abc_Var2Lit( iNode, fUseOr ); + } + } +*/ + } + return -1; +} +void Gia_ManResubPerform( Gia_ResbMan_t * p, Vec_Ptr_t * vDivs, int nWords, int nLimit, int nDivsMax, int iChoice, int fUseXor, int fDebug, int fVerbose, int Depth ) +{ + int Res; + Gia_ResbInit( p, vDivs, nWords, nLimit, nDivsMax, iChoice, fUseXor, fDebug, fVerbose, fVerbose ); + Res = Gia_ManResubPerform_rec( p, nLimit, Depth ); + if ( Res >= 0 ) + Vec_IntPush( p->vGates, Res ); + else + Vec_IntClear( p->vGates ); + if ( fVerbose ) + printf( "\n" ); +} +Vec_Int_t * Gia_ManResubOne( Vec_Ptr_t * vDivs, int nWords, int nLimit, int nDivsMax, int iChoice, int fUseXor, int fDebug, int fVerbose, word * pFunc, int Depth ) +{ + Vec_Int_t * vRes; + Gia_ResbMan_t * p = Gia_ResbAlloc( nWords ); + Gia_ManResubPerform( p, vDivs, nWords, nLimit, nDivsMax, iChoice, fUseXor, fDebug, fVerbose, Depth ); + if ( fVerbose ) + Gia_ManResubPrint( p->vGates, Vec_PtrSize(vDivs) ); + //if ( fVerbose ) + // printf( "\n" ); + if ( !Gia_ManResubVerify(p, pFunc) ) + { + Gia_ManResubPrint( p->vGates, Vec_PtrSize(vDivs) ); + printf( "Verification FAILED.\n" ); + } + else if ( fDebug && fVerbose ) + printf( "Verification succeeded." ); + if ( fVerbose ) + printf( "\n" ); + vRes = Vec_IntDup( p->vGates ); + Gia_ResbFree( p ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [Top level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Gia_ResbMan_t * s_pResbMan = NULL; + +void Abc_ResubPrepareManager( int nWords ) +{ + if ( s_pResbMan != NULL ) + Gia_ResbFree( s_pResbMan ); + s_pResbMan = NULL; + if ( nWords > 0 ) + s_pResbMan = Gia_ResbAlloc( nWords ); +} + +int Abc_ResubComputeFunction( void ** ppDivs, int nDivs, int nWords, int nLimit, int nDivsMax, int iChoice, int fUseXor, int fDebug, int fVerbose, int ** ppArray ) +{ + Vec_Ptr_t Divs = { nDivs, nDivs, ppDivs }; + assert( s_pResbMan != NULL ); // first call Abc_ResubPrepareManager() + Gia_ManResubPerform( s_pResbMan, &Divs, nWords, nLimit, nDivsMax, iChoice, fUseXor, fDebug, fVerbose==2, 0 ); + if ( fVerbose ) + { + int nGates = Vec_IntSize(s_pResbMan->vGates)/2; + if ( nGates ) + { + printf( " Gain = %2d Gates = %2d __________ F = ", nLimit+1-nGates, nGates ); + Gia_ManResubPrint( s_pResbMan->vGates, nDivs ); + printf( "\n" ); + } + } + if ( fDebug ) + { + if ( !Gia_ManResubVerify(s_pResbMan, NULL) ) + { + Gia_ManResubPrint( s_pResbMan->vGates, nDivs ); + printf( "Verification FAILED.\n" ); + } + //else + // printf( "Verification succeeded.\n" ); + } + *ppArray = Vec_IntArray(s_pResbMan->vGates); + assert( Vec_IntSize(s_pResbMan->vGates)/2 <= nLimit ); + return Vec_IntSize(s_pResbMan->vGates); +} + +void Abc_ResubDumpProblem( char * pFileName, void ** ppDivs, int nDivs, int nWords ) +{ + Vec_Wrd_t * vSims = Vec_WrdAlloc( nDivs * nWords ); + word ** pDivs = (word **)ppDivs; + int d, w; + for ( d = 0; d < nDivs; d++ ) + for ( w = 0; w < nWords; w++ ) + Vec_WrdPush( vSims, pDivs[d][w] ); + Vec_WrdDumpHex( pFileName, vSims, nWords, 1 ); + Vec_WrdFree( vSims ); +} + +/**Function************************************************************* + + Synopsis [Top level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +extern void Extra_PrintHex( FILE * pFile, unsigned * pTruth, int nVars ); +extern void Dau_DsdPrintFromTruth2( word * pTruth, int nVarsInit ); + +void Gia_ManResubTest3() +{ + int nVars = 4; + int fVerbose = 1; + word Divs[6] = { 0, 0, + ABC_CONST(0xAAAAAAAAAAAAAAAA), + ABC_CONST(0xCCCCCCCCCCCCCCCC), + ABC_CONST(0xF0F0F0F0F0F0F0F0), + ABC_CONST(0xFF00FF00FF00FF00) + }; + Vec_Ptr_t * vDivs = Vec_PtrAlloc( 6 ); + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); + int i, k, ArraySize, * pArray; + for ( i = 0; i < 6; i++ ) + Vec_PtrPush( vDivs, Divs+i ); + Abc_ResubPrepareManager( 1 ); + for ( i = 0; i < (1<<(1<vGates, Vec_PtrSize(vDivs) ); + printf( "\n" ); + //Vec_PtrFree( vDivs ); + Gia_ResbFree( p ); +} + +/**Function************************************************************* + + Synopsis [Top level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCheckResub( Vec_Ptr_t * vDivs, int nWords ) +{ + //int i, nVars = 6, pVarSet[10] = { 2, 189, 2127, 2125, 177, 178 }; + int i, nVars = 3, pVarSet[10] = { 2, 3, 4 }; + word * pOff = (word *)Vec_PtrEntry( vDivs, 0 ); + word * pOn = (word *)Vec_PtrEntry( vDivs, 1 ); + Vec_Int_t * vValue = Vec_IntStartFull( 1 << 6 ); + printf( "Verifying resub:\n" ); + for ( i = 0; i < 64*nWords; i++ ) + { + int v, Mint = 0, Value = Abc_TtGetBit(pOn, i); + if ( !Abc_TtGetBit(pOff, i) && !Value ) + continue; + for ( v = 0; v < nVars; v++ ) + if ( Abc_TtGetBit((word *)Vec_PtrEntry(vDivs, pVarSet[v]), i) ) + Mint |= 1 << v; + if ( Vec_IntEntry(vValue, Mint) == -1 ) + Vec_IntWriteEntry(vValue, Mint, Value); + else if ( Vec_IntEntry(vValue, Mint) != Value ) + printf( "Mismatch in pattern %d\n", i ); + } + printf( "Finished verifying resub.\n" ); + Vec_IntFree( vValue ); +} +Vec_Ptr_t * Gia_ManDeriveDivs( Vec_Wrd_t * vSims, int nWords ) +{ + int i, nDivs = Vec_WrdSize(vSims)/nWords; + Vec_Ptr_t * vDivs = Vec_PtrAlloc( nDivs ); + for ( i = 0; i < nDivs; i++ ) + Vec_PtrPush( vDivs, Vec_WrdEntryP(vSims, nWords*i) ); + return vDivs; +} +Gia_Man_t * Gia_ManResub2( Gia_Man_t * pGia, int nNodes, int nSupp, int nDivs, int iChoice, int fUseXor, int fVerbose, int fVeryVerbose ) +{ + return NULL; +} +Gia_Man_t * Gia_ManResub1( char * pFileName, int nNodes, int nSupp, int nDivs, int iChoice, int fUseXor, int fVerbose, int fVeryVerbose ) +{ + int nWords = 0; + Gia_Man_t * pMan = NULL; + Vec_Wrd_t * vSims = Vec_WrdReadHex( pFileName, &nWords, 1 ); + Vec_Ptr_t * vDivs = vSims ? Gia_ManDeriveDivs( vSims, nWords ) : NULL; + Gia_ResbMan_t * p = Gia_ResbAlloc( nWords ); + //Gia_ManCheckResub( vDivs, nWords ); + if ( Vec_PtrSize(vDivs) >= (1<<14) ) + { + printf( "Reducing all divs from %d to %d.\n", Vec_PtrSize(vDivs), (1<<14)-1 ); + Vec_PtrShrink( vDivs, (1<<14)-1 ); + } + assert( Vec_PtrSize(vDivs) < (1<<14) ); + Gia_ManResubPerform( p, vDivs, nWords, 100, 50, iChoice, fUseXor, 1, 1, 0 ); + if ( Vec_IntSize(p->vGates) ) + { + Vec_Wec_t * vGates = Vec_WecStart(1); + Vec_IntAppend( Vec_WecEntry(vGates, 0), p->vGates ); + pMan = Gia_ManConstructFromGates( vGates, Vec_PtrSize(vDivs) ); + Vec_WecFree( vGates ); + } + else + printf( "Decomposition did not succeed.\n" ); + Gia_ResbFree( p ); + Vec_PtrFree( vDivs ); + Vec_WrdFree( vSims ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManUnivTfo_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vNodes, Vec_Int_t * vPos ) +{ + int i, iFan, Count = 1; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return 0; + Gia_ObjSetTravIdCurrentId(p, iObj); + if ( vNodes && Gia_ObjIsCo(Gia_ManObj(p, iObj)) ) + Vec_IntPush( vNodes, iObj ); + if ( vPos && Gia_ObjIsCo(Gia_ManObj(p, iObj)) ) + Vec_IntPush( vPos, iObj ); + Gia_ObjForEachFanoutStaticId( p, iObj, iFan, i ) + Count += Gia_ManUnivTfo_rec( p, iFan, vNodes, vPos ); + return Count; +} +int Gia_ManUnivTfo( Gia_Man_t * p, int * pObjs, int nObjs, Vec_Int_t ** pvNodes, Vec_Int_t ** pvPos ) +{ + int i, Count = 0; + if ( pvNodes ) + { + if ( *pvNodes ) + Vec_IntClear( *pvNodes ); + else + *pvNodes = Vec_IntAlloc( 100 ); + } + if ( pvPos ) + { + if ( *pvPos ) + Vec_IntClear( *pvPos ); + else + *pvPos = Vec_IntAlloc( 100 ); + } + Gia_ManIncrementTravId( p ); + for ( i = 0; i < nObjs; i++ ) + Count += Gia_ManUnivTfo_rec( p, pObjs[i], pvNodes ? *pvNodes : NULL, pvPos ? *pvPos : NULL ); + if ( pvNodes ) + Vec_IntSort( *pvNodes, 0 ); + if ( pvPos ) + Vec_IntSort( *pvPos, 0 ); + return Count; +} + +/**Function************************************************************* + + Synopsis [Tuning resub.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManTryResub( Gia_Man_t * p ) +{ + int nLimit = 20; + int nDivsMax = 200; + int iChoice = 0; + int fUseXor = 1; + int fDebug = 1; + int fVerbose = 0; + abctime clk, clkResub = 0, clkStart = Abc_Clock(); + Vec_Ptr_t * vvSims = Vec_PtrAlloc( 100 ); + Vec_Wrd_t * vSims; + word * pSets[2], * pFunc; + Gia_Obj_t * pObj, * pObj2; + int i, i2, nWords, nNonDec = 0, nTotal = 0; + assert( Gia_ManCiNum(p) < 16 ); + Vec_WrdFreeP( &p->vSimsPi ); + p->vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(p) ); + nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + //Vec_WrdPrintHex( p->vSimsPi, nWords ); + pSets[0] = ABC_CALLOC( word, nWords ); + pSets[1] = ABC_CALLOC( word, nWords ); + vSims = Gia_ManSimPatSim( p ); + Gia_ManLevelNum(p); + Gia_ManCreateRefs(p); + Abc_ResubPrepareManager( nWords ); + Gia_ManStaticFanoutStart( p ); + Gia_ManForEachAnd( p, pObj, i ) + { + Vec_Int_t vGates; + int * pArray, nArray, nTfo, iObj = Gia_ObjId(p, pObj); + int Level = Gia_ObjLevel(p, pObj); + int nMffc = Gia_NodeMffcSizeMark(p, pObj); + pFunc = Vec_WrdEntryP( vSims, nWords*iObj ); + Abc_TtCopy( pSets[0], pFunc, nWords, 1 ); + Abc_TtCopy( pSets[1], pFunc, nWords, 0 ); + Vec_PtrClear( vvSims ); + Vec_PtrPushTwo( vvSims, pSets[0], pSets[1] ); + nTfo = Gia_ManUnivTfo( p, &iObj, 1, NULL, NULL ); + Gia_ManForEachCi( p, pObj2, i2 ) + Vec_PtrPush( vvSims, Vec_WrdEntryP(vSims, nWords*Gia_ObjId(p, pObj2)) ); + Gia_ManForEachAnd( p, pObj2, i2 ) + if ( !Gia_ObjIsTravIdCurrent(p, pObj2) && !Gia_ObjIsTravIdPrevious(p, pObj2) && Gia_ObjLevel(p, pObj2) <= Level ) + Vec_PtrPush( vvSims, Vec_WrdEntryP(vSims, nWords*Gia_ObjId(p, pObj2)) ); + if ( fVerbose ) + printf( "%3d : Lev = %2d Mffc = %2d Divs = %3d Tfo = %3d\n", iObj, Level, nMffc, Vec_PtrSize(vvSims)-2, nTfo ); + clk = Abc_Clock(); + nArray = Abc_ResubComputeFunction( (void **)Vec_PtrArray(vvSims), Vec_PtrSize(vvSims), nWords, Abc_MinInt(nMffc-1, nLimit), nDivsMax, iChoice, fUseXor, fDebug, fVerbose, &pArray ); + clkResub += Abc_Clock() - clk; + vGates.nSize = vGates.nCap = nArray; + vGates.pArray = pArray; + assert( nMffc > Vec_IntSize(&vGates)/2 ); + if ( Vec_IntSize(&vGates) > 0 ) + nTotal += nMffc - Vec_IntSize(&vGates)/2; + nNonDec += Vec_IntSize(&vGates) == 0; + } + printf( "Total nodes = %5d. Non-realizable = %5d. Gain = %6d. ", Gia_ManAndNum(p), nNonDec, nTotal ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart ); + Abc_PrintTime( 1, "Pure resub time", clkResub ); + Abc_ResubPrepareManager( 0 ); + Gia_ManStaticFanoutStop( p ); + Vec_PtrFree( vvSims ); + Vec_WrdFree( vSims ); + ABC_FREE( pSets[0] ); + ABC_FREE( pSets[1] ); +} + + +/**Function************************************************************* + + Synopsis [Deriving a subset.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManDeriveShrink( Vec_Wrd_t * vFuncs, int nWords ) +{ + int i, k = 0, nFuncs = Vec_WrdSize(vFuncs) / nWords / 2; + assert( 2 * nFuncs * nWords == Vec_WrdSize(vFuncs) ); + for ( i = 0; i < nFuncs; i++ ) + { + word * pFunc0 = Vec_WrdEntryP(vFuncs, (2*i+0)*nWords); + word * pFunc1 = Vec_WrdEntryP(vFuncs, (2*i+1)*nWords); + if ( Abc_TtIsConst0(pFunc0, nWords) || Abc_TtIsConst0(pFunc1, nWords) ) + continue; + if ( k < i ) Abc_TtCopy( Vec_WrdEntryP(vFuncs, (2*k+0)*nWords), pFunc0, nWords, 0 ); + if ( k < i ) Abc_TtCopy( Vec_WrdEntryP(vFuncs, (2*k+1)*nWords), pFunc1, nWords, 0 ); + k++; + } + Vec_WrdShrink( vFuncs, 2*k*nWords ); + return k; +} +void Gia_ManDeriveCounts( Vec_Wrd_t * vFuncs, int nWords, Vec_Int_t * vCounts ) +{ + int i, nFuncs = Vec_WrdSize(vFuncs) / nWords / 2; + assert( 2 * nFuncs * nWords == Vec_WrdSize(vFuncs) ); + Vec_IntClear( vCounts ); + for ( i = 0; i < 2*nFuncs; i++ ) + Vec_IntPush( vCounts, Abc_TtCountOnesVec(Vec_WrdEntryP(vFuncs, i*nWords), nWords) ); +} +int Gia_ManDeriveCost( Vec_Wrd_t * vFuncs, int nWords, word * pMask, Vec_Int_t * vCounts ) +{ + int i, Res = 0, nFuncs = Vec_WrdSize(vFuncs) / nWords / 2; + assert( 2 * nFuncs * nWords == Vec_WrdSize(vFuncs) ); + assert( Vec_IntSize(vCounts) * nWords == Vec_WrdSize(vFuncs) ); + for ( i = 0; i < nFuncs; i++ ) + { + int Total[2] = { Vec_IntEntry(vCounts, 2*i+0), Vec_IntEntry(vCounts, 2*i+1) }; + int This[2] = { Abc_TtCountOnesVecMask(Vec_WrdEntryP(vFuncs, (2*i+0)*nWords), pMask, nWords, 0), + Abc_TtCountOnesVecMask(Vec_WrdEntryP(vFuncs, (2*i+1)*nWords), pMask, nWords, 0) }; + assert( Total[0] >= This[0] && Total[1] >= This[1] ); + Res += This[0] * This[1] + (Total[0] - This[0]) * (Total[1] - This[1]); + } + return Res; +} +int Gia_ManDeriveSimpleCost( Vec_Int_t * vCounts ) +{ + int i, Ent1, Ent2, Res = 0; + Vec_IntForEachEntryDouble( vCounts, Ent1, Ent2, i ) + Res += Ent1*Ent2; + return Res; +} +void Gia_ManDeriveNext( Vec_Wrd_t * vFuncs, int nWords, word * pMask ) +{ + int i, iStop = Vec_WrdSize(vFuncs); word Data; + int nFuncs = Vec_WrdSize(vFuncs) / nWords / 2; + assert( 2 * nFuncs * nWords == Vec_WrdSize(vFuncs) ); + Vec_WrdForEachEntryStop( vFuncs, Data, i, iStop ) + Vec_WrdPush( vFuncs, Data ); + for ( i = 0; i < nFuncs; i++ ) + { + word * pFunc0n = Vec_WrdEntryP(vFuncs, (2*i+0)*nWords); + word * pFunc1n = Vec_WrdEntryP(vFuncs, (2*i+1)*nWords); + word * pFunc0p = Vec_WrdEntryP(vFuncs, (2*i+0)*nWords + iStop); + word * pFunc1p = Vec_WrdEntryP(vFuncs, (2*i+1)*nWords + iStop); + Abc_TtAnd( pFunc0p, pFunc0n, pMask, nWords, 0 ); + Abc_TtAnd( pFunc1p, pFunc1n, pMask, nWords, 0 ); + Abc_TtSharp( pFunc0n, pFunc0n, pMask, nWords ); + Abc_TtSharp( pFunc1n, pFunc1n, pMask, nWords ); + } +} +Vec_Int_t * Gia_ManDeriveSubset( Gia_Man_t * p, Vec_Wrd_t * vFuncs, Vec_Int_t * vObjs, Vec_Wrd_t * vSims, int nWords, int fVerbose ) +{ + int i, k, iObj, CostBestPrev, nFuncs = Vec_WrdSize(vFuncs) / nWords; + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); + Vec_Int_t * vCounts = Vec_IntAlloc( nFuncs * 2 ); + Vec_Wrd_t * vFSims = Vec_WrdDup( vFuncs ); + assert( nFuncs * nWords == Vec_WrdSize(vFuncs) ); + assert( Gia_ManObjNum(p) * nWords == Vec_WrdSize(vSims) ); + assert( Vec_IntSize(vObjs) <= Gia_ManCandNum(p) ); + nFuncs = Gia_ManDeriveShrink( vFSims, nWords ); + Gia_ManDeriveCounts( vFSims, nWords, vCounts ); + assert( Vec_IntSize(vCounts) * nWords == Vec_WrdSize(vFSims) ); + CostBestPrev = Gia_ManDeriveSimpleCost( vCounts ); + if ( fVerbose ) + printf( "Processing %d functions and %d objects with cost %d\n", nFuncs, Vec_IntSize(vObjs), CostBestPrev ); + for ( i = 0; nFuncs > 0; i++ ) + { + int iObjBest = -1, CountThis, Count0 = ABC_INFINITY, CountBest = ABC_INFINITY; + Vec_IntForEachEntry( vObjs, iObj, k ) + { + if ( Vec_IntFind(vRes, iObj) >= 0 ) + continue; + CountThis = Gia_ManDeriveCost( vFSims, nWords, Vec_WrdEntryP(vSims, iObj*nWords), vCounts ); + if ( CountBest > CountThis ) + { + CountBest = CountThis; + iObjBest = iObj; + } + if ( !k ) Count0 = CountThis; + } + if ( Count0 < CostBestPrev ) + { + CountBest = Count0; + iObjBest = Vec_IntEntry(vObjs, 0); + } + Gia_ManDeriveNext( vFSims, nWords, Vec_WrdEntryP(vSims, iObjBest*nWords) ); + nFuncs = Gia_ManDeriveShrink( vFSims, nWords ); + Gia_ManDeriveCounts( vFSims, nWords, vCounts ); + assert( CountBest == Gia_ManDeriveSimpleCost(vCounts) ); + Vec_IntPush( vRes, iObjBest ); + CostBestPrev = CountBest; + if ( fVerbose ) + printf( "Iter %2d : Funcs = %6d. Object %6d. Cost %6d.\n", i, nFuncs, iObjBest, CountBest ); + } + Vec_IntFree( vCounts ); + Vec_WrdFree( vFSims ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManResubFindUsed( Vec_Int_t * vRes, int nDivs, int nNodes, Vec_Int_t * vSupp ) +{ + int i, k, iLit, Counter = 1; + Vec_Int_t * vUsed = Vec_IntStartFull( nDivs ); + Vec_Int_t * vRes2 = Vec_IntDup( vRes ); + Vec_IntWriteEntry( vUsed, 0, 0 ); + assert( Vec_IntSize(vRes) % 2 == 1 ); + Vec_IntSort( vRes2, 0 ); + Vec_IntForEachEntry( vRes2, iLit, k ) + { + int iVar = Abc_Lit2Var(iLit); + if ( iVar > 0 && iVar < nDivs && Vec_IntEntry(vUsed, iVar) == -1 ) { + Vec_IntWriteEntry( vUsed, iVar, Counter++ ); + Vec_IntPush( vSupp, iVar-2 ); + } + } + Vec_IntFree( vRes2 ); + for ( i = nDivs; i < nDivs + nNodes; i++ ) + Vec_IntPush( vUsed, Counter++ ); + return vUsed; +} +Vec_Int_t * Gia_ManResubRemapSolution( Vec_Int_t * vRes, Vec_Int_t * vUsed ) +{ + int i, iLit; + Vec_Int_t * vResNew = Vec_IntAlloc( Vec_IntSize(vRes) ); + Vec_IntForEachEntry( vRes, iLit, i ) + Vec_IntPush( vResNew, Abc_Lit2LitV(Vec_IntArray(vUsed), iLit) ); + return vResNew; +} +void Gia_ManResubRecordSolution( char * pFileName, Vec_Int_t * vRes, int nDivs ) +{ + FILE * pFile = fopen( pFileName, "ab" ); + if ( pFile == NULL ) { + printf( "Cannot open file \"%s\" for writing.\n", pFileName ); + return; + } + Vec_Int_t * vSupp = Vec_IntAlloc( 100 ); + Vec_Int_t * vUsed = Gia_ManResubFindUsed( vRes, nDivs, Vec_IntSize(vRes)/2, vSupp ); + Vec_Int_t * vResN = Gia_ManResubRemapSolution( vRes, vUsed ); + + int i, Temp; + fprintf( pFile, "\n.s" ); + Vec_IntForEachEntry( vSupp, Temp, i ) + fprintf( pFile, " %d", Temp ); + fprintf( pFile, "\n.a" ); + Vec_IntForEachEntry( vResN, Temp, i ) + fprintf( pFile, " %d", Temp ); + fprintf( pFile, "\n" ); + fclose( pFile ); + + Vec_IntFree( vUsed ); + Vec_IntFree( vSupp ); + Vec_IntFree( vResN ); +} +Gia_Man_t * Gia_ManResubUnateOne( char * pFileName, int nLimit, int nDivMax, int fWriteSol, int fVerbose ) +{ + Gia_Man_t * pNew = NULL; + Abc_RData_t * p = Abc_ReadPla( pFileName ); + if ( p == NULL ) return NULL; + assert( p->nOuts == 1 ); + Vec_Ptr_t * vDivs = Vec_PtrAlloc( 2+p->nIns ); + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); + Vec_PtrPush( vDivs, Vec_WrdEntryP(p->vSimsOut, 0*p->nSimWords) ); + Vec_PtrPush( vDivs, Vec_WrdEntryP(p->vSimsOut, 1*p->nSimWords) ); + int i, k, ArraySize, * pArray; + for ( i = 0; i < p->nIns; i++ ) + Vec_PtrPush( vDivs, Vec_WrdEntryP(p->vSimsIn, i*p->nSimWords) ); + Abc_ResubPrepareManager( p->nSimWords ); + if ( fVerbose ) + printf( "The problem has %d divisors and %d outputs.\n", p->nIns, p->nOuts ); + ArraySize = Abc_ResubComputeFunction( (void **)Vec_PtrArray(vDivs), Vec_PtrSize(vDivs), p->nSimWords, nLimit, nDivMax, 0, 0, 1, fVerbose, &pArray ); + for ( k = 0; k < ArraySize; k++ ) + Vec_IntPush( vRes, pArray[k] ); + if ( ArraySize ) { + //Vec_IntPrint( vRes ); + Vec_Wec_t * vGates = Vec_WecStart(1); + Vec_IntAppend( Vec_WecEntry(vGates, 0), vRes ); + pNew = Gia_ManConstructFromGates( vGates, Vec_PtrSize(vDivs) ); + Vec_WecFree( vGates ); + if ( fVerbose ) + printf( "The solution has %d inputs and %d nodes.\n", Gia_ManCiNum(pNew), Gia_ManAndNum(pNew) ); + } + if ( fWriteSol && ArraySize ) + Gia_ManResubRecordSolution( pFileName, vRes, Vec_PtrSize(vDivs) ); + Abc_ResubPrepareManager( 0 ); + Vec_IntFree( vRes ); + Vec_PtrFree( vDivs ); + Abc_RDataStop( p ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaResub2.c b/yosys/abc/src/aig/gia/giaResub2.c new file mode 100644 index 00000000000..10c5a9e0e9e --- /dev/null +++ b/yosys/abc/src/aig/gia/giaResub2.c @@ -0,0 +1,1558 @@ +/**CFile**************************************************************** + + FileName [giaResub2.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaResub2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/util/utilTruth.h" +#include "misc/vec/vecHsh.h" +#include "opt/dau/dau.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Gia_Rsb2Man_t_ Gia_Rsb2Man_t; +struct Gia_Rsb2Man_t_ +{ + // hyper-parameters + int nDivsMax; + int nLevelIncrease; + int fUseXor; + int fUseZeroCost; + int fDebug; + int fVerbose; + // input AIG + int nObjs; + int nPis; + int nNodes; + int nPos; + int iFirstPo; + int Level; + int nMffc; + // intermediate data + Vec_Int_t vObjs; + Vec_Wrd_t vSims; + Vec_Ptr_t vpDivs; + Vec_Int_t vDivs; + Vec_Int_t vLevels; + Vec_Int_t vRefs; + Vec_Int_t vCopies; + Vec_Int_t vTried; + word Truth0; + word Truth1; + word CareSet; +}; + +extern void Abc_ResubPrepareManager( int nWords ); +extern int Abc_ResubComputeFunction( void ** ppDivs, int nDivs, int nWords, int nLimit, int nDivsMax, int iChoice, int fUseXor, int fDebug, int fVerbose, int ** ppArray ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Rsb2Man_t * Gia_Rsb2ManAlloc() +{ + Gia_Rsb2Man_t * p = ABC_CALLOC( Gia_Rsb2Man_t, 1 ); + return p; +} +void Gia_Rsb2ManFree( Gia_Rsb2Man_t * p ) +{ + Vec_IntErase( &p->vObjs ); + Vec_WrdErase( &p->vSims ); + Vec_PtrErase( &p->vpDivs ); + Vec_IntErase( &p->vDivs ); + Vec_IntErase( &p->vLevels ); + Vec_IntErase( &p->vRefs ); + Vec_IntErase( &p->vCopies ); + Vec_IntErase( &p->vTried ); + ABC_FREE( p ); +} +void Gia_Rsb2ManStart( Gia_Rsb2Man_t * p, int * pObjs, int nObjs, int nDivsMax, int nLevelIncrease, int fUseXor, int fUseZeroCost, int fDebug, int fVerbose ) +{ + int i; + // hyper-parameters + p->nDivsMax = nDivsMax; + p->nLevelIncrease = nLevelIncrease; + p->fUseXor = fUseXor; + p->fUseZeroCost = fUseZeroCost; + p->fDebug = fDebug; + p->fVerbose = fVerbose; + // user data + Vec_IntClear( &p->vObjs ); + Vec_IntPushArray( &p->vObjs, pObjs, 2*nObjs ); + assert( pObjs[0] == 0 ); + assert( pObjs[1] == 0 ); + p->nObjs = nObjs; + p->nPis = 0; + p->nNodes = 0; + p->nPos = 0; + p->iFirstPo = 0; + for ( i = 1; i < nObjs; i++ ) + { + if ( pObjs[2*i+0] == 0 && pObjs[2*i+1] == 0 ) + p->nPis++; + else if ( pObjs[2*i+0] == pObjs[2*i+1] ) + p->nPos++; + else + p->nNodes++; + } + assert( nObjs == 1 + p->nPis + p->nNodes + p->nPos ); + p->iFirstPo = nObjs - p->nPos; + Vec_WrdClear( &p->vSims ); + Vec_WrdGrow( &p->vSims, 2*nObjs ); + Vec_WrdPush( &p->vSims, 0 ); + Vec_WrdPush( &p->vSims, 0 ); + for ( i = 0; i < p->nPis; i++ ) + { + Vec_WrdPush( &p->vSims, s_Truths6[i] ); + Vec_WrdPush( &p->vSims, ~s_Truths6[i] ); + } + p->vSims.nSize = 2*p->nObjs; + Vec_IntClear( &p->vDivs ); + Vec_IntClear( &p->vLevels ); + Vec_IntClear( &p->vRefs ); + Vec_IntClear( &p->vCopies ); + Vec_IntClear( &p->vTried ); + Vec_PtrClear( &p->vpDivs ); + Vec_IntGrow( &p->vDivs, nObjs ); + Vec_IntGrow( &p->vLevels, nObjs ); + Vec_IntGrow( &p->vRefs, nObjs ); + Vec_IntGrow( &p->vCopies, nObjs ); + Vec_IntGrow( &p->vTried, nObjs ); + Vec_PtrGrow( &p->vpDivs, nObjs ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_Rsb2ManPrint( Gia_Rsb2Man_t * p ) +{ + int i, * pObjs = Vec_IntArray( &p->vObjs ); + printf( "PI = %d. PO = %d. Obj = %d.\n", p->nPis, p->nPos, p->nObjs ); + for ( i = p->nPis + 1; i < p->iFirstPo; i++ ) + printf( "%2d = %c%2d & %c%2d;\n", i, + Abc_LitIsCompl(pObjs[2*i+0]) ? '!' : ' ', Abc_Lit2Var(pObjs[2*i+0]), + Abc_LitIsCompl(pObjs[2*i+1]) ? '!' : ' ', Abc_Lit2Var(pObjs[2*i+1]) ); + for ( i = p->iFirstPo; i < p->nObjs; i++ ) + printf( "%2d = %c%2d;\n", i, + Abc_LitIsCompl(pObjs[2*i+0]) ? '!' : ' ', Abc_Lit2Var(pObjs[2*i+0]) ); +} + +int Gia_Rsb2ManLevel( Gia_Rsb2Man_t * p ) +{ + int i, * pLevs, Level = 0; + Vec_IntClear( &p->vLevels ); + Vec_IntGrow( &p->vLevels, p->nObjs ); + pLevs = Vec_IntArray( &p->vLevels ); + for ( i = p->nPis + 1; i < p->iFirstPo; i++ ) + pLevs[i] = 1 + Abc_MaxInt( pLevs[2*i+0]/2, pLevs[2*i+1]/2 ); + for ( i = p->iFirstPo; i < p->nObjs; i++ ) + Level = Abc_MaxInt( Level, pLevs[i] = pLevs[2*i+0]/2 ); + return Level; +} +word Gia_Rsb2ManOdcs( Gia_Rsb2Man_t * p, int iNode ) +{ + int i; word Res = 0; + int * pObjs = Vec_IntArray( &p->vObjs ); + word * pSims = Vec_WrdArray( &p->vSims ); + for ( i = p->nPis + 1; i < p->iFirstPo; i++ ) + { + if ( pObjs[2*i+0] < pObjs[2*i+1] ) + pSims[2*i+0] = pSims[pObjs[2*i+0]] & pSims[pObjs[2*i+1]]; + else if ( pObjs[2*i+0] > pObjs[2*i+1] ) + pSims[2*i+0] = pSims[pObjs[2*i+0]] ^ pSims[pObjs[2*i+1]]; + else assert( 0 ); + pSims[2*i+1] = ~pSims[2*i+0]; + } + for ( i = p->iFirstPo; i < p->nObjs; i++ ) + pSims[2*i+0] = pSims[pObjs[2*i+0]]; + ABC_SWAP( word, pSims[2*iNode+0], pSims[2*iNode+1] ); + for ( i = iNode + 1; i < p->iFirstPo; i++ ) + { + if ( pObjs[2*i+0] < pObjs[2*i+1] ) + pSims[2*i+0] = pSims[pObjs[2*i+0]] & pSims[pObjs[2*i+1]]; + else if ( pObjs[2*i+0] < pObjs[2*i+1] ) + pSims[2*i+0] = pSims[pObjs[2*i+0]] ^ pSims[pObjs[2*i+1]]; + else assert( 0 ); + pSims[2*i+1] = ~pSims[2*i+0]; + } + for ( i = p->iFirstPo; i < p->nObjs; i++ ) + Res |= pSims[2*i+0] ^ pSims[pObjs[2*i+0]]; + ABC_SWAP( word, pSims[2*iNode+0], pSims[2*iNode+1] ); + return Res; +} +// marks MFFC and returns its size +int Gia_Rsb2ManDeref_rec( Gia_Rsb2Man_t * p, int * pObjs, int * pRefs, int iNode ) +{ + int Counter = 1; + if ( iNode <= p->nPis ) + return 0; + if ( --pRefs[Abc_Lit2Var(pObjs[2*iNode+0])] == 0 ) + Counter += Gia_Rsb2ManDeref_rec( p, pObjs, pRefs, Abc_Lit2Var(pObjs[2*iNode+0]) ); + if ( --pRefs[Abc_Lit2Var(pObjs[2*iNode+1])] == 0 ) + Counter += Gia_Rsb2ManDeref_rec( p, pObjs, pRefs, Abc_Lit2Var(pObjs[2*iNode+1]) ); + return Counter; +} +int Gia_Rsb2ManMffc( Gia_Rsb2Man_t * p, int iNode ) +{ + int i, * pRefs, * pObjs; + Vec_IntFill( &p->vRefs, p->nObjs, 0 ); + pRefs = Vec_IntArray( &p->vRefs ); + pObjs = Vec_IntArray( &p->vObjs ); + assert( pObjs[2*iNode+0] != pObjs[2*iNode+1] ); + for ( i = p->nPis + 1; i < p->iFirstPo; i++ ) + pRefs[Abc_Lit2Var(pObjs[2*i+0])]++, + pRefs[Abc_Lit2Var(pObjs[2*i+1])]++; + for ( i = p->iFirstPo; i < p->nObjs; i++ ) + pRefs[Abc_Lit2Var(pObjs[2*i+0])]++; + for ( i = p->nPis + 1; i < p->iFirstPo; i++ ) + assert( pRefs[i] ); + pRefs[iNode] = 0; + for ( i = iNode + 1; i < p->iFirstPo; i++ ) + if ( !pRefs[Abc_Lit2Var(pObjs[2*i+0])] || !pRefs[Abc_Lit2Var(pObjs[2*i+1])] ) + pRefs[i] = 0; + return Gia_Rsb2ManDeref_rec( p, pObjs, pRefs, iNode ); +} +// collects divisors and maps them into nodes +// assumes MFFC is already marked +int Gia_Rsb2ManDivs( Gia_Rsb2Man_t * p, int iNode ) +{ + int i, iNodeLevel = 0; + int * pRefs = Vec_IntArray( &p->vRefs ); + p->CareSet = Gia_Rsb2ManOdcs( p, iNode ); + p->Truth1 = p->CareSet & Vec_WrdEntry(&p->vSims, 2*iNode); + p->Truth0 = p->CareSet & ~p->Truth1; + Vec_PtrClear( &p->vpDivs ); + Vec_PtrPush( &p->vpDivs, &p->Truth0 ); + Vec_PtrPush( &p->vpDivs, &p->Truth1 ); + Vec_IntClear( &p->vDivs ); + Vec_IntPushTwo( &p->vDivs, -1, -1 ); + for ( i = 1; i <= p->nPis; i++ ) + { + Vec_PtrPush( &p->vpDivs, Vec_WrdEntryP(&p->vSims, 2*i) ); + Vec_IntPush( &p->vDivs, i ); + } + p->nMffc = Gia_Rsb2ManMffc( p, iNode ); + if ( p->nLevelIncrease >= 0 ) + { + p->Level = Gia_Rsb2ManLevel(p); + iNodeLevel = Vec_IntEntry(&p->vLevels, iNode); + } + for ( i = p->nPis + 1; i < p->iFirstPo; i++ ) + { + if ( !pRefs[i] || (p->nLevelIncrease >= 0 && Vec_IntEntry(&p->vLevels, i) > iNodeLevel + p->nLevelIncrease) ) + continue; + Vec_PtrPush( &p->vpDivs, Vec_WrdEntryP(&p->vSims, 2*i) ); + Vec_IntPush( &p->vDivs, i ); + } + assert( Vec_IntSize(&p->vDivs) == Vec_PtrSize(&p->vpDivs) ); + return Vec_IntSize(&p->vDivs); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_Rsb2AddNode( Vec_Int_t * vRes, int iLit0, int iLit1, int iRes0, int iRes1 ) +{ + int iLitMin = iRes0 < iRes1 ? Abc_LitNotCond(iRes0, Abc_LitIsCompl(iLit0)) : Abc_LitNotCond(iRes1, Abc_LitIsCompl(iLit1)); + int iLitMax = iRes0 < iRes1 ? Abc_LitNotCond(iRes1, Abc_LitIsCompl(iLit1)) : Abc_LitNotCond(iRes0, Abc_LitIsCompl(iLit0)); + int iLitRes = Vec_IntSize(vRes); + if ( iLit0 < iLit1 ) // and + { + if ( iLitMin == 0 ) + return 0; + if ( iLitMin == 1 ) + return iLitMax; + if ( iLitMin == Abc_LitNot(iLitMax) ) + return 0; + } + else if ( iLit0 > iLit1 ) // xor + { + if ( iLitMin == 0 ) + return iLitMax; + if ( iLitMin == 1 ) + return Abc_LitNot(iLitMax); + if ( iLitMin == Abc_LitNot(iLitMax) ) + return 1; + } + else assert( 0 ); + assert( iLitMin >= 2 && iLitMax >= 2 ); + if ( iLit0 < iLit1 ) // and + Vec_IntPushTwo( vRes, iLitMin, iLitMax ); + else if ( iLit0 > iLit1 ) // xor + { + assert( !Abc_LitIsCompl(iLit0) ); + assert( !Abc_LitIsCompl(iLit1) ); + Vec_IntPushTwo( vRes, iLitMax, iLitMin ); + } + else assert( 0 ); + return iLitRes; +} +int Gia_Rsb2ManInsert_rec( Vec_Int_t * vRes, int nPis, Vec_Int_t * vObjs, int iNode, Vec_Int_t * vResub, Vec_Int_t * vDivs, Vec_Int_t * vCopies, int iObj ) +{ + if ( Vec_IntEntry(vCopies, iObj) >= 0 ) + return Vec_IntEntry(vCopies, iObj); + assert( iObj > nPis ); + if ( iObj == iNode ) + { + int nVars = Vec_IntSize(vDivs); + int iLitRes = -1, iTopLit = Vec_IntEntryLast( vResub ); + if ( Abc_Lit2Var(iTopLit) == 0 ) + iLitRes = 0; + else if ( Abc_Lit2Var(iTopLit) < nVars ) + iLitRes = Gia_Rsb2ManInsert_rec( vRes, nPis, vObjs, -1, vResub, vDivs, vCopies, Vec_IntEntry(vDivs, Abc_Lit2Var(iTopLit)) ); + else + { + Vec_Int_t * vCopy = Vec_IntAlloc( 10 ); + int k, iLit, iLit0, iLit1; + Vec_IntForEachEntryStop( vResub, iLit, k, Vec_IntSize(vResub)-1 ) + if ( Abc_Lit2Var(iLit) < nVars ) + Gia_Rsb2ManInsert_rec( vRes, nPis, vObjs, -1, vResub, vDivs, vCopies, Vec_IntEntry(vDivs, Abc_Lit2Var(iLit)) ); + Vec_IntForEachEntryDouble( vResub, iLit0, iLit1, k ) + { + int iVar0 = Abc_Lit2Var(iLit0); + int iVar1 = Abc_Lit2Var(iLit1); + int iRes0 = iVar0 < nVars ? Vec_IntEntry(vCopies, Vec_IntEntry(vDivs, iVar0)) : Vec_IntEntry(vCopy, iVar0 - nVars); + int iRes1 = iVar1 < nVars ? Vec_IntEntry(vCopies, Vec_IntEntry(vDivs, iVar1)) : Vec_IntEntry(vCopy, iVar1 - nVars); + iLitRes = Gia_Rsb2AddNode( vRes, iLit0, iLit1, iRes0, iRes1 ); + Vec_IntPush( vCopy, iLitRes ); + } + Vec_IntFree( vCopy ); + } + iLitRes = Abc_LitNotCond( iLitRes, Abc_LitIsCompl(iTopLit) ); + Vec_IntWriteEntry( vCopies, iObj, iLitRes ); + return iLitRes; + } + else + { + int iLit0 = Vec_IntEntry( vObjs, 2*iObj+0 ); + int iLit1 = Vec_IntEntry( vObjs, 2*iObj+1 ); + int iRes0 = Gia_Rsb2ManInsert_rec( vRes, nPis, vObjs, iNode, vResub, vDivs, vCopies, Abc_Lit2Var(iLit0) ); + int iRes1 = Gia_Rsb2ManInsert_rec( vRes, nPis, vObjs, iNode, vResub, vDivs, vCopies, Abc_Lit2Var(iLit1) ); + int iLitRes = Gia_Rsb2AddNode( vRes, iLit0, iLit1, iRes0, iRes1 ); + Vec_IntWriteEntry( vCopies, iObj, iLitRes ); + return iLitRes; + } +} +Vec_Int_t * Gia_Rsb2ManInsert( int nPis, int nPos, Vec_Int_t * vObjs, int iNode, Vec_Int_t * vResub, Vec_Int_t * vDivs, Vec_Int_t * vCopies ) +{ + int i, nObjs = Vec_IntSize(vObjs)/2, iFirstPo = nObjs - nPos; + Vec_Int_t * vRes = Vec_IntAlloc( Vec_IntSize(vObjs) ); +//Vec_IntPrint( vDivs ); +//Vec_IntPrint( vResub ); + Vec_IntFill( vCopies, Vec_IntSize(vObjs), -1 ); + Vec_IntFill( vRes, 2*(nPis + 1), 0 ); + for ( i = 0; i <= nPis; i++ ) + Vec_IntWriteEntry( vCopies, i, 2*i ); + for ( i = iFirstPo; i < nObjs; i++ ) + Gia_Rsb2ManInsert_rec( vRes, nPis, vObjs, iNode, vResub, vDivs, vCopies, Abc_Lit2Var( Vec_IntEntry(vObjs, 2*i) ) ); + for ( i = iFirstPo; i < nObjs; i++ ) + { + int iLitNew = Abc_Lit2LitL( Vec_IntArray(vCopies), Vec_IntEntry(vObjs, 2*i) ); + Vec_IntPushTwo( vRes, iLitNew, iLitNew ); + } + return vRes; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ResubPrintDivs( void ** ppDivs, int nDivs ) +{ + word ** pDivs = (word **)ppDivs; + int i; + for ( i = 0; i < nDivs; i++ ) + { + printf( "Div %2d : ", i ); + Dau_DsdPrintFromTruth( pDivs[i], 6 ); + } +} +int Abc_ResubNodeToTry( Vec_Int_t * vTried, int iFirst, int iLast ) +{ + int iNode; + //for ( iNode = iFirst; iNode < iLast; iNode++ ) + for ( iNode = iLast - 1; iNode >= iFirst; iNode-- ) + if ( Vec_IntFind(vTried, iNode) == -1 ) + return iNode; + return -1; +} +int Abc_ResubComputeWindow( int * pObjs, int nObjs, int nDivsMax, int nLevelIncrease, int fUseXor, int fUseZeroCost, int fDebug, int fVerbose, int ** ppArray, int * pnResubs ) +{ + int iNode, nChanges = 0, RetValue = 0; + Gia_Rsb2Man_t * p = Gia_Rsb2ManAlloc(); + Gia_Rsb2ManStart( p, pObjs, nObjs, nDivsMax, nLevelIncrease, fUseXor, fUseZeroCost, fDebug, fVerbose ); + *ppArray = NULL; + while ( (iNode = Abc_ResubNodeToTry(&p->vTried, p->nPis+1, p->iFirstPo)) > 0 ) + { + int nDivs = Gia_Rsb2ManDivs( p, iNode ); + int * pResub, nResub = Abc_ResubComputeFunction( Vec_PtrArray(&p->vpDivs), nDivs, 1, p->nMffc-1, nDivsMax, 0, fUseXor, fDebug, fVerbose, &pResub ); + if ( nResub == 0 ) + Vec_IntPush( &p->vTried, iNode ); + else + { + int i, k = 0, iTried; + Vec_Int_t vResub = { nResub, nResub, pResub }; + Vec_Int_t * vRes = Gia_Rsb2ManInsert( p->nPis, p->nPos, &p->vObjs, iNode, &vResub, &p->vDivs, &p->vCopies ); + //printf( "\nResubing node %d:\n", iNode ); + //Gia_Rsb2ManPrint( p ); + p->nObjs = Vec_IntSize(vRes)/2; + p->iFirstPo = p->nObjs - p->nPos; + Vec_IntClear( &p->vObjs ); + Vec_IntAppend( &p->vObjs, vRes ); + Vec_IntFree( vRes ); + Vec_IntForEachEntry( &p->vTried, iTried, i ) + if ( Vec_IntEntry(&p->vCopies, iTried) > Abc_Var2Lit(p->nPis, 0) ) // internal node + Vec_IntWriteEntry( &p->vTried, k++, Abc_Lit2Var(Vec_IntEntry(&p->vCopies, iTried)) ); + Vec_IntShrink( &p->vTried, k ); + nChanges++; + //Gia_Rsb2ManPrint( p ); + } + } + if ( nChanges ) + { + RetValue = p->nObjs; + *ppArray = p->vObjs.pArray; + Vec_IntZero( &p->vObjs ); + } + Gia_Rsb2ManFree( p ); + if ( pnResubs ) + *pnResubs = nChanges; + return RetValue; +} +int Abc_ResubComputeWindow2( int * pObjs, int nObjs, int nDivsMax, int nLevelIncrease, int fUseXor, int fUseZeroCost, int fDebug, int fVerbose, int ** ppArray, int * pnResubs ) +{ + *ppArray = ABC_ALLOC( int, 2*nObjs ); + memmove( *ppArray, pObjs, 2*nObjs * sizeof(int) ); + if ( pnResubs ) + *pnResubs = 0; + return nObjs; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Gia_ManToResub( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, * pObjs = ABC_CALLOC( int, 2*Gia_ManObjNum(p) ); + assert( Gia_ManIsNormalized(p) ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + continue; + pObjs[2*i+0] = Gia_ObjFaninLit0(Gia_ManObj(p, i), i); + if ( Gia_ObjIsCo(pObj) ) + pObjs[2*i+1] = pObjs[2*i+0]; + else if ( Gia_ObjIsAnd(pObj) ) + pObjs[2*i+1] = Gia_ObjFaninLit1(Gia_ManObj(p, i), i); + else assert( 0 ); + } + return pObjs; +} +Gia_Man_t * Gia_ManFromResub( int * pObjs, int nObjs, int nIns ) +{ + Gia_Man_t * pNew = Gia_ManStart( nObjs ); + int i; + for ( i = 1; i < nObjs; i++ ) + { + if ( pObjs[2*i] == 0 && i <= nIns ) // pi + Gia_ManAppendCi( pNew ); + else if ( pObjs[2*i] == pObjs[2*i+1] ) // po + Gia_ManAppendCo( pNew, pObjs[2*i] ); + else if ( pObjs[2*i] < pObjs[2*i+1] ) + Gia_ManAppendAnd( pNew, pObjs[2*i], pObjs[2*i+1] ); + else if ( pObjs[2*i] > pObjs[2*i+1] ) + Gia_ManAppendXor( pNew, pObjs[2*i], pObjs[2*i+1] ); + else assert( 0 ); + } + return pNew; +} +Gia_Man_t * Gia_ManResub2Test( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + int nResubs, nObjsNew, * pObjsNew, * pObjs = Gia_ManToResub( p ); +//Gia_ManPrint( p ); + Abc_ResubPrepareManager( 1 ); + nObjsNew = Abc_ResubComputeWindow( pObjs, Gia_ManObjNum(p), 1000, -1, 0, 0, 0, 0, &pObjsNew, &nResubs ); + //printf( "Performed resub %d times. Reduced %d nodes.\n", nResubs, nObjsNew ? Gia_ManObjNum(p) - nObjsNew : 0 ); + Abc_ResubPrepareManager( 0 ); + if ( nObjsNew ) + { + pNew = Gia_ManFromResub( pObjsNew, nObjsNew, Gia_ManCiNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + } + else + pNew = Gia_ManDup( p ); + ABC_FREE( pObjs ); + ABC_FREE( pObjsNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Creating a window with support composed of primary inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +// returns the number of nodes added to the window when is iPivot is added +// the window nodes in vNodes are labeled with the current traversal ID +// the new node iPivot and its fanout are temporarily labeled and then unlabeled +int Gia_WinTryAddingNode( Gia_Man_t * p, int iPivot, int iPivot2, Vec_Wec_t * vLevels, Vec_Int_t * vNodes ) +{ + Vec_Int_t * vLevel; + Gia_Obj_t * pObj, * pFanout; + int k, i, f, Count = 0; + // precondition: the levelized structure is empty + assert( Vec_WecSizeSize(vLevels) == 0 ); + // precondition: the new object to be added (iPivot) is not in the window + assert( !Gia_ObjIsTravIdCurrentId(p, iPivot) ); + // add the object to the window and to the levelized structure + Gia_ObjSetTravIdCurrentId( p, iPivot ); + Vec_WecPush( vLevels, Gia_ObjLevelId(p, iPivot), iPivot ); + // the same about the second node if it is given + if ( iPivot2 != -1 ) + { + // precondition: the new object to be added (iPivot2) is not in the window + assert( !Gia_ObjIsTravIdCurrentId(p, iPivot2) ); + // add the object to the window and to the levelized structure + Gia_ObjSetTravIdCurrentId( p, iPivot2 ); + Vec_WecPush( vLevels, Gia_ObjLevelId(p, iPivot2), iPivot2 ); + } + // iterate through all objects and explore their fanouts + Vec_WecForEachLevel( vLevels, vLevel, k ) + Gia_ManForEachObjVec( vLevel, p, pObj, i ) + Gia_ObjForEachFanoutStatic( p, pObj, pFanout, f ) + { + if ( f == 5 ) // explore first 5 fanouts of the node + break; + if ( Gia_ObjIsAnd(pFanout) && // internal node + !Gia_ObjIsTravIdCurrent(p, pFanout) && // not in the window + Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pFanout)) && // but fanins are + Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pFanout)) ) // in the window + { + // add fanout to the window and to the levelized structure + Gia_ObjSetTravIdCurrent( p, pFanout ); + Vec_WecPush( vLevels, Gia_ObjLevel(p, pFanout), Gia_ObjId(p, pFanout) ); + // count the number of nodes in the structure + Count++; + } + } + // iterate through the nodes in the levelized structure + Vec_WecForEachLevel( vLevels, vLevel, k ) + { + Gia_ManForEachObjVec( vLevel, p, pObj, i ) + if ( vNodes == NULL ) // it was a test run - unmark the node + Gia_ObjSetTravIdPrevious( p, pObj ); + else // it was a real run - permanently add to the node to the window + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); + // clean the levelized structure + Vec_IntClear( vLevel ); + } + // return the number of nodes to be added + return Count; +} +// find the first PI to add based on the fanout count +int Gia_WinAddCiWithMaxFanouts( Gia_Man_t * p ) +{ + int i, Id, nMaxFan = -1, iMaxFan = -1; + Gia_ManForEachCiId( p, Id, i ) + if ( nMaxFan < Gia_ObjFanoutNumId(p, Id) ) + { + nMaxFan = Gia_ObjFanoutNumId(p, Id); + iMaxFan = Id; + } + assert( iMaxFan >= 0 ); + return iMaxFan; +} +// find the next PI to add based on how many nodes will be added to the window +int Gia_WinAddCiWithMaxDivisors( Gia_Man_t * p, Vec_Wec_t * vLevels ) +{ + int i, Id, nCurFan, nMaxFan = -1, iMaxFan = -1; + Gia_ManForEachCiId( p, Id, i ) + { + if ( Gia_ObjIsTravIdCurrentId( p, Id ) ) + continue; + nCurFan = Gia_WinTryAddingNode( p, Id, -1, vLevels, NULL ); + if ( nMaxFan < nCurFan ) + { + nMaxFan = nCurFan; + iMaxFan = Id; + } + } + assert( iMaxFan >= 0 ); + return iMaxFan; +} +// check if the node has unmarked fanouts +int Gia_WinNodeHasUnmarkedFanouts( Gia_Man_t * p, int iPivot ) +{ + int f, iFan; + Gia_ObjForEachFanoutStaticId( p, iPivot, iFan, f ) + if ( !Gia_ObjIsTravIdCurrentId(p, iFan) ) + return 1; + return 0; +} +// this is a translation procedure, which converts the array of node IDs (vObjs) +// into the internal represnetation for the resub engine, which is returned +// (this procedure is not needed when we simply construct a window) +Vec_Int_t * Gia_RsbCiTranslate( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Int_t * vMap ) +{ + int i, iObj, Lit0, Lit1, Fan0, Fan1; + Vec_Int_t * vNodes = Vec_IntAlloc( 100 ); + assert( Vec_IntSize(vMap) == Gia_ManObjNum(p) ); + Vec_IntPushTwo( vNodes, 0, 0 ); // const0 node + Vec_IntForEachEntry( vObjs, iObj, i ) + { + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); + assert( Gia_ObjIsTravIdCurrentId(p, iObj) ); + Fan0 = Gia_ObjIsCi(pObj) ? 0 : Vec_IntEntry(vMap, Gia_ObjFaninId0(pObj, iObj)); + Fan1 = Gia_ObjIsCi(pObj) ? 0 : Vec_IntEntry(vMap, Gia_ObjFaninId1(pObj, iObj)); + Lit0 = Gia_ObjIsCi(pObj) ? 0 : Abc_LitNotCond( Fan0, Gia_ObjFaninC0(pObj) ); + Lit1 = Gia_ObjIsCi(pObj) ? 0 : Abc_LitNotCond( Fan1, Gia_ObjFaninC1(pObj) ); + Vec_IntWriteEntry( vMap, iObj, Vec_IntSize(vNodes) ); + Vec_IntPushTwo( vNodes, Lit0, Lit1 ); + } + Vec_IntForEachEntry( vObjs, iObj, i ) + if ( Gia_WinNodeHasUnmarkedFanouts( p, iObj ) ) + Vec_IntPushTwo( vNodes, Vec_IntEntry(vMap, iObj), Vec_IntEntry(vMap, iObj) ); + return vNodes; +} +// construct a high-volume window support by the given number (nPis) of primary inputs +Vec_Int_t * Gia_RsbCiWindow( Gia_Man_t * p, int nPis ) +{ + Vec_Int_t * vRes; int i, iMaxFan; + Vec_Int_t * vNodes = Vec_IntAlloc( 100 ); + Vec_Int_t * vMap = Vec_IntStartFull( Gia_ManObjNum(p) ); + Vec_Wec_t * vLevels = Vec_WecStart( Gia_ManLevelNum(p)+1 ); + Gia_ManStaticFanoutStart( p ); + Gia_ManIncrementTravId(p); + // add the first one + iMaxFan = Gia_WinAddCiWithMaxFanouts( p ); + Gia_ObjSetTravIdCurrentId( p, iMaxFan ); + Vec_IntPush( vNodes, iMaxFan ); + // add remaining ones + for ( i = 1; i < nPis; i++ ) + { + iMaxFan = Gia_WinAddCiWithMaxDivisors( p, vLevels ); + Gia_WinTryAddingNode( p, iMaxFan, -1, vLevels, vNodes ); + } + Vec_IntSort( vNodes, 0 ); + vRes = Gia_RsbCiTranslate( p, vNodes, vMap ); + Gia_ManStaticFanoutStop( p ); + Vec_WecFree( vLevels ); + Vec_IntFree( vMap ); +//Vec_IntPrint( vNodes ); + Vec_IntFree( vNodes ); + return vRes; +} +void Gia_RsbCiWindowTest( Gia_Man_t * p ) +{ + Vec_Int_t * vWin = Gia_RsbCiWindow( p, 6 ); + //Vec_IntPrint( vWin ); + Vec_IntFree( vWin ); +} + + + + +/**Function************************************************************* + + Synopsis [Return initial window for the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +//static inline int Gia_ObjFaninId( Gia_Obj_t * pObj, int iObj, int n ) { return n ? Gia_ObjFaninId1(pObj, iObj) : Gia_ObjFaninId0(pObj, iObj); } + +static inline int Gia_ObjTravIsTopTwo( Gia_Man_t * p, int iNodeA ) { return (p->pTravIds[iNodeA] >= p->nTravIds - 1); } +static inline int Gia_ObjTravIsSame( Gia_Man_t * p, int iNodeA, int iNodeB ) { return (p->pTravIds[iNodeA] == p->pTravIds[iNodeB]); } +static inline void Gia_ObjTravSetSame( Gia_Man_t * p, int iNodeA, int iNodeB ) { p->pTravIds[iNodeA] = p->pTravIds[iNodeB]; } + +// collect nodes on the path from the meeting point to the root node, excluding the meeting point +void Gia_RsbWindowGather( Gia_Man_t * p, Vec_Int_t * vPaths, int iNode, Vec_Int_t * vVisited ) +{ + int iPrev; + if ( iNode == 0 ) + return; + Vec_IntPush( vVisited, iNode ); + iPrev = Vec_IntEntry( vPaths, iNode ); + if ( iPrev == 0 ) + return; + assert( Gia_ObjTravIsSame(p, iPrev, iNode) ); + Gia_RsbWindowGather( p, vPaths, iPrev, vVisited ); +} +// explore the frontier of nodes in the breadth-first traversal +int Gia_RsbWindowExplore( Gia_Man_t * p, Vec_Int_t * vVisited, int iStart, Vec_Int_t * vPaths, int * piMeet, int * piNode ) +{ + int i, n, iObj, iLimit = Vec_IntSize( vVisited ); + *piMeet = *piNode = 0; + Vec_IntForEachEntryStartStop( vVisited, iObj, i, iStart, iLimit ) + { + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + if ( !Gia_ObjIsAnd(pObj) ) + continue; + for ( n = 0; n < 2; n++ ) + { + int iFan = Gia_ObjFaninId( pObj, iObj, n ); + // if the node was visited on the paths to both fanins, collect it + if ( Gia_ObjTravIsTopTwo(p, iObj) && Gia_ObjTravIsTopTwo(p, iFan) && !Gia_ObjTravIsSame(p, iObj, iFan) ) + { + *piMeet = iFan; + *piNode = iObj; + return 1; + } + // if the node was visited already on this path, skip it + if ( Gia_ObjTravIsTopTwo(p, iFan) ) + { + assert( Gia_ObjTravIsSame(p, iObj, iFan) ); + continue; + } + // label the node as visited + Gia_ObjTravSetSame( p, iFan, iObj ); + Vec_IntWriteEntry( vPaths, iFan, iObj ); + Vec_IntPush( vVisited, iFan ); + } + } + return 0; +} +Vec_Int_t * Gia_RsbWindowInit( Gia_Man_t * p, Vec_Int_t * vPaths, int iPivot, int nIter ) +{ + Vec_Int_t * vVisited = Vec_IntAlloc( 100 ); + Gia_Obj_t * pPivot = Gia_ManObj( p, iPivot ); + int i, n, iStart = 0; + assert( Gia_ObjIsAnd(pPivot) ); + // start paths for both fanins of the pivot node + for ( n = 0; n < 2; n++ ) + { + int iFan = Gia_ObjFaninId( pPivot, iPivot, n ); + Gia_ManIncrementTravId(p); + Vec_IntPush( vVisited, iFan ); + Vec_IntWriteEntry( vPaths, iFan, 0 ); + Gia_ObjSetTravIdCurrentId( p, iFan ); + } + // perform several iterations of breadth-first search + for ( i = 0; i < nIter; i++ ) + { + int iMeet, iNode, iNext = Vec_IntSize(vVisited); + if ( Gia_RsbWindowExplore( p, vVisited, iStart, vPaths, &iMeet, &iNode ) ) + { + // found the shared path + if ( Gia_ObjIsTravIdCurrentId(p, iMeet) ) + assert( Gia_ObjIsTravIdPreviousId(p, iNode) ); + else if ( Gia_ObjIsTravIdPreviousId(p, iMeet) ) + assert( Gia_ObjIsTravIdCurrentId(p, iNode) ); + else assert( 0 ); + // collect the initial window + Vec_IntClear( vVisited ); + Gia_RsbWindowGather( p, vPaths, Vec_IntEntry(vPaths, iMeet), vVisited ); + Gia_RsbWindowGather( p, vPaths, iNode, vVisited ); + Vec_IntPush( vVisited, iPivot ); + break; + } + iStart = iNext; + } + // if no meeting point is found, make sure to return NULL + if ( i == nIter ) + Vec_IntFreeP( &vVisited ); + return vVisited; +} +Vec_Int_t * Gia_RsbCreateWindowInputs( Gia_Man_t * p, Vec_Int_t * vWin ) +{ + Vec_Int_t * vInputs = Vec_IntAlloc(10); + Gia_Obj_t * pObj; int i, n, iObj; + Gia_ManIncrementTravId(p); + Gia_ManForEachObjVec( vWin, p, pObj, i ) + Gia_ObjSetTravIdCurrent(p, pObj); + Gia_ManForEachObjVec( vWin, p, pObj, i ) + { + assert( Gia_ObjIsAnd(pObj) ); + for ( n = 0; n < 2; n++ ) + { + int iFan = n ? Gia_ObjFaninId1p(p, pObj) : Gia_ObjFaninId0p(p, pObj); + if ( !Gia_ObjIsTravIdCurrentId(p, iFan) ) + Vec_IntPushUnique( vInputs, iFan ); + } + } + Vec_IntForEachEntry( vInputs, iObj, i ) + { + Gia_ObjSetTravIdCurrentId( p, iObj ); + Vec_IntPush( vWin, iObj ); + } + return vInputs; +} + +/**Function************************************************************* + + Synopsis [Grow window for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_RsbAddSideInputs( Gia_Man_t * p, Vec_Wec_t * vLevels, Vec_Int_t * vWin ) +{ + Vec_Int_t * vLevel; + Gia_Obj_t * pObj, * pFanout; + int k, i, f, iObj; + // precondition: the levelized structure is empty + assert( Vec_WecSizeSize(vLevels) == 0 ); + // precondition: window nodes are labeled with the current ID + Vec_IntForEachEntry( vWin, iObj, i ) + { + assert( Gia_ObjIsTravIdCurrentId(p, iObj) ); + Vec_WecPush( vLevels, Gia_ObjLevelId(p, iObj), iObj ); + } + // iterate through all objects and explore their fanouts + Vec_WecForEachLevel( vLevels, vLevel, k ) + Gia_ManForEachObjVec( vLevel, p, pObj, i ) + Gia_ObjForEachFanoutStatic( p, pObj, pFanout, f ) + { + if ( f == 5 ) // explore first 5 fanouts of the node + break; + if ( Gia_ObjIsAnd(pFanout) && // internal node + !Gia_ObjIsTravIdCurrent(p, pFanout) && // not in the window + Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pFanout)) && // but fanins are + Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pFanout)) ) // in the window + { + // add fanout to the window and to the levelized structure + Gia_ObjSetTravIdCurrent( p, pFanout ); + Vec_WecPush( vLevels, Gia_ObjLevel(p, pFanout), Gia_ObjId(p, pFanout) ); + Vec_IntPush( vWin, Gia_ObjId(p, pFanout) ); + } + } + // iterate through the nodes in the levelized structure + Vec_WecForEachLevel( vLevels, vLevel, k ) + Vec_IntClear( vLevel ); +} +// expland inputs until saturation while adding the side-fanouts +void Gia_RsbExpandInputs( Gia_Man_t * p, Vec_Wec_t * vLevels, Vec_Int_t * vWin, Vec_Int_t * vInputs ) +{ + Gia_Obj_t * pObj; + int i, n, iFans[2], fChange = 1; + while ( fChange ) + { + fChange = 0; + Gia_ManForEachObjVec( vInputs, p, pObj, i ) + { + if ( !Gia_ObjIsAnd(pObj) ) + continue; + iFans[0] = Gia_ObjFaninId0p(p, pObj); + iFans[1] = Gia_ObjFaninId1p(p, pObj); + if ( !Gia_ObjIsTravIdCurrentId(p, iFans[0]) && !Gia_ObjIsTravIdCurrentId(p, iFans[1]) ) + continue; + Vec_IntRemove( vInputs, Gia_ObjId(p, pObj) ); + assert( Vec_IntFind(vWin, Gia_ObjId(p, pObj)) >= 0 ); + for ( n = 0; n < 2; n++ ) + { + if ( Gia_ObjIsTravIdCurrentId(p, iFans[n]) ) + continue; + assert( Vec_IntFind(vInputs, iFans[n]) == -1 ); + Vec_IntPush( vInputs, iFans[n] ); + Gia_WinTryAddingNode( p, iFans[n], -1, vLevels, vWin ); + assert( Gia_ObjIsTravIdCurrentId(p, iFans[n]) ); + } + fChange = 1; + } + } +} +// select the best input to expand, based on its contribution to the window size +int Gia_RsbSelectOneInput( Gia_Man_t * p, Vec_Wec_t * vLevels, Vec_Int_t * vIns ) +{ + int i, iNode = 0, WeightThis, WeightBest = -1; + Gia_Obj_t * pObj; + Gia_ManForEachObjVec( vIns, p, pObj, i ) + if ( Gia_ObjIsAnd(pObj) ) + { + int iFan0 = Gia_ObjFaninId0p(p, pObj); + int iFan1 = Gia_ObjFaninId1p(p, pObj); + assert( !Gia_ObjIsTravIdCurrentId(p, iFan0) && !Gia_ObjIsTravIdCurrentId(p, iFan1) ); + WeightThis = Gia_WinTryAddingNode( p, iFan0, iFan1, vLevels, NULL ); + if ( WeightBest < WeightThis ) + { + WeightBest = WeightThis; + iNode = Gia_ObjId(p, pObj); + } + } + return iNode; +} +// grow the initial window as long as it fits the input count limit +void Gia_RsbWindowGrow( Gia_Man_t * p, Vec_Wec_t * vLevels, Vec_Int_t * vWin, Vec_Int_t * vIns, int nInputsMax ) +{ + int iNode; + Gia_RsbAddSideInputs( p, vLevels, vWin ); + Gia_RsbExpandInputs( p, vLevels, vWin, vIns ); + while ( Vec_IntSize(vIns) < nInputsMax && (iNode = Gia_RsbSelectOneInput(p, vLevels, vIns)) ) + { + int iFan0 = Gia_ObjFaninId0p(p, Gia_ManObj(p, iNode)); + int iFan1 = Gia_ObjFaninId1p(p, Gia_ManObj(p, iNode)); + assert( !Gia_ObjIsTravIdCurrentId(p, iFan0) && !Gia_ObjIsTravIdCurrentId(p, iFan1) ); + Gia_WinTryAddingNode( p, iFan0, iFan1, vLevels, vWin ); + assert( Gia_ObjIsTravIdCurrentId(p, iFan0) && Gia_ObjIsTravIdCurrentId(p, iFan1) ); + Vec_IntRemove( vIns, iNode ); + Vec_IntPushTwo( vIns, iFan0, iFan1 ); + Gia_RsbExpandInputs( p, vLevels, vWin, vIns ); + } +} + +/**Function************************************************************* + + Synopsis [Grow window for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_WinCreateFromCut_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vWin ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return; + Gia_ObjSetTravIdCurrentId(p, iObj); + pObj = Gia_ManObj( p, iObj ); + assert( Gia_ObjIsAnd(pObj) ); + Gia_WinCreateFromCut_rec( p, Gia_ObjFaninId0(pObj, iObj), vWin ); + Gia_WinCreateFromCut_rec( p, Gia_ObjFaninId1(pObj, iObj), vWin ); + Vec_IntPush( vWin, iObj ); +} +// uses levelized structure (vLevels) to collect in array vWin divisors supported by the cut (vIn) +void Gia_WinCreateFromCut( Gia_Man_t * p, int iPivot, Vec_Int_t * vIn, Vec_Wec_t * vLevels, Vec_Int_t * vWin ) +{ + Vec_Int_t * vLevel; + Gia_Obj_t * pObj, * pFanout; + int k, i, f, iObj, Level; + Vec_Int_t * vUsed = Vec_IntAlloc( 100 ); + // precondition: the levelized structure is empty + assert( Vec_WecSizeSize(vLevels) == 0 ); + // clean the resulting array + Vec_IntClear( vWin ); + // collect leaves + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vIn, iObj, i ) + { + Gia_ObjSetTravIdCurrentId( p, iObj ); + Vec_IntPush( vWin, iObj ); + } + // collect internal cone + Gia_WinCreateFromCut_rec( p, iPivot, vWin ); + // add nodes to the levelized structure + Vec_IntForEachEntry( vWin, iObj, i ) + { + Vec_WecPush( vLevels, Gia_ObjLevelId(p, iObj), iObj ); + Vec_IntPushUniqueOrder( vUsed, Gia_ObjLevelId(p, iObj) ); + } + // iterate through all objects and explore their fanouts + //Vec_WecForEachLevel( vLevels, vLevel, k ) + Vec_IntForEachEntry( vUsed, Level, k ) + { + vLevel = Vec_WecEntry( vLevels, Level ); + Gia_ManForEachObjVec( vLevel, p, pObj, i ) + Gia_ObjForEachFanoutStatic( p, pObj, pFanout, f ) + { + if ( f == 5 ) // explore first 5 fanouts of the node + break; + if ( Gia_ObjIsAnd(pFanout) && // internal node + !Gia_ObjIsTravIdCurrent(p, pFanout) && // not in the window + Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pFanout)) && // but fanins are + Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pFanout)) ) // in the window + { + // add fanout to the window and to the levelized structure + Gia_ObjSetTravIdCurrent( p, pFanout ); + Vec_WecPush( vLevels, Gia_ObjLevel(p, pFanout), Gia_ObjId(p, pFanout) ); + Vec_IntPush( vWin, Gia_ObjId(p, pFanout) ); + Vec_IntPushUniqueOrder( vUsed, Gia_ObjLevel(p, pFanout) ); + } + } + Vec_IntClear( vLevel ); + } + Vec_IntSort( vWin, 0 ); + Vec_IntFree( vUsed ); +} +// update the cut until both fanins of AND nodes are not in the cut +int Gia_RsbExpandCut( Gia_Man_t * p, Vec_Int_t * vIns ) +{ + int fOnlyPis = 0, fChange = 1, nSize = Vec_IntSize(vIns); + while ( fChange ) + { + Gia_Obj_t * pObj; + int i, iFan0, iFan1, fHave0, fHave1; + fOnlyPis = 1; + fChange = 0; + // check if some nodes can be expanded without increasing cut size + Gia_ManForEachObjVec( vIns, p, pObj, i ) + { + assert( Gia_ObjIsTravIdCurrent(p, pObj) ); + if ( !Gia_ObjIsAnd(pObj) ) + continue; + fOnlyPis = 0; + iFan0 = Gia_ObjFaninId0p(p, pObj); + iFan1 = Gia_ObjFaninId1p(p, pObj); + fHave0 = Gia_ObjIsTravIdCurrentId(p, iFan0); + fHave1 = Gia_ObjIsTravIdCurrentId(p, iFan1); + if ( !fHave0 && !fHave1 ) + continue; + // can expand because one of the fanins is already in the cut + // remove current cut node + Vec_IntDrop( vIns, i ); + // add missing fanin + if ( !fHave0 ) + { + Vec_IntPush( vIns, iFan0 ); + Gia_ObjSetTravIdCurrentId( p, iFan0 ); + } + if ( !fHave1 ) + { + Vec_IntPush( vIns, iFan1 ); + Gia_ObjSetTravIdCurrentId( p, iFan1 ); + } + fChange = 1; + break; + } + } + assert( Vec_IntSize(vIns) <= nSize ); + return fOnlyPis; +} +int Gia_RsbFindFaninAdd( int iFan, int pFanins[32], int pFaninCounts[32], int nFanins ) +{ + int i; + for ( i = 0; i < nFanins; i++ ) + if ( pFanins[i] == iFan ) + break; + pFanins[i] = iFan; + pFaninCounts[i]++; + return nFanins + (i == nFanins); +} +int Gia_RsbFindFaninToAddToCut( Gia_Man_t * p, Vec_Int_t * vIns ) +{ + Gia_Obj_t * pObj; + int nFanins = 0, pFanins[64] = {0}, pFaninCounts[64] = {0}; + int i, iFan0, iFan1, iFanMax = -1, CountMax = 0; + Gia_ManForEachObjVec( vIns, p, pObj, i ) + { + if ( !Gia_ObjIsAnd(pObj) ) + continue; + iFan0 = Gia_ObjFaninId0p(p, pObj); + iFan1 = Gia_ObjFaninId1p(p, pObj); + assert( !Gia_ObjIsTravIdCurrentId(p, iFan0) ); + assert( !Gia_ObjIsTravIdCurrentId(p, iFan1) ); + nFanins = Gia_RsbFindFaninAdd( iFan0, pFanins, pFaninCounts, nFanins ); + nFanins = Gia_RsbFindFaninAdd( iFan1, pFanins, pFaninCounts, nFanins ); + assert( nFanins < 64 ); + } + // find fanin with the highest count + if ( p->vFanoutNums != NULL ) + { + for ( i = 0; i < nFanins; i++ ) + if ( CountMax < pFaninCounts[i] || (CountMax == pFaninCounts[i] && (Gia_ObjFanoutNumId(p, iFanMax) < Gia_ObjFanoutNumId(p, pFanins[i]))) ) + { + CountMax = pFaninCounts[i]; + iFanMax = pFanins[i]; + } + } + else + { + for ( i = 0; i < nFanins; i++ ) + if ( CountMax < pFaninCounts[i] || (CountMax == pFaninCounts[i] && (Gia_ObjRefNumId(p, iFanMax) < Gia_ObjRefNumId(p, pFanins[i]))) ) + { + CountMax = pFaninCounts[i]; + iFanMax = pFanins[i]; + } + } + return iFanMax; +} +// precondition: nodes in vWin and in vIns are marked with the current ID +void Gia_RsbWindowGrow2( Gia_Man_t * p, int iObj, Vec_Wec_t * vLevels, Vec_Int_t * vWin, Vec_Int_t * vIns, int nInputsMax ) +{ + // window will be recomputed later + Vec_IntClear( vWin ); + // expand the cut without increasing its cost + if ( !Gia_RsbExpandCut( p, vIns ) ) + { + // save it as the best cut + Vec_Int_t * vBest = Vec_IntSize(vIns) <= nInputsMax ? Vec_IntDup(vIns) : NULL; + int fOnlyPis = 0, Iter = 0; + // iterate expansion until + // (1) the cut cannot be expanded because all leaves are PIs + // (2) the cut size exceeded the limit for 5 consecutive iterations + while ( !fOnlyPis && (Vec_IntSize(vIns) <= nInputsMax || Iter < 5) ) + { + int iFanBest = Gia_RsbFindFaninToAddToCut( p, vIns ); + Vec_IntPush( vIns, iFanBest ); + Gia_ObjSetTravIdCurrentId( p, iFanBest ); + fOnlyPis = Gia_RsbExpandCut( p, vIns ); + if ( Vec_IntSize(vIns) > nInputsMax ) + Iter++; + else + Iter = 0; + if ( Vec_IntSize(vIns) <= nInputsMax && (!vBest || Vec_IntSize(vBest) <= Vec_IntSize(vIns)) ) + { + if ( vBest ) + Vec_IntClear(vBest); + else + vBest = Vec_IntAlloc( 10 ); + Vec_IntAppend( vBest, vIns ); + } + } + if ( vBest ) + { + Vec_IntClear( vIns ); + Vec_IntAppend( vIns, vBest ); + Vec_IntFree( vBest ); + } + else + assert( Vec_IntSize(vIns) > nInputsMax ); + } + if ( vLevels && Vec_IntSize(vIns) <= nInputsMax ) + { + Vec_IntSort( vIns, 0 ); + Gia_WinCreateFromCut( p, iObj, vIns, vLevels, vWin ); + } +} + +/**Function************************************************************* + + Synopsis [Create window for the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_RsbWindowCompute( Gia_Man_t * p, int iObj, int nInputsMax, int nLevelsMax, Vec_Wec_t * vLevels, Vec_Int_t * vPaths, Vec_Int_t ** pvWin, Vec_Int_t ** pvIns ) +{ + Vec_Int_t * vWin, * vIns; + *pvWin = *pvIns = NULL; + vWin = Gia_RsbWindowInit( p, vPaths, iObj, nLevelsMax ); + if ( vWin == NULL ) + return 0; + vIns = Gia_RsbCreateWindowInputs( p, vWin ); + // vWin and vIns are labeled with the current trav ID + //Vec_IntPrint( vWin ); + //Vec_IntPrint( vIns ); + if ( Vec_IntSize(vIns) <= nInputsMax + 3 ) // consider windows, which initially has a larger input space + Gia_RsbWindowGrow2( p, iObj, vLevels, vWin, vIns, nInputsMax ); + if ( Vec_IntSize(vIns) <= nInputsMax ) + { + Vec_IntSort( vWin, 0 ); + Vec_IntSort( vIns, 0 ); + *pvWin = vWin; + *pvIns = vIns; + return 1; + } + else + { + Vec_IntFree( vWin ); + Vec_IntFree( vIns ); + return 0; + } +} + +/**Function************************************************************* + + Synopsis [Derive GIA from the window] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_RsbFindOutputs( Gia_Man_t * p, Vec_Int_t * vWin, Vec_Int_t * vIns, Vec_Int_t * vRefs ) +{ + Vec_Int_t * vOuts = Vec_IntAlloc( 100 ); + Gia_Obj_t * pObj; int i; + Gia_ManIncrementTravId( p ); + Gia_ManForEachObjVec( vIns, p, pObj, i ) + Gia_ObjSetTravIdCurrent( p, pObj ); + Gia_ManForEachObjVec( vWin, p, pObj, i ) + if ( !Gia_ObjIsTravIdCurrent(p, pObj) && Gia_ObjIsAnd(pObj) ) + { + Vec_IntAddToEntry( vRefs, Gia_ObjFaninId0p(p, pObj), 1 ); + Vec_IntAddToEntry( vRefs, Gia_ObjFaninId1p(p, pObj), 1 ); + } + Gia_ManForEachObjVec( vWin, p, pObj, i ) + if ( !Gia_ObjIsTravIdCurrent(p, pObj) && Gia_ObjFanoutNum(p, pObj) != Vec_IntEntry(vRefs, Gia_ObjId(p, pObj)) ) + Vec_IntPush( vOuts, Gia_ObjId(p, pObj) ); + Gia_ManForEachObjVec( vWin, p, pObj, i ) + if ( !Gia_ObjIsTravIdCurrent(p, pObj) && Gia_ObjIsAnd(pObj) ) + { + Vec_IntAddToEntry( vRefs, Gia_ObjFaninId0p(p, pObj), -1 ); + Vec_IntAddToEntry( vRefs, Gia_ObjFaninId1p(p, pObj), -1 ); + } + return vOuts; +} + +Gia_Man_t * Gia_RsbDeriveGiaFromWindows( Gia_Man_t * p, Vec_Int_t * vWin, Vec_Int_t * vIns, Vec_Int_t * vOuts ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObjVec( vIns, p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachObjVec( vWin, p, pObj, i ) + if ( !~pObj->Value ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachObjVec( vOuts, p, pObj, i ) + Gia_ManAppendCo( pNew, pObj->Value ); + Gia_ManHashStop( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Naive truth-table-based verification.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word Gia_LutComputeTruth66_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + word Truth0, Truth1; + if ( Gia_ObjIsCi(pObj) ) + return s_Truths6[Gia_ObjCioId(pObj)]; + if ( Gia_ObjIsConst0(pObj) ) + return 0; + assert( Gia_ObjIsAnd(pObj) ); + Truth0 = Gia_LutComputeTruth66_rec( p, Gia_ObjFanin0(pObj) ); + Truth1 = Gia_LutComputeTruth66_rec( p, Gia_ObjFanin1(pObj) ); + if ( Gia_ObjFaninC0(pObj) ) + Truth0 = ~Truth0; + if ( Gia_ObjFaninC1(pObj) ) + Truth1 = ~Truth1; + return Truth0 & Truth1; +} +int Gia_ManVerifyTwoTruths( Gia_Man_t * p1, Gia_Man_t * p2 ) +{ + int i, fFailed = 0; + assert( Gia_ManCoNum(p1) == Gia_ManCoNum(p2) ); + for ( i = 0; i < Gia_ManCoNum(p1); i++ ) + { + Gia_Obj_t * pPo1 = Gia_ManCo(p1, i); + Gia_Obj_t * pPo2 = Gia_ManCo(p2, i); + word word1 = Gia_LutComputeTruth66_rec( p1, Gia_ObjFanin0(pPo1) ); + word word2 = Gia_LutComputeTruth66_rec( p2, Gia_ObjFanin0(pPo2) ); + if ( Gia_ObjFaninC0(pPo1) ) + word1 = ~word1; + if ( Gia_ObjFaninC0(pPo2) ) + word2 = ~word2; + if ( word1 != word2 ) + { + //Dau_DsdPrintFromTruth( &word1, 6 ); + //Dau_DsdPrintFromTruth( &word2, 6 ); + printf( "Verification failed for output %d (out of %d).\n", i, Gia_ManCoNum(p1) ); + fFailed = 1; + } + } +// if ( !fFailed ) +// printf( "Verification succeeded for %d outputs.\n", Gia_ManCoNum(p1) ); + return !fFailed; +} + + + +/**Function************************************************************* + + Synopsis [Enumerate windows of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_RsbEnumerateWindows( Gia_Man_t * p, int nInputsMax, int nLevelsMax ) +{ + int fVerbose = 0; + int fUseHash = 0; + int i, nWins = 0, nWinSize = 0, nInsSize = 0, nOutSize = 0, nNodeGain = 0; + Vec_Wec_t * vLevels = Vec_WecStart( Gia_ManLevelNum(p)+1 ); + Vec_Int_t * vPaths = Vec_IntStart( Gia_ManObjNum(p) ); + Vec_Int_t * vRefs = Vec_IntStart( Gia_ManObjNum(p) ); + Hsh_VecMan_t * pHash = Hsh_VecManStart( 1000 ); + Gia_Obj_t * pObj; + Gia_Man_t * pIn, * pOut; + abctime clk = Abc_Clock(); + Gia_ManStaticFanoutStart( p ); + Gia_ManForEachAnd( p, pObj, i ) + { + Vec_Int_t * vWin, * vIns, * vOuts; + if ( !Gia_RsbWindowCompute( p, i, nInputsMax, nLevelsMax, vLevels, vPaths, &vWin, &vIns ) ) + continue; + vOuts = Gia_RsbFindOutputs( p, vWin, vIns, vRefs ); + nWins++; + nWinSize += Vec_IntSize(vWin); + nInsSize += Vec_IntSize(vIns); + nOutSize += Vec_IntSize(vOuts); + + + if ( fVerbose ) + { + printf( "\n\nObj %d\n", i ); + Vec_IntPrint( vWin ); + Vec_IntPrint( vIns ); + Vec_IntPrint( vOuts ); + printf( "\n" ); + } + else if ( Vec_IntSize(vWin) > 1000 ) + printf( "Obj %d. Window: Ins = %d. Ands = %d. Outs = %d.\n", + i, Vec_IntSize(vIns), Vec_IntSize(vWin)-Vec_IntSize(vIns), Vec_IntSize(vOuts) ); + + if ( fUseHash ) + { + int nEntries = Hsh_VecSize(pHash); + Hsh_VecManAdd( pHash, vWin ); + if ( nEntries == Hsh_VecSize(pHash) ) + { + Vec_IntFree( vWin ); + Vec_IntFree( vIns ); + Vec_IntFree( vOuts ); + continue; + } + } + + pIn = Gia_RsbDeriveGiaFromWindows( p, vWin, vIns, vOuts ); + pOut = Gia_ManResub2Test( pIn ); + //pOut = Gia_ManDup( pIn ); + if ( !Gia_ManVerifyTwoTruths( pIn, pOut ) ) + { + Gia_ManPrint( pIn ); + Gia_ManPrint( pOut ); + pOut = pOut; + } + + nNodeGain += Gia_ManAndNum(pIn) - Gia_ManAndNum(pOut); + Gia_ManStop( pIn ); + Gia_ManStop( pOut ); + + Vec_IntFree( vWin ); + Vec_IntFree( vIns ); + Vec_IntFree( vOuts ); + } + Gia_ManStaticFanoutStop( p ); + Vec_WecFree( vLevels ); + Vec_IntFree( vPaths ); + Vec_IntFree( vRefs ); + printf( "Computed windows for %d nodes (out of %d). Unique = %d. Ave inputs = %.2f. Ave outputs = %.2f. Ave volume = %.2f. Gain = %d. ", + nWins, Gia_ManAndNum(p), Hsh_VecSize(pHash), 1.0*nInsSize/Abc_MaxInt(1,nWins), + 1.0*nOutSize/Abc_MaxInt(1,nWins), 1.0*nWinSize/Abc_MaxInt(1,nWins), nNodeGain ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + Hsh_VecManStop( pHash ); +} + +/**Function************************************************************* + + Synopsis [Apply k-resub to one AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_RsbTryOneWindow( Gia_Man_t * p ) +{ + return Gia_ManResub2Test( p ); +} + +/**Function************************************************************* + + Synopsis [Apply k-resub to one AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_RsbTestArray() +{ + int Array[1000] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 3, 7, 15, 17, 8, 19, + 5, 20, 5, 12, 8, 24, 4, 12, 9, 28, 27, 31, 23, 32, 4, 13, 8, 36, 5, + 13, 18, 40, 9, 18, 5, 44, 19, 36, 9, 48, 47, 51, 10, 18, 40, 54, 8, + 56, 25, 37, 44, 61, 59, 63, 8, 28, 8, 18, 25, 68, 66, 70, 64, 73, 11, + 19, 8, 13, 76, 78, 10, 19, 40, 82, 9, 84, 81, 87, 20, 61, 19, 28, 30, + 92, 91, 95, 88, 96, 74, 98, 9, 40, 49, 103, 27, 104, 10, 107, 8, 40, + 9, 24, 111, 113, 11, 115, 109, 117, 11, 66, 51, 121, 118, 122, 18, 36, + 18, 110, 93, 127, 10, 131, 129, 133, 11, 38, 32, 137, 103, 138, 19, 141, + 134, 143, 28, 76, 9, 146, 11, 110, 19, 150, 149, 153, 87, 95, 9, 19, 10, + 159, 61, 160, 18, 30, 61, 158, 9, 12, 25, 169, 19, 171, 111, 173, 10, 175, + 167, 177, 18, 102, 4, 20, 18, 171, 183, 185, 11, 187, 181, 189, 178, 190, + 24, 44, 11, 194, 8, 54, 4, 198, 197, 201, 45, 49, 10, 39, 9, 126, 73, 209, + 11, 211, 54, 168, 213, 215, 43, 167, 67, 218, 10, 221, 26, 54, 18, 18, 34, + 34, 38, 38, 40, 40, 42, 42, 52, 52, 100, 100, 124, 124, 126, 126, 144, 144, + 148, 148, 154, 154, 156, 156, 162, 162, 164, 164, 192, 192, 70, 70, 202, + 202, 204, 204, 206, 206, 216, 216, 222, 222, 224, 224 + }; + int i, iFan0, iFan1, nResubs; + int * pRes; + // create the internal array + Vec_Int_t * vArray = Vec_IntAlloc( 100 ); + for ( i = 0; i < 50 || Array[i] > 0; i++ ) + Vec_IntPush( vArray, Array[i] ); + Vec_IntPrint( vArray ); + // check the nodes + printf( "Constant0 and primary inputs:\n" ); + Vec_IntForEachEntryDouble( vArray, iFan0, iFan1, i ) + { + if ( iFan0 != iFan1 ) + break; + printf( "%2d = %c%2d & %c%2d;\n", i, + Abc_LitIsCompl(iFan0) ? '!' : ' ', Abc_Lit2Var(iFan0), + Abc_LitIsCompl(iFan1) ? '!' : ' ', Abc_Lit2Var(iFan1) ); + } + printf( "Primary outputs:\n" ); + Vec_IntForEachEntryDoubleStart( vArray, iFan0, iFan1, i, 14 ) + { + if ( iFan0 != iFan1 ) + continue; + printf( "%2d = %c%2d & %c%2d;\n", i, + Abc_LitIsCompl(iFan0) ? '!' : ' ', Abc_Lit2Var(iFan0), + Abc_LitIsCompl(iFan1) ? '!' : ' ', Abc_Lit2Var(iFan1) ); + } + // run the resub + Abc_ResubPrepareManager( 1 ); + Abc_ResubComputeWindow( Vec_IntArray(vArray), Vec_IntSize(vArray)/2, 10, -1, 0, 0, 1, 1, &pRes, &nResubs ); + Abc_ResubPrepareManager( 0 ); + Vec_IntFree( vArray ); +} + +/**Function************************************************************* + + Synopsis [Computing cuts of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Gia_ManExtractCuts2( Gia_Man_t * p, int nCutSize, int nCuts, int fVerbose ) +{ + int c, nLevelMax = 8; + abctime clk = Abc_Clock(); + Vec_Wec_t * vCuts = Vec_WecStart( nCuts ); + Vec_Int_t * vPaths = Vec_IntStart( Gia_ManObjNum(p) ); + srand( time(NULL) ); + for ( c = 0; c < nCuts; ) + { + Vec_Int_t * vCut, * vWin = NULL; + while ( vWin == NULL ) + { + int iPivot = 1 + Gia_ManCiNum(p) + rand() % Gia_ManAndNum(p); + assert( Gia_ObjIsAnd(Gia_ManObj(p, iPivot)) ); + vWin = Gia_RsbWindowInit( p, vPaths, iPivot, nLevelMax ); + } + vCut = Gia_RsbCreateWindowInputs( p, vWin ); + if ( Vec_IntSize(vCut) >= nCutSize - 2 && Vec_IntSize(vCut) <= nCutSize ) + { + Vec_IntPush( Vec_WecEntry(vCuts, c), Vec_IntSize(vCut) ); + Vec_IntAppend( Vec_WecEntry(vCuts, c++), vCut ); + } + Vec_IntFree( vCut ); + Vec_IntFree( vWin ); + } + Vec_IntFree( vPaths ); + Abc_PrintTime( 0, "Computing cuts ", Abc_Clock() - clk ); + return vCuts; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaResub3.c b/yosys/abc/src/aig/gia/giaResub3.c new file mode 100644 index 00000000000..71e182d11c3 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaResub3.c @@ -0,0 +1,54 @@ +/**CFile**************************************************************** + + FileName [giaResub3.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Resubstitution computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaResub3.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManPerformNewResub( Gia_Man_t * p, int nWinCount, int nCutSize, int nProcs, int fVerbose ) +{ + return NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaResub6.c b/yosys/abc/src/aig/gia/giaResub6.c new file mode 100644 index 00000000000..85d5bb094aa --- /dev/null +++ b/yosys/abc/src/aig/gia/giaResub6.c @@ -0,0 +1,564 @@ +/**CFile**************************************************************** + + FileName [giaResub6.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Resubstitution.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaResub6.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/util/utilTruth.h" +#include "base/io/ioResub.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define MAX_NODE 100 + +typedef struct Res6_Man_t_ Res6_Man_t; +struct Res6_Man_t_ +{ + int nIns; // inputs + int nDivs; // divisors + int nDivsA; // divisors alloc + int nOuts; // outputs + int nPats; // patterns + int nWords; // words + Vec_Wrd_t vIns; // input sim data + Vec_Wrd_t vOuts; // input sim data + word ** ppLits; // literal sim info + word ** ppSets; // set sim info + Vec_Int_t vSol; // current solution + Vec_Int_t vSolBest; // best solution + Vec_Int_t vTempBest;// current best solution + Vec_Int_t vSupp; // support +}; + +extern void Dau_DsdPrintFromTruth2( word * pTruth, int nVarsInit ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Res6_Man_t * Res6_ManStart( int nIns, int nNodes, int nOuts, int nPats ) +{ + Res6_Man_t * p; int i; + p = ABC_CALLOC( Res6_Man_t, 1 ); + p->nIns = nIns; + p->nDivs = 1 + nIns + nNodes; + p->nDivsA = p->nDivs + MAX_NODE; + p->nOuts = nOuts; + p->nPats = nPats; + p->nWords =(nPats + 63)/64; + Vec_WrdFill( &p->vIns, 2*p->nDivsA*p->nWords, 0 ); + Vec_WrdFill( &p->vOuts, (1 << nOuts)*p->nWords, 0 ); + p->ppLits = ABC_CALLOC( word *, 2*p->nDivsA ); + p->ppSets = ABC_CALLOC( word *, 1 << nOuts ); + for ( i = 0; i < 2*p->nDivsA; i++ ) + p->ppLits[i] = Vec_WrdEntryP( &p->vIns, i*p->nWords ); + for ( i = 0; i < (1 << nOuts); i++ ) + p->ppSets[i] = Vec_WrdEntryP( &p->vOuts, i*p->nWords ); + Abc_TtFill( p->ppLits[1], p->nWords ); + Vec_IntGrow( &p->vSol, 2*MAX_NODE+nOuts ); + Vec_IntGrow( &p->vSolBest, 2*MAX_NODE+nOuts ); + Vec_IntGrow( &p->vTempBest, 2*MAX_NODE+nOuts ); + return p; +} +static inline void Res6_ManStop( Res6_Man_t * p ) +{ + Vec_WrdErase( &p->vIns ); + Vec_WrdErase( &p->vOuts ); + Vec_IntErase( &p->vSol ); + Vec_IntErase( &p->vSolBest ); + Vec_IntErase( &p->vTempBest ); + Vec_IntErase( &p->vSupp ); + ABC_FREE( p->ppLits ); + ABC_FREE( p->ppSets ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Res6_Man_t * Res6_ManReadPla( char * pFileName ) +{ + int i, n; + Abc_RData_t * pData = Abc_ReadPla( pFileName ); assert( pData->nOuts == 1 ); + Res6_Man_t * p = pData ? Res6_ManStart( 0, pData->nIns, pData->nOuts, pData->nPats ) : NULL; + if ( p == NULL ) return NULL; + assert( pData->nSimWords == p->nWords ); + for ( i = 1; i < p->nDivs; i++ ) + for ( n = 0; n < 2; n++ ) + Abc_TtCopy( p->ppLits[2*i+n], Vec_WrdEntryP(pData->vSimsIn, (i-1)*pData->nSimWords), pData->nSimWords, n ); + for ( i = 0; i < (1 << p->nOuts); i++ ) + Abc_TtCopy( p->ppSets[i], Vec_WrdEntryP(pData->vSimsOut, i*pData->nSimWords), pData->nSimWords, 0 ); + if ( pData->vDivs ) + Vec_IntForEachEntry( pData->vDivs, n, i ) + Vec_IntPush( &p->vSupp, 1+n ); + if ( pData->vSol ) { + Vec_IntForEachEntry( pData->vSol, n, i ) + Vec_IntPush( &p->vSol, n ); + Vec_IntPush( &p->vSol, Vec_IntEntryLast(&p->vSol) ); + } + Abc_RDataStop( pData ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Res6_Man_t * Res6_ManRead( char * pFileName ) +{ + Res6_Man_t * p = NULL; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + printf( "Cannot open input file \"%s\".\n", pFileName ); + else + { + int i, k, nIns, nNodes, nOuts, nPats; + char Temp[100], Buffer[100]; + char * pLine = fgets( Buffer, 100, pFile ); + if ( pLine == NULL ) + { + printf( "Cannot read the header line of input file \"%s\".\n", pFileName ); + return NULL; + } + if ( 5 != sscanf(pLine, "%s %d %d %d %d", Temp, &nIns, &nNodes, &nOuts, &nPats) ) + { + printf( "Cannot read the parameters from the header of input file \"%s\".\n", pFileName ); + return NULL; + } + p = Res6_ManStart( nIns, nNodes, nOuts, nPats ); + pLine = ABC_ALLOC( char, nPats + 100 ); + for ( i = 1; i < p->nDivs; i++ ) + { + char * pNext = fgets( pLine, nPats + 100, pFile ); + if ( pNext == NULL ) + { + printf( "Cannot read line %d of input file \"%s\".\n", i, pFileName ); + Res6_ManStop( p ); + ABC_FREE( pLine ); + fclose( pFile ); + return NULL; + } + for ( k = 0; k < p->nPats; k++ ) + if ( pNext[k] == '0' ) + Abc_TtSetBit( p->ppLits[2*i+1], k ); + else if ( pNext[k] == '1' ) + Abc_TtSetBit( p->ppLits[2*i], k ); + } + for ( i = 0; i < (1 << p->nOuts); i++ ) + { + char * pNext = fgets( pLine, nPats + 100, pFile ); + if ( pNext == NULL ) + { + printf( "Cannot read line %d of input file \"%s\".\n", i, pFileName ); + Res6_ManStop( p ); + ABC_FREE( pLine ); + fclose( pFile ); + return NULL; + } + for ( k = 0; k < p->nPats; k++ ) + if ( pNext[k] == '1' ) + Abc_TtSetBit( p->ppSets[i], k ); + } + ABC_FREE( pLine ); + fclose( pFile ); + } + return p; +} +void Res6_ManWrite( char * pFileName, Res6_Man_t * p ) +{ + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + printf( "Cannot open output file \"%s\".\n", pFileName ); + else + { + int i, k; + fprintf( pFile, "resyn %d %d %d %d\n", p->nIns, p->nDivs - p->nIns - 1, p->nOuts, p->nPats ); + for ( i = 1; i < p->nDivs; i++, fputc('\n', pFile) ) + for ( k = 0; k < p->nPats; k++ ) + if ( Abc_TtGetBit(p->ppLits[2*i+1], k) ) + fputc( '0', pFile ); + else if ( Abc_TtGetBit(p->ppLits[2*i], k) ) + fputc( '1', pFile ); + else + fputc( '-', pFile ); + for ( i = 0; i < (1 << p->nOuts); i++, fputc('\n', pFile) ) + for ( k = 0; k < p->nPats; k++ ) + fputc( '0' + Abc_TtGetBit(p->ppSets[i], k), pFile ); + fclose( pFile ); + } +} +void Res6_ManPrintProblem( Res6_Man_t * p, int fVerbose ) +{ + int i, nInputs = (p->nIns && p->nIns < 6) ? p->nIns : 6; + printf( "Problem: In = %d Div = %d Out = %d Pat = %d\n", p->nIns, p->nDivs - p->nIns - 1, p->nOuts, p->nPats ); + if ( !fVerbose ) + return; + printf( "%02d : %s\n", 0, "const0" ); + printf( "%02d : %s\n", 1, "const1" ); + for ( i = 1; i < p->nDivs; i++ ) + { + if ( nInputs < 6 ) + { + *p->ppLits[2*i+0] = Abc_Tt6Stretch( *p->ppLits[2*i+0], nInputs ); + *p->ppLits[2*i+1] = Abc_Tt6Stretch( *p->ppLits[2*i+1], nInputs ); + } + printf("%02d : ", 2*i+0), Dau_DsdPrintFromTruth2(p->ppLits[2*i+0], nInputs), printf( "\n" ); + printf("%02d : ", 2*i+1), Dau_DsdPrintFromTruth2(p->ppLits[2*i+1], nInputs), printf( "\n" ); + } + for ( i = 0; i < (1 << p->nOuts); i++ ) + { + if ( nInputs < 6 ) + *p->ppSets[i] = Abc_Tt6Stretch( *p->ppSets[i], nInputs ); + printf("%02d : ", i), Dau_DsdPrintFromTruth2(p->ppSets[i], nInputs), printf( "\n" ); + } +} +static inline Vec_Int_t * Res6_ManReadSol( char * pFileName ) +{ + Vec_Int_t * vRes = NULL; int Num; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + printf( "Cannot open input file \"%s\".\n", pFileName ); + else + { + while ( fgetc(pFile) != '\n' ); + vRes = Vec_IntAlloc( 10 ); + while ( fscanf(pFile, "%d", &Num) == 1 ) + Vec_IntPush( vRes, Num ); + fclose ( pFile ); + } + return vRes; +} +static inline void Res6_ManWriteSol( char * pFileName, Vec_Int_t * p ) +{ + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + printf( "Cannot open output file \"%s\".\n", pFileName ); + else + { + int i, iLit; + Vec_IntForEachEntry( p, iLit, i ) + fprintf( pFile, "%d ", iLit ); + fclose ( pFile ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Res6_LitSign( int iLit ) +{ + return Abc_LitIsCompl(iLit) ? '~' : ' '; +} +static inline int Res6_LitChar( int iLit, int nDivs ) +{ + return Abc_Lit2Var(iLit) < nDivs ? (nDivs < 28 ? 'a'+Abc_Lit2Var(iLit)-1 : 'd') : 'x'; +} +static inline void Res6_LitPrint( int iLit, int nDivs ) +{ + if ( iLit < 2 ) + printf( "%d", iLit ); + else + { + printf( "%c%c", Res6_LitSign(iLit), Res6_LitChar(iLit, nDivs) ); + if ( Abc_Lit2Var(iLit) >= nDivs || nDivs >= 28 ) + printf( "%d", Abc_Lit2Var(iLit) ); + } +} +Vec_Int_t * Res6_FindSupport( Vec_Int_t * vSol, int nDivs ) +{ + int i, iLit; + Vec_Int_t * vSupp = Vec_IntAlloc( 10 ); + Vec_IntForEachEntry( vSol, iLit, i ) + if ( iLit >= 2 && iLit < 2*nDivs ) + Vec_IntPushUnique( vSupp, Abc_Lit2Var(iLit) ); + return vSupp; +} +void Res6_PrintSuppSims( Vec_Int_t * vSol, word ** ppLits, int nWords, int nDivs ) +{ + Vec_Int_t * vSupp = Res6_FindSupport( vSol, nDivs ); + int i, k, iObj; + Vec_IntForEachEntry( vSupp, iObj, i ) + { + for ( k = 0; k < 64*nWords; k++ ) + if ( Abc_TtGetBit(ppLits[2*iObj+1], k) ) + printf( "0" ); + else if ( Abc_TtGetBit(ppLits[2*iObj], k) ) + printf( "1" ); + else + printf( "-" ); + printf( "\n" ); + } + for ( k = 0; k < 64*nWords; k++ ) + { + Vec_IntForEachEntry( vSupp, iObj, i ) + if ( Abc_TtGetBit(ppLits[2*iObj+1], k) ) + printf( "0" ); + else if ( Abc_TtGetBit(ppLits[2*iObj+0], k) ) + printf( "1" ); + else + printf( "-" ); + printf( "\n" ); + if ( k == 9 ) + break; + } + Vec_IntFree( vSupp ); +} +int Res6_FindSupportSize( Vec_Int_t * vSol, int nDivs ) +{ + Vec_Int_t * vSupp = Res6_FindSupport( vSol, nDivs ); + int Res = Vec_IntSize(vSupp); + Vec_IntFree( vSupp ); + return Res; +} +void Res6_PrintSolution( Vec_Int_t * vSol, int nDivs ) +{ + int iNode, nNodes = Vec_IntSize(vSol)/2-1; + assert( Vec_IntSize(vSol) % 2 == 0 ); + printf( "Solution: In = %d Div = %d Node = %d Out = %d\n", Res6_FindSupportSize(vSol, nDivs), nDivs-1, nNodes, 1 ); + for ( iNode = 0; iNode <= nNodes; iNode++ ) + { + int * pLits = Vec_IntEntryP( vSol, 2*iNode ); + printf( "x%-2d = ", nDivs + iNode ); + Res6_LitPrint( pLits[0], nDivs ); + if ( pLits[0] != pLits[1] ) + { + printf( " %c ", pLits[0] < pLits[1] ? '&' : '^' ); + Res6_LitPrint( pLits[1], nDivs ); + } + printf( "\n" ); + } +} +int Res6_FindGetCost( Res6_Man_t * p, int iDiv ) +{ + int w, Cost = 0; + //printf( "DivLit = %d\n", iDiv ); + //Abc_TtPrintBinary1( stdout, p->ppLits[iDiv], p->nIns ); printf( "\n" ); + //printf( "Set0\n" ); + //Abc_TtPrintBinary1( stdout, p->ppSets[0], p->nIns ); printf( "\n" ); + //printf( "Set1\n" ); + //Abc_TtPrintBinary1( stdout, p->ppSets[1], p->nIns ); printf( "\n" ); + for ( w = 0; w < p->nWords; w++ ) + Cost += Abc_TtCountOnes( (p->ppLits[iDiv][w] & p->ppSets[0][w]) | (p->ppLits[iDiv^1][w] & p->ppSets[1][w]) ); + return Cost; +} +int Res6_FindBestDiv( Res6_Man_t * p, int * pCost ) +{ + int d, dBest = -1, CostBest = ABC_INFINITY; + for ( d = 0; d < 2*p->nDivs; d++ ) + { + int Cost = Res6_FindGetCost( p, d ); + printf( "Div = %d Cost = %d\n", d, Cost ); + if ( CostBest >= Cost ) + CostBest = Cost, dBest = d; + } + if ( pCost ) + *pCost = CostBest; + return dBest; +} +int Res6_FindBestEval( Res6_Man_t * p, Vec_Int_t * vSol, int Start ) +{ + int i, iLit0, iLit1; + assert( Vec_IntSize(vSol) % 2 == 0 ); + Vec_IntForEachEntryDoubleStart( vSol, iLit0, iLit1, i, 2*Start ) + { + if ( iLit0 > iLit1 ) + { + Abc_TtXor( p->ppLits[2*p->nDivs+i+0], p->ppLits[iLit0], p->ppLits[iLit1], p->nWords, 0 ); + Abc_TtXor( p->ppLits[2*p->nDivs+i+1], p->ppLits[iLit0], p->ppLits[iLit1], p->nWords, 1 ); + } + else + { + Abc_TtAnd( p->ppLits[2*p->nDivs+i+0], p->ppLits[iLit0], p->ppLits[iLit1], p->nWords, 0 ); + Abc_TtOr ( p->ppLits[2*p->nDivs+i+1], p->ppLits[iLit0^1], p->ppLits[iLit1^1], p->nWords ); + } + + //printf( "Node %d\n", i/2 ); + //Abc_TtPrintBinary1( stdout, p->ppLits[2*p->nDivs+i+0], 6 ); printf( "\n" ); + //Abc_TtPrintBinary1( stdout, p->ppLits[2*p->nDivs+i+1], 6 ); printf( "\n" ); + } + return Res6_FindGetCost( p, Vec_IntEntryLast(vSol) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Res6_ManResubVerify( Res6_Man_t * p, Vec_Int_t * vSol ) +{ + int Cost = Res6_FindBestEval( p, vSol, 0 ); + if ( Cost == 0 ) + printf( "Verification successful.\n" ); + else + printf( "Verification FAILED with %d errors on %d patterns.\n", Cost, p->nPats ); +} +void Res6_ManResubCheck( char * pFileNameRes, char * pFileNameSol, int fVerbose ) +{ + char FileNameSol[1000]; + if ( pFileNameSol ) + strcpy( FileNameSol, pFileNameSol ); + else + { + strcpy( FileNameSol, pFileNameRes ); + strcpy( FileNameSol + strlen(FileNameSol) - strlen(".resub"), ".sol" ); + } + { + Res6_Man_t * p = Res6_ManRead( pFileNameRes ); + Vec_Int_t * vSol = Res6_ManReadSol( FileNameSol ); + //Vec_IntPrint( vSol ); + if ( p == NULL || vSol == NULL ) + return; + if ( fVerbose ) + Res6_ManPrintProblem( p, 0 ); + if ( fVerbose ) + Res6_PrintSolution( vSol, p->nDivs ); + //if ( fVerbose ) + // Res6_PrintSuppSims( vSol, p->ppLits, p->nWords, p->nDivs ); + Res6_ManResubVerify( p, vSol ); + Vec_IntFree( vSol ); + Res6_ManStop( p ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Res6_FindBestEvalPla( Res6_Man_t * p, Vec_Int_t * vSol ) +{ + int i, n, iObj, iLit0, iLit1, iOffset = 2*(1+Vec_IntSize(&p->vSupp)); + assert( Vec_IntSize(vSol) % 2 == 0 ); + Vec_IntForEachEntry( &p->vSupp, iObj, i ) + for ( n = 0; n < 2; n++ ) + Abc_TtCopy( p->ppLits[2*(1+i)+n], p->ppLits[2*iObj+n], p->nWords, 0 ); + Vec_IntForEachEntryDouble( vSol, iLit0, iLit1, i ) + { + if ( iLit0 > iLit1 ) + { + Abc_TtXor( p->ppLits[iOffset+i+0], p->ppLits[iLit0], p->ppLits[iLit1], p->nWords, 0 ); + Abc_TtXor( p->ppLits[iOffset+i+1], p->ppLits[iLit0], p->ppLits[iLit1], p->nWords, 1 ); + } + else + { + Abc_TtAnd( p->ppLits[iOffset+i+0], p->ppLits[iLit0], p->ppLits[iLit1], p->nWords, 0 ); + Abc_TtOr ( p->ppLits[iOffset+i+1], p->ppLits[iLit0^1], p->ppLits[iLit1^1], p->nWords ); + } + } + return Res6_FindGetCost( p, Vec_IntEntryLast(vSol) ); +} +void Res6_ManResubVerifyPla( Res6_Man_t * p, Vec_Int_t * vSol ) +{ + int Cost = Res6_FindBestEvalPla( p, vSol ); + if ( Cost == 0 ) + printf( "Verification successful.\n" ); + else + printf( "Verification FAILED with %d errors on %d patterns.\n", Cost, p->nPats ); +} +void Res6_PrintSolutionPla( Vec_Int_t * vSol, int nSuppSize, int nDivs ) +{ + int iNode, nNodes = Vec_IntSize(vSol)/2-1; + assert( Vec_IntSize(vSol) % 2 == 0 ); + printf( "Solution: In = %d Div = %d Node = %d Out = %d\n", nSuppSize, nDivs-1, nNodes, 1 ); + for ( iNode = 0; iNode <= nNodes; iNode++ ) + { + int * pLits = Vec_IntEntryP( vSol, 2*iNode ); + printf( "x%-2d = ", 1+nSuppSize+iNode ); + Res6_LitPrint( pLits[0], 1+nSuppSize ); + if ( pLits[0] != pLits[1] ) + { + printf( " %c ", pLits[0] < pLits[1] ? '&' : '^' ); + Res6_LitPrint( pLits[1], 1+nSuppSize ); + } + printf( "\n" ); + } +} +void Res6_ManResubCheckPla( char * pFileName, int fVerbose ) +{ + Res6_Man_t * p = Res6_ManReadPla( pFileName ); + if ( p == NULL ) return; + //Vec_IntPrint( &p->vSupp ); + //Vec_IntPrint( &p->vSol ); + if ( fVerbose ) + Res6_ManPrintProblem( p, 0 ); + if ( fVerbose ) + Res6_PrintSolutionPla( &p->vSol, Vec_IntSize(&p->vSupp), p->nDivs ); + //if ( fVerbose ) + // Res6_PrintSuppSims( vSol, p->ppLits, p->nWords, p->nDivs ); + Res6_ManResubVerifyPla( p, &p->vSol ); + Res6_ManStop( p ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaRetime.c b/yosys/abc/src/aig/gia/giaRetime.c new file mode 100644 index 00000000000..c229adae9b4 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaRetime.c @@ -0,0 +1,304 @@ +/**CFile**************************************************************** + + FileName [giaRetime.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Performs most-forward retiming for AIG with flop classes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaRetime.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Marks objects reachables from Const0 and PIs/ + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManMarkAutonomous_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return pObj->fMark0; + Gia_ObjSetTravIdCurrent(p, pObj); + assert( pObj->fMark0 == 0 ); + if ( Gia_ObjIsPi(p, pObj) || Gia_ObjIsConst0(pObj) ) + return pObj->fMark0 = 1; + if ( Gia_ObjIsCo(pObj) ) + return pObj->fMark0 = Gia_ManMarkAutonomous_rec( p, Gia_ObjFanin0(pObj) ); + if ( Gia_ObjIsCi(pObj) ) + return pObj->fMark0 = Gia_ManMarkAutonomous_rec( p, Gia_ObjRoToRi(p, pObj) ); + assert( Gia_ObjIsAnd(pObj) ); + if ( Gia_ManMarkAutonomous_rec( p, Gia_ObjFanin0(pObj) ) ) + return pObj->fMark0 = 1; + return pObj->fMark0 = Gia_ManMarkAutonomous_rec( p, Gia_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Marks with current trav ROs reachable from Const0 and PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManMarkAutonomous( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManCleanMark0( p ); + Gia_ManIncrementTravId( p ); + Gia_ManForEachRo( p, pObj, i ) + Gia_ManMarkAutonomous_rec( p, pObj ); + Gia_ManIncrementTravId( p ); + Gia_ManForEachRo( p, pObj, i ) + if ( pObj->fMark0 ) + Gia_ObjSetTravIdCurrent( p, pObj ); + Gia_ManCleanMark0( p ); +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG recursively.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManRetimeDup_rec( Gia_Man_t * pNew, Gia_Obj_t * pObj ) +{ + if ( ~pObj->Value ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManRetimeDup_rec( pNew, Gia_ObjFanin0(pObj) ); + Gia_ManRetimeDup_rec( pNew, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG while retiming the registers to the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManRetimeDupForward( Gia_Man_t * p, Vec_Ptr_t * vCut ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pObjRi, * pObjRo; + int i; + // create the new manager + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + // create the true PIs + Gia_ManFillValue( p ); + Gia_ManSetPhase( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + // create the registers + Vec_PtrForEachEntry( Gia_Obj_t *, vCut, pObj, i ) + pObj->Value = Abc_LitNotCond( Gia_ManAppendCi(pNew), pObj->fPhase ); + // duplicate logic above the cut + Gia_ManForEachCo( p, pObj, i ) + Gia_ManRetimeDup_rec( pNew, Gia_ObjFanin0(pObj) ); + // create the true POs + Gia_ManForEachPo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + // remember value in LI + Gia_ManForEachRi( p, pObj, i ) + pObj->Value = Gia_ObjFanin0Copy(pObj); + // transfer values from the LIs to the LOs + Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) + pObjRo->Value = pObjRi->Value; + // erase the data values on the internal nodes of the cut + Vec_PtrForEachEntry( Gia_Obj_t *, vCut, pObj, i ) + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = ~0; + // duplicate logic below the cut + Vec_PtrForEachEntry( Gia_Obj_t *, vCut, pObj, i ) + { + Gia_ManRetimeDup_rec( pNew, pObj ); + Gia_ManAppendCo( pNew, Abc_LitNotCond( pObj->Value, pObj->fPhase ) ); + } + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Vec_PtrSize(vCut) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Derives the cut for forward retiming.] + + Description [Assumes topological ordering of the nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManRetimeForwardOne( Gia_Man_t * p, int * pnRegFixed, int * pnRegMoves ) +{ + Vec_Int_t * vFlopClasses = NULL; + Vec_Int_t * vObjClasses = NULL; + Gia_Man_t * pNew; + Vec_Ptr_t * vCut; + Gia_Obj_t * pObj; + int i; + if ( p->vFlopClasses ) + { +// printf( "Performing retiming with register classes.\n" ); + vObjClasses = Vec_IntAlloc( Gia_ManObjNum(p) ); + for ( i = 0; i < Gia_ManObjNum(p); i++ ) + Vec_IntPush( vObjClasses, -1 ); + Gia_ManForEachRo( p, pObj, i ) + Vec_IntWriteEntry( vObjClasses, Gia_ObjId(p, pObj), Vec_IntEntry(p->vFlopClasses, i) ); + vFlopClasses = Vec_IntAlloc( Gia_ManRegNum(p) ); + } + // mark the retimable nodes + Gia_ManIncrementTravId( p ); + Gia_ManMarkAutonomous( p ); + // mark the retimable registers with the fresh trav ID + Gia_ManIncrementTravId( p ); + *pnRegFixed = 0; + Gia_ManForEachRo( p, pObj, i ) + if ( Gia_ObjIsTravIdPrevious(p, pObj) ) + Gia_ObjSetTravIdCurrent(p, pObj); + else + (*pnRegFixed)++; + // mark all the nodes that can be retimed forward + *pnRegMoves = 0; + Gia_ManForEachAnd( p, pObj, i ) + if ( Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pObj)) && Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pObj)) ) + { + if ( vObjClasses && Vec_IntEntry(vObjClasses, Gia_ObjFaninId0(pObj, i)) != Vec_IntEntry(vObjClasses, Gia_ObjFaninId1(pObj, i)) ) + continue; + if ( vObjClasses ) + Vec_IntWriteEntry( vObjClasses, Gia_ObjId(p, pObj), Vec_IntEntry(vObjClasses, Gia_ObjFaninId0(pObj, i)) ); + Gia_ObjSetTravIdCurrent(p, pObj); + (*pnRegMoves)++; + } + // mark the remaining registers + Gia_ManForEachRo( p, pObj, i ) + Gia_ObjSetTravIdCurrent(p, pObj); + // find the cut (all such marked objects that fanout into unmarked nodes) + vCut = Vec_PtrAlloc( 1000 ); + Gia_ManIncrementTravId( p ); + Gia_ManForEachObj( p, pObj, i ) + { + if ( Gia_ObjIsTravIdPrevious(p, pObj) ) + continue; + if ( (Gia_ObjIsCo(pObj) || Gia_ObjIsAnd(pObj)) && Gia_ObjIsTravIdPrevious(p, Gia_ObjFanin0(pObj)) ) + { + if ( vFlopClasses ) + Vec_IntPush( vFlopClasses, Vec_IntEntry(vObjClasses, Gia_ObjFaninId0(pObj, i)) ); + Vec_PtrPush( vCut, Gia_ObjFanin0(pObj) ); + Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin0(pObj) ); + } + if ( Gia_ObjIsAnd(pObj) && Gia_ObjIsTravIdPrevious(p, Gia_ObjFanin1(pObj)) ) + { + if ( vFlopClasses ) + Vec_IntPush( vFlopClasses, Vec_IntEntry(vObjClasses, Gia_ObjFaninId1(pObj, i)) ); + Vec_PtrPush( vCut, Gia_ObjFanin1(pObj) ); + Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin1(pObj) ); + } + } + assert( vFlopClasses == NULL || Vec_IntSize(vFlopClasses) == Vec_PtrSize(vCut) ); + // finally derive the new manager + pNew = Gia_ManRetimeDupForward( p, vCut ); + Vec_PtrFree( vCut ); + if ( vObjClasses ) + Vec_IntFree( vObjClasses ); + pNew->vFlopClasses = vFlopClasses; + return pNew; +} + +/**Function************************************************************* + + Synopsis [Derives the cut for forward retiming.] + + Description [Assumes topological ordering of the nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManRetimeForward( Gia_Man_t * p, int nMaxIters, int fVerbose ) +{ + Gia_Man_t * pNew, * pTemp; + int i, nRegFixed, nRegMoves = 1; + abctime clk; + pNew = p; + for ( i = 0; i < nMaxIters && nRegMoves > 0; i++ ) + { + clk = Abc_Clock(); + pNew = Gia_ManRetimeForwardOne( pTemp = pNew, &nRegFixed, &nRegMoves ); + if ( fVerbose ) + { + printf( "%2d : And = %6d. Reg = %5d. Unret = %5d. Move = %6d. ", + i + 1, Gia_ManAndNum(pTemp), Gia_ManRegNum(pTemp), nRegFixed, nRegMoves ); + ABC_PRT( "Time", Abc_Clock() - clk ); + } + if ( pTemp != p ) + Gia_ManStop( pTemp ); + } +/* + clk = Abc_Clock(); + pNew = Gia_ManReduceLaches( pNew, fVerbose ); + if ( fVerbose ) + { + ABC_PRT( "Register sharing time", Abc_Clock() - clk ); + } +*/ + return pNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaRex.c b/yosys/abc/src/aig/gia/giaRex.c new file mode 100644 index 00000000000..7f8d365e82b --- /dev/null +++ b/yosys/abc/src/aig/gia/giaRex.c @@ -0,0 +1,545 @@ +/**CFile**************************************************************** + + FileName [giaRex.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Regular expressions.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaRex.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/extra/extra.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Simulate AIG with the given sequence.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManAutomSimulate( Gia_Man_t * p, Vec_Int_t * vAlpha, char * pSim ) +{ + Gia_Obj_t * pObj, * pObjRi, * pObjRo; + int nInputs = Vec_IntSize(vAlpha); + int nFrames = strlen(pSim); + int i, k; + assert( Gia_ManPiNum(p) == nInputs ); + printf( "Simulating string \"%s\":\n", pSim ); + Gia_ManCleanMark0(p); + Gia_ManForEachRo( p, pObj, i ) + pObj->fMark0 = 0; + for ( i = 0; i < nFrames; i++ ) + { + Gia_ManForEachPi( p, pObj, k ) + pObj->fMark0 = (int)(Vec_IntFind(vAlpha, pSim[i]) == k); + Gia_ManForEachAnd( p, pObj, k ) + pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & + (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)); + Gia_ManForEachCo( p, pObj, k ) + pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); + Gia_ManForEachRiRo( p, pObjRi, pObjRo, k ) + pObjRo->fMark0 = pObjRi->fMark0; + + printf( "Frame %d : %c %d\n", i, pSim[i], Gia_ManPo(p, 0)->fMark0 ); + } + Gia_ManCleanMark0(p); +} + +/**Function************************************************************* + + Synopsis [Builds 1-hotness contraint.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManBuild1Hot_rec( Gia_Man_t * p, int * pLits, int nLits, int * pZero, int * pOne ) +{ + int Zero0, One0, Zero1, One1; + if ( nLits == 1 ) + { + *pZero = Abc_LitNot(pLits[0]); + *pOne = pLits[0]; + return; + } + Gia_ManBuild1Hot_rec( p, pLits, nLits/2, &Zero0, &One0 ); + Gia_ManBuild1Hot_rec( p, pLits + nLits/2, nLits - nLits/2, &Zero1, &One1 ); + *pZero = Gia_ManHashAnd( p, Zero0, Zero1 ); + *pOne = Gia_ManHashOr( p, Gia_ManHashAnd(p, Zero0, One1), Gia_ManHashAnd(p, Zero1, One0) ); +} +int Gia_ManBuild1Hot( Gia_Man_t * p, Vec_Int_t * vLits ) +{ + int Zero, One; + assert( Vec_IntSize(vLits) > 0 ); + Gia_ManBuild1Hot_rec( p, Vec_IntArray(vLits), Vec_IntSize(vLits), &Zero, &One ); + return One; +} + +/**Function************************************************************* + + Synopsis [Converting regular expressions into sequential AIGs.] + + Description [http://algs4.cs.princeton.edu/lectures/54RegularExpressions.pdf] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_SymbSpecial( char c ) { return c == '(' || c == ')' || c == '*' || c == '|'; } +// collects info about input alphabet and state of the automaton +int Gia_ManRexNumInputs( char * pStr, Vec_Int_t ** pvAlphas, Vec_Int_t ** pvStr2Sta ) +{ + int i, nStates = 0, Length = strlen(pStr); + Vec_Int_t * vAlphas = Vec_IntAlloc( 100 ); // alphabet + Vec_Int_t * vStr2Sta = Vec_IntStartFull( Length + 1 ); // symbol to state + for ( i = 0; i < Length; i++ ) + { + if ( Gia_SymbSpecial(pStr[i]) ) + continue; + if ( Vec_IntFind(vAlphas, pStr[i]) == -1 ) + Vec_IntPush( vAlphas, pStr[i] ); + Vec_IntWriteEntry( vStr2Sta, i, nStates++ ); + } + Vec_IntWriteEntry( vStr2Sta, i, nStates ); + *pvAlphas = vAlphas; + *pvStr2Sta = vStr2Sta; + return nStates; +} +// prints automaton +void Gia_ManPrintAutom( char * pStr, Vec_Int_t * vStaTrans ) +{ + int i = 0, nLength = strlen(pStr); + for ( i = 0; i < nLength; i++ ) + { + printf( "%d \'%c\' ", i, pStr[i] ); + if ( Vec_IntEntry(vStaTrans, i) >= 0 ) + printf( "-> %d \'%c\' ", Vec_IntEntry(vStaTrans, i), pStr[Vec_IntEntry(vStaTrans, i)] ); + printf( "\n" ); + } +} +// prints states reachable through e-transitions +void Gia_ManPrintReached( char * pStr, int iState, Vec_Int_t * vReached ) +{ + int i, Entry; + printf( "Reached from state %d \'%c\': ", iState, pStr[iState] ); + Vec_IntForEachEntry( vReached, Entry, i ) + printf( "%d \'%c\' ", Entry, pStr[Entry] ); + printf( "\n" ); +} +// collect states reachable from the given one by e-transitions +void Gia_ManPrintReached_rec( char * pStr, Vec_Int_t * vStaTrans, int iState, Vec_Int_t * vReached, Vec_Int_t * vVisited, int TravId ) +{ + if ( Vec_IntEntry(vVisited, iState) == TravId ) + return; + Vec_IntWriteEntry( vVisited, iState, TravId ); + if ( !Gia_SymbSpecial(pStr[iState]) ) // read state + Vec_IntPush( vReached, iState ); + if ( pStr[iState] == '\0' ) + return; + if ( Gia_SymbSpecial(pStr[iState]) && pStr[iState] != '|' ) // regular e-transition + Gia_ManPrintReached_rec( pStr, vStaTrans, iState + 1, vReached, vVisited, TravId ); + if ( Vec_IntEntry(vStaTrans, iState) >= 0 ) // additional e-transition + Gia_ManPrintReached_rec( pStr, vStaTrans, Vec_IntEntry(vStaTrans, iState), vReached, vVisited, TravId ); +} +void Gia_ManCollectReached( char * pStr, Vec_Int_t * vStaTrans, int iState, Vec_Int_t * vReached, Vec_Int_t * vVisited, int TravId ) +{ + assert( iState == 0 || !Gia_SymbSpecial(pStr[iState]) ); + assert( Vec_IntEntry(vVisited, iState) != TravId ); + Vec_IntClear( vReached ); + Gia_ManPrintReached_rec( pStr, vStaTrans, iState + 1, vReached, vVisited, TravId ); +} +// preprocesses the regular expression +char * Gia_ManRexPreprocess( char * pStr ) +{ + char * pCopy = ABC_CALLOC( char, strlen(pStr) * 2 + 10 ); + int i, k = 0; + pCopy[k++] = '('; + pCopy[k++] = '('; + for ( i = 0; pStr[i]; i++ ) + { + if ( pStr[i] == '(' ) + pCopy[k++] = '('; + else if ( pStr[i] == ')' ) + pCopy[k++] = ')'; + if ( pStr[i] != ' ' && pStr[i] != '\t' && pStr[i] != '\n' && pStr[i] != '\r' ) + pCopy[k++] = pStr[i]; + } + pCopy[k++] = ')'; + pCopy[k++] = ')'; + pCopy[k++] = '\0'; + return pCopy; +} +// construct sequential AIG for the automaton +Gia_Man_t * Gia_ManRex2Gia( char * pStrInit, int fOrder, int fVerbose ) +{ + Gia_Man_t * pNew = NULL, * pTemp; + Vec_Int_t * vAlphas, * vStr2Sta, * vStaLits; + Vec_Int_t * vStaTrans, * vStack, * vVisited; + Vec_Str_t * vInit; + char * pStr = Gia_ManRexPreprocess( pStrInit ); + int nStates = Gia_ManRexNumInputs( pStr, &vAlphas, &vStr2Sta ); + int i, k, iLit, Entry, nLength = strlen(pStr), nTravId = 1; + if ( fOrder ) + Vec_IntSort( vAlphas, 0 ); +// if ( fVerbose ) + { + printf( "Input variable order: " ); + Vec_IntForEachEntry( vAlphas, Entry, k ) + printf( "%c", (char)Entry ); + printf( "\n" ); + } + // start AIG + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( pStrInit ); + for ( i = 0; i < Vec_IntSize(vAlphas) + nStates; i++ ) + Gia_ManAppendCi( pNew ); + // prepare automaton + vStaLits = Vec_IntStart( nStates + 1 ); + vStaTrans = Vec_IntStartFull( nLength ); + vStack = Vec_IntAlloc( nLength ); + vVisited = Vec_IntStartFull( nLength + 1 ); + for ( i = 0; i < nLength; i++ ) + { + int Lp = i; + if ( pStr[i] == '(' || pStr[i] == '|' ) + Vec_IntPush( vStack, i ); + else if ( pStr[i] == ')' ) + { + int Or = Vec_IntPop( vStack ); + if ( pStr[Or] == '|' ) + { + Lp = Vec_IntPop( vStack ); + Vec_IntWriteEntry( vStaTrans, Lp, Or + 1 ); + Vec_IntWriteEntry( vStaTrans, Or, i ); + } + else + Lp = Or; + } + if ( i < nLength - 1 && pStr[i+1] == '*' ) + { + Vec_IntWriteEntry( vStaTrans, Lp, i+1 ); + Vec_IntWriteEntry( vStaTrans, i+1, Lp ); + } + } + assert( Vec_IntSize(vStack) == 0 ); + if ( fVerbose ) + Gia_ManPrintAutom( pStr, vStaTrans ); + + // create next-state functions for each state + Gia_ManHashAlloc( pNew ); + for ( i = 1; i < nLength; i++ ) + { + int iThis, iThat, iThisLit, iInputLit; + if ( Gia_SymbSpecial(pStr[i]) ) + continue; + Gia_ManCollectReached( pStr, vStaTrans, i, vStack, vVisited, nTravId++ ); + if ( fVerbose ) + Gia_ManPrintReached( pStr, i, vStack ); + // create transitions from this state under this input + iThis = Vec_IntEntry(vStr2Sta, i); + iThisLit = Gia_Obj2Lit(pNew, Gia_ManPi(pNew, Vec_IntSize(vAlphas) + iThis)); + iInputLit = Gia_Obj2Lit(pNew, Gia_ManPi(pNew, Vec_IntFind(vAlphas, pStr[i]))); + iLit = Gia_ManHashAnd( pNew, iThisLit, iInputLit ); + Vec_IntForEachEntry( vStack, Entry, k ) + { + iThat = Vec_IntEntry(vStr2Sta, Entry); + iLit = Gia_ManHashOr( pNew, iLit, Vec_IntEntry(vStaLits, iThat) ); + Vec_IntWriteEntry( vStaLits, iThat, iLit ); + } + } + // create one-hotness + Vec_IntClear( vStack ); + for ( i = 0; i < Vec_IntSize(vAlphas); i++ ) + Vec_IntPush( vStack, Gia_Obj2Lit(pNew, Gia_ManPi(pNew, i)) ); + iLit = Gia_ManBuild1Hot( pNew, vStack ); + // combine with outputs + Vec_IntForEachEntry( vStaLits, Entry, k ) + Vec_IntWriteEntry( vStaLits, k, Gia_ManHashAnd(pNew, iLit, Entry) ); + Gia_ManHashStop( pNew ); + + // collect initial state + Gia_ManCollectReached( pStr, vStaTrans, 0, vStack, vVisited, nTravId++ ); + if ( fVerbose ) + Gia_ManPrintReached( pStr, 0, vStack ); + vInit = Vec_StrStart( nStates + 1 ); + Vec_StrFill( vInit, nStates, '0' ); + Vec_IntForEachEntry( vStack, Entry, k ) + if ( pStr[Entry] != '\0' ) + Vec_StrWriteEntry( vInit, Vec_IntEntry(vStr2Sta, Entry), '1' ); + if ( fVerbose ) + printf( "Init state = %s\n", Vec_StrArray(vInit) ); + + // add outputs + Vec_IntPushFirst( vStaLits, Vec_IntPop(vStaLits) ); + assert( Vec_IntSize(vStaLits) == nStates + 1 ); + Vec_IntForEachEntry( vStaLits, iLit, i ) + Gia_ManAppendCo( pNew, iLit ); + Gia_ManSetRegNum( pNew, nStates ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + + // add initial state + pNew = Gia_ManDupZeroUndc( pTemp = pNew, Vec_StrArray(vInit), 0, 0, 0 ); + Gia_ManStop( pTemp ); + Vec_StrFree( vInit ); +/* + Gia_ManAutomSimulate( pNew, vAlphas, "0" ); + Gia_ManAutomSimulate( pNew, vAlphas, "01" ); + Gia_ManAutomSimulate( pNew, vAlphas, "110" ); + Gia_ManAutomSimulate( pNew, vAlphas, "011" ); + Gia_ManAutomSimulate( pNew, vAlphas, "111" ); + Gia_ManAutomSimulate( pNew, vAlphas, "1111" ); + Gia_ManAutomSimulate( pNew, vAlphas, "1010" ); + + Gia_ManAutomSimulate( pNew, vAlphas, "A" ); + Gia_ManAutomSimulate( pNew, vAlphas, "AD" ); + Gia_ManAutomSimulate( pNew, vAlphas, "ABCD" ); + Gia_ManAutomSimulate( pNew, vAlphas, "BCD" ); + Gia_ManAutomSimulate( pNew, vAlphas, "CD" ); +*/ + + // cleanup + Vec_IntFree( vAlphas ); + Vec_IntFree( vStr2Sta ); + Vec_IntFree( vStaLits ); + Vec_IntFree( vStaTrans ); + Vec_IntFree( vStack ); + Vec_IntFree( vVisited ); + ABC_FREE( pStr ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Transposing 64-bit matrix.] + + Description [Borrowed from "Hacker's Delight", by Henry Warren.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManAutomTranspose64( word A[64] ) +{ + int j, k; + word t, m = 0x00000000FFFFFFFF; + for ( j = 32; j != 0; j = j >> 1, m = m ^ (m << j) ) + { + for ( k = 0; k < 64; k = (k + j + 1) & ~j ) + { + t = (A[k] ^ (A[k+j] >> j)) & m; + A[k] = A[k] ^ t; + A[k+j] = A[k+j] ^ (t << j); + } + } +} + +/**Function************************************************************* + + Synopsis [Simulate AIG with the given sequence.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline word Gia_ManAutomSim0( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Wrd_t * vTemp ) +{ + return Gia_ObjFaninC0(pObj) ? ~Vec_WrdEntry(vTemp, Gia_ObjFaninId0p(p, pObj)) : Vec_WrdEntry(vTemp, Gia_ObjFaninId0p(p, pObj)); +} +static inline word Gia_ManAutomSim1( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Wrd_t * vTemp ) +{ + return Gia_ObjFaninC1(pObj) ? ~Vec_WrdEntry(vTemp, Gia_ObjFaninId1p(p, pObj)) : Vec_WrdEntry(vTemp, Gia_ObjFaninId1p(p, pObj)); +} +word Gia_ManAutomStep( Gia_Man_t * p, word Cur, word * pNext, Vec_Wrd_t * vTemp ) +{ + Gia_Obj_t * pObj; int i; + assert( Gia_ManPoNum(p) == 1 ); + assert( Vec_WrdSize(vTemp) >= Gia_ManObjNum(p) ); + Vec_WrdWriteEntry( vTemp, 0, 0 ); + Gia_ManForEachPi( p, pObj, i ) + Vec_WrdWriteEntry( vTemp, Gia_ObjId(p, pObj), ((word)1) << (63-i) ); + Gia_ManForEachRo( p, pObj, i ) + Vec_WrdWriteEntry( vTemp, Gia_ObjId(p, pObj), ((Cur >> (63-i)) & 1) ? ~((word)0) : 0 ); + Gia_ManForEachAnd( p, pObj, i ) + Vec_WrdWriteEntry( vTemp, i, Gia_ManAutomSim0(p, pObj, vTemp) & Gia_ManAutomSim1(p, pObj, vTemp) ); + Gia_ManForEachRi( p, pObj, i ) + pNext[i] = Gia_ManAutomSim0(p, pObj, vTemp); + for ( ; i < 64; i++ ) + pNext[i] = 0; + // transpose +// for ( i = 0; i < 64; i++ ) +// Extra_PrintBinary( stdout, (unsigned *)&pNext[i], 64 ), Abc_Print( 1, "\n" ); +// printf( "\n" ); + Gia_ManAutomTranspose64( pNext ); +// for ( i = 0; i < 64; i++ ) +// Extra_PrintBinary( stdout, (unsigned *)&pNext[i], 64 ), Abc_Print( 1, "\n" ); +// printf( "\n" ); + // return output values + return Gia_ManAutomSim0(p, Gia_ManPo(p, 0), vTemp); +} +void Gia_ManAutomWalkOne( Gia_Man_t * p, int nSteps, Vec_Wrd_t * vStates, Vec_Int_t * vCounts, Vec_Wrd_t * vTemp, word Init ) +{ + word iState = 0, Output, pNext[64]; + int i, k, kMin, Index, IndexMin; + int Count, CountMin; + for ( i = 0; i < nSteps; i++ ) + { + Output = Gia_ManAutomStep( p, iState, pNext, vTemp ); + // check visited states + kMin = -1; + IndexMin = -1; + CountMin = ABC_INFINITY; + for ( k = 0; k < Gia_ManPiNum(p); k++ ) + { + if ( pNext[k] == Init ) + continue; + Index = Vec_WrdFind( vStates, pNext[k] ); + Count = Index == -1 ? 0 : Vec_IntEntry( vCounts, Index ); + if ( CountMin > Count || (CountMin != ABC_INFINITY && Count && ((float)CountMin / Count) > (float)rand()/RAND_MAX ) ) + { + CountMin = Count; + IndexMin = Index; + kMin = k; + } + if ( CountMin == 0 ) + break; + } + // choose the best state + if ( CountMin == ABC_INFINITY ) + { + for ( k = 0; k < Gia_ManPiNum(p); k++ ) + if ( (Output >> (63-k)) & 1 ) + { + printf( "%c", 'a' + k ); + printf( "!" ); + } + break; + } + assert( CountMin < ABC_INFINITY ); + if ( IndexMin == -1 ) + { + assert( CountMin == 0 ); + IndexMin = Vec_IntSize(vCounts); + Vec_IntPush( vCounts, 0 ); + Vec_WrdPush( vStates, pNext[kMin] ); + } + Vec_IntAddToEntry( vCounts, IndexMin, 1 ); + iState = pNext[kMin]; +//Extra_PrintBinary( stdout, (unsigned *)&iState, 64 ); printf( "\n" ); + // print the transition + printf( "%c", 'a' + kMin ); + if ( (Output >> (63-kMin)) & 1 ) + printf( "!" ); + } + printf( "\n" ); +} +// find flop variables pointed to by negative edges +word Gia_ManAutomInit( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, Index; + word Init = 0; + Gia_ManForEachAnd( p, pObj, i ) + { + if ( Gia_ObjFaninC0(pObj) && Gia_ObjIsCi(Gia_ObjFanin0(pObj)) ) + { + Index = Gia_ObjCioId(Gia_ObjFanin0(pObj)) - Gia_ManPiNum(p); + if ( Index >= 0 ) + Init |= ((word)1 << (63-Index)); + } + if ( Gia_ObjFaninC1(pObj) && Gia_ObjIsCi(Gia_ObjFanin1(pObj)) ) + { + Index = Gia_ObjCioId(Gia_ObjFanin1(pObj)) - Gia_ManPiNum(p); + if ( Index >= 0 ) + Init |= ((word)1 << (63-Index)); + } + } + return Init; +} +void Gia_ManAutomWalk( Gia_Man_t * p, int nSteps, int nWalks, int fVerbose ) +{ + Vec_Wrd_t * vTemp, * vStates; + Vec_Int_t * vCounts; int i; word Init; + if ( Gia_ManPoNum(p) != 1 ) + { + printf( "AIG should have one primary output.\n" ); + return; + } + if ( Gia_ManPiNum(p) > 64 ) + { + printf( "Cannot simulate an automaton with more than 64 inputs.\n" ); + return; + } + if ( Gia_ManRegNum(p) > 64 ) + { + printf( "Cannot simulate an automaton with more than 63 states.\n" ); + return; + } + vTemp = Vec_WrdStart( Gia_ManObjNum(p) ); + vStates = Vec_WrdAlloc( 1000 ); + vCounts = Vec_IntAlloc( 1000 ); + Vec_WrdPush( vStates, 0 ); + Vec_IntPush( vCounts, 1 ); + Init = Gia_ManAutomInit( p ); + for ( i = 0; i < nWalks; i++ ) + Gia_ManAutomWalkOne( p, nSteps, vStates, vCounts, vTemp, Init ); + if ( fVerbose ) + { + word State; + Vec_WrdForEachEntry( vStates, State, i ) + { + State ^= Init; + printf( "%3d : ", i ); + Extra_PrintBinary( stdout, (unsigned *)&State, 64 ); + printf( " %d ", Vec_IntEntry(vCounts, i) ); + printf( "\n" ); + } + printf( "\n" ); + } + Vec_WrdFree( vTemp ); + Vec_WrdFree( vStates ); + Vec_IntFree( vCounts ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaRrr.cpp b/yosys/abc/src/aig/gia/giaRrr.cpp new file mode 100644 index 00000000000..1eccd4dc233 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaRrr.cpp @@ -0,0 +1,42 @@ +#include "aig/gia/gia.h" + +#include "opt/rrr/rrr.h" +#include "opt/rrr/rrrAbc.h" + +ABC_NAMESPACE_IMPL_START + +Gia_Man_t *Gia_ManRrr(Gia_Man_t *pGia, int iSeed, int nWords, int nTimeout, int nSchedulerVerbose, int nPartitionerVerbose, int nOptimizerVerbose, int nAnalyzerVerbose, int nSimulatorVerbose, int nSatSolverVerbose, int fUseBddCspf, int fUseBddMspf, int nConflictLimit, int nSortType, int nOptimizerFlow, int nSchedulerFlow, int nPartitionType, int nDistance, int nJobs, int nThreads, int nPartitionSize, int nPartitionSizeMin, int fDeterministic, int nParallelPartitions, int fOptOnInsert, int fGreedy) { + rrr::AndNetwork ntk; + ntk.Read(pGia, rrr::GiaReader); + rrr::Parameter Par; + Par.iSeed = iSeed; + Par.nWords = nWords; + Par.nTimeout = nTimeout; + Par.nSchedulerVerbose = nSchedulerVerbose; + Par.nPartitionerVerbose = nPartitionerVerbose; + Par.nOptimizerVerbose = nOptimizerVerbose; + Par.nAnalyzerVerbose = nAnalyzerVerbose; + Par.nSimulatorVerbose = nSimulatorVerbose; + Par.nSatSolverVerbose = nSatSolverVerbose; + Par.fUseBddCspf = fUseBddCspf; + Par.fUseBddMspf = fUseBddMspf; + Par.nConflictLimit = nConflictLimit; + Par.nSortType = nSortType; + Par.nOptimizerFlow = nOptimizerFlow; + Par.nSchedulerFlow = nSchedulerFlow; + Par.nPartitionType = nPartitionType; + Par.nDistance = nDistance; + Par.nJobs = nJobs; + Par.nThreads = nThreads; + Par.nPartitionSize = nPartitionSize; + Par.nPartitionSizeMin = nPartitionSizeMin; + Par.fDeterministic = fDeterministic; + Par.nParallelPartitions = nParallelPartitions; + Par.fOptOnInsert = fOptOnInsert; + Par.fGreedy = fGreedy; + rrr::Perform(&ntk, &Par); + Gia_Man_t *pNew = rrr::CreateGia(&ntk); + return pNew; +} + +ABC_NAMESPACE_IMPL_END diff --git a/yosys/abc/src/aig/gia/giaSat.c b/yosys/abc/src/aig/gia/giaSat.c new file mode 100644 index 00000000000..9bea8ef7f96 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaSat.c @@ -0,0 +1,427 @@ +/**CFile**************************************************************** + + FileName [giaSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [New constraint-propagation procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define GIA_LIMIT 10 + + +typedef struct Gia_ManSat_t_ Gia_ManSat_t; +struct Gia_ManSat_t_ +{ + Aig_MmFlex_t * pMem; +}; + +typedef struct Gia_ObjSat1_t_ Gia_ObjSat1_t; +struct Gia_ObjSat1_t_ +{ + char nFans; + char nOffset; + char PathsH; + char PathsV; +}; + +typedef struct Gia_ObjSat2_t_ Gia_ObjSat2_t; +struct Gia_ObjSat2_t_ +{ + unsigned fTerm : 1; + unsigned iLit : 31; +}; + +typedef struct Gia_ObjSat_t_ Gia_ObjSat_t; +struct Gia_ObjSat_t_ +{ + union { + Gia_ObjSat1_t Obj1; + Gia_ObjSat2_t Obj2; + }; +}; + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_ManSat_t * Gia_ManSatStart() +{ + Gia_ManSat_t * p; + p = ABC_CALLOC( Gia_ManSat_t, 1 ); + p->pMem = Aig_MmFlexStart(); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSatStop( Gia_ManSat_t * p ) +{ + Aig_MmFlexStop( p->pMem, 0 ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [Collects the supergate rooted at this ] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSatPartCollectSuper( Gia_Man_t * p, Gia_Obj_t * pObj, int * pLits, int * pnLits ) +{ + Gia_Obj_t * pFanin; + assert( Gia_ObjIsAnd(pObj) ); + assert( pObj->fMark0 == 0 ); + pFanin = Gia_ObjFanin0(pObj); + if ( pFanin->fMark0 || Gia_ObjFaninC0(pObj) ) + pLits[(*pnLits)++] = Gia_Var2Lit(Gia_ObjId(p, pFanin), Gia_ObjFaninC0(pObj)); + else + Gia_ManSatPartCollectSuper(p, pFanin, pLits, pnLits); + pFanin = Gia_ObjFanin1(pObj); + if ( pFanin->fMark0 || Gia_ObjFaninC1(pObj) ) + pLits[(*pnLits)++] = Gia_Var2Lit(Gia_ObjId(p, pFanin), Gia_ObjFaninC1(pObj)); + else + Gia_ManSatPartCollectSuper(p, pFanin, pLits, pnLits); +} + +/**Function************************************************************* + + Synopsis [Returns the number of words used.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSatPartCreate_rec( Gia_Man_t * p, Gia_Obj_t * pObj, int * pObjPlace, int * pStore ) +{ + Gia_Obj_t * pFanin; + int i, nWordsUsed, nSuperSize = 0, Super[2*GIA_LIMIT]; + // make sure this is a valid node + assert( Gia_ObjIsAnd(pObj) ); + assert( pObj->fMark0 == 0 ); + // collect inputs to the supergate + Gia_ManSatPartCollectSuper( p, pObj, Super, &nSuperSize ); + assert( nSuperSize <= 2*GIA_LIMIT ); + // create the root entry + *pObjPlace = 0; + ((Gia_ObjSat1_t *)pObjPlace)->nFans = Gia_Var2Lit( nSuperSize, 0 ); + ((Gia_ObjSat1_t *)pObjPlace)->nOffset = pStore - pObjPlace; + nWordsUsed = nSuperSize; + for ( i = 0; i < nSuperSize; i++ ) + { + pFanin = Gia_ManObj( p, Gia_Lit2Var(Super[i]) ); + if ( pFanin->fMark0 ) + { + ((Gia_ObjSat2_t *)(pStore + i))->fTerm = 1; + ((Gia_ObjSat2_t *)(pStore + i))->iLit = Super[i]; + } + else + { + assert( Gia_LitIsCompl(Super[i]) ); + nWordsUsed += Gia_ManSatPartCreate_rec( p, pFanin, pStore + i, pStore + nWordsUsed ); + } + } + return nWordsUsed; +} + +/**Function************************************************************* + + Synopsis [Creates part and returns the number of words used.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSatPartCreate( Gia_Man_t * p, Gia_Obj_t * pObj, int * pStore ) +{ + return 1 + Gia_ManSatPartCreate_rec( p, pObj, pStore, pStore + 1 ); +} + + +/**Function************************************************************* + + Synopsis [Count the number of internal nodes in the leaf-DAG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSatPartCountClauses( Gia_Man_t * p, Gia_Obj_t * pObj, int * pnOnset, int * pnOffset ) +{ + Gia_Obj_t * pFanin; + int nOnset0, nOnset1, nOffset0, nOffset1; + assert( Gia_ObjIsAnd(pObj) ); + pFanin = Gia_ObjFanin0(pObj); + if ( pFanin->fMark0 ) + nOnset0 = 1, nOffset0 = 1; + else + { + Gia_ManSatPartCountClauses(p, pFanin, &nOnset0, &nOffset0); + if ( Gia_ObjFaninC0(pObj) ) + { + int Temp = nOnset0; + nOnset0 = nOffset0; + nOffset0 = Temp; + } + } + pFanin = Gia_ObjFanin1(pObj); + if ( pFanin->fMark0 ) + nOnset1 = 1, nOffset1 = 1; + else + { + Gia_ManSatPartCountClauses(p, pFanin, &nOnset1, &nOffset1); + if ( Gia_ObjFaninC1(pObj) ) + { + int Temp = nOnset1; + nOnset1 = nOffset1; + nOffset1 = Temp; + } + } + *pnOnset = nOnset0 * nOnset1; + *pnOffset = nOffset0 + nOffset1; +} + +/**Function************************************************************* + + Synopsis [Count the number of internal nodes in the leaf-DAG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSatPartCount( Gia_Man_t * p, Gia_Obj_t * pObj, int * pnLeaves, int * pnNodes ) +{ + Gia_Obj_t * pFanin; + int Level0 = 0, Level1 = 0; + assert( Gia_ObjIsAnd(pObj) ); + assert( pObj->fMark0 == 0 ); + (*pnNodes)++; + pFanin = Gia_ObjFanin0(pObj); + if ( pFanin->fMark0 ) + (*pnLeaves)++; + else + Level0 = Gia_ManSatPartCount(p, pFanin, pnLeaves, pnNodes) + Gia_ObjFaninC0(pObj); + pFanin = Gia_ObjFanin1(pObj); + if ( pFanin->fMark0 ) + (*pnLeaves)++; + else + Level1 = Gia_ManSatPartCount(p, pFanin, pnLeaves, pnNodes) + Gia_ObjFaninC1(pObj); + return Abc_MaxInt( Level0, Level1 ); +} + +/**Function************************************************************* + + Synopsis [Count the number of internal nodes in the leaf-DAG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSatPartCountNodes( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + Gia_Obj_t * pFanin; + int nNodes0 = 0, nNodes1 = 0; + assert( Gia_ObjIsAnd(pObj) ); + assert( pObj->fMark0 == 0 ); + pFanin = Gia_ObjFanin0(pObj); + if ( !(pFanin->fMark0) ) + nNodes0 = Gia_ManSatPartCountNodes(p, pFanin); + pFanin = Gia_ObjFanin1(pObj); + if ( !(pFanin->fMark0) ) + nNodes1 = Gia_ManSatPartCountNodes(p, pFanin); + return nNodes0 + nNodes1 + 1; +} + +/**Function************************************************************* + + Synopsis [Count the number of internal nodes in the leaf-DAG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSatPartPrint( Gia_Man_t * p, Gia_Obj_t * pObj, int Step ) +{ + Gia_Obj_t * pFanin; + assert( Gia_ObjIsAnd(pObj) ); + assert( pObj->fMark0 == 0 ); + pFanin = Gia_ObjFanin0(pObj); + if ( pFanin->fMark0 ) + printf( "%s%d", Gia_ObjFaninC0(pObj)?"!":"", Gia_ObjId(p,pFanin) ); + else + { + if ( Gia_ObjFaninC0(pObj) ) + printf( "(" ); + Gia_ManSatPartPrint(p, pFanin, Step + Gia_ObjFaninC0(pObj)); + if ( Gia_ObjFaninC0(pObj) ) + printf( ")" ); + } + printf( "%s", (Step & 1)? " + " : "*" ); + pFanin = Gia_ObjFanin1(pObj); + if ( pFanin->fMark0 ) + printf( "%s%d", Gia_ObjFaninC1(pObj)?"!":"", Gia_ObjId(p,pFanin) ); + else + { + if ( Gia_ObjFaninC1(pObj) ) + printf( "(" ); + Gia_ManSatPartPrint(p, pFanin, Step + Gia_ObjFaninC1(pObj)); + if ( Gia_ObjFaninC1(pObj) ) + printf( ")" ); + } +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSatExperiment( Gia_Man_t * p ) +{ + int nStored, Storage[1000], * pStart; + Gia_ManSat_t * pMan; + Gia_Obj_t * pObj; + int i, nLevels, nLeaves, nNodes, nCount[2*GIA_LIMIT+2] = {0}, nCountAll = 0; + int Num0 = 0, Num1 = 0; + clock_t clk = clock(); + int nWords = 0, nWords2 = 0; + pMan = Gia_ManSatStart(); + // mark the nodes to become roots of leaf-DAGs + Gia_ManCreateValueRefs( p ); + Gia_ManForEachObj( p, pObj, i ) + { + pObj->fMark0 = 0; + if ( Gia_ObjIsCo(pObj) ) + Gia_ObjFanin0(pObj)->fMark0 = 1; + else if ( Gia_ObjIsCi(pObj) ) + pObj->fMark0 = 1; + else if ( Gia_ObjIsAnd(pObj) ) + { + if ( pObj->Value > 1 || Gia_ManSatPartCountNodes(p,pObj) >= GIA_LIMIT ) + pObj->fMark0 = 1; + } + pObj->Value = 0; + } + // compute the sizes of leaf-DAGs + Gia_ManForEachAnd( p, pObj, i ) + { + if ( pObj->fMark0 == 0 ) + continue; + pObj->fMark0 = 0; + + nCountAll++; + nStored = Gia_ManSatPartCreate( p, pObj, Storage ); + nWords2 += nStored; + assert( nStored < 500 ); + pStart = (int *)Aig_MmFlexEntryFetch( pMan->pMem, sizeof(int) * nStored ); + memcpy( pStart, Storage, sizeof(int) * nStored ); + + nLeaves = nNodes = 0; + nLevels = 1+Gia_ManSatPartCount( p, pObj, &nLeaves, &nNodes ); + nWords += nLeaves + nNodes; + if ( nNodes <= 2*GIA_LIMIT ) + nCount[nNodes]++; + else + nCount[2*GIA_LIMIT+1]++; +// if ( nNodes > 10 && i % 100 == 0 ) +// if ( nNodes > 5 ) + if ( 0 ) + { + Gia_ManSatPartCountClauses( p, pObj, &Num0, &Num1 ); + printf( "%8d : And = %3d. Lev = %2d. Clauses = %3d. (%3d + %3d).\n", i, nNodes, nLevels, Num0+Num1, Num0, Num1 ); + Gia_ManSatPartPrint( p, pObj, 0 ); + printf( "\n" ); + } + + pObj->fMark0 = 1; + } + printf( "\n" ); + Gia_ManForEachObj( p, pObj, i ) + pObj->fMark0 = 0; + Gia_ManSatStop( pMan ); + for ( i = 0; i < 2*GIA_LIMIT+2; i++ ) + printf( "%2d=%6d %7.2f %% %7.2f %%\n", i, nCount[i], 100.0*nCount[i]/nCountAll, 100.0*i*nCount[i]/Gia_ManAndNum(p) ); + ABC_PRMn( "MemoryEst", 4*nWords ); + ABC_PRMn( "MemoryReal", 4*nWords2 ); + printf( "%5.2f bpn ", 4.0*nWords2/Gia_ManObjNum(p) ); + ABC_PRT( "Time", clock() - clk ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaSat3.c b/yosys/abc/src/aig/gia/giaSat3.c new file mode 100644 index 00000000000..fe76b078d37 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaSat3.c @@ -0,0 +1,136 @@ +/**CFile**************************************************************** + + FileName [giaSatoko.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Interface to Satoko solver.] + + Author [Alan Mishchenko, Bruno Schmitt] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSatoko.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "sat/cnf/cnf.h" +#include "sat/bsat/satSolver3.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +sat_solver3 * Gia_ManSat3Init( Cnf_Dat_t * pCnf ) +{ + sat_solver3 * pSat = sat_solver3_new(); + int i; + //sat_solver_setnvars( pSat, p->nVars ); + for ( i = 0; i < pCnf->nClauses; i++ ) + { + if ( !sat_solver3_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) ) + { + sat_solver3_delete( pSat ); + return NULL; + } + } + return pSat; +} +void Gia_ManSat3Report( int iOutput, int status, abctime clk ) +{ + if ( iOutput >= 0 ) + Abc_Print( 1, "Output %6d : ", iOutput ); + else + Abc_Print( 1, "Total: " ); + + if ( status == l_Undef ) + Abc_Print( 1, "UNDECIDED " ); + else if ( status == l_True ) + Abc_Print( 1, "SATISFIABLE " ); + else + Abc_Print( 1, "UNSATISFIABLE " ); + + Abc_PrintTime( 1, "Time", clk ); +} +sat_solver3 * Gia_ManSat3Create( Gia_Man_t * p ) +{ + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( p, 8, 0, 1, 0, 0 ); + sat_solver3 * pSat = Gia_ManSat3Init( pCnf ); + int status = pSat ? sat_solver3_simplify(pSat) : 0; + Cnf_DataFree( pCnf ); + if ( status ) + return pSat; + if ( pSat ) + sat_solver3_delete( pSat ); + return NULL; +} +int Gia_ManSat3CallOne( Gia_Man_t * p, int iOutput ) +{ + abctime clk = Abc_Clock(); + sat_solver3 * pSat; + int status, Cost = 0; + + pSat = Gia_ManSat3Create( p ); + if ( pSat ) + { + status = sat_solver3_solve( pSat, NULL, NULL, 0, 0, 0, 0 ); + Cost = (unsigned)pSat->stats.conflicts; + sat_solver3_delete( pSat ); + } + else + status = l_False; + + Gia_ManSat3Report( iOutput, status, Abc_Clock() - clk ); + return Cost; +} +void Gia_ManSat3Call( Gia_Man_t * p, int fSplit ) +{ + Gia_Man_t * pOne; + Gia_Obj_t * pRoot; + int i; + if ( fSplit ) + { + abctime clk = Abc_Clock(); + Gia_ManForEachCo( p, pRoot, i ) + { + pOne = Gia_ManDupDfsCone( p, pRoot ); + Gia_ManSat3CallOne( pOne, i ); + Gia_ManStop( pOne ); + } + Abc_PrintTime( 1, "Total time", Abc_Clock() - clk ); + return; + } + Gia_ManSat3CallOne( p, -1 ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaSatEdge.c b/yosys/abc/src/aig/gia/giaSatEdge.c new file mode 100644 index 00000000000..45d5b158945 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaSatEdge.c @@ -0,0 +1,537 @@ +/**CFile**************************************************************** + + FileName [giaSatEdge.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSatEdge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/tim/tim.h" +#include "sat/bsat/satStore.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Seg_Man_t_ Seg_Man_t; +struct Seg_Man_t_ +{ + sat_solver * pSat; // SAT solver + //Vec_Int_t * vCardVars; // candinality variables + int nVars; // max vars (edge num) + int LogN; // base-2 log of max vars + int Power2; // power-2 of LogN + int FirstVar; // first variable to be used + // parameters + int nBTLimit; // conflicts + int DelayMax; // external delay + int nEdges; // the number of edges + int fDelay; // delay mode + int fReverse; // reverse windowing + int fVerbose; // verbose + // window + Gia_Man_t * pGia; + Vec_Int_t * vPolars; // polarity + Vec_Int_t * vToSkip; // edges to skip + Vec_Int_t * vEdges; // edges as fanin/fanout pairs + Vec_Int_t * vFirsts; // first SAT variable + Vec_Int_t * vNvars; // number of SAT variables + Vec_Int_t * vLits; // literals + int * pLevels; // levels + + // statistics + abctime timeStart; +}; + +extern sat_solver * Sbm_AddCardinSolver( int LogN, Vec_Int_t ** pvVars ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Count the number of edges between internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Seg_ManCountIntEdges( Gia_Man_t * p, Vec_Int_t * vPolars, Vec_Int_t * vToSkip, int nFanouts ) +{ + int i, iLut, iFanin; + Vec_Int_t * vEdges = Vec_IntAlloc( 1000 ); + assert( Gia_ManHasMapping(p) ); + Vec_IntClear( vPolars ); + Vec_IntClear( vToSkip ); + if ( nFanouts ) + Gia_ManSetLutRefs( p ); + Gia_ManForEachLut( p, iLut ) + Gia_LutForEachFanin( p, iLut, iFanin, i ) + if ( Gia_ObjIsAnd(Gia_ManObj(p, iFanin)) ) + { + if ( p->vEdge1 && Gia_ObjCheckEdge(p, iFanin, iLut) ) + Vec_IntPush( vPolars, Vec_IntSize(vEdges)/2 ); + if ( nFanouts && Gia_ObjLutRefNumId(p, iFanin) >= nFanouts ) + Vec_IntPush( vToSkip, Vec_IntSize(vEdges)/2 ); + Vec_IntPushTwo( vEdges, iFanin, iLut ); + } + if ( nFanouts ) + ABC_FREE( p->pLutRefs ); + return vEdges; +} +Vec_Wec_t * Seg_ManCollectObjEdges( Vec_Int_t * vEdges, int nObjs ) +{ + int iFanin, iObj, i; + Vec_Wec_t * vRes = Vec_WecStart( nObjs ); + Vec_IntForEachEntryDouble( vEdges, iFanin, iObj, i ) + { + Vec_WecPush( vRes, iFanin, i/2 ); + Vec_WecPush( vRes, iObj, i/2 ); + } + return vRes; +} +int Seg_ManCountIntLevels( Seg_Man_t * p, int iStartVar ) +{ + Gia_Obj_t * pObj; + int iLut, nVars; + Vec_IntFill( p->vFirsts, Gia_ManObjNum(p->pGia), -1 ); + Vec_IntFill( p->vNvars, Gia_ManObjNum(p->pGia), 0 ); + ABC_FREE( p->pLevels ); + if ( p->pGia->pManTime ) + { + p->DelayMax = Gia_ManLutLevelWithBoxes( p->pGia ); + p->pLevels = Vec_IntReleaseArray( p->pGia->vLevels ); + Vec_IntFreeP( &p->pGia->vLevels ); + } + else + p->DelayMax = Gia_ManLutLevel( p->pGia, &p->pLevels ); + Gia_ManForEachObj1( p->pGia, pObj, iLut ) + { + if ( Gia_ObjIsCo(pObj) ) + continue; + if ( Gia_ObjIsAnd(pObj) && !Gia_ObjIsLut(p->pGia, iLut) ) + continue; + assert( Gia_ObjIsCi(pObj) || Gia_ObjIsLut(p->pGia, iLut) ); + Vec_IntWriteEntry( p->vFirsts, iLut, iStartVar ); + //assert( p->pLevels[iLut] > 0 ); + nVars = p->pLevels[iLut] < 2 ? 0 : p->pLevels[iLut]; + Vec_IntWriteEntry( p->vNvars, iLut, nVars ); + iStartVar += nVars; + } + return iStartVar; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Seg_Man_t * Seg_ManAlloc( Gia_Man_t * pGia, int nFanouts ) +{ + int nVarsAll; + Seg_Man_t * p = ABC_CALLOC( Seg_Man_t, 1 ); + p->vPolars = Vec_IntAlloc( 1000 ); + p->vToSkip = Vec_IntAlloc( 1000 ); + p->vEdges = Seg_ManCountIntEdges( pGia, p->vPolars, p->vToSkip, nFanouts ); + p->nVars = Vec_IntSize(p->vEdges)/2; + p->LogN = Abc_Base2Log(p->nVars); + p->Power2 = 1 << p->LogN; + //p->pSat = Sbm_AddCardinSolver( p->LogN, &p->vCardVars ); + p->pSat = sat_solver_new(); + sat_solver_setnvars( p->pSat, p->nVars ); + p->FirstVar = sat_solver_nvars( p->pSat ); + sat_solver_bookmark( p->pSat ); + p->pGia = pGia; + // internal + p->vFirsts = Vec_IntAlloc( 0 ); + p->vNvars = Vec_IntAlloc( 0 ); + p->vLits = Vec_IntAlloc( 0 ); + nVarsAll = Seg_ManCountIntLevels( p, p->FirstVar ); + sat_solver_setnvars( p->pSat, nVarsAll ); + // other + Gia_ManFillValue( pGia ); + return p; +} +void Seg_ManClean( Seg_Man_t * p ) +{ + p->timeStart = Abc_Clock(); + sat_solver_rollback( p->pSat ); + sat_solver_bookmark( p->pSat ); + // internal + Vec_IntClear( p->vEdges ); + Vec_IntClear( p->vFirsts ); + Vec_IntClear( p->vNvars ); + Vec_IntClear( p->vLits ); + Vec_IntClear( p->vPolars ); + Vec_IntClear( p->vToSkip ); + // other + Gia_ManFillValue( p->pGia ); +} +void Seg_ManStop( Seg_Man_t * p ) +{ + sat_solver_delete( p->pSat ); + //Vec_IntFree( p->vCardVars ); + // internal + Vec_IntFree( p->vEdges ); + Vec_IntFree( p->vFirsts ); + Vec_IntFree( p->vNvars ); + Vec_IntFree( p->vLits ); + Vec_IntFree( p->vPolars ); + Vec_IntFree( p->vToSkip ); + ABC_FREE( p->pLevels ); + // other + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Seg_ManCreateCnf( Seg_Man_t * p, int fTwo, int fVerbose ) +{ + Tim_Man_t * pTim = (Tim_Man_t *)p->pGia->pManTime; + Gia_Obj_t * pObj; + Vec_Wec_t * vObjEdges; + Vec_Int_t * vLevel; + int iLut, iFanin, iFirst; + int pLits[3], Count = 0; + int i, k, nVars, Edge, value; + abctime clk = Abc_Clock(); + // edge delay constraints + int nConstr = sat_solver_nclauses(p->pSat); + Gia_ManForEachObj( p->pGia, pObj, iLut ) + { + int iFirstLut = Vec_IntEntry( p->vFirsts, iLut ); + int nVarsLut = Vec_IntEntry( p->vNvars, iLut ); + if ( pTim && Gia_ObjIsCi(pObj) ) + { + int iBox = Tim_ManBoxForCi( pTim, Gia_ObjCioId(pObj) ); + if ( nVarsLut > 0 && iBox >= 0 ) + { + int iCiId = Tim_ManBoxOutputFirst( pTim, iBox ); + if ( iCiId == Gia_ObjCioId(pObj) ) // first input + { + int nIns = Tim_ManBoxInputNum( pTim, iBox ); + int iIn0 = Tim_ManBoxInputFirst( pTim, iBox ); + for ( i = 0; i < nIns-1; i++ ) // skip carry-in pin + { + Gia_Obj_t * pOut = Gia_ManCo( p->pGia, iIn0+i ); + int iDriverId = Gia_ObjFaninId0p( p->pGia, pOut ); + int AddOn; + + iFirst = Vec_IntEntry( p->vFirsts, iDriverId ); + nVars = Vec_IntEntry( p->vNvars, iDriverId ); + assert( nVars < nVarsLut ); + AddOn = (int)(nVars < nVarsLut); + for ( k = 0; k < nVars; k++ ) + { + pLits[0] = Abc_Var2Lit( iFirst+k, 1 ); + pLits[1] = Abc_Var2Lit( iFirstLut+k+AddOn, 0 ); + value = sat_solver_addclause( p->pSat, pLits, pLits+2 ); + assert( value ); + } + } + } + else // intermediate input + { + Gia_Obj_t * pIn = Gia_ManCi( p->pGia, iCiId ); + int iObjId = Gia_ObjId( p->pGia, pIn ); + + iFirst = Vec_IntEntry( p->vFirsts, iObjId ); + nVars = Vec_IntEntry( p->vNvars, iObjId ); + if ( nVars > 0 ) + { + for ( k = 0; k < nVars; k++ ) + { + pLits[0] = Abc_Var2Lit( iFirst+k, 1 ); + pLits[1] = Abc_Var2Lit( iFirstLut+k, 0 ); + value = sat_solver_addclause( p->pSat, pLits, pLits+2 ); + assert( value ); + } + } + } + } + continue; + } + if ( !Gia_ObjIsLut(p->pGia, iLut) ) + continue; + Gia_LutForEachFanin( p->pGia, iLut, iFanin, i ) + if ( pTim && Gia_ObjIsCi(Gia_ManObj(p->pGia, iFanin)) ) + { + iFirst = Vec_IntEntry( p->vFirsts, iFanin ); + nVars = Vec_IntEntry( p->vNvars, iFanin ); + assert( nVars <= nVarsLut ); + if ( nVars > 0 ) + { + for ( k = 0; k < nVars; k++ ) + { + pLits[0] = Abc_Var2Lit( iFirst+k, 1 ); + pLits[1] = Abc_Var2Lit( iFirstLut+k, 0 ); + value = sat_solver_addclause( p->pSat, pLits, pLits+2 ); + assert( value ); + } + } + } + else if ( Gia_ObjIsAnd(Gia_ManObj(p->pGia, iFanin)) ) + { + iFirst = Vec_IntEntry( p->vFirsts, iFanin ); + nVars = Vec_IntEntry( p->vNvars, iFanin ); + assert( nVars != 1 && nVars < nVarsLut ); + // add initial + if ( nVars == 0 ) + { + pLits[0] = Abc_Var2Lit( Count, 1 ); + pLits[1] = Abc_Var2Lit( iFirstLut, 0 ); + value = sat_solver_addclause( p->pSat, pLits, pLits+2 ); + assert( value ); + + pLits[0] = Abc_Var2Lit( Count, 0 ); + pLits[1] = Abc_Var2Lit( iFirstLut+1, 0 ); + value = sat_solver_addclause( p->pSat, pLits, pLits+2 ); + assert( value ); + } + // add others + for ( k = 0; k < nVars; k++ ) + { + pLits[0] = Abc_Var2Lit( iFirst+k, 1 ); + pLits[1] = Abc_Var2Lit( Count, 1 ); + pLits[2] = Abc_Var2Lit( iFirstLut+k, 0 ); + value = sat_solver_addclause( p->pSat, pLits, pLits+3 ); + assert( value ); + + pLits[0] = Abc_Var2Lit( iFirst+k, 1 ); + pLits[1] = Abc_Var2Lit( Count, 0 ); + pLits[2] = Abc_Var2Lit( iFirstLut+k+1, 0 ); + value = sat_solver_addclause( p->pSat, pLits, pLits+3 ); + assert( value ); + } + Count++; + } + } + assert( Count == p->nVars ); + if ( fVerbose ) + printf( "Delay constraints = %d. ", sat_solver_nclauses(p->pSat) - nConstr ); + nConstr = sat_solver_nclauses(p->pSat); +/* + // delay relationship constraints + Vec_IntForEachEntryTwo( p->vFirsts, p->vNvars, iFirst, nVars, iLut ) + { + if ( nVars < 2 ) + continue; + for ( i = 1; i < nVars; i++ ) + { + pLits[0] = Abc_Var2Lit( iFirst + i - 1, 1 ); + pLits[1] = Abc_Var2Lit( iFirst + i, 0 ); + value = sat_solver_addclause( p->pSat, pLits, pLits+2 ); + assert( value ); + } + } +*/ + // edge compatibility constraint + vObjEdges = Seg_ManCollectObjEdges( p->vEdges, Gia_ManObjNum(p->pGia) ); + Vec_WecForEachLevel( vObjEdges, vLevel, i ) + { + int v1, v2, v3, Var1, Var2, Var3; + if ( (!fTwo && Vec_IntSize(vLevel) >= 2) || (fTwo && Vec_IntSize(vLevel) > 10) ) + { + Vec_IntForEachEntry( vLevel, Var1, v1 ) + Vec_IntForEachEntryStart( vLevel, Var2, v2, v1 + 1 ) + { + pLits[0] = Abc_Var2Lit( Var1, 1 ); + pLits[1] = Abc_Var2Lit( Var2, 1 ); + value = sat_solver_addclause( p->pSat, pLits, pLits+2 ); + assert( value ); + } + } + else if ( fTwo && Vec_IntSize(vLevel) >= 3 ) + { + Vec_IntForEachEntry( vLevel, Var1, v1 ) + Vec_IntForEachEntryStart( vLevel, Var2, v2, v1 + 1 ) + Vec_IntForEachEntryStart( vLevel, Var3, v3, v2 + 1 ) + { + pLits[0] = Abc_Var2Lit( Var1, 1 ); + pLits[1] = Abc_Var2Lit( Var2, 1 ); + pLits[2] = Abc_Var2Lit( Var3, 1 ); + value = sat_solver_addclause( p->pSat, pLits, pLits+3 ); + assert( value ); + } + } + } + Vec_WecFree( vObjEdges ); + // block forbidden edges + Vec_IntForEachEntry( p->vToSkip, Edge, i ) + { + pLits[0] = Abc_Var2Lit( Edge, 1 ); + value = sat_solver_addclause( p->pSat, pLits, pLits+1 ); + assert( value ); + } + if ( fVerbose ) + printf( "Edge constraints = %d. ", sat_solver_nclauses(p->pSat) - nConstr ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Seg_ManConvertResult( Seg_Man_t * p ) +{ + int iFanin, iObj, i; + Vec_Int_t * vEdges2 = Vec_IntAlloc( 1000 ); + Vec_IntForEachEntryDouble( p->vEdges, iFanin, iObj, i ) + if ( sat_solver_var_value(p->pSat, i/2) ) + Vec_IntPushTwo( vEdges2, iFanin, iObj ); + return vEdges2; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Seg_ManComputeDelay( Gia_Man_t * pGia, int DelayInit, int nFanouts, int fTwo, int fVerbose ) +{ + int nBTLimit = 0; + int nTimeOut = 0; + int fVeryVerbose = 0; + + Gia_Obj_t * pObj; + abctime clk = Abc_Clock(); + Vec_Int_t * vEdges2 = NULL; + int i, iLut, iFirst, nVars, status, Delay, nConfs; + Seg_Man_t * p = Seg_ManAlloc( pGia, nFanouts ); + int DelayStart = DelayInit ? DelayInit : p->DelayMax; + + if ( fVerbose ) + printf( "Running SatEdge with starting delay %d and edge %d (edge vars %d, total vars %d)\n", + DelayStart, fTwo+1, p->FirstVar, sat_solver_nvars(p->pSat) ); + Seg_ManCreateCnf( p, fTwo, fVerbose ); + //Sat_SolverWriteDimacs( p->pSat, "test_edge.cnf", NULL, NULL, 0 ); + // set resource limits + sat_solver_set_resource_limits( p->pSat, nBTLimit, 0, 0, 0 ); + sat_solver_set_runtime_limit( p->pSat, nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 ); + sat_solver_set_random( p->pSat, 1 ); + sat_solver_set_polarity( p->pSat, Vec_IntArray(p->vPolars), Vec_IntSize(p->vPolars) ); + //sat_solver_set_var_activity( p->pSat, NULL, p->nVars ); + // increment delay gradually + for ( Delay = p->DelayMax; Delay >= 0; Delay-- ) + { + // we constrain COs, although it would be fine to constrain only POs + Gia_ManForEachCoDriver( p->pGia, pObj, i ) + { + iLut = Gia_ObjId( p->pGia, pObj ); + iFirst = Vec_IntEntry( p->vFirsts, iLut ); + nVars = Vec_IntEntry( p->vNvars, iLut ); + if ( Delay < nVars && !sat_solver_push(p->pSat, Abc_Var2Lit(iFirst + Delay, 1)) ) + break; + } + if ( i < Gia_ManCoNum(p->pGia) ) + { + printf( "Proved UNSAT for delay %d. ", Delay ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + break; + } + if ( Delay > DelayStart ) + continue; + // solve with assumptions + //clk = Abc_Clock(); + nConfs = sat_solver_nconflicts( p->pSat ); + status = sat_solver_solve_internal( p->pSat ); + nConfs = sat_solver_nconflicts( p->pSat ) - nConfs; + if ( status == l_True ) + { + if ( fVerbose ) + { + int Count = 0; + for ( i = 0; i < p->nVars; i++ ) + Count += sat_solver_var_value(p->pSat, i); + printf( "Solution with delay %2d and %5d edges exists. Conf = %8d. ", Delay, Count, nConfs ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + // save the result + Vec_IntFreeP( &vEdges2 ); + vEdges2 = Seg_ManConvertResult( p ); + if ( fVeryVerbose ) + { + for ( i = 0; i < p->nVars; i++ ) + printf( "%d=%d ", i, sat_solver_var_value(p->pSat, i) ); + printf( " " ); + + for ( i = p->nVars; i < sat_solver_nvars(p->pSat); i++ ) + printf( "%d=%d ", i, sat_solver_var_value(p->pSat, i) ); + printf( "\n" ); + } + } + else + { + if ( fVerbose ) + { + if ( status == l_False ) + printf( "Proved UNSAT for delay %d. ", Delay ); + else + printf( "Resource limit reached for delay %d. ", Delay ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + break; + } + } + Gia_ManEdgeFromArray( p->pGia, vEdges2 ); + Vec_IntFreeP( &vEdges2 ); + Seg_ManStop( p ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaSatLE.c b/yosys/abc/src/aig/gia/giaSatLE.c new file mode 100644 index 00000000000..04935f99aad --- /dev/null +++ b/yosys/abc/src/aig/gia/giaSatLE.c @@ -0,0 +1,1083 @@ +/**CFile**************************************************************** + + FileName [giaSatLE.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Mapping with edges.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSatLE.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/extra/extra.h" +#include "misc/tim/tim.h" +#include "sat/bsat/satStore.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Sle_CutSize( int * pCut ) { return pCut[0] & 0xF; } // 4 bits +static inline int Sle_CutSign( int * pCut ) { return ((unsigned)pCut[0]) >> 4; } // 28 bits +static inline int Sle_CutSetSizeSign( int s, int S ) { return (S << 4) | s; } +static inline int * Sle_CutLeaves( int * pCut ) { return pCut + 1; } + +static inline int Sle_CutIsUsed( int * pCut ) { return pCut[1] != 0; } +static inline void Sle_CutSetUnused( int * pCut ) { pCut[1] = 0; } + +static inline int Sle_ListCutNum( int * pList ) { return pList[0]; } + +#define Sle_ForEachCut( pList, pCut, i ) for ( i = 0, pCut = pList + 1; i < pList[0]; i++, pCut += Sle_CutSize(pCut) + 1 ) // cuts with unit-cut +#define Sle_ForEachCut1( pList, pCut, i ) for ( i = 0, pCut = pList + 1; i <= pList[0]; i++, pCut += Sle_CutSize(pCut) + 1 ) // only non-unit cuts + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Cut computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Sle_CutMergeOrder( int * pCut0, int * pCut1, int * pCut, int nLutSize ) +{ + int nSize0 = Sle_CutSize(pCut0); + int nSize1 = Sle_CutSize(pCut1); + int i, * pC0 = Sle_CutLeaves(pCut0); + int k, * pC1 = Sle_CutLeaves(pCut1); + int c, * pC = Sle_CutLeaves(pCut); + // the case of the largest cut sizes + if ( nSize0 == nLutSize && nSize1 == nLutSize ) + { + for ( i = 0; i < nSize0; i++ ) + { + if ( pC0[i] != pC1[i] ) return 0; + pC[i] = pC0[i]; + } + pCut[0] = Sle_CutSetSizeSign( nLutSize, Sle_CutSign(pCut0) | Sle_CutSign(pCut1) ); + return 1; + } + // compare two cuts with different numbers + i = k = c = 0; + if ( nSize0 == 0 ) goto FlushCut1; + if ( nSize1 == 0 ) goto FlushCut0; + while ( 1 ) + { + if ( c == nLutSize ) return 0; + if ( pC0[i] < pC1[k] ) + { + pC[c++] = pC0[i++]; + if ( i >= nSize0 ) goto FlushCut1; + } + else if ( pC0[i] > pC1[k] ) + { + pC[c++] = pC1[k++]; + if ( k >= nSize1 ) goto FlushCut0; + } + else + { + pC[c++] = pC0[i++]; k++; + if ( i >= nSize0 ) goto FlushCut1; + if ( k >= nSize1 ) goto FlushCut0; + } + } + +FlushCut0: + if ( c + nSize0 > nLutSize + i ) return 0; + while ( i < nSize0 ) + pC[c++] = pC0[i++]; + pCut[0] = Sle_CutSetSizeSign( c, Sle_CutSign(pCut0) | Sle_CutSign(pCut1) ); + return 1; + +FlushCut1: + if ( c + nSize1 > nLutSize + k ) return 0; + while ( k < nSize1 ) + pC[c++] = pC1[k++]; + pCut[0] = Sle_CutSetSizeSign( c, Sle_CutSign(pCut0) | Sle_CutSign(pCut1) ); + return 1; +} +static inline int Sle_SetCutIsContainedOrder( int * pBase, int * pCut ) // check if pCut is contained in pBase +{ + int i, nSizeB = Sle_CutSize(pBase); + int k, nSizeC = Sle_CutSize(pCut); + int * pLeaveB = Sle_CutLeaves(pBase); + int * pLeaveC = Sle_CutLeaves(pCut); + if ( nSizeB == nSizeC ) + { + for ( i = 0; i < nSizeB; i++ ) + if ( pLeaveB[i] != pLeaveC[i] ) + return 0; + return 1; + } + assert( nSizeB > nSizeC ); + if ( nSizeC == 0 ) + return 1; + for ( i = k = 0; i < nSizeB; i++ ) + { + if ( pLeaveB[i] > pLeaveC[k] ) + return 0; + if ( pLeaveB[i] == pLeaveC[k] ) + { + if ( ++k == nSizeC ) + return 1; + } + } + return 0; +} +static inline int Sle_CutCountBits( unsigned i ) +{ + i = i - ((i >> 1) & 0x55555555); + i = (i & 0x33333333) + ((i >> 2) & 0x33333333); + i = ((i + (i >> 4)) & 0x0F0F0F0F); + return (i*(0x01010101))>>24; +} +static inline int Sle_SetLastCutIsContained( Vec_Int_t * vTemp, int * pBase ) +{ + int i, * pCut, * pList = Vec_IntArray(vTemp); + Sle_ForEachCut( pList, pCut, i ) + if ( Sle_CutIsUsed(pCut) && Sle_CutSize(pCut) <= Sle_CutSize(pBase) && (Sle_CutSign(pCut) & Sle_CutSign(pBase)) == Sle_CutSign(pCut) && Sle_SetCutIsContainedOrder(pBase, pCut) ) + return 1; + return 0; +} +static inline void Sle_SetAddCut( Vec_Int_t * vTemp, int * pCut ) +{ + int i, * pBase, * pList = Vec_IntArray(vTemp); + Sle_ForEachCut( pList, pBase, i ) + if ( Sle_CutIsUsed(pBase) && Sle_CutSize(pCut) < Sle_CutSize(pBase) && (Sle_CutSign(pCut) & Sle_CutSign(pBase)) == Sle_CutSign(pCut) && Sle_SetCutIsContainedOrder(pBase, pCut) ) + Sle_CutSetUnused( pBase ); + Vec_IntPushArray( vTemp, pCut, Sle_CutSize(pCut)+1 ); + Vec_IntAddToEntry( vTemp, 0, 1 ); +} +int Sle_ManCutMerge( Gia_Man_t * p, int iObj, Vec_Int_t * vCuts, Vec_Int_t * vTemp, int nLutSize ) +{ + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + int * pList0 = Vec_IntEntryP( vCuts, Vec_IntEntry(vCuts, Gia_ObjFaninId0(pObj, iObj)) ); + int * pList1 = Vec_IntEntryP( vCuts, Vec_IntEntry(vCuts, Gia_ObjFaninId1(pObj, iObj)) ); + int * pCut0, * pCut1, i, k, Cut[8], nCuts = 0; + Vec_IntFill( vTemp, 1, 0 ); + Sle_ForEachCut1( pList0, pCut0, i ) + Sle_ForEachCut1( pList1, pCut1, k ) + { + if ( Sle_CutSize(pCut0) + Sle_CutSize(pCut1) > nLutSize && Sle_CutCountBits(Sle_CutSign(pCut0) | Sle_CutSign(pCut1)) > nLutSize ) + continue; + if ( !Sle_CutMergeOrder(pCut0, pCut1, Cut, nLutSize) ) + continue; + if ( Sle_SetLastCutIsContained(vTemp, Cut) ) + continue; + Sle_SetAddCut( vTemp, Cut ); + } + // reload + Vec_IntWriteEntry( vCuts, iObj, Vec_IntSize(vCuts) ); + Vec_IntPush( vCuts, -1 ); + pList0 = Vec_IntArray(vTemp); + Sle_ForEachCut( pList0, pCut0, i ) + { + if ( !Sle_CutIsUsed(pCut0) ) + continue; + Vec_IntPushArray( vCuts, pCut0, Sle_CutSize(pCut0)+1 ); + nCuts++; + } + // add unit cut + Vec_IntPush( vCuts, Sle_CutSetSizeSign(1, 1<<(iObj % 28)) ); + Vec_IntPush( vCuts, iObj ); + Vec_IntWriteEntry( vCuts, Vec_IntEntry(vCuts, iObj), nCuts ); + return nCuts; +} +Vec_Int_t * Sle_ManComputeCuts( Gia_Man_t * p, int nLutSize, int fVerbose ) +{ + int i, iObj, nCuts = 0; + Vec_Int_t * vTemp = Vec_IntAlloc( 1000 ); + Vec_Int_t * vCuts = Vec_IntAlloc( 30 * Gia_ManAndNum(p) ); + assert( nLutSize <= 6 ); + Vec_IntFill( vCuts, Gia_ManObjNum(p), 0 ); + Gia_ManForEachCiId( p, iObj, i ) + { + Vec_IntWriteEntry( vCuts, iObj, Vec_IntSize(vCuts) ); + Vec_IntPush( vCuts, 0 ); + Vec_IntPush( vCuts, Sle_CutSetSizeSign(1, 1<<(iObj % 28)) ); + Vec_IntPush( vCuts, iObj ); + } + Gia_ManForEachAndId( p, iObj ) + nCuts += Sle_ManCutMerge( p, iObj, vCuts, vTemp, nLutSize ); + if ( fVerbose ) + printf( "Nodes = %d. Cuts = %d. Cuts/Node = %.2f. Ints/Node = %.2f. Mem = %.2f MB.\n", + Gia_ManAndNum(p), nCuts, 1.0*nCuts/Gia_ManAndNum(p), + 1.0*(Vec_IntSize(vCuts)-Gia_ManObjNum(p))/Gia_ManAndNum(p), + 1.0*Vec_IntMemory(vCuts) / (1<<20) ); + Vec_IntFree( vTemp ); + return vCuts; +} + +/**Function************************************************************* + + Synopsis [Cut delay computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sle_ManComputeDelayCut( Gia_Man_t * p, int * pCut, Vec_Int_t * vTime ) +{ + int nSize = Sle_CutSize(pCut); + int k, * pC = Sle_CutLeaves(pCut); + int DelayMax = 0; + for ( k = 0; k < nSize; k++ ) + DelayMax = Abc_MaxInt( DelayMax, Vec_IntEntry(vTime, pC[k]) ); + return DelayMax + 1; +} +int Sle_ManComputeDelayOne( Gia_Man_t * p, int iObj, Vec_Int_t * vCuts, Vec_Int_t * vTime ) +{ + int i, * pCut, Delay, DelayMin = ABC_INFINITY; + int * pList = Vec_IntEntryP( vCuts, Vec_IntEntry(vCuts, iObj) ); + Sle_ForEachCut( pList, pCut, i ) + { + Delay = Sle_ManComputeDelayCut( p, pCut, vTime ); + DelayMin = Abc_MinInt( DelayMin, Delay ); + } + Vec_IntWriteEntry( vTime, iObj, DelayMin ); + return DelayMin; +} +int Sle_ManComputeDelay( Gia_Man_t * p, Vec_Int_t * vCuts ) +{ + int iObj, Delay, DelayMax = 0; + Vec_Int_t * vTime = Vec_IntStart( Gia_ManObjNum(p) ); + Gia_ManForEachAndId( p, iObj ) + { + Delay = Sle_ManComputeDelayOne( p, iObj, vCuts, vTime ); + DelayMax = Abc_MaxInt( DelayMax, Delay ); + } + Vec_IntFree( vTime ); + //printf( "Delay = %d.\n", DelayMax ); + return DelayMax; +} + +/**Function************************************************************* + + Synopsis [Cut printing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sle_ManPrintCut( int * pCut ) +{ + int nSize = Sle_CutSize(pCut); + int k, * pC = Sle_CutLeaves(pCut); + printf( "{" ); + for ( k = 0; k < nSize; k++ ) + printf( " %d", pC[k] ); + printf( " }\n" ); +} +void Sle_ManPrintCuts( Gia_Man_t * p, Vec_Int_t * vCuts, int iObj ) +{ + int i, * pCut; + int * pList = Vec_IntEntryP( vCuts, Vec_IntEntry(vCuts, iObj) ); + printf( "Obj %3d\n", iObj ); + Sle_ForEachCut( pList, pCut, i ) + Sle_ManPrintCut( pCut ); + printf( "\n" ); +} +void Sle_ManPrintCutsAll( Gia_Man_t * p, Vec_Int_t * vCuts ) +{ + int iObj; + Gia_ManForEachAndId( p, iObj ) + Sle_ManPrintCuts( p, vCuts, iObj ); +} +void Sle_ManComputeCutsTest( Gia_Man_t * p ) +{ + Vec_Int_t * vCuts = Sle_ManComputeCuts( p, 4, 1 ); + //Sle_ManPrintCutsAll( p, vCuts ); + Vec_IntFree( vCuts ); +} + + + +/**Function************************************************************* + + Synopsis [Derive mask representing internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Bit_t * Sle_ManInternalNodeMask( Gia_Man_t * pGia ) +{ + int iObj; + Vec_Bit_t * vMask = Vec_BitStart( Gia_ManObjNum(pGia) ); + Gia_ManForEachAndId( pGia, iObj ) + Vec_BitWriteEntry( vMask, iObj, 1 ); + return vMask; +} + +/**Function************************************************************* + + Synopsis [Check if the cut contains only primary inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sle_ManCutHasPisOnly( int * pCut, Vec_Bit_t * vMask ) +{ + int k, * pC = Sle_CutLeaves(pCut); + for ( k = 0; k < Sle_CutSize(pCut); k++ ) + if ( Vec_BitEntry(vMask, pC[k]) ) // internal node + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Derive cut fanins of each node.] + + Description [These are nodes that are fanins of some cut of this node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sle_ManCollectCutFaninsOne( Gia_Man_t * pGia, int iObj, Vec_Int_t * vCuts, Vec_Bit_t * vMask, Vec_Int_t * vCutFanins, Vec_Bit_t * vMap ) +{ + int i, iFanin, * pCut, * pList = Vec_IntEntryP( vCuts, Vec_IntEntry(vCuts, iObj) ); + Sle_ForEachCut( pList, pCut, i ) + { + int nSize = Sle_CutSize(pCut); + int k, * pC = Sle_CutLeaves(pCut); + assert( nSize > 1 ); + for ( k = 0; k < nSize; k++ ) + if ( Vec_BitEntry(vMask, pC[k]) && !Vec_BitEntry(vMap, pC[k]) ) + { + Vec_BitWriteEntry( vMap, pC[k], 1 ); + Vec_IntPush( vCutFanins, pC[k] ); + } + } + Vec_IntForEachEntry( vCutFanins, iFanin, i ) + Vec_BitWriteEntry( vMap, iFanin, 0 ); +} +Vec_Wec_t * Sle_ManCollectCutFanins( Gia_Man_t * pGia, Vec_Int_t * vCuts, Vec_Bit_t * vMask ) +{ + int iObj; + Vec_Bit_t * vMap = Vec_BitStart( Gia_ManObjNum(pGia) ); + Vec_Wec_t * vCutFanins = Vec_WecStart( Gia_ManObjNum(pGia) ); + Gia_ManForEachAndId( pGia, iObj ) + Sle_ManCollectCutFaninsOne( pGia, iObj, vCuts, vMask, Vec_WecEntry(vCutFanins, iObj), vMap ); + Vec_BitFree( vMap ); + return vCutFanins; +} + + +typedef struct Sle_Man_t_ Sle_Man_t; +struct Sle_Man_t_ +{ + // user's data + Gia_Man_t * pGia; // user's manager (with mapping and edges) + int nLevels; // total number of levels + int fVerbose; // verbose flag + int nSatCalls; // the number of SAT calls + // SAT variables + int nNodeVars; // node variables (Gia_ManAndNum(pGia)) + int nCutVars; // cut variables (total number of non-trivial cuts) + int nEdgeVars; // edge variables (total number of internal edges) + int nDelayVars; // delay variables (nNodeVars * nLevelsMax) + int nVarsTotal; // total number of variables + // SAT clauses + int nCutClas; // cut clauses + int nEdgeClas; // edge clauses + int nEdgeClas2; // edge clauses exclusivity + int nDelayClas; // delay clauses + // internal data + sat_solver * pSat; // SAT solver + Vec_Bit_t * vMask; // internal node mask + Vec_Int_t * vCuts; // cuts for each node + Vec_Wec_t * vCutFanins; // internal cut fanins of each node + Vec_Wec_t * vFanoutEdges; // internal cut fanins of each node + Vec_Wec_t * vEdgeCuts; // cuts of each edge for one node + Vec_Int_t * vObjMap; // temporary object map + Vec_Int_t * vCutFirst; // first cut of each node + Vec_Int_t * vEdgeFirst; // first edge of each node + Vec_Int_t * vDelayFirst; // first edge of each node + Vec_Int_t * vPolars; // initial + Vec_Int_t * vLits; // literals + // statistics + abctime timeStart; +}; + +static inline int * Sle_ManList( Sle_Man_t * p, int i ) { return Vec_IntEntryP(p->vCuts, Vec_IntEntry(p->vCuts, i)); } + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Sle_Man_t * Sle_ManAlloc( Gia_Man_t * pGia, int nLevels, int fVerbose ) +{ + Sle_Man_t * p = ABC_CALLOC( Sle_Man_t, 1 ); + p->pGia = pGia; + p->nLevels = nLevels; + p->fVerbose = fVerbose; + p->vMask = Sle_ManInternalNodeMask( pGia ); + p->vCuts = Sle_ManComputeCuts( pGia, 4, fVerbose ); + p->vCutFanins = Sle_ManCollectCutFanins( pGia, p->vCuts, p->vMask ); + p->vFanoutEdges = Vec_WecStart( Gia_ManObjNum(pGia) ); + p->vEdgeCuts = Vec_WecAlloc( 100 ); + p->vObjMap = Vec_IntStartFull( Gia_ManObjNum(pGia) ); + p->vCutFirst = Vec_IntStartFull( Gia_ManObjNum(pGia) ); + p->vEdgeFirst = Vec_IntStartFull( Gia_ManObjNum(pGia) ); + p->vDelayFirst = Vec_IntStartFull( Gia_ManObjNum(pGia) ); + p->vPolars = Vec_IntAlloc( 100 ); + p->vLits = Vec_IntAlloc( 100 ); + p->nLevels = Sle_ManComputeDelay( pGia, p->vCuts ); + return p; +} +void Sle_ManStop( Sle_Man_t * p ) +{ + sat_solver_delete( p->pSat ); + Vec_BitFree( p->vMask ); + Vec_IntFree( p->vCuts ); + Vec_WecFree( p->vCutFanins ); + Vec_WecFree( p->vFanoutEdges ); + Vec_WecFree( p->vEdgeCuts ); + Vec_IntFree( p->vObjMap ); + Vec_IntFree( p->vCutFirst ); + Vec_IntFree( p->vEdgeFirst ); + Vec_IntFree( p->vDelayFirst ); + Vec_IntFree( p->vPolars ); + Vec_IntFree( p->vLits ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sle_ManMarkupVariables( Sle_Man_t * p ) +{ + int iObj, Counter = Gia_ManObjNum(p->pGia); + // node variables + p->nNodeVars = Counter; + // cut variables + Gia_ManForEachAndId( p->pGia, iObj ) + { + Vec_IntWriteEntry( p->vCutFirst, iObj, Counter ); + Counter += Sle_ListCutNum( Sle_ManList(p, iObj) ); + } + p->nCutVars = Counter - p->nNodeVars; + // edge variables + Gia_ManForEachAndId( p->pGia, iObj ) + { + Vec_IntWriteEntry( p->vEdgeFirst, iObj, Counter ); + Counter += Vec_IntSize( Vec_WecEntry(p->vCutFanins, iObj) ); + } + p->nEdgeVars = Counter - p->nCutVars - p->nNodeVars; + // delay variables + Gia_ManForEachAndId( p->pGia, iObj ) + { + Vec_IntWriteEntry( p->vDelayFirst, iObj, Counter ); + Counter += p->nLevels; + } + p->nDelayVars = Counter - p->nEdgeVars - p->nCutVars - p->nNodeVars; + p->nVarsTotal = Counter; +} + + +/**Function************************************************************* + + Synopsis [Derive initial variable assignment.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +// returns 1 if Cut can represent LUT (Cut is equal or is contained in LUT) +static inline int Sle_ManCheckContained( int * pCutLeaves, int nCutLeaves, int * pLutFanins, int nLutFanins ) +{ + int i, k; + if ( nCutLeaves > nLutFanins ) + return 0; + for ( i = 0; i < nCutLeaves; i++ ) + { + for ( k = 0; k < nLutFanins; k++ ) + if ( pCutLeaves[i] == pLutFanins[k] ) + break; + if ( k == nLutFanins ) // not found + return 0; + } + return 1; +} +void Sle_ManDeriveInit( Sle_Man_t * p ) +{ + Vec_Int_t * vEdges; + int i, iObj, iFanin, iEdge; + if ( !Gia_ManHasMapping(p->pGia) ) + return; + // derive initial state + Vec_IntClear( p->vPolars ); + Gia_ManForEachAndId( p->pGia, iObj ) + { + int nFanins, * pFanins, * pCut, * pList, iFound = -1; + if ( !Gia_ObjIsLut(p->pGia, iObj) ) + continue; + Vec_IntPush( p->vPolars, iObj ); // node var + nFanins = Gia_ObjLutSize( p->pGia, iObj ); + pFanins = Gia_ObjLutFanins( p->pGia, iObj ); + // find cut + pList = Sle_ManList( p, iObj ); + Sle_ForEachCut( pList, pCut, i ) + if ( Sle_ManCheckContained( Sle_CutLeaves(pCut), Sle_CutSize(pCut), pFanins, nFanins ) ) + { + iFound = i; + break; + } + if ( iFound == -1 ) + { + printf( "Cannot find the following cut at node %d: {", iObj ); + for ( i = 0; i < nFanins; i++ ) + printf( " %d", pFanins[i] ); + printf( " }\n" ); + Sle_ManPrintCuts( p->pGia, p->vCuts, iObj ); + fflush( stdout ); + } + assert( iFound >= 0 ); + Vec_IntPush( p->vPolars, Vec_IntEntry(p->vCutFirst, iObj) + iFound ); // cut var + // check if the cut contains only primary inputs - if so, its delay is equal to 1 + if ( Sle_ManCutHasPisOnly(pCut, p->vMask) ) + Vec_IntPush( p->vPolars, Vec_IntEntry(p->vDelayFirst, iObj) ); // delay var + } + Vec_IntSort( p->vPolars, 0 ); + // find zero-delay edges + if ( !p->pGia->vEdge1 ) + return; + vEdges = Gia_ManEdgeToArray( p->pGia ); + Vec_IntForEachEntryDouble( vEdges, iFanin, iObj, i ) + { + assert( iFanin < iObj ); + assert( Gia_ObjIsLut(p->pGia, iFanin) ); + assert( Gia_ObjIsLut(p->pGia, iObj) ); + assert( Gia_ObjIsAnd(Gia_ManObj(p->pGia, iFanin)) ); + assert( Gia_ObjIsAnd(Gia_ManObj(p->pGia, iObj)) ); + // find edge + iEdge = Vec_IntFind( Vec_WecEntry(p->vCutFanins, iObj), iFanin ); + if ( iEdge < 0 ) + continue; + assert( iEdge >= 0 ); + Vec_IntPush( p->vPolars, Vec_IntEntry(p->vEdgeFirst, iObj) + iEdge ); // edge + } + Vec_IntFree( vEdges ); +} + +/**Function************************************************************* + + Synopsis [Derive CNF.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sle_ManDeriveCnf( Sle_Man_t * p, int nBTLimit, int fDynamic ) +{ + int nTimeOut = 0; + int i, iObj, value; + Vec_Int_t * vArray; + + // start the SAT solver + p->pSat = sat_solver_new(); + sat_solver_setnvars( p->pSat, p->nVarsTotal ); + sat_solver_set_resource_limits( p->pSat, nBTLimit, 0, 0, 0 ); + sat_solver_set_runtime_limit( p->pSat, nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 ); + sat_solver_set_random( p->pSat, 1 ); + sat_solver_set_polarity( p->pSat, Vec_IntArray(p->vPolars), Vec_IntSize(p->vPolars) ); + //sat_solver_set_var_activity( p->pSat, NULL, p->nVarsTotal ); + + // set drivers to be mapped + Gia_ManForEachCoDriverId( p->pGia, iObj, i ) + if ( Vec_BitEntry(p->vMask, iObj) ) // internal node + { + Vec_IntFill( p->vLits, 1, Abc_Var2Lit(iObj, 0) ); // pos lit + value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); + assert( value ); + } + + // add cover clauses and edge-to-cut clauses + Gia_ManForEachAndId( p->pGia, iObj ) + { + int e, iEdge, nEdges = 0, Entry; + int iCutVar0 = Vec_IntEntry( p->vCutFirst, iObj ); + int iEdgeVar0 = Vec_IntEntry( p->vEdgeFirst, iObj ); + int * pCut, * pList = Sle_ManList( p, iObj ); + Vec_Int_t * vCutFans = Vec_WecEntry( p->vCutFanins, iObj ); + assert( iCutVar0 > 0 && iEdgeVar0 > 0 ); + // node requires one of the cuts + Vec_IntFill( p->vLits, 1, Abc_Var2Lit(iObj, 1) ); // neg lit + for ( i = 0; i < Sle_ListCutNum(pList); i++ ) + Vec_IntPush( p->vLits, Abc_Var2Lit(iCutVar0 + i, 0) ); + value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); + assert( value ); + // cuts are mutually exclusive + for ( i = 0; i < Sle_ListCutNum(pList); i++ ) + for ( e = i+1; e < Sle_ListCutNum(pList); e++ ) + { + Vec_IntFillTwo( p->vLits, 2, Abc_Var2Lit(iCutVar0 + i, 1), Abc_Var2Lit(iCutVar0 + e, 1) ); + value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); + assert( value ); + } + // cut requires fanin nodes + Vec_WecInit( p->vEdgeCuts, Vec_IntSize(vCutFans) ); + Sle_ForEachCut( pList, pCut, i ) + { + int nSize = Sle_CutSize(pCut); + int k, * pC = Sle_CutLeaves(pCut); + assert( nSize > 1 ); + for ( k = 0; k < nSize; k++ ) + { + if ( !Vec_BitEntry(p->vMask, pC[k]) ) + continue; + Vec_IntFillTwo( p->vLits, 2, Abc_Var2Lit(iCutVar0 + i, 1), Abc_Var2Lit(pC[k], 0) ); + value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); + assert( value ); + // find the edge ID between pC[k] and iObj + iEdge = Vec_IntEntry(p->vObjMap, pC[k]); + if ( iEdge == -1 ) + { + Vec_IntWriteEntry( p->vObjMap, pC[k], (iEdge = nEdges++) ); + Vec_WecPush( p->vFanoutEdges, pC[k], iEdgeVar0 + iEdge ); + } + Vec_WecPush( p->vEdgeCuts, iEdge, iCutVar0 + i ); + p->nCutClas++; + } + // cut requires the node + Vec_IntFillTwo( p->vLits, 2, Abc_Var2Lit(iCutVar0 + i, 1), Abc_Var2Lit(iObj, 0) ); + value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); + assert( value ); + } + assert( nEdges == Vec_IntSize(vCutFans) ); + + // edge requires one of the fanout cuts + Vec_WecForEachLevel( p->vEdgeCuts, vArray, e ) + { + assert( Vec_IntSize(vArray) > 0 ); + Vec_IntFill( p->vLits, 1, Abc_Var2Lit(iEdgeVar0 + e, 1) ); // neg lit (edge) + Vec_IntForEachEntry( vArray, Entry, i ) + Vec_IntPush( p->vLits, Abc_Var2Lit(Entry, 0) ); // pos lit (cut) + value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); + assert( value ); + p->nEdgeClas++; + } + + // clean object map + Vec_IntForEachEntry( vCutFans, Entry, i ) + Vec_IntWriteEntry( p->vObjMap, Entry, -1 ); + } + + // mutual exclusivity of edges + Vec_WecForEachLevel( p->vFanoutEdges, vArray, iObj ) + { + int j, k, EdgeJ, EdgeK; + int iEdgeVar0 = Vec_IntEntry( p->vEdgeFirst, iObj ); + Vec_Int_t * vCutFans = Vec_WecEntry( p->vCutFanins, iObj ); + // add fanin edges + for ( i = 0; i < Vec_IntSize(vCutFans); i++ ) + Vec_IntPush( vArray, iEdgeVar0 + i ); + // generate pairs + if ( fDynamic ) + continue; + Vec_IntForEachEntry( vArray, EdgeJ, j ) + Vec_IntForEachEntryStart( vArray, EdgeK, k, j+1 ) + { + Vec_IntFillTwo( p->vLits, 2, Abc_Var2Lit(EdgeJ, 1), Abc_Var2Lit(EdgeK, 1) ); + value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); + assert( value ); + } + p->nEdgeClas2 += Vec_IntSize(vArray) * (Vec_IntSize(vArray) - 1) / 2; + } + + // add delay clauses + Gia_ManForEachAndId( p->pGia, iObj ) + { + int e, iFanin; + int iEdgeVar0 = Vec_IntEntry( p->vEdgeFirst, iObj ); + int iDelayVar0 = Vec_IntEntry( p->vDelayFirst, iObj ); + Vec_Int_t * vCutFans = Vec_WecEntry( p->vCutFanins, iObj ); + // check if the node has cuts containing only primary inputs + int * pCut, * pList = Sle_ManList( p, iObj ); + Sle_ForEachCut( pList, pCut, i ) + if ( Sle_ManCutHasPisOnly(pCut, p->vMask) ) + { + Vec_IntFill( p->vLits, 1, Abc_Var2Lit(iDelayVar0, 0) ); // pos lit +// Vec_IntFillTwo( p->vLits, 2, Abc_Var2Lit(iObj, 1), Abc_Var2Lit(iDelayVar0, 0) ); + value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); + assert( value ); + break; + } +// if ( i < Sle_ListCutNum(pList) ) +// continue; + // create delay requirements for each cut fanin of this node + Vec_IntForEachEntry( vCutFans, iFanin, e ) + { + int d, iDelayVarIn = Vec_IntEntry( p->vDelayFirst, iFanin ); + for ( d = 0; d < p->nLevels; d++ ) + { + Vec_IntClear( p->vLits ); + Vec_IntPush( p->vLits, Abc_Var2Lit(iObj, 1) ); + Vec_IntPush( p->vLits, Abc_Var2Lit(iFanin, 1) ); + Vec_IntPush( p->vLits, Abc_Var2Lit(iDelayVarIn + d, 1) ); + Vec_IntPush( p->vLits, Abc_Var2Lit(iEdgeVar0 + e, 0) ); + if ( d < p->nLevels-1 ) + Vec_IntPush( p->vLits, Abc_Var2Lit(iDelayVar0 + d+1, 0) ); + value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); + assert( value ); + + Vec_IntClear( p->vLits ); + Vec_IntPush( p->vLits, Abc_Var2Lit(iObj, 1) ); + Vec_IntPush( p->vLits, Abc_Var2Lit(iFanin, 1) ); + Vec_IntPush( p->vLits, Abc_Var2Lit(iDelayVarIn + d, 1) ); + if ( d < p->nLevels-1 ) + Vec_IntPush( p->vLits, Abc_Var2Lit(iEdgeVar0 + e, 1) ); + Vec_IntPush( p->vLits, Abc_Var2Lit(iDelayVar0 + d, 0) ); + value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); + assert( value ); + } + p->nDelayClas += 2*p->nLevels; + } + } +} + +/**Function************************************************************* + + Synopsis [Add edge compatibility constraints.] + + Description [Returns 1 if constraints have been added.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sle_ManAddEdgeConstraints( Sle_Man_t * p, int nEdges ) +{ + Vec_Int_t * vArray; + Vec_Int_t * vTemp = Vec_IntAlloc( 100 ); + int value, iObj, nAdded = 0; + assert( nEdges == 1 || nEdges == 2 ); + Vec_WecForEachLevel( p->vFanoutEdges, vArray, iObj ) + { + int j, k, EdgeJ, EdgeK; + // check if they are incompatible + Vec_IntClear( vTemp ); + Vec_IntForEachEntry( vArray, EdgeJ, j ) + if ( sat_solver_var_value(p->pSat, EdgeJ) ) + Vec_IntPush( vTemp, EdgeJ ); + if ( Vec_IntSize(vTemp) <= nEdges ) + continue; + nAdded++; + if ( nEdges == 1 ) + { + // generate pairs + Vec_IntForEachEntry( vTemp, EdgeJ, j ) + Vec_IntForEachEntryStart( vTemp, EdgeK, k, j+1 ) + { + Vec_IntFillTwo( p->vLits, 2, Abc_Var2Lit(EdgeJ, 1), Abc_Var2Lit(EdgeK, 1) ); + value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); + assert( value ); + } + p->nEdgeClas2 += Vec_IntSize(vTemp) * (Vec_IntSize(vTemp) - 1) / 2; + } + else if ( nEdges == 2 ) + { + int m, EdgeM; + // generate triples + Vec_IntForEachEntry( vTemp, EdgeJ, j ) + Vec_IntForEachEntryStart( vTemp, EdgeK, k, j+1 ) + Vec_IntForEachEntryStart( vTemp, EdgeM, m, k+1 ) + { + Vec_IntFillTwo( p->vLits, 2, Abc_Var2Lit(EdgeJ, 1), Abc_Var2Lit(EdgeK, 1) ); + Vec_IntPush( p->vLits, Abc_Var2Lit(EdgeM, 1) ); + value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); + assert( value ); + } + p->nEdgeClas2 += Vec_IntSize(vTemp) * (Vec_IntSize(vTemp) - 1) * (Vec_IntSize(vTemp) - 2) / 6; + } + else assert( 0 ); + } + Vec_IntFree( vTemp ); + //printf( "Added clauses to %d nodes.\n", nAdded ); + return nAdded; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sle_ManDeriveResult( Sle_Man_t * p, Vec_Int_t * vEdge2, Vec_Int_t * vMapping ) +{ + Vec_Int_t * vMapTemp; + int iObj; + // create mapping + Vec_IntFill( vMapping, Gia_ManObjNum(p->pGia), 0 ); + Gia_ManForEachAndId( p->pGia, iObj ) + { + int i, iCut, iCutVar0 = Vec_IntEntry( p->vCutFirst, iObj ); + int * pCut, * pCutThis = NULL, * pList = Sle_ManList( p, iObj ); + if ( !sat_solver_var_value(p->pSat, iObj) ) + continue; + Sle_ForEachCut( pList, pCut, iCut ) + if ( sat_solver_var_value(p->pSat, iCutVar0 + iCut) ) + { + assert( pCutThis == NULL ); + pCutThis = pCut; + } + assert( pCutThis != NULL ); + Vec_IntWriteEntry( vMapping, iObj, Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, Sle_CutSize(pCutThis) ); + for ( i = 0; i < Sle_CutSize(pCutThis); i++ ) + Vec_IntPush( vMapping, Sle_CutLeaves(pCutThis)[i] ); + Vec_IntPush( vMapping, iObj ); + } + vMapTemp = p->pGia->vMapping; + p->pGia->vMapping = vMapping; + // collect edges + Vec_IntClear( vEdge2 ); + Gia_ManForEachAndId( p->pGia, iObj ) + { + int i, iFanin, iEdgeVar0 = Vec_IntEntry( p->vEdgeFirst, iObj ); + Vec_Int_t * vCutFans = Vec_WecEntry( p->vCutFanins, iObj ); + //int * pCut, * pList = Sle_ManList( p, iObj ); + // int iCutVar0 = Vec_IntEntry( p->vCutFirst, iObj ); + if ( !sat_solver_var_value(p->pSat, iObj) ) + continue; + //for ( i = 0; i < Sle_ListCutNum(pList); i++ ) + // printf( "%d", sat_solver_var_value(p->pSat, iCutVar0 + i) ); + //printf( "\n" ); + Vec_IntForEachEntry( vCutFans, iFanin, i ) + if ( sat_solver_var_value(p->pSat, iFanin) && sat_solver_var_value(p->pSat, iEdgeVar0 + i) ) + { + // verify edge + int * pFanins = Gia_ObjLutFanins( p->pGia, iObj ); + int k, nFanins = Gia_ObjLutSize( p->pGia, iObj ); + for ( k = 0; k < nFanins; k++ ) + { + //printf( "%d ", pFanins[k] ); + if ( pFanins[k] == iFanin ) + break; + } + //printf( "\n" ); + if ( k == nFanins ) +// printf( "Cannot find LUT with input %d at node %d.\n", iFanin, iObj ); + continue; + Vec_IntPushTwo( vEdge2, iFanin, iObj ); + } + } + p->pGia->vMapping = vMapTemp; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sle_ManExplore( Gia_Man_t * pGia, int nBTLimit, int DelayInit, int fDynamic, int fTwoEdges, int fVerbose ) +{ + int fVeryVerbose = 0; + abctime clk = Abc_Clock(); + Vec_Int_t * vEdges2 = Vec_IntAlloc(1000); + Vec_Int_t * vMapping = Vec_IntAlloc(1000); + int i, iLut, nConfs, status, Delay, iFirstVar; + int DelayStart = (DelayInit || !Gia_ManHasMapping(pGia)) ? DelayInit : Gia_ManLutLevel(pGia, NULL); + Sle_Man_t * p = Sle_ManAlloc( pGia, DelayStart, fVerbose ); + if ( fVerbose ) + printf( "Running solver with %d conflicts, %d initial delay, and %d edges. Dynamic constraints = %s.\n", nBTLimit, DelayInit, 1+fTwoEdges, fDynamic?"yes":"no" ); + Sle_ManMarkupVariables( p ); + if ( fVerbose ) + printf( "Vars: Total = %d. Node = %d. Cut = %d. Edge = %d. Delay = %d.\n", + p->nVarsTotal, p->nNodeVars, p->nCutVars, p->nEdgeVars, p->nDelayVars ); + Sle_ManDeriveInit( p ); + Sle_ManDeriveCnf( p, nBTLimit, fDynamic || fTwoEdges ); + if ( fVerbose ) + printf( "Clas: Total = %d. Cut = %d. Edge = %d. EdgeEx = %d. Delay = %d.\n", + sat_solver_nclauses(p->pSat), p->nCutClas, p->nEdgeClas, p->nEdgeClas2, p->nDelayClas ); + //Sat_SolverWriteDimacs( p->pSat, "temp.cnf", NULL, NULL, 0 ); + for ( Delay = p->nLevels; Delay >= 0; Delay-- ) + { + // we constrain COs, although it would be fine to constrain only POs + if ( Delay < p->nLevels ) + { + Gia_ManForEachCoDriverId( p->pGia, iLut, i ) + if ( Vec_BitEntry(p->vMask, iLut) ) // internal node + { + iFirstVar = Vec_IntEntry( p->vDelayFirst, iLut ); + if ( !sat_solver_push(p->pSat, Abc_Var2Lit(iFirstVar + Delay, 1)) ) + break; + } + if ( i < Gia_ManCoNum(p->pGia) ) + { + if ( fVerbose ) + { + printf( "Proved UNSAT for delay %d. ", Delay ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + break; + } + } + // solve with assumptions + //clk = Abc_Clock(); + nConfs = sat_solver_nconflicts( p->pSat ); + while ( 1 ) + { + p->nSatCalls++; + status = sat_solver_solve_internal( p->pSat ); + if ( status != l_True ) + break; + if ( !Sle_ManAddEdgeConstraints(p, 1+fTwoEdges) ) + break; + } + nConfs = sat_solver_nconflicts( p->pSat ) - nConfs; + if ( status == l_True ) + { + if ( fVerbose ) + { + int nNodes = 0, nEdges = 0; + for ( i = 0; i < p->nNodeVars; i++ ) + nNodes += sat_solver_var_value(p->pSat, i); + for ( i = 0; i < p->nEdgeVars; i++ ) + nEdges += sat_solver_var_value(p->pSat, p->nNodeVars + p->nCutVars + i); + printf( "Solution with delay %2d, node count %5d, and edge count %5d exists. Conf = %8d. ", Delay, nNodes, nEdges, nConfs ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + // save the result + Sle_ManDeriveResult( p, vEdges2, vMapping ); + if ( fVeryVerbose ) + { + printf( "Nodes: " ); + for ( i = 0; i < p->nNodeVars; i++ ) + if ( sat_solver_var_value(p->pSat, i) ) + printf( "%d ", i ); + printf( "\n" ); + printf( "\n" ); + + Vec_IntPrint( p->vCutFirst ); + printf( "Cuts: " ); + for ( i = 0; i < p->nCutVars; i++ ) + if ( sat_solver_var_value(p->pSat, p->nNodeVars + i) ) + printf( "%d ", p->nNodeVars + i ); + printf( "\n" ); + printf( "\n" ); + + Vec_IntPrint( p->vEdgeFirst ); + printf( "Edges: " ); + for ( i = 0; i < p->nEdgeVars; i++ ) + if ( sat_solver_var_value(p->pSat, p->nNodeVars + p->nCutVars + i) ) + printf( "%d ", p->nNodeVars + p->nCutVars + i ); + printf( "\n" ); + printf( "\n" ); + + Vec_IntPrint( p->vDelayFirst ); + printf( "Delays: " ); + for ( i = 0; i < p->nDelayVars; i++ ) + if ( sat_solver_var_value(p->pSat, p->nNodeVars + p->nCutVars + p->nEdgeVars + i) ) + printf( "%d ", p->nNodeVars + p->nCutVars + p->nEdgeVars + i ); + printf( "\n" ); + printf( "\n" ); + } + } + else + { + if ( fVerbose ) + { + if ( status == l_False ) + printf( "Proved UNSAT for delay %d. Conf = %8d. ", Delay, nConfs ); + else + printf( "Resource limit reached for delay %d. Conf = %8d. ", Delay, nConfs ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + break; + } + } + if ( fVerbose ) + printf( "Clas: Total = %d. Cut = %d. Edge = %d. EdgeEx = %d. Delay = %d. Calls = %d.\n", + sat_solver_nclauses(p->pSat), p->nCutClas, p->nEdgeClas, p->nEdgeClas2, p->nDelayClas, p->nSatCalls ); + if ( Vec_IntSize(vMapping) > 0 ) + { + Gia_ManEdgeFromArray( p->pGia, vEdges2 ); + Vec_IntFree( vEdges2 ); + Vec_IntFreeP( &p->pGia->vMapping ); + p->pGia->vMapping = vMapping; + } + else + { + Vec_IntFree( vEdges2 ); + Vec_IntFree( vMapping ); + } + Vec_IntFreeP( &p->pGia->vPacking ); + Sle_ManStop( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaSatLut.c b/yosys/abc/src/aig/gia/giaSatLut.c new file mode 100644 index 00000000000..cc6068a9602 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaSatLut.c @@ -0,0 +1,2090 @@ +/**CFile**************************************************************** + + FileName [giaSatLut.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSatLut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/tim/tim.h" +#include "misc/util/utilTruth.h" +#include "sat/bsat/satStore.h" +#include "misc/util/utilNam.h" +#include "map/scl/sclCon.h" +#include "misc/vec/vecHsh.h" + +#ifdef _MSC_VER +#define unlink _unlink +#else +#include +#endif + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Sbl_Man_t_ Sbl_Man_t; +struct Sbl_Man_t_ +{ + sat_solver * pSat; // SAT solver + Vec_Int_t * vCardVars; // candinality variables + int nVars; // max vars + int LogN; // base-2 log of max vars + int Power2; // power-2 of LogN + int FirstVar; // first variable to be used + // statistics + int nTried; // nodes tried + int nImproved; // nodes improved + int nRuns; // the number of runs + int nHashWins; // the number of hashed windows + int nSmallWins; // the number of small windows + int nLargeWins; // the number of large windows + int nIterOuts; // the number of iters exceeded + // parameters + int LutSize; // LUT size + int nBTLimit; // conflicts + int DelayMax; // external delay + int nEdges; // the number of edges + int fDelay; // delay mode + int fReverse; // reverse windowing + int fVerbose; // verbose + int fVeryVerbose; // verbose + int fVeryVeryVerbose; // verbose + // window + Gia_Man_t * pGia; + Vec_Int_t * vLeaves; // leaf nodes + Vec_Int_t * vAnds; // AND-gates + Vec_Int_t * vNodes; // internal LUTs + Vec_Int_t * vRoots; // driver nodes (a subset of vAnds) + Vec_Int_t * vRootVars; // driver nodes (as SAT variables) + Hsh_VecMan_t * pHash; // hash table for windows + // timing + Vec_Int_t * vArrs; // arrival times + Vec_Int_t * vReqs; // required times + Vec_Wec_t * vWindow; // fanins of each node in the window + Vec_Int_t * vPath; // critical path (as SAT variables) + Vec_Int_t * vEdges; // fanin edges + // cuts + Vec_Wrd_t * vCutsI1; // input bit patterns + Vec_Wrd_t * vCutsI2; // input bit patterns + Vec_Wrd_t * vCutsN1; // node bit patterns + Vec_Wrd_t * vCutsN2; // node bit patterns + Vec_Int_t * vCutsNum; // cut counts for each obj + Vec_Int_t * vCutsStart; // starting cuts for each obj + Vec_Int_t * vCutsObj; // object to which this cut belongs + Vec_Wrd_t * vTempI1; // temporary cuts + Vec_Wrd_t * vTempI2; // temporary cuts + Vec_Wrd_t * vTempN1; // temporary cuts + Vec_Wrd_t * vTempN2; // temporary cuts + Vec_Int_t * vSolInit; // initial solution + Vec_Int_t * vSolCur; // current solution + Vec_Int_t * vSolBest; // best solution + // temporary + Vec_Int_t * vLits; // literals + Vec_Int_t * vAssump; // literals + Vec_Int_t * vPolar; // variables polarity + // statistics + abctime timeWin; // windowing + abctime timeCut; // cut computation + abctime timeSat; // SAT runtime + abctime timeSatSat; // satisfiable time + abctime timeSatUns; // unsatisfiable time + abctime timeSatUnd; // undecided time + abctime timeTime; // timing time + abctime timeStart; // starting time + abctime timeTotal; // all runtime + abctime timeOther; // other time +}; + +extern sat_solver * Sbm_AddCardinSolver( int LogN, Vec_Int_t ** pvVars ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Sbl_Man_t * Sbl_ManAlloc( Gia_Man_t * pGia, int Number ) +{ + Sbl_Man_t * p = ABC_CALLOC( Sbl_Man_t, 1 ); + p->nVars = Number; + p->LogN = Abc_Base2Log(Number); + p->Power2 = 1 << p->LogN; + p->pSat = Sbm_AddCardinSolver( p->LogN, &p->vCardVars ); + p->FirstVar = sat_solver_nvars( p->pSat ); + sat_solver_bookmark( p->pSat ); + // window + p->pGia = pGia; + p->vLeaves = Vec_IntAlloc( p->nVars ); + p->vAnds = Vec_IntAlloc( p->nVars ); + p->vNodes = Vec_IntAlloc( p->nVars ); + p->vRoots = Vec_IntAlloc( p->nVars ); + p->vRootVars = Vec_IntAlloc( p->nVars ); + p->pHash = Hsh_VecManStart( 1000 ); + // timing + p->vArrs = Vec_IntAlloc( 0 ); + p->vReqs = Vec_IntAlloc( 0 ); + p->vWindow = Vec_WecAlloc( 128 ); + p->vPath = Vec_IntAlloc( 32 ); + p->vEdges = Vec_IntAlloc( 32 ); + // cuts + p->vCutsI1 = Vec_WrdAlloc( 1000 ); // input bit patterns + p->vCutsI2 = Vec_WrdAlloc( 1000 ); // input bit patterns + p->vCutsN1 = Vec_WrdAlloc( 1000 ); // node bit patterns + p->vCutsN2 = Vec_WrdAlloc( 1000 ); // node bit patterns + p->vCutsNum = Vec_IntAlloc( 64 ); // cut counts for each obj + p->vCutsStart = Vec_IntAlloc( 64 ); // starting cuts for each obj + p->vCutsObj = Vec_IntAlloc( 1000 ); + p->vSolInit = Vec_IntAlloc( 64 ); + p->vSolCur = Vec_IntAlloc( 64 ); + p->vSolBest = Vec_IntAlloc( 64 ); + p->vTempI1 = Vec_WrdAlloc( 32 ); + p->vTempI2 = Vec_WrdAlloc( 32 ); + p->vTempN1 = Vec_WrdAlloc( 32 ); + p->vTempN2 = Vec_WrdAlloc( 32 ); + // internal + p->vLits = Vec_IntAlloc( 64 ); + p->vAssump = Vec_IntAlloc( 64 ); + p->vPolar = Vec_IntAlloc( 1000 ); + // other + Gia_ManFillValue( pGia ); + return p; +} +void Sbl_ManClean( Sbl_Man_t * p ) +{ + p->timeStart = Abc_Clock(); + sat_solver_rollback( p->pSat ); + sat_solver_bookmark( p->pSat ); + // internal + Vec_IntClear( p->vLeaves ); + Vec_IntClear( p->vAnds ); + Vec_IntClear( p->vNodes ); + Vec_IntClear( p->vRoots ); + Vec_IntClear( p->vRootVars ); + // timing + Vec_IntClear( p->vArrs ); + Vec_IntClear( p->vReqs ); + Vec_WecClear( p->vWindow ); + Vec_IntClear( p->vPath ); + Vec_IntClear( p->vEdges ); + // cuts + Vec_WrdClear( p->vCutsI1 ); + Vec_WrdClear( p->vCutsI2 ); + Vec_WrdClear( p->vCutsN1 ); + Vec_WrdClear( p->vCutsN2 ); + Vec_IntClear( p->vCutsNum ); + Vec_IntClear( p->vCutsStart ); + Vec_IntClear( p->vCutsObj ); + Vec_IntClear( p->vSolInit ); + Vec_IntClear( p->vSolCur ); + Vec_IntClear( p->vSolBest ); + Vec_WrdClear( p->vTempI1 ); + Vec_WrdClear( p->vTempI2 ); + Vec_WrdClear( p->vTempN1 ); + Vec_WrdClear( p->vTempN2 ); + // temporary + Vec_IntClear( p->vLits ); + Vec_IntClear( p->vAssump ); + Vec_IntClear( p->vPolar ); + // other + Gia_ManFillValue( p->pGia ); +} +void Sbl_ManStop( Sbl_Man_t * p ) +{ + sat_solver_delete( p->pSat ); + Vec_IntFree( p->vCardVars ); + // internal + Vec_IntFree( p->vLeaves ); + Vec_IntFree( p->vAnds ); + Vec_IntFree( p->vNodes ); + Vec_IntFree( p->vRoots ); + Vec_IntFree( p->vRootVars ); + Hsh_VecManStop( p->pHash ); + // timing + Vec_IntFree( p->vArrs ); + Vec_IntFree( p->vReqs ); + Vec_WecFree( p->vWindow ); + Vec_IntFree( p->vPath ); + Vec_IntFree( p->vEdges ); + // cuts + Vec_WrdFree( p->vCutsI1 ); + Vec_WrdFree( p->vCutsI2 ); + Vec_WrdFree( p->vCutsN1 ); + Vec_WrdFree( p->vCutsN2 ); + Vec_IntFree( p->vCutsNum ); + Vec_IntFree( p->vCutsStart ); + Vec_IntFree( p->vCutsObj ); + Vec_IntFree( p->vSolInit ); + Vec_IntFree( p->vSolCur ); + Vec_IntFree( p->vSolBest ); + Vec_WrdFree( p->vTempI1 ); + Vec_WrdFree( p->vTempI2 ); + Vec_WrdFree( p->vTempN1 ); + Vec_WrdFree( p->vTempN2 ); + // temporary + Vec_IntFree( p->vLits ); + Vec_IntFree( p->vAssump ); + Vec_IntFree( p->vPolar ); + // other + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [For each node in the window, create fanins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sbl_ManGetCurrentMapping( Sbl_Man_t * p ) +{ + Vec_Int_t * vObj; + word CutI1, CutI2, CutN1, CutN2; + int i, c, b, iObj; + Vec_WecClear( p->vWindow ); + Vec_WecInit( p->vWindow, Vec_IntSize(p->vAnds) ); + assert( Vec_IntSize(p->vSolCur) > 0 ); + Vec_IntForEachEntry( p->vSolCur, c, i ) + { + CutI1 = Vec_WrdEntry( p->vCutsI1, c ); + CutI2 = Vec_WrdEntry( p->vCutsI2, c ); + CutN1 = Vec_WrdEntry( p->vCutsN1, c ); + CutN2 = Vec_WrdEntry( p->vCutsN2, c ); + iObj = Vec_IntEntry( p->vCutsObj, c ); + //iObj = Vec_IntEntry( p->vAnds, iObj ); + vObj = Vec_WecEntry( p->vWindow, iObj ); + Vec_IntClear( vObj ); + assert( Vec_IntSize(vObj) == 0 ); + for ( b = 0; b < 64; b++ ) + if ( (CutI1 >> b) & 1 ) + Vec_IntPush( vObj, Vec_IntEntry(p->vLeaves, b) ); + for ( b = 0; b < 64; b++ ) + if ( (CutI2 >> b) & 1 ) + Vec_IntPush( vObj, Vec_IntEntry(p->vLeaves, 64+b) ); + for ( b = 0; b < 64; b++ ) + if ( (CutN1 >> b) & 1 ) + Vec_IntPush( vObj, Vec_IntEntry(p->vAnds, b) ); + for ( b = 0; b < 64; b++ ) + if ( (CutN2 >> b) & 1 ) + Vec_IntPush( vObj, Vec_IntEntry(p->vAnds, 64+b) ); + } +} + + +/**Function************************************************************* + + Synopsis [Timing computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sbl_ManComputeDelay( Sbl_Man_t * p, int iLut, Vec_Int_t * vFanins ) +{ + int k, iFan, Delay = 0; + Vec_IntForEachEntry( vFanins, iFan, k ) + Delay = Abc_MaxInt( Delay, Vec_IntEntry(p->vArrs, iFan) + 1 ); + return Delay; +} +int Sbl_ManCreateTiming( Sbl_Man_t * p, int DelayStart ) +{ + Vec_Int_t * vFanins; + int DelayMax = DelayStart, Delay, iLut, iFan, k; + // compute arrival times + Vec_IntFill( p->vArrs, Gia_ManObjNum(p->pGia), 0 ); + if ( p->pGia->pManTime != NULL && Tim_ManBoxNum((Tim_Man_t*)p->pGia->pManTime) ) + { + Gia_Obj_t * pObj; + Vec_Int_t * vNodes = Gia_ManOrderWithBoxes( p->pGia ); + Tim_ManIncrementTravId( (Tim_Man_t*)p->pGia->pManTime ); + Gia_ManForEachObjVec( vNodes, p->pGia, pObj, k ) + { + iLut = Gia_ObjId( p->pGia, pObj ); + if ( Gia_ObjIsAnd(pObj) ) + { + if ( Gia_ObjIsLut2(p->pGia, iLut) ) + { + vFanins = Gia_ObjLutFanins2(p->pGia, iLut); + Delay = Sbl_ManComputeDelay( p, iLut, vFanins ); + Vec_IntWriteEntry( p->vArrs, iLut, Delay ); + DelayMax = Abc_MaxInt( DelayMax, Delay ); + } + } + else if ( Gia_ObjIsCi(pObj) ) + { + int arrTime = Tim_ManGetCiArrival( (Tim_Man_t*)p->pGia->pManTime, Gia_ObjCioId(pObj) ); + Vec_IntWriteEntry( p->vArrs, iLut, arrTime ); + } + else if ( Gia_ObjIsCo(pObj) ) + { + int arrTime = Vec_IntEntry( p->vArrs, Gia_ObjFaninId0(pObj, iLut) ); + Tim_ManSetCoArrival( (Tim_Man_t*)p->pGia->pManTime, Gia_ObjCioId(pObj), arrTime ); + } + else if ( !Gia_ObjIsConst0(pObj) ) + assert( 0 ); + } + Vec_IntFree( vNodes ); + } + else + { + Gia_ManForEachLut2( p->pGia, iLut ) + { + vFanins = Gia_ObjLutFanins2(p->pGia, iLut); + Delay = Sbl_ManComputeDelay( p, iLut, vFanins ); + Vec_IntWriteEntry( p->vArrs, iLut, Delay ); + DelayMax = Abc_MaxInt( DelayMax, Delay ); + } + } + // compute required times + Vec_IntFill( p->vReqs, Gia_ManObjNum(p->pGia), ABC_INFINITY ); + Gia_ManForEachCoDriverId( p->pGia, iLut, k ) + Vec_IntDowndateEntry( p->vReqs, iLut, DelayMax ); + if ( p->pGia->pManTime != NULL && Tim_ManBoxNum((Tim_Man_t*)p->pGia->pManTime) ) + { + Gia_Obj_t * pObj; + Vec_Int_t * vNodes = Gia_ManOrderWithBoxes( p->pGia ); + Tim_ManIncrementTravId( (Tim_Man_t*)p->pGia->pManTime ); + Tim_ManInitPoRequiredAll( (Tim_Man_t*)p->pGia->pManTime, DelayMax ); + Gia_ManForEachObjVecReverse( vNodes, p->pGia, pObj, k ) + { + iLut = Gia_ObjId( p->pGia, pObj ); + if ( Gia_ObjIsAnd(pObj) ) + { + if ( Gia_ObjIsLut2(p->pGia, iLut) ) + { + Delay = Vec_IntEntry(p->vReqs, iLut) - 1; + vFanins = Gia_ObjLutFanins2(p->pGia, iLut); + Vec_IntForEachEntry( vFanins, iFan, k ) + Vec_IntDowndateEntry( p->vReqs, iFan, Delay ); + } + } + else if ( Gia_ObjIsCi(pObj) ) + { + int reqTime = Vec_IntEntry( p->vReqs, iLut ); + Tim_ManSetCiRequired( (Tim_Man_t*)p->pGia->pManTime, Gia_ObjCioId(pObj), reqTime ); + } + else if ( Gia_ObjIsCo(pObj) ) + { + int reqTime = Tim_ManGetCoRequired( (Tim_Man_t*)p->pGia->pManTime, Gia_ObjCioId(pObj) ); + Vec_IntWriteEntry( p->vReqs, Gia_ObjFaninId0(pObj, iLut), reqTime ); + } + else if ( !Gia_ObjIsConst0(pObj) ) + assert( 0 ); + } + Vec_IntFree( vNodes ); + } + else + { + Gia_ManForEachLut2Reverse( p->pGia, iLut ) + { + Delay = Vec_IntEntry(p->vReqs, iLut) - 1; + vFanins = Gia_ObjLutFanins2(p->pGia, iLut); + Vec_IntForEachEntry( vFanins, iFan, k ) + Vec_IntDowndateEntry( p->vReqs, iFan, Delay ); + } + } + return DelayMax; +} + + +/**Function************************************************************* + + Synopsis [Given mapping in p->vSolCur, check if mapping meets delay.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sbl_ManEvaluateMappingEdge( Sbl_Man_t * p, int DelayGlo ) +{ + abctime clk = Abc_Clock(); + Vec_Int_t * vArray; + int i, DelayMax; + Vec_IntClear( p->vPath ); + // update new timing + Sbl_ManGetCurrentMapping( p ); + // derive new timing + DelayMax = Gia_ManEvalWindow( p->pGia, p->vLeaves, p->vAnds, p->vWindow, p->vPolar, 1 ); + p->timeTime += Abc_Clock() - clk; + if ( DelayMax <= DelayGlo ) + return 1; + // create critical path composed of all nodes + Vec_WecForEachLevel( p->vWindow, vArray, i ) + if ( Vec_IntSize(vArray) > 0 ) + Vec_IntPush( p->vPath, Abc_Var2Lit(i, 1) ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Given mapping in p->vSolCur, check the critical path.] + + Description [Returns 1 if the mapping satisfies the timing. Returns 0, + if the critical path is detected.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sbl_ManCriticalFanin( Sbl_Man_t * p, int iLut, Vec_Int_t * vFanins ) +{ + int k, iFan, Delay = Vec_IntEntry(p->vArrs, iLut); + Vec_IntForEachEntry( vFanins, iFan, k ) + if ( Vec_IntEntry(p->vArrs, iFan) + 1 == Delay ) + return iFan; + return -1; +} +int Sbl_ManEvaluateMapping( Sbl_Man_t * p, int DelayGlo ) +{ + abctime clk = Abc_Clock(); + Vec_Int_t * vFanins; + int i, iLut = -1, iAnd, Delay, Required; + if ( p->pGia->vEdge1 ) + return Sbl_ManEvaluateMappingEdge( p, DelayGlo ); + Vec_IntClear( p->vPath ); + // derive timing + Sbl_ManCreateTiming( p, DelayGlo ); + // update new timing + Sbl_ManGetCurrentMapping( p ); + Vec_IntForEachEntry( p->vAnds, iLut, i ) + { + vFanins = Vec_WecEntry( p->vWindow, i ); + Delay = Sbl_ManComputeDelay( p, iLut, vFanins ); + Vec_IntWriteEntry( p->vArrs, iLut, Delay ); + } + // compare timing at the root nodes + Vec_IntForEachEntry( p->vRoots, iLut, i ) + { + Delay = Vec_IntEntry( p->vArrs, iLut ); + Required = Vec_IntEntry( p->vReqs, iLut ); + if ( Delay > Required ) // updated timing exceeded original timing + break; + } + p->timeTime += Abc_Clock() - clk; + if ( i == Vec_IntSize(p->vRoots) ) + return 1; + // derive the critical path + + // find SAT variable of the node whose GIA ID is "iLut" + iAnd = Vec_IntFind( p->vAnds, iLut ); + assert( iAnd >= 0 ); + // critical path begins in node "iLut", which is i-th root of the window + assert( iAnd == Vec_IntEntry(p->vRootVars, i) ); + while ( 1 ) + { + Vec_IntPush( p->vPath, Abc_Var2Lit(iAnd, 1) ); + // find fanins of this node + vFanins = Vec_WecEntry( p->vWindow, iAnd ); + // find critical fanin + iLut = Sbl_ManCriticalFanin( p, iLut, vFanins ); + assert( iLut > 0 ); + // find SAT variable of the node whose GIA ID is "iLut" + iAnd = Vec_IntFind( p->vAnds, iLut ); + if ( iAnd == -1 ) + break; + } + return 0; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Sbl_ManUpdateMapping( Sbl_Man_t * p ) +{ +// Gia_Obj_t * pObj; + Vec_Int_t * vObj; + word CutI1, CutI2, CutN1, CutN2; + int i, c, b, iObj, iTemp; + assert( Vec_IntSize(p->vSolBest) < Vec_IntSize(p->vSolInit) ); + Vec_IntForEachEntry( p->vAnds, iObj, i ) + { + vObj = Vec_WecEntry(p->pGia->vMapping2, iObj); + Vec_IntForEachEntry( vObj, iTemp, b ) + Gia_ObjLutRefDecId( p->pGia, iTemp ); + Vec_IntClear( vObj ); + } + Vec_IntForEachEntry( p->vSolBest, c, i ) + { + CutI1 = Vec_WrdEntry( p->vCutsI1, c ); + CutI2 = Vec_WrdEntry( p->vCutsI2, c ); + CutN1 = Vec_WrdEntry( p->vCutsN1, c ); + CutN2 = Vec_WrdEntry( p->vCutsN2, c ); + iObj = Vec_IntEntry( p->vCutsObj, c ); + iObj = Vec_IntEntry( p->vAnds, iObj ); + vObj = Vec_WecEntry( p->pGia->vMapping2, iObj ); + Vec_IntClear( vObj ); + assert( Vec_IntSize(vObj) == 0 ); + for ( b = 0; b < 64; b++ ) + if ( (CutI1 >> b) & 1 ) + Vec_IntPush( vObj, Vec_IntEntry(p->vLeaves, b) ); + for ( b = 0; b < 64; b++ ) + if ( (CutI2 >> b) & 1 ) + Vec_IntPush( vObj, Vec_IntEntry(p->vLeaves, 64+b) ); + for ( b = 0; b < 64; b++ ) + if ( (CutN1 >> b) & 1 ) + Vec_IntPush( vObj, Vec_IntEntry(p->vAnds, b) ); + for ( b = 0; b < 64; b++ ) + if ( (CutN2 >> b) & 1 ) + Vec_IntPush( vObj, Vec_IntEntry(p->vAnds, 64+b) ); + Vec_IntForEachEntry( vObj, iTemp, b ) + Gia_ObjLutRefIncId( p->pGia, iTemp ); + } +/* + // verify + Gia_ManForEachLut2Vec( p->pGia, vObj, i ) + Vec_IntForEachEntry( vObj, iTemp, b ) + Gia_ObjLutRefDecId( p->pGia, iTemp ); + Gia_ManForEachCo( p->pGia, pObj, i ) + Gia_ObjLutRefDecId( p->pGia, Gia_ObjFaninId0p(p->pGia, pObj) ); + + for ( i = 0; i < Gia_ManObjNum(p->pGia); i++ ) + if ( p->pGia->pLutRefs[i] ) + printf( "Object %d has %d refs\n", i, p->pGia->pLutRefs[i] ); + + Gia_ManForEachCo( p->pGia, pObj, i ) + Gia_ObjLutRefIncId( p->pGia, Gia_ObjFaninId0p(p->pGia, pObj) ); + Gia_ManForEachLut2Vec( p->pGia, vObj, i ) + Vec_IntForEachEntry( vObj, iTemp, b ) + Gia_ObjLutRefIncId( p->pGia, iTemp ); +*/ +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Sbl_ManPrintCut( word CutI1, word CutI2, word CutN1, word CutN2 ) +{ + int b, Count = 0; + printf( "{ " ); + for ( b = 0; b < 64; b++ ) + if ( (CutI1 >> b) & 1 ) + printf( "i%d ", b ), Count++; + for ( b = 0; b < 64; b++ ) + if ( (CutI2 >> b) & 1 ) + printf( "i%d ", 64+b ), Count++; + printf( " " ); + for ( b = 0; b < 64; b++ ) + if ( (CutN1 >> b) & 1 ) + printf( "n%d ", b ), Count++; + for ( b = 0; b < 64; b++ ) + if ( (CutN2 >> b) & 1 ) + printf( "n%d ", 64+b ), Count++; + printf( "};\n" ); + return Count; +} +static int Sbl_ManFindAndPrintCut( Sbl_Man_t * p, int c ) +{ + return Sbl_ManPrintCut( Vec_WrdEntry(p->vCutsI1, c), Vec_WrdEntry(p->vCutsI2, c), Vec_WrdEntry(p->vCutsN1, c), Vec_WrdEntry(p->vCutsN2, c) ); +} +static inline int Sbl_CutIsFeasible( word CutI1, word CutI2, word CutN1, word CutN2, int LutSize ) +{ + int Count = (CutI1 != 0) + (CutI2 != 0) + (CutN1 != 0) + (CutN2 != 0); + assert( LutSize <= 6 ); + CutI1 &= CutI1-1; CutI2 &= CutI2-1; CutN1 &= CutN1-1; CutN2 &= CutN2-1; Count += (CutI1 != 0) + (CutI2 != 0) + (CutN1 != 0) + (CutN2 != 0); + CutI1 &= CutI1-1; CutI2 &= CutI2-1; CutN1 &= CutN1-1; CutN2 &= CutN2-1; Count += (CutI1 != 0) + (CutI2 != 0) + (CutN1 != 0) + (CutN2 != 0); + CutI1 &= CutI1-1; CutI2 &= CutI2-1; CutN1 &= CutN1-1; CutN2 &= CutN2-1; Count += (CutI1 != 0) + (CutI2 != 0) + (CutN1 != 0) + (CutN2 != 0); + CutI1 &= CutI1-1; CutI2 &= CutI2-1; CutN1 &= CutN1-1; CutN2 &= CutN2-1; Count += (CutI1 != 0) + (CutI2 != 0) + (CutN1 != 0) + (CutN2 != 0); + if ( LutSize <= 4 ) + return Count <= 4; + CutI1 &= CutI1-1; CutI2 &= CutI2-1; CutN1 &= CutN1-1; CutN2 &= CutN2-1; Count += (CutI1 != 0) + (CutI2 != 0) + (CutN1 != 0) + (CutN2 != 0); + CutI1 &= CutI1-1; CutI2 &= CutI2-1; CutN1 &= CutN1-1; CutN2 &= CutN2-1; Count += (CutI1 != 0) + (CutI2 != 0) + (CutN1 != 0) + (CutN2 != 0); + return Count <= 6; +} +static inline int Sbl_CutPushUncontained( Vec_Wrd_t * vCutsI1, Vec_Wrd_t * vCutsI2, Vec_Wrd_t * vCutsN1, Vec_Wrd_t * vCutsN2, word CutI1, word CutI2, word CutN1, word CutN2 ) +{ + int i, k = 0; + assert( vCutsI1->nSize == vCutsN1->nSize ); + assert( vCutsI2->nSize == vCutsN2->nSize ); + for ( i = 0; i < vCutsI1->nSize; i++ ) + if ( (vCutsI1->pArray[i] & CutI1) == vCutsI1->pArray[i] && + (vCutsI2->pArray[i] & CutI2) == vCutsI2->pArray[i] && + (vCutsN1->pArray[i] & CutN1) == vCutsN1->pArray[i] && + (vCutsN2->pArray[i] & CutN2) == vCutsN2->pArray[i] ) + return 1; + for ( i = 0; i < vCutsI1->nSize; i++ ) + if ( (vCutsI1->pArray[i] & CutI1) != CutI1 || + (vCutsI2->pArray[i] & CutI2) != CutI2 || + (vCutsN1->pArray[i] & CutN1) != CutN1 || + (vCutsN2->pArray[i] & CutN2) != CutN2 ) + { + Vec_WrdWriteEntry( vCutsI1, k, vCutsI1->pArray[i] ); + Vec_WrdWriteEntry( vCutsI2, k, vCutsI2->pArray[i] ); + Vec_WrdWriteEntry( vCutsN1, k, vCutsN1->pArray[i] ); + Vec_WrdWriteEntry( vCutsN2, k, vCutsN2->pArray[i] ); + k++; + } + Vec_WrdShrink( vCutsI1, k ); + Vec_WrdShrink( vCutsI2, k ); + Vec_WrdShrink( vCutsN1, k ); + Vec_WrdShrink( vCutsN2, k ); + Vec_WrdPush( vCutsI1, CutI1 ); + Vec_WrdPush( vCutsI2, CutI2 ); + Vec_WrdPush( vCutsN1, CutN1 ); + Vec_WrdPush( vCutsN2, CutN2 ); + return 0; +} +static inline void Sbl_ManComputeCutsOne( Sbl_Man_t * p, int Fan0, int Fan1, int Obj ) +{ + word * pCutsI1 = Vec_WrdArray(p->vCutsI1); + word * pCutsI2 = Vec_WrdArray(p->vCutsI2); + word * pCutsN1 = Vec_WrdArray(p->vCutsN1); + word * pCutsN2 = Vec_WrdArray(p->vCutsN2); + int Start0 = Vec_IntEntry( p->vCutsStart, Fan0 ); + int Start1 = Vec_IntEntry( p->vCutsStart, Fan1 ); + int Limit0 = Start0 + Vec_IntEntry( p->vCutsNum, Fan0 ); + int Limit1 = Start1 + Vec_IntEntry( p->vCutsNum, Fan1 ); + int i, k; + assert( Obj >= 0 && Obj < 128 ); + Vec_WrdClear( p->vTempI1 ); + Vec_WrdClear( p->vTempI2 ); + Vec_WrdClear( p->vTempN1 ); + Vec_WrdClear( p->vTempN2 ); + for ( i = Start0; i < Limit0; i++ ) + for ( k = Start1; k < Limit1; k++ ) + if ( Sbl_CutIsFeasible(pCutsI1[i] | pCutsI1[k], pCutsI2[i] | pCutsI2[k], pCutsN1[i] | pCutsN1[k], pCutsN2[i] | pCutsN2[k], p->LutSize) ) + Sbl_CutPushUncontained( p->vTempI1, p->vTempI2, p->vTempN1, p->vTempN2, pCutsI1[i] | pCutsI1[k], pCutsI2[i] | pCutsI2[k], pCutsN1[i] | pCutsN1[k], pCutsN2[i] | pCutsN2[k] ); + Vec_IntPush( p->vCutsStart, Vec_WrdSize(p->vCutsI1) ); + Vec_IntPush( p->vCutsNum, Vec_WrdSize(p->vTempI1) + 1 ); + Vec_WrdAppend( p->vCutsI1, p->vTempI1 ); + Vec_WrdAppend( p->vCutsI2, p->vTempI2 ); + Vec_WrdAppend( p->vCutsN1, p->vTempN1 ); + Vec_WrdAppend( p->vCutsN2, p->vTempN2 ); + Vec_WrdPush( p->vCutsI1, 0 ); + Vec_WrdPush( p->vCutsI2, 0 ); + if ( Obj < 64 ) + { + Vec_WrdPush( p->vCutsN1, (((word)1) << Obj) ); + Vec_WrdPush( p->vCutsN2, 0 ); + } + else + { + Vec_WrdPush( p->vCutsN1, 0 ); + Vec_WrdPush( p->vCutsN2, (((word)1) << (Obj-64)) ); + } + for ( i = 0; i <= Vec_WrdSize(p->vTempI1); i++ ) + Vec_IntPush( p->vCutsObj, Obj ); +} +static inline int Sbl_ManFindCut( Sbl_Man_t * p, int Obj, word CutI1, word CutI2, word CutN1, word CutN2 ) +{ + word * pCutsI1 = Vec_WrdArray(p->vCutsI1); + word * pCutsI2 = Vec_WrdArray(p->vCutsI2); + word * pCutsN1 = Vec_WrdArray(p->vCutsN1); + word * pCutsN2 = Vec_WrdArray(p->vCutsN2); + int Start0 = Vec_IntEntry( p->vCutsStart, Obj ); + int Limit0 = Start0 + Vec_IntEntry( p->vCutsNum, Obj ); + int i; + //printf( "\nLooking for:\n" ); + //Sbl_ManPrintCut( CutI, CutN ); + //printf( "\n" ); + for ( i = Start0; i < Limit0; i++ ) + { + //Sbl_ManPrintCut( pCutsI[i], pCutsN[i] ); + if ( pCutsI1[i] == CutI1 && pCutsI2[i] == CutI2 && pCutsN1[i] == CutN1 && pCutsN2[i] == CutN2 ) + return i; + } + return -1; +} +int Sbl_ManComputeCuts( Sbl_Man_t * p ) +{ + abctime clk = Abc_Clock(); + Gia_Obj_t * pObj; Vec_Int_t * vFanins; + int i, k, Index, Fanin, nObjs = Vec_IntSize(p->vLeaves) + Vec_IntSize(p->vAnds); + assert( Vec_IntSize(p->vLeaves) <= 128 && Vec_IntSize(p->vAnds) <= p->nVars ); + // assign leaf cuts + Vec_IntClear( p->vCutsStart ); + Vec_IntClear( p->vCutsObj ); + Vec_IntClear( p->vCutsNum ); + Vec_WrdClear( p->vCutsI1 ); + Vec_WrdClear( p->vCutsI2 ); + Vec_WrdClear( p->vCutsN1 ); + Vec_WrdClear( p->vCutsN2 ); + Gia_ManForEachObjVec( p->vLeaves, p->pGia, pObj, i ) + { + Vec_IntPush( p->vCutsStart, Vec_WrdSize(p->vCutsI1) ); + Vec_IntPush( p->vCutsObj, -1 ); + Vec_IntPush( p->vCutsNum, 1 ); + if ( i < 64 ) + { + Vec_WrdPush( p->vCutsI1, (((word)1) << i) ); + Vec_WrdPush( p->vCutsI2, 0 ); + } + else + { + Vec_WrdPush( p->vCutsI1, 0 ); + Vec_WrdPush( p->vCutsI2, (((word)1) << (i-64)) ); + } + Vec_WrdPush( p->vCutsN1, 0 ); + Vec_WrdPush( p->vCutsN2, 0 ); + pObj->Value = i; + } + // assign internal cuts + Gia_ManForEachObjVec( p->vAnds, p->pGia, pObj, i ) + { + assert( Gia_ObjIsAnd(pObj) ); + assert( ~Gia_ObjFanin0(pObj)->Value ); + assert( ~Gia_ObjFanin1(pObj)->Value ); + Sbl_ManComputeCutsOne( p, Gia_ObjFanin0(pObj)->Value, Gia_ObjFanin1(pObj)->Value, i ); + pObj->Value = Vec_IntSize(p->vLeaves) + i; + } + assert( Vec_IntSize(p->vCutsStart) == nObjs ); + assert( Vec_IntSize(p->vCutsNum) == nObjs ); + assert( Vec_WrdSize(p->vCutsI1) == Vec_WrdSize(p->vCutsN1) ); + assert( Vec_WrdSize(p->vCutsI2) == Vec_WrdSize(p->vCutsN2) ); + assert( Vec_WrdSize(p->vCutsI1) == Vec_IntSize(p->vCutsObj) ); + // check that roots are mapped nodes + Vec_IntClear( p->vRootVars ); + Gia_ManForEachObjVec( p->vRoots, p->pGia, pObj, i ) + { + int Obj = Gia_ObjId(p->pGia, pObj); + if ( Gia_ObjIsCi(pObj) ) + continue; + assert( Gia_ObjIsLut2(p->pGia, Obj) ); + assert( ~pObj->Value ); + Vec_IntPush( p->vRootVars, pObj->Value - Vec_IntSize(p->vLeaves) ); + } + // create current solution + Vec_IntClear( p->vPolar ); + Vec_IntClear( p->vSolInit ); + Gia_ManForEachObjVec( p->vAnds, p->pGia, pObj, i ) + { + word CutI1 = 0, CutI2 = 0, CutN1 = 0, CutN2 = 0; + int Obj = Gia_ObjId(p->pGia, pObj); + if ( !Gia_ObjIsLut2(p->pGia, Obj) ) + continue; + assert( (int)pObj->Value == Vec_IntSize(p->vLeaves) + i ); + // add node + Vec_IntPush( p->vPolar, i ); + Vec_IntPush( p->vSolInit, i ); + // add its cut + //Gia_LutForEachFaninObj( p->pGia, Obj, pFanin, k ) + vFanins = Gia_ObjLutFanins2( p->pGia, Obj ); + Vec_IntForEachEntry( vFanins, Fanin, k ) + { + Gia_Obj_t * pFanin = Gia_ManObj( p->pGia, Fanin ); + assert( (int)pFanin->Value < Vec_IntSize(p->vLeaves) || Gia_ObjIsLut2(p->pGia, Fanin) ); +// if ( ~pFanin->Value == 0 ) +// Gia_ManPrintConeMulti( p->pGia, p->vAnds, p->vLeaves, p->vPath ); + if ( ~pFanin->Value == 0 ) + continue; + assert( ~pFanin->Value ); + if ( (int)pFanin->Value < Vec_IntSize(p->vLeaves) ) + { + if ( (int)pFanin->Value < 64 ) + CutI1 |= ((word)1 << pFanin->Value); + else + CutI2 |= ((word)1 << (pFanin->Value - 64)); + } + else + { + if ( pFanin->Value - Vec_IntSize(p->vLeaves) < 64 ) + CutN1 |= ((word)1 << (pFanin->Value - Vec_IntSize(p->vLeaves))); + else + CutN2 |= ((word)1 << (pFanin->Value - Vec_IntSize(p->vLeaves) - 64)); + } + } + // find the new cut + Index = Sbl_ManFindCut( p, Vec_IntSize(p->vLeaves) + i, CutI1, CutI2, CutN1, CutN2 ); + if ( Index < 0 ) + { + //printf( "Cannot find the available cut.\n" ); + continue; + } + assert( Index >= 0 ); + Vec_IntPush( p->vPolar, p->FirstVar+Index ); + } + // clean value + Gia_ManForEachObjVec( p->vLeaves, p->pGia, pObj, i ) + pObj->Value = ~0; + Gia_ManForEachObjVec( p->vAnds, p->pGia, pObj, i ) + pObj->Value = ~0; + p->timeCut += Abc_Clock() - clk; + return Vec_WrdSize(p->vCutsI1); +} +int Sbl_ManCreateCnf( Sbl_Man_t * p ) +{ + int i, k, c, pLits[2], value; + word * pCutsN1 = Vec_WrdArray(p->vCutsN1); + word * pCutsN2 = Vec_WrdArray(p->vCutsN2); + assert( p->FirstVar == sat_solver_nvars(p->pSat) ); + sat_solver_setnvars( p->pSat, sat_solver_nvars(p->pSat) + Vec_WrdSize(p->vCutsI1) ); + //printf( "\n" ); + for ( i = 0; i < Vec_IntSize(p->vAnds); i++ ) + { + int Start0 = Vec_IntEntry( p->vCutsStart, Vec_IntSize(p->vLeaves) + i ); + int Limit0 = Start0 + Vec_IntEntry( p->vCutsNum, Vec_IntSize(p->vLeaves) + i ) - 1; + // add main clause + Vec_IntClear( p->vLits ); + Vec_IntPush( p->vLits, Abc_Var2Lit(i, 1) ); + //printf( "Node %d implies cuts: ", i ); + for ( k = Start0; k < Limit0; k++ ) + { + Vec_IntPush( p->vLits, Abc_Var2Lit(p->FirstVar+k, 0) ); + //printf( "%d ", p->FirstVar+k ); + } + //printf( "\n" ); + value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntLimit(p->vLits) ); + assert( value ); + // binary clauses + for ( k = Start0; k < Limit0; k++ ) + { + word Cut1 = pCutsN1[k]; + word Cut2 = pCutsN2[k]; + //printf( "Cut %d implies root node %d.\n", p->FirstVar+k, i ); + // root clause + pLits[0] = Abc_Var2Lit( p->FirstVar+k, 1 ); + pLits[1] = Abc_Var2Lit( i, 0 ); + value = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( value ); + // fanin clauses + for ( c = 0; c < 64 && Cut1; c++, Cut1 >>= 1 ) + { + if ( (Cut1 & 1) == 0 ) + continue; + //printf( "Cut %d implies fanin %d.\n", p->FirstVar+k, c ); + pLits[1] = Abc_Var2Lit( c, 0 ); + value = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( value ); + } + for ( c = 0; c < 64 && Cut2; c++, Cut2 >>= 1 ) + { + if ( (Cut2 & 1) == 0 ) + continue; + //printf( "Cut %d implies fanin %d.\n", p->FirstVar+k, c ); + pLits[1] = Abc_Var2Lit( c+64, 0 ); + value = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( value ); + } + } + } + sat_solver_set_polarity( p->pSat, Vec_IntArray(p->vPolar), Vec_IntSize(p->vPolar) ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +void Sbl_ManWindow( Sbl_Man_t * p ) +{ + int i, ObjId; + // collect leaves + Vec_IntClear( p->vLeaves ); + Gia_ManForEachCiId( p->pGia, ObjId, i ) + Vec_IntPush( p->vLeaves, ObjId ); + // collect internal + Vec_IntClear( p->vAnds ); + Gia_ManForEachAndId( p->pGia, ObjId ) + Vec_IntPush( p->vAnds, ObjId ); + // collect roots + Vec_IntClear( p->vRoots ); + Gia_ManForEachCoDriverId( p->pGia, ObjId, i ) + Vec_IntPush( p->vRoots, ObjId ); +} + +int Sbl_ManWindow2( Sbl_Man_t * p, int iPivot ) +{ + abctime clk = Abc_Clock(); + Vec_Int_t * vRoots, * vNodes, * vLeaves, * vAnds; + int Count = Gia_ManComputeOneWin( p->pGia, iPivot, &vRoots, &vNodes, &vLeaves, &vAnds ); + p->timeWin += Abc_Clock() - clk; + if ( Count == 0 ) + return 0; + Vec_IntClear( p->vRoots ); Vec_IntAppend( p->vRoots, vRoots ); + Vec_IntClear( p->vNodes ); Vec_IntAppend( p->vNodes, vNodes ); + Vec_IntClear( p->vLeaves ); Vec_IntAppend( p->vLeaves, vLeaves ); + Vec_IntClear( p->vAnds ); Vec_IntAppend( p->vAnds, vAnds ); +//Vec_IntPrint( vRoots ); +//Vec_IntPrint( vAnds ); +//Vec_IntPrint( vLeaves ); + // recompute internal nodes +// Gia_ManIncrementTravId( p->pGia ); +// Gia_ManCollectAnds( p->pGia, Vec_IntArray(p->vRoots), Vec_IntSize(p->vRoots), p->vAnds, p->vLeaves ); + return Count; +} + +int Sbl_ManTestSat( Sbl_Man_t * p, int iPivot ) +{ + int fKeepTrying = 1; + abctime clk = Abc_Clock(), clk2; + int i, status, Root, Count, StartSol, nConfTotal = 0, nIters = 0; + int nEntries = Hsh_VecSize( p->pHash ); + p->nTried++; + + Sbl_ManClean( p ); + + // compute one window + Count = Sbl_ManWindow2( p, iPivot ); + if ( Count == 0 ) + { + if ( p->fVeryVerbose ) + printf( "Obj %d: Window with less than %d nodes does not exist.\n", iPivot, p->nVars ); + p->nSmallWins++; + return 0; + } + Hsh_VecManAdd( p->pHash, p->vAnds ); + if ( nEntries == Hsh_VecSize(p->pHash) ) + { + if ( p->fVeryVerbose ) + printf( "Obj %d: This window was already tried.\n", iPivot ); + p->nHashWins++; + return 0; + } + if ( p->fVeryVerbose ) + printf( "\nObj = %6d : Leaf = %2d. AND = %2d. Root = %2d. LUT = %2d.\n", + iPivot, Vec_IntSize(p->vLeaves), Vec_IntSize(p->vAnds), Vec_IntSize(p->vRoots), Vec_IntSize(p->vNodes) ); + + if ( Vec_IntSize(p->vLeaves) > 128 || Vec_IntSize(p->vAnds) > p->nVars ) + { + if ( p->fVeryVerbose ) + printf( "Obj %d: Encountered window with %d inputs and %d internal nodes.\n", iPivot, Vec_IntSize(p->vLeaves), Vec_IntSize(p->vAnds) ); + p->nLargeWins++; + return 0; + } + if ( Vec_IntSize(p->vAnds) < 10 ) + { + if ( p->fVeryVerbose ) + printf( "Skipping.\n" ); + return 0; + } + + // derive cuts + Sbl_ManComputeCuts( p ); + // derive SAT instance + Sbl_ManCreateCnf( p ); + + if ( p->fVeryVeryVerbose ) + printf( "All clauses = %d. Multi clauses = %d. Binary clauses = %d. Other clauses = %d.\n\n", + sat_solver_nclauses(p->pSat), Vec_IntSize(p->vAnds), Vec_WrdSize(p->vCutsI1) - Vec_IntSize(p->vAnds), + sat_solver_nclauses(p->pSat) - Vec_WrdSize(p->vCutsI1) ); + + // create assumptions + // cardinality + Vec_IntClear( p->vAssump ); + Vec_IntPush( p->vAssump, -1 ); + // unused variables + for ( i = Vec_IntSize(p->vAnds); i < p->Power2; i++ ) + Vec_IntPush( p->vAssump, Abc_Var2Lit(i, 1) ); + // root variables + Vec_IntForEachEntry( p->vRootVars, Root, i ) + Vec_IntPush( p->vAssump, Abc_Var2Lit(Root, 0) ); +// Vec_IntPrint( p->vAssump ); + + StartSol = Vec_IntSize(p->vSolInit) + 1; +// StartSol = 30; + while ( fKeepTrying && StartSol-fKeepTrying > 0 ) + { + int Count = 0, LitCount = 0; + int nConfBef, nConfAft; + if ( p->fVeryVerbose ) + printf( "Trying to find mapping with %d LUTs.\n", StartSol-fKeepTrying ); + // for ( i = Vec_IntSize(p->vSolInit)-5; i < nVars; i++ ) + // Vec_IntPush( p->vAssump, Abc_Var2Lit(Vec_IntEntry(p->vCardVars, i), 1) ); + Vec_IntWriteEntry( p->vAssump, 0, Abc_Var2Lit(Vec_IntEntry(p->vCardVars, StartSol-fKeepTrying), 1) ); + // solve the problem + clk2 = Abc_Clock(); + nConfBef = (int)p->pSat->stats.conflicts; + status = sat_solver_solve( p->pSat, Vec_IntArray(p->vAssump), Vec_IntLimit(p->vAssump), p->nBTLimit, 0, 0, 0 ); + p->timeSat += Abc_Clock() - clk2; + nConfAft = (int)p->pSat->stats.conflicts; + nConfTotal += nConfAft - nConfBef; + nIters++; + p->nRuns++; + if ( status == l_True ) + p->timeSatSat += Abc_Clock() - clk2; + else if ( status == l_False ) + p->timeSatUns += Abc_Clock() - clk2; + else + p->timeSatUnd += Abc_Clock() - clk2; + if ( status == l_Undef ) + break; + if ( status == l_True ) + { + if ( p->fVeryVeryVerbose ) + { + for ( i = 0; i < Vec_IntSize(p->vAnds); i++ ) + printf( "%d", sat_solver_var_value(p->pSat, i) ); + printf( "\n" ); + for ( i = 0; i < Vec_IntSize(p->vAnds); i++ ) + if ( sat_solver_var_value(p->pSat, i) ) + { + printf( "%d=%d ", i, sat_solver_var_value(p->pSat, i) ); + Count++; + } + printf( "Count = %d\n", Count ); + } +// for ( i = p->FirstVar; i < sat_solver_nvars(p->pSat); i++ ) +// printf( "%d", sat_solver_var_value(p->pSat, i) ); +// printf( "\n" ); + Count = 1; + Vec_IntClear( p->vSolCur ); + for ( i = p->FirstVar; i < sat_solver_nvars(p->pSat); i++ ) + if ( sat_solver_var_value(p->pSat, i) ) + { + if ( p->fVeryVeryVerbose ) + printf( "Cut %3d : Node = %3d %6d ", Count++, Vec_IntEntry(p->vCutsObj, i-p->FirstVar), Vec_IntEntry(p->vAnds, Vec_IntEntry(p->vCutsObj, i-p->FirstVar)) ); + if ( p->fVeryVeryVerbose ) + LitCount += Sbl_ManFindAndPrintCut( p, i-p->FirstVar ); + Vec_IntPush( p->vSolCur, i-p->FirstVar ); + } + //Vec_IntPrint( p->vRootVars ); + //Vec_IntPrint( p->vRoots ); + //Vec_IntPrint( p->vAnds ); + //Vec_IntPrint( p->vLeaves ); + } + +// fKeepTrying = status == l_True ? fKeepTrying + 1 : 0; + // check the timing + if ( status == l_True ) + { + if ( p->fDelay && !Sbl_ManEvaluateMapping(p, p->DelayMax) ) + { + int iLit, value; + if ( p->fVeryVerbose ) + { + printf( "Critical path of length (%d) is detected: ", Vec_IntSize(p->vPath) ); + Vec_IntForEachEntry( p->vPath, iLit, i ) + printf( "%d=%d ", i, Vec_IntEntry(p->vAnds, Abc_Lit2Var(iLit)) ); + printf( "\n" ); + } + // add the clause + value = sat_solver_addclause( p->pSat, Vec_IntArray(p->vPath), Vec_IntLimit(p->vPath) ); + assert( value ); + } + else + { + Vec_IntClear( p->vSolBest ); + Vec_IntAppend( p->vSolBest, p->vSolCur ); + fKeepTrying++; + } + } + else + fKeepTrying = 0; + if ( p->fVeryVerbose ) + { + if ( status == l_False ) + printf( "UNSAT " ); + else if ( status == l_True ) + printf( "SAT " ); + else + printf( "UNDEC " ); + printf( "confl =%8d. ", nConfAft - nConfBef ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk2 ); + + printf( "Total " ); + printf( "confl =%8d. ", nConfTotal ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + if ( p->fVeryVeryVerbose && status == l_True ) + printf( "LitCount = %d.\n", LitCount ); + printf( "\n" ); + } + if ( nIters == 10 ) + { + p->nIterOuts++; + //printf( "Obj %d : Quitting after %d iterations.\n", iPivot, nIters ); + break; + } + } + + // update solution + if ( Vec_IntSize(p->vSolBest) > 0 && Vec_IntSize(p->vSolBest) < Vec_IntSize(p->vSolInit) ) + { + int nDelayCur, nEdgesCur = 0; + Sbl_ManUpdateMapping( p ); + if ( p->pGia->vEdge1 ) + { + nDelayCur = Gia_ManEvalEdgeDelay( p->pGia ); + nEdgesCur = Gia_ManEvalEdgeCount( p->pGia ); + } + else + nDelayCur = Sbl_ManCreateTiming( p, p->DelayMax ); + if ( p->fVerbose ) + printf( "Object %5d : Saved %2d nodes (Conf =%8d) Iter =%3d Delay = %d Edges = %4d\n", + iPivot, Vec_IntSize(p->vSolInit)-Vec_IntSize(p->vSolBest), nConfTotal, nIters, nDelayCur, nEdgesCur ); + p->timeTotal += Abc_Clock() - p->timeStart; + p->nImproved++; + return 2; + } + else + { +// printf( "Object %5d : Saved %2d nodes (Conf =%8d) Iter =%3d\n", iPivot, 0, nConfTotal, nIters ); + } + p->timeTotal += Abc_Clock() - p->timeStart; + return 1; +} +void Sbl_ManPrintRuntime( Sbl_Man_t * p ) +{ + printf( "Runtime breakdown:\n" ); + p->timeOther = p->timeTotal - p->timeWin - p->timeCut - p->timeSat - p->timeTime; + ABC_PRTP( "Win ", p->timeWin , p->timeTotal ); + ABC_PRTP( "Cut ", p->timeCut , p->timeTotal ); + ABC_PRTP( "Sat ", p->timeSat, p->timeTotal ); + ABC_PRTP( " Sat ", p->timeSatSat, p->timeTotal ); + ABC_PRTP( " Unsat", p->timeSatUns, p->timeTotal ); + ABC_PRTP( " Undec", p->timeSatUnd, p->timeTotal ); + ABC_PRTP( "Timing", p->timeTime , p->timeTotal ); + ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); + ABC_PRTP( "ALL ", p->timeTotal, p->timeTotal ); +} +void Gia_ManLutSat( Gia_Man_t * pGia, int LutSize, int nNumber, int nImproves, int nBTLimit, int DelayMax, int nEdges, int fDelay, int fReverse, int fVerbose, int fVeryVerbose ) +{ + int iLut, nImproveCount = 0; + Sbl_Man_t * p = Sbl_ManAlloc( pGia, nNumber ); + p->LutSize = LutSize; // LUT size + p->nBTLimit = nBTLimit; // conflicts + p->DelayMax = DelayMax; // external delay + p->nEdges = nEdges; // the number of edges + p->fDelay = fDelay; // delay mode + p->fReverse = fReverse; // reverse windowing + p->fVerbose = fVerbose | fVeryVerbose; + p->fVeryVerbose = fVeryVerbose; + if ( p->fVerbose ) + printf( "Parameters: WinSize = %d AIG nodes. Conf = %d. DelayMax = %d.\n", p->nVars, p->nBTLimit, p->DelayMax ); + // determine delay limit + if ( fDelay && pGia->vEdge1 && p->DelayMax == 0 ) + p->DelayMax = Gia_ManEvalEdgeDelay( pGia ); + // iterate through the internal nodes + Gia_ManComputeOneWinStart( pGia, nNumber, fReverse ); + Gia_ManForEachLut2( pGia, iLut ) + { + if ( Sbl_ManTestSat( p, iLut ) != 2 ) + continue; + if ( ++nImproveCount == nImproves ) + break; + } + Gia_ManComputeOneWin( pGia, -1, NULL, NULL, NULL, NULL ); + if ( p->fVerbose ) + printf( "Tried = %d. Used = %d. HashWin = %d. SmallWin = %d. LargeWin = %d. IterOut = %d. SAT runs = %d.\n", + p->nTried, p->nImproved, p->nHashWins, p->nSmallWins, p->nLargeWins, p->nIterOuts, p->nRuns ); + if ( p->fVerbose ) + Sbl_ManPrintRuntime( p ); + Sbl_ManStop( p ); + Vec_IntFreeP( &pGia->vPacking ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_RunKadical( char * pFileNameIn, char * pFileNameOut, int Seed, int nBTLimit, int TimeOut, int fVerbose, int * pStatus ) +{ + extern Vec_Int_t * Exa4_ManParse( char *pFileName ); + int fVerboseSolver = 0; + abctime clkTotal = Abc_Clock(); + Vec_Int_t * vRes = NULL; +#ifdef _WIN32 + char * pKadical = "kadical.exe"; +#else + char * pKadical = "./kadical"; + FILE * pFile = fopen( pKadical, "rb" ); + if ( pFile == NULL ) + pKadical += 2; + else + fclose( pFile ); +#endif + char Command[1000], * pCommand = (char *)&Command; + if ( nBTLimit ) { + if ( TimeOut ) + sprintf( pCommand, "%s --seed=%d -c %d -t %d %s %s > %s", pKadical, Seed, nBTLimit, TimeOut, fVerboseSolver ? "": "-q", pFileNameIn, pFileNameOut ); + else + sprintf( pCommand, "%s --seed=%d -c %d %s %s > %s", pKadical, Seed, nBTLimit, fVerboseSolver ? "": "-q", pFileNameIn, pFileNameOut ); + } + else { + if ( TimeOut ) + sprintf( pCommand, "%s --seed=%d -t %d %s %s > %s", pKadical, Seed, TimeOut, fVerboseSolver ? "": "-q", pFileNameIn, pFileNameOut ); + else + sprintf( pCommand, "%s --seed=%d %s %s > %s", pKadical, Seed, fVerboseSolver ? "": "-q", pFileNameIn, pFileNameOut ); + } +#ifdef __wasm + if ( 1 ) +#else + if ( system( pCommand ) == -1 ) +#endif + { + fprintf( stdout, "Command \"%s\" did not succeed.\n", pCommand ); + return 0; + } + vRes = Exa4_ManParse( pFileNameOut ); + if ( fVerbose ) + { + if ( vRes ) + printf( "The problem has a solution. " ), *pStatus = 0; + else if ( vRes == NULL && TimeOut == 0 ) + printf( "The problem has no solution. " ), *pStatus = 1; + else if ( vRes == NULL ) + printf( "The problem has no solution or reached a resource limit after %d sec. ", TimeOut ), *pStatus = -1; + Abc_PrintTime( 1, "SAT solver time", Abc_Clock() - clkTotal ); + } + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_SatVarReqPos( int i ) { return i*7+0; } // p +int Gia_SatVarReqNeg( int i ) { return i*7+1; } // n +int Gia_SatVarAckPos( int i ) { return i*7+2; } // P +int Gia_SatVarAckNeg( int i ) { return i*7+3; } // N +int Gia_SatVarInv ( int i ) { return i*7+4; } // i +int Gia_SatVarFan0 ( int i ) { return i*7+5; } // 0 +int Gia_SatVarFan1 ( int i ) { return i*7+6; } // 1 + +int Gia_SatValReqPos( Vec_Int_t * p, int i ) { return Vec_IntEntry(p, i*7+0); } // p +int Gia_SatValReqNeg( Vec_Int_t * p, int i ) { return Vec_IntEntry(p, i*7+1); } // n +int Gia_SatValAckPos( Vec_Int_t * p, int i ) { return Vec_IntEntry(p, i*7+2); } // P +int Gia_SatValAckNeg( Vec_Int_t * p, int i ) { return Vec_IntEntry(p, i*7+3); } // N +int Gia_SatValInv ( Vec_Int_t * p, int i ) { return Vec_IntEntry(p, i*7+4); } // i +int Gia_SatValFan0 ( Vec_Int_t * p, int i ) { return Vec_IntEntry(p, i*7+5); } // 0 +int Gia_SatValFan1 ( Vec_Int_t * p, int i ) { return Vec_IntEntry(p, i*7+6); } // 1 + +void Gia_SatDumpClause( Vec_Str_t * vStr, int * pLits, int nLits ) +{ + for ( int i = 0; i < nLits; i++ ) + Vec_StrPrintF( vStr, "%d ", Abc_LitIsCompl(pLits[i]) ? -Abc_Lit2Var(pLits[i])-1 : Abc_Lit2Var(pLits[i])+1 ); + Vec_StrPrintF( vStr, "0\n" ); +} +void Gia_SatDumpLiteral( Vec_Str_t * vStr, int Lit ) +{ + Gia_SatDumpClause( vStr, &Lit, 1 ); +} +void Gia_SatDumpKlause( Vec_Str_t * vStr, int nIns, int nAnds, int nBound ) +{ + int i, nVars = nIns + 7*nAnds; + Vec_StrPrintF( vStr, "k %d ", nVars - nBound ); + // counting primary inputs: n + for ( i = 0; i < nIns; i++ ) + Vec_StrPrintF( vStr, "-%d ", Gia_SatVarReqNeg(1+i)+1 ); + // counting internal nodes: p, n, P, N, i, 0, 1 + for ( i = 0; i < 7*nAnds; i++ ) + Vec_StrPrintF( vStr, "-%d ", (1+nIns)*7+i+1 ); + Vec_StrPrintF( vStr, "0\n" ); +} + +Vec_Str_t * Gia_ManSimpleCnf( Gia_Man_t * p, int nBound ) +{ + Vec_Str_t * vStr = Vec_StrAlloc( 10000 ); + Gia_SatDumpKlause( vStr, Gia_ManCiNum(p), Gia_ManAndNum(p), nBound ); + int i, n, m, Id, pLits[4]; Gia_Obj_t * pObj; + for ( n = 0; n < 7; n++ ) + Gia_SatDumpLiteral( vStr, Abc_Var2Lit(n, 1) ); + // acknowledge positive PI literals + Gia_ManForEachCiId( p, Id, i ) + for ( n = 0; n < 7; n++ ) if ( n != 1 ) + Gia_SatDumpLiteral( vStr, Abc_Var2Lit(Gia_SatVarReqPos(Id)+n, n>0) ); + // require driving PO literals + Gia_ManForEachCo( p, pObj, i ) + Gia_SatDumpLiteral( vStr, Abc_Var2Lit( Gia_SatVarReqPos(Gia_ObjFaninId0p(p, pObj)) + Gia_ObjFaninC0(pObj), 0 ) ); + // internal nodes + Gia_ManForEachAnd( p, pObj, i ) { + int fCompl[2] = { Gia_ObjFaninC0(pObj), Gia_ObjFaninC1(pObj) }; + int iFans[2] = { Gia_ObjFaninId0(pObj, i), Gia_ObjFaninId1(pObj, i) }; + Gia_Obj_t * pFans[2] = { Gia_ObjFanin0(pObj), Gia_ObjFanin1(pObj) }; + // require inverter: p & !n & N -> i, n & !p & P -> i + for ( n = 0; n < 2; n++ ) { + pLits[0] = Abc_Var2Lit( Gia_SatVarReqPos(i)+n, 1 ); + pLits[1] = Abc_Var2Lit( Gia_SatVarReqNeg(i)-n, 0 ); + pLits[2] = Abc_Var2Lit( Gia_SatVarAckNeg(i)-n, 1 ); + pLits[3] = Abc_Var2Lit( Gia_SatVarInv (i), 0 ); + Gia_SatDumpClause( vStr, pLits, 4 ); + } + // exclusive acknowledge: !P + !N + pLits[0] = Abc_Var2Lit( Gia_SatVarAckPos(i), 1 ); + pLits[1] = Abc_Var2Lit( Gia_SatVarAckNeg(i), 1 ); + Gia_SatDumpClause( vStr, pLits, 2 ); + // required acknowledge: p -> P + N, n -> P + N + pLits[1] = Abc_Var2Lit( Gia_SatVarAckPos(i), 0 ); + pLits[2] = Abc_Var2Lit( Gia_SatVarAckNeg(i), 0 ); + pLits[0] = Abc_Var2Lit( Gia_SatVarReqPos(i), 1 ); + Gia_SatDumpClause( vStr, pLits, 3 ); + pLits[0] = Abc_Var2Lit( Gia_SatVarReqNeg(i), 1 ); + Gia_SatDumpClause( vStr, pLits, 3 ); + // forbid acknowledge: !p & !n -> !P, !p & !n -> !N + pLits[0] = Abc_Var2Lit( Gia_SatVarReqPos(i), 0 ); + pLits[1] = Abc_Var2Lit( Gia_SatVarReqNeg(i), 0 ); + pLits[2] = Abc_Var2Lit( Gia_SatVarAckPos(i), 1 ); + Gia_SatDumpClause( vStr, pLits, 3 ); + pLits[2] = Abc_Var2Lit( Gia_SatVarAckNeg(i), 1 ); + Gia_SatDumpClause( vStr, pLits, 3 ); + // when fanins can be used: !N & !P -> !0, !N & !P -> !1 + pLits[0] = Abc_Var2Lit( Gia_SatVarAckPos(i), 0 ); + pLits[1] = Abc_Var2Lit( Gia_SatVarAckNeg(i), 0 ); + pLits[2] = Abc_Var2Lit( Gia_SatVarFan0(i), 1 ); + Gia_SatDumpClause( vStr, pLits, 3 ); + pLits[2] = Abc_Var2Lit( Gia_SatVarFan1(i), 1 ); + Gia_SatDumpClause( vStr, pLits, 3 ); + // when fanins are not used: 0 -> !N, 0 -> !P, 1 -> !N, 1 -> !P + for ( m = 0; m < 2; m++ ) + for ( n = 0; n < 2; n++ ) { + pLits[0] = Abc_Var2Lit( Gia_SatVarFan0(i)+n, 1 ); + pLits[1] = Abc_Var2Lit( Gia_SatVarReqPos(iFans[n])+m, 1 ); + Gia_SatDumpClause( vStr, pLits, 2 ); + } + // can only extend both when both complemented: !(C0 & C1) -> !0 + !1 + pLits[0] = Abc_Var2Lit( Gia_SatVarFan0(i), 1 ); + pLits[1] = Abc_Var2Lit( Gia_SatVarFan1(i), 1 ); + if ( !fCompl[0] || !fCompl[1] ) + Gia_SatDumpClause( vStr, pLits, 2 ); + // if fanin is a primary input, cannot extend it (pi -> !0 or pi -> !1) + for ( n = 0; n < 2; n++ ) + if ( Gia_ObjIsCi(pFans[n]) ) + Gia_SatDumpLiteral( vStr, Abc_Var2Lit( Gia_SatVarFan0(i)+n, 1 ) ); + // propagating assignments when fanin is not used + // P & !0 -> C0 ? P0 : N0 + // N & !0 -> C0 ? N0 : P0 + // P & !1 -> C1 ? P1 : N1 + // N & !1 -> C1 ? N1 : P1 + for ( m = 0; m < 2; m++ ) + for ( n = 0; n < 2; n++ ) { + pLits[0] = Abc_Var2Lit( Gia_SatVarAckPos(i)+m, 1 ); + pLits[1] = Abc_Var2Lit( Gia_SatVarFan0(i)+n, 0 ); + pLits[2] = Abc_Var2Lit( Gia_SatVarReqPos(iFans[n]) + !(m ^ fCompl[n]), 0 ); + Gia_SatDumpClause( vStr, pLits, 3 ); + } + // propagating assignments when fanins are used + // P & 0 -> (C0 ^ C00) ? P00 : N00 + // P & 0 -> (C0 ^ C01) ? P01 : N01 + // N & 0 -> (C0 ^ C00) ? N00 : P00 + // N & 0 -> (C0 ^ C01) ? N01 : P01 + // P & 1 -> (C1 ^ C10) ? P10 : N10 + // P & 1 -> (C1 ^ C11) ? P11 : N11 + // N & 1 -> (C1 ^ C10) ? N10 : P10 + // N & 1 -> (C1 ^ C11) ? N11 : P11 + for ( m = 0; m < 2; m++ ) + for ( n = 0; n < 2; n++ ) + if ( Gia_ObjIsAnd(pFans[n]) ) { + pLits[0] = Abc_Var2Lit( Gia_SatVarAckPos(i)+m, 1 ); + pLits[1] = Abc_Var2Lit( Gia_SatVarFan0(i)+n, 1 ); + pLits[2] = Abc_Var2Lit( Gia_SatVarReqPos(Gia_ObjFaninId0p(p, pFans[n])) + !(m ^ fCompl[n] ^ Gia_ObjFaninC0(pFans[n])), 0 ); + Gia_SatDumpClause( vStr, pLits, 3 ); + pLits[2] = Abc_Var2Lit( Gia_SatVarReqPos(Gia_ObjFaninId1p(p, pFans[n])) + !(m ^ fCompl[n] ^ Gia_ObjFaninC1(pFans[n])), 0 ); + Gia_SatDumpClause( vStr, pLits, 3 ); + } + } + Vec_StrPush( vStr, '\0' ); + return vStr; +} + +typedef enum { + GIA_GATE_ZERO, // 0: + GIA_GATE_ONE, // 1: + GIA_GATE_BUF, // 2: + GIA_GATE_INV, // 3: + GIA_GATE_NAN2, // 4: + GIA_GATE_NOR2, // 5: + GIA_GATE_AOI21, // 6: + GIA_GATE_NAN3, // 7: + GIA_GATE_NOR3, // 8: + GIA_GATE_OAI21, // 9: + GIA_GATE_AOI22, // 10: + GIA_GATE_OAI22, // 11: + RTM_VAL_VOID // 12: unused value +} Gia_ManGate_t; + +Vec_Int_t * Gia_ManDeriveSimpleMapping( Gia_Man_t * p, Vec_Int_t * vRes ) +{ + Vec_Int_t * vMapping = Vec_IntStart( 2*Gia_ManObjNum(p) ); + int i, Id; Gia_Obj_t * pObj; + Gia_ManForEachCiId( p, Id, i ) + if ( Gia_SatValReqNeg(vRes, Id) ) + Vec_IntWriteEntry( vMapping, Abc_Var2Lit(Id, 1), -1 ); + Gia_ManForEachAnd( p, pObj, i ) + { + if ( Gia_SatValAckPos(vRes, i) + Gia_SatValAckNeg(vRes, i) == 0 ) + continue; + assert( Gia_SatValAckPos(vRes, i) != Gia_SatValAckNeg(vRes, i) ); + if ( (Gia_SatValReqPos(vRes, i) && Gia_SatValReqNeg(vRes, i)) || Gia_SatValInv(vRes, i) ) + Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, Gia_SatValAckPos(vRes, i)), -1 ); + int fComp = Gia_SatValAckNeg(vRes, i); + int fFan0 = Gia_SatValFan0(vRes, i); + int fFan1 = Gia_SatValFan1(vRes, i); + Gia_Obj_t * pFans[2] = { Gia_ObjFanin0(pObj), Gia_ObjFanin1(pObj) }; + Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, fComp), Vec_IntSize(vMapping) ); + if ( fFan0 && fFan1 ) { + assert( Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ); + Vec_IntPush( vMapping, 4 ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC0(pFans[0]))) ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC1(pFans[0]))) ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC0(pFans[1]))) ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC1(pFans[1]))) ); + Vec_IntPush( vMapping, fComp ? GIA_GATE_OAI22 : GIA_GATE_AOI22 ); + } else if ( fFan0 ) { + Vec_IntPush( vMapping, 3 ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC0(pFans[0]))) ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC1(pFans[0]))) ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pObj), !(fComp ^ Gia_ObjFaninC1(pObj))) ); + if ( Gia_ObjFaninC0(pObj) ) + Vec_IntPush( vMapping, fComp ? GIA_GATE_OAI21 : GIA_GATE_AOI21 ); + else + Vec_IntPush( vMapping, fComp ? GIA_GATE_NAN3 : GIA_GATE_NOR3 ); + } else if ( fFan1 ) { + Vec_IntPush( vMapping, 3 ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC0(pFans[1]))) ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC1(pFans[1]))) ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pObj), !(fComp ^ Gia_ObjFaninC0(pObj))) ); + if ( Gia_ObjFaninC1(pObj) ) + Vec_IntPush( vMapping, fComp ? GIA_GATE_OAI21 : GIA_GATE_AOI21 ); + else + Vec_IntPush( vMapping, fComp ? GIA_GATE_NAN3 : GIA_GATE_NOR3 ); + } else { + Vec_IntPush( vMapping, 2 ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pObj), !(fComp ^ Gia_ObjFaninC0(pObj))) ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pObj), !(fComp ^ Gia_ObjFaninC1(pObj))) ); + Vec_IntPush( vMapping, fComp ? GIA_GATE_NAN2 : GIA_GATE_NOR2 ); + } + } + return vMapping; +} +void Gia_ManSimplePrintMapping( Vec_Int_t * vRes, int nIns ) +{ + int i, k, nObjs = Vec_IntSize(vRes)/7, nSteps = Abc_Base10Log(nObjs); + int nCard = Vec_IntSum(vRes) - nIns; char NumStr[10]; + printf( "Solution with cardinality %d:\n", nCard ); + for ( k = 0; k < nSteps; k++ ) { + printf( " " ); + for ( i = 0; i < nObjs; i++ ) { + sprintf( NumStr, "%02d", i ); + printf( "%c", NumStr[k] ); + } + printf( "\n" ); + } + for ( k = 0; k < 7; k++ ) { + printf( "%c ", "pnPNi01"[k] ); + for ( i = 0; i < nObjs; i++ ) + if ( Vec_IntEntry( vRes, i*7+k ) == 0 ) + printf( " " ); + else + printf( "1" ); + printf( "\n" ); + } +} +int Gia_ManDumpCnf( char * pFileName, Vec_Str_t * vStr, int nVars ) +{ + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) { printf( "Cannot open input file \"%s\".\n", pFileName ); return 0; } + fprintf( pFile, "p knf %d %d\n%s\n", nVars, Vec_StrCountEntry(vStr, '\n'), Vec_StrArray(vStr) ); + fclose( pFile ); + return 1; +} +int Gia_ManDumpCnf2( Vec_Str_t * vStr, int nVars, int argc, char ** argv, abctime Time, int Status ) +{ + Vec_Str_t * vFileName = Vec_StrAlloc( 100 ); int c; + Vec_StrPrintF( vFileName, "%s", argv[0] + (argv[0][0] == '&') ); + for ( c = 1; c < argc; c++ ) + Vec_StrPrintF( vFileName, "_%s", argv[c] + (argv[c][0] == '-') ); + Vec_StrPrintF( vFileName, ".cnf" ); + Vec_StrPush( vFileName, '\0' ); + FILE * pFile = fopen( Vec_StrArray(vFileName), "wb" ); + if ( pFile == NULL ) { printf( "Cannot open output file \"%s\".\n", Vec_StrArray(vFileName) ); Vec_StrFree(vFileName); return 0; } + Vec_StrFree(vFileName); + fprintf( pFile, "c This file was generated by ABC command: \"" ); + fprintf( pFile, "%s", argv[0] ); + for ( c = 1; c < argc; c++ ) + fprintf( pFile, " %s", argv[c] ); + fprintf( pFile, "\" on %s\n", Gia_TimeStamp() ); + fprintf( pFile, "c Cardinality CDCL (https://github.com/jreeves3/Cardinality-CDCL) found it to be " ); + if ( Status == 1 ) + fprintf( pFile, "UNSAT" ); + if ( Status == 0 ) + fprintf( pFile, "SAT" ); + if ( Status == -1 ) + fprintf( pFile, "UNDECIDED" ); + fprintf( pFile, " in %.2f sec\n", 1.0*((double)(Time))/((double)CLOCKS_PER_SEC) ); + fprintf( pFile, "p knf %d %d\n%s\n", nVars, Vec_StrCountEntry(vStr, '\n'), Vec_StrArray(vStr) ); + fclose( pFile ); + return 1; +} +int Gia_ManSimpleMapping( Gia_Man_t * p, int nBound, int Seed, int nBTLimit, int nTimeout, int fVerbose, int fKeepFile, int argc, char ** argv ) +{ + abctime clkStart = Abc_Clock(); + srand(time(NULL)); + int Status, Rand = ((((unsigned)rand()) << 12) ^ ((unsigned)rand())) & 0xFFFFFF; + char pFileNameI[32]; sprintf( pFileNameI, "_%06x_.cnf", Rand ); + char pFileNameO[32]; sprintf( pFileNameO, "_%06x_.out", Rand ); + if ( nBound == 0 ) + nBound = 5 * Gia_ManAndNum(p); + Vec_Str_t * vStr = Gia_ManSimpleCnf( p, nBound/2 ); + int nVars = 7*(Gia_ManObjNum(p)-Gia_ManCoNum(p)); + if ( !Gia_ManDumpCnf(pFileNameI, vStr, nVars) ) { + Vec_StrFree( vStr ); + return 0; + } + if ( fVerbose ) + printf( "SAT variables = %d. SAT clauses = %d. Cardinality bound = %d. Conflict limit = %d. Timeout = %d.\n", + nVars, Vec_StrCountEntry(vStr, '\n'), nBound, nBTLimit, nTimeout ); + Vec_Int_t * vRes = Gia_RunKadical( pFileNameI, pFileNameO, Seed, nBTLimit, nTimeout, fVerbose, &Status ); + unlink( pFileNameI ); + //unlink( pFileNameO ); + if ( fKeepFile ) Gia_ManDumpCnf2( vStr, nVars, argc, argv, Abc_Clock() - clkStart, Status ); + Vec_StrFree( vStr ); + if ( vRes == NULL ) + return 0; + Vec_IntFreeP( &p->vCellMapping ); + assert( p->vCellMapping == NULL ); + Vec_IntDrop( vRes, 0 ); + if ( fVerbose ) Gia_ManSimplePrintMapping( vRes, Gia_ManCiNum(p) ); + p->vCellMapping = Gia_ManDeriveSimpleMapping( p, vRes ); + Vec_IntFree( vRes ); + if ( fVerbose ) Abc_PrintTime( 0, "Total time", Abc_Clock() - clkStart ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +#define KSAT_OBJS 24 +#define KSAT_MINTS 64 +#define KSAT_SPACE (4+3*KSAT_OBJS+3*KSAT_MINTS) + +int Gia_KSatVarInv( int * pMap, int i ) { return pMap[i*KSAT_SPACE+0]; } +int Gia_KSatVarAnd( int * pMap, int i ) { return pMap[i*KSAT_SPACE+1]; } +int Gia_KSatVarEqu( int * pMap, int i ) { return pMap[i*KSAT_SPACE+2]; } +int Gia_KSatVarRef( int * pMap, int i ) { return pMap[i*KSAT_SPACE+3]; } +int Gia_KSatVarFan( int * pMap, int i, int f, int k ) { return pMap[i*KSAT_SPACE+4+f*KSAT_OBJS+k]; } +int Gia_KSatVarMin( int * pMap, int i, int m, int k ) { return pMap[i*KSAT_SPACE+4+3*KSAT_OBJS+3*m+k]; } + +void Gia_KSatSetInv( int * pMap, int i, int iVar ) { assert( -1 == pMap[i*KSAT_SPACE+0] ); pMap[i*KSAT_SPACE+0] = iVar; } +void Gia_KSatSetAnd( int * pMap, int i, int iVar ) { assert( -1 == pMap[i*KSAT_SPACE+1] ); pMap[i*KSAT_SPACE+1] = iVar; } +void Gia_KSatSetEqu( int * pMap, int i, int iVar ) { assert( -1 == pMap[i*KSAT_SPACE+2] ); pMap[i*KSAT_SPACE+2] = iVar; } +void Gia_KSatSetRef( int * pMap, int i, int iVar ) { assert( -1 == pMap[i*KSAT_SPACE+3] ); pMap[i*KSAT_SPACE+3] = iVar; } +void Gia_KSatSetFan( int * pMap, int i, int f, int k, int iVar ) { assert( -1 == pMap[i*KSAT_SPACE+4+f*KSAT_OBJS+k] ); pMap[i*KSAT_SPACE+4+f*KSAT_OBJS+k] = iVar; } +void Gia_KSatSetMin( int * pMap, int i, int m, int k, int iVar ) { assert( -1 == pMap[i*KSAT_SPACE+4+3*KSAT_OBJS+3*m+k] ); pMap[i*KSAT_SPACE+4+3*KSAT_OBJS+3*m+k] = iVar; } + +int Gia_KSatValInv( int * pMap, int i, Vec_Int_t * vRes ) { assert( -1 != pMap[i*KSAT_SPACE+0] ); return Vec_IntEntry( vRes, pMap[i*KSAT_SPACE+0] ); } +int Gia_KSatValAnd( int * pMap, int i, Vec_Int_t * vRes ) { assert( -1 != pMap[i*KSAT_SPACE+1] ); return Vec_IntEntry( vRes, pMap[i*KSAT_SPACE+1] ); } +int Gia_KSatValEqu( int * pMap, int i, Vec_Int_t * vRes ) { assert( -1 != pMap[i*KSAT_SPACE+2] ); return Vec_IntEntry( vRes, pMap[i*KSAT_SPACE+2] ); } +int Gia_KSatValRef( int * pMap, int i, Vec_Int_t * vRes ) { assert( -1 != pMap[i*KSAT_SPACE+3] ); return Vec_IntEntry( vRes, pMap[i*KSAT_SPACE+3] ); } +int Gia_KSatValFan( int * pMap, int i, int f, int k, Vec_Int_t * vRes ) { assert( -1 != pMap[i*KSAT_SPACE+4+f*KSAT_OBJS+k] ); return Vec_IntEntry( vRes, pMap[i*KSAT_SPACE+4+f*KSAT_OBJS+k] ); } +int Gia_KSatValMin( int * pMap, int i, int m, int k, Vec_Int_t * vRes ) { assert( -1 != pMap[i*KSAT_SPACE+4+3*KSAT_OBJS+3*m+k] ); return Vec_IntEntry( vRes, pMap[i*KSAT_SPACE+4+3*KSAT_OBJS+3*m+k] ); } + +int * Gia_KSatMapInit( int nIns, int nNodes, word Truth, int * pnVars ) +{ + assert( nIns + nNodes <= KSAT_OBJS ); + assert( (1 << nIns) <= KSAT_MINTS ); + int n, m, f, k, nVars = 2, * pMap = ABC_FALLOC( int, KSAT_OBJS*KSAT_SPACE ); + for ( n = nIns; n < nIns+nNodes; n++ ) { + Gia_KSatSetInv(pMap, n, nVars++); + Gia_KSatSetAnd(pMap, n, nVars++); + Gia_KSatSetEqu(pMap, n, nVars++); + Gia_KSatSetRef(pMap, n, nVars++); + } + for ( n = nIns; n < nIns+nNodes; n++ ) { + for ( f = 0; f < 2; f++ ) + for ( k = 0; k < n; k++ ) + Gia_KSatSetFan(pMap, n, f, k, nVars++); + for ( k = n+1; k < nIns+nNodes; k++ ) + Gia_KSatSetFan(pMap, n, 2, k, nVars++); + } + for ( m = 0; m < (1<> n) & 1 ); + Gia_KSatSetMin(pMap, nIns+nNodes-1, m, 0, (Truth >> m) & 1 ); + for ( n = nIns; n < nIns+nNodes; n++ ) + for ( k = 0; k < 3; k++ ) + if ( k || n < nIns+nNodes-1 ) + Gia_KSatSetMin(pMap, n, m, k, nVars++); + + } + if ( pnVars ) *pnVars = nVars; + return pMap; +} + +int Gia_KSatFindFan( int * pMap, int i, int f, Vec_Int_t * vRes ) +{ + assert( f < 2 ); + for ( int k = 0; k < i; k++ ) + if ( Gia_KSatValFan( pMap, i, f, k, vRes ) ) + return k; + assert( 0 ); + return -1; +} + +Vec_Int_t * Gia_ManKSatGenLevels( char * pGuide, int nIns, int nNodes ) +{ + Vec_Int_t * vRes; + int i, k, Count = 0; + for ( i = 0; pGuide[i]; i++ ) + Count += pGuide[i] - '0'; + if ( Count != nNodes ) { + printf( "Guidance %s has %d nodes while the problem has %d nodes.\n", pGuide, Count, nNodes ); + return NULL; + } + int FirstPrev = 0; + int FirstThis = nIns; + int FirstNext = FirstThis; + vRes = Vec_IntStartFull( 2*nIns ); + for ( i = 0; pGuide[i]; i++ ) { + FirstNext += pGuide[i] - '0'; + for ( k = FirstThis; k < FirstNext; k++ ) + Vec_IntPushTwo( vRes, FirstPrev, FirstThis ); + FirstPrev = FirstThis; + FirstThis = FirstNext; + } + assert( Vec_IntSize(vRes) == 2*(nIns + nNodes) ); + Count = 0; + //int Start, Stop; + //Vec_IntForEachEntryDouble(vRes, Start, Stop, i) + // printf( "%2d : Start %2d Stop %2d\n", Count++, Start, Stop ); + return vRes; +} + +Vec_Str_t * Gia_ManKSatCnf( int * pMap, int nIns, int nNodes, int nBound, int fMultiLevel, char * pGuide ) +{ + Vec_Str_t * vStr = Vec_StrAlloc( 10000 ); + Vec_Int_t * vRes = pGuide ? Gia_ManKSatGenLevels( pGuide, nIns, nNodes ) : NULL; + int i, j, m, n, f, c, a, Start, Stop, nLits = 0, pLits[256] = {0}; + Gia_SatDumpLiteral( vStr, 1 ); + Gia_SatDumpLiteral( vStr, 2 ); + if ( vRes ) { + n = nIns; + Vec_IntForEachEntryDoubleStart( vRes, Start, Stop, i, 2*nIns ) { + for ( j = 0; j < Start; j++ ) + Gia_SatDumpLiteral( vStr, Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 1, j), 1 ) ); + for ( f = 0; f < 2; f++ ) + for ( j = Stop; j < n; j++ ) + Gia_SatDumpLiteral( vStr, Abc_Var2Lit( Gia_KSatVarFan(pMap, n, f, j), 1 ) ); + n++; + } + assert( n == nIns + nNodes ); + } + // fanins are connected once + for ( n = nIns; n < nIns+nNodes; n++ ) + for ( f = 0; f < 2; f++ ) { + + nLits = 0; + for ( i = 0; i < n; i++ ) + pLits[nLits++] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, f, i), 0 ); + Gia_SatDumpClause( vStr, pLits, nLits ); +/* + for ( i = 0; i < n; i++ ) + for ( j = 0; j < i; j++ ) { + pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, f, i), 1 ); + pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, f, j), 1 ); + Gia_SatDumpClause( vStr, pLits, 2 ); + } +*/ + Vec_StrPrintF( vStr, "k %d ", n-1 ); + for ( i = 0; i < n; i++ ) + pLits[i] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, f, i), 1 ); + Gia_SatDumpClause( vStr, pLits, n ); + } + for ( n = nIns; n < nIns+nNodes; n++ ) { + // fanins are equal + for ( i = 0; i < n; i++ ) { + pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 0, i), 1 ); + pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 1, i), 1 ); + pLits[2] = Abc_Var2Lit( Gia_KSatVarEqu(pMap, n), 0 ); + Gia_SatDumpClause( vStr, pLits, 3 ); + } + for ( i = 0; i < n; i++ ) + for ( j = i+1; j < n; j++ ) { + pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 0, i), 1 ); + pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 1, j), 1 ); + pLits[2] = Abc_Var2Lit( Gia_KSatVarEqu(pMap, n), 1 ); + Gia_SatDumpClause( vStr, pLits, 3 ); + } + // if fanins are equal, inv is used + pLits[0] = Abc_Var2Lit( Gia_KSatVarEqu(pMap, n), 1 ); + pLits[1] = Abc_Var2Lit( Gia_KSatVarInv(pMap, n), 0 ); + Gia_SatDumpClause( vStr, pLits, 2 ); + // fanin ordering + for ( i = 0; i < n; i++ ) + for ( j = 0; j < i; j++ ) { + pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 0, i), 1 ); + pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 1, j), 1 ); + Gia_SatDumpClause( vStr, pLits, 2 ); + } + } + for ( n = nIns; n < nIns+nNodes-1; n++ ) { + // there is a fanout to the node above + for ( i = n+1; i < nIns+nNodes; i++ ) { + for ( f = 0; f < 2; f++ ) { + pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, i, f, n), 1 ); + pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 2, i), 0 ); + Gia_SatDumpClause( vStr, pLits, 2 ); + } + pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, i, 0, n), 0 ); + pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, i, 1, n), 0 ); + pLits[2] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 2, i), 1 ); + Gia_SatDumpClause( vStr, pLits, 3 ); + } + // there is at least one fanout, except the last one + nLits = 0; + for ( i = n+1; i < nIns+nNodes; i++ ) + pLits[nLits++] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 2, i), 0 ); + assert( nLits > 0 ); + Gia_SatDumpClause( vStr, pLits, nLits ); + } + // there is more than one fanout, except the last one + for ( n = nIns; n < nIns+nNodes-1; n++ ) { + for ( i = n+1; i < nIns+nNodes; i++ ) + for ( j = i+1; j < nIns+nNodes; j++ ) { + pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 2, i), 1 ); + pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 2, j), 1 ); + pLits[2] = Abc_Var2Lit( Gia_KSatVarRef(pMap, n), 0 ); + Gia_SatDumpClause( vStr, pLits, 3 ); + } + // if more than one fanout, inv is used + pLits[0] = Abc_Var2Lit( Gia_KSatVarRef(pMap, n), 1 ); + pLits[1] = Abc_Var2Lit( Gia_KSatVarInv(pMap, n), 0 ); + Gia_SatDumpClause( vStr, pLits, 2 ); + // if inv is not used, its fanins' invs are used + if ( !fMultiLevel ) { + pLits[0] = Abc_Var2Lit( Gia_KSatVarInv(pMap, n), 0 ); + for ( i = nIns; i < n; i++ ) + for ( f = 0; f < 2; f++ ) { + pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, f, i), 1 ); + pLits[2] = Abc_Var2Lit( Gia_KSatVarInv(pMap, i), 0 ); + Gia_SatDumpClause( vStr, pLits, 3 ); + } + } + } + // the last one always uses inverter + Gia_SatDumpLiteral( vStr, Abc_Var2Lit( Gia_KSatVarInv(pMap, nIns+nNodes-1), 0 ) ); +/* + // for each minterm, for each pair of possible fanins, the node's output is determined using and/or and inv (4*N*N*M) + for ( m = 0; m < (1 << nIns); m++ ) + for ( n = nIns; n < nIns+nNodes; n++ ) + for ( c = 0; c < 2; c++ ) + for ( a = 0; a < 2; a++ ) { + // implications: Fan(f) & Mint(m) & !And & !Inv -> Val1 + for ( f = 0; f < 2; f++ ) + for ( i = 0; i < n; i++ ) { + pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, f, i), 1 ); + pLits[1] = Abc_Var2Lit( Gia_KSatVarMin(pMap, i, m, 0), !a ); + pLits[2] = Abc_Var2Lit( Gia_KSatVarAnd(pMap, n), a ); + pLits[3] = Abc_Var2Lit( Gia_KSatVarInv(pMap, n), c ); + pLits[4] = Abc_Var2Lit( Gia_KSatVarMin(pMap, n, m, 0), a^c ); + Gia_SatDumpClause( vStr, pLits, 5 ); + } + // large clauses: Fan(0) & Fan(1) & !Mint(m) & !Mint(m) & !And & !Inv -> Val0 + for ( i = 0; i < n; i++ ) + for ( j = i; j < n; j++ ) { + pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 0, i), 1 ); + pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 1, j), 1 ); + pLits[2] = Abc_Var2Lit( Gia_KSatVarMin(pMap, i, m, 0), a ); + pLits[3] = Abc_Var2Lit( Gia_KSatVarMin(pMap, j, m, 0), a ); + pLits[4] = Abc_Var2Lit( Gia_KSatVarAnd(pMap, n), a ); + pLits[5] = Abc_Var2Lit( Gia_KSatVarInv(pMap, n), c ); + pLits[6] = Abc_Var2Lit( Gia_KSatVarMin(pMap, n, m, 0), a==c ); + Gia_SatDumpClause( vStr, pLits, 7 ); + } + } +*/ + // for each minterm, define a fanin variable and use it to get the node's output based on and/or and inv (4*N*N*M) + for ( m = 0; m < (1 << nIns); m++ ) + for ( n = nIns; n < nIns+nNodes; n++ ) { + for ( i = 0; i < n; i++ ) + for ( f = 0; f < 2; f++ ) + for ( c = 0; c < 2; c++ ) { + pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, f, i), 1 ); + pLits[1] = Abc_Var2Lit( Gia_KSatVarMin(pMap, i, m, 0), c ); + pLits[2] = Abc_Var2Lit( Gia_KSatVarMin(pMap, n, m, 1+f), !c ); + Gia_SatDumpClause( vStr, pLits, 3 ); + } + for ( c = 0; c < 2; c++ ) + for ( a = 0; a < 2; a++ ) { + // implications: Mint(m,f) & !And & !Inv -> Val1 + for ( f = 0; f < 2; f++ ) { + pLits[0] = Abc_Var2Lit( Gia_KSatVarMin(pMap, n, m, 1+f), !a ); + pLits[1] = Abc_Var2Lit( Gia_KSatVarAnd(pMap, n), a ); + pLits[2] = Abc_Var2Lit( Gia_KSatVarInv(pMap, n), c ); + pLits[3] = Abc_Var2Lit( Gia_KSatVarMin(pMap, n, m, 0), a^c ); + Gia_SatDumpClause( vStr, pLits, 4 ); + } + // large clauses: !Mint(m,0) & !Mint(m,1) & !And & !Inv -> Val0 + pLits[0] = Abc_Var2Lit( Gia_KSatVarMin(pMap, n, m, 1), a ); + pLits[1] = Abc_Var2Lit( Gia_KSatVarMin(pMap, n, m, 2), a ); + pLits[2] = Abc_Var2Lit( Gia_KSatVarAnd(pMap, n), a ); + pLits[3] = Abc_Var2Lit( Gia_KSatVarInv(pMap, n), c ); + pLits[4] = Abc_Var2Lit( Gia_KSatVarMin(pMap, n, m, 0), a==c ); + Gia_SatDumpClause( vStr, pLits, 5 ); + } + } + // the number of nodes with duplicated fanins and without inv is maximized + if ( nBound && 2*nNodes > nBound ) { + Vec_StrPrintF( vStr, "k %d ", 2*nNodes-nBound ); + nLits = 0; + for ( n = nIns; n < nIns+nNodes; n++ ) { + pLits[nLits++] = Abc_Var2Lit(Gia_KSatVarEqu(pMap, n), 0); + pLits[nLits++] = Abc_Var2Lit(Gia_KSatVarInv(pMap, n), 1); + } + Gia_SatDumpClause( vStr, pLits, nLits ); + } + Vec_StrPush( vStr, '\0' ); + Vec_IntFreeP( &vRes ); + return vStr; +} + + +typedef enum { + GIA_GATE2_ZERO, // 0: + GIA_GATE2_ONE, // 1: + GIA_GATE2_BUF, // 2: + GIA_GATE2_INV, // 3: + GIA_GATE2_NAN2, // 4: + GIA_GATE2_NOR2, // 5: + GIA_GATE2_AOI21, // 6: + GIA_GATE2_NAN3, // 7: + GIA_GATE2_NOR3, // 8: + GIA_GATE2_OAI21, // 9: + GIA_GATE2_NOR4, // 10: + GIA_GATE2_AOI211, // 11: + GIA_GATE2_AOI22, // 12: + GIA_GATE2_NAN4, // 13: + GIA_GATE2_OAI211, // 14: + GIA_GATE2_OAI22, // 15: + GIA_GATE2_VOID // 16: unused value +} Gia_ManGate2_t; + +Vec_Int_t * Gia_ManDeriveKSatMappingArray( Gia_Man_t * p, Vec_Int_t * vRes ) +{ + Vec_Int_t * vMapping = Vec_IntStart( 2*Gia_ManObjNum(p) ); + int i, Id; Gia_Obj_t * pObj; + Gia_ManForEachCiId( p, Id, i ) + if ( Vec_IntEntry(vRes, Id) ) + Vec_IntWriteEntry( vMapping, Abc_Var2Lit(Id, 1), -1 ); + Gia_ManForEachAnd( p, pObj, i ) { + assert( Vec_IntEntry(vRes, i) > 0 ); + if ( (Vec_IntEntry(vRes, i) & 2) == 0 ) { + assert( (Vec_IntEntry(vRes, i) & 1) == 0 ); + continue; + } + Gia_Obj_t * pFans[2] = { Gia_ObjFanin0(pObj), Gia_ObjFanin1(pObj) }; + int fComp = ((Vec_IntEntry(vRes, i) >> 2) & 1) != 0; + int fFan0 = ((Vec_IntEntry(vRes, Gia_ObjFaninId0(pObj, i)) >> 1) & 1) == 0 && Gia_ObjIsAnd(pFans[0]); + int fFan1 = ((Vec_IntEntry(vRes, Gia_ObjFaninId1(pObj, i)) >> 1) & 1) == 0 && Gia_ObjIsAnd(pFans[1]); + if ( Vec_IntEntry(vRes, i) & 1 ) + Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, !fComp), -1 ); + Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, fComp), Vec_IntSize(vMapping) ); + if ( fFan0 && fFan1 ) { + Vec_IntPush( vMapping, 4 ); + if ( !Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ) { + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC0(pFans[1]))) ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC1(pFans[1]))) ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC0(pFans[0]))) ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC1(pFans[0]))) ); + } + else { + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC0(pFans[0]))) ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC1(pFans[0]))) ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC0(pFans[1]))) ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC1(pFans[1]))) ); + } + if ( Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ) + Vec_IntPush( vMapping, fComp ? GIA_GATE2_OAI22 : GIA_GATE2_AOI22 ); + else if ( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ) + Vec_IntPush( vMapping, fComp ? GIA_GATE2_NAN4 : GIA_GATE2_NOR4 ); + else + Vec_IntPush( vMapping, fComp ? GIA_GATE2_OAI211 : GIA_GATE2_AOI211 ); + } else if ( fFan0 ) { + Vec_IntPush( vMapping, 3 ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC0(pFans[0]))) ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC1(pFans[0]))) ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pObj), !(fComp ^ Gia_ObjFaninC1(pObj))) ); + if ( Gia_ObjFaninC0(pObj) ) + Vec_IntPush( vMapping, fComp ? GIA_GATE2_OAI21 : GIA_GATE2_AOI21 ); + else + Vec_IntPush( vMapping, fComp ? GIA_GATE2_NAN3 : GIA_GATE2_NOR3 ); + } else if ( fFan1 ) { + Vec_IntPush( vMapping, 3 ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC0(pFans[1]))) ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC1(pFans[1]))) ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pObj), !(fComp ^ Gia_ObjFaninC0(pObj))) ); + if ( Gia_ObjFaninC1(pObj) ) + Vec_IntPush( vMapping, fComp ? GIA_GATE2_OAI21 : GIA_GATE2_AOI21 ); + else + Vec_IntPush( vMapping, fComp ? GIA_GATE2_NAN3 : GIA_GATE2_NOR3 ); + } else { + Vec_IntPush( vMapping, 2 ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pObj), !(fComp ^ Gia_ObjFaninC0(pObj))) ); + Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pObj), !(fComp ^ Gia_ObjFaninC1(pObj))) ); + Vec_IntPush( vMapping, fComp ? GIA_GATE2_NAN2 : GIA_GATE2_NOR2 ); + } + } + return vMapping; +} + +Gia_Man_t * Gia_ManDeriveKSatMapping( Vec_Int_t * vRes, int * pMap, int nIns, int nNodes, int fVerbose ) +{ + Vec_Int_t * vGuide = Vec_IntStart( 1000 ); + Gia_Man_t * pNew = Gia_ManStart( nIns + nNodes + 2 ); + pNew->pName = Abc_UtilStrsav( "test" ); + int i, nSave = 0, pCopy[256] = {0}; + for ( i = 1; i <= nIns; i++ ) + pCopy[i] = Gia_ManAppendCi( pNew ); + for ( i = nIns; i < nIns+nNodes; i++ ) { + int iFan0 = Gia_KSatFindFan( pMap, i, 0, vRes ); + int iFan1 = Gia_KSatFindFan( pMap, i, 1, vRes ); + if ( iFan0 == iFan1 ) + pCopy[i+1] = pCopy[iFan0+1]; + else if ( Gia_KSatValAnd(pMap, i, vRes) ) + pCopy[i+1] = Gia_ManAppendAnd( pNew, pCopy[iFan0+1], pCopy[iFan1+1] ); + else + pCopy[i+1] = Gia_ManAppendOr( pNew, pCopy[iFan0+1], pCopy[iFan1+1] ); + pCopy[i+1] = Abc_LitNotCond( pCopy[i+1], Gia_KSatValInv(pMap, i, vRes) ); + if ( iFan0 == iFan1 ) + *Vec_IntEntryP(vGuide, Abc_Lit2Var(pCopy[i+1])) ^= 1; + else if ( Gia_KSatValAnd(pMap, i, vRes) ) + *Vec_IntEntryP(vGuide, Abc_Lit2Var(pCopy[i+1])) ^= 4 | (2*Gia_KSatValInv(pMap, i, vRes)); + else + *Vec_IntEntryP(vGuide, Abc_Lit2Var(pCopy[i+1])) ^= 8 | (2*Gia_KSatValInv(pMap, i, vRes)); + if ( fVerbose ) { + if ( i == nIns+nNodes-1 ) + printf( " F = " ); + else + printf( "%2d = ", i ); + if ( iFan0 == iFan1 ) + printf( "INV( %d )\n", iFan0 ); + else if ( Gia_KSatValAnd(pMap, i, vRes) ) + printf( "%sAND( %d, %d )\n", Gia_KSatValInv(pMap, i, vRes) ? "N":"", iFan0, iFan1 ); + else + printf( "%sOR( %d, %d )\n", Gia_KSatValInv(pMap, i, vRes) ? "N":"", iFan0, iFan1 ); + nSave += (iFan0 == iFan1) || !Gia_KSatValInv(pMap, i, vRes); + if ( i == nIns+nNodes-1 ) + printf( "Solution cost = %d\n", 2*(2*nNodes - nSave) ); + } + } + Gia_ManAppendCo( pNew, pCopy[nIns+nNodes] ); + //pNew->vCellMapping = Gia_ManDeriveKSatMappingArray( pNew, vGuide ); + Vec_IntFree( vGuide ); + return pNew; +} + +word Gia_ManGetTruth( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; int i, Id; + word pFuncs[256] = {0}, Const[2] = {0, ~(word)0}; + assert( Gia_ManObjNum(p) <= 256 ); + Gia_ManForEachCiId( p, Id, i ) + pFuncs[Id] = s_Truths6[i]; + Gia_ManForEachAnd( p, pObj, i ) + pFuncs[i] = (Const[Gia_ObjFaninC0(pObj)] ^ pFuncs[Gia_ObjFaninId0(pObj, i)]) & (Const[Gia_ObjFaninC1(pObj)] ^ pFuncs[Gia_ObjFaninId1(pObj, i)]); + pObj = Gia_ManCo(p, 0); + return Const[Gia_ObjFaninC0(pObj)] ^ pFuncs[Gia_ObjFaninId0p(p, pObj)]; +} + +Gia_Man_t * Gia_ManKSatMapping( word Truth, int nIns, int nNodes, int nBound, int Seed, int fMultiLevel, int nBTLimit, int nTimeout, int fVerbose, int fKeepFile, int argc, char ** argv, char * pGuide ) +{ + abctime clkStart = Abc_Clock(); + Gia_Man_t * pNew = NULL; + srand(time(NULL)); + int Status, Rand = ((((unsigned)rand()) << 12) ^ ((unsigned)rand())) & 0xFFFFFF; + char pFileNameI[32]; sprintf( pFileNameI, "_%06x_.cnf", Rand ); + char pFileNameO[32]; sprintf( pFileNameO, "_%06x_.out", Rand ); + int nVars = 0, * pMap = Gia_KSatMapInit( nIns, nNodes, Truth, &nVars ); + Vec_Str_t * vStr = Gia_ManKSatCnf( pMap, nIns, nNodes, nBound/2, fMultiLevel, pGuide ); + if ( !Gia_ManDumpCnf(pFileNameI, vStr, nVars) ) { + Vec_StrFree( vStr ); + return NULL; + } + if ( fVerbose ) + printf( "Vars = %d. Nodes = %d. Cardinality bound = %d. SAT vars = %d. SAT clauses = %d. Conflict limit = %d. Timeout = %d.\n", + nIns, nNodes, nBound, nVars, Vec_StrCountEntry(vStr, '\n'), nBTLimit, nTimeout ); + Vec_Int_t * vRes = Gia_RunKadical( pFileNameI, pFileNameO, Seed, nBTLimit, nTimeout, 1, &Status ); + unlink( pFileNameI ); + //unlink( pFileNameO ); + if ( fKeepFile ) Gia_ManDumpCnf2( vStr, nVars, argc, argv, Abc_Clock() - clkStart, Status ); + Vec_StrFree( vStr ); + if ( vRes == NULL ) + return 0; + Vec_IntDrop( vRes, 0 ); + pNew = Gia_ManDeriveKSatMapping( vRes, pMap, nIns, nNodes, fVerbose ); + printf( "Verification %s. ", Truth == Gia_ManGetTruth(pNew) ? "passed" : "failed" ); + Abc_PrintTime( 0, "Total time", Abc_Clock() - clkStart ); + Vec_IntFree( vRes ); + ABC_FREE( pMap ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaSatMap.c b/yosys/abc/src/aig/gia/giaSatMap.c new file mode 100644 index 00000000000..a73950fba2c --- /dev/null +++ b/yosys/abc/src/aig/gia/giaSatMap.c @@ -0,0 +1,666 @@ +/**CFile**************************************************************** + + FileName [giaSatMap.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSatMap.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "sat/bsat/satStore.h" +#include "misc/vec/vecWec.h" +#include "misc/util/utilNam.h" +#include "map/scl/sclCon.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + + +// operation manager +typedef struct Sbm_Man_t_ Sbm_Man_t; +struct Sbm_Man_t_ +{ + sat_solver * pSat; // SAT solver + Vec_Int_t * vCardVars; // candinality variables + int LogN; // max vars + int FirstVar; // first variable to be used + int LitShift; // shift in terms of literals (2*Gia_ManCiNum(pGia)+2) + int nInputs; // the number of inputs + // window + Vec_Int_t * vRoots; // output drivers to be mapped (root -> lit) + Vec_Wec_t * vCuts; // cuts (cut -> node lit + fanin lits) + Vec_Wec_t * vObjCuts; // cuts (obj -> node lit + cut lits) + Vec_Int_t * vSolCuts; // current solution (index -> cut) + Vec_Int_t * vCutGates; // gates (cut -> gate) + Vec_Wrd_t * vCutAreas; // area of each cut + // solver + Vec_Int_t * vAssump; // assumptions (root nodes) + Vec_Int_t * vPolar; // polarity of nodes and cuts + // timing + Vec_Int_t * vArrs; // arrivals for the inputs (input -> time) + Vec_Int_t * vReqs; // required for the outputs (root -> time) + // internal + Vec_Int_t * vLit2Used; // current solution (lit -> used) + Vec_Int_t * vDelays; // node arrivals (lit -> time) + Vec_Int_t * vReason; // timing reasons (lit -> cut) +}; + +/* + Cuts in p->vCuts have 0-based numbers and are expressed in terms of object literals. + Cuts in p->vObjCuts are expressed in terms of the obj-lit + cut-lits (i + p->FirstVar) + Unit cuts for each polarity are ordered in the end. +*/ + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Verify solution. Create polarity and assumptions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sbm_ManCheckSol( Sbm_Man_t * p, Vec_Int_t * vSol ) +{ + //int K = Vec_IntSize(vSol) - 1; + int i, j, Lit, Cut; + int RetValue = 1; + Vec_Int_t * vCut; + // clear polarity and assumptions + Vec_IntClear( p->vPolar ); + // mark used literals + Vec_IntFill( p->vLit2Used, Vec_WecSize(p->vObjCuts) + p->nInputs, 0 ); + Vec_IntForEachEntry( p->vSolCuts, Cut, i ) + { + if ( Cut < 0 ) // input inverter variable + { + Vec_IntWriteEntry( p->vLit2Used, -Cut, 1 ); + Vec_IntPush( p->vPolar, -Cut ); + continue; + } + Vec_IntPush( p->vPolar, p->FirstVar + Cut ); + vCut = Vec_WecEntry( p->vCuts, Cut ); + Lit = Vec_IntEntry( vCut, 0 ) - p->LitShift; // obj literal + if ( Vec_IntEntry(p->vLit2Used, Lit) ) + continue; + Vec_IntWriteEntry( p->vLit2Used, Lit, 1 ); + Vec_IntPush( p->vPolar, Lit ); // literal variable + } + // check that the output literals are used + Vec_IntForEachEntry( p->vRoots, Lit, i ) + { + if ( Vec_IntEntry(p->vLit2Used, Lit) == 0 ) + printf( "Output literal %d has no cut.\n", Lit ), RetValue = 0; + } + // check internal nodes + Vec_IntForEachEntry( p->vSolCuts, Cut, i ) + { + if ( Cut < 0 ) + continue; + vCut = Vec_WecEntry( p->vCuts, Cut ); + Vec_IntForEachEntryStart( vCut, Lit, j, 1 ) + if ( Lit - p->LitShift < 0 ) + { + assert( Abc_LitIsCompl(Lit) ); + if ( Vec_IntEntry(p->vLit2Used, Vec_WecSize(p->vObjCuts) + Abc_Lit2Var(Lit)-1) == 0 ) + printf( "Inverter of input %d of cut %d is not mapped.\n", Abc_Lit2Var(Lit)-1, Cut ), RetValue = 0; + } + else if ( Vec_IntEntry(p->vLit2Used, Lit - p->LitShift) == 0 ) + printf( "Internal literal %d of cut %d is not mapped.\n", Lit - p->LitShift, Cut ), RetValue = 0; + // create polarity + Vec_IntPush( p->vPolar, p->FirstVar + Cut ); // cut variable + } + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Sbm_ManCreateCnf( Sbm_Man_t * p ) +{ + int i, k, Lit, Lits[2], value; + Vec_Int_t * vLits, * vCutOne, * vLitsPrev; + // sat_solver_rollback( p->Sat ); + if ( !Sbm_ManCheckSol(p, p->vSolCuts) ) + return 0; + // increase var count + assert( p->FirstVar == sat_solver_nvars(p->pSat) ); + sat_solver_setnvars( p->pSat, sat_solver_nvars(p->pSat) + Vec_WecSize(p->vCuts) ); + // iterate over arrays containing obj-lit cuts (neg-obj-lit cut-lits followed by pos-obj-lit cut-lits) + vLitsPrev = NULL; + Vec_WecForEachLevel( p->vObjCuts, vLits, i ) + { + assert( Vec_IntSize(vLits) >= 2 ); + value = sat_solver_addclause( p->pSat, Vec_IntArray(vLits), Vec_IntLimit(vLits) ); + assert( value ); +/* + // for each cut, add implied nodes + Lits[0] = Abc_LitNot( Vec_IntEntry(vLits, 0) ); + assert( Lits[0] < 2*p->FirstVar ); + Vec_IntForEachEntryStart( vLits, Lit, k, 1 ) + { + assert( Lit >= 2*p->FirstVar ); + Lits[1] = Abc_LitNot( Lit ); + value = sat_solver_addclause( p->pSat, Lits, Lits + 2 ); + assert( value ); + //printf( "Adding clause %d + %d.\n", Lits[0], Lits[1]-2*p->FirstVar ); + } +*/ + //printf( "\n" ); + // create invertor exclusivity clause + if ( i & 1 ) + { + Lits[0] = Abc_LitNot( Vec_IntEntryLast(vLits) ); + Lits[1] = Abc_LitNot( Vec_IntEntryLast(vLitsPrev) ); + value = sat_solver_addclause( p->pSat, Lits, Lits + 2 ); + assert( value ); + //printf( "Adding exclusivity clause %d + %d.\n", Lits[0]-2*p->FirstVar, Lits[1]-2*p->FirstVar ); + } + vLitsPrev = vLits; + } + // add inverters + Vec_WecForEachLevel( p->vCuts, vCutOne, i ) + Vec_IntForEachEntry( vCutOne, Lit, k ) + if ( Abc_Lit2Var(Lit)-1 < p->nInputs ) // input + { + assert( k > 0 ); + Lits[0] = Abc_Var2Lit( Vec_WecSize(p->vObjCuts) + Abc_Lit2Var(Lit)-1, 0 ); + Lits[1] = Abc_Var2Lit( p->FirstVar + i, 1 ); + value = sat_solver_addclause( p->pSat, Lits, Lits + 2 ); + assert( value ); + } + else // internal node + { + Lits[0] = Abc_Var2Lit( Lit-p->LitShift, 0 ); + Lits[1] = Abc_Var2Lit( p->FirstVar + i, 1 ); + value = sat_solver_addclause( p->pSat, Lits, Lits + 2 ); + assert( value ); + } + + sat_solver_set_polarity( p->pSat, Vec_IntArray(p->vPolar), Vec_IntSize(p->vPolar) ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int sat_solver_add_and1( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1, int fCompl ) +{ + lit Lits[3]; + int Cid; + + Lits[0] = toLitCond( iVar, !fCompl ); + Lits[1] = toLitCond( iVar0, fCompl0 ); + Cid = sat_solver_addclause( pSat, Lits, Lits + 2 ); + assert( Cid ); + + Lits[0] = toLitCond( iVar, !fCompl ); + Lits[1] = toLitCond( iVar1, fCompl1 ); + Cid = sat_solver_addclause( pSat, Lits, Lits + 2 ); + assert( Cid ); +/* + Lits[0] = toLitCond( iVar, fCompl ); + Lits[1] = toLitCond( iVar0, !fCompl0 ); + Lits[2] = toLitCond( iVar1, !fCompl1 ); + Cid = sat_solver_addclause( pSat, Lits, Lits + 3 ); + assert( Cid ); +*/ + return 3; +} + +static inline int sat_solver_add_and2( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1, int fCompl ) +{ + lit Lits[3]; + int Cid; +/* + Lits[0] = toLitCond( iVar, !fCompl ); + Lits[1] = toLitCond( iVar0, fCompl0 ); + Cid = sat_solver_addclause( pSat, Lits, Lits + 2 ); + assert( Cid ); + + Lits[0] = toLitCond( iVar, !fCompl ); + Lits[1] = toLitCond( iVar1, fCompl1 ); + Cid = sat_solver_addclause( pSat, Lits, Lits + 2 ); + assert( Cid ); +*/ + Lits[0] = toLitCond( iVar, fCompl ); + Lits[1] = toLitCond( iVar0, !fCompl0 ); + Lits[2] = toLitCond( iVar1, !fCompl1 ); + Cid = sat_solver_addclause( pSat, Lits, Lits + 3 ); + assert( Cid ); + return 3; +} + + +/**Function************************************************************* + + Synopsis [Adds a general cardinality constraint in terms of vVars.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Card_AddClause( Vec_Int_t * p, int* begin, int* end ) +{ + Vec_IntPush( p, (int)(end-begin) ); + while ( begin < end ) + Vec_IntPush( p, (int)*begin++ ); + return 1; +} +static inline int Card_AddHalfSorter( Vec_Int_t * p, int iVarA, int iVarB, int iVar0, int iVar1 ) +{ + lit Lits[3]; + int Cid; + + Lits[0] = toLitCond( iVarA, 0 ); + Lits[1] = toLitCond( iVar0, 1 ); + Cid = Card_AddClause( p, Lits, Lits + 2 ); + assert( Cid ); + + Lits[0] = toLitCond( iVarA, 0 ); + Lits[1] = toLitCond( iVar1, 1 ); + Cid = Card_AddClause( p, Lits, Lits + 2 ); + assert( Cid ); + + Lits[0] = toLitCond( iVarB, 0 ); + Lits[1] = toLitCond( iVar0, 1 ); + Lits[2] = toLitCond( iVar1, 1 ); + Cid = Card_AddClause( p, Lits, Lits + 3 ); + assert( Cid ); + return 3; +} +static inline void Card_AddSorter( Vec_Int_t * p, int * pVars, int i, int k, int * pnVars ) +{ + int iVar1 = (*pnVars)++; + int iVar2 = (*pnVars)++; + Card_AddHalfSorter( p, iVar1, iVar2, pVars[i], pVars[k] ); + pVars[i] = iVar1; + pVars[k] = iVar2; +} +static inline void Card_AddCardinConstrMerge( Vec_Int_t * p, int * pVars, int lo, int hi, int r, int * pnVars ) +{ + int i, step = r * 2; + if ( step < hi - lo ) + { + Card_AddCardinConstrMerge( p, pVars, lo, hi-r, step, pnVars ); + Card_AddCardinConstrMerge( p, pVars, lo+r, hi, step, pnVars ); + for ( i = lo+r; i < hi-r; i += step ) + Card_AddSorter( p, pVars, i, i+r, pnVars ); + for ( i = lo+r; i < hi-r-1; i += r ) + { + lit Lits[2] = { Abc_Var2Lit(pVars[i], 0), Abc_Var2Lit(pVars[i+r], 1) }; + int Cid = Card_AddClause( p, Lits, Lits + 2 ); + assert( Cid ); + } + } +} +static inline void Card_AddCardinConstrRange( Vec_Int_t * p, int * pVars, int lo, int hi, int * pnVars ) +{ + if ( hi - lo >= 1 ) + { + int i, mid = lo + (hi - lo) / 2; + for ( i = lo; i <= mid; i++ ) + Card_AddSorter( p, pVars, i, i + (hi - lo + 1) / 2, pnVars ); + Card_AddCardinConstrRange( p, pVars, lo, mid, pnVars ); + Card_AddCardinConstrRange( p, pVars, mid+1, hi, pnVars ); + Card_AddCardinConstrMerge( p, pVars, lo, hi, 1, pnVars ); + } +} +int Card_AddCardinConstrPairWise( Vec_Int_t * p, Vec_Int_t * vVars ) +{ + int nVars = Vec_IntSize(vVars); + Card_AddCardinConstrRange( p, Vec_IntArray(vVars), 0, nVars - 1, &nVars ); + return nVars; +} +int Card_AddCardinSolver( int LogN, Vec_Int_t ** pvVars, Vec_Int_t ** pvRes ) +{ + int nVars = 1 << LogN; + int nVarsAlloc = nVars + 2 * (nVars * LogN * (LogN-1) / 4 + nVars - 1); + Vec_Int_t * vRes = Vec_IntAlloc( 1000 ); + Vec_Int_t * vVars = Vec_IntStartNatural( nVars ); + int nVarsReal = Card_AddCardinConstrPairWise( vRes, vVars ); + assert( nVarsReal == nVarsAlloc ); + Vec_IntPush( vRes, -1 ); + *pvVars = vVars; + *pvRes = vRes; + return nVarsReal; +} +sat_solver * Sbm_AddCardinSolver2( int LogN, Vec_Int_t ** pvVars, Vec_Int_t ** pvRes ) +{ + Vec_Int_t * vVars = NULL; + Vec_Int_t * vRes = NULL; + int nVarsReal = Card_AddCardinSolver( LogN, &vVars, &vRes ), i, size; + sat_solver * pSat = sat_solver_new(); + sat_solver_setnvars( pSat, nVarsReal ); + for ( i = 0, size = Vec_IntEntry(vRes, i++); i < Vec_IntSize(vRes); i += size, size = Vec_IntEntry(vRes, i++) ) + sat_solver_addclause( pSat, Vec_IntEntryP(vRes, i), Vec_IntEntryP(vRes, i+size) ); + if ( pvVars ) *pvVars = vVars; + if ( pvRes ) *pvRes = vRes; + return pSat; +} + + +/**Function************************************************************* + + Synopsis [Adds a general cardinality constraint in terms of vVars.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Sbm_AddSorter( sat_solver * p, int * pVars, int i, int k, int * pnVars ) +{ + int iVar1 = (*pnVars)++; + int iVar2 = (*pnVars)++; + int fVerbose = 0; + if ( fVerbose ) + { + int v; + for ( v = 0; v < i; v++ ) + printf( " " ); + printf( "<" ); + for ( v = i+1; v < k; v++ ) + printf( "-" ); + printf( ">" ); + for ( v = k+1; v < 8; v++ ) + printf( " " ); + printf( " " ); + printf( "[%3d :%3d ] -> [%3d :%3d ]\n", pVars[i], pVars[k], iVar1, iVar2 ); + } +// sat_solver_add_and1( p, iVar1, pVars[i], pVars[k], 1, 1, 1 ); +// sat_solver_add_and2( p, iVar2, pVars[i], pVars[k], 0, 0, 0 ); + sat_solver_add_half_sorter( p, iVar1, iVar2, pVars[i], pVars[k] ); + pVars[i] = iVar1; + pVars[k] = iVar2; +} +static inline void Sbm_AddCardinConstrMerge( sat_solver * p, int * pVars, int lo, int hi, int r, int * pnVars ) +{ + int i, step = r * 2; + if ( step < hi - lo ) + { + Sbm_AddCardinConstrMerge( p, pVars, lo, hi-r, step, pnVars ); + Sbm_AddCardinConstrMerge( p, pVars, lo+r, hi, step, pnVars ); + for ( i = lo+r; i < hi-r; i += step ) + Sbm_AddSorter( p, pVars, i, i+r, pnVars ); + for ( i = lo+r; i < hi-r-1; i += r ) + { + lit Lits[2] = { Abc_Var2Lit(pVars[i], 0), Abc_Var2Lit(pVars[i+r], 1) }; + int Cid = sat_solver_addclause( p, Lits, Lits + 2 ); + assert( Cid ); + } + } +} +static inline void Sbm_AddCardinConstrRange( sat_solver * p, int * pVars, int lo, int hi, int * pnVars ) +{ + if ( hi - lo >= 1 ) + { + int i, mid = lo + (hi - lo) / 2; + for ( i = lo; i <= mid; i++ ) + Sbm_AddSorter( p, pVars, i, i + (hi - lo + 1) / 2, pnVars ); + Sbm_AddCardinConstrRange( p, pVars, lo, mid, pnVars ); + Sbm_AddCardinConstrRange( p, pVars, mid+1, hi, pnVars ); + Sbm_AddCardinConstrMerge( p, pVars, lo, hi, 1, pnVars ); + } +} +int Sbm_AddCardinConstrPairWise( sat_solver * p, Vec_Int_t * vVars, int K ) +{ + int nVars = Vec_IntSize(vVars); + Sbm_AddCardinConstrRange( p, Vec_IntArray(vVars), 0, nVars - 1, &nVars ); + sat_solver_bookmark( p ); + return nVars; +} +sat_solver * Sbm_AddCardinSolver( int LogN, Vec_Int_t ** pvVars ) +{ + int nVars = 1 << LogN; + int nVarsAlloc = nVars + 2 * (nVars * LogN * (LogN-1) / 4 + nVars - 1), nVarsReal; + Vec_Int_t * vVars = Vec_IntStartNatural( nVars ); + sat_solver * pSat = sat_solver_new(); + sat_solver_setnvars( pSat, nVarsAlloc ); + nVarsReal = Sbm_AddCardinConstrPairWise( pSat, vVars, 2 ); + assert( nVarsReal == nVarsAlloc ); + *pvVars = vVars; + return pSat; +} + +void Sbm_AddCardinConstrTest() +{ + int LogN = 3, nVars = 1 << LogN, K = 2, Count = 1; + Vec_Int_t * vVars, * vLits = Vec_IntAlloc( nVars ); + sat_solver * pSat = Sbm_AddCardinSolver( LogN, &vVars ); + int nVarsReal = sat_solver_nvars( pSat ); + + int Lit = Abc_Var2Lit( Vec_IntEntry(vVars, K), 1 ); + printf( "LogN = %d. N = %3d. Vars = %5d. Clauses = %6d. Comb = %d.\n", LogN, nVars, nVarsReal, sat_solver_nclauses(pSat), nVars * (nVars-1)/2 + nVars + 1 ); + while ( 1 ) + { + int i, status = sat_solver_solve( pSat, &Lit, &Lit+1, 0, 0, 0, 0 ); + if ( status != l_True ) + break; + Vec_IntClear( vLits ); + printf( "%3d : ", Count++ ); + for ( i = 0; i < nVars; i++ ) + { + Vec_IntPush( vLits, Abc_Var2Lit(i, sat_solver_var_value(pSat, i)) ); + printf( "%d", sat_solver_var_value(pSat, i) ); + } + printf( "\n" ); + status = sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + nVars ); + if ( status == 0 ) + break; + } + + sat_solver_delete( pSat ); + Vec_IntFree( vVars ); + Vec_IntFree( vLits ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Sbm_Man_t * Sbm_ManAlloc( int LogN ) +{ + Sbm_Man_t * p = ABC_CALLOC( Sbm_Man_t, 1 ); + p->pSat = Sbm_AddCardinSolver( LogN, &p->vCardVars ); + p->LogN = LogN; + p->FirstVar = sat_solver_nvars( p->pSat ); + // window + p->vRoots = Vec_IntAlloc( 100 ); + p->vCuts = Vec_WecAlloc( 1000 ); + p->vObjCuts = Vec_WecAlloc( 1000 ); + p->vSolCuts = Vec_IntAlloc( 100 ); + p->vCutGates = Vec_IntAlloc( 100 ); + p->vCutAreas = Vec_WrdAlloc( 100 ); + // solver + p->vAssump = Vec_IntAlloc( 100 ); + p->vPolar = Vec_IntAlloc( 100 ); + // timing + p->vArrs = Vec_IntAlloc( 100 ); + p->vReqs = Vec_IntAlloc( 100 ); + // internal + p->vLit2Used = Vec_IntAlloc( 100 ); + p->vDelays = Vec_IntAlloc( 100 ); + p->vReason = Vec_IntAlloc( 100 ); + return p; +} + +void Sbm_ManStop( Sbm_Man_t * p ) +{ + sat_solver_delete( p->pSat ); + Vec_IntFree( p->vCardVars ); + // internal + Vec_IntFree( p->vRoots ); + Vec_WecFree( p->vCuts ); + Vec_WecFree( p->vObjCuts ); + Vec_IntFree( p->vSolCuts ); + Vec_IntFree( p->vCutGates ); + Vec_WrdFree( p->vCutAreas ); + // internal + Vec_IntFree( p->vAssump ); + Vec_IntFree( p->vPolar ); + // internal + Vec_IntFree( p->vArrs ); + Vec_IntFree( p->vReqs ); + // internal + Vec_IntFree( p->vLit2Used ); + Vec_IntFree( p->vDelays ); + Vec_IntFree( p->vReason ); + ABC_FREE( p ); +} + +int Sbm_ManTestSat( void * pMan ) +{ + abctime clk = Abc_Clock(), clk2; + int i, k, Lit, LogN = 7, nVars = 1 << LogN, status, Root; + Sbm_Man_t * p = Sbm_ManAlloc( LogN ); + word InvArea = 0; + int fKeepTrying = 1; + int StartSol; + // derive window + extern int Nf_ManExtractWindow( void * pMan, Vec_Int_t * vRoots, Vec_Wec_t * vCuts, Vec_Wec_t * vObjCuts, Vec_Int_t * vSolCuts, Vec_Int_t * vCutGates, Vec_Wrd_t * vCutAreas, word * pInvArea, int StartVar, int nVars ); + p->nInputs = Nf_ManExtractWindow( pMan, p->vRoots, p->vCuts, p->vObjCuts, p->vSolCuts, p->vCutGates, p->vCutAreas, &InvArea, p->FirstVar, nVars ); + p->LitShift = 2*p->nInputs+2; + assert( Vec_WecSize(p->vObjCuts) + p->nInputs <= nVars ); + + // print-out +// Vec_WecPrint( p->vCuts, 0 ); +// printf( "\n" ); +// Vec_WecPrint( p->vObjCuts, 0 ); +// printf( "\n" ); + Vec_IntPrint( p->vSolCuts ); + printf( "All clauses = %d. Multi clauses = %d. Binary clauses = %d. Other clauses = %d.\n", + sat_solver_nclauses(p->pSat), Vec_WecSize(p->vObjCuts), Vec_WecSizeSize(p->vCuts), + sat_solver_nclauses(p->pSat) - Vec_WecSize(p->vObjCuts) - Vec_WecSizeSize(p->vCuts) ); + + // creating CNF + if ( !Sbm_ManCreateCnf(p) ) + return 0; + + // create assumptions + // cardinality + Vec_IntClear( p->vAssump ); + Vec_IntPush( p->vAssump, -1 ); + // unused variables + for ( i = Vec_WecSize(p->vObjCuts) + p->nInputs; i < nVars; i++ ) + Vec_IntPush( p->vAssump, Abc_Var2Lit(i, 1) ); + // root variables + Vec_IntForEachEntry( p->vRoots, Root, i ) + Vec_IntPush( p->vAssump, Abc_Var2Lit(Root, 0) ); +// Vec_IntPrint( p->vAssump ); + + StartSol = Vec_IntSize(p->vSolCuts); +// StartSol = 30; + while ( fKeepTrying && StartSol-fKeepTrying > 0 ) + { + printf( "Trying to find mapping with %d gates.\n", StartSol-fKeepTrying ); + // for ( i = Vec_IntSize(p->vSolCuts)-5; i < nVars; i++ ) + // Vec_IntPush( p->vAssump, Abc_Var2Lit(Vec_IntEntry(p->vCardVars, i), 1) ); + Vec_IntWriteEntry( p->vAssump, 0, Abc_Var2Lit(Vec_IntEntry(p->vCardVars, StartSol-fKeepTrying), 1) ); + // solve the problem + clk2 = Abc_Clock(); + status = sat_solver_solve( p->pSat, Vec_IntArray(p->vAssump), Vec_IntLimit(p->vAssump), 0, 0, 0, 0 ); + if ( status == l_True ) + { + word AreaNew = 0; + int Count = 0; + printf( "AND Lits = %d. Inputs = %d. Vars = %d. All vars = %d.\n", Vec_WecSize(p->vObjCuts), p->nInputs, Vec_WecSize(p->vObjCuts) + p->nInputs, nVars ); +// for ( i = 0; i < nVars; i++ ) +// printf( "%d", sat_solver_var_value(p->pSat, i) ); +// printf( "\n" ); + for ( i = 0; i < nVars; i++ ) + if ( sat_solver_var_value(p->pSat, i) ) + { + printf( "%d=%d ", i, sat_solver_var_value(p->pSat, i) ); + Count++; + if ( i >= Vec_WecSize(p->vObjCuts) ) + AreaNew += InvArea; + } + printf( "Count = %d\n", Count ); +// for ( i = p->FirstVar; i < sat_solver_nvars(p->pSat); i++ ) +// printf( "%d", sat_solver_var_value(p->pSat, i) ); +// printf( "\n" ); + Count = 1; + for ( i = p->FirstVar; i < sat_solver_nvars(p->pSat); i++ ) + if ( sat_solver_var_value(p->pSat, i) ) + { + Vec_Int_t * vCutOne = Vec_WecEntry(p->vCuts, i-p->FirstVar); + printf( "%2d : Cut %3d (Gate %2d) ", Count, i-p->FirstVar, Vec_IntEntry(p->vCutGates, i-p->FirstVar) ); + Vec_IntForEachEntry( vCutOne, Lit, k ) + printf( "%d(%d) ", Lit - 2*(p->nInputs+1), Abc_Lit2Var(Lit) ); + printf( "\n" ); + Count++; + AreaNew += Vec_WrdEntry(p->vCutAreas, i-p->FirstVar); + } + printf( "Area = %7.2f\n", Scl_Int2Flt((int)AreaNew) ); + } + if ( status == l_False ) + printf( "UNSAT " ), fKeepTrying = 0; + else if ( status == l_True ) + printf( "SAT " ), fKeepTrying++; + Abc_PrintTime( 1, "Time", Abc_Clock() - clk2 ); + Abc_PrintTime( 1, "Total time", Abc_Clock() - clk ); + printf( "\n" ); + } + Sbm_ManStop( p ); + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaSatSyn.c b/yosys/abc/src/aig/gia/giaSatSyn.c new file mode 100644 index 00000000000..15829f79b90 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaSatSyn.c @@ -0,0 +1,60 @@ +/**CFile**************************************************************** + + FileName [giaSyn.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [High-effort synthesis.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSyn.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/util/utilTruth.h" +#include "sat/glucose/AbcGlucose.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManSyn( Gia_Man_t * p, int nNodes, int nOuts, int nTimeLimit, int fUseXor, int fFancy, int fVerbose ) +{ + Gia_Man_t * pNew = NULL; + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaSatoko.c b/yosys/abc/src/aig/gia/giaSatoko.c new file mode 100644 index 00000000000..dad3bcc4f01 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaSatoko.c @@ -0,0 +1,274 @@ +/**CFile**************************************************************** + + FileName [giaSatoko.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Interface to Satoko solver.] + + Author [Alan Mishchenko, Bruno Schmitt] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSatoko.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "sat/cnf/cnf.h" +#include "misc/extra/extra.h" +#include "sat/satoko/satoko.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCollectVars_rec( int Var, Vec_Int_t * vMapping, Vec_Int_t * vRes, Vec_Bit_t * vVisit ) +{ + int * pCut, i; + if ( Vec_BitEntry(vVisit, Var) ) + return; + Vec_BitWriteEntry(vVisit, Var, 1); + if ( Vec_IntEntry(vMapping, Var) ) // primary input or constant 0 + { + pCut = Vec_IntEntryP( vMapping, Vec_IntEntry(vMapping, Var) ); + for ( i = 1; i <= pCut[0]; i++ ) + Gia_ManCollectVars_rec( pCut[i], vMapping, vRes, vVisit ); + } + Vec_IntPush( vRes, Var ); +} +Vec_Int_t * Gia_ManCollectVars( int Root, Vec_Int_t * vMapping, int nVars ) +{ + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); + Vec_Bit_t * vVisit = Vec_BitStart( nVars ); + assert( Vec_IntEntry(vMapping, Root) ); + Gia_ManCollectVars_rec( Root, vMapping, vRes, vVisit ); + Vec_BitFree( vVisit ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSatokoReport( int iOutput, int status, abctime clk ) +{ + if ( iOutput >= 0 ) + Abc_Print( 1, "Output %6d : ", iOutput ); + else + Abc_Print( 1, "Total: " ); + + if ( status == SATOKO_UNDEC ) + Abc_Print( 1, "UNDECIDED " ); + else if ( status == SATOKO_SAT ) + Abc_Print( 1, "SATISFIABLE " ); + else + Abc_Print( 1, "UNSATISFIABLE " ); + + Abc_PrintTime( 1, "Time", clk ); +} +satoko_t * Gia_ManSatokoFromDimacs( char * pFileName, satoko_opts_t * opts ) +{ + satoko_t * pSat = satoko_create(); + char * pBuffer = Extra_FileReadContents( pFileName ); + Vec_Int_t * vLits = Vec_IntAlloc( 100 ); + char * pTemp; int fComp, Var, VarMax = 0; + for ( pTemp = pBuffer; *pTemp; pTemp++ ) + { + if ( *pTemp == 'c' || *pTemp == 'p' ) + { + while ( *pTemp != '\n' ) + pTemp++; + continue; + } + while ( *pTemp == ' ' || *pTemp == '\t' || *pTemp == '\r' || *pTemp == '\n' ) + pTemp++; + fComp = 0; + if ( *pTemp == '-' ) + fComp = 1, pTemp++; + if ( *pTemp == '+' ) + pTemp++; + Var = atoi( pTemp ); + if ( Var == 0 ) { + if ( Vec_IntSize(vLits) > 0 ) + { + satoko_setnvars( pSat, VarMax+1 ); + if ( !satoko_add_clause( pSat, Vec_IntArray(vLits), Vec_IntSize(vLits) ) ) + { + satoko_destroy(pSat); + Vec_IntFree( vLits ); + ABC_FREE( pBuffer ); + return NULL; + } + Vec_IntClear( vLits ); + } + } + else + { + Var--; + VarMax = Abc_MaxInt( VarMax, Var ); + Vec_IntPush( vLits, Abc_Var2Lit(Var, fComp) ); + } + while ( *pTemp >= '0' && *pTemp <= '9' ) + pTemp++; + } + ABC_FREE( pBuffer ); + Vec_IntFree( vLits ); + return pSat; +} +void Gia_ManSatokoDimacs( char * pFileName, satoko_opts_t * opts ) +{ + abctime clk = Abc_Clock(); + int status = SATOKO_UNSAT; + satoko_t * pSat = Gia_ManSatokoFromDimacs( pFileName, opts ); + if ( pSat ) + { + status = satoko_solve( pSat ); + satoko_destroy( pSat ); + } + Gia_ManSatokoReport( -1, status, Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +satoko_t * Gia_ManSatokoInit( Cnf_Dat_t * pCnf, satoko_opts_t * opts ) +{ + satoko_t * pSat = satoko_create(); + int i; + //sat_solver_setnvars( pSat, p->nVars ); + for ( i = 0; i < pCnf->nClauses; i++ ) + { + if ( !satoko_add_clause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1]-pCnf->pClauses[i] ) ) + { + satoko_destroy( pSat ); + return NULL; + } + } + satoko_configure(pSat, opts); + return pSat; +} +satoko_t * Gia_ManSatokoCreate( Gia_Man_t * p, satoko_opts_t * opts ) +{ + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( p, 8, 0, 1, 0, 0 ); + satoko_t * pSat = Gia_ManSatokoInit( pCnf, opts ); + int status = pSat ? satoko_simplify(pSat) : SATOKO_OK; + Cnf_DataFree( pCnf ); + if ( status == SATOKO_OK ) + return pSat; + satoko_destroy( pSat ); + return NULL; +} +int Gia_ManSatokoCallOne( Gia_Man_t * p, satoko_opts_t * opts, int iOutput ) +{ + abctime clk = Abc_Clock(); + satoko_t * pSat; + int status = SATOKO_UNSAT, Cost = 0; + pSat = Gia_ManSatokoCreate( p, opts ); + if ( pSat ) + { + status = satoko_solve( pSat ); + Cost = satoko_stats(pSat)->n_conflicts; + satoko_destroy( pSat ); + } + Gia_ManSatokoReport( iOutput, status, Abc_Clock() - clk ); + return Cost; +} +void Gia_ManSatokoCall( Gia_Man_t * p, satoko_opts_t * opts, int fSplit, int fIncrem ) +{ + int fUseCone = 1; + Gia_Man_t * pOne; + Gia_Obj_t * pRoot; + Vec_Int_t * vCone; + int i, iLit, status; + if ( fIncrem ) + { + abctime clk = Abc_Clock(); + Cnf_Dat_t * pCnf = (Cnf_Dat_t *)Mf_ManGenerateCnf( p, 8, 0, 0, fUseCone, 0 ); + satoko_t * pSat = Gia_ManSatokoInit( pCnf, opts ); + Gia_ManForEachCo( p, pRoot, i ) + { + abctime clk = Abc_Clock(); + iLit = Abc_Var2Lit( i+1, 0 ); + satoko_assump_push( pSat, iLit ); + if ( fUseCone ) + { + vCone = Gia_ManCollectVars( i+1, pCnf->vMapping, pCnf->nVars ); + satoko_mark_cone( pSat, Vec_IntArray(vCone), Vec_IntSize(vCone) ); + printf( "Cone has %6d vars (out of %6d). ", Vec_IntSize(vCone), pCnf->nVars ); + status = satoko_solve( pSat ); + satoko_unmark_cone( pSat, Vec_IntArray(vCone), Vec_IntSize(vCone) ); + Vec_IntFree( vCone ); + } + else + { + status = satoko_solve( pSat ); + } + satoko_assump_pop( pSat ); + Gia_ManSatokoReport( i, status, Abc_Clock() - clk ); + } + Cnf_DataFree( pCnf ); + satoko_destroy( pSat ); + Abc_PrintTime( 1, "Total time", Abc_Clock() - clk ); + return; + } + if ( fSplit ) + { + abctime clk = Abc_Clock(); + Gia_ManForEachCo( p, pRoot, i ) + { + pOne = Gia_ManDupDfsCone( p, pRoot ); + Gia_ManSatokoCallOne( pOne, opts, i ); + Gia_ManStop( pOne ); + } + Abc_PrintTime( 1, "Total time", Abc_Clock() - clk ); + return; + } + Gia_ManSatokoCallOne( p, opts, -1 ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaScl.c b/yosys/abc/src/aig/gia/giaScl.c new file mode 100644 index 00000000000..70bc9fe8629 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaScl.c @@ -0,0 +1,300 @@ +/**CFile**************************************************************** + + FileName [giaScl.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Sequential cleanup.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaScl.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Marks unreachable internal nodes and returns their number.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCombMarkUsed_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( pObj == NULL ) + return 0; + if ( !pObj->fMark0 ) + return 0; + pObj->fMark0 = 0; + assert( Gia_ObjIsAnd(pObj) ); + assert( !Gia_ObjIsBuf(pObj) ); + return 1 + Gia_ManCombMarkUsed_rec( p, Gia_ObjFanin0(pObj) ) + + Gia_ManCombMarkUsed_rec( p, Gia_ObjFanin1(pObj) ) + + (p->pNexts ? Gia_ManCombMarkUsed_rec( p, Gia_ObjNextObj(p, Gia_ObjId(p, pObj)) ) : 0) + + (p->pSibls ? Gia_ManCombMarkUsed_rec( p, Gia_ObjSiblObj(p, Gia_ObjId(p, pObj)) ) : 0) + + (p->pMuxes ? Gia_ManCombMarkUsed_rec( p, Gia_ObjFanin2(p, pObj) ) : 0); +} +int Gia_ManCombMarkUsed( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, nNodes = 0; + Gia_ManForEachObj( p, pObj, i ) + pObj->fMark0 = Gia_ObjIsAnd(pObj) && !Gia_ObjIsBuf(pObj); + Gia_ManForEachBuf( p, pObj, i ) + nNodes += Gia_ManCombMarkUsed_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + nNodes += Gia_ManCombMarkUsed_rec( p, Gia_ObjFanin0(pObj) ); + return nNodes; +} + +/**Function************************************************************* + + Synopsis [Performs combinational cleanup.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManCleanup( Gia_Man_t * p ) +{ + Gia_ManCombMarkUsed( p ); + return Gia_ManDupMarked( p ); +} + +/**Function************************************************************* + + Synopsis [Skip the first outputs during cleanup.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManCleanupOutputs( Gia_Man_t * p, int nOutputs ) +{ + Gia_Obj_t * pObj; + int i; + assert( Gia_ManRegNum(p) == 0 ); + assert( nOutputs < Gia_ManCoNum(p) ); + Gia_ManCombMarkUsed( p ); + Gia_ManForEachCo( p, pObj, i ) + if ( i < nOutputs ) + pObj->fMark0 = 1; + else + break; + return Gia_ManDupMarked( p ); +} + + +/**Function************************************************************* + + Synopsis [Marks CIs/COs/ANDs unreachable from POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSeqMarkUsed_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vRoots ) +{ + if ( !pObj->fMark0 ) + return 0; + pObj->fMark0 = 0; + if ( Gia_ObjIsCo(pObj) ) + return Gia_ManSeqMarkUsed_rec( p, Gia_ObjFanin0(pObj), vRoots ); + if ( Gia_ObjIsRo(p, pObj) ) + { + Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ObjRoToRi(p, pObj)) ); + return 0; + } + assert( Gia_ObjIsAnd(pObj) ); + return 1 + Gia_ManSeqMarkUsed_rec( p, Gia_ObjFanin0(pObj), vRoots ) + + Gia_ManSeqMarkUsed_rec( p, Gia_ObjFanin1(pObj), vRoots ); +} + +/**Function************************************************************* + + Synopsis [Marks CIs/COs/ANDs unreachable from POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSeqMarkUsed( Gia_Man_t * p ) +{ + Vec_Int_t * vRoots; + Gia_Obj_t * pObj; + int i, nNodes = 0; + Gia_ManSetMark0( p ); + Gia_ManConst0(p)->fMark0 = 0; + Gia_ManForEachPi( p, pObj, i ) + pObj->fMark0 = 0; + vRoots = Gia_ManCollectPoIds( p ); + Gia_ManForEachObjVec( vRoots, p, pObj, i ) + nNodes += Gia_ManSeqMarkUsed_rec( p, pObj, vRoots ); + Vec_IntFree( vRoots ); + return nNodes; +} + +/**Function************************************************************* + + Synopsis [Performs sequential cleanup.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManSeqCleanup( Gia_Man_t * p ) +{ + Gia_ManSeqMarkUsed( p ); + return Gia_ManDupMarked( p ); +} + +/**Function************************************************************* + + Synopsis [Find representatives due to identical fanins.] + + Description [Returns the old manager if there is no changes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManReduceEquiv( Gia_Man_t * p, int fVerbose ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObjRi, * pObjRo; + unsigned * pCi2Lit, * pMaps; + int i, iLit, nFanins = 1, Counter0 = 0, Counter = 0; + Gia_ManForEachRi( p, pObjRi, i ) + Gia_ObjFanin0(pObjRi)->Value = 0; + Gia_ManForEachRi( p, pObjRi, i ) + if ( Gia_ObjFanin0(pObjRi)->Value == 0 ) + Gia_ObjFanin0(pObjRi)->Value = 2*nFanins++; + pCi2Lit = ABC_FALLOC( unsigned, Gia_ManCiNum(p) ); + pMaps = ABC_FALLOC( unsigned, 2 * nFanins ); + Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) + { + iLit = Gia_ObjFanin0Copy( pObjRi ); + if ( Gia_ObjFaninId0p(p, pObjRi) == 0 && Gia_ObjFaninC0(pObjRi) == 0 ) // const 0 + pCi2Lit[Gia_ManPiNum(p)+i] = 0, Counter0++; + else if ( ~pMaps[iLit] ) // in this case, ID(pObj) > ID(pRepr) + pCi2Lit[Gia_ManPiNum(p)+i] = pMaps[iLit], Counter++; + else + pMaps[iLit] = Abc_Var2Lit( Gia_ObjId(p, pObjRo), 0 ); + } +/* + Gia_ManForEachCi( p, pObjRo, i ) + { + if ( ~pCi2Lit[i] ) + { + Gia_Obj_t * pObj0 = Gia_ObjRoToRi(p, pObjRo); + Gia_Obj_t * pObj1 = Gia_ObjRoToRi(p, Gia_ManObj(p, pCi2Lit[i])); + Gia_Obj_t * pFan0 = Gia_ObjChild0( p, Gia_ObjRoToRi(p, pObjRo) ); + Gia_Obj_t * pFan1 = Gia_ObjChild0( p, Gia_ObjRoToRi(p, Gia_ManObj(p, pCi2Lit[i])) ); + assert( pFan0 == pFan1 ); + } + } +*/ +// if ( fVerbose ) +// printf( "ReduceEquiv detected %d constant regs and %d equivalent regs.\n", Counter0, Counter ); + ABC_FREE( pMaps ); + if ( Counter0 || Counter ) + pNew = Gia_ManDupDfsCiMap( p, (int *)pCi2Lit, NULL ); + else + pNew = p; + ABC_FREE( pCi2Lit ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Performs sequential cleanup.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManSeqStructSweep( Gia_Man_t * p, int fConst, int fEquiv, int fVerbose ) +{ + Gia_Man_t * pTemp; + if ( Gia_ManRegNum(p) == 0 ) + return Gia_ManCleanup( p ); + if ( fVerbose ) + printf( "Performing sequential cleanup.\n" ); + p = Gia_ManSeqCleanup( pTemp = p ); + if ( fVerbose ) + Gia_ManReportImprovement( pTemp, p ); + if ( fConst && Gia_ManRegNum(p) ) + { + p = Gia_ManReduceConst( pTemp = p, fVerbose ); + if ( fVerbose ) + Gia_ManReportImprovement( pTemp, p ); + Gia_ManStop( pTemp ); + } + if ( fVerbose && fEquiv ) + printf( "Merging combinationally equivalent flops.\n" ); + if ( fEquiv ) + while ( 1 ) + { + p = Gia_ManSeqCleanup( pTemp = p ); + if ( fVerbose ) + Gia_ManReportImprovement( pTemp, p ); + Gia_ManStop( pTemp ); + if ( Gia_ManRegNum(p) == 0 ) + break; + p = Gia_ManReduceEquiv( pTemp = p, fVerbose ); + if ( p == pTemp ) + break; + Gia_ManStop( pTemp ); + } + return p; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaScript.c b/yosys/abc/src/aig/gia/giaScript.c new file mode 100644 index 00000000000..b52288a946e --- /dev/null +++ b/yosys/abc/src/aig/gia/giaScript.c @@ -0,0 +1,808 @@ +/**CFile**************************************************************** + + FileName [giaScript.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Various hardcoded scripts.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaScript.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "giaAig.h" +#include "base/main/main.h" +#include "base/cmd/cmd.h" +#include "proof/dch/dch.h" +#include "opt/dau/dau.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Synthesis script.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManAigPrintPiLevels( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachPi( p, pObj, i ) + printf( "%d ", Gia_ObjLevel(p, pObj) ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Synthesis script.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManAigSyn2( Gia_Man_t * pInit, int fOldAlgo, int fCoarsen, int fCutMin, int nRelaxRatio, int fDelayMin, int fVerbose, int fVeryVerbose ) +{ + Gia_Man_t * p, * pNew, * pTemp; + Jf_Par_t Pars, * pPars = &Pars; + if ( fOldAlgo ) + { + Jf_ManSetDefaultPars( pPars ); + pPars->fCutMin = fCutMin; + } + else + { + Lf_ManSetDefaultPars( pPars ); + pPars->fCutMin = fCutMin; + pPars->fCoarsen = fCoarsen; + pPars->nRelaxRatio = nRelaxRatio; + pPars->nAreaTuner = 1; + pPars->nCutNum = 4; + } + if ( fVerbose ) Gia_ManPrintStats( pInit, NULL ); + p = Gia_ManDup( pInit ); + Gia_ManTransferTiming( p, pInit ); + if ( Gia_ManAndNum(p) == 0 ) + { + pNew = Gia_ManDup(p); + Gia_ManTransferTiming( pNew, p ); + Gia_ManStop( p ); + return pNew; + } + // delay optimization + if ( fDelayMin && p->pManTime == NULL ) + { + int Area0, Area1, Delay0, Delay1; + int fCutMin = pPars->fCutMin; + int fCoarsen = pPars->fCoarsen; + int nRelaxRatio = pPars->nRelaxRatio; + pPars->fCutMin = 0; + pPars->fCoarsen = 0; + pPars->nRelaxRatio = 0; + // perform mapping + if ( fOldAlgo ) + Jf_ManPerformMapping( p, pPars ); + else + Lf_ManPerformMapping( p, pPars ); + Area0 = (int)pPars->Area; + Delay0 = (int)pPars->Delay; + // perform balancing + pNew = Gia_ManPerformDsdBalance( p, 6, 4, 0, 0 ); + // perform mapping again + if ( fOldAlgo ) + Jf_ManPerformMapping( pNew, pPars ); + else + Lf_ManPerformMapping( pNew, pPars ); + Area1 = (int)pPars->Area; + Delay1 = (int)pPars->Delay; + // choose the best result + if ( Delay1 < Delay0 - 1 || (Delay1 == Delay0 + 1 && 100.0 * (Area1 - Area0) / Area1 < 3.0) ) + { + Gia_ManStop( p ); + p = pNew; + } + else + { + Gia_ManStop( pNew ); + Vec_IntFreeP( &p->vMapping ); + } + // reset params + pPars->fCutMin = fCutMin; + pPars->fCoarsen = fCoarsen; + pPars->nRelaxRatio = nRelaxRatio; + } + // perform balancing + pNew = Gia_ManAreaBalance( p, 0, ABC_INFINITY, fVeryVerbose, 0 ); + if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); + Gia_ManStop( p ); + // perform mapping + if ( fOldAlgo ) + pNew = Jf_ManPerformMapping( pTemp = pNew, pPars ); + else + pNew = Lf_ManPerformMapping( pTemp = pNew, pPars ); + if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); + if ( pTemp != pNew ) + Gia_ManStop( pTemp ); + // perform balancing + pNew = Gia_ManAreaBalance( pTemp = pNew, 0, ABC_INFINITY, fVeryVerbose, 0 ); + if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); + Gia_ManStop( pTemp ); + return pNew; +} +Gia_Man_t * Gia_ManAigSyn3( Gia_Man_t * p, int fVerbose, int fVeryVerbose ) +{ + Gia_Man_t * pNew, * pTemp; + Jf_Par_t Pars, * pPars = &Pars; + Jf_ManSetDefaultPars( pPars ); + pPars->nRelaxRatio = 40; + if ( fVerbose ) Gia_ManPrintStats( p, NULL ); + if ( Gia_ManAndNum(p) == 0 ) + { + pNew = Gia_ManDup(p); + Gia_ManTransferTiming( pNew, p ); + //Gia_ManStop( p ); + return pNew; + } + // perform balancing + pNew = Gia_ManAreaBalance( p, 0, ABC_INFINITY, fVeryVerbose, 0 ); + if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); + // perform mapping + pPars->nLutSize = 6; + pNew = Jf_ManPerformMapping( pTemp = pNew, pPars ); + if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); +// Gia_ManStop( pTemp ); + // perform balancing + pNew = Gia_ManAreaBalance( pTemp = pNew, 0, ABC_INFINITY, fVeryVerbose, 0 ); + if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); + Gia_ManStop( pTemp ); + // perform mapping + pPars->nLutSize = 4; + pNew = Jf_ManPerformMapping( pTemp = pNew, pPars ); + if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); +// Gia_ManStop( pTemp ); + // perform balancing + pNew = Gia_ManAreaBalance( pTemp = pNew, 0, ABC_INFINITY, fVeryVerbose, 0 ); + if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); + Gia_ManStop( pTemp ); + return pNew; +} +Gia_Man_t * Gia_ManAigSyn4( Gia_Man_t * p, int fVerbose, int fVeryVerbose ) +{ + Gia_Man_t * pNew, * pTemp; + Jf_Par_t Pars, * pPars = &Pars; + Jf_ManSetDefaultPars( pPars ); + pPars->nRelaxRatio = 40; + if ( fVerbose ) Gia_ManPrintStats( p, NULL ); + if ( Gia_ManAndNum(p) == 0 ) + { + pNew = Gia_ManDup(p); + Gia_ManTransferTiming( pNew, p ); + //Gia_ManStop( p ); + return pNew; + } +//Gia_ManAigPrintPiLevels( p ); + // perform balancing + pNew = Gia_ManAreaBalance( p, 0, ABC_INFINITY, fVeryVerbose, 0 ); + if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); + // perform mapping + pPars->nLutSize = 7; + pNew = Jf_ManPerformMapping( pTemp = pNew, pPars ); + if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); +// Gia_ManStop( pTemp ); + // perform extraction + pNew = Gia_ManPerformFx( pTemp = pNew, ABC_INFINITY, 0, 0, fVeryVerbose, 0 ); + if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); + Gia_ManStop( pTemp ); + // perform balancing + pNew = Gia_ManAreaBalance( pTemp = pNew, 0, ABC_INFINITY, fVeryVerbose, 0 ); + if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); + Gia_ManStop( pTemp ); + // perform mapping + pPars->nLutSize = 5; + pNew = Jf_ManPerformMapping( pTemp = pNew, pPars ); + if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); +// Gia_ManStop( pTemp ); + // perform extraction + pNew = Gia_ManPerformFx( pTemp = pNew, ABC_INFINITY, 0, 0, fVeryVerbose, 0 ); + if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); + Gia_ManStop( pTemp ); + // perform balancing + pNew = Gia_ManAreaBalance( pTemp = pNew, 0, ABC_INFINITY, fVeryVerbose, 0 ); + if ( fVerbose ) Gia_ManPrintStats( pNew, NULL ); + Gia_ManStop( pTemp ); +//Gia_ManAigPrintPiLevels( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager.] + + Description [This duplicator works for AIGs with choices.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Gia_ManOrderPios( Aig_Man_t * p, Gia_Man_t * pOrder ) +{ + Vec_Ptr_t * vPios; + Gia_Obj_t * pObj; + int i; + assert( Aig_ManCiNum(p) == Gia_ManCiNum(pOrder) ); + assert( Aig_ManCoNum(p) == Gia_ManCoNum(pOrder) ); + vPios = Vec_PtrAlloc( Aig_ManCiNum(p) + Aig_ManCoNum(p) ); + Gia_ManForEachObj( pOrder, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + Vec_PtrPush( vPios, Aig_ManCi(p, Gia_ObjCioId(pObj)) ); + else if ( Gia_ObjIsCo(pObj) ) + Vec_PtrPush( vPios, Aig_ManCo(p, Gia_ObjCioId(pObj)) ); + } + return vPios; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupFromBarBufs( Gia_Man_t * p ) +{ + Vec_Int_t * vBufObjs; + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i, k = 0; + assert( Gia_ManBufNum(p) > 0 ); + assert( Gia_ManRegNum(p) == 0 ); + assert( !Gia_ManHasChoices(p) ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + vBufObjs = Vec_IntAlloc( Gia_ManBufNum(p) ); + for ( i = 0; i < Gia_ManBufNum(p); i++ ) + Vec_IntPush( vBufObjs, Gia_ManAppendCi(pNew) ); + Gia_ManForEachAnd( p, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + { + pObj->Value = Vec_IntEntry( vBufObjs, k ); + Vec_IntWriteEntry( vBufObjs, k++, Gia_ObjFanin0Copy(pObj) ); + } + else + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + assert( k == Gia_ManBufNum(p) ); + for ( i = 0; i < Gia_ManBufNum(p); i++ ) + Gia_ManAppendCo( pNew, Vec_IntEntry(vBufObjs, i) ); + Vec_IntFree( vBufObjs ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} +Gia_Man_t * Gia_ManDupToBarBufs( Gia_Man_t * p, int nBarBufs ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int nPiReal = Gia_ManCiNum(p) - nBarBufs; + int nPoReal = Gia_ManCoNum(p) - nBarBufs; + int i, k = 0; + assert( Gia_ManBufNum(p) == 0 ); + assert( Gia_ManRegNum(p) == 0 ); + assert( Gia_ManHasChoices(p) ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + if ( Gia_ManHasChoices(p) ) + pNew->pSibls = ABC_CALLOC( int, Gia_ManObjNum(p) ); + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = 0; + for ( i = 0; i < nPiReal; i++ ) + Gia_ManCi(p, i)->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + { + for ( ; k < nBarBufs; k++ ) + if ( ~Gia_ObjFanin0(Gia_ManCo(p, k))->Value ) + Gia_ManCi(p, nPiReal + k)->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(Gia_ManCo(p, k)) ); + else + break; + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) ) + pNew->pSibls[Abc_Lit2Var(pObj->Value)] = Abc_Lit2Var(Gia_ObjSiblObj(p, Gia_ObjId(p, pObj))->Value); + } + for ( ; k < nBarBufs; k++ ) + if ( ~Gia_ObjFanin0Copy(Gia_ManCo(p, k)) ) + Gia_ManCi(p, nPiReal + k)->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(Gia_ManCo(p, k)) ); + assert( k == nBarBufs ); + for ( i = 0; i < nPoReal; i++ ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(Gia_ManCo(p, nBarBufs+i)) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + assert( Gia_ManBufNum(pNew) == nBarBufs ); + assert( Gia_ManCiNum(pNew) == nPiReal ); + assert( Gia_ManCoNum(pNew) == nPoReal ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManAigSynch2Choices( Gia_Man_t * pGia1, Gia_Man_t * pGia2, Gia_Man_t * pGia3, Dch_Pars_t * pPars ) +{ + Aig_Man_t * pMan, * pTemp; + Gia_Man_t * pGia, * pMiter; + // derive miter + Vec_Ptr_t * vPios, * vGias = Vec_PtrAlloc( 3 ); + if ( pGia3 ) Vec_PtrPush( vGias, pGia3 ); + if ( pGia2 ) Vec_PtrPush( vGias, pGia2 ); + if ( pGia1 ) Vec_PtrPush( vGias, pGia1 ); + pMiter = Gia_ManChoiceMiter( vGias ); + Vec_PtrFree( vGias ); + // transform into an AIG + pMan = Gia_ManToAigSkip( pMiter, 3 ); + Gia_ManStop( pMiter ); + // compute choices + pMan = Dch_ComputeChoices( pTemp = pMan, pPars ); + Aig_ManStop( pTemp ); + // reconstruct the network + vPios = Gia_ManOrderPios( pMan, pGia1 ); + pMan = Aig_ManDupDfsGuided( pTemp = pMan, vPios ); + Aig_ManStop( pTemp ); + Vec_PtrFree( vPios ); + // convert to GIA + pGia = Gia_ManFromAigChoices( pMan ); + Aig_ManStop( pMan ); + return pGia; +} +Gia_Man_t * Gia_ManAigSynch2( Gia_Man_t * pInit, void * pPars0, int nLutSize, int nRelaxRatio ) +{ + extern Gia_Man_t * Gia_ManLutBalance( Gia_Man_t * p, int nLutSize, int fUseMuxes, int fRecursive, int fOptArea, int fVerbose ); + Dch_Pars_t * pParsDch = (Dch_Pars_t *)pPars0; + Gia_Man_t * pGia1, * pGia2, * pGia3, * pNew, * pTemp; + int fVerbose = pParsDch->fVerbose; + Jf_Par_t Pars, * pPars = &Pars; + Lf_ManSetDefaultPars( pPars ); + pPars->fCutMin = 1; + pPars->fCoarsen = 1; + pPars->nRelaxRatio = nRelaxRatio; + pPars->nAreaTuner = 5; + pPars->nCutNum = 12; + pPars->fVerbose = fVerbose; + if ( fVerbose ) Gia_ManPrintStats( pInit, NULL ); + pGia1 = Gia_ManDup( pInit ); + if ( Gia_ManAndNum(pGia1) == 0 ) + { + Gia_ManTransferTiming( pGia1, pInit ); + return pGia1; + } + if ( pGia1->pManTime && pGia1->vLevels == NULL ) + Gia_ManLevelWithBoxes( pGia1 ); + // unmap if mapped + if ( Gia_ManHasMapping(pInit) ) + { + Gia_ManTransferMapping( pGia1, pInit ); + pGia1 = (Gia_Man_t *)Dsm_ManDeriveGia( pTemp = pGia1, 0 ); + Gia_ManStop( pTemp ); + } + // perform balancing + if ( Gia_ManBufNum(pGia1) || 1 ) + pGia2 = Gia_ManAreaBalance( pGia1, 0, ABC_INFINITY, 0, 0 ); + else + { + pGia2 = Gia_ManLutBalance( pGia1, nLutSize, 1, 1, 1, 0 ); + pGia2 = Gia_ManAreaBalance( pTemp = pGia2, 0, ABC_INFINITY, 0, 0 ); + Gia_ManStop( pTemp ); + } + if ( fVerbose ) Gia_ManPrintStats( pGia2, NULL ); + // perform mapping + pGia2 = Lf_ManPerformMapping( pTemp = pGia2, pPars ); + if ( fVerbose ) Gia_ManPrintStats( pGia2, NULL ); + if ( pTemp != pGia2 ) + Gia_ManStop( pTemp ); + // perform balancing + if ( pParsDch->fLightSynth || Gia_ManBufNum(pGia2) ) + pGia3 = Gia_ManAreaBalance( pGia2, 0, ABC_INFINITY, 0, 0 ); + else + { + assert( Gia_ManBufNum(pGia2) == 0 ); + pGia2 = Gia_ManAreaBalance( pTemp = pGia2, 0, ABC_INFINITY, 0, 0 ); + if ( fVerbose ) Gia_ManPrintStats( pGia2, NULL ); + Gia_ManStop( pTemp ); + // perform DSD balancing + pGia3 = Gia_ManPerformDsdBalance( pGia2, 6, 8, 0, 0 ); + } + if ( fVerbose ) Gia_ManPrintStats( pGia3, NULL ); + // perform choice computation + if ( Gia_ManBufNum(pInit) ) + { + assert( Gia_ManBufNum(pInit) == Gia_ManBufNum(pGia1) ); + pGia1 = Gia_ManDupFromBarBufs( pTemp = pGia1 ); + Gia_ManStop( pTemp ); + assert( Gia_ManBufNum(pInit) == Gia_ManBufNum(pGia2) ); + pGia2 = Gia_ManDupFromBarBufs( pTemp = pGia2 ); + Gia_ManStop( pTemp ); + assert( Gia_ManBufNum(pInit) == Gia_ManBufNum(pGia3) ); + pGia3 = Gia_ManDupFromBarBufs( pTemp = pGia3 ); + Gia_ManStop( pTemp ); + } + pNew = Gia_ManAigSynch2Choices( pGia1, pGia2, pGia3, pParsDch ); + Gia_ManStop( pGia1 ); + Gia_ManStop( pGia2 ); + Gia_ManStop( pGia3 ); + if ( Gia_ManBufNum(pInit) ) + { + pNew = Gia_ManDupToBarBufs( pTemp = pNew, Gia_ManBufNum(pInit) ); + Gia_ManStop( pTemp ); + } + // copy names + ABC_FREE( pNew->pName ); + ABC_FREE( pNew->pSpec ); + pNew->pName = Abc_UtilStrsav(pInit->pName); + pNew->pSpec = Abc_UtilStrsav(pInit->pSpec); + Gia_ManTransferTiming( pNew, pInit ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPerformMap( int nAnds, int nLutSize, int nCutNum, int fMinAve, int fUseMfs, int fVerbose ) +{ + char Command[200]; + sprintf( Command, "&unmap; &lf -K %d -C %d -k %s; &save", nLutSize, nCutNum, fMinAve?"-t":"" ); +// sprintf( Command, "&unmap; &if -K %d -C %d %s; &save", nLutSize, nCutNum, fMinAve?"-t":"" ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command ); + if ( fVerbose ) + { + printf( "MAPPING:\n" ); + printf( "Mapping with &lf -k:\n" ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); + } + sprintf( Command, "&unmap; &lf -K %d -C %d %s; &save", nLutSize, nCutNum, fMinAve?"-t":"" ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command ); + if ( fVerbose ) + { + printf( "Mapping with &lf:\n" ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); + } + if ( (nLutSize == 4 && nAnds < 100000) || (nLutSize == 6 && nAnds < 2000) ) + { + sprintf( Command, "&unmap; &if -sz -S %d%d -K %d -C %d %s", nLutSize, nLutSize, 2*nLutSize-1, 2*nCutNum, fMinAve?"-t":"" ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command ); + Vec_IntFreeP( &Abc_FrameReadGia(Abc_FrameGetGlobalFrame())->vPacking ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&save" ); + if ( fVerbose ) + { + printf( "Mapping with &if -sz -S %d%d -K %d -C %d %s:\n", nLutSize, nLutSize, 2*nLutSize-1, 2*nCutNum, fMinAve?"-t":"" ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); + } + } + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&load" ); + if ( fUseMfs ) + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&put; mfs2 -W 4 -M 500 -C 7000; &get -m" ); + if ( fVerbose ) + { + printf( "Mapping final:\n" ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); + } +} +void Gia_ManPerformRound( int fIsMapped, int nAnds, int nLevels, int nLutSize, int nCutNum, int fMinAve, int fUseMfs, int fVerbose ) +{ + char Command[200]; + + // perform AIG-based synthesis + if ( nAnds < 50000 ) + { + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "" ); + sprintf( Command, "&dsdb; &dch -C 500; &if -K %d -C %d %s; &save", nLutSize, nCutNum, fMinAve?"-t":"" ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command ); + if ( fVerbose ) + { + printf( "Mapping with &dch -C 500; &if -K %d -C %d %s:\n", nLutSize, nCutNum, fMinAve?"-t":"" ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); + } + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st" ); + } + + // perform AIG-based synthesis + if ( nAnds < 20000 ) + { + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "" ); + sprintf( Command, "&dsdb; &dch -C 500; &if -K %d -C %d %s; &save", nLutSize, nCutNum, fMinAve?"-t":"" ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command ); + if ( fVerbose ) + { + printf( "Mapping with &dch -C 500; &if -K %d -C %d %s:\n", nLutSize, nCutNum, fMinAve?"-t":"" ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); + } + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st" ); + } + + // perform first round of mapping + Gia_ManPerformMap( nAnds, nLutSize, nCutNum, fMinAve, fUseMfs, fVerbose ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st" ); + + // perform synthesis + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&dsdb" ); + + // perform second round of mapping + Gia_ManPerformMap( nAnds, nLutSize, nCutNum, fMinAve, fUseMfs, fVerbose ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st" ); + + // perform synthesis + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&syn2 -m -R 10; &dsdb" ); + + // prepare for final mapping + sprintf( Command, "&blut -a -K %d", nLutSize ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Command ); + + // perform third round of mapping + Gia_ManPerformMap( nAnds, nLutSize, nCutNum, fMinAve, fUseMfs, fVerbose ); +} +void Gia_ManPerformFlow( int fIsMapped, int nAnds, int nLevels, int nLutSize, int nCutNum, int fMinAve, int fUseMfs, int fVerbose ) +{ + // remove comb equivs + if ( fIsMapped ) + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st" ); +// if ( Abc_FrameReadGia(Abc_FrameGetGlobalFrame())->pManTime ) +// Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&sweep" ); +// else +// Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&fraig -c" ); + + // perform first round + Gia_ManPerformRound( fIsMapped, nAnds, nLevels, nLutSize, nCutNum, fMinAve, fUseMfs, fVerbose ); + + // perform synthesis + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st; &sopb" ); + + // perform first round + Gia_ManPerformRound( fIsMapped, nAnds, nLevels, nLutSize, nCutNum, fMinAve, fUseMfs, fVerbose ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPerformFlow2( int fIsMapped, int nAnds, int nLevels, int nLutSize, int nCutNum, int fBalance, int fMinAve, int fUseMfs, int fVerbose ) +{ + char Comm1[1000], Comm2[1000], Comm3[1000], Comm4[1000]; + if ( nLutSize == 0 ) + { + sprintf( Comm1, "&synch2 -K 6 -C 500; &if -m%s -C %d; %s &save", fMinAve?"t":"", nCutNum, fUseMfs ? "&put; mfs2 -W 4 -M 500 -C 7000; &get -m;":"" ); + sprintf( Comm2, "&dch -C 500; &if -m%s -C %d; %s &save", fMinAve?"t":"", nCutNum+4, fUseMfs ? "&put; mfs2 -W 4 -M 500 -C 7000; &get -m;":"" ); + sprintf( Comm3, "&synch2 -K 6 -C 500; &lf -m%s -E 5 -C %d; %s &save", fMinAve?"t":"", nCutNum, fUseMfs ? "&put; mfs2 -W 4 -M 500 -C 7000; &get -m;":"" ); + sprintf( Comm4, "&dch -C 500; &lf -m%sk -E 5 -C %d; %s &save", fMinAve?"t":"", nCutNum+4, fUseMfs ? "&put; mfs2 -W 4 -M 500 -C 7000; &get -m;":"" ); + } + else + { + sprintf( Comm1, "&synch2 -K %d -C 500; &if -m%s -K %d -C %d; %s &save", nLutSize, fMinAve?"t":"", nLutSize, nCutNum, fUseMfs ? "&put; mfs2 -W 4 -M 500 -C 7000; &get -m;":"" ); + sprintf( Comm2, "&dch -C 500; &if -m%s -K %d -C %d; %s &save", fMinAve?"t":"", nLutSize, nCutNum+4, fUseMfs ? "&put; mfs2 -W 4 -M 500 -C 7000; &get -m;":"" ); + sprintf( Comm3, "&synch2 -K %d -C 500; &lf -m%s -E 5 -K %d -C %d; %s &save", nLutSize, fMinAve?"t":"", nLutSize, nCutNum, fUseMfs ? "&put; mfs2 -W 4 -M 500 -C 7000; &get -m;":"" ); + sprintf( Comm4, "&dch -C 500; &lf -m%sk -E 5 -K %d -C %d; %s &save", fMinAve?"t":"", nLutSize, nCutNum+4, fUseMfs ? "&put; mfs2 -W 4 -M 500 -C 7000; &get -m;":"" ); + } + + // perform synthesis + if ( fVerbose ) + printf( "Trying synthesis...\n" ); + if ( fIsMapped ) + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st" ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Comm1 ); + if ( fVerbose ) + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); + + // perform synthesis + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st" ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Comm2 ); + if ( fVerbose ) + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); + + // return the result + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&load" ); + if ( fVerbose ) + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); + + + // perform balancing + if ( fBalance ) + { + if ( fVerbose ) + printf( "Trying SOP balancing...\n" ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st; &sopb -R 10 -C 4" ); + } + + + // perform synthesis + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Comm3 ); + if ( fVerbose ) + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); + + // perform synthesis + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st" ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Comm2 ); + if ( fVerbose ) + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); + + // return the result + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&load" ); + if ( fVerbose ) + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); + if ( nAnds > 100000 ) + return; + + + // perform balancing + if ( fBalance ) + { + if ( fVerbose ) + printf( "Trying SOP balancing...\n" ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st; &sopb -R 10" ); + } + + + // perform synthesis + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Comm3 ); + if ( fVerbose ) + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); + + // perform synthesis + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st" ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Comm2 ); + if ( fVerbose ) + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); + + // return the result + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&load" ); + if ( fVerbose ) + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); + if ( nAnds > 50000 ) + return; + + + // perform balancing + if ( fBalance ) + { + if ( fVerbose ) + printf( "Trying SOP balancing...\n" ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st; &sopb -R 10" ); + } + + + // perform synthesis + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Comm3 ); + if ( fVerbose ) + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); + + // perform synthesis + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&st" ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Comm2 ); + if ( fVerbose ) + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); + + // return the result + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&load" ); + if ( fVerbose ) + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPerformFlow3( int nLutSize, int nCutNum, int fBalance, int fMinAve, int fUseMfs, int fUseLutLib, int fVerbose ) +{ + char Comm1[200], Comm2[200], Comm3[200]; + if ( fUseLutLib ) + sprintf( Comm1, "&st; &if -C %d; &save; &st; &syn2; &if -C %d; &save; &load", nCutNum, nCutNum ); + else + sprintf( Comm1, "&st; &if -C %d -K %d; &save; &st; &syn2; &if -C %d -K %d; &save; &load", nCutNum, nLutSize, nCutNum, nLutSize ); + if ( fUseLutLib ) + sprintf( Comm2, "&st; &if -%s -K 6; &dch -f; &if -C %d; %s&save; &load", Abc_NtkRecIsRunning3() ? "y" : "g", nCutNum, fUseMfs ? "&mfs; ":"" ); + else + sprintf( Comm2, "&st; &if -%s -K 6; &dch -f; &if -C %d -K %d; %s&save; &load", Abc_NtkRecIsRunning3() ? "y" : "g", nCutNum, nLutSize, fUseMfs ? "&mfs; ":"" ); + if ( fUseLutLib ) + sprintf( Comm3, "&st; &if -%s -K 6; &synch2; &if -C %d; %s&save; &load", Abc_NtkRecIsRunning3() ? "y" : "g", nCutNum, fUseMfs ? "&mfs; ":"" ); + else + sprintf( Comm3, "&st; &if -%s -K 6; &synch2; &if -C %d -K %d; %s&save; &load", Abc_NtkRecIsRunning3() ? "y" : "g", nCutNum, nLutSize, fUseMfs ? "&mfs; ":"" ); + + if ( fVerbose ) printf( "Trying simple synthesis with %s...\n", Abc_NtkRecIsRunning3() ? "LMS" : "SOP balancing" ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Comm1 ); + if ( fVerbose ) + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); + + if ( Gia_ManAndNum( Abc_FrameReadGia(Abc_FrameGetGlobalFrame()) ) < 200000 ) + { + if ( fVerbose ) printf( "Trying medium synthesis...\n" ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Comm2 ); + if ( fVerbose ) + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); + } + + if ( Gia_ManAndNum( Abc_FrameReadGia(Abc_FrameGetGlobalFrame()) ) < 10000 ) + { + if ( fVerbose ) printf( "Trying harder synthesis...\n" ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), Comm3 ); + if ( fVerbose ) + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); + } + + if ( fVerbose ) printf( "Final result...\n" ); + if ( fVerbose ) + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "&ps" ); +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaShow.c b/yosys/abc/src/aig/gia/giaShow.c new file mode 100644 index 00000000000..6a25cfd898c --- /dev/null +++ b/yosys/abc/src/aig/gia/giaShow.c @@ -0,0 +1,1164 @@ +/**CFile**************************************************************** + + FileName [giaShow.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [AIG visualization.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: giaShow.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "proof/cec/cec.h" +#include "proof/acec/acec.h" +#include "misc/extra/extra.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define NODE_MAX 2000 + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Writes the graph structure of AIG for DOT.] + + Description [Useful for graph visualization using tools such as GraphViz: + http://www.graphviz.org/] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ShowPath( Gia_Man_t * p, char * pFileName ) +{ + FILE * pFile; + Gia_Obj_t * pNode; + Vec_Bit_t * vPath = Vec_BitStart( Gia_ManObjNum(p) ); + int i, k, iFan, LevelMax, nLevels, * pLevels, Level, Prev; + int nLuts = 0, nNodes = 0, nEdges = 0; + assert( Gia_ManHasMapping(p) ); + + // set critical CO drivers + nLevels = Gia_ManLutLevel( p, &pLevels ); + Gia_ManForEachCoDriverId( p, iFan, i ) + if ( pLevels[iFan] == nLevels ) + Vec_BitWriteEntry( vPath, iFan, 1 ); + + // set critical internal nodes + Gia_ManForEachLutReverse( p, i ) + { + nLuts++; + if ( !Vec_BitEntry(vPath, i) ) + continue; + nNodes++; + Gia_LutForEachFanin( p, i, iFan, k ) + { + if ( pLevels[iFan] +1 < pLevels[i] ) + continue; + assert( pLevels[iFan] + 1 == pLevels[i] ); + Vec_BitWriteEntry( vPath, iFan, 1 ); + nEdges++; + //printf( "%d -> %d\n", i, iFan ); + } + } + + if ( nNodes > NODE_MAX ) + { + ABC_FREE( pLevels ); + Vec_BitFree( vPath ); + fprintf( stdout, "Cannot visualize AIG with more than %d critical nodes.\n", NODE_MAX ); + return; + } + if ( (pFile = fopen( pFileName, "w" )) == NULL ) + { + ABC_FREE( pLevels ); + Vec_BitFree( vPath ); + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); + return; + } + + Vec_IntFreeP( &p->vLevels ); + p->vLevels = Vec_IntAllocArray( pLevels, Gia_ManObjNum(p) ); + + // compute CO levels + LevelMax = 1 + nLevels; + Gia_ManForEachCo( p, pNode, i ) + Vec_IntWriteEntry( p->vLevels, Gia_ObjId(p, pNode), LevelMax ); + + // write the DOT header + fprintf( pFile, "# %s\n", "AIG structure generated by GIA package" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "digraph AIG {\n" ); + fprintf( pFile, "size = \"7.5,10\";\n" ); +// fprintf( pFile, "ranksep = 0.5;\n" ); +// fprintf( pFile, "nodesep = 0.5;\n" ); + fprintf( pFile, "center = true;\n" ); +// fprintf( pFile, "orientation = landscape;\n" ); +// fprintf( pFile, "edge [fontsize = 10];\n" ); +// fprintf( pFile, "edge [dir = none];\n" ); + fprintf( pFile, "edge [dir = back];\n" ); + fprintf( pFile, "\n" ); + + // labels on the left of the picture + fprintf( pFile, "{\n" ); + fprintf( pFile, " node [shape = plaintext];\n" ); + fprintf( pFile, " edge [style = invis];\n" ); + fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); + fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); + // generate node names with labels + for ( Level = LevelMax; Level >= 0; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + fprintf( pFile, " [label = " ); + // label name + fprintf( pFile, "\"" ); + fprintf( pFile, "\"" ); + fprintf( pFile, "];\n" ); + } + + // genetate the sequence of visible/invisible nodes to mark levels + fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); + for ( Level = LevelMax; Level >= 0; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + // the connector + if ( Level != 0 ) + fprintf( pFile, " ->" ); + else + fprintf( pFile, ";" ); + } + fprintf( pFile, "\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate title box on top + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle1;\n" ); + fprintf( pFile, " title1 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=20,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + fprintf( pFile, "%s", "AIG structure visualized by ABC" ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "Benchmark \\\"%s\\\". ", "aig" ); +// fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate statistics box + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle2;\n" ); + fprintf( pFile, " title2 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=18,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + fprintf( pFile, "The critical path contains %d LUTs with %d critical edges and spans %d levels.", nNodes, nEdges, nLevels ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate the COs + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", LevelMax ); + // generate the CO nodes + Gia_ManForEachCo( p, pNode, i ) + { + if ( Gia_ObjLevel(p, Gia_ObjFanin0(pNode)) < nLevels ) + continue; + assert( Gia_ObjLevel(p, Gia_ObjFanin0(pNode)) == nLevels ); + fprintf( pFile, " Node%d [label = \"%d\"", Gia_ObjId(p, pNode), Gia_ObjId(p, pNode) ); + fprintf( pFile, ", shape = %s", "invtriangle" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate nodes of each rank + for ( Level = LevelMax - 1; Level > 0; Level-- ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", Level ); + Gia_ManForEachObj( p, pNode, i ) + { + if ( (int)Gia_ObjLevel(p, pNode) != Level || !Vec_BitEntry(vPath, i) ) + continue; + fprintf( pFile, " Node%d [label = \"%d:%d\"", i, Vec_IntSize(p->vIdsOrig)?Vec_IntEntry(p->vIdsOrig,i):i, Gia_ObjIsAnd(pNode)?Gia_ObjLutSize(p, i):0 ); + fprintf( pFile, ", shape = ellipse" ); + if ( pNode->fMark0 ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate the CI nodes + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", 0 ); + // generate the CI nodes + Gia_ManForEachCi( p, pNode, i ) + { + if ( !Vec_BitEntry(vPath, Gia_ObjId(p, pNode)) ) + continue; + fprintf( pFile, " Node%d [label = \"%d\"", Gia_ObjId(p, pNode), Gia_ObjId(p, pNode) ); + fprintf( pFile, ", shape = %s", "triangle" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate invisible edges from the square down + fprintf( pFile, "title1 -> title2 [style = invis];\n" ); + Gia_ManForEachCo( p, pNode, i ) + { + if ( Gia_ObjLevel(p, Gia_ObjFanin0(pNode)) < nLevels ) + continue; + fprintf( pFile, "title2 -> Node%d [style = invis];\n", Gia_ObjId(p, pNode) ); + } + // generate invisible edges among the COs + Prev = -1; + Gia_ManForEachCo( p, pNode, i ) + { + if ( Gia_ObjLevel(p, Gia_ObjFanin0(pNode)) < nLevels ) + continue; + assert( Gia_ObjLevel(p, Gia_ObjFanin0(pNode)) == nLevels ); + if ( Prev >= 0 ) + fprintf( pFile, "Node%d -> Node%d [style = invis];\n", Prev, Gia_ObjId(p, pNode) ); + Prev = Gia_ObjId(p, pNode); + } + // generate invisible edges among the CIs + Prev = -1; + Gia_ManForEachCi( p, pNode, i ) + { + if ( !Vec_BitEntry(vPath, Gia_ObjId(p, pNode)) ) + continue; + if ( Prev >= 0 ) + fprintf( pFile, "Node%d -> Node%d [style = invis];\n", Prev, Gia_ObjId(p, pNode) ); + Prev = Gia_ObjId(p, pNode); + } + + // generate edges + Gia_ManForEachObj( p, pNode, i ) + { + if ( Gia_ObjIsCo(pNode) ) + { + if ( Gia_ObjLevel(p, Gia_ObjFanin0(pNode)) == nLevels ) + { + // generate the edge from this node to the next + fprintf( pFile, "Node%d", i ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", Gia_ObjFaninId0p(p, pNode) ); + fprintf( pFile, " [" ); + fprintf( pFile, "style = %s", "solid" ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + } + continue; + } + if ( !Gia_ObjIsAnd(pNode) || !Vec_BitEntry(vPath, i) ) + continue; + Gia_LutForEachFanin( p, i, iFan, k ) + { + if ( pLevels[iFan] + 1 < pLevels[i] ) + continue; + assert( pLevels[iFan] + 1 == pLevels[i] ); + // generate the edge from this node to the next + fprintf( pFile, "Node%d", i ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", iFan ); + fprintf( pFile, " [" ); + fprintf( pFile, "style = %s", "solid" ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + } + } + + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + fclose( pFile ); + + Vec_IntFreeP( &p->vLevels ); + Vec_BitFree( vPath ); +} + + +/**Function************************************************************* + + Synopsis [Writes the graph structure of AIG for DOT.] + + Description [Useful for graph visualization using tools such as GraphViz: + http://www.graphviz.org/] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_WriteDotAigSimple( Gia_Man_t * p, char * pFileName, Vec_Int_t * vBold ) +{ + FILE * pFile; + Gia_Obj_t * pNode;//, * pTemp, * pPrev; + int LevelMax, Prev, Level, i; + int fConstIsUsed = 0; + + if ( Gia_ManAndNum(p) > NODE_MAX ) + { + fprintf( stdout, "Cannot visualize AIG with more than %d nodes.\n", NODE_MAX ); + return; + } + if ( (pFile = fopen( pFileName, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); + return; + } + + // mark the nodes + if ( vBold ) + Gia_ManForEachObjVec( vBold, p, pNode, i ) + pNode->fMark0 = 1; + else if ( p->nXors || p->nMuxes ) + Gia_ManForEachObj( p, pNode, i ) + if ( Gia_ObjIsXor(pNode) || Gia_ObjIsMux(p, pNode) ) + pNode->fMark0 = 1; + + // compute levels + LevelMax = 1 + Gia_ManLevelNum( p ); + Gia_ManForEachCo( p, pNode, i ) + Vec_IntWriteEntry( p->vLevels, Gia_ObjId(p, pNode), LevelMax ); + + // write the DOT header + fprintf( pFile, "# %s\n", "AIG structure generated by GIA package" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "digraph AIG {\n" ); + fprintf( pFile, "size = \"7.5,10\";\n" ); +// fprintf( pFile, "ranksep = 0.5;\n" ); +// fprintf( pFile, "nodesep = 0.5;\n" ); + fprintf( pFile, "center = true;\n" ); +// fprintf( pFile, "orientation = landscape;\n" ); +// fprintf( pFile, "edge [fontsize = 10];\n" ); +// fprintf( pFile, "edge [dir = none];\n" ); + fprintf( pFile, "edge [dir = back];\n" ); + fprintf( pFile, "\n" ); + + // labels on the left of the picture + fprintf( pFile, "{\n" ); + fprintf( pFile, " node [shape = plaintext];\n" ); + fprintf( pFile, " edge [style = invis];\n" ); + fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); + fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); + // generate node names with labels + for ( Level = LevelMax; Level >= 0; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + fprintf( pFile, " [label = " ); + // label name + fprintf( pFile, "\"" ); + fprintf( pFile, "\"" ); + fprintf( pFile, "];\n" ); + } + + // genetate the sequence of visible/invisible nodes to mark levels + fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); + for ( Level = LevelMax; Level >= 0; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + // the connector + if ( Level != 0 ) + fprintf( pFile, " ->" ); + else + fprintf( pFile, ";" ); + } + fprintf( pFile, "\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate title box on top + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle1;\n" ); + fprintf( pFile, " title1 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=20,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + fprintf( pFile, "%s", "AIG structure visualized by ABC" ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "Benchmark \\\"%s\\\". ", "aig" ); +// fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate statistics box + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle2;\n" ); + fprintf( pFile, " title2 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=18,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + fprintf( pFile, "The AIG contains %d nodes and spans %d levels.", Gia_ManAndNum(p), LevelMax-1 ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate the COs + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", LevelMax ); + // generate the CO nodes + Gia_ManForEachCo( p, pNode, i ) + { + if ( Gia_ObjFaninId0p(p, pNode) == 0 ) + fConstIsUsed = 1; +/* + if ( fHaig || pNode->pEquiv == NULL ) + fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id, + (Gia_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Gia_ObjIsLatch(pNode)? "_in":"") ); + else + fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, + (Gia_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Gia_ObjIsLatch(pNode)? "_in":""), + Gia_Regular(pNode->pEquiv)->Id, Gia_IsComplement(pNode->pEquiv)? "\'":"" ); +*/ + fprintf( pFile, " Node%d [label = \"%d\"", Gia_ObjId(p, pNode), Gia_ObjId(p, pNode) ); + + fprintf( pFile, ", shape = %s", "invtriangle" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate nodes of each rank + for ( Level = LevelMax - 1; Level > 0; Level-- ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", Level ); + Gia_ManForEachObj( p, pNode, i ) + { + if ( (int)Gia_ObjLevel(p, pNode) != Level ) + continue; +/* + if ( fHaig || pNode->pEquiv == NULL ) + fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); + else + fprintf( pFile, " Node%d [label = \"%d(%d%s)\"", pNode->Id, pNode->Id, + Gia_Regular(pNode->pEquiv)->Id, Gia_IsComplement(pNode->pEquiv)? "\'":"" ); +*/ + fprintf( pFile, " Node%d [label = \"%d\"", i, i ); + + if ( Gia_ObjIsXor(pNode) ) + fprintf( pFile, ", shape = doublecircle" ); + else if ( Gia_ObjIsMux(p, pNode) ) + fprintf( pFile, ", shape = trapezium" ); + else + fprintf( pFile, ", shape = ellipse" ); + + if ( pNode->fMark0 ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate the CI nodes + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", 0 ); + // generate constant node + if ( fConstIsUsed ) + { + // check if the costant node is present + fprintf( pFile, " Node%d [label = \"Const0\"", 0 ); + fprintf( pFile, ", shape = ellipse" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + // generate the CI nodes + Gia_ManForEachCi( p, pNode, i ) + { +/* + if ( fHaig || pNode->pEquiv == NULL ) + fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id, + (Gia_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Gia_ObjIsLatch(pNode)? "_out":"") ); + else + fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, + (Gia_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Gia_ObjIsLatch(pNode)? "_out":""), + Gia_Regular(pNode->pEquiv)->Id, Gia_IsComplement(pNode->pEquiv)? "\'":"" ); +*/ + fprintf( pFile, " Node%d [label = \"%d\"", Gia_ObjId(p, pNode), Gia_ObjId(p, pNode) ); + + fprintf( pFile, ", shape = %s", "triangle" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate invisible edges from the square down + fprintf( pFile, "title1 -> title2 [style = invis];\n" ); + Gia_ManForEachCo( p, pNode, i ) + fprintf( pFile, "title2 -> Node%d [style = invis];\n", Gia_ObjId(p, pNode) ); + // generate invisible edges among the COs + Prev = -1; + Gia_ManForEachCo( p, pNode, i ) + { + if ( i > 0 ) + fprintf( pFile, "Node%d -> Node%d [style = invis];\n", Prev, Gia_ObjId(p, pNode) ); + Prev = Gia_ObjId(p, pNode); + } + // generate invisible edges among the CIs + Prev = -1; + Gia_ManForEachCi( p, pNode, i ) + { + if ( i > 0 ) + fprintf( pFile, "Node%d -> Node%d [style = invis];\n", Prev, Gia_ObjId(p, pNode) ); + Prev = Gia_ObjId(p, pNode); + } + + // generate edges + Gia_ManForEachObj( p, pNode, i ) + { + if ( !Gia_ObjIsAnd(pNode) && !Gia_ObjIsCo(pNode) && !Gia_ObjIsBuf(pNode) ) + continue; + // generate the edge from this node to the next + fprintf( pFile, "Node%d", i ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", Gia_ObjFaninId0(pNode, i) ); + fprintf( pFile, " [" ); + fprintf( pFile, "style = %s", Gia_ObjFaninC0(pNode)? "dotted" : "solid" ); +// if ( Gia_NtkIsSeq(pNode->p) && Seq_ObjFaninL0(pNode) > 0 ) +// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,0) ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + if ( !Gia_ObjIsAnd(pNode) ) + continue; + // generate the edge from this node to the next + fprintf( pFile, "Node%d", i ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", Gia_ObjFaninId1(pNode, i) ); + fprintf( pFile, " [" ); + fprintf( pFile, "style = %s", Gia_ObjFaninC1(pNode)? "dotted" : "solid" ); +// if ( Gia_NtkIsSeq(pNode->p) && Seq_ObjFaninL1(pNode) > 0 ) +// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,1) ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + + if ( !Gia_ObjIsMux(p, pNode) ) + continue; + // generate the edge from this node to the next + fprintf( pFile, "Node%d", i ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", Gia_ObjFaninId2(p, i) ); + fprintf( pFile, " [" ); + fprintf( pFile, "style = %s", Gia_ObjFaninC2(p, pNode)? "dotted" : "bold" ); +// if ( Gia_NtkIsSeq(pNode->p) && Seq_ObjFaninL1(pNode) > 0 ) +// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,1) ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + +/* + // generate the edges between the equivalent nodes + if ( fHaig && pNode->pEquiv && Gia_ObjRefs(pNode) > 0 ) + { + pPrev = pNode; + for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Gia_Regular(pTemp->pEquiv) ) + { + fprintf( pFile, "Node%d", pPrev->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", pTemp->Id ); + fprintf( pFile, " [style = %s]", Gia_IsComplement(pTemp->pEquiv)? "dotted" : "solid" ); + fprintf( pFile, ";\n" ); + pPrev = pTemp; + } + // connect the last node with the first + fprintf( pFile, "Node%d", pPrev->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", pNode->Id ); + fprintf( pFile, " [style = %s]", Gia_IsComplement(pPrev->pEquiv)? "dotted" : "solid" ); + fprintf( pFile, ";\n" ); + } +*/ + } + + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + fclose( pFile ); + + // unmark nodes + if ( vBold ) + Gia_ManForEachObjVec( vBold, p, pNode, i ) + pNode->fMark0 = 0; + else if ( p->nXors || p->nMuxes ) + Gia_ManCleanMark0( p ); + + Vec_IntFreeP( &p->vLevels ); +} + +/**Function************************************************************* + + Synopsis [Writes the graph structure of AIG for DOT.] + + Description [Useful for graph visualization using tools such as GraphViz: + http://www.graphviz.org/] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ShowAddOut( Vec_Int_t * vAdds, Vec_Int_t * vMapAdds, int Node ) +{ + int iBox = Vec_IntEntry( vMapAdds, Node ); + if ( iBox >= 0 ) + return Vec_IntEntry( vAdds, 6*iBox+4 ); + return Node; +} +void Gia_WriteDotAig( Gia_Man_t * p, char * pFileName, Vec_Int_t * vBold, Vec_Int_t * vAdds, Vec_Int_t * vXors, Vec_Int_t * vMapAdds, Vec_Int_t * vMapXors, Vec_Int_t * vOrder ) +{ + FILE * pFile; + Gia_Obj_t * pNode;//, * pTemp, * pPrev; + int LevelMax, Prev, Level, i; + int fConstIsUsed = 0; + int nFadds = Ree_ManCountFadds( vAdds ); + + if ( Gia_ManAndNum(p) > NODE_MAX ) + { + fprintf( stdout, "Cannot visualize AIG with more than %d nodes.\n", NODE_MAX ); + return; + } + if ( (pFile = fopen( pFileName, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); + return; + } + + // mark the nodes + if ( vBold ) + Gia_ManForEachObjVec( vBold, p, pNode, i ) + pNode->fMark0 = 1; + + // compute levels + LevelMax = 1 + p->nLevels; + Gia_ManForEachCo( p, pNode, i ) + Vec_IntWriteEntry( p->vLevels, Gia_ObjId(p, pNode), LevelMax ); + + // write the DOT header + fprintf( pFile, "# %s\n", "AIG structure generated by GIA package" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "digraph AIG {\n" ); + fprintf( pFile, "size = \"7.5,10\";\n" ); +// fprintf( pFile, "ranksep = 0.5;\n" ); +// fprintf( pFile, "nodesep = 0.5;\n" ); + fprintf( pFile, "center = true;\n" ); +// fprintf( pFile, "orientation = landscape;\n" ); +// fprintf( pFile, "edge [fontsize = 10];\n" ); +// fprintf( pFile, "edge [dir = none];\n" ); + fprintf( pFile, "edge [dir = back];\n" ); + fprintf( pFile, "\n" ); + + // labels on the left of the picture + fprintf( pFile, "{\n" ); + fprintf( pFile, " node [shape = plaintext];\n" ); + fprintf( pFile, " edge [style = invis];\n" ); + fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); + fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); + // generate node names with labels + for ( Level = LevelMax; Level >= 0; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + fprintf( pFile, " [label = " ); + // label name + fprintf( pFile, "\"" ); + fprintf( pFile, "\"" ); + fprintf( pFile, "];\n" ); + } + + // genetate the sequence of visible/invisible nodes to mark levels + fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); + for ( Level = LevelMax; Level >= 0; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + // the connector + if ( Level != 0 ) + fprintf( pFile, " ->" ); + else + fprintf( pFile, ";" ); + } + fprintf( pFile, "\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate title box on top + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle1;\n" ); + fprintf( pFile, " title1 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=20,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + fprintf( pFile, "%s", "AIG structure visualized by ABC" ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "Benchmark \\\"%s\\\". ", "aig" ); +// fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate statistics box + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle2;\n" ); + fprintf( pFile, " title2 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=18,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + fprintf( pFile, "The AIG contains %d nodes, %d full-adders, and %d half-adders, and spans %d levels.", + Gia_ManAndNum(p), nFadds, Vec_IntSize(vAdds)/6-nFadds, LevelMax-1 ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate the COs + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", LevelMax ); + // generate the CO nodes + Gia_ManForEachCo( p, pNode, i ) + { + if ( Gia_ObjFaninId0p(p, pNode) == 0 ) + fConstIsUsed = 1; + fprintf( pFile, " Node%d [label = \"%d\"", Gia_ObjId(p, pNode), Gia_ObjId(p, pNode) ); + + fprintf( pFile, ", shape = %s", "invtriangle" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate nodes of each rank + for ( Level = LevelMax - 1; Level > 0; Level-- ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", Level ); + Gia_ManForEachObjVec( vOrder, p, pNode, i ) + { + int iNode = Gia_ObjId( p, pNode ); + if ( (int)Gia_ObjLevel(p, pNode) != Level ) + continue; +/* + fprintf( pFile, " Node%d [label = \"%d\"", Gia_ObjId(p, pNode), Gia_ObjId(p, pNode) ); + if ( Gia_ObjIsXor(pNode) ) + fprintf( pFile, ", shape = doublecircle" ); + else if ( Gia_ObjIsMux(p, pNode) ) + fprintf( pFile, ", shape = trapezium" ); + else + fprintf( pFile, ", shape = ellipse" ); +*/ + if ( !pNode->fMark0 && Vec_IntEntry(vMapAdds, iNode) >= 0 ) + { + int iBox = Vec_IntEntry(vMapAdds, iNode); + fprintf( pFile, " Node%d [label = \"%d_%d\"", Gia_ShowAddOut(vAdds, vMapAdds, iNode), Vec_IntEntry(vAdds, 6*iBox+3), Vec_IntEntry(vAdds, 6*iBox+4) ); + if ( Vec_IntEntry(vAdds, 6*iBox+2) == 0 ) + fprintf( pFile, ", shape = octagon" ); + else + fprintf( pFile, ", shape = doubleoctagon" ); + } + else if ( Vec_IntEntry(vMapXors, iNode) >= 0 ) + { + fprintf( pFile, " Node%d [label = \"%d\"", iNode, iNode ); + fprintf( pFile, ", shape = doublecircle" ); + } + else if ( Gia_ObjIsXor(pNode) ) + { + fprintf( pFile, " Node%d [label = \"%d\"", iNode, iNode ); + fprintf( pFile, ", shape = doublecircle" ); + } + else if ( Gia_ObjIsMux(p, pNode) ) + { + fprintf( pFile, " Node%d [label = \"%d\"", iNode, iNode ); + fprintf( pFile, ", shape = trapezium" ); + } + else + { + fprintf( pFile, " Node%d [label = \"%d\"", iNode, iNode ); + fprintf( pFile, ", shape = ellipse" ); + } + if ( pNode->fMark0 ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate the CI nodes + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", 0 ); + // generate constant node + if ( fConstIsUsed ) + { + // check if the costant node is present + fprintf( pFile, " Node%d [label = \"Const0\"", 0 ); + fprintf( pFile, ", shape = ellipse" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + // generate the CI nodes + Gia_ManForEachCi( p, pNode, i ) + { + fprintf( pFile, " Node%d [label = \"%d\"", Gia_ObjId(p, pNode), Gia_ObjId(p, pNode) ); + + fprintf( pFile, ", shape = %s", "triangle" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate invisible edges from the square down + fprintf( pFile, "title1 -> title2 [style = invis];\n" ); + Gia_ManForEachCo( p, pNode, i ) + fprintf( pFile, "title2 -> Node%d [style = invis];\n", Gia_ObjId(p, pNode) ); + // generate invisible edges among the COs + Prev = -1; + Gia_ManForEachCo( p, pNode, i ) + { + if ( i > 0 ) + fprintf( pFile, "Node%d -> Node%d [style = invis];\n", Prev, Gia_ObjId(p, pNode) ); + Prev = Gia_ObjId(p, pNode); + } + // generate invisible edges among the CIs + Prev = -1; + Gia_ManForEachCi( p, pNode, i ) + { + if ( i > 0 ) + fprintf( pFile, "Node%d -> Node%d [style = invis];\n", Prev, Gia_ObjId(p, pNode) ); + Prev = Gia_ObjId(p, pNode); + } + + // generate edges + Gia_ManForEachCo( p, pNode, i ) + { + int iNode = Gia_ObjId( p, pNode ); + fprintf( pFile, "Node%d", iNode ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", Gia_ShowAddOut(vAdds, vMapAdds, Gia_ObjFaninId0(pNode, iNode)) ); + fprintf( pFile, " [" ); + fprintf( pFile, "style = %s", Gia_ObjFaninC0(pNode)? "dotted" : "solid" ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + } + Gia_ManForEachObjVec( vOrder, p, pNode, i ) + { + int iNode = Gia_ObjId( p, pNode ); + if ( Vec_IntEntry(vMapAdds, Gia_ObjId(p, pNode)) >= 0 ) + { + int k, iBox = Vec_IntEntry(vMapAdds, iNode); + for ( k = 0; k < 3; k++ ) + if ( Vec_IntEntry(vAdds, 6*iBox+k) ) + { + int iBox2 = Vec_IntEntry(vMapAdds, Vec_IntEntry(vAdds, 6*iBox+k)); + int fXor2 = iBox2 >= 0 ? (int)(Vec_IntEntry(vAdds, 6*iBox2+3) == Vec_IntEntry(vAdds, 6*iBox+k)) : 0; + fprintf( pFile, "Node%d", Gia_ShowAddOut(vAdds, vMapAdds, iNode) ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", Gia_ShowAddOut(vAdds, vMapAdds, Vec_IntEntry(vAdds, 6*iBox+k)) ); + fprintf( pFile, " [" ); + fprintf( pFile, "style = %s", fXor2? "bold" : "solid" ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + } + continue; + } + if ( Vec_IntEntry(vMapXors, Gia_ObjId(p, pNode)) >= 0 ) + { + int k, iXor = Vec_IntEntry(vMapXors, iNode); + for ( k = 1; k < 4; k++ ) + if ( Vec_IntEntry(vXors, 4*iXor+k) ) + { + int iXor2 = Vec_IntEntry(vMapXors, Vec_IntEntry(vXors, 4*iXor+k)); + fprintf( pFile, "Node%d", iNode ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", Gia_ShowAddOut(vAdds, vMapAdds, Vec_IntEntry(vXors, 4*iXor+k)) ); + fprintf( pFile, " [" ); + fprintf( pFile, "style = %s", iXor2 >= 0? "bold" : "solid" ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + } + continue; + } + // generate the edge from this node to the next + fprintf( pFile, "Node%d", iNode ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", Gia_ShowAddOut(vAdds, vMapAdds, Gia_ObjFaninId0(pNode, iNode)) ); + fprintf( pFile, " [" ); + fprintf( pFile, "style = %s", Gia_ObjFaninC0(pNode)? "dotted" : "solid" ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + if ( !Gia_ObjIsAnd(pNode) ) + continue; + // generate the edge from this node to the next + fprintf( pFile, "Node%d", iNode ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", Gia_ShowAddOut(vAdds, vMapAdds, Gia_ObjFaninId1(pNode, iNode)) ); + fprintf( pFile, " [" ); + fprintf( pFile, "style = %s", Gia_ObjFaninC1(pNode)? "dotted" : "solid" ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + + if ( !Gia_ObjIsMux(p, pNode) ) + continue; + // generate the edge from this node to the next + fprintf( pFile, "Node%d", iNode ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", Gia_ShowAddOut(vAdds, vMapAdds, Gia_ObjFaninId2(p, iNode)) ); + fprintf( pFile, " [" ); + fprintf( pFile, "style = %s", Gia_ObjFaninC2(p, pNode)? "dotted" : "solid" ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + } + + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + fclose( pFile ); + + // unmark nodes + if ( vBold ) + Gia_ManForEachObjVec( vBold, p, pNode, i ) + pNode->fMark0 = 0; + + Vec_IntFreeP( &p->vLevels ); +} + +/**Function************************************************************* + + Synopsis [Returns DFS ordered array of objects and their levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ShowMapAdds( Gia_Man_t * p, Vec_Int_t * vAdds, int fFadds, Vec_Int_t * vBold ) +{ + Vec_Bit_t * vIsBold = Vec_BitStart( Gia_ManObjNum(p) ); + Vec_Int_t * vMapAdds = Vec_IntStartFull( Gia_ManObjNum(p) ); int i, Entry; + if ( vBold ) + Vec_IntForEachEntry( vBold, Entry, i ) + Vec_BitWriteEntry( vIsBold, Entry, 1 ); + for ( i = 0; 6*i < Vec_IntSize(vAdds); i++ ) + { + if ( fFadds && Vec_IntEntry(vAdds, 6*i+2) == 0 ) + continue; + if ( Vec_BitEntry(vIsBold, Vec_IntEntry(vAdds, 6*i+3)) || Vec_BitEntry(vIsBold, Vec_IntEntry(vAdds, 6*i+4)) ) + continue; + Vec_IntWriteEntry( vMapAdds, Vec_IntEntry(vAdds, 6*i+3), i ); + Vec_IntWriteEntry( vMapAdds, Vec_IntEntry(vAdds, 6*i+4), i ); + } + Vec_BitFree( vIsBold ); + return vMapAdds; +} +Vec_Int_t * Gia_ShowMapXors( Gia_Man_t * p, Vec_Int_t * vXors ) +{ + Vec_Int_t * vMapXors = Vec_IntStartFull( Gia_ManObjNum(p) ); int i; + for ( i = 0; 4*i < Vec_IntSize(vXors); i++ ) + Vec_IntWriteEntry( vMapXors, Vec_IntEntry(vXors, 4*i), i ); + return vMapXors; +} +int Gia_ShowCollectObjs_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vAdds, Vec_Int_t * vXors, Vec_Int_t * vMapAdds, Vec_Int_t * vMapXors, Vec_Int_t * vOrder ) +{ + int Level0, Level1, Level2 = 0, Level = 0; + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return Gia_ObjLevel(p, pObj); + Gia_ObjSetTravIdCurrent(p, pObj); + if ( Gia_ObjIsCi(pObj) ) + return 0; + if ( Vec_IntEntry(vMapAdds, Gia_ObjId(p, pObj)) >= 0 ) + { + int iBox = Vec_IntEntry(vMapAdds, Gia_ObjId(p, pObj)); + Gia_ObjSetTravIdCurrentId(p, Vec_IntEntry(vAdds, 6*iBox+3) ); + Gia_ObjSetTravIdCurrentId(p, Vec_IntEntry(vAdds, 6*iBox+4) ); + Level0 = Gia_ShowCollectObjs_rec( p, Gia_ManObj( p, Vec_IntEntry(vAdds, 6*iBox+0) ), vAdds, vXors, vMapAdds, vMapXors, vOrder ); + Level1 = Gia_ShowCollectObjs_rec( p, Gia_ManObj( p, Vec_IntEntry(vAdds, 6*iBox+1) ), vAdds, vXors, vMapAdds, vMapXors, vOrder ); + if ( Vec_IntEntry(vAdds, 6*iBox+2) ) + Level2 = Gia_ShowCollectObjs_rec( p, Gia_ManObj( p, Vec_IntEntry(vAdds, 6*iBox+2) ), vAdds, vXors, vMapAdds, vMapXors, vOrder ); + Level = 1 + Abc_MaxInt( Abc_MaxInt(Level0, Level1), Level2 ); + Gia_ObjSetLevelId( p, Vec_IntEntry(vAdds, 6*iBox+3), Level ); + Gia_ObjSetLevelId( p, Vec_IntEntry(vAdds, 6*iBox+4), Level ); + pObj = Gia_ManObj( p, Vec_IntEntry(vAdds, 6*iBox+4) ); + } + else if ( Vec_IntEntry(vMapXors, Gia_ObjId(p, pObj)) >= 0 ) + { + int iXor = Vec_IntEntry(vMapXors, Gia_ObjId(p, pObj)); + Level0 = Gia_ShowCollectObjs_rec( p, Gia_ManObj( p, Vec_IntEntry(vXors, 4*iXor+1) ), vAdds, vXors, vMapAdds, vMapXors, vOrder ); + Level1 = Gia_ShowCollectObjs_rec( p, Gia_ManObj( p, Vec_IntEntry(vXors, 4*iXor+2) ), vAdds, vXors, vMapAdds, vMapXors, vOrder ); + if ( Vec_IntEntry(vXors, 4*iXor+3) ) + Level2 = Gia_ShowCollectObjs_rec( p, Gia_ManObj( p, Vec_IntEntry(vXors, 4*iXor+3) ), vAdds, vXors, vMapAdds, vMapXors, vOrder ); + Level = 1 + Abc_MaxInt( Abc_MaxInt(Level0, Level1), Level2 ); + Gia_ObjSetLevel( p, pObj, Level ); + } + else + { + assert( !Gia_ObjIsMux(p, pObj) ); + Level0 = Gia_ShowCollectObjs_rec( p, Gia_ObjFanin0(pObj), vAdds, vXors, vMapAdds, vMapXors, vOrder ); + Level1 = Gia_ShowCollectObjs_rec( p, Gia_ObjFanin1(pObj), vAdds, vXors, vMapAdds, vMapXors, vOrder ); + Level = 1 + Abc_MaxInt(Level0, Level1); + Gia_ObjSetLevel( p, pObj, Level ); + } + Vec_IntPush( vOrder, Gia_ObjId(p, pObj) ); + p->nLevels = Abc_MaxInt( p->nLevels, Level ); + return Level; +} +Vec_Int_t * Gia_ShowCollectObjs( Gia_Man_t * p, Vec_Int_t * vAdds, Vec_Int_t * vXors, Vec_Int_t * vMapAdds, Vec_Int_t * vMapXors ) +{ + Gia_Obj_t * pObj; int i; + Vec_Int_t * vOrder = Vec_IntAlloc( 100 ); + Gia_ManCleanLevels( p, Gia_ManObjNum(p) ); + p->nLevels = 0; + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrent(p, Gia_ManConst0(p)); + Gia_ManForEachCi( p, pObj, i ) + Gia_ObjSetTravIdCurrent(p, pObj); + Gia_ManForEachCo( p, pObj, i ) + Gia_ShowCollectObjs_rec( p, Gia_ObjFanin0(pObj), vAdds, vXors, vMapAdds, vMapXors, vOrder ); + return vOrder; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ShowProcess( Gia_Man_t * p, char * pFileName, Vec_Int_t * vBold, Vec_Int_t * vAdds, Vec_Int_t * vXors, int fFadds ) +{ + Vec_Int_t * vMapAdds = Gia_ShowMapAdds( p, vAdds, fFadds, vBold ); + Vec_Int_t * vMapXors = Gia_ShowMapXors( p, vXors ); + Vec_Int_t * vOrder = Gia_ShowCollectObjs( p, vAdds, vXors, vMapAdds, vMapXors ); + Gia_WriteDotAig( p, pFileName, vBold, vAdds, vXors, vMapAdds, vMapXors, vOrder ); + Vec_IntFree( vMapAdds ); + Vec_IntFree( vMapXors ); + Vec_IntFree( vOrder ); +} +void Gia_ManShow( Gia_Man_t * pMan, Vec_Int_t * vBold, int fAdders, int fFadds, int fPath ) +{ + extern void Abc_ShowFile( char * FileNameDot, int fKeepDot ); + char FileNameDot[200]; + FILE * pFile; + Vec_Int_t * vXors = NULL, * vAdds = fAdders ? Ree_ManComputeCuts( pMan, &vXors, 0 ) : NULL; + sprintf( FileNameDot, "%s", Extra_FileNameGenericAppend(pMan->pName ? pMan->pName : (char *)"unknown", ".dot") ); + // check that the file can be opened + if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); + return; + } + fclose( pFile ); + // generate the file + if ( fPath ) + Gia_ShowPath( pMan, FileNameDot ); + else if ( fAdders ) + Gia_ShowProcess( pMan, FileNameDot, vBold, vAdds, vXors, fFadds ); + else + Gia_WriteDotAigSimple( pMan, FileNameDot, vBold ); + // visualize the file + Abc_ShowFile( FileNameDot, 0 ); + + Vec_IntFreeP( &vAdds ); + Vec_IntFreeP( &vXors ); +} + + + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaShrink.c b/yosys/abc/src/aig/gia/giaShrink.c new file mode 100644 index 00000000000..05372d1a82a --- /dev/null +++ b/yosys/abc/src/aig/gia/giaShrink.c @@ -0,0 +1,154 @@ +/**CFile**************************************************************** + + FileName [giaShrink.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Implementation of mapShrink based on ideas of Niklas Een.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaShrink.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "aig/aig/aig.h" +#include "opt/dar/dar.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern int Dar_LibEvalBuild( Gia_Man_t * p, Vec_Int_t * vCut, unsigned uTruth, int fKeepLevel, Vec_Int_t * vLeavesBest ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs AIG shrinking using the current mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManMapShrink4( Gia_Man_t * p, int fKeepLevel, int fVerbose ) +{ + Vec_Int_t * vLeaves, * vTruth, * vVisited, * vLeavesBest; + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pFanin; + unsigned * pTruth; + int i, k, iFan; + abctime clk = Abc_Clock(); +// int ClassCounts[222] = {0}; + int * pLutClass, Counter = 0; + assert( Gia_ManHasMapping(p) ); + if ( Gia_ManLutSizeMax( p ) > 4 ) + { + printf( "Resynthesis is not performed when nodes have more than 4 inputs.\n" ); + return NULL; + } + pLutClass = ABC_CALLOC( int, Gia_ManObjNum(p) ); + vLeaves = Vec_IntAlloc( 0 ); + vTruth = Vec_IntAlloc( (1<<16) ); + vVisited = Vec_IntAlloc( 0 ); + vLeavesBest = Vec_IntAlloc( 4 ); + // prepare the library + Dar_LibPrepare( 5 ); + // clean the old manager + Gia_ManCleanTruth( p ); + Gia_ManSetPhase( p ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + // start the new manager + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManCleanLevels( pNew, Gia_ManObjNum(p) ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + { + pObj->Value = Gia_ManAppendCi( pNew ); + if ( p->vLevels ) + Gia_ObjSetLevel( pNew, Gia_ObjFromLit(pNew, Gia_ObjValue(pObj)), Gia_ObjLevel(p, pObj) ); + } + else if ( Gia_ObjIsCo(pObj) ) + { + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + else if ( Gia_ObjIsLut(p, i) ) + { + Counter++; + // collect leaves of this gate + Vec_IntClear( vLeaves ); + Gia_LutForEachFanin( p, i, iFan, k ) + Vec_IntPush( vLeaves, iFan ); + for ( ; k < 4; k++ ) + Vec_IntPush( vLeaves, 0 ); + //.compute the truth table + pTruth = Gia_ManConvertAigToTruth( p, pObj, vLeaves, vTruth, vVisited ); + // change from node IDs to their literals + Gia_ManForEachObjVec( vLeaves, p, pFanin, k ) + { +// assert( Gia_ObjValue(pFanin) != ~0 ); + Vec_IntWriteEntry( vLeaves, k, Gia_ObjValue(pFanin) != ~0 ? Gia_ObjValue(pFanin) : 0 ); + } + // derive new structre + if ( Gia_ManTruthIsConst0(pTruth, Vec_IntSize(vLeaves)) ) + pObj->Value = 0; + else if ( Gia_ManTruthIsConst1(pTruth, Vec_IntSize(vLeaves)) ) + pObj->Value = 1; + else + { + pObj->Value = Dar_LibEvalBuild( pNew, vLeaves, 0xffff & *pTruth, fKeepLevel, vLeavesBest ); + pObj->Value = Abc_LitNotCond( pObj->Value, Gia_ObjPhaseRealLit(pNew, pObj->Value) ^ pObj->fPhase ); + } + } + } + // cleanup the AIG + Gia_ManHashStop( pNew ); + // check the presence of dangling nodes + if ( Gia_ManHasDangling(pNew) ) + { + pNew = Gia_ManCleanup( pTemp = pNew ); + if ( fVerbose && Gia_ManAndNum(pNew) != Gia_ManAndNum(pTemp) ) + printf( "Gia_ManMapShrink4() node reduction after sweep %6d -> %6d.\n", Gia_ManAndNum(pTemp), Gia_ManAndNum(pNew) ); + Gia_ManStop( pTemp ); + } + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + Vec_IntFree( vLeaves ); + Vec_IntFree( vTruth ); + Vec_IntFree( vVisited ); + Vec_IntFree( vLeavesBest ); + if ( fVerbose ) + { + printf( "Total gain in AIG nodes = %d. ", Gia_ManObjNum(p)-Gia_ManObjNum(pNew) ); + ABC_PRT( "Total runtime", Abc_Clock() - clk ); + } + ABC_FREE( pLutClass ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaShrink6.c b/yosys/abc/src/aig/gia/giaShrink6.c new file mode 100644 index 00000000000..9b92c213710 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaShrink6.c @@ -0,0 +1,492 @@ +/**CFile**************************************************************** + + FileName [giaShrink6.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Implementation of DAG-aware unmapping for 6-input cuts.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaShrink6.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "bool/bdc/bdc.h" +#include "bool/rsb/rsb.h" +//#include "misc/util/utilTruth.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static word Truth[8] = { + ABC_CONST(0xAAAAAAAAAAAAAAAA), + ABC_CONST(0xCCCCCCCCCCCCCCCC), + ABC_CONST(0xF0F0F0F0F0F0F0F0), + ABC_CONST(0xFF00FF00FF00FF00), + ABC_CONST(0xFFFF0000FFFF0000), + ABC_CONST(0xFFFFFFFF00000000), + ABC_CONST(0x0000000000000000), + ABC_CONST(0xFFFFFFFFFFFFFFFF) +}; + +// fanout structure +typedef struct Shr_Fan_t_ Shr_Fan_t; +struct Shr_Fan_t_ +{ + int iFan; // fanout ID + int Next; // next structure +}; + +// operation manager +typedef struct Shr_Man_t_ Shr_Man_t; +struct Shr_Man_t_ +{ + Gia_Man_t * pGia; // user's AIG + Gia_Man_t * pNew; // constructed AIG + int nDivMax; // max number of divisors + int nNewSize; // max growth size + // dynamic fanout (can only grow) + Vec_Wrd_t * vFanMem; // fanout memory + Vec_Int_t * vObj2Fan; // fanout + Shr_Fan_t * pFanTemp; // temporary fanout + // divisors + Vec_Int_t * vDivs; // divisors + Vec_Int_t * vPrio; // priority queue + Vec_Int_t * vDivResub; // resubstitution + Vec_Int_t * vLeaves; // cut leaves + // truth tables + Vec_Wrd_t * vTruths; // truth tables + Vec_Wrd_t * vDivTruths; // truth tables + // bidecomposition + Rsb_Man_t * pManRsb; + Bdc_Man_t * pManDec; + Bdc_Par_t Pars; + // statistics +}; + +#define Shr_ObjForEachFanout( p, iNode, iFan ) \ + for ( iFan = Shr_ManFanIterStart(p, iNode); iFan; iFan = Shr_ManFanIterNext(p) ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Shr_Man_t * Shr_ManAlloc( Gia_Man_t * pGia ) +{ + Shr_Man_t * p; + p = ABC_CALLOC( Shr_Man_t, 1 ); + p->nDivMax = 64; + p->nNewSize = 2 * Gia_ManObjNum(pGia); + p->pGia = pGia; + p->vFanMem = Vec_WrdAlloc( 1000 ); Vec_WrdPush(p->vFanMem, -1); + p->vObj2Fan = Vec_IntStart( p->nNewSize ); + p->vDivs = Vec_IntAlloc( 1000 ); + p->vPrio = Vec_IntAlloc( 1000 ); + p->vTruths = Vec_WrdStart( p->nNewSize ); + p->vDivTruths = Vec_WrdAlloc( 100 ); + p->vDivResub = Vec_IntAlloc( 6 ); + p->vLeaves = Vec_IntAlloc( 6 ); + // start new manager + p->pNew = Gia_ManStart( p->nNewSize ); + p->pNew->pName = Abc_UtilStrsav( pGia->pName ); + p->pNew->pSpec = Abc_UtilStrsav( pGia->pSpec ); + Gia_ManHashAlloc( p->pNew ); + Gia_ManCleanLevels( p->pNew, p->nNewSize ); + // allocate traversal IDs + p->pNew->nObjs = p->nNewSize; + Gia_ManIncrementTravId( p->pNew ); + p->pNew->nObjs = 1; + // start decompostion + p->Pars.nVarsMax = 6; + p->Pars.fVerbose = 0; + p->pManDec = Bdc_ManAlloc( &p->Pars ); + p->pManRsb = Rsb_ManAlloc( 6, p->nDivMax, 4, 1 ); + return p; +} +Gia_Man_t * Shr_ManFree( Shr_Man_t * p ) +{ + // prepare the manager + Gia_Man_t * pTemp; + Gia_ManHashStop( p->pNew ); + Vec_IntFreeP( &p->pNew->vLevels ); + if ( Gia_ManHasDangling(p->pNew) ) + { + p->pNew = Gia_ManCleanup( pTemp = p->pNew ); + if ( Gia_ManAndNum(p->pNew) != Gia_ManAndNum(pTemp) ) + printf( "Node reduction after sweep %6d -> %6d.\n", Gia_ManAndNum(pTemp), Gia_ManAndNum(p->pNew) ); + Gia_ManStop( pTemp ); + } + Gia_ManSetRegNum( p->pNew, Gia_ManRegNum(p->pGia) ); + pTemp = p->pNew; p->pNew = NULL; + // free data structures + Rsb_ManFree( p->pManRsb ); + Bdc_ManFree( p->pManDec ); + Gia_ManStopP( &p->pNew ); + Vec_WrdFree( p->vFanMem ); + Vec_IntFree( p->vObj2Fan ); + Vec_IntFree( p->vDivs ); + Vec_IntFree( p->vPrio ); + Vec_WrdFree( p->vTruths ); + Vec_WrdFree( p->vDivTruths ); + Vec_IntFree( p->vDivResub ); + Vec_IntFree( p->vLeaves ); + ABC_FREE( p ); + return pTemp; +} + + +/**Function************************************************************* + + Synopsis [Fanout manipulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Shr_ManAddFanout( Shr_Man_t * p, int iFanin, int iFanout ) +{ + union { + Shr_Fan_t sFan; + word sWord; + } FanStr; + FanStr.sFan.iFan = iFanout; + FanStr.sFan.Next = Vec_IntEntry(p->vObj2Fan, iFanin); + Vec_IntWriteEntry( p->vObj2Fan, iFanin, Vec_WrdSize(p->vFanMem) ); + Vec_WrdPush(p->vFanMem, FanStr.sWord ); +} +static inline int Shr_ManFanIterStart( Shr_Man_t * p, int iNode ) +{ + if ( Vec_IntEntry(p->vObj2Fan, iNode) == 0 ) + return 0; + p->pFanTemp = (Shr_Fan_t *)Vec_WrdEntryP( p->vFanMem, Vec_IntEntry(p->vObj2Fan, iNode) ); + return p->pFanTemp->iFan; +} +static inline int Shr_ManFanIterNext( Shr_Man_t * p ) +{ + if ( p->pFanTemp->Next == 0 ) + return 0; + p->pFanTemp = (Shr_Fan_t *)Vec_WrdEntryP( p->vFanMem, p->pFanTemp->Next ); + return p->pFanTemp->iFan; +} + +/**Function************************************************************* + + Synopsis [Collect divisors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Shr_ManDivPushOrderByLevel( Shr_Man_t * p, int iDiv ) +{ + int iPlace, * pArray; + Vec_IntPush( p->vPrio, iDiv ); + if ( Vec_IntSize(p->vPrio) == 1 ) + return 0; + pArray = Vec_IntArray(p->vPrio); + for ( iPlace = Vec_IntSize(p->vPrio) - 1; iPlace > 0; iPlace-- ) + if ( Gia_ObjLevel(p->pNew, Gia_ManObj(p->pNew, pArray[iPlace-1])) > + Gia_ObjLevel(p->pNew, Gia_ManObj(p->pNew, pArray[iPlace])) ) + ABC_SWAP( int, pArray[iPlace-1], pArray[iPlace] ) + else + break; + return iPlace; // the place of the new divisor +} +static inline int Shr_ManCollectDivisors( Shr_Man_t * p, Vec_Int_t * vLeaves, int Limit, int nFanoutMax ) +{ + Gia_Obj_t * pFan; + int i, c, iDiv, iFan, iPlace; + assert( Limit > 6 ); + Vec_IntClear( p->vDivs ); + Vec_IntClear( p->vPrio ); + Gia_ManIncrementTravId( p->pNew ); + Vec_IntForEachEntry( vLeaves, iDiv, i ) + { + Vec_IntPush( p->vDivs, iDiv ); + Shr_ManDivPushOrderByLevel( p, iDiv ); + Gia_ObjSetTravIdCurrentId( p->pNew, iDiv ); + } + Vec_IntForEachEntry( p->vPrio, iDiv, i ) + { + c = 0; + assert( Gia_ObjIsTravIdCurrentId(p->pNew, iDiv) ); + Shr_ObjForEachFanout( p, iDiv, iFan ) + { + if ( c++ == nFanoutMax ) + break; + if ( Gia_ObjIsTravIdCurrentId(p->pNew, iFan) ) + continue; + pFan = Gia_ManObj( p->pNew, iFan ); + assert( Gia_ObjIsAnd(pFan) ); + assert( Gia_ObjLevel(p->pNew, Gia_ManObj(p->pNew, iDiv)) < Gia_ObjLevel(p->pNew, pFan) ); + if ( !Gia_ObjIsTravIdCurrentId(p->pNew, Gia_ObjFaninId0(pFan, iFan)) || + !Gia_ObjIsTravIdCurrentId(p->pNew, Gia_ObjFaninId1(pFan, iFan)) ) + continue; + Vec_IntPush( p->vDivs, iFan ); + Gia_ObjSetTravIdCurrentId( p->pNew, iFan ); + iPlace = Shr_ManDivPushOrderByLevel( p, iFan ); + assert( i < iPlace ); + if ( Vec_IntSize(p->vDivs) == Limit ) + return Vec_IntSize(p->vDivs); + } + } + return Vec_IntSize(p->vDivs); +} + +/**Function************************************************************* + + Synopsis [Resynthesizes nodes using bi-decomposition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Shr_ObjPerformBidec( Shr_Man_t * p, Bdc_Man_t * pManDec, Gia_Man_t * pNew, Vec_Int_t * vLeafLits, word uTruth1, word uTruthC ) +{ + Bdc_Fun_t * pFunc; + Gia_Obj_t * pObj; + int i, iVar, iLit, nNodes, iLast; + int nVars = Vec_IntSize(vLeafLits); + assert( uTruth1 != 0 && uTruthC != 0 ); + Bdc_ManDecompose( pManDec, (unsigned *)&uTruth1, (unsigned *)&uTruthC, nVars, NULL, 1000 ); + Bdc_FuncSetCopyInt( Bdc_ManFunc(pManDec, 0), 1 ); + Vec_IntForEachEntry( vLeafLits, iVar, i ) + Bdc_FuncSetCopyInt( Bdc_ManFunc(pManDec, i+1), Abc_Var2Lit(iVar, 0) ); + nNodes = Bdc_ManNodeNum( pManDec ); + for ( i = nVars + 1; i < nNodes; i++ ) + { + pFunc = Bdc_ManFunc( pManDec, i ); + iLast = Gia_ManObjNum(pNew); + iLit = Gia_ManHashAnd( pNew, Bdc_FunFanin0Copy(pFunc), Bdc_FunFanin1Copy(pFunc) ); + Bdc_FuncSetCopyInt( pFunc, iLit ); + if ( iLast == Gia_ManObjNum(pNew) ) + continue; + assert( iLast + 1 == Gia_ManObjNum(pNew) ); + pObj = Gia_ManObj(pNew, Abc_Lit2Var(iLit)); + Gia_ObjSetAndLevel( pNew, pObj ); + Shr_ManAddFanout( p, Gia_ObjFaninId0p(pNew, pObj), Gia_ObjId(pNew, pObj) ); + Shr_ManAddFanout( p, Gia_ObjFaninId1p(pNew, pObj), Gia_ObjId(pNew, pObj) ); + assert( Gia_ManObjNum(pNew) < p->nNewSize ); + } + return Bdc_FunObjCopy( Bdc_ManRoot(pManDec) ); +} + + +/**Function************************************************************* + + Synopsis [Compute truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word Shr_ManComputeTruth6_rec( Gia_Man_t * p, int iNode, Vec_Wrd_t * vTruths ) +{ + Gia_Obj_t * pObj; + word Truth0, Truth1; + if ( Gia_ObjIsTravIdCurrentId(p, iNode) ) + return Vec_WrdEntry(vTruths, iNode); + Gia_ObjSetTravIdCurrentId(p, iNode); + pObj = Gia_ManObj( p, iNode ); + assert( Gia_ObjIsAnd(pObj) ); + Truth0 = Shr_ManComputeTruth6_rec( p, Gia_ObjFaninId0p(p, pObj), vTruths ); + Truth1 = Shr_ManComputeTruth6_rec( p, Gia_ObjFaninId1p(p, pObj), vTruths ); + if ( Gia_ObjFaninC0(pObj) ) + Truth0 = ~Truth0; + if ( Gia_ObjFaninC1(pObj) ) + Truth1 = ~Truth1; + Vec_WrdWriteEntry( vTruths, iNode, Truth0 & Truth1 ); + return Truth0 & Truth1; +} +word Shr_ManComputeTruth6( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vLeaves, Vec_Wrd_t * vTruths ) +{ + int i, iLeaf; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vLeaves, iLeaf, i ) + { + Gia_ObjSetTravIdCurrentId( p, iLeaf ); + Vec_WrdWriteEntry( vTruths, iLeaf, Truth[i] ); + } + return Shr_ManComputeTruth6_rec( p, Gia_ObjId(p, pObj), vTruths ); +} + +/**Function************************************************************* + + Synopsis [Compute truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Shr_ManComputeTruths( Gia_Man_t * p, int nVars, Vec_Int_t * vDivs, Vec_Wrd_t * vDivTruths, Vec_Wrd_t * vTruths ) +{ + Gia_Obj_t * pObj; + word Truth0, Truth1;//, Truthh; + int i, iDiv; + Vec_WrdClear( vDivTruths ); + Vec_IntForEachEntryStop( vDivs, iDiv, i, nVars ) + { + Vec_WrdWriteEntry( vTruths, iDiv, Truth[i] ); + Vec_WrdPush( vDivTruths, Truth[i] ); + } + Vec_IntForEachEntryStart( vDivs, iDiv, i, nVars ) + { + pObj = Gia_ManObj( p, iDiv ); + Truth0 = Vec_WrdEntry( vTruths, Gia_ObjFaninId0(pObj, iDiv) ); + Truth1 = Vec_WrdEntry( vTruths, Gia_ObjFaninId1(pObj, iDiv) ); + if ( Gia_ObjFaninC0(pObj) ) + Truth0 = ~Truth0; + if ( Gia_ObjFaninC1(pObj) ) + Truth1 = ~Truth1; + Vec_WrdWriteEntry( vTruths, iDiv, Truth0 & Truth1 ); + Vec_WrdPush( vDivTruths, Truth0 & Truth1 ); + +// Truthh = Truth0 & Truth1; +// Abc_TtPrintBinary( &Truthh, nVars ); //printf( "\n" ); +// Kit_DsdPrintFromTruth( &Truthh, nVars ); printf( "\n" ); + } +// printf( "\n" ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManMapShrink6( Gia_Man_t * p, int nFanoutMax, int fKeepLevel, int fVerbose ) +{ + Shr_Man_t * pMan; + Gia_Obj_t * pObj, * pFanin; + word uTruth, uTruth0, uTruth1; + int i, k, nDivs, iNode; + int RetValue, Counter1 = 0, Counter2 = 0; + abctime clk2, clk = Abc_Clock(); + abctime timeFanout = 0; + assert( Gia_ManHasMapping(p) ); + pMan = Shr_ManAlloc( p ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + { + pObj->Value = Gia_ManAppendCi( pMan->pNew ); + if ( p->vLevels ) + Gia_ObjSetLevel( pMan->pNew, Gia_ObjFromLit(pMan->pNew, Gia_ObjValue(pObj)), Gia_ObjLevel(p, pObj) ); + } + else if ( Gia_ObjIsCo(pObj) ) + { + pObj->Value = Gia_ManAppendCo( pMan->pNew, Gia_ObjFanin0Copy(pObj) ); + } + else if ( Gia_ObjIsLut(p, i) ) + { + // collect leaves of this gate + Vec_IntClear( pMan->vLeaves ); + Gia_LutForEachFanin( p, i, iNode, k ) + Vec_IntPush( pMan->vLeaves, iNode ); + assert( Vec_IntSize(pMan->vLeaves) <= 6 ); + // compute truth table + uTruth = Shr_ManComputeTruth6( pMan->pGia, pObj, pMan->vLeaves, pMan->vTruths ); + assert( pObj->Value == ~0 ); + if ( uTruth == 0 || ~uTruth == 0 ) + pObj->Value = Abc_LitNotCond( 0, ~uTruth == 0 ); + else + Gia_ManForEachObjVec( pMan->vLeaves, p, pFanin, k ) + if ( uTruth == Truth[k] || ~uTruth == Truth[k] ) + pObj->Value = Abc_LitNotCond( pFanin->Value, ~uTruth == Truth[k] ); + if ( pObj->Value != ~0 ) + continue; + // translate into new nodes + Gia_ManForEachObjVec( pMan->vLeaves, p, pFanin, k ) + { + if ( Abc_LitIsCompl(pFanin->Value) ) + uTruth = ((uTruth & Truth[k]) >> (1 << k)) | ((uTruth & ~Truth[k]) << (1 << k)); + Vec_IntWriteEntry( pMan->vLeaves, k, Abc_Lit2Var(pFanin->Value) ); + } + // compute divisors + clk2 = Abc_Clock(); + nDivs = Shr_ManCollectDivisors( pMan, pMan->vLeaves, pMan->nDivMax, nFanoutMax ); + assert( nDivs <= pMan->nDivMax ); + timeFanout += Abc_Clock() - clk2; + // compute truth tables + Shr_ManComputeTruths( pMan->pNew, Vec_IntSize(pMan->vLeaves), pMan->vDivs, pMan->vDivTruths, pMan->vTruths ); + // perform resubstitution + RetValue = Rsb_ManPerformResub6( pMan->pManRsb, Vec_IntSize(pMan->vLeaves), uTruth, pMan->vDivTruths, &uTruth0, &uTruth1, 0 ); + if ( RetValue ) // resub exists + { + Vec_Int_t * vResult = Rsb_ManGetFanins(pMan->pManRsb); + Vec_IntClear( pMan->vDivResub ); + Vec_IntForEachEntry( vResult, iNode, k ) + Vec_IntPush( pMan->vDivResub, Vec_IntEntry(pMan->vDivs, iNode) ); + pObj->Value = Shr_ObjPerformBidec( pMan, pMan->pManDec, pMan->pNew, pMan->vDivResub, uTruth1, uTruth0 | uTruth1 ); + Counter1++; + } + else + { + pObj->Value = Shr_ObjPerformBidec( pMan, pMan->pManDec, pMan->pNew, pMan->vLeaves, uTruth, ~(word)0 ); + Counter2++; + } + } + } + if ( fVerbose ) + { + printf( "Performed %d resubs and %d decomps. ", Counter1, Counter2 ); + printf( "Gain in AIG nodes = %d. ", Gia_ManObjNum(p)-Gia_ManObjNum(pMan->pNew) ); + ABC_PRT( "Runtime", Abc_Clock() - clk ); +// ABC_PRT( "Divisors", timeFanout ); + } + return Shr_ManFree( pMan ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaShrink7.c b/yosys/abc/src/aig/gia/giaShrink7.c new file mode 100644 index 00000000000..e5556d273f9 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaShrink7.c @@ -0,0 +1,373 @@ +/**CFile**************************************************************** + + FileName [giaShrink7.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Implementation of DAG-aware unmapping for 6-input cuts.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaShrink6.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/vec/vecHash.h" +#include "misc/util/utilTruth.h" + + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// operation manager +typedef struct Unm_Man_t_ Unm_Man_t; +struct Unm_Man_t_ +{ + Gia_Man_t * pGia; // user's AIG + Gia_Man_t * pNew; // constructed AIG + Hash_IntMan_t * pHash; // hash table + int nNewSize; // expected size of new manager + Vec_Int_t * vUsed; // used nodes + Vec_Int_t * vId2Used; // mapping of obj IDs into used node IDs + Vec_Wrd_t * vTruths; // truth tables + Vec_Int_t * vLeaves; // temporary storage for leaves + abctime clkStart; // starting the clock +}; + +extern word Shr_ManComputeTruth6( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vLeaves, Vec_Wrd_t * vTruths ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Unm_Man_t * Unm_ManAlloc( Gia_Man_t * pGia ) +{ + Unm_Man_t * p; + p = ABC_CALLOC( Unm_Man_t, 1 ); + p->clkStart = Abc_Clock(); + p->nNewSize = 3 * Gia_ManObjNum(pGia) / 2; + p->pGia = pGia; + p->pNew = Gia_ManStart( p->nNewSize ); + p->pNew->pName = Abc_UtilStrsav( pGia->pName ); + p->pNew->pSpec = Abc_UtilStrsav( pGia->pSpec ); + Gia_ManHashAlloc( p->pNew ); + Gia_ManCleanLevels( p->pNew, p->nNewSize ); + // allocate traversal IDs + p->pNew->nObjs = p->nNewSize; + Gia_ManIncrementTravId( p->pNew ); + p->pNew->nObjs = 1; + // start hashing + p->pHash = Hash_IntManStart( 1000 ); + // truth tables + p->vLeaves = Vec_IntStart( 10 ); + return p; +} +Gia_Man_t * Unm_ManFree( Unm_Man_t * p ) +{ + Gia_Man_t * pTemp = p->pNew; p->pNew = NULL; + Gia_ManHashStop( pTemp ); + Vec_IntFreeP( &pTemp->vLevels ); + Gia_ManSetRegNum( pTemp, Gia_ManRegNum(p->pGia) ); + // truth tables + Vec_WrdFreeP( &p->vTruths ); + Vec_IntFreeP( &p->vLeaves ); + Vec_IntFreeP( &p->vUsed ); + Vec_IntFreeP( &p->vId2Used ); + // free data structures + Hash_IntManStop( p->pHash ); + ABC_FREE( p ); + + Gia_ManStop( pTemp ); + pTemp = NULL; + + return pTemp; +} + +/**Function************************************************************* + + Synopsis [Computes information about node pairs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Unm_ManPrintPairStats( Hash_IntMan_t * pHash, int nTotal0, int nPairs0, int nPairs1, int fUseLit ) +{ + int i, Num, nRefs, nPairs = 0, nTotal = 0, Counter[21] = {0}; + Num = Hash_IntManEntryNum( pHash ); + for ( i = 1; i <= Num; i++ ) + { + nRefs = Abc_MinInt( 20, Hash_IntObjData2(pHash, i) ); + nTotal += nRefs; + Counter[nRefs]++; + nPairs += (nRefs > 1); +/* + if ( fUseLit ) + printf( "(%c%c, %c%c) %d\n", + Abc_LitIsCompl(Hash_IntObjData0(pHash, i)-2) ? '!' : ' ', + 'a' + Abc_Lit2Var(Hash_IntObjData0(pHash, i)-2), + Abc_LitIsCompl(Hash_IntObjData1(pHash, i)-2) ? '!' : ' ', + 'a' + Abc_Lit2Var(Hash_IntObjData1(pHash, i)-2), nRefs ); + else + printf( "( %c, %c) %d\n", + 'a' + Hash_IntObjData0(pHash, i)-1, + 'a' + Hash_IntObjData1(pHash, i)-1, nRefs ); +*/ +// printf( "(%4d, %4d) %d\n", Hash_IntObjData0(pHash, i), Hash_IntObjData1(pHash, i), nRefs ); + + } + printf( "Statistics for pairs appearing less than 20 times:\n" ); + for ( i = 0; i < 21; i++ ) + if ( Counter[i] > 0 ) + printf( "%3d : %7d %7.2f %%\n", i, Counter[i], 100.0 * Counter[i] * i / Abc_MaxInt(nTotal, 1) ); + printf( "Pairs: Total = %8d Init = %8d %7.2f %% Final = %8d %7.2f %% Real = %8d %7.2f %%\n", nTotal0, + nPairs0, 100.0 * nPairs0 / Abc_MaxInt(nTotal0, 1), + nPairs, 100.0 * nPairs / Abc_MaxInt(nTotal0, 1), + nPairs1, 100.0 * nPairs1 / Abc_MaxInt(nTotal0, 1) ); + return nPairs; +} +Vec_Int_t * Unm_ManComputePairs( Unm_Man_t * p, int fVerbose ) +{ + Gia_Obj_t * pObj; + Vec_Int_t * vPairs = Vec_IntAlloc( 1000 ); + Vec_Int_t * vNum2Obj = Vec_IntStart( 1 ); + Hash_IntMan_t * pHash = Hash_IntManStart( 1000 ); + int nTotal = 0, nPairs0 = 0, nPairs = 0; + int i, k, j, FanK, FanJ, Num, nRefs; + Gia_ManSetRefsMapped( p->pGia ); + Gia_ManForEachLut( p->pGia, i ) + { + nTotal += Gia_ObjLutSize(p->pGia, i) * (Gia_ObjLutSize(p->pGia, i) - 1) / 2; + pObj = Gia_ManObj( p->pGia, i ); + // collect leaves of this gate + Vec_IntClear( p->vLeaves ); + Gia_LutForEachFanin( p->pGia, i, Num, k ) + if ( Gia_ObjRefNumId(p->pGia, Num) > 1 ) + Vec_IntPush( p->vLeaves, Num ); + if ( Vec_IntSize(p->vLeaves) < 2 ) + continue; + nPairs0 += Vec_IntSize(p->vLeaves) * (Vec_IntSize(p->vLeaves) - 1) / 2; + // enumerate pairs + Vec_IntForEachEntry( p->vLeaves, FanK, k ) + Vec_IntForEachEntryStart( p->vLeaves, FanJ, j, k+1 ) + { + if ( FanK > FanJ ) + ABC_SWAP( int, FanK, FanJ ); + Num = Hash_Int2ManInsert( pHash, FanK, FanJ, 0 ); + nRefs = Hash_Int2ObjInc(pHash, Num); + if ( nRefs == 0 ) + { + assert( Num == Hash_IntManEntryNum(pHash) ); + assert( Num == Vec_IntSize(vNum2Obj) ); + Vec_IntPush( vNum2Obj, i ); + continue; + } + if ( nRefs == 1 ) + { + assert( Num < Vec_IntSize(vNum2Obj) ); + Vec_IntPush( vPairs, Vec_IntEntry(vNum2Obj, Num) ); + Vec_IntPush( vPairs, FanK ); + Vec_IntPush( vPairs, FanJ); + } + Vec_IntPush( vPairs, i ); + Vec_IntPush( vPairs, FanK ); + Vec_IntPush( vPairs, FanJ ); + } + } + Vec_IntFree( vNum2Obj ); + if ( fVerbose ) + nPairs = Unm_ManPrintPairStats( pHash, nTotal, nPairs0, Vec_IntSize(vPairs) / 3, 0 ); + Hash_IntManStop( pHash ); + return vPairs; +} +// finds used nodes +Vec_Int_t * Unm_ManFindUsedNodes( Vec_Int_t * vPairs, int nObjs ) +{ + Vec_Int_t * vNodes = Vec_IntAlloc( 1000 ); + Vec_Str_t * vMarks = Vec_StrStart( nObjs ); int i; + for ( i = 0; i < Vec_IntSize(vPairs); i += 3 ) + Vec_StrWriteEntry( vMarks, Vec_IntEntry(vPairs, i), 1 ); + for ( i = 0; i < nObjs; i++ ) + if ( Vec_StrEntry( vMarks, i ) ) + Vec_IntPush( vNodes, i ); + Vec_StrFree( vMarks ); + printf( "The number of used nodes = %d\n", Vec_IntSize(vNodes) ); + return vNodes; +} +// computes truth table for selected nodes +Vec_Wrd_t * Unm_ManComputeTruths( Unm_Man_t * p ) +{ + Vec_Wrd_t * vTruthsTemp, * vTruths; + int i, k, iObj, iNode; + word uTruth; + vTruths = Vec_WrdAlloc( Vec_IntSize(p->vUsed) ); + vTruthsTemp = Vec_WrdStart( Gia_ManObjNum(p->pGia) ); + Vec_IntForEachEntry( p->vUsed, iObj, i ) + { + assert( Gia_ObjIsLut(p->pGia, iObj) ); + // collect leaves of this gate + Vec_IntClear( p->vLeaves ); + Gia_LutForEachFanin( p->pGia, iObj, iNode, k ) + Vec_IntPush( p->vLeaves, iNode ); + assert( Vec_IntSize(p->vLeaves) <= 6 ); + // compute truth table + uTruth = Shr_ManComputeTruth6( p->pGia, Gia_ManObj(p->pGia, iObj), p->vLeaves, vTruthsTemp ); + Vec_WrdPush( vTruths, uTruth ); +// if ( i % 100 == 0 ) +// Kit_DsdPrintFromTruth( (unsigned *)&uTruth, 6 ), printf( "\n" ); + } + Vec_WrdFreeP( &vTruthsTemp ); + return vTruths; +} + +/**Function************************************************************* + + Synopsis [Collects decomposable pairs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Unm_ManCollectDecomp( Unm_Man_t * p, Vec_Int_t * vPairs, int fVerbose ) +{ + word uTruth; int nNonUnique = 0; + int i, k, j, s, iObj, iNode, iUsed, FanK, FanJ, Res, Num, nRefs; + Vec_Int_t * vNum2Obj = Vec_IntStart( 1 ); + Vec_Int_t * vPairs2 = Vec_IntAlloc( 1000 ); + assert( Hash_IntManEntryNum(p->pHash) == 0 ); + for ( i = 0; i < Vec_IntSize(vPairs); i += 3 ) + { + iObj = Vec_IntEntry( vPairs, i ); + assert( Gia_ObjIsLut(p->pGia, iObj) ); + // collect leaves of this gate + Vec_IntClear( p->vLeaves ); + Gia_LutForEachFanin( p->pGia, iObj, iNode, s ) + Vec_IntPush( p->vLeaves, iNode ); + assert( Vec_IntSize(p->vLeaves) <= 6 ); + FanK = Vec_IntEntry(vPairs, i+1); + FanJ = Vec_IntEntry(vPairs, i+2); + k = Vec_IntFind( p->vLeaves, FanK ); + j = Vec_IntFind( p->vLeaves, FanJ ); + assert( FanK < FanJ ); + iUsed = Vec_IntEntry( p->vId2Used, iObj ); + uTruth = Vec_WrdEntry( p->vTruths, iUsed ); + Res = Abc_TtCheckDsdAnd( uTruth, k, j, NULL ); + if ( Res == -1 ) + continue; + // derive literals + FanK = Abc_Var2Lit( FanK, ((Res >> 0) & 1) ); + FanJ = Abc_Var2Lit( FanJ, ((Res >> 1) & 1) ); + if ( Res == 4 ) + ABC_SWAP( int, FanK, FanJ ); + Num = Hash_Int2ManInsert( p->pHash, FanK, FanJ, 0 ); + nRefs = Hash_Int2ObjInc(p->pHash, Num); + if ( nRefs == 0 ) + { + assert( Num == Hash_IntManEntryNum(p->pHash) ); + assert( Num == Vec_IntSize(vNum2Obj) ); + Vec_IntPush( vNum2Obj, iObj ); + continue; + } + if ( nRefs == 1 ) + { + assert( Num < Vec_IntSize(vNum2Obj) ); + Vec_IntPush( vPairs2, Vec_IntEntry(vNum2Obj, Num) ); + Vec_IntPush( vPairs2, FanK ); + Vec_IntPush( vPairs2, FanJ ); + nNonUnique++; + } + Vec_IntPush( vPairs2, iObj ); + Vec_IntPush( vPairs2, FanK ); + Vec_IntPush( vPairs2, FanJ ); + } + Vec_IntFree( vNum2Obj ); + if ( fVerbose ) + Unm_ManPrintPairStats( p->pHash, Vec_IntSize(vPairs)/3, Hash_IntManEntryNum(p->pHash), Vec_IntSize(vPairs2)/3, 1 ); +// Hash_IntManStop( pHash ); + return vPairs2; +} + +/**Function************************************************************* + + Synopsis [Compute truth tables for the selected nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Unm_ManWork( Unm_Man_t * p ) +{ + Vec_Int_t * vPairs, * vPairs2; + // find the duplicated pairs + vPairs = Unm_ManComputePairs( p, 1 ); + // find the used nodes + p->vUsed = Unm_ManFindUsedNodes( vPairs, Gia_ManObjNum(p->pGia) ); + p->vId2Used = Vec_IntInvert( p->vUsed, -1 ); + Vec_IntFillExtra( p->vId2Used, Gia_ManObjNum(p->pGia), -1 ); + // compute truth tables for used nodes + p->vTruths = Unm_ManComputeTruths( p ); + // derive new pairs + vPairs2 = Unm_ManCollectDecomp( p, vPairs, 1 ); + Vec_IntFreeP( &vPairs ); + Vec_IntFreeP( &vPairs2 ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Unm_ManTest( Gia_Man_t * pGia ) +{ + Unm_Man_t * p; + p = Unm_ManAlloc( pGia ); + Unm_ManWork( p ); + + Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart ); + return Unm_ManFree( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaSif.c b/yosys/abc/src/aig/gia/giaSif.c new file mode 100644 index 00000000000..4df5c47f776 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaSif.c @@ -0,0 +1,676 @@ +/**CFile**************************************************************** + + FileName [giaSif.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Sequential mapping.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSif.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSifDupNode_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( Gia_ObjUpdateTravIdCurrent(p, pObj) ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManSifDupNode_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManSifDupNode_rec( pNew, p, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManAppendAnd2( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +void Gia_ManSifDupNode( Gia_Man_t * pNew, Gia_Man_t * p, int iObj, Vec_Int_t * vCopy ) +{ + int k, iFan; + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); + Gia_ManIncrementTravId( p ); + Gia_LutForEachFanin( p, iObj, iFan, k ) + { + assert( Vec_IntEntry(vCopy, iFan) >= 0 ); + Gia_ManObj(p, iFan)->Value = Vec_IntEntry(vCopy, iFan); + Gia_ObjUpdateTravIdCurrentId(p, iFan); + } + Gia_ManSifDupNode_rec( pNew, p, pObj ); + Vec_IntWriteEntry( vCopy, iObj, pObj->Value ); +} +Vec_Int_t * Gia_ManSifInitNeg( Gia_Man_t * p, Vec_Int_t * vMoves, Vec_Int_t * vRegs ) +{ + Vec_Int_t * vRes = Vec_IntAlloc( Vec_IntSize(vRegs) ); + Gia_Obj_t * pObj; int i, iObj; + Gia_Man_t * pNew = Gia_ManStart( 1000 ), * pTemp; + Vec_Int_t * vCopy = Vec_IntStartFull( Gia_ManObjNum(p) ); + Vec_IntWriteEntry( vCopy, 0, 0 ); + Gia_ManForEachRo( p, pObj, i ) + Vec_IntWriteEntry( vCopy, Gia_ObjId(p, pObj), Gia_ManAppendCi(pNew) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Vec_IntForEachEntry( vMoves, iObj, i ) + Gia_ManSifDupNode( pNew, p, iObj, vCopy ); + Vec_IntForEachEntry( vRegs, iObj, i ) + { + int iLit = Vec_IntEntry( vCopy, iObj ); + assert( iLit >= 0 ); + Gia_ManAppendCo( pNew, iLit ); + } + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Gia_ManSetPhase( pNew ); + Gia_ManForEachPo( pNew, pObj, i ) + Vec_IntPush( vRes, pObj->fPhase ); + Gia_ManStop( pNew ); + Vec_IntFree( vCopy ); + assert( Vec_IntSize(vRes) == Vec_IntSize(vRegs) ); + return vRes; +} +Vec_Int_t * Gia_ManSifInitPos( Gia_Man_t * p, Vec_Int_t * vMoves, Vec_Int_t * vRegs ) +{ + extern int * Abc_NtkSolveGiaMiter( Gia_Man_t * p ); + int i, iObj, iLitAnd = 1, * pResult = NULL; + Gia_Obj_t * pObj; Vec_Int_t * vRes = NULL; + Gia_Man_t * pNew = Gia_ManStart( 1000 ), * pTemp; + Vec_Int_t * vCopy = Vec_IntStartFull( Gia_ManObjNum(p) ); + Vec_IntWriteEntry( vCopy, 0, 0 ); + Vec_IntForEachEntry( vRegs, iObj, i ) + Vec_IntWriteEntry( vCopy, iObj, Gia_ManAppendCi(pNew) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Vec_IntForEachEntry( vMoves, iObj, i ) + Gia_ManSifDupNode( pNew, p, iObj, vCopy ); + Gia_ManForEachRi( p, pObj, i ) + { + int iFan = Gia_ObjFaninId0p(p, pObj); + int iLit = Vec_IntEntry(vCopy, iFan); + if ( iLit == -1 ) + continue; + iLit = Abc_LitNotCond( iLit, Gia_ObjFaninC0(pObj) ); + iLitAnd = Gia_ManAppendAnd2( pNew, iLitAnd, Abc_LitNot(iLit) ); + } + Gia_ManAppendCo( pNew, iLitAnd ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + pResult = Abc_NtkSolveGiaMiter( pNew ); + if ( pResult ) + { + vRes = Vec_IntAllocArray( pResult, Vec_IntSize(vRegs) ); + Gia_ManSetPhasePattern( pNew, vRes ); + assert( Gia_ManPo(pNew, 0)->fPhase == 1 ); + } + else + { + vRes = Vec_IntStart( Vec_IntSize(vRegs) ); + printf( "***!!!*** The SAT problem has no solution. Using all-0 initial state. ***!!!***\n" ); + } + Gia_ManStop( pNew ); + Vec_IntFree( vCopy ); + assert( Vec_IntSize(vRes) == Vec_IntSize(vRegs) ); + return vRes; +} +Gia_Man_t * Gia_ManSifDerive( Gia_Man_t * p, Vec_Int_t * vCounts, int fVerbose ) +{ + Gia_Man_t * pNew = NULL; Gia_Obj_t * pObj; + Vec_Int_t * vCopy = Vec_IntStartFull( Gia_ManObjNum(p) ); + Vec_Int_t * vCopy2 = Vec_IntStartFull( Gia_ManObjNum(p) ); + Vec_Int_t * vLuts[3], * vRos[3], * vRegs[2], * vInits[2], * vTemp; + int i, k, Id, iFan; + for ( i = 0; i < 3; i++ ) + { + vLuts[i] = Vec_IntAlloc(100); + vRos[i] = Vec_IntAlloc(100); + if ( i == 2 ) break; + vRegs[i] = Vec_IntAlloc(100); + } + Gia_ManForEachLut( p, i ) + if ( Vec_IntEntry(vCounts, i) == 1 ) + Vec_IntPush( vLuts[0], i ); + else if ( Vec_IntEntry(vCounts, i) == -1 ) + Vec_IntPush( vLuts[1], i ); + else if ( Vec_IntEntry(vCounts, i) == 0 ) + Vec_IntPush( vLuts[2], i ); + else assert( 0 ); + assert( Vec_IntSize(vLuts[0]) || Vec_IntSize(vLuts[1]) ); + if ( Vec_IntSize(vLuts[0]) ) + { + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vLuts[0], Id, i ) + Gia_ObjSetTravIdCurrentId(p, Id); + Gia_ManForEachRo( p, pObj, i ) + if ( Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(Gia_ObjRoToRi(p, pObj))) ) + Vec_IntPush( vRos[0], Gia_ObjId(p, pObj) ); + assert( !Vec_IntSize(vLuts[0]) == !Vec_IntSize(vRos[0]) ); + } + if ( Vec_IntSize(vLuts[1]) ) + { + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vLuts[1], Id, i ) + Gia_LutForEachFanin( p, Id, iFan, k ) + Gia_ObjSetTravIdCurrentId(p, iFan); + Gia_ManForEachRo( p, pObj, i ) + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + Vec_IntPush( vRos[1], Gia_ObjId(p, pObj) ); + assert( !Vec_IntSize(vLuts[1]) == !Vec_IntSize(vRos[1]) ); + } + Gia_ManIncrementTravId( p ); + for ( k = 0; k < 2; k++ ) + Vec_IntForEachEntry( vRos[k], Id, i ) + Gia_ObjSetTravIdCurrentId(p, Id); + Gia_ManForEachRo( p, pObj, i ) + if ( !Gia_ObjIsTravIdCurrent(p, pObj) ) + Vec_IntPush( vRos[2], Gia_ObjId(p, pObj) ); + + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vLuts[0], Id, i ) + Gia_ObjSetTravIdCurrentId(p, Id); + Vec_IntForEachEntry( vLuts[0], Id, i ) + Gia_LutForEachFanin( p, Id, iFan, k ) + if ( !Gia_ObjUpdateTravIdCurrentId(p, iFan) ) + Vec_IntPush( vRegs[0], iFan ); + Vec_IntSort( vRegs[0], 0 ); + assert( Vec_IntCountDuplicates(vRegs[1]) == 0 ); + assert( !Vec_IntSize(vLuts[0]) == !Vec_IntSize(vRegs[0]) ); + + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vLuts[0], Id, i ) + Gia_LutForEachFanin( p, Id, iFan, k ) + Gia_ObjSetTravIdCurrentId(p, iFan); + Vec_IntForEachEntry( vLuts[2], Id, i ) + Gia_LutForEachFanin( p, Id, iFan, k ) + Gia_ObjSetTravIdCurrentId(p, iFan); + Gia_ManForEachCo( p, pObj, i ) + Gia_ObjSetTravIdCurrentId(p, Gia_ObjFaninId0p(p, pObj)); + Vec_IntForEachEntry( vRos[1], Id, i ) + if ( Gia_ObjIsTravIdCurrentId(p, Id) ) + Vec_IntPush( vRegs[1], Id ); + Vec_IntForEachEntry( vLuts[1], Id, i ) + if ( Gia_ObjIsTravIdCurrentId(p, Id) ) + Vec_IntPush( vRegs[1], Id ); + Vec_IntSort( vRegs[1], 0 ); + assert( Vec_IntCountDuplicates(vRegs[1]) == 0 ); + assert( !Vec_IntSize(vLuts[1]) == !Vec_IntSize(vRegs[1]) ); + + vInits[0] = Vec_IntSize(vLuts[0]) ? Gia_ManSifInitPos( p, vLuts[0], vRegs[0] ) : Vec_IntAlloc(0); + vInits[1] = Vec_IntSize(vLuts[1]) ? Gia_ManSifInitNeg( p, vLuts[1], vRegs[1] ) : Vec_IntAlloc(0); + + if ( fVerbose ) + { + printf( "Flops : %5d %5d %5d\n", Vec_IntSize(vRos[0]), Vec_IntSize(vRos[1]), Vec_IntSize(vRos[2]) ); + printf( "LUTs : %5d %5d %5d\n", Vec_IntSize(vLuts[0]), Vec_IntSize(vLuts[1]), Vec_IntSize(vLuts[2]) ); + printf( "Spots : %5d %5d %5d\n", Vec_IntSize(vRegs[0]), Vec_IntSize(vRegs[1]), 0 ); + } + + pNew = Gia_ManStart( Gia_ManObjNum(p) + Vec_IntSize(vRegs[0]) + Vec_IntSize(vRegs[1]) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + + Vec_IntWriteEntry( vCopy, 0, 0 ); + Gia_ManForEachPi( p, pObj, i ) + Vec_IntWriteEntry( vCopy, Gia_ObjId(p, pObj), Gia_ManAppendCi(pNew) ); + Vec_IntForEachEntry( vRos[2], Id, i ) + Vec_IntWriteEntry( vCopy, Id, Gia_ManAppendCi(pNew) ); + Vec_IntForEachEntry( vRegs[1], Id, i ) + Vec_IntWriteEntry( vCopy, Id, Abc_LitNotCond(Gia_ManAppendCi(pNew), Vec_IntEntry(vInits[1], i)) ); + + vTemp = Vec_IntAlloc(100); + Vec_IntForEachEntry( vRegs[0], Id, i ) + Vec_IntPush( vTemp, Vec_IntEntry(vCopy, Id) ); + Vec_IntForEachEntry( vRegs[0], Id, i ) + Vec_IntWriteEntry( vCopy, Id, Abc_LitNotCond(Gia_ManAppendCi(pNew), Vec_IntEntry(vInits[0], i)) ); + Vec_IntForEachEntry( vLuts[0], Id, i ) + Gia_ManSifDupNode( pNew, p, Id, vCopy ); + Vec_IntForEachEntry( vRegs[0], Id, i ) + Vec_IntWriteEntry( vCopy, Id, Vec_IntEntry(vTemp, i) ); + Vec_IntFree( vTemp ); + + Gia_ManForEachRoToRiVec( vRos[0], p, pObj, i ) + Vec_IntWriteEntry( vCopy, Vec_IntEntry(vRos[0], i), Abc_LitNotCond(Vec_IntEntry(vCopy, Gia_ObjFaninId0p(p, pObj)), Gia_ObjFaninC0(pObj)) ); + Vec_IntForEachEntry( vLuts[2], Id, i ) + Gia_ManSifDupNode( pNew, p, Id, vCopy ); + + Gia_ManForEachRoToRiVec( vRos[1], p, pObj, i ) + Vec_IntWriteEntry( vCopy2, Vec_IntEntry(vRos[1], i), Abc_LitNotCond(Vec_IntEntry(vCopy, Gia_ObjFaninId0p(p, pObj)), Gia_ObjFaninC0(pObj)) ); + Vec_IntForEachEntry( vLuts[1], Id, i ) + Gia_ManSifDupNode( pNew, p, Id, vCopy2 ); + + Gia_ManForEachPo( p, pObj, i ) + Gia_ManAppendCo( pNew, Abc_LitNotCond(Vec_IntEntry(vCopy, Gia_ObjFaninId0p(p, pObj)), Gia_ObjFaninC0(pObj)) ); + Gia_ManForEachRoToRiVec( vRos[2], p, pObj, i ) + Gia_ManAppendCo( pNew, Abc_LitNotCond(Vec_IntEntry(vCopy, Gia_ObjFaninId0p(p, pObj)), Gia_ObjFaninC0(pObj)) ); + Vec_IntForEachEntry( vRegs[1], Id, i ) + Gia_ManAppendCo( pNew, Abc_LitNotCond(Vec_IntEntry(vCopy2, Id), Vec_IntEntry(vInits[1], i)) ); + Vec_IntForEachEntry( vRegs[0], Id, i ) + Gia_ManAppendCo( pNew, Abc_LitNotCond(Vec_IntEntry(vCopy, Id), Vec_IntEntry(vInits[0], i)) ); + + Gia_ManSetRegNum( pNew, Vec_IntSize(vRos[2]) + Vec_IntSize(vRegs[0]) + Vec_IntSize(vRegs[1]) ); + + for ( i = 0; i < 3; i++ ) + { + Vec_IntFreeP( &vLuts[i] ); + Vec_IntFreeP( &vRos[i] ); + if ( i == 2 ) break; + Vec_IntFreeP( &vRegs[i] ); + Vec_IntFreeP( &vInits[i] ); + } + Vec_IntFree( vCopy ); + Vec_IntFree( vCopy2 ); + return pNew; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSifArea_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vCuts, int nSize ) +{ + int i, * pCut, Area = 1; + if ( Gia_ObjUpdateTravIdCurrent(p, pObj) ) + return 0; + if ( !Gia_ObjIsAnd(pObj) ) + return 0; + pCut = Vec_IntEntryP( vCuts, Gia_ObjId(p, pObj)*nSize ); + for ( i = 1; i <= pCut[0]; i++ ) + Area += Gia_ManSifArea_rec( p, Gia_ManObj(p, pCut[i] >> 8), vCuts, nSize ); + return Area; +} +int Gia_ManSifArea( Gia_Man_t * p, Vec_Int_t * vCuts, int nSize ) +{ + Gia_Obj_t * pObj; int i, nArea = 0; + Gia_ManIncrementTravId( p ); + Gia_ManForEachCo( p, pObj, i ) + nArea += Gia_ManSifArea_rec( p, Gia_ObjFanin0(pObj), vCuts, nSize ); + return nArea; +} +int Gia_ManSifDelay_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nSize ) +{ + int i, * pCut, Delay, nFails = 0; + if ( Gia_ObjUpdateTravIdCurrent(p, pObj) ) + return 0; + if ( !Gia_ObjIsAnd(pObj) ) + return 0; + pCut = Vec_IntEntryP( vCuts, Gia_ObjId(p, pObj)*nSize ); + Delay = -ABC_INFINITY-10000; + for ( i = 1; i <= pCut[0]; i++ ) + { + nFails += Gia_ManSifDelay_rec( p, Gia_ManObj(p, pCut[i] >> 8), vCuts, vTimes, nSize ); + Delay = Abc_MaxInt( Delay, Vec_IntEntry(vTimes, pCut[i] >> 8) ); + } + Delay += 1; + return nFails + (int)(Delay > Vec_IntEntry(vTimes, Gia_ObjId(p, pObj))); +} +int Gia_ManSifDelay( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nSize ) +{ + Gia_Obj_t * pObj; int i, nFails = 0; + Gia_ManIncrementTravId( p ); + Gia_ManForEachCo( p, pObj, i ) + nFails += Gia_ManSifDelay_rec( p, Gia_ObjFanin0(pObj), vCuts, vTimes, nSize ); + return nFails; +} +static inline int Gia_ManSifTimeToCount( int Value, int Period ) +{ + return (Period*0xFFFF + Value)/Period + ((Period*0xFFFF + Value)%Period != 0) - 0x10000; +} +Vec_Int_t * Gia_ManSifTimesToCounts( Gia_Man_t * p, Vec_Int_t * vTimes, int Period ) +{ + int i, Times; + Vec_Int_t * vCounts = Vec_IntStart( Gia_ManObjNum(p) ); + Vec_IntFillExtra( vTimes, Gia_ManObjNum(p), 0 ); + Vec_IntForEachEntry( vTimes, Times, i ) + if ( Gia_ObjIsLut(p, i) ) + Vec_IntWriteEntry( vCounts, i, Gia_ManSifTimeToCount(Times, Period) ); + return vCounts; +} +Gia_Man_t * Gia_ManSifTransform( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nLutSize, int Period, int fVerbose ) +{ + Gia_Man_t * pNew = NULL; Vec_Int_t * vCounts = NULL; + if ( fVerbose ) + printf( "Current area = %d. Period = %d. ", Gia_ManSifArea(p, vCuts, nLutSize+1), Period ); + if ( fVerbose ) + printf( "Delay checking failed for %d cuts.\n", Gia_ManSifDelay( p, vCuts, vTimes, nLutSize+1 ) ); + vCounts = Gia_ManSifTimesToCounts( p, vTimes, Period ); + pNew = Gia_ManSifDerive( p, vCounts, fVerbose ); + Vec_IntFreeP( &vCounts ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSifCutMerge( int * pCut, int * pCut1, int * pCut2, int nSize ) +{ + int * pBeg = pCut+1; + int * pBeg1 = pCut1+1; + int * pBeg2 = pCut2+1; + int * pEnd1 = pBeg1 + pCut1[0]; + int * pEnd2 = pBeg2 + pCut2[0]; + while ( pBeg1 < pEnd1 && pBeg2 < pEnd2 ) + { + if ( pBeg == pCut+nSize ) + { + pCut[0] = -1; + return; + } + if ( *pBeg1 == *pBeg2 ) + *pBeg++ = *pBeg1++, pBeg2++; + else if ( *pBeg1 < *pBeg2 ) + *pBeg++ = *pBeg1++; + else + *pBeg++ = *pBeg2++; + } + while ( pBeg1 < pEnd1 ) + { + if ( pBeg == pCut+nSize ) + { + pCut[0] = -1; + return; + } + *pBeg++ = *pBeg1++; + } + while ( pBeg2 < pEnd2 ) + { + if ( pBeg == pCut+nSize ) + { + pCut[0] = -1; + return; + } + *pBeg++ = *pBeg2++; + } + pCut[0] = pBeg-(pCut+1); + assert( pCut[0] < nSize ); +} +static inline int Gia_ManSifCutChoice( Gia_Man_t * p, int Level, int iObj, int iSibl, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nSize ) +{ + int * pCut = Vec_IntEntryP( vCuts, iObj*nSize ); + int * pCut2 = Vec_IntEntryP( vCuts, iSibl*nSize ); + int Level2 = Vec_IntEntry( vTimes, iSibl ); int i; + assert( iObj > iSibl ); + if ( Level < Level2 || (Level == Level2 && pCut[0] <= pCut2[0]) ) + return Level; + for ( i = 0; i <= pCut2[0]; i++ ) + pCut[i] = pCut2[i]; + return Level2; +} +static inline int Gia_ManSifCutOne( Gia_Man_t * p, int iObj, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nSize ) +{ + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + int iFan0 = Gia_ObjFaninId0(pObj, iObj); + int iFan1 = Gia_ObjFaninId1(pObj, iObj); + int Cut0[2] = { 1, iFan0 << 8 }; + int Cut1[2] = { 1, iFan1 << 8 }; + int * pCut = Vec_IntEntryP( vCuts, iObj*nSize ); + int * pCut0 = Vec_IntEntryP( vCuts, iFan0*nSize ); + int * pCut1 = Vec_IntEntryP( vCuts, iFan1*nSize ); + int Level_ = Vec_IntEntry( vTimes, iObj ); + int Level0 = Vec_IntEntry( vTimes, iFan0 ); + int Level1 = Vec_IntEntry( vTimes, iFan1 ); + int Level = -ABC_INFINITY, i; + assert( pCut0[0] > 0 && pCut1[0] > 0 ); + if ( Level0 == Level1 ) + Gia_ManSifCutMerge( pCut, pCut0, pCut1, nSize ); + else if ( Level0 > Level1 ) + Gia_ManSifCutMerge( pCut, pCut0, Cut1, nSize ); + else //if ( Level0 < Level1 ) + Gia_ManSifCutMerge( pCut, pCut1, Cut0, nSize ); + if ( pCut[0] == -1 ) + { + pCut[0] = 2; + pCut[1] = iFan0 << 8; + pCut[2] = iFan1 << 8; + } + for ( i = 1; i <= pCut[0]; i++ ) + Level = Abc_MaxInt( Level, Vec_IntEntry(vTimes, pCut[i] >> 8) ); + Level++; + if ( Gia_ObjSibl(p, iObj) ) + Level = Gia_ManSifCutChoice( p, Level, iObj, Gia_ObjSibl(p, iObj), vCuts, vTimes, nSize ); + assert( pCut[0] > 0 && pCut[0] < nSize ); + Vec_IntUpdateEntry( vTimes, iObj, Level ); + return Level > Level_; +} +int Gia_ManSifCheckIter( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nLutSize, int Period ) +{ + int i, fChange = 0, nSize = nLutSize+1; + Gia_Obj_t * pObj, * pObjRi, * pObjRo; + Gia_ManForEachAnd( p, pObj, i ) + fChange |= Gia_ManSifCutOne( p, i, vCuts, vTimes, nSize ); + Gia_ManForEachCo( p, pObj, i ) + Vec_IntWriteEntry( vTimes, Gia_ObjId(p, pObj), Vec_IntEntry(vTimes, Gia_ObjFaninId0p(p, pObj)) ); + Gia_ManForEachRiRo( p, pObjRi, pObjRo, i ) + { + int TimeNew = Vec_IntEntry(vTimes, Gia_ObjId(p, pObjRi)) - Period; + TimeNew = Abc_MaxInt( TimeNew, Vec_IntEntry(vTimes, Gia_ObjId(p, pObjRo)) ); + Vec_IntWriteEntry( vTimes, Gia_ObjId(p, pObjRo), TimeNew ); + } + return fChange; +} +int Gia_ManSifCheckPeriod( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nLutSize, int Period, int * pIters ) +{ + Gia_Obj_t * pObj; int i, Id, Stop, nSize = nLutSize+1; + assert( Gia_ManRegNum(p) > 0 ); + Gia_ManForEachCiId( p, Id, i ) + Vec_IntWriteEntry( vCuts, Id*nSize, 1 ); + Gia_ManForEachCiId( p, Id, i ) + Vec_IntWriteEntry( vCuts, Id*nSize+1, Id << 8 ); + Vec_IntFill( vTimes, Gia_ManObjNum(p), -Period ); + if ( p->vStopsF ) + Vec_StrForEachEntry( p->vStopsF, Stop, i ) + if ( Stop ) Vec_IntWriteEntry( vTimes, i, 0 ); + Vec_IntWriteEntry( vTimes, 0, 0 ); + Gia_ManForEachPi( p, pObj, i ) + Vec_IntWriteEntry( vTimes, Gia_ObjId(p, pObj), 0 ); + for ( *pIters = 0; *pIters < 100; (*pIters)++ ) + { + if ( !Gia_ManSifCheckIter(p, vCuts, vTimes, nLutSize, Period) ) + return 1; + Gia_ManForEachPo( p, pObj, i ) + if ( Vec_IntEntry(vTimes, Gia_ObjId(p, pObj)) > Period ) + return 0; + Gia_ManForEachObj( p, pObj, i ) + if ( Vec_IntEntry(vTimes, Gia_ObjId(p, pObj)) > 2*Period ) + return 0; + if ( p->vStopsB ) + Vec_StrForEachEntry( p->vStopsB, Stop, i ) + if ( Stop && Vec_IntEntry(vTimes, i) > Period ) + return 0; + } + return 0; +} +int Gia_ManSifMapComb( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nLutSize ) +{ + Gia_Obj_t * pObj; int i, Id, Res = 0, nSize = nLutSize+1; + Vec_IntFill( vTimes, Gia_ManObjNum(p), 0 ); + Gia_ManForEachCiId( p, Id, i ) + Vec_IntWriteEntry( vCuts, Id*nSize, 1 ); + Gia_ManForEachCiId( p, Id, i ) + Vec_IntWriteEntry( vCuts, Id*nSize+1, Id << 8 ); + Gia_ManForEachAnd( p, pObj, i ) + Gia_ManSifCutOne( p, i, vCuts, vTimes, nSize ); + Gia_ManForEachCo( p, pObj, i ) + Res = Abc_MaxInt( Res, Vec_IntEntry(vTimes, Gia_ObjFaninId0p(p, pObj)) ); + return Res; +} +void Gia_ManSifPrintTimes( Gia_Man_t * p, Vec_Int_t * vTimes, int Period ) +{ + int i, Value, Pos[256] = {0}, Neg[256] = {0}; + Gia_ManForEachLut( p, i ) + { + Value = Gia_ManSifTimeToCount( Vec_IntEntry(vTimes, i), Period ); + Value = Abc_MinInt( Value, 255 ); + Value = Abc_MaxInt( Value, -255 ); + if ( Value >= 0 ) + Pos[Value]++; + else + Neg[-Value]++; + } + printf( "Statistics: " ); + for ( i = 255; i > 0; i-- ) + if ( Neg[i] ) + printf( " -%d=%d", i, Neg[i] ); + for ( i = 0; i < 256; i++ ) + if ( Pos[i] ) + printf( " %d=%d", i, Pos[i] ); + printf( "\n" ); +} +int Gia_ManSifDeriveMapping_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vCuts, int nSize ) +{ + int i, * pCut, Area = 1; + if ( !Gia_ObjIsAnd(pObj) ) + return 0; + if ( Gia_ObjUpdateTravIdCurrent(p, pObj) ) + return 0; + pCut = Vec_IntEntryP( vCuts, Gia_ObjId(p, pObj)*nSize ); + for ( i = 1; i <= pCut[0]; i++ ) + Area += Gia_ManSifDeriveMapping_rec( p, Gia_ManObj(p, pCut[i] >> 8), vCuts, nSize ); + Vec_IntWriteEntry( p->vMapping, Gia_ObjId(p, pObj), Vec_IntSize(p->vMapping) ); + Vec_IntPush( p->vMapping, pCut[0] ); + for ( i = 1; i <= pCut[0]; i++ ) + { + Gia_Obj_t * pObj = Gia_ManObj(p, pCut[i] >> 8); + assert( !Gia_ObjIsAnd(pObj) || Gia_ObjIsLut(p, pCut[i] >> 8) ); + Vec_IntPush( p->vMapping, pCut[i] >> 8 ); + } + Vec_IntPush( p->vMapping, -1 ); + return Area; +} +int Gia_ManSifDeriveMapping( Gia_Man_t * p, Vec_Int_t * vCuts, Vec_Int_t * vTimes, int nLutSize, int Period, int fVerbose ) +{ + Gia_Obj_t * pObj; int i, nArea = 0; + if ( p->vMapping != NULL ) + { + printf( "Removing available combinational mapping.\n" ); + Vec_IntFreeP( &p->vMapping ); + } + assert( p->vMapping == NULL ); + p->vMapping = Vec_IntStart( Gia_ManObjNum(p) ); + Gia_ManIncrementTravId( p ); + Gia_ManForEachCo( p, pObj, i ) + nArea += Gia_ManSifDeriveMapping_rec( p, Gia_ObjFanin0(pObj), vCuts, nLutSize+1 ); + return nArea; +} +Gia_Man_t * Gia_ManSifPerform( Gia_Man_t * p, int nLutSize, int fEvalOnly, int fVerbose ) +{ + Gia_Man_t * pNew = NULL; + int nIters, Status, nSize = nLutSize+1; // (2+1+nSize)*4=40 bytes/node + abctime clk = Abc_Clock(); + Vec_Int_t * vCuts = Vec_IntStart( Gia_ManObjNum(p) * nSize ); + Vec_Int_t * vTimes = Vec_IntAlloc( Gia_ManObjNum(p) ); + int Lower = 0; + int Upper = Gia_ManSifMapComb( p, vCuts, vTimes, nLutSize ); + int CombD = Upper; + if ( fVerbose && Gia_ManRegNum(p) ) + printf( "Clock period %2d is %s\n", Lower, 0 ? "Yes" : "No " ); + if ( fVerbose && Gia_ManRegNum(p) ) + printf( "Clock period %2d is %s\n", Upper, 1 ? "Yes" : "No " ); + while ( Gia_ManRegNum(p) > 0 && Upper - Lower > 1 ) + { + int Middle = (Upper + Lower) / 2; + int Status = Gia_ManSifCheckPeriod( p, vCuts, vTimes, nLutSize, Middle, &nIters ); + if ( Status ) + Upper = Middle; + else + Lower = Middle; + if ( fVerbose ) + printf( "Clock period %2d is %s after %d iterations\n", Middle, Status ? "Yes" : "No ", nIters ); + } + if ( fVerbose ) + printf( "Best period = <<%d>> (%.2f %%) ", Upper, (float)(100.0*(CombD-Upper)/CombD) ); + if ( fVerbose ) + printf( "LUT size = %d ", nLutSize ); + if ( fVerbose ) + printf( "Memory usage = %.2f MB ", 4.0*(2+1+nSize)*Gia_ManObjNum(p)/(1 << 20) ); + if ( fVerbose ) + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + if ( Upper == CombD ) + { + Vec_IntFree( vCuts ); + Vec_IntFree( vTimes ); + printf( "Combinational delay (%d) cannot be improved.\n", CombD ); + return Gia_ManDup( p ); + } + Status = Gia_ManSifCheckPeriod( p, vCuts, vTimes, nLutSize, Upper, &nIters ); + assert( Status ); + Status = Gia_ManSifDeriveMapping( p, vCuts, vTimes, nLutSize, Upper, fVerbose ); + if ( fEvalOnly ) + { + printf( "Optimized level %2d (%6.2f %% less than comb level %2d). LUT size = %d. Area estimate = %d.\n", + Upper, (float)(100.0*(CombD-Upper)/CombD), CombD, nLutSize, Gia_ManSifArea(p, vCuts, nLutSize+1) ); + printf( "The command is invoked in the evaluation mode. Retiming is not performed.\n" ); + } + else + pNew = Gia_ManSifTransform( p, vCuts, vTimes, nLutSize, Upper, fVerbose ); + Vec_IntFree( vCuts ); + Vec_IntFree( vTimes ); + //Gia_ManTransferTiming( pNew, p ); + if ( p->vNamesIn ) { + char * pName; int i; + pNew->vNamesIn = p->vNamesIn; p->vNamesIn = NULL; + Vec_PtrForEachEntryStart( char *, pNew->vNamesIn, pName, i, Gia_ManPiNum(pNew) ) + ABC_FREE( pName ); + Vec_PtrShrink( pNew->vNamesIn, Gia_ManPiNum(pNew) ); + for ( i = 0; i < Gia_ManRegNum(pNew); i++ ) + Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsavNum("_fo", i) ); + } + if ( p->vNamesOut ) { + char * pName; int i; + pNew->vNamesOut = p->vNamesOut; p->vNamesOut = NULL; + Vec_PtrForEachEntryStart( char *, pNew->vNamesOut, pName, i, Gia_ManPoNum(pNew) ) + ABC_FREE( pName ); + Vec_PtrShrink( pNew->vNamesOut, Gia_ManPoNum(pNew) ); + for ( i = 0; i < Gia_ManRegNum(pNew); i++ ) + Vec_PtrPush( pNew->vNamesOut, Abc_UtilStrsavNum("_fi", i) ); + } + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaSim.c b/yosys/abc/src/aig/gia/giaSim.c new file mode 100644 index 00000000000..ecad182f76e --- /dev/null +++ b/yosys/abc/src/aig/gia/giaSim.c @@ -0,0 +1,1398 @@ +/**CFile**************************************************************** + + FileName [giaSim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Fast sequential simulator.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/util/utilTruth.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline unsigned * Gia_SimData( Gia_ManSim_t * p, int i ) { return p->pDataSim + i * p->nWords; } +static inline unsigned * Gia_SimDataCi( Gia_ManSim_t * p, int i ) { return p->pDataSimCis + i * p->nWords; } +static inline unsigned * Gia_SimDataCo( Gia_ManSim_t * p, int i ) { return p->pDataSimCos + i * p->nWords; } + +unsigned * Gia_SimDataExt( Gia_ManSim_t * p, int i ) { return Gia_SimData(p, i); } +unsigned * Gia_SimDataCiExt( Gia_ManSim_t * p, int i ) { return Gia_SimDataCi(p, i); } +unsigned * Gia_SimDataCoExt( Gia_ManSim_t * p, int i ) { return Gia_SimDataCo(p, i); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimCollect_rec( Gia_Man_t * pGia, Gia_Obj_t * pObj, Vec_Int_t * vVec ) +{ + Vec_IntPush( vVec, Gia_ObjToLit(pGia, pObj) ); + if ( Gia_IsComplement(pObj) || Gia_ObjIsCi(pObj) ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManSimCollect_rec( pGia, Gia_ObjChild0(pObj), vVec ); + Gia_ManSimCollect_rec( pGia, Gia_ObjChild1(pObj), vVec ); +} + +/**Function************************************************************* + + Synopsis [Derives signal implications.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimCollect( Gia_Man_t * pGia, Gia_Obj_t * pObj, Vec_Int_t * vVec ) +{ + Vec_IntClear( vVec ); + Gia_ManSimCollect_rec( pGia, pObj, vVec ); + Vec_IntUniqify( vVec ); +} + +/**Function************************************************************* + + Synopsis [Finds signals, which reset flops to have constant values.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManSimDeriveResets( Gia_Man_t * pGia ) +{ + int nImpLimit = 5; + Vec_Int_t * vResult; + Vec_Int_t * vCountLits, * vSuperGate; + Gia_Obj_t * pObj; + int i, k, Lit, Count; + int Counter0 = 0, Counter1 = 0; + int CounterPi0 = 0, CounterPi1 = 0; + abctime clk = Abc_Clock(); + + // create reset counters for each literal + vCountLits = Vec_IntStart( 2 * Gia_ManObjNum(pGia) ); + + // collect implications for each flop input driver + vSuperGate = Vec_IntAlloc( 1000 ); + Gia_ManForEachRi( pGia, pObj, i ) + { + if ( Gia_ObjFaninId0p(pGia, pObj) == 0 ) + continue; + Vec_IntAddToEntry( vCountLits, Gia_ObjToLit(pGia, Gia_ObjChild0(pObj)), 1 ); + Gia_ManSimCollect( pGia, Gia_ObjFanin0(pObj), vSuperGate ); + Vec_IntForEachEntry( vSuperGate, Lit, k ) + Vec_IntAddToEntry( vCountLits, Lit, 1 ); + } + Vec_IntFree( vSuperGate ); + + // label signals whose counter if more than the limit + vResult = Vec_IntStartFull( Gia_ManObjNum(pGia) ); + Vec_IntForEachEntry( vCountLits, Count, Lit ) + { + if ( Count < nImpLimit ) + continue; + pObj = Gia_ManObj( pGia, Abc_Lit2Var(Lit) ); + if ( Abc_LitIsCompl(Lit) ) // const 0 + { +// Ssm_ObjSetLogic0( pObj ); + Vec_IntWriteEntry( vResult, Abc_Lit2Var(Lit), 0 ); + CounterPi0 += Gia_ObjIsPi(pGia, pObj); + Counter0++; + } + else + { +// Ssm_ObjSetLogic1( pObj ); + Vec_IntWriteEntry( vResult, Abc_Lit2Var(Lit), 1 ); + CounterPi1 += Gia_ObjIsPi(pGia, pObj); + Counter1++; + } +// if ( Gia_ObjIsPi(pGia, pObj) ) +// printf( "%d ", Count ); + } +// printf( "\n" ); + Vec_IntFree( vCountLits ); + + printf( "Logic0 = %d (%d). Logic1 = %d (%d). ", Counter0, CounterPi0, Counter1, CounterPi1 ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return vResult; +} + + +/**Function************************************************************* + + Synopsis [This procedure sets default parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimSetDefaultParams( Gia_ParSim_t * p ) +{ + memset( p, 0, sizeof(Gia_ParSim_t) ); + // user-controlled parameters + p->nWords = 8; // the number of machine words + p->nIters = 32; // the number of timeframes + p->RandSeed = 0; // the seed to generate random numbers + p->TimeLimit = 60; // time limit in seconds + p->fCheckMiter = 0; // check if miter outputs are non-zero + p->fVerbose = 0; // enables verbose output + p->iOutFail = -1; // index of the failed output +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimDelete( Gia_ManSim_t * p ) +{ + Vec_IntFreeP( &p->vConsts ); + Vec_IntFreeP( &p->vCis2Ids ); + Gia_ManStopP( &p->pAig ); + ABC_FREE( p->pDataSim ); + ABC_FREE( p->pDataSimCis ); + ABC_FREE( p->pDataSimCos ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Creates fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_ManSim_t * Gia_ManSimCreate( Gia_Man_t * pAig, Gia_ParSim_t * pPars ) +{ + Gia_ManSim_t * p; + int Entry, i; + p = ABC_ALLOC( Gia_ManSim_t, 1 ); + memset( p, 0, sizeof(Gia_ManSim_t) ); + // look for reset signals + if ( pPars->fVerbose ) + p->vConsts = Gia_ManSimDeriveResets( pAig ); + // derive the frontier + p->pAig = Gia_ManFront( pAig ); + p->pPars = pPars; + p->nWords = pPars->nWords; + p->pDataSim = ABC_ALLOC( unsigned, p->nWords * p->pAig->nFront ); + p->pDataSimCis = ABC_ALLOC( unsigned, p->nWords * Gia_ManCiNum(p->pAig) ); + p->pDataSimCos = ABC_ALLOC( unsigned, p->nWords * Gia_ManCoNum(p->pAig) ); + if ( !p->pDataSim || !p->pDataSimCis || !p->pDataSimCos ) + { + Abc_Print( 1, "Simulator could not allocate %.2f GB for simulation info.\n", + 4.0 * p->nWords * (p->pAig->nFront + Gia_ManCiNum(p->pAig) + Gia_ManCoNum(p->pAig)) / (1<<30) ); + Gia_ManSimDelete( p ); + return NULL; + } + p->vCis2Ids = Vec_IntAlloc( Gia_ManCiNum(p->pAig) ); + Vec_IntForEachEntry( pAig->vCis, Entry, i ) + Vec_IntPush( p->vCis2Ids, i ); // do we need p->vCis2Ids? + if ( pPars->fVerbose ) + Abc_Print( 1, "AIG = %7.2f MB. Front mem = %7.2f MB. Other mem = %7.2f MB.\n", + 12.0*Gia_ManObjNum(p->pAig)/(1<<20), + 4.0*p->nWords*p->pAig->nFront/(1<<20), + 4.0*p->nWords*(Gia_ManCiNum(p->pAig) + Gia_ManCoNum(p->pAig))/(1<<20) ); + + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSimInfoRandom( Gia_ManSim_t * p, unsigned * pInfo ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = Gia_ManRandom( 0 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSimInfoZero( Gia_ManSim_t * p, unsigned * pInfo ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = 0; +} + +/**Function************************************************************* + + Synopsis [Returns index of the first pattern that failed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManSimInfoIsZero( Gia_ManSim_t * p, unsigned * pInfo ) +{ + int w; + for ( w = 0; w < p->nWords; w++ ) + if ( pInfo[w] ) + return 32*w + Gia_WordFindFirstBit( pInfo[w] ); + return -1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSimInfoOne( Gia_ManSim_t * p, unsigned * pInfo ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = ~0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSimInfoCopy( Gia_ManSim_t * p, unsigned * pInfo, unsigned * pInfo0 ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSimulateCi( Gia_ManSim_t * p, Gia_Obj_t * pObj, int iCi ) +{ + unsigned * pInfo = Gia_SimData( p, Gia_ObjValue(pObj) ); + unsigned * pInfo0 = Gia_SimDataCi( p, iCi ); + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSimulateCo( Gia_ManSim_t * p, int iCo, Gia_Obj_t * pObj ) +{ + unsigned * pInfo = Gia_SimDataCo( p, iCo ); + unsigned * pInfo0 = Gia_SimData( p, Gia_ObjDiff0(pObj) ); + int w; + if ( Gia_ObjFaninC0(pObj) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = ~pInfo0[w]; + else + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSimulateNode( Gia_ManSim_t * p, Gia_Obj_t * pObj ) +{ + unsigned * pInfo = Gia_SimData( p, Gia_ObjValue(pObj) ); + unsigned * pInfo0 = Gia_SimData( p, Gia_ObjDiff0(pObj) ); + unsigned * pInfo1 = Gia_SimData( p, Gia_ObjDiff1(pObj) ); + int w; + if ( Gia_ObjFaninC0(pObj) ) + { + if ( Gia_ObjFaninC1(pObj) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = ~(pInfo0[w] | pInfo1[w]); + else + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = ~pInfo0[w] & pInfo1[w]; + } + else + { + if ( Gia_ObjFaninC1(pObj) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w] & ~pInfo1[w]; + else + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w] & pInfo1[w]; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimInfoInit( Gia_ManSim_t * p ) +{ + int iPioNum, i; + Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) + { + if ( iPioNum < Gia_ManPiNum(p->pAig) ) + Gia_ManSimInfoRandom( p, Gia_SimDataCi(p, i) ); + else + Gia_ManSimInfoZero( p, Gia_SimDataCi(p, i) ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimInfoTransfer( Gia_ManSim_t * p ) +{ + int iPioNum, i; + Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) + { + if ( iPioNum < Gia_ManPiNum(p->pAig) ) + Gia_ManSimInfoRandom( p, Gia_SimDataCi(p, i) ); + else + Gia_ManSimInfoCopy( p, Gia_SimDataCi(p, i), Gia_SimDataCo(p, Gia_ManPoNum(p->pAig)+iPioNum-Gia_ManPiNum(p->pAig)) ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimulateRound( Gia_ManSim_t * p ) +{ + Gia_Obj_t * pObj; + int i, iCis = 0, iCos = 0; + assert( p->pAig->nFront > 0 ); + assert( Gia_ManConst0(p->pAig)->Value == 0 ); + Gia_ManSimInfoZero( p, Gia_SimData(p, 0) ); + Gia_ManForEachObj1( p->pAig, pObj, i ) + { + if ( Gia_ObjIsAndOrConst0(pObj) ) + { + assert( Gia_ObjValue(pObj) < p->pAig->nFront ); + Gia_ManSimulateNode( p, pObj ); + } + else if ( Gia_ObjIsCo(pObj) ) + { + assert( Gia_ObjValue(pObj) == GIA_NONE ); + Gia_ManSimulateCo( p, iCos++, pObj ); + } + else // if ( Gia_ObjIsCi(pObj) ) + { + assert( Gia_ObjValue(pObj) < p->pAig->nFront ); + Gia_ManSimulateCi( p, pObj, iCis++ ); + } + } + assert( Gia_ManCiNum(p->pAig) == iCis ); + assert( Gia_ManCoNum(p->pAig) == iCos ); +} + +/**Function************************************************************* + + Synopsis [Returns index of the PO and pattern that failed it.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManCheckPos( Gia_ManSim_t * p, int * piPo, int * piPat ) +{ + int i, iPat; + for ( i = 0; i < Gia_ManPoNum(p->pAig); i++ ) + { + iPat = Gia_ManSimInfoIsZero( p, Gia_SimDataCo(p, i) ); + if ( iPat >= 0 ) + { + *piPo = i; + *piPat = iPat; + return 1; + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Gia_ManGenerateCounter( Gia_Man_t * pAig, int iFrame, int iOut, int nWords, int iPat, Vec_Int_t * vCis2Ids ) +{ + Abc_Cex_t * p; + unsigned * pData; + int f, i, w, iPioId, Counter; + p = Abc_CexAlloc( Gia_ManRegNum(pAig), Gia_ManPiNum(pAig), iFrame+1 ); + p->iFrame = iFrame; + p->iPo = iOut; + // fill in the binary data + Counter = p->nRegs; + pData = ABC_ALLOC( unsigned, nWords ); + for ( f = 0; f <= iFrame; f++, Counter += p->nPis ) + for ( i = 0; i < Gia_ManPiNum(pAig); i++ ) + { + iPioId = Vec_IntEntry( vCis2Ids, i ); + if ( iPioId >= p->nPis ) + continue; + for ( w = nWords-1; w >= 0; w-- ) + pData[w] = Gia_ManRandom( 0 ); + if ( Abc_InfoHasBit( pData, iPat ) ) + Abc_InfoSetBit( p->pData, Counter + iPioId ); + } + ABC_FREE( pData ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManResetRandom( Gia_ParSim_t * pPars ) +{ + int i; + Gia_ManRandom( 1 ); + for ( i = 0; i < pPars->RandSeed; i++ ) + Gia_ManRandom( 0 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSimSimulate( Gia_Man_t * pAig, Gia_ParSim_t * pPars ) +{ + extern int Gia_ManSimSimulateEquiv( Gia_Man_t * pAig, Gia_ParSim_t * pPars ); + Gia_ManSim_t * p; + abctime clkTotal = Abc_Clock(); + int i, iOut, iPat, RetValue = 0; + abctime nTimeToStop = pPars->TimeLimit ? pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0; + if ( pAig->pReprs && pAig->pNexts ) + return Gia_ManSimSimulateEquiv( pAig, pPars ); + ABC_FREE( pAig->pCexSeq ); + p = Gia_ManSimCreate( pAig, pPars ); + Gia_ManResetRandom( pPars ); + Gia_ManSimInfoInit( p ); + for ( i = 0; i < pPars->nIters; i++ ) + { + Gia_ManSimulateRound( p ); + if ( pPars->fVerbose ) + { + Abc_Print( 1, "Frame %4d out of %4d and timeout %3d sec. ", i+1, pPars->nIters, pPars->TimeLimit ); + Abc_Print( 1, "Time = %7.2f sec\r", (1.0*Abc_Clock()-clkTotal)/CLOCKS_PER_SEC ); + } + if ( pPars->fCheckMiter && Gia_ManCheckPos( p, &iOut, &iPat ) ) + { + Gia_ManResetRandom( pPars ); + pPars->iOutFail = iOut; + pAig->pCexSeq = Gia_ManGenerateCounter( pAig, i, iOut, p->nWords, iPat, p->vCis2Ids ); + Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", iOut, pAig->pName, i ); + if ( !Gia_ManVerifyCex( pAig, pAig->pCexSeq, 0 ) ) + { +// Abc_Print( 1, "\n" ); + Abc_Print( 1, "\nGenerated counter-example is INVALID. " ); +// Abc_Print( 1, "\n" ); + } + else + { +// Abc_Print( 1, "\n" ); +// if ( pPars->fVerbose ) +// Abc_Print( 1, "\nGenerated counter-example is verified correctly. " ); +// Abc_Print( 1, "\n" ); + } + RetValue = 1; + break; + } + if ( Abc_Clock() > nTimeToStop ) + { + i++; + break; + } + if ( i < pPars->nIters - 1 ) + Gia_ManSimInfoTransfer( p ); + } + Gia_ManSimDelete( p ); + if ( pAig->pCexSeq == NULL ) + Abc_Print( 1, "No bug detected after simulating %d frames with %d words. ", i, pPars->nWords ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManSimReadFile( char * pFileIn ) +{ + int c; + Vec_Int_t * vPat; + FILE * pFile = fopen( pFileIn, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open input file.\n" ); + return NULL; + } + vPat = Vec_IntAlloc( 1000 ); + while ( (c = fgetc(pFile)) != EOF ) + if ( c == '0' || c == '1' ) + Vec_IntPush( vPat, c - '0' ); + fclose( pFile ); + return vPat; +} +int Gia_ManSimWriteFile( char * pFileOut, Vec_Int_t * vPat, int nOuts ) +{ + int c, i; + FILE * pFile = fopen( pFileOut, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open output file.\n" ); + return 0; + } + assert( Vec_IntSize(vPat) % nOuts == 0 ); + Vec_IntForEachEntry( vPat, c, i ) + { + fputc( '0' + c, pFile ); + if ( i % nOuts == nOuts - 1 ) + fputc( '\n', pFile ); + } + fclose( pFile ); + return 1; +} +Vec_Int_t * Gia_ManSimSimulateOne( Gia_Man_t * p, Vec_Int_t * vPat ) +{ + Vec_Int_t * vPatOut; + Gia_Obj_t * pObj, * pObjRo; + int i, k, f; + assert( Vec_IntSize(vPat) % Gia_ManPiNum(p) == 0 ); + Gia_ManConst0(p)->fMark1 = 0; + Gia_ManForEachRo( p, pObj, i ) + pObj->fMark1 = 0; + vPatOut = Vec_IntAlloc( 1000 ); + for ( k = f = 0; f < Vec_IntSize(vPat) / Gia_ManPiNum(p); f++ ) + { + Gia_ManForEachPi( p, pObj, i ) + pObj->fMark1 = Vec_IntEntry( vPat, k++ ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark1 ^ Gia_ObjFaninC1(pObj)); + Gia_ManForEachCo( p, pObj, i ) + pObj->fMark1 = (Gia_ObjFanin0(pObj)->fMark1 ^ Gia_ObjFaninC0(pObj)); + Gia_ManForEachPo( p, pObj, i ) + Vec_IntPush( vPatOut, pObj->fMark1 ); + Gia_ManForEachRiRo( p, pObj, pObjRo, i ) + pObjRo->fMark1 = pObj->fMark1; + } + assert( k == Vec_IntSize(vPat) ); + Gia_ManForEachObj( p, pObj, i ) + pObj->fMark1 = 0; + return vPatOut; +} +void Gia_ManSimSimulatePattern( Gia_Man_t * p, char * pFileIn, char * pFileOut ) +{ + Vec_Int_t * vPat, * vPatOut; + vPat = Gia_ManSimReadFile( pFileIn ); + if ( vPat == NULL ) + return; + if ( Vec_IntSize(vPat) % Gia_ManPiNum(p) ) + { + printf( "The number of 0s and 1s in the input file (%d) does not evenly divide by the number of primary inputs (%d).\n", + Vec_IntSize(vPat), Gia_ManPiNum(p) ); + Vec_IntFree( vPat ); + return; + } + vPatOut = Gia_ManSimSimulateOne( p, vPat ); + if ( Gia_ManSimWriteFile( pFileOut, vPatOut, Gia_ManPoNum(p) ) ) + printf( "Output patterns are written into file \"%s\".\n", pFileOut ); + Vec_IntFree( vPat ); + Vec_IntFree( vPatOut ); +} + + +/**Function************************************************************* + + Synopsis [Bit-parallel simulation during AIG construction.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline word * Gia_ManBuiltInDataPi( Gia_Man_t * p, int iCiId ) +{ + return Vec_WrdEntryP( p->vSimsPi, p->nSimWords * iCiId ); +} +static inline word * Gia_ManBuiltInData( Gia_Man_t * p, int iObj ) +{ + return Vec_WrdEntryP( p->vSims, p->nSimWords * iObj ); +} +static inline void Gia_ManBuiltInDataPrint( Gia_Man_t * p, int iObj ) +{ +// printf( "Obj %6d : ", iObj ); Extra_PrintBinary( stdout, Gia_ManBuiltInData(p, iObj), p->nSimWords * 64 ); printf( "\n" ); +} +void Gia_ManBuiltInSimStart( Gia_Man_t * p, int nWords, int nObjs ) +{ + int i, k; + assert( !p->fBuiltInSim ); + assert( Gia_ManAndNum(p) == 0 ); + p->fBuiltInSim = 1; + p->iPatsPi = 0; + p->iPastPiMax = 0; + p->nSimWords = nWords; + p->nSimWordsMax = 8; + Gia_ManRandomW( 1 ); + // init PI care info + p->vSimsPi = Vec_WrdAlloc( p->nSimWords * Gia_ManCiNum(p) ); + Vec_WrdFill( p->vSimsPi, p->nSimWords * Gia_ManCiNum(p), 0 ); + // init object sim info + p->vSims = Vec_WrdAlloc( p->nSimWords * nObjs ); + Vec_WrdFill( p->vSims, p->nSimWords, 0 ); + for ( i = 0; i < Gia_ManCiNum(p); i++ ) + for ( k = 0; k < p->nSimWords; k++ ) + Vec_WrdPush( p->vSims, Gia_ManRandomW(0) ); +} +void Gia_ManBuiltInSimPerformInt( Gia_Man_t * p, int iObj ) +{ + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); int w; + word * pInfo = Gia_ManBuiltInData( p, iObj ); + word * pInfo0 = Gia_ManBuiltInData( p, Gia_ObjFaninId0(pObj, iObj) ); + word * pInfo1 = Gia_ManBuiltInData( p, Gia_ObjFaninId1(pObj, iObj) ); + assert( p->fBuiltInSim || p->fIncrSim ); + if ( Gia_ObjFaninC0(pObj) ) + { + if ( Gia_ObjFaninC1(pObj) ) + for ( w = 0; w < p->nSimWords; w++ ) + pInfo[w] = ~(pInfo0[w] | pInfo1[w]); + else + for ( w = 0; w < p->nSimWords; w++ ) + pInfo[w] = ~pInfo0[w] & pInfo1[w]; + } + else + { + if ( Gia_ObjFaninC1(pObj) ) + for ( w = 0; w < p->nSimWords; w++ ) + pInfo[w] = pInfo0[w] & ~pInfo1[w]; + else + for ( w = 0; w < p->nSimWords; w++ ) + pInfo[w] = pInfo0[w] & pInfo1[w]; + } + assert( Vec_WrdSize(p->vSims) == Gia_ManObjNum(p) * p->nSimWords ); +} +void Gia_ManBuiltInSimPerform( Gia_Man_t * p, int iObj ) +{ + int w; + for ( w = 0; w < p->nSimWords; w++ ) + Vec_WrdPush( p->vSims, 0 ); + Gia_ManBuiltInSimPerformInt( p, iObj ); +} + +void Gia_ManBuiltInSimResimulateCone_rec( Gia_Man_t * p, int iObj ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return; + Gia_ObjSetTravIdCurrentId(p, iObj); + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManBuiltInSimResimulateCone_rec( p, Gia_ObjFaninId0(pObj, iObj) ); + Gia_ManBuiltInSimResimulateCone_rec( p, Gia_ObjFaninId1(pObj, iObj) ); + Gia_ManBuiltInSimPerformInt( p, iObj ); +} +void Gia_ManBuiltInSimResimulateCone( Gia_Man_t * p, int iLit0, int iLit1 ) +{ + Gia_ManIncrementTravId( p ); + Gia_ManBuiltInSimResimulateCone_rec( p, Abc_Lit2Var(iLit0) ); + Gia_ManBuiltInSimResimulateCone_rec( p, Abc_Lit2Var(iLit1) ); +} +void Gia_ManBuiltInSimResimulate( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; int iObj; + Gia_ManForEachAnd( p, pObj, iObj ) + Gia_ManBuiltInSimPerformInt( p, iObj ); +} + +int Gia_ManBuiltInSimCheckOver( Gia_Man_t * p, int iLit0, int iLit1 ) +{ + word * pInfo0 = Gia_ManBuiltInData( p, Abc_Lit2Var(iLit0) ); + word * pInfo1 = Gia_ManBuiltInData( p, Abc_Lit2Var(iLit1) ); int w; + assert( p->fBuiltInSim || p->fIncrSim ); + +// printf( "%d %d\n", Abc_LitIsCompl(iLit0), Abc_LitIsCompl(iLit1) ); +// Extra_PrintBinary( stdout, pInfo0, 64*p->nSimWords ); printf( "\n" ); +// Extra_PrintBinary( stdout, pInfo1, 64*p->nSimWords ); printf( "\n" ); +// printf( "\n" ); + + if ( Abc_LitIsCompl(iLit0) ) + { + if ( Abc_LitIsCompl(iLit1) ) + { + for ( w = 0; w < p->nSimWords; w++ ) + if ( ~pInfo0[w] & ~pInfo1[w] ) + return 1; + } + else + { + for ( w = 0; w < p->nSimWords; w++ ) + if ( ~pInfo0[w] & pInfo1[w] ) + return 1; + } + } + else + { + if ( Abc_LitIsCompl(iLit1) ) + { + for ( w = 0; w < p->nSimWords; w++ ) + if ( pInfo0[w] & ~pInfo1[w] ) + return 1; + } + else + { + for ( w = 0; w < p->nSimWords; w++ ) + if ( pInfo0[w] & pInfo1[w] ) + return 1; + } + } + return 0; +} +int Gia_ManBuiltInSimCheckEqual( Gia_Man_t * p, int iLit0, int iLit1 ) +{ + word * pInfo0 = Gia_ManBuiltInData( p, Abc_Lit2Var(iLit0) ); + word * pInfo1 = Gia_ManBuiltInData( p, Abc_Lit2Var(iLit1) ); int w; + assert( p->fBuiltInSim || p->fIncrSim ); + +// printf( "%d %d\n", Abc_LitIsCompl(iLit0), Abc_LitIsCompl(iLit1) ); +// Extra_PrintBinary( stdout, pInfo0, 64*p->nSimWords ); printf( "\n" ); +// Extra_PrintBinary( stdout, pInfo1, 64*p->nSimWords ); printf( "\n" ); +// printf( "\n" ); + + if ( Abc_LitIsCompl(iLit0) ) + { + if ( Abc_LitIsCompl(iLit1) ) + { + for ( w = 0; w < p->nSimWords; w++ ) + if ( ~pInfo0[w] != ~pInfo1[w] ) + return 0; + } + else + { + for ( w = 0; w < p->nSimWords; w++ ) + if ( ~pInfo0[w] != pInfo1[w] ) + return 0; + } + } + else + { + if ( Abc_LitIsCompl(iLit1) ) + { + for ( w = 0; w < p->nSimWords; w++ ) + if ( pInfo0[w] != ~pInfo1[w] ) + return 0; + } + else + { + for ( w = 0; w < p->nSimWords; w++ ) + if ( pInfo0[w] != pInfo1[w] ) + return 0; + } + } + return 1; +} + +int Gia_ManBuiltInSimPack( Gia_Man_t * p, Vec_Int_t * vPat ) +{ + int i, k, iLit; + assert( Vec_IntSize(vPat) > 0 ); + //printf( "%d ", Vec_IntSize(vPat) ); + for ( i = 0; i < p->iPatsPi; i++ ) + { + Vec_IntForEachEntry( vPat, iLit, k ) + if ( Abc_TtGetBit(Gia_ManBuiltInDataPi(p, Abc_Lit2Var(iLit)), i) && + Abc_TtGetBit(Gia_ManBuiltInData(p, 1+Abc_Lit2Var(iLit)), i) == Abc_LitIsCompl(iLit) ) + break; + if ( k == Vec_IntSize(vPat) ) + return i; // success + } + return -1; // failure +} +// adds PI pattern to storage; the pattern comes in terms of CiIds +int Gia_ManBuiltInSimAddPat( Gia_Man_t * p, Vec_Int_t * vPat ) +{ + int Period = 0xF; + int fOverflow = p->iPatsPi == 64 * p->nSimWords && p->nSimWords == p->nSimWordsMax; + int k, iLit, iPat = Gia_ManBuiltInSimPack( p, vPat ); + if ( iPat == -1 ) + { + if ( fOverflow ) + { + if ( (p->iPastPiMax & Period) == 0 ) + Gia_ManBuiltInSimResimulate( p ); + iPat = p->iPastPiMax; + //if ( p->iPastPiMax == 64 * p->nSimWordsMax - 1 ) + // printf( "Completed the cycle.\n" ); + p->iPastPiMax = p->iPastPiMax == 64 * p->nSimWordsMax - 1 ? 0 : p->iPastPiMax + 1; + } + else + { + if ( p->iPatsPi && (p->iPatsPi & Period) == 0 ) + Gia_ManBuiltInSimResimulate( p ); + if ( p->iPatsPi == 64 * p->nSimWords ) + { + Vec_Wrd_t * vTemp = Vec_WrdAlloc( 2 * Vec_WrdSize(p->vSims) ); + word Data; int w, Count = 0, iObj = 0; + Vec_WrdForEachEntry( p->vSims, Data, w ) + { + Vec_WrdPush( vTemp, Data ); + if ( ++Count == p->nSimWords ) + { + Gia_Obj_t * pObj = Gia_ManObj(p, iObj++); + if ( Gia_ObjIsCi(pObj) ) + Vec_WrdPush( vTemp, Gia_ManRandomW(0) ); // Vec_WrdPush( vTemp, 0 ); + else if ( Gia_ObjIsAnd(pObj) ) + Vec_WrdPush( vTemp, pObj->fPhase ? ~(word)0 : 0 ); + else + Vec_WrdPush( vTemp, 0 ); + Count = 0; + } + } + assert( iObj == Gia_ManObjNum(p) ); + Vec_WrdFree( p->vSims ); + p->vSims = vTemp; + + vTemp = Vec_WrdAlloc( 2 * Vec_WrdSize(p->vSimsPi) ); + Count = 0; + Vec_WrdForEachEntry( p->vSimsPi, Data, w ) + { + Vec_WrdPush( vTemp, Data ); + if ( ++Count == p->nSimWords ) + { + Vec_WrdPush( vTemp, 0 ); + Count = 0; + } + } + Vec_WrdFree( p->vSimsPi ); + p->vSimsPi = vTemp; + + // update the word count + p->nSimWords++; + assert( Vec_WrdSize(p->vSims) == p->nSimWords * Gia_ManObjNum(p) ); + assert( Vec_WrdSize(p->vSimsPi) == p->nSimWords * Gia_ManCiNum(p) ); + //printf( "Resizing to %d words.\n", p->nSimWords ); + } + iPat = p->iPatsPi++; + } + } + assert( iPat >= 0 && iPat < p->iPatsPi ); + // add literals + if ( fOverflow ) + { + int iVar; + Vec_IntForEachEntry( &p->vSuppVars, iVar, k ) + if ( Abc_TtGetBit(Gia_ManBuiltInDataPi(p, iVar), iPat) ) + Abc_TtXorBit(Gia_ManBuiltInDataPi(p, iVar), iPat); + Vec_IntForEachEntry( vPat, iLit, k ) + { + if ( Abc_TtGetBit(Gia_ManBuiltInData(p, 1+Abc_Lit2Var(iLit)), iPat) == Abc_LitIsCompl(iLit) ) + Abc_TtXorBit(Gia_ManBuiltInData(p, 1+Abc_Lit2Var(iLit)), iPat); + Abc_TtXorBit(Gia_ManBuiltInDataPi(p, Abc_Lit2Var(iLit)), iPat); + } + } + else + { + Vec_IntForEachEntry( vPat, iLit, k ) + { + if ( Abc_TtGetBit(Gia_ManBuiltInDataPi(p, Abc_Lit2Var(iLit)), iPat) ) + assert( Abc_TtGetBit(Gia_ManBuiltInData(p, 1+Abc_Lit2Var(iLit)), iPat) != Abc_LitIsCompl(iLit) ); + else + { + if ( Abc_TtGetBit(Gia_ManBuiltInData(p, 1+Abc_Lit2Var(iLit)), iPat) == Abc_LitIsCompl(iLit) ) + Abc_TtXorBit(Gia_ManBuiltInData(p, 1+Abc_Lit2Var(iLit)), iPat); + Abc_TtXorBit(Gia_ManBuiltInDataPi(p, Abc_Lit2Var(iLit)), iPat); + } + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Finds a satisfying assignment.] + + Description [Returns 1 if a sat assignment is found; 0 otherwise.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManObjCheckSat_rec( Gia_Man_t * p, int iLit, Vec_Int_t * vObjs ) +{ + int iObj = Abc_Lit2Var(iLit); + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + if ( pObj->fMark0 ) + return pObj->fMark1 == (unsigned)Abc_LitIsCompl(iLit); + pObj->fMark0 = 1; + pObj->fMark1 = Abc_LitIsCompl(iLit); + Vec_IntPush( vObjs, iObj ); + if ( Gia_ObjIsAnd(pObj) ) + { + if ( pObj->fMark1 == 0 ) // node value is 1 + { + if ( !Gia_ManObjCheckSat_rec( p, Gia_ObjFaninLit0(pObj, iObj), vObjs ) ) return 0; + if ( !Gia_ManObjCheckSat_rec( p, Gia_ObjFaninLit1(pObj, iObj), vObjs ) ) return 0; + } + else + { + if ( !Gia_ManObjCheckSat_rec( p, Abc_LitNot(Gia_ObjFaninLit0(pObj, iObj)), vObjs ) ) return 0; + } + } + return 1; +} +int Gia_ManObjCheckOverlap1( Gia_Man_t * p, int iLit0, int iLit1, Vec_Int_t * vObjs ) +{ + Gia_Obj_t * pObj; + int i, Res0, Res1 = 0; +// Gia_ManForEachObj( p, pObj, i ) +// assert( pObj->fMark0 == 0 && pObj->fMark1 == 0 ); + Vec_IntClear( vObjs ); + Res0 = Gia_ManObjCheckSat_rec( p, iLit0, vObjs ); + if ( Res0 ) + Res1 = Gia_ManObjCheckSat_rec( p, iLit1, vObjs ); + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + pObj->fMark0 = pObj->fMark1 = 0; + return Res0 && Res1; +} +int Gia_ManObjCheckOverlap( Gia_Man_t * p, int iLit0, int iLit1, Vec_Int_t * vObjs ) +{ + if ( Gia_ManObjCheckOverlap1( p, iLit0, iLit1, vObjs ) ) + return 1; + return Gia_ManObjCheckOverlap1( p, iLit1, iLit0, vObjs ); +} + + + + + +/**Function************************************************************* + + Synopsis [Bit-parallel simulation during AIG construction.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManIncrSimUpdate( Gia_Man_t * p ) +{ + int i, k; + // extend timestamp info + assert( Vec_IntSize(p->vTimeStamps) <= Gia_ManObjNum(p) ); + Vec_IntFillExtra( p->vTimeStamps, Gia_ManObjNum(p), 0 ); + // extend simulation info + assert( Vec_WrdSize(p->vSims) <= Gia_ManObjNum(p) * p->nSimWords ); + Vec_WrdFillExtra( p->vSims, Gia_ManObjNum(p) * p->nSimWords, 0 ); + // extend PI info + assert( p->iNextPi <= Gia_ManCiNum(p) ); + for ( i = p->iNextPi; i < Gia_ManCiNum(p); i++ ) + { + word * pSims = Gia_ManBuiltInData( p, Gia_ManCiIdToId(p, i) ); + for ( k = 0; k < p->nSimWords; k++ ) + pSims[k] = Gia_ManRandomW(0); + } + p->iNextPi = Gia_ManCiNum(p); +} +void Gia_ManIncrSimStart( Gia_Man_t * p, int nWords, int nObjs ) +{ + assert( !p->fIncrSim ); + p->fIncrSim = 1; + p->iPatsPi = 0; + p->nSimWords = nWords; + // init time stamps + p->iTimeStamp = 1; + p->vTimeStamps = Vec_IntAlloc( p->nSimWords ); + // init object sim info + p->iNextPi = 0; + p->vSims = Vec_WrdAlloc( p->nSimWords * nObjs ); + Gia_ManRandomW( 1 ); +} +void Gia_ManIncrSimStop( Gia_Man_t * p ) +{ + assert( p->fIncrSim ); + p->fIncrSim = 0; + p->iPatsPi = 0; + p->nSimWords = 0; + p->iTimeStamp = 1; + Vec_IntFreeP( &p->vTimeStamps ); + Vec_WrdFreeP( &p->vSims ); +} +void Gia_ManIncrSimSet( Gia_Man_t * p, Vec_Int_t * vObjLits ) +{ + int i, iLit; + assert( Vec_IntSize(vObjLits) > 0 ); + p->iTimeStamp++; + Vec_IntForEachEntry( vObjLits, iLit, i ) + { + word * pSims = Gia_ManBuiltInData( p, Abc_Lit2Var(iLit) ); + if ( Gia_ObjIsAnd(Gia_ManObj(p, Abc_Lit2Var(iLit))) ) + continue; + //assert( Vec_IntEntry(p->vTimeStamps, Abc_Lit2Var(iLit)) == p->iTimeStamp-1 ); + Vec_IntWriteEntry(p->vTimeStamps, Abc_Lit2Var(iLit), p->iTimeStamp); + if ( Abc_TtGetBit(pSims, p->iPatsPi) == Abc_LitIsCompl(iLit) ) + Abc_TtXorBit(pSims, p->iPatsPi); + } + p->iPatsPi = (p->iPatsPi == p->nSimWords * 64 - 1) ? 0 : p->iPatsPi + 1; +} +void Gia_ManIncrSimCone_rec( Gia_Man_t * p, int iObj ) +{ + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + return; + if ( Vec_IntEntry(p->vTimeStamps, iObj) == p->iTimeStamp ) + return; + assert( Vec_IntEntry(p->vTimeStamps, iObj) < p->iTimeStamp ); + Vec_IntWriteEntry( p->vTimeStamps, iObj, p->iTimeStamp ); + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManIncrSimCone_rec( p, Gia_ObjFaninId0(pObj, iObj) ); + Gia_ManIncrSimCone_rec( p, Gia_ObjFaninId1(pObj, iObj) ); + Gia_ManBuiltInSimPerformInt( p, iObj ); +} +int Gia_ManIncrSimCheckOver( Gia_Man_t * p, int iLit0, int iLit1 ) +{ + assert( iLit0 > 1 && iLit1 > 1 ); + Gia_ManIncrSimUpdate( p ); + Gia_ManIncrSimCone_rec( p, Abc_Lit2Var(iLit0) ); + Gia_ManIncrSimCone_rec( p, Abc_Lit2Var(iLit1) ); +// return 0; // disable + return Gia_ManBuiltInSimCheckOver( p, iLit0, iLit1 ); +} +int Gia_ManIncrSimCheckEqual( Gia_Man_t * p, int iLit0, int iLit1 ) +{ + assert( iLit0 > 1 && iLit1 > 1 ); + Gia_ManIncrSimUpdate( p ); + Gia_ManIncrSimCone_rec( p, Abc_Lit2Var(iLit0) ); + Gia_ManIncrSimCone_rec( p, Abc_Lit2Var(iLit1) ); +// return 1; // disable + return Gia_ManBuiltInSimCheckEqual( p, iLit0, iLit1 ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimOneBit( Gia_Man_t * p, Vec_Int_t * vValues ) +{ + Gia_Obj_t * pObj; int k; + assert( Vec_IntSize(vValues) == Gia_ManCiNum(p) ); + + Gia_ManConst0(p)->fMark0 = 0; + Gia_ManForEachCi( p, pObj, k ) + pObj->fMark0 = Vec_IntEntry(vValues, k); + Gia_ManForEachAnd( p, pObj, k ) + pObj->fMark0 = (Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj)) & (Gia_ObjFanin1(pObj)->fMark0 ^ Gia_ObjFaninC1(pObj)); + Gia_ManForEachCo( p, pObj, k ) + pObj->fMark0 = Gia_ObjFanin0(pObj)->fMark0 ^ Gia_ObjFaninC0(pObj); + + Gia_ManForEachCi( p, pObj, k ) + printf( "%d", k % 10 ); + printf( "\n" ); + Gia_ManForEachCi( p, pObj, k ) + printf( "%d", Vec_IntEntry(vValues, k) ); + printf( "\n" ); + + Gia_ManForEachCo( p, pObj, k ) + printf( "%d", k % 10 ); + printf( "\n" ); + Gia_ManForEachCo( p, pObj, k ) + printf( "%d", pObj->fMark0 ); + printf( "\n" ); + printf( "\n" ); +} +void Gia_ManSimOneBitTest2( Gia_Man_t * p ) +{ + Vec_Int_t * vValues = Vec_IntStart( Gia_ManCiNum(p) ); + + Vec_IntWriteEntry( vValues, 0, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, 0, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, 0, 1 ); + Vec_IntWriteEntry( vValues, 1, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2+2, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, 0, 1 ); + Vec_IntWriteEntry( vValues, 1, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntFill( vValues, Vec_IntSize(vValues)/2, 1 ); + Vec_IntFillExtra( vValues, Gia_ManCiNum(p), 0 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Gia_ManCiNum(p), 0 ); + + Vec_IntFill( vValues, Gia_ManCiNum(p), 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Gia_ManCiNum(p), 0 ); + + Vec_IntFill( vValues, Gia_ManCiNum(p), 1 ); + Vec_IntWriteEntry( vValues, 127, 1 ); + Vec_IntWriteEntry( vValues, 255, 0 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Gia_ManCiNum(p), 0 ); + + Vec_IntFill( vValues, Gia_ManCiNum(p), 1 ); + Vec_IntWriteEntry( vValues, 127, 0 ); + Vec_IntWriteEntry( vValues, 255, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Gia_ManCiNum(p), 0 ); + + Vec_IntFill( vValues, Gia_ManCiNum(p), 1 ); + Vec_IntWriteEntry( vValues, 127, 0 ); + Vec_IntWriteEntry( vValues, 255, 0 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Gia_ManCiNum(p), 0 ); + + Vec_IntFree( vValues ); +} +void Gia_ManSimOneBitTest3( Gia_Man_t * p ) +{ + Vec_Int_t * vValues = Vec_IntStart( Gia_ManCiNum(p) ); + + Vec_IntWriteEntry( vValues, 0, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, 0, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, 0, 1 ); + Vec_IntWriteEntry( vValues, 1, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2+2, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-1, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -1, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-1, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-2, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -1, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -2, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-2, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -2, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-1, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-2, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-3, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -1, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -2, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -3, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-2, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p)/2-3, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -2, 1 ); + Vec_IntWriteEntry( vValues, Gia_ManCiNum(p) -3, 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntFill( vValues, Vec_IntSize(vValues), 1 ); + Gia_ManSimOneBit( p, vValues ); + Vec_IntFill( vValues, Vec_IntSize(vValues), 0 ); + + Vec_IntFree( vValues ); +} + + +void Gia_ManSimOneBitTest( Gia_Man_t * p ) +{ + Vec_Int_t * vValues = Vec_IntStart( Gia_ManCiNum(p) ); + int i, k; + for ( i = 0; i < 10; i++ ) + { + for ( k = 0; k < Vec_IntSize(vValues); k++ ) + Vec_IntWriteEntry( vValues, k, Vec_IntEntry(vValues, k) ^ (rand()&1) ); + + printf( "Values = %d ", Vec_IntSum(vValues) ); + Gia_ManSimOneBit( p, vValues ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaSim2.c b/yosys/abc/src/aig/gia/giaSim2.c new file mode 100644 index 00000000000..349f8732bf1 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaSim2.c @@ -0,0 +1,706 @@ +/**CFile**************************************************************** + + FileName [giaSim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Fast sequential simulator.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Gia_Sim2_t_ Gia_Sim2_t; +struct Gia_Sim2_t_ +{ + Gia_Man_t * pAig; + Gia_ParSim_t * pPars; + int nWords; + unsigned * pDataSim; + Vec_Int_t * vClassOld; + Vec_Int_t * vClassNew; +}; + +static inline unsigned * Gia_Sim2Data( Gia_Sim2_t * p, int i ) { return p->pDataSim + i * p->nWords; } + +extern void Gia_ManResetRandom( Gia_ParSim_t * pPars ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_Sim2Delete( Gia_Sim2_t * p ) +{ + Vec_IntFreeP( &p->vClassOld ); + Vec_IntFreeP( &p->vClassNew ); + ABC_FREE( p->pDataSim ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Creates fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Sim2_t * Gia_Sim2Create( Gia_Man_t * pAig, Gia_ParSim_t * pPars ) +{ + Gia_Sim2_t * p; + Gia_Obj_t * pObj; + int i; + p = ABC_CALLOC( Gia_Sim2_t, 1 ); + p->pAig = pAig; + p->pPars = pPars; + p->nWords = pPars->nWords; + p->pDataSim = ABC_ALLOC( unsigned, p->nWords * Gia_ManObjNum(p->pAig) ); + if ( !p->pDataSim ) + { + Abc_Print( 1, "Simulator could not allocate %.2f GB for simulation info.\n", + 4.0 * p->nWords * Gia_ManObjNum(p->pAig) / (1<<30) ); + Gia_Sim2Delete( p ); + return NULL; + } + p->vClassOld = Vec_IntAlloc( 100 ); + p->vClassNew = Vec_IntAlloc( 100 ); + if ( pPars->fVerbose ) + Abc_Print( 1, "Memory: AIG = %7.2f MB. SimInfo = %7.2f MB.\n", + 12.0*Gia_ManObjNum(p->pAig)/(1<<20), 4.0*p->nWords*Gia_ManObjNum(p->pAig)/(1<<20) ); + // prepare AIG + Gia_ManSetPhase( pAig ); + Gia_ManForEachObj( pAig, pObj, i ) + pObj->Value = i; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_Sim2InfoRandom( Gia_Sim2_t * p, unsigned * pInfo ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = Gia_ManRandom( 0 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_Sim2InfoZero( Gia_Sim2_t * p, unsigned * pInfo ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_Sim2InfoOne( Gia_Sim2_t * p, unsigned * pInfo ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = ~0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_Sim2InfoCopy( Gia_Sim2_t * p, unsigned * pInfo, unsigned * pInfo0 ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_Sim2SimulateCo( Gia_Sim2_t * p, Gia_Obj_t * pObj ) +{ + unsigned * pInfo = Gia_Sim2Data( p, Gia_ObjValue(pObj) ); + unsigned * pInfo0 = Gia_Sim2Data( p, Gia_ObjFaninId0(pObj, Gia_ObjValue(pObj)) ); + int w; + if ( Gia_ObjFaninC0(pObj) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = ~pInfo0[w]; + else + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_Sim2SimulateNode( Gia_Sim2_t * p, Gia_Obj_t * pObj ) +{ + unsigned * pInfo = Gia_Sim2Data( p, Gia_ObjValue(pObj) ); + unsigned * pInfo0 = Gia_Sim2Data( p, Gia_ObjFaninId0(pObj, Gia_ObjValue(pObj)) ); + unsigned * pInfo1 = Gia_Sim2Data( p, Gia_ObjFaninId1(pObj, Gia_ObjValue(pObj)) ); + int w; + if ( Gia_ObjFaninC0(pObj) ) + { + if ( Gia_ObjFaninC1(pObj) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = ~(pInfo0[w] | pInfo1[w]); + else + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = ~pInfo0[w] & pInfo1[w]; + } + else + { + if ( Gia_ObjFaninC1(pObj) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w] & ~pInfo1[w]; + else + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w] & pInfo1[w]; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_Sim2InfoTransfer( Gia_Sim2_t * p ) +{ + Gia_Obj_t * pObjRo, * pObjRi; + unsigned * pInfo0, * pInfo1; + int i; + Gia_ManForEachRiRo( p->pAig, pObjRi, pObjRo, i ) + { + pInfo0 = Gia_Sim2Data( p, Gia_ObjValue(pObjRo) ); + pInfo1 = Gia_Sim2Data( p, Gia_ObjValue(pObjRi) ); + Gia_Sim2InfoCopy( p, pInfo0, pInfo1 ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_Sim2SimulateRound( Gia_Sim2_t * p ) +{ + Gia_Obj_t * pObj; + int i; + pObj = Gia_ManConst0(p->pAig); + assert( Gia_ObjValue(pObj) == 0 ); + Gia_Sim2InfoZero( p, Gia_Sim2Data(p, Gia_ObjValue(pObj)) ); + Gia_ManForEachPi( p->pAig, pObj, i ) + Gia_Sim2InfoRandom( p, Gia_Sim2Data(p, Gia_ObjValue(pObj)) ); + Gia_ManForEachAnd( p->pAig, pObj, i ) + { + assert( Gia_ObjValue(pObj) == i ); + Gia_Sim2SimulateNode( p, pObj ); + } + Gia_ManForEachCo( p->pAig, pObj, i ) + Gia_Sim2SimulateCo( p, pObj ); +} + + + +/**Function************************************************************* + + Synopsis [Compares simulation info of two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_Sim2CompareEqual( unsigned * p0, unsigned * p1, int nWords, int fCompl ) +{ + int w; + if ( !fCompl ) + { + for ( w = 0; w < nWords; w++ ) + if ( p0[w] != p1[w] ) + return 0; + return 1; + } + else + { + for ( w = 0; w < nWords; w++ ) + if ( p0[w] != ~p1[w] ) + return 0; + return 1; + } +} + +/**Function************************************************************* + + Synopsis [Compares simulation info of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_Sim2CompareZero( unsigned * p0, int nWords, int fCompl ) +{ + int w; + if ( !fCompl ) + { + for ( w = 0; w < nWords; w++ ) + if ( p0[w] != 0 ) + return 0; + return 1; + } + else + { + for ( w = 0; w < nWords; w++ ) + if ( p0[w] != ~0 ) + return 0; + return 1; + } +} + +/**Function************************************************************* + + Synopsis [Creates equivalence class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_Sim2ClassCreate( Gia_Man_t * p, Vec_Int_t * vClass ) +{ + int Repr = GIA_VOID, EntPrev = -1, Ent, i; + assert( Vec_IntSize(vClass) > 0 ); + Vec_IntForEachEntry( vClass, Ent, i ) + { + if ( i == 0 ) + { + Repr = Ent; + Gia_ObjSetRepr( p, Ent, GIA_VOID ); + EntPrev = Ent; + } + else + { + assert( Repr < Ent ); + Gia_ObjSetRepr( p, Ent, Repr ); + Gia_ObjSetNext( p, EntPrev, Ent ); + EntPrev = Ent; + } + } + Gia_ObjSetNext( p, EntPrev, 0 ); +} + +/**Function************************************************************* + + Synopsis [Refines one equivalence class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_Sim2ClassRefineOne( Gia_Sim2_t * p, int i ) +{ + Gia_Obj_t * pObj0, * pObj1; + unsigned * pSim0, * pSim1; + int Ent; + Vec_IntClear( p->vClassOld ); + Vec_IntClear( p->vClassNew ); + Vec_IntPush( p->vClassOld, i ); + pObj0 = Gia_ManObj( p->pAig, i ); + pSim0 = Gia_Sim2Data( p, i ); + Gia_ClassForEachObj1( p->pAig, i, Ent ) + { + pObj1 = Gia_ManObj( p->pAig, Ent ); + pSim1 = Gia_Sim2Data( p, Ent ); + if ( Gia_Sim2CompareEqual( pSim0, pSim1, p->nWords, Gia_ObjPhase(pObj0) ^ Gia_ObjPhase(pObj1) ) ) + Vec_IntPush( p->vClassOld, Ent ); + else + Vec_IntPush( p->vClassNew, Ent ); + } + if ( Vec_IntSize( p->vClassNew ) == 0 ) + return 0; + Gia_Sim2ClassCreate( p->pAig, p->vClassOld ); + Gia_Sim2ClassCreate( p->pAig, p->vClassNew ); + if ( Vec_IntSize(p->vClassNew) > 1 ) + return 1 + Gia_Sim2ClassRefineOne( p, Vec_IntEntry(p->vClassNew,0) ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes hash key of the simuation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_Sim2HashKey( unsigned * pSim, int nWords, int nTableSize ) +{ + static int s_Primes[16] = { + 1291, 1699, 1999, 2357, 2953, 3313, 3907, 4177, + 4831, 5147, 5647, 6343, 6899, 7103, 7873, 8147 }; + unsigned uHash = 0; + int i; + if ( pSim[0] & 1 ) + for ( i = 0; i < nWords; i++ ) + uHash ^= ~pSim[i] * s_Primes[i & 0xf]; + else + for ( i = 0; i < nWords; i++ ) + uHash ^= pSim[i] * s_Primes[i & 0xf]; + return (int)(uHash % nTableSize); + +} + +/**Function************************************************************* + + Synopsis [Refines nodes belonging to candidate constant class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_Sim2ProcessRefined( Gia_Sim2_t * p, Vec_Int_t * vRefined ) +{ + unsigned * pSim; + int * pTable, nTableSize, i, k, Key; + if ( Vec_IntSize(vRefined) == 0 ) + return; + nTableSize = Abc_PrimeCudd( 1000 + Vec_IntSize(vRefined) / 3 ); + pTable = ABC_CALLOC( int, nTableSize ); + Vec_IntForEachEntry( vRefined, i, k ) + { + pSim = Gia_Sim2Data( p, i ); + Key = Gia_Sim2HashKey( pSim, p->nWords, nTableSize ); + if ( pTable[Key] == 0 ) + { + assert( Gia_ObjRepr(p->pAig, i) == 0 ); + assert( Gia_ObjNext(p->pAig, i) == 0 ); + Gia_ObjSetRepr( p->pAig, i, GIA_VOID ); + } + else + { + Gia_ObjSetNext( p->pAig, pTable[Key], i ); + Gia_ObjSetRepr( p->pAig, i, Gia_ObjRepr(p->pAig, pTable[Key]) ); + if ( Gia_ObjRepr(p->pAig, i) == GIA_VOID ) + Gia_ObjSetRepr( p->pAig, i, pTable[Key] ); + assert( Gia_ObjRepr(p->pAig, i) > 0 ); + } + pTable[Key] = i; + } +/* + Vec_IntForEachEntry( vRefined, i, k ) + { + if ( Gia_ObjIsHead( p->pAig, i ) ) + Gia_Sim2ClassRefineOne( p, i ); + } +*/ + ABC_FREE( pTable ); +} +/**Function************************************************************* + + Synopsis [Refines equivalences after one simulation round.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_Sim2InfoRefineEquivs( Gia_Sim2_t * p ) +{ + Vec_Int_t * vRefined; + Gia_Obj_t * pObj; + unsigned * pSim; + int i, Count = 0; + // process constant candidates + vRefined = Vec_IntAlloc( 100 ); + Gia_ManForEachObj1( p->pAig, pObj, i ) + { + if ( !Gia_ObjIsConst(p->pAig, i) ) + continue; + pSim = Gia_Sim2Data( p, i ); +//Extra_PrintBinary( stdout, pSim, 32 * p->nWords ); printf( "\n" ); + if ( !Gia_Sim2CompareZero( pSim, p->nWords, Gia_ObjPhase(pObj) ) ) + { + Vec_IntPush( vRefined, i ); + Count++; + } + } + Gia_Sim2ProcessRefined( p, vRefined ); + Vec_IntFree( vRefined ); + // process other classes + Gia_ManForEachClass( p->pAig, i ) + Count += Gia_Sim2ClassRefineOne( p, i ); +// if ( Count ) +// printf( "Refined %d times.\n", Count ); +} + +/**Function************************************************************* + + Synopsis [Returns index of the first pattern that failed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_Sim2InfoIsZero( Gia_Sim2_t * p, unsigned * pInfo ) +{ + int w; + for ( w = 0; w < p->nWords; w++ ) + if ( pInfo[w] ) + return 32*w + Gia_WordFindFirstBit( pInfo[w] ); + return -1; +} + +/**Function************************************************************* + + Synopsis [Returns index of the PO and pattern that failed it.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_Sim2CheckPos( Gia_Sim2_t * p, int * piPo, int * piPat ) +{ + Gia_Obj_t * pObj; + int i, iPat; + Gia_ManForEachPo( p->pAig, pObj, i ) + { + iPat = Gia_Sim2InfoIsZero( p, Gia_Sim2Data( p, Gia_ObjValue(pObj) ) ); + if ( iPat >= 0 ) + { + *piPo = i; + *piPat = iPat; + return 1; + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Gia_Sim2GenerateCounter( Gia_Man_t * pAig, int iFrame, int iOut, int nWords, int iPat ) +{ + Abc_Cex_t * p; + unsigned * pData; + int f, i, w, Counter; + p = Abc_CexAlloc( Gia_ManRegNum(pAig), Gia_ManPiNum(pAig), iFrame+1 ); + p->iFrame = iFrame; + p->iPo = iOut; + // fill in the binary data + Counter = p->nRegs; + pData = ABC_ALLOC( unsigned, nWords ); + for ( f = 0; f <= iFrame; f++, Counter += p->nPis ) + for ( i = 0; i < Gia_ManPiNum(pAig); i++ ) + { + for ( w = nWords-1; w >= 0; w-- ) + pData[w] = Gia_ManRandom( 0 ); + if ( Abc_InfoHasBit( pData, iPat ) ) + Abc_InfoSetBit( p->pData, Counter + i ); + } + ABC_FREE( pData ); + return p; +} + +/**Function************************************************************* + + Synopsis [Performs simulation to refine equivalence classes.] + + Description [Returns 1 if counter-example is detected.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSimSimulateEquiv( Gia_Man_t * pAig, Gia_ParSim_t * pPars ) +{ + Gia_Sim2_t * p; + Gia_Obj_t * pObj; + abctime clkTotal = Abc_Clock(); + int i, RetValue = 0, iOut, iPat; + abctime nTimeToStop = pPars->TimeLimit ? pPars->TimeLimit * CLOCKS_PER_SEC + Abc_Clock(): 0; + assert( pAig->pReprs && pAig->pNexts ); + ABC_FREE( pAig->pCexSeq ); + p = Gia_Sim2Create( pAig, pPars ); + Gia_ManResetRandom( pPars ); + Gia_ManForEachRo( p->pAig, pObj, i ) + Gia_Sim2InfoZero( p, Gia_Sim2Data(p, Gia_ObjValue(pObj)) ); + for ( i = 0; i < pPars->nIters; i++ ) + { + Gia_Sim2SimulateRound( p ); + if ( pPars->fVerbose ) + { + Abc_Print( 1, "Frame %4d out of %4d and timeout %3d sec. ", i+1, pPars->nIters, pPars->TimeLimit ); + if ( pAig->pReprs && pAig->pNexts ) + Abc_Print( 1, "Lits = %4d. ", Gia_ManEquivCountLitsAll(pAig) ); + Abc_Print( 1, "Time = %7.2f sec\r", (1.0*Abc_Clock()-clkTotal)/CLOCKS_PER_SEC ); + } + if ( pPars->fCheckMiter && Gia_Sim2CheckPos( p, &iOut, &iPat ) ) + { + Gia_ManResetRandom( pPars ); + pPars->iOutFail = iOut; + pAig->pCexSeq = Gia_Sim2GenerateCounter( pAig, i, iOut, p->nWords, iPat ); + Abc_Print( 1, "Output %d of miter \"%s\" was asserted in frame %d. ", iOut, pAig->pName, i ); + if ( !Gia_ManVerifyCex( pAig, pAig->pCexSeq, 0 ) ) + { +// Abc_Print( 1, "\n" ); + Abc_Print( 1, "\nGenerated counter-example is INVALID. " ); +// Abc_Print( 1, "\n" ); + } + else + { +// Abc_Print( 1, "\n" ); +// if ( pPars->fVerbose ) +// Abc_Print( 1, "\nGenerated counter-example is verified correctly. " ); +// Abc_Print( 1, "\n" ); + } + RetValue = 1; + break; + } + if ( pAig->pReprs && pAig->pNexts ) + Gia_Sim2InfoRefineEquivs( p ); + if ( Abc_Clock() > nTimeToStop ) + { + i++; + break; + } + if ( i < pPars->nIters - 1 ) + Gia_Sim2InfoTransfer( p ); + } + Gia_Sim2Delete( p ); + if ( pAig->pCexSeq == NULL ) + Abc_Print( 1, "No bug detected after simulating %d frames with %d words. ", i, pPars->nWords ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clkTotal ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaSimBase.c b/yosys/abc/src/aig/gia/giaSimBase.c new file mode 100644 index 00000000000..b5c3c080224 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaSimBase.c @@ -0,0 +1,3750 @@ +/**CFile**************************************************************** + + FileName [giaSim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Fast sequential simulator.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/util/utilTruth.h" +#include "misc/extra/extra.h" +//#include +#include "aig/miniaig/miniaig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + + +typedef struct Gia_SimRsbMan_t_ Gia_SimRsbMan_t; +struct Gia_SimRsbMan_t_ +{ + Gia_Man_t * pGia; + Vec_Int_t * vTfo; + Vec_Int_t * vCands; + Vec_Int_t * vFanins; + Vec_Int_t * vFanins2; + Vec_Wrd_t * vSimsObj; + Vec_Wrd_t * vSimsObj2; + int nWords; + word * pFunc[3]; +}; + + +typedef struct Gia_SimAbsMan_t_ Gia_SimAbsMan_t; +struct Gia_SimAbsMan_t_ +{ + // problem formulation + Gia_Man_t * pGia; // AIG manager + word * pSet[2]; // offset/onset truth tables + int nCands; // candidate count + int nWords; // word count + Vec_Wrd_t * vSims; // candidate simulation info + Vec_Int_t * vResub; // the result + int fVerbose; // verbose + // intermediate result + Vec_Int_t * vValues; // function values in each pattern + Vec_Int_t * vPatPairs; // used minterms + int nWordsTable; // words of table data + word * pTableTemp; // temporary table pattern + Vec_Wrd_t * vCoverTable; // columns = minterms; rows = classes + Vec_Int_t * vTtMints; // truth table minterms +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimPatAssignInputs( Gia_Man_t * p, int nWords, Vec_Wrd_t * vSims, Vec_Wrd_t * vSimsIn ) +{ + int i, Id; + assert( Vec_WrdSize(vSims) == nWords * Gia_ManObjNum(p) ); + assert( Vec_WrdSize(vSimsIn) == nWords * Gia_ManCiNum(p) ); + Gia_ManForEachCiId( p, Id, i ) + memcpy( Vec_WrdEntryP(vSims, Id*nWords), Vec_WrdEntryP(vSimsIn, i*nWords), sizeof(word)*nWords ); +} +static inline void Gia_ManSimPatSimAnd( Gia_Man_t * p, int i, Gia_Obj_t * pObj, int nWords, Vec_Wrd_t * vSims ) +{ + word pComps[2] = { 0, ~(word)0 }; + word Diff0 = pComps[Gia_ObjFaninC0(pObj)]; + word Diff1 = pComps[Gia_ObjFaninC1(pObj)]; + word * pSims = Vec_WrdArray(vSims); + word * pSims0 = pSims + nWords*Gia_ObjFaninId0(pObj, i); + word * pSims1 = pSims + nWords*Gia_ObjFaninId1(pObj, i); + word * pSims2 = pSims + nWords*i; int w; + if ( Gia_ObjIsXor(pObj) ) + for ( w = 0; w < nWords; w++ ) + pSims2[w] = (pSims0[w] ^ Diff0) ^ (pSims1[w] ^ Diff1); + else + for ( w = 0; w < nWords; w++ ) + pSims2[w] = (pSims0[w] ^ Diff0) & (pSims1[w] ^ Diff1); +} +static inline void Gia_ManSimPatSimPo( Gia_Man_t * p, int i, Gia_Obj_t * pObj, int nWords, Vec_Wrd_t * vSims ) +{ + word pComps[2] = { 0, ~(word)0 }; + word Diff0 = pComps[Gia_ObjFaninC0(pObj)]; + word * pSims = Vec_WrdArray(vSims); + word * pSims0 = pSims + nWords*Gia_ObjFaninId0(pObj, i); + word * pSims2 = pSims + nWords*i; int w; + for ( w = 0; w < nWords; w++ ) + pSims2[w] = (pSims0[w] ^ Diff0); +} +static inline void Gia_ManSimPatSimNot( Gia_Man_t * p, int i, Gia_Obj_t * pObj, int nWords, Vec_Wrd_t * vSims ) +{ + word * pSims = Vec_WrdArray(vSims) + nWords*i; int w; + for ( w = 0; w < nWords; w++ ) + pSims[w] = ~pSims[w]; +} +Vec_Wrd_t * Gia_ManSimPatSim( Gia_Man_t * pGia ) +{ + Gia_Obj_t * pObj; + int i, nWords = Vec_WrdSize(pGia->vSimsPi) / Gia_ManCiNum(pGia); + Vec_Wrd_t * vSims = Vec_WrdStart( Gia_ManObjNum(pGia) * nWords ); + assert( Vec_WrdSize(pGia->vSimsPi) % Gia_ManCiNum(pGia) == 0 ); + Gia_ManSimPatAssignInputs( pGia, nWords, vSims, pGia->vSimsPi ); + Gia_ManForEachAnd( pGia, pObj, i ) + Gia_ManSimPatSimAnd( pGia, i, pObj, nWords, vSims ); + Gia_ManForEachCo( pGia, pObj, i ) + Gia_ManSimPatSimPo( pGia, Gia_ObjId(pGia, pObj), pObj, nWords, vSims ); + return vSims; +} +Vec_Wrd_t * Gia_ManSimPatSimOut( Gia_Man_t * pGia, Vec_Wrd_t * vSimsPi, int fOuts ) +{ + Gia_Obj_t * pObj; + int i, nWords = Vec_WrdSize(vSimsPi) / Gia_ManCiNum(pGia); + Vec_Wrd_t * vSimsCo = fOuts ? Vec_WrdStart( Gia_ManCoNum(pGia) * nWords ) : NULL; + Vec_Wrd_t * vSims = Vec_WrdStart( Gia_ManObjNum(pGia) * nWords ); + assert( Vec_WrdSize(vSimsPi) % Gia_ManCiNum(pGia) == 0 ); + Gia_ManSimPatAssignInputs( pGia, nWords, vSims, vSimsPi ); + Gia_ManForEachAnd( pGia, pObj, i ) + Gia_ManSimPatSimAnd( pGia, i, pObj, nWords, vSims ); + Gia_ManForEachCo( pGia, pObj, i ) + Gia_ManSimPatSimPo( pGia, Gia_ObjId(pGia, pObj), pObj, nWords, vSims ); + if ( !fOuts ) + return vSims; + Gia_ManForEachCo( pGia, pObj, i ) + memcpy( Vec_WrdEntryP(vSimsCo, i*nWords), Vec_WrdEntryP(vSims, Gia_ObjId(pGia, pObj)*nWords), sizeof(word)*nWords ); + Vec_WrdFree( vSims ); + return vSimsCo; +} +static inline void Gia_ManSimPatSimAnd3( Gia_Man_t * p, int i, Gia_Obj_t * pObj, int nWords, Vec_Wrd_t * vSims, Vec_Wrd_t * vSimsC ) +{ + word pComps[2] = { ~(word)0, 0 }; + word Diff0 = pComps[Gia_ObjFaninC0(pObj)]; + word Diff1 = pComps[Gia_ObjFaninC1(pObj)]; + word * pSims0 = Vec_WrdArray(vSims) + nWords*Gia_ObjFaninId0(pObj, i); + word * pSims1 = Vec_WrdArray(vSims) + nWords*Gia_ObjFaninId1(pObj, i); + word * pSims2 = Vec_WrdArray(vSims) + nWords*i; + word * pSimsC0 = Vec_WrdArray(vSimsC) + nWords*Gia_ObjFaninId0(pObj, i); + word * pSimsC1 = Vec_WrdArray(vSimsC) + nWords*Gia_ObjFaninId1(pObj, i); + word * pSimsC2 = Vec_WrdArray(vSimsC) + nWords*i; int w; + if ( Gia_ObjIsXor(pObj) ) + for ( w = 0; w < nWords; w++ ) + { + pSimsC0[w] |= pSimsC2[w]; + pSimsC1[w] |= pSimsC2[w]; + } + else + for ( w = 0; w < nWords; w++ ) + { + pSimsC0[w] |= (pSims2[w] | (pSims0[w] ^ Diff0)) & pSimsC2[w]; + pSimsC1[w] |= (pSims2[w] | (pSims1[w] ^ Diff1)) & pSimsC2[w]; + } +} +Vec_Wrd_t * Gia_ManSimPatSimIn( Gia_Man_t * pGia, Vec_Wrd_t * vSims, int fIns, Vec_Int_t * vAnds ) +{ + Gia_Obj_t * pObj; + int i, Id, nWords = Vec_WrdSize(vSims) / Gia_ManObjNum(pGia); + Vec_Wrd_t * vSimsCi = fIns ? Vec_WrdStart( Gia_ManCiNum(pGia) * nWords ) : NULL; + Vec_Wrd_t * vSimsC = Vec_WrdStart( Vec_WrdSize(vSims) ); + assert( Vec_WrdSize(vSims) % Gia_ManObjNum(pGia) == 0 ); + if ( vAnds ) + Vec_IntForEachEntry( vAnds, Id, i ) + memset( Vec_WrdEntryP(vSimsC, Id*nWords), 0xFF, sizeof(word)*nWords ); + else + Gia_ManForEachCoDriverId( pGia, Id, i ) + memset( Vec_WrdEntryP(vSimsC, Id*nWords), 0xFF, sizeof(word)*nWords ); + Gia_ManForEachAndReverse( pGia, pObj, i ) + Gia_ManSimPatSimAnd3( pGia, i, pObj, nWords, vSims, vSimsC ); + if ( !fIns ) + return vSimsC; + Gia_ManForEachCi( pGia, pObj, i ) + memcpy( Vec_WrdEntryP(vSimsCi, i*nWords), Vec_WrdEntryP(vSimsC, Gia_ObjId(pGia, pObj)*nWords), sizeof(word)*nWords ); + Vec_WrdFree( vSimsC ); + return vSimsCi; +} +void Gia_ManSimPatSimInTest( Gia_Man_t * pGia ) +{ + int nWords = 10; + Vec_Wrd_t * vSimsCi = Vec_WrdStartRandom( Gia_ManCiNum(pGia) * nWords ); + Vec_Wrd_t * vSims = Gia_ManSimPatSimOut( pGia, vSimsCi, 0 ); + Vec_Wrd_t * vSims2 = Gia_ManSimPatSimIn( pGia, vSims, 0, NULL ); + int nOnes = Abc_TtCountOnesVec( Vec_WrdArray(vSims2), Vec_WrdSize(vSims2) ); + int nTotal = 64*nWords*Gia_ManCandNum(pGia); + printf( "Ratio = %6.2f %%\n", 100.0*nOnes/nTotal ); + Vec_WrdFree( vSims ); + Vec_WrdFree( vSims2 ); + Vec_WrdFree( vSimsCi ); +} +static inline void Gia_ManSimPatSimAnd4( Gia_Man_t * p, int i, Gia_Obj_t * pObj, int nWords, Vec_Wrd_t * vSims, Vec_Wrd_t * vSimsC ) +{ + word pComps[2] = { ~(word)0, 0 }; + word Diff0 = pComps[Gia_ObjFaninC0(pObj)]; + word Diff1 = pComps[Gia_ObjFaninC1(pObj)]; + word * pSims0 = Vec_WrdArray(vSims) + nWords*Gia_ObjFaninId0(pObj, i); + word * pSims1 = Vec_WrdArray(vSims) + nWords*Gia_ObjFaninId1(pObj, i); + word * pSimsC0 = Vec_WrdArray(vSimsC) + nWords*Gia_ObjFaninId0(pObj, i); + word * pSimsC1 = Vec_WrdArray(vSimsC) + nWords*Gia_ObjFaninId1(pObj, i); + word * pSimsC2 = Vec_WrdArray(vSimsC) + nWords*i; int w; + if ( Gia_ObjIsXor(pObj) ) + for ( w = 0; w < nWords; w++ ) + pSimsC2[w] = pSimsC0[w] & pSimsC1[w]; + else + for ( w = 0; w < nWords; w++ ) + pSimsC2[w] = (pSimsC0[w] & pSimsC1[w]) | ((pSims0[w] ^ Diff0) & pSimsC0[w]) | ((pSims1[w] ^ Diff1) & pSimsC1[w]); +} +Vec_Wrd_t * Gia_ManSimPatSimC( Gia_Man_t * pGia, Vec_Wrd_t * vSims, Vec_Wrd_t * vSimsCiC ) +{ + Gia_Obj_t * pObj; + int i, Id, nWords = Vec_WrdSize(vSims) / Gia_ManObjNum(pGia); + Vec_Wrd_t * vSimsC = Vec_WrdStart( Vec_WrdSize(vSims) ); + assert( Vec_WrdSize(vSims) % Gia_ManObjNum(pGia) == 0 ); + memset( Vec_WrdEntryP(vSimsC, 0), 0xFF, sizeof(word)*nWords ); + Gia_ManForEachCiId( pGia, Id, i ) + memmove( Vec_WrdEntryP(vSimsC, Id*nWords), Vec_WrdEntryP(vSimsCiC, i*nWords), sizeof(word)*nWords ); + Gia_ManForEachAnd( pGia, pObj, i ) + Gia_ManSimPatSimAnd4( pGia, i, pObj, nWords, vSims, vSimsC ); + return vSimsC; +} +void Gia_ManSimPatSimCTest( Gia_Man_t * pGia ) +{ + int nWords = 10; + Vec_Wrd_t * vSimsCi = Vec_WrdStartRandom( Gia_ManCiNum(pGia) * nWords ); + Vec_Wrd_t * vSims = Gia_ManSimPatSimOut( pGia, vSimsCi, 0 ); + Vec_Wrd_t * vSims2 = Gia_ManSimPatSimIn( pGia, vSims, 0, NULL ); + Vec_Wrd_t * vSimsCi2 = Gia_ManSimPatSimIn( pGia, vSims, 1, NULL ); + Vec_Wrd_t * vSims3 = Gia_ManSimPatSimC( pGia, vSims, vSimsCi2 ); + int nOnes2 = Abc_TtCountOnesVec( Vec_WrdArray(vSims2), Vec_WrdSize(vSims2) ); + int nOnes3 = Abc_TtCountOnesVec( Vec_WrdArray(vSims3), Vec_WrdSize(vSims3) ); + int nTotal = 64*nWords*Gia_ManCandNum(pGia); + printf( "Ratio = %6.2f %% Ratio = %6.2f %%\n", 100.0*nOnes2/nTotal, 100.0*nOnes3/nTotal ); + Vec_WrdFree( vSims ); + Vec_WrdFree( vSims2 ); + Vec_WrdFree( vSims3 ); + Vec_WrdFree( vSimsCi ); + Vec_WrdFree( vSimsCi2 ); +} +void Gia_ManSimPatResim( Gia_Man_t * pGia, Vec_Int_t * vObjs, int nWords, Vec_Wrd_t * vSims ) +{ + Gia_Obj_t * pObj; int i; + Gia_ManForEachObjVec( vObjs, pGia, pObj, i ) + if ( i == 0 ) + Gia_ManSimPatSimNot( pGia, Gia_ObjId(pGia, pObj), pObj, nWords, vSims ); + else if ( Gia_ObjIsAnd(pObj) ) + Gia_ManSimPatSimAnd( pGia, Gia_ObjId(pGia, pObj), pObj, nWords, vSims ); + else if ( !Gia_ObjIsCo(pObj) ) assert(0); +} +void Gia_ManSimPatWrite( char * pFileName, Vec_Wrd_t * vSimsIn, int nWords ) +{ + Vec_WrdDumpHex( pFileName, vSimsIn, nWords, 0 ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word * Gia_ManDeriveFuncs( Gia_Man_t * p ) +{ + int nVars2 = (Gia_ManCiNum(p) + 6)/2; + int nVars3 = Gia_ManCiNum(p) - nVars2; + int nWords = Abc_Truth6WordNum( Gia_ManCiNum(p) ); + int nWords2 = Abc_Truth6WordNum( nVars2 ); + word * pRes = ABC_ALLOC( word, Gia_ManCoNum(p) * nWords ); + Vec_Wrd_t * vSims = Vec_WrdStart( nWords2 * Gia_ManObjNum(p) ); + Vec_Ptr_t * vTruths = Vec_PtrAllocTruthTables( nVars2 ); + Gia_Obj_t * pObj; int i, v, m; + Gia_ManForEachCi( p, pObj, i ) + assert( Gia_ObjId(p, pObj) == i+1 ); + for ( i = 0; i < nVars2; i++ ) + Abc_TtCopy( Vec_WrdEntryP(vSims, nWords2*(i+1)), (word *)Vec_PtrEntry(vTruths, i), nWords2, 0 ); + Vec_PtrFree( vTruths ); + for ( m = 0; m < (1 << nVars3); m++ ) + { + for ( v = 0; v < nVars3; v++ ) + Abc_TtConst( Vec_WrdEntryP(vSims, nWords2*(nVars2+v+1)), nWords2, (m >> v) & 1 ); + Gia_ManForEachAnd( p, pObj, i ) + Gia_ManSimPatSimAnd( p, i, pObj, nWords2, vSims ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManSimPatSimPo( p, Gia_ObjId(p, pObj), pObj, nWords2, vSims ); + Gia_ManForEachCo( p, pObj, i ) + Abc_TtCopy( pRes + i*nWords + m*nWords2, Vec_WrdEntryP(vSims, nWords2*Gia_ObjId(p, pObj)), nWords2, 0 ); + } + Vec_WrdFree( vSims ); + return pRes; +} +Gia_Man_t * Gia_ManPerformMuxDec( Gia_Man_t * p ) +{ + extern int Gia_ManFindMuxTree_rec( Gia_Man_t * pNew, int * pCtrl, int nCtrl, Vec_Int_t * vData, int Shift ); + extern int Kit_TruthToGia( Gia_Man_t * pMan, unsigned * pTruth, int nVars, Vec_Int_t * vMemory, Vec_Int_t * vLeaves, int fHash ); + int nWords = Abc_Truth6WordNum( Gia_ManCiNum(p) ); + int nCofs = 1 << (Gia_ManCiNum(p) - 6); + word * pRes = Gia_ManDeriveFuncs( p ); + Vec_Int_t * vMemory = Vec_IntAlloc( 1 << 16 ); + Vec_Int_t * vLeaves = Vec_IntAlloc( 6 ); + Vec_Int_t * vCtrls = Vec_IntAlloc( nCofs ); + Vec_Int_t * vDatas = Vec_IntAlloc( Gia_ManCoNum(p) ); + Gia_Man_t * pNew, * pTemp; int i, o; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + for ( i = 0; i < Gia_ManCiNum(p); i++ ) + Vec_IntPush( i < 6 ? vLeaves : vCtrls, Gia_ManAppendCi(pNew) ); + Gia_ManHashAlloc( pNew ); + for ( o = 0; o < Gia_ManCoNum(p); o++ ) + { + Vec_IntClear( vDatas ); + for ( i = 0; i < nWords; i++ ) + Vec_IntPush( vDatas, Kit_TruthToGia(pNew, (unsigned *)(pRes+o*nWords+i), 6, vMemory, vLeaves, 1) ); + Gia_ManAppendCo( pNew, Gia_ManFindMuxTree_rec(pNew, Vec_IntArray(vCtrls), Vec_IntSize(vCtrls), vDatas, 0) ); + } + Gia_ManHashStop( pNew ); + ABC_FREE( pRes ); + Vec_IntFree( vMemory ); + Vec_IntFree( vLeaves ); + Vec_IntFree( vCtrls ); + Vec_IntFree( vDatas ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Gia_ManTransferTiming( pNew, p ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManComputeTfos_rec( Gia_Man_t * p, int iObj, int iRoot, Vec_Int_t * vNode ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjIsTravIdPreviousId(p, iObj) ) + return 1; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return 0; + pObj = Gia_ManObj( p, iObj ); + if ( !Gia_ObjIsAnd(pObj) ) + return 0; + if ( Gia_ManComputeTfos_rec( p, Gia_ObjFaninId0(pObj, iObj), iRoot, vNode ) | + Gia_ManComputeTfos_rec( p, Gia_ObjFaninId1(pObj, iObj), iRoot, vNode ) ) + { + Gia_ObjSetTravIdPreviousId(p, iObj); + Vec_IntPush( vNode, iObj ); + return 1; + } + Gia_ObjSetTravIdCurrentId(p, iObj); + return 0; +} +Vec_Wec_t * Gia_ManComputeTfos( Gia_Man_t * p ) +{ + Vec_Wec_t * vNodes = Vec_WecStart( Gia_ManCiNum(p) ); + Vec_Int_t * vTemp = Vec_IntAlloc( 100 ); + int i, o, IdCi, IdCo; + Gia_ManForEachCiId( p, IdCi, i ) + { + Vec_Int_t * vNode = Vec_WecEntry( vNodes, i ); + Gia_ManIncrementTravId( p ); + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdPreviousId(p, IdCi); + Vec_IntPush( vNode, IdCi ); + Vec_IntClear( vTemp ); + Gia_ManForEachCoId( p, IdCo, o ) + if ( Gia_ManComputeTfos_rec( p, Gia_ObjFaninId0(Gia_ManObj(p, IdCo), IdCo), IdCi, vNode ) ) + Vec_IntPush( vTemp, Gia_ManObjNum(p) + (o >> 1) ); + Vec_IntUniqify( vTemp ); + Vec_IntAppend( vNode, vTemp ); + } + Vec_IntFree( vTemp ); + Vec_WecSort( vNodes, 1 ); + //Vec_WecPrint( vNodes, 0 ); + //Gia_AigerWrite( p, "dump.aig", 0, 0, 0 ); + return vNodes; +} +int Gia_ManFindDividerVar( Gia_Man_t * p, int fVerbose ) +{ + int iVar, Target = 1 << 28; + for ( iVar = 6; iVar < Gia_ManCiNum(p); iVar++ ) + if ( (1 << (iVar-3)) * Gia_ManObjNum(p) > Target ) + break; + if ( iVar == Gia_ManCiNum(p) ) + iVar = Gia_ManCiNum(p) - 1; + if ( fVerbose ) + printf( "Split var = %d. Rounds = %d. Bytes per node = %d. Total = %.2f MB.\n", iVar, 1 << (Gia_ManCiNum(p) - iVar), 1 << (iVar-3), 1.0*(1 << (iVar-3)) * Gia_ManObjNum(p)/(1<<20) ); + return iVar; +} +int Gia_ManComparePair( Gia_Man_t * p, Vec_Wrd_t * vSims, int iOut, int nWords2 ) +{ + Gia_Obj_t * pObj0 = Gia_ManCo( p, 2*iOut+0 ); + Gia_Obj_t * pObj1 = Gia_ManCo( p, 2*iOut+1 ); + word * pSim0 = Vec_WrdEntryP( vSims, nWords2*Gia_ObjId(p, pObj0) ); + word * pSim1 = Vec_WrdEntryP( vSims, nWords2*Gia_ObjId(p, pObj1) ); + Gia_ManSimPatSimPo( p, Gia_ObjId(p, pObj0), pObj0, nWords2, vSims ); + Gia_ManSimPatSimPo( p, Gia_ObjId(p, pObj1), pObj1, nWords2, vSims ); + return Abc_TtEqual( pSim0, pSim1, nWords2 ); +} +int Gia_ManCheckSimEquiv( Gia_Man_t * p, int fVerbose ) +{ + abctime clk = Abc_Clock(); int fWarning = 0; + //int nVars2 = (Gia_ManCiNum(p) + 6)/2; + int nVars2 = Gia_ManFindDividerVar( p, fVerbose ); + int nVars3 = Gia_ManCiNum(p) - nVars2; + int nWords2 = Abc_Truth6WordNum( nVars2 ); + Vec_Wrd_t * vSims = Vec_WrdStart( nWords2 * Gia_ManObjNum(p) ); + Vec_Wec_t * vNodes = Gia_ManComputeTfos( p ); + Vec_Ptr_t * vTruths = Vec_PtrAllocTruthTables( nVars2 ); + Gia_Obj_t * pObj; Vec_Int_t * vNode; int i, m, iObj; + Vec_WecForEachLevelStop( vNodes, vNode, i, nVars2 ) + Abc_TtCopy( Vec_WrdEntryP(vSims, nWords2*Vec_IntEntry(vNode,0)), (word *)Vec_PtrEntry(vTruths, i), nWords2, 0 ); + Vec_PtrFree( vTruths ); + Gia_ManForEachAnd( p, pObj, i ) + Gia_ManSimPatSimAnd( p, i, pObj, nWords2, vSims ); + for ( i = 0; i < Gia_ManCoNum(p)/2; i++ ) + { + if ( !Gia_ManComparePair( p, vSims, i, nWords2 ) ) + { + printf( "Miter is asserted for output %d.\n", i ); + Vec_WecFree( vNodes ); + Vec_WrdFree( vSims ); + return 0; + } + } + for ( m = 0; m < (1 << nVars3); m++ ) + { + int iVar = m ? Abc_TtSuppFindFirst( m ^ (m >> 1) ^ (m-1) ^ ((m-1) >> 1) ) : 0; + vNode = Vec_WecEntry( vNodes, nVars2+iVar ); + Abc_TtNot( Vec_WrdEntryP(vSims, nWords2*Vec_IntEntry(vNode,0)), nWords2 ); + Vec_IntForEachEntryStart( vNode, iObj, i, 1 ) + { + if ( iObj < Gia_ManObjNum(p) ) + { + pObj = Gia_ManObj( p, iObj ); + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManSimPatSimAnd( p, iObj, pObj, nWords2, vSims ); + } + else if ( !Gia_ManComparePair( p, vSims, iObj - Gia_ManObjNum(p), nWords2 ) ) + { + printf( "Miter is asserted for output %d.\n", iObj - Gia_ManObjNum(p) ); + Vec_WecFree( vNodes ); + Vec_WrdFree( vSims ); + return 0; + } + } + //for ( i = 0; i < Gia_ManObjNum(p); i++ ) + // printf( "%3d : ", i), Extra_PrintHex2( stdout, (unsigned *)Vec_WrdEntryP(vSims, i), 6 ), printf( "\n" ); + if ( !fWarning && Abc_Clock() > clk + 5*CLOCKS_PER_SEC ) + printf( "The computation is expected to take about %.2f sec.\n", 5.0*(1 << nVars3)/m ), fWarning = 1; + //if ( (m & 0x3F) == 0x3F ) + if ( fVerbose && (m & 0xFF) == 0xFF ) + printf( "Finished %6d (out of %6d)...\n", m, 1 << nVars3 ); + } + Vec_WecFree( vNodes ); + Vec_WrdFree( vSims ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimPatAssignInputs2( Gia_Man_t * p, int nWords, Vec_Wrd_t * vSims, Vec_Wrd_t * vSimsIn ) +{ + int i, Id; + assert( Vec_WrdSize(vSims) == 2 * nWords * Gia_ManObjNum(p) ); + assert( Vec_WrdSize(vSimsIn) == nWords * Gia_ManCiNum(p) ); + Gia_ManForEachCiId( p, Id, i ) + { + Abc_TtCopy( Vec_WrdEntryP(vSims, 2*Id*nWords+0), Vec_WrdEntryP(vSimsIn, i*nWords), nWords, 0 ); + Abc_TtCopy( Vec_WrdEntryP(vSims, 2*Id*nWords+1), Vec_WrdEntryP(vSimsIn, i*nWords), nWords, 1 ); + } +} +static inline void Gia_ManSimPatSimAnd2( Gia_Man_t * p, int i, Gia_Obj_t * pObj, int nWords, Vec_Wrd_t * vSims ) +{ + word * pSims = Vec_WrdArray(vSims); + word * pSims0 = pSims + nWords*Gia_ObjFaninLit0(pObj, i); + word * pSims1 = pSims + nWords*Gia_ObjFaninLit1(pObj, i); + word * pSims2 = pSims + nWords*(2*i+0); + word * pSims3 = pSims + nWords*(2*i+1); int w; + assert( !Gia_ObjIsXor(pObj) ); +// if ( Gia_ObjIsXor(pObj) ) +// for ( w = 0; w < nWords; w++ ) +// pSims2[w] = pSims0[w] ^ pSims1[w]; +// else + for ( w = 0; w < nWords; w++ ) + { + pSims2[w] = pSims0[w] & pSims1[w]; + pSims3[w] = ~pSims2[w]; + } + //_mm256_storeu_ps( (float *)pSims2, _mm256_and_ps(_mm256_loadu_ps((float *)pSims0), _mm256_loadu_ps((float *)pSims1)) ); +} +static inline void Gia_ManSimPatSimPo2( Gia_Man_t * p, int i, Gia_Obj_t * pObj, int nWords, Vec_Wrd_t * vSims ) +{ + word * pSims = Vec_WrdArray(vSims); + word * pSims0 = pSims + nWords*Gia_ObjFaninLit0(pObj, i); + word * pSims2 = pSims + nWords*i; int w; + for ( w = 0; w < nWords; w++ ) + pSims2[w] = pSims0[w]; +} +Vec_Wrd_t * Gia_ManSimPatSim2( Gia_Man_t * pGia ) +{ + Gia_Obj_t * pObj; + int i, nWords = Vec_WrdSize(pGia->vSimsPi) / Gia_ManCiNum(pGia); + Vec_Wrd_t * vSims = Vec_WrdStart( Gia_ManObjNum(pGia) * nWords * 2 ); + assert( Vec_WrdSize(pGia->vSimsPi) % Gia_ManCiNum(pGia) == 0 ); + Gia_ManSimPatAssignInputs2( pGia, nWords, vSims, pGia->vSimsPi ); + Gia_ManForEachAnd( pGia, pObj, i ) + Gia_ManSimPatSimAnd2( pGia, i, pObj, nWords, vSims ); + Gia_ManForEachCo( pGia, pObj, i ) + Gia_ManSimPatSimPo2( pGia, Gia_ObjId(pGia, pObj), pObj, nWords, vSims ); + return vSims; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimPatValuesDerive( Gia_Man_t * p, int nWords, Vec_Wrd_t * vSims, Vec_Wrd_t * vValues ) +{ + int i, Id; + assert( Vec_WrdSize(vSims) == nWords * Gia_ManObjNum(p) ); + assert( Vec_WrdSize(vValues) == nWords * Gia_ManCoNum(p) ); + Gia_ManForEachCoId( p, Id, i ) + memcpy( Vec_WrdEntryP(vValues, nWords * i), Vec_WrdEntryP(vSims, nWords * Id), sizeof(word)* nWords ); +} +Vec_Wrd_t * Gia_ManSimPatValues( Gia_Man_t * p ) +{ + int i, Id, nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + Vec_Wrd_t * vSims = Gia_ManSimPatSim( p ); + Vec_Wrd_t * vValues = Vec_WrdStart( Gia_ManCoNum(p) * nWords ); + assert( Vec_WrdSize(p->vSimsPi) == nWords * Gia_ManCiNum(p) ); + assert( Vec_WrdSize(vValues) == nWords * Gia_ManCoNum(p) ); + assert( Vec_WrdSize(vSims) == nWords * Gia_ManObjNum(p) ); + Gia_ManForEachCoId( p, Id, i ) + memcpy( Vec_WrdEntryP(vValues, nWords * i), Vec_WrdEntryP(vSims, nWords * Id), sizeof(word)* nWords ); + Vec_WrdFree( vSims ); + return vValues; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wrd_t * Gia_ManSimCombine( int nInputs, Vec_Wrd_t * vBase, Vec_Wrd_t * vAddOn, int nWordsUse ) +{ + int nWordsBase = Vec_WrdSize(vBase) / nInputs; + int nWordsAddOn = Vec_WrdSize(vAddOn) / nInputs; int i, w; + Vec_Wrd_t * vSimsIn = Vec_WrdAlloc( nInputs * (nWordsBase + nWordsUse) ); + assert( Vec_WrdSize(vBase) % nInputs == 0 ); + assert( Vec_WrdSize(vAddOn) % nInputs == 0 ); + assert( nWordsUse <= nWordsAddOn ); + for ( i = 0; i < nInputs; i++ ) + { + word * pSimsB = nWordsBase ? Vec_WrdEntryP( vBase, i * nWordsBase ) : NULL; + word * pSimsA = nWordsAddOn ? Vec_WrdEntryP( vAddOn, i * nWordsAddOn ) : NULL; + for ( w = 0; w < nWordsBase; w++ ) + Vec_WrdPush( vSimsIn, pSimsB[w] ); + for ( w = 0; w < nWordsUse; w++ ) + Vec_WrdPush( vSimsIn, pSimsA[w] ); + } + assert( Vec_WrdSize(vSimsIn) == Vec_WrdCap(vSimsIn) || Vec_WrdSize(vSimsIn) < 16 ); + return vSimsIn; +} +int Gia_ManSimBitPackOne( int nWords, Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsCare, int iPat, int * pLits, int nLits ) +{ + word * pSimsI, * pSimsC; int i, k; + for ( i = 0; i < iPat; i++ ) + { + for ( k = 0; k < nLits; k++ ) + { + int iVar = Abc_Lit2Var( pLits[k] ); + pSimsI = Vec_WrdEntryP( vSimsIn, nWords * iVar ); + pSimsC = Vec_WrdEntryP( vSimsCare, nWords * iVar ); + if ( Abc_TtGetBit(pSimsC, i) && (Abc_TtGetBit(pSimsI, i) == Abc_LitIsCompl(pLits[k])) ) + break; + } + if ( k == nLits ) + break; + } + for ( k = 0; k < nLits; k++ ) + { + int iVar = Abc_Lit2Var( pLits[k] ); + pSimsI = Vec_WrdEntryP( vSimsIn, nWords * iVar ); + pSimsC = Vec_WrdEntryP( vSimsCare, nWords * iVar ); + if ( !Abc_TtGetBit(pSimsC, i) && Abc_TtGetBit(pSimsI, i) == Abc_LitIsCompl(pLits[k]) ) + Abc_TtXorBit( pSimsI, i ); + Abc_TtSetBit( pSimsC, i ); + assert( Abc_TtGetBit(pSimsC, i) && (Abc_TtGetBit(pSimsI, i) != Abc_LitIsCompl(pLits[k])) ); + } + return (int)(i == iPat); +} +Vec_Wrd_t * Gia_ManSimBitPacking( Gia_Man_t * p, Vec_Int_t * vCexStore, int nCexes, int nUnDecs ) +{ + int c, iCur = 0, iPat = 0; + int nWordsMax = Abc_Bit6WordNum( nCexes ); + Vec_Wrd_t * vSimsIn = Vec_WrdStartRandom( Gia_ManCiNum(p) * nWordsMax ); + Vec_Wrd_t * vSimsCare = Vec_WrdStart( Gia_ManCiNum(p) * nWordsMax ); + Vec_Wrd_t * vSimsRes = NULL; + for ( c = 0; c < nCexes + nUnDecs; c++ ) + { + int Out = Vec_IntEntry( vCexStore, iCur++ ); + int Size = Vec_IntEntry( vCexStore, iCur++ ); + if ( Size == -1 ) + continue; + iPat += Gia_ManSimBitPackOne( nWordsMax, vSimsIn, vSimsCare, iPat, Vec_IntEntryP(vCexStore, iCur), Size ); + iCur += Size; + assert( iPat <= nCexes + nUnDecs ); + Out = 0; + } + assert( iCur == Vec_IntSize(vCexStore) ); + vSimsRes = Gia_ManSimCombine( Gia_ManCiNum(p), p->vSimsPi, vSimsIn, Abc_Bit6WordNum(iPat+1) ); + printf( "Compressed %d CEXes into %d patterns and added %d words to available %d words.\n", + nCexes, iPat, Abc_Bit6WordNum(iPat+1), Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p) ); + Vec_WrdFree( vSimsIn ); + Vec_WrdFree( vSimsCare ); + return vSimsRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSimPatHashPatterns( Gia_Man_t * p, int nWords, Vec_Wrd_t * vSims, int * pnC0, int * pnC1 ) +{ + Gia_Obj_t * pObj; + int i, nUnique; + Vec_Mem_t * vStore; + vStore = Vec_MemAlloc( nWords, 12 ); // 2^12 N-word entries per page + Vec_MemHashAlloc( vStore, 1 << 12 ); + Gia_ManForEachCand( p, pObj, i ) + { + word * pSim = Vec_WrdEntryP(vSims, i*nWords); + if ( pnC0 && Abc_TtIsConst0(pSim, nWords) ) + (*pnC0)++; + if ( pnC1 && Abc_TtIsConst1(pSim, nWords) ) + (*pnC1)++; + Vec_MemHashInsert( vStore, pSim ); + } + nUnique = Vec_MemEntryNum( vStore ); + Vec_MemHashFree( vStore ); + Vec_MemFree( vStore ); + return nUnique; +} +Gia_Man_t * Gia_ManSimPatGenMiter( Gia_Man_t * p, Vec_Wrd_t * vSims ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i, nWords = Vec_WrdSize(vSims) / Gia_ManObjNum(p); + pNew = Gia_ManStart( Gia_ManObjNum(p) + Gia_ManCoNum(p) ); + Gia_ManHashStart( pNew ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachAnd( p, pObj, i ) + { + word * pSim = Vec_WrdEntryP(vSims, i*nWords); + if ( Abc_TtIsConst0(pSim, nWords) ) + Gia_ManAppendCo( pNew, Abc_LitNotCond(pObj->Value, 0) ); + if ( Abc_TtIsConst1(pSim, nWords) ) + Gia_ManAppendCo( pNew, Abc_LitNotCond(pObj->Value, 1) ); + } + Gia_ManHashStop( pNew ); + return pNew; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimProfile( Gia_Man_t * pGia ) +{ + Vec_Wrd_t * vSims = Gia_ManSimPatSim( pGia ); + int nWords = Vec_WrdSize(vSims) / Gia_ManObjNum(pGia); + int nC0s = 0, nC1s = 0, nUnique = Gia_ManSimPatHashPatterns( pGia, nWords, vSims, &nC0s, &nC1s ); + printf( "Simulating %d patterns leads to %d unique objects (%.2f %% out of %d). Const0 = %d. Const1 = %d.\n", + 64*nWords, nUnique, 100.0*nUnique/Gia_ManCandNum(pGia), Gia_ManCandNum(pGia), nC0s, nC1s ); + Vec_WrdFree( vSims ); +} +void Gia_ManPatSatImprove( Gia_Man_t * p, int nWords0, int fVerbose ) +{ + extern Vec_Int_t * Cbs2_ManSolveMiterNc( Gia_Man_t * pAig, int nConfs, Vec_Str_t ** pvStatus, int fVerbose ); + int i, Status, Counts[3] = {0}; + Gia_Man_t * pGia; + Vec_Wrd_t * vSimsIn = NULL; + Vec_Str_t * vStatus = NULL; + Vec_Int_t * vCexStore = NULL; + Vec_Wrd_t * vSims = Gia_ManSimPatSim( p ); + //Gia_ManSimProfile( p ); + pGia = Gia_ManSimPatGenMiter( p, vSims ); + vCexStore = Cbs2_ManSolveMiterNc( pGia, 1000, &vStatus, 0 ); + Gia_ManStop( pGia ); + Vec_StrForEachEntry( vStatus, Status, i ) + { + assert( Status >= -1 && Status <= 1 ); + Counts[Status+1]++; + } + if ( fVerbose ) + printf( "Total = %d : SAT = %d. UNSAT = %d. UNDEC = %d.\n", Counts[1]+Counts[2]+Counts[0], Counts[1], Counts[2], Counts[0] ); + if ( Counts[1] == 0 ) + printf( "There are no counter-examples. No need for more simulation.\n" ); + else + { + vSimsIn = Gia_ManSimBitPacking( p, vCexStore, Counts[1], Counts[0] ); + Vec_WrdFreeP( &p->vSimsPi ); + p->vSimsPi = vSimsIn; + //Gia_ManSimProfile( p ); + } + Vec_StrFree( vStatus ); + Vec_IntFree( vCexStore ); + Vec_WrdFree( vSims ); +} + + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_SimRsbMan_t * Gia_SimRsbAlloc( Gia_Man_t * pGia ) +{ + Gia_SimRsbMan_t * p = ABC_CALLOC( Gia_SimRsbMan_t, 1 ); + p->pGia = pGia; + p->nWords = Vec_WrdSize(pGia->vSimsPi) / Gia_ManCiNum(pGia); assert( Vec_WrdSize(pGia->vSimsPi) % Gia_ManCiNum(pGia) == 0 ); + p->pFunc[0] = ABC_CALLOC( word, p->nWords ); + p->pFunc[1] = ABC_CALLOC( word, p->nWords ); + p->pFunc[2] = ABC_CALLOC( word, p->nWords ); + p->vTfo = Vec_IntAlloc( 1000 ); + p->vCands = Vec_IntAlloc( 1000 ); + p->vFanins = Vec_IntAlloc( 10 ); + p->vFanins2 = Vec_IntAlloc( 10 ); + p->vSimsObj = Gia_ManSimPatSim( pGia ); + p->vSimsObj2 = Vec_WrdStart( Vec_WrdSize(p->vSimsObj) ); + assert( p->nWords == Vec_WrdSize(p->vSimsObj) / Gia_ManObjNum(pGia) ); + Gia_ManStaticFanoutStart( pGia ); + return p; +} +void Gia_SimRsbFree( Gia_SimRsbMan_t * p ) +{ + Gia_ManStaticFanoutStop( p->pGia ); + Vec_IntFree( p->vTfo ); + Vec_IntFree( p->vCands ); + Vec_IntFree( p->vFanins ); + Vec_IntFree( p->vFanins2 ); + Vec_WrdFree( p->vSimsObj ); + Vec_WrdFree( p->vSimsObj2 ); + ABC_FREE( p->pFunc[0] ); + ABC_FREE( p->pFunc[1] ); + ABC_FREE( p->pFunc[2] ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_SimRsbTfo_rec( Gia_Man_t * p, int iObj, int iFanout, Vec_Int_t * vTfo ) +{ + int i, iFan; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return; + Gia_ObjSetTravIdCurrentId(p, iObj); + Gia_ObjForEachFanoutStaticId( p, iObj, iFan, i ) + if ( iFanout == -1 || iFan == iFanout ) + Gia_SimRsbTfo_rec( p, iFan, -1, vTfo ); + Vec_IntPush( vTfo, iObj ); +} +Vec_Int_t * Gia_SimRsbTfo( Gia_SimRsbMan_t * p, int iObj, int iFanout ) +{ + assert( iObj > 0 ); + Vec_IntClear( p->vTfo ); + Gia_ManIncrementTravId( p->pGia ); + Gia_SimRsbTfo_rec( p->pGia, iObj, iFanout, p->vTfo ); + assert( Vec_IntEntryLast(p->vTfo) == iObj ); + Vec_IntPop( p->vTfo ); + Vec_IntReverseOrder( p->vTfo ); + Vec_IntSort( p->vTfo, 0 ); + return p->vTfo; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word * Gia_SimRsbFunc( Gia_SimRsbMan_t * p, int iObj, Vec_Int_t * vFanins, int fOnSet ) +{ + int nTruthWords = Abc_Truth6WordNum( Vec_IntSize(vFanins) ); + word * pTruth = ABC_CALLOC( word, nTruthWords ); + word * pFunc = Vec_WrdEntryP( p->vSimsObj, p->nWords*iObj ); + word * pFanins[16] = {NULL}; int s, b, iMint, i, iFanin; + assert( Vec_IntSize(vFanins) <= 16 ); + Vec_IntForEachEntry( vFanins, iFanin, i ) + pFanins[i] = Vec_WrdEntryP( p->vSimsObj, p->nWords*iFanin ); + for ( s = 0; s < 64*p->nWords; s++ ) + { + if ( !Abc_TtGetBit(p->pFunc[2], s) || Abc_TtGetBit(pFunc, s) != fOnSet ) + continue; + iMint = 0; + for ( b = 0; b < Vec_IntSize(vFanins); b++ ) + if ( Abc_TtGetBit(pFanins[b], s) ) + iMint |= 1 << b; + Abc_TtSetBit( pTruth, iMint ); + } + return pTruth; +} +int Gia_SimRsbResubVerify( Gia_SimRsbMan_t * p, int iObj, Vec_Int_t * vFanins ) +{ + word * pTruth0 = Gia_SimRsbFunc( p, iObj, p->vFanins, 0 ); + word * pTruth1 = Gia_SimRsbFunc( p, iObj, p->vFanins, 1 ); + int Res = !Abc_TtIntersect( pTruth0, pTruth1, p->nWords, 0 ); + ABC_FREE( pTruth0 ); + ABC_FREE( pTruth1 ); + return Res; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_SimRsbSimAndCareSet( Gia_Man_t * p, int i, Gia_Obj_t * pObj, int nWords, Vec_Wrd_t * vSims, Vec_Wrd_t * vSims2 ) +{ + word pComps[2] = { 0, ~(word)0 }; + word Diff0 = pComps[Gia_ObjFaninC0(pObj)]; + word Diff1 = pComps[Gia_ObjFaninC1(pObj)]; + Vec_Wrd_t * vSims0 = Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId0(pObj, i)) ? vSims2 : vSims; + Vec_Wrd_t * vSims1 = Gia_ObjIsTravIdCurrentId(p, Gia_ObjFaninId1(pObj, i)) ? vSims2 : vSims; + word * pSims0 = Vec_WrdEntryP( vSims0, nWords*Gia_ObjFaninId0(pObj, i) ); + word * pSims1 = Vec_WrdEntryP( vSims1, nWords*Gia_ObjFaninId1(pObj, i) ); + word * pSims2 = Vec_WrdEntryP( vSims2, nWords*i ); int w; + if ( Gia_ObjIsXor(pObj) ) + for ( w = 0; w < nWords; w++ ) + pSims2[w] = (pSims0[w] ^ Diff0) ^ (pSims1[w] ^ Diff1); + else + for ( w = 0; w < nWords; w++ ) + pSims2[w] = (pSims0[w] ^ Diff0) & (pSims1[w] ^ Diff1); +} +word * Gia_SimRsbCareSet( Gia_SimRsbMan_t * p, int iObj, Vec_Int_t * vTfo ) +{ + word * pSims = Vec_WrdEntryP( p->vSimsObj, p->nWords*iObj ); + word * pSims2 = Vec_WrdEntryP( p->vSimsObj2, p->nWords*iObj ); int iNode, i; + Abc_TtCopy( pSims2, pSims, p->nWords, 1 ); + Abc_TtClear( p->pFunc[2], p->nWords ); + Vec_IntForEachEntry( vTfo, iNode, i ) + { + Gia_Obj_t * pNode = Gia_ManObj(p->pGia, iNode); + if ( Gia_ObjIsAnd(pNode) ) + Gia_SimRsbSimAndCareSet( p->pGia, iNode, pNode, p->nWords, p->vSimsObj, p->vSimsObj2 ); + else if ( Gia_ObjIsCo(pNode) ) + { + word * pSimsA = Vec_WrdEntryP( p->vSimsObj, p->nWords*Gia_ObjFaninId0p(p->pGia, pNode) ); + word * pSimsB = Vec_WrdEntryP( p->vSimsObj2, p->nWords*Gia_ObjFaninId0p(p->pGia, pNode) ); + Abc_TtOrXor( p->pFunc[2], pSimsA, pSimsB, p->nWords ); + } + else assert( 0 ); + } + return p->pFunc[2]; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ObjSimCollect( Gia_SimRsbMan_t * p ) +{ + int i, k, iTemp, iFanout; + Vec_IntClear( p->vFanins2 ); + assert( Vec_IntSize(p->vFanins) > 0 ); + Vec_IntForEachEntry( p->vFanins, iTemp, i ) + { + Gia_Obj_t * pObj = Gia_ManObj( p->pGia, iTemp ); + if ( Gia_ObjIsAnd(pObj) && !Gia_ObjIsTravIdCurrentId( p->pGia, Gia_ObjFaninId0(pObj, iTemp) ) ) + Vec_IntPush( p->vFanins2, Gia_ObjFaninId0(pObj, iTemp) ); + if ( Gia_ObjIsAnd(pObj) && !Gia_ObjIsTravIdCurrentId( p->pGia, Gia_ObjFaninId1(pObj, iTemp) ) ) + Vec_IntPush( p->vFanins2, Gia_ObjFaninId1(pObj, iTemp) ); + Gia_ObjForEachFanoutStaticId( p->pGia, iTemp, iFanout, k ) + if ( Gia_ObjIsAnd(Gia_ManObj(p->pGia, iFanout)) && !Gia_ObjIsTravIdCurrentId( p->pGia, iFanout ) ) + Vec_IntPush( p->vFanins2, iFanout ); + } +} +Vec_Int_t * Gia_ObjSimCands( Gia_SimRsbMan_t * p, int iObj, int nCands ) +{ + assert( iObj > 0 ); + assert( Gia_ObjIsAnd(Gia_ManObj(p->pGia, iObj)) ); + Vec_IntClear( p->vCands ); + Vec_IntFill( p->vFanins, 1, iObj ); + while ( Vec_IntSize(p->vFanins) > 0 && Vec_IntSize(p->vCands) < nCands ) + { + int i, iTemp; + Vec_IntForEachEntry( p->vFanins, iTemp, i ) + Gia_ObjSetTravIdCurrentId( p->pGia, iTemp ); + Gia_ObjSimCollect( p ); // p->vFanins -> p->vFanins2 + Vec_IntAppend( p->vCands, p->vFanins2 ); + ABC_SWAP( Vec_Int_t *, p->vFanins, p->vFanins2 ); + } + assert( Vec_IntSize(p->vFanins) == 0 || Vec_IntSize(p->vCands) >= nCands ); + if ( Vec_IntSize(p->vCands) > nCands ) + Vec_IntShrink( p->vCands, nCands ); + return p->vCands; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ObjSimRsb( Gia_SimRsbMan_t * p, int iObj, int nCands, int fVerbose, int * pnBufs, int * pnInvs ) +{ + int i, iCand, RetValue = 0; + Vec_Int_t * vTfo = Gia_SimRsbTfo( p, iObj, -1 ); + word * pCareSet = Gia_SimRsbCareSet( p, iObj, vTfo ); + word * pFunc = Vec_WrdEntryP( p->vSimsObj, p->nWords*iObj ); + Vec_Int_t * vCands = Gia_ObjSimCands( p, iObj, nCands ); + Abc_TtAndSharp( p->pFunc[0], pCareSet, pFunc, p->nWords, 1 ); + Abc_TtAndSharp( p->pFunc[1], pCareSet, pFunc, p->nWords, 0 ); + +/* +printf( "Considering node %d with %d candidates:\n", iObj, Vec_IntSize(vCands) ); +Vec_IntPrint( vTfo ); +Vec_IntPrint( vCands ); +Extra_PrintBinary( stdout, (unsigned *)pCareSet, 64 ); printf( "\n" ); +Extra_PrintBinary( stdout, (unsigned *)pFunc, 64 ); printf( "\n" ); +Extra_PrintBinary( stdout, (unsigned *)p->pFunc[0], 64 ); printf( "\n" ); +Extra_PrintBinary( stdout, (unsigned *)p->pFunc[1], 64 ); printf( "\n" ); +*/ + Vec_IntForEachEntry( vCands, iCand, i ) + { + word * pDiv = Vec_WrdEntryP( p->vSimsObj, p->nWords*iCand ); + if ( !Abc_TtIntersect(pDiv, p->pFunc[0], p->nWords, 0) && + !Abc_TtIntersect(pDiv, p->pFunc[1], p->nWords, 1) ) + { (*pnBufs)++; if ( fVerbose ) printf( "Level %3d : %d = buf(%d)\n", Gia_ObjLevelId(p->pGia, iObj), iObj, iCand ); RetValue = 1; } + if ( !Abc_TtIntersect(pDiv, p->pFunc[0], p->nWords, 1) && + !Abc_TtIntersect(pDiv, p->pFunc[1], p->nWords, 0) ) + { (*pnInvs)++; if ( fVerbose ) printf( "Level %3d : %d = inv(%d)\n", Gia_ObjLevelId(p->pGia, iObj), iObj, iCand ); RetValue = 1; } + } + return RetValue; +} + +int Gia_ManSimRsb( Gia_Man_t * pGia, int nCands, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Gia_Obj_t * pObj; int iObj, nCount = 0, nBufs = 0, nInvs = 0; + Gia_SimRsbMan_t * p = Gia_SimRsbAlloc( pGia ); + assert( pGia->vSimsPi != NULL ); + Gia_ManLevelNum( pGia ); + Gia_ManForEachAnd( pGia, pObj, iObj ) + //if ( iObj == 6 ) + nCount += Gia_ObjSimRsb( p, iObj, nCands, fVerbose, &nBufs, &nInvs ); + printf( "Can resubstitute %d nodes (%.2f %% out of %d) (Bufs = %d Invs = %d) ", + nCount, 100.0*nCount/Gia_ManAndNum(pGia), Gia_ManAndNum(pGia), nBufs, nInvs ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + Gia_SimRsbFree( p ); + return nCount; +} + + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimRelAssignInputs( Gia_Man_t * p, int nWords, Vec_Wrd_t * vSims, int nWordsIn, Vec_Wrd_t * vSimsIn ) +{ + int i, m, Id, nMints = nWords / nWordsIn; + assert( Vec_WrdSize(vSims) == nWords * Gia_ManObjNum(p) ); + assert( Vec_WrdSize(vSimsIn) == nWordsIn * Gia_ManCiNum(p) ); + Gia_ManForEachCiId( p, Id, i ) + for ( m = 0; m < nMints; m++ ) + memcpy( Vec_WrdEntryP(vSims, Id * nWords + nWordsIn * m), + Vec_WrdEntryP(vSimsIn, i * nWordsIn), sizeof(word) * nWordsIn ); +} +int Gia_ManSimRelCompare( Gia_Man_t * p, int nWords, Vec_Wrd_t * vSims, int nWordsOut, Vec_Wrd_t * vSimsOut, int iPat, int iMint ) +{ + int i, Id; + Gia_ManForEachCoId( p, Id, i ) + { + word * pSim = Vec_WrdEntryP( vSims, nWords * Id + iMint * nWordsOut ); + word * pSimOut = Vec_WrdEntryP( vSimsOut, nWordsOut * i ); +/* + int k; + for ( k = 0; k < 64*nWordsOut; k++ ) + printf( "%d", Abc_TtGetBit( pSim, k ) ); + printf( "\n" ); + for ( k = 0; k < 64*nWordsOut; k++ ) + printf( "%d", Abc_TtGetBit( pSimOut, k ) ); + printf( "\n\n" ); +*/ + if ( Abc_TtGetBit(pSim, iPat) != Abc_TtGetBit(pSimOut, iPat) ) + return 0; + } + return 1; +} +int Gia_ManSimRelCollectOutputs( Gia_Man_t * p, int nWords, Vec_Wrd_t * vSims, int nWordsOut, Vec_Wrd_t * vSimsOut, Vec_Wrd_t * vRel ) +{ + int i, m, nMints = nWords / nWordsOut, Count = 0; + assert( Vec_WrdSize(vSims) == nWords * Gia_ManObjNum(p) ); + assert( Vec_WrdSize(vSimsOut) == nWordsOut * Gia_ManCoNum(p) ); + assert( Vec_WrdSize(vRel) == nWordsOut * nMints ); + for ( i = 0; i < 64 * nWordsOut; i++ ) + { + int CountMints = 0; + for ( m = 0; m < nMints; m++ ) + if ( Gia_ManSimRelCompare(p, nWords, vSims, nWordsOut, vSimsOut, i, m) ) + Abc_TtSetBit( Vec_WrdArray(vRel), i*nMints+m ), CountMints++; + Count += CountMints == 0; + } + if ( Count ) + printf( "The relation is not well-defined for %d (out of %d) patterns.\n", Count, 64 * nWordsOut ); + return Count; +} +Vec_Wrd_t * Gia_ManSimRel( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Wrd_t * vVals ) +{ + int nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + int nMints = 1 << Vec_IntSize(vObjs), i, m, iObj; + Gia_Obj_t * pObj; + Vec_Wrd_t * vRel = Vec_WrdStart( nWords * nMints ); + Vec_Wrd_t * vSims = Vec_WrdStart( Gia_ManObjNum(p) * nWords * nMints ); + Gia_ManSimRelAssignInputs( p, nWords * nMints, vSims, nWords, p->vSimsPi ); + Vec_IntForEachEntry( vObjs, iObj, i ) + for ( m = 0; m < nMints; m++ ) + if ( (m >> i) & 1 ) + memset( Vec_WrdEntryP(vSims, iObj*nMints*nWords + nWords*m), 0xFF, sizeof(word)*nWords ); + else + memset( Vec_WrdEntryP(vSims, iObj*nMints*nWords + nWords*m), 0x00, sizeof(word)*nWords ); + Gia_ManCleanPhase( p ); + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + pObj->fPhase = 1; + Gia_ManForEachAnd( p, pObj, i ) + if ( !pObj->fPhase ) + Gia_ManSimPatSimAnd( p, i, pObj, nWords * nMints, vSims ); + Gia_ManForEachCo( p, pObj, i ) + if ( !pObj->fPhase ) + Gia_ManSimPatSimPo( p, Gia_ObjId(p, pObj), pObj, nWords * nMints, vSims ); + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + pObj->fPhase = 0; + if ( Gia_ManSimRelCollectOutputs( p, nWords * nMints, vSims, nWords, vVals, vRel ) ) + Vec_WrdFreeP( &vRel ); + Vec_WrdFree( vSims ); + return vRel; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimRelCheckFuncs( Gia_Man_t * p, Vec_Wrd_t * vRel, int nOuts, Vec_Wrd_t * vFuncs ) +{ + int i, k, m, Values[32], nErrors = 0, nMints = 1 << nOuts, nWords = Vec_WrdSize(vRel) / nMints; + assert( Vec_WrdSize(vFuncs) == 2 * nOuts * nWords ); + assert( nOuts <= 32 ); + for ( i = 0; i < 64 * nWords; i++ ) + { + for ( k = 0; k < nOuts; k++ ) + { + int Value0 = Abc_TtGetBit( Vec_WrdEntryP(vFuncs, (2*k+0)*nWords), i ); + int Value1 = Abc_TtGetBit( Vec_WrdEntryP(vFuncs, (2*k+1)*nWords), i ); + if ( Value0 && !Value1 ) + Values[k] = 1; + else if ( !Value0 && Value1 ) + Values[k] = 2; + else if ( !Value0 && !Value1 ) + Values[k] = 3; + else assert( 0 ); + } + for ( m = 0; m < nMints; m++ ) + { + for ( k = 0; k < nOuts; k++ ) + if ( ((Values[k] >> ((m >> k) & 1)) & 1) == 0 ) + break; + if ( k < nOuts ) + continue; + if ( Abc_TtGetBit( Vec_WrdArray(vRel), i*nMints+m ) ) + continue; + if ( nErrors++ == 0 ) + printf( "For pattern %d, minterm %d produced by function is not in the relation.\n", i, m ); + } + } + if ( nErrors ) + printf( "Total number of similar errors = %d.\n", nErrors ); + else + printf( "The function agrees with the relation.\n" ); +} +Vec_Wrd_t * Gia_ManSimRelDeriveFuncs( Gia_Man_t * p, Vec_Wrd_t * vRel, int nOuts ) +{ + int i, k, m, Count = 0, nMints = 1 << nOuts, nWords = Vec_WrdSize(vRel) / nMints; + Vec_Wrd_t * vFuncs = Vec_WrdStart( 2 * nOuts * nWords ); + assert( Vec_WrdSize(vRel) % nMints == 0 ); + for ( i = 0; i < 64 * nWords; i++ ) + { + for ( m = 0; m < nMints; m++ ) + if ( Abc_TtGetBit( Vec_WrdArray(vRel), i*nMints+m ) ) + break; + Count += m == nMints; + for ( k = 0; k < nOuts; k++ ) + if ( (m >> k) & 1 ) + Abc_TtSetBit( Vec_WrdEntryP(vFuncs, (2*k+1)*nWords), i ); + else + Abc_TtSetBit( Vec_WrdEntryP(vFuncs, (2*k+0)*nWords), i ); + } + if ( Count ) + printf( "The relation is not well-defined for %d (out of %d) patterns.\n", Count, 64 * nWords ); + else + printf( "The relation was successfully determized without don't-cares for %d patterns.\n", 64 * nWords ); + Gia_ManSimRelCheckFuncs( p, vRel, nOuts, vFuncs ); + return vFuncs; +} +Vec_Wrd_t * Gia_ManSimRelDeriveFuncs2( Gia_Man_t * p, Vec_Wrd_t * vRel, int nOuts ) +{ + int i, k, m, nDCs[32] = {0}, Count = 0, nMints = 1 << nOuts, nWords = Vec_WrdSize(vRel) / nMints; + Vec_Wrd_t * vFuncs = Vec_WrdStart( 2 * nOuts * nWords ); + assert( Vec_WrdSize(vRel) % nMints == 0 ); + assert( nOuts <= 32 ); + for ( i = 0; i < 64 * nWords; i++ ) + { + for ( m = 0; m < nMints; m++ ) + if ( Abc_TtGetBit( Vec_WrdArray(vRel), i*nMints+m ) ) + break; + Count += m == nMints; + for ( k = 0; k < nOuts; k++ ) + { + if ( Abc_TtGetBit( Vec_WrdArray(vRel), i*nMints+(m^(1<> k) & 1 ) + Abc_TtSetBit( Vec_WrdEntryP(vFuncs, (2*k+1)*nWords), i ); + else + Abc_TtSetBit( Vec_WrdEntryP(vFuncs, (2*k+0)*nWords), i ); + } + if ( 0 ) + { + for ( m = 0; m < nMints; m++ ) + printf( "%d", Abc_TtGetBit( Vec_WrdArray(vRel), i*nMints+m ) ); + printf( " " ); + for ( k = 0; k < nOuts; k++ ) + { + if ( Abc_TtGetBit( Vec_WrdEntryP(vFuncs, (2*k+0)*nWords), i ) ) + printf( "0" ); + else if ( Abc_TtGetBit( Vec_WrdEntryP(vFuncs, (2*k+1)*nWords), i ) ) + printf( "1" ); + else + printf( "-" ); + } + printf( "\n" ); + } + } + if ( Count ) + printf( "The relation is not well-defined for %d (out of %d) patterns.\n", Count, 64 * nWords ); + else + { + printf( "The relation was successfully determized with don't-cares for %d patterns.\n", 64 * nWords ); + for ( k = 0; k < nOuts; k++ ) + { + int nOffs = Abc_TtCountOnesVec( Vec_WrdEntryP(vFuncs, (2*k+0)*nWords), nWords ); + int nOns = Abc_TtCountOnesVec( Vec_WrdEntryP(vFuncs, (2*k+1)*nWords), nWords ); + printf( "%4d : Off = %6d On = %6d Dc = %6d (%6.2f %%)\n", k, nOffs, nOns, nDCs[k], 100.0*nDCs[k]/(64*nWords) ); + } + printf( "\n" ); + } + Gia_ManSimRelCheckFuncs( p, vRel, nOuts, vFuncs ); + return vFuncs; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimRelPrint( Gia_Man_t * p, Vec_Wrd_t * vRel, Vec_Int_t * vOutMints ) +{ + int nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + int nMints = Vec_WrdSize(vRel) / nWords; + int i, m, Count; +/* + for ( i = 0; i < 64 * nWords; i++ ) + { + int k; + for ( k = 0; k < Gia_ManCiNum(p); k++ ) + printf( "%d", Abc_TtGetBit( Vec_WrdEntryP(p->vSimsPi, k), i ) ); + printf( " " ); + Count = 0; + for ( m = 0; m < nMints; m++ ) + { + printf( "%d", Abc_TtGetBit( Vec_WrdArray(vRel), i*nMints+m ) ); + Count += Abc_TtGetBit( Vec_WrdArray(vRel), i*nMints+m ); + } + printf( " Count = %2d ", Count ); + if ( vOutMints ) + { + printf( " %3d ", Vec_IntEntry(vOutMints, i) ); + if ( Abc_TtGetBit( Vec_WrdArray(vRel), i*nMints+Vec_IntEntry(vOutMints, i) ) ) + printf( "yes" ); + else + printf( "no" ); + } + printf( "\n" ); + } +*/ +/* + for ( i = 0; i < 64 * nWords; i++ ) + { + Count = 0; + for ( m = 0; m < nMints; m++ ) + Count += Abc_TtGetBit( Vec_WrdArray(vRel), i*nMints+m ); + printf( "%d ", Count ); + } + printf( "\n" ); +*/ + for ( i = 0; i < 64 * nWords; i++ ) + { + Count = 0; + for ( m = 0; m < nMints; m++ ) + { + printf( "%d", Abc_TtGetBit( Vec_WrdArray(vRel), i*nMints+m ) ); + Count += Abc_TtGetBit( Vec_WrdArray(vRel), i*nMints+m ); + } + printf( " Count = %2d \n", Count ); + } +} +Vec_Int_t * Gia_ManSimPatStart( int nItems ) +{ + Vec_Int_t * vValues = Vec_IntAlloc( nItems ); + Vec_IntPush( vValues, 17 ); + Vec_IntPush( vValues, 39 ); + Vec_IntPush( vValues, 56 ); + Vec_IntPush( vValues, 221 ); + return vValues; +} +void Gia_ManSimRelTest( Gia_Man_t * p ) +{ + //int nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + Vec_Int_t * vObjs = Gia_ManSimPatStart( 4 ); // can be CI/AND/CO + Vec_Wrd_t * vVals = Gia_ManSimPatValues( p ); + Vec_Wrd_t * vRel = Gia_ManSimRel( p, vObjs, vVals ); + assert( p->vSimsPi != NULL ); + Gia_ManSimRelPrint( p, vRel, NULL ); + Vec_IntFree( vObjs ); + Vec_WrdFree( vVals ); + Vec_WrdFree( vRel ); +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_Sim5CollectValues( word * pOffSet, word * pOnSet, int nWords ) +{ + Vec_Int_t * vBits = Vec_IntAlloc( 64*nWords ); int i, Count[2] = {0}; + for ( i = 0; i < 64*nWords; i++ ) + if ( Abc_TtGetBit( pOffSet, i ) ) + Vec_IntPush( vBits, 0 ), Count[0]++; + else if ( Abc_TtGetBit( pOnSet, i ) ) + Vec_IntPush( vBits, 1 ), Count[1]++; + else + Vec_IntPush( vBits, -1 ); + //printf( "Offset = %d. Onset = %d. Dcset = %d.\n", Count[0], Count[1], 64*nWords - Count[0] - Count[1] ); + return vBits; +} +Gia_SimAbsMan_t * Gia_SimAbsAlloc( Gia_Man_t * pGia, word * pOffSet, word * pOnSet, Vec_Wrd_t * vSims, int nWords, Vec_Int_t * vResub, int fVerbose ) +{ + Gia_SimAbsMan_t * p = ABC_CALLOC( Gia_SimAbsMan_t, 1 ); + p->pGia = pGia; + p->pSet[0] = pOffSet; + p->pSet[1] = pOnSet; + p->nCands = Vec_WrdSize(vSims)/nWords; + p->nWords = nWords; + p->vSims = vSims; + p->vResub = vResub; + p->fVerbose = fVerbose; + p->vValues = Gia_Sim5CollectValues( pOffSet, pOnSet, nWords ); + p->vPatPairs = Vec_IntAlloc( 100 ); + p->vCoverTable = Vec_WrdAlloc( 10000 ); + p->vTtMints = Vec_IntAlloc( 100 ); + assert( Vec_WrdSize(vSims) % nWords == 0 ); + return p; +} +void Gia_SimAbsFree( Gia_SimAbsMan_t * p ) +{ + Vec_IntFree( p->vValues ); + Vec_IntFree( p->vPatPairs ); + Vec_WrdFree( p->vCoverTable ); + Vec_IntFree( p->vTtMints ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_SimAbsCheckSolution( Gia_SimAbsMan_t * p ) +{ + int x, y, z, w, fFound = 0; + assert( Vec_WrdSize(p->vCoverTable) == p->nWordsTable * (p->nCands+1) ); + + Abc_TtClear( p->pTableTemp, p->nWordsTable ); + for ( x = 0; x < Vec_IntSize(p->vPatPairs)/2; x++ ) + Abc_TtXorBit( p->pTableTemp, x ); + + for ( x = 0; x < p->nCands; x++ ) + { + word * pSimTableX = Vec_WrdEntryP( p->vCoverTable, p->nWordsTable * x ); + for ( w = 0; w < p->nWordsTable; w++ ) + if ( p->pTableTemp[w] != pSimTableX[w] ) + break; + if ( w == p->nWordsTable ) + { + printf( "Found solution { %d }\n", x ); + fFound = 1; + } + } + if ( fFound ) + return; + + for ( x = 0; x < p->nCands; x++ ) + for ( y = 0; y < x; y++ ) + { + word * pSimTableX = Vec_WrdEntryP( p->vCoverTable, p->nWordsTable * x ); + word * pSimTableY = Vec_WrdEntryP( p->vCoverTable, p->nWordsTable * y ); + for ( w = 0; w < p->nWordsTable; w++ ) + if ( p->pTableTemp[w] != (pSimTableX[w] | pSimTableY[w]) ) + break; + if ( w == p->nWordsTable ) + { + printf( "Found solution { %d %d }\n", y, x ); + fFound = 1; + } + } + if ( fFound ) + return; + + for ( x = 0; x < p->nCands; x++ ) + for ( y = 0; y < x; y++ ) + for ( z = 0; z < y; z++ ) + { + word * pSimTableX = Vec_WrdEntryP( p->vCoverTable, p->nWordsTable * x ); + word * pSimTableY = Vec_WrdEntryP( p->vCoverTable, p->nWordsTable * y ); + word * pSimTableZ = Vec_WrdEntryP( p->vCoverTable, p->nWordsTable * z ); + for ( w = 0; w < p->nWordsTable; w++ ) + if ( p->pTableTemp[w] != (pSimTableX[w] | pSimTableY[w] | pSimTableZ[w]) ) + break; + if ( w == p->nWordsTable ) + printf( "Found solution { %d %d %d }\n", z, y, x ); + } +} + +void Gia_SimAbsSolve( Gia_SimAbsMan_t * p ) +{ + abctime clk = Abc_Clock(); + int i, k, iPat, iPat2; +/* + Vec_Int_t * vSimPats = Vec_IntDup( p->vPatPairs ); + Vec_IntUniqify( vSimPats ); + printf( "Selected %d pattern pairs contain %d unique patterns.\n", Vec_IntSize(p->vPatPairs)/2, Vec_IntSize(vSimPats) ); + Vec_IntFree( vSimPats ); +*/ + // set up the covering problem + p->nWordsTable = Abc_Bit6WordNum( Vec_IntSize(p->vPatPairs)/2 ); + Vec_WrdFill( p->vCoverTable, p->nWordsTable * (p->nCands + 1), 0 ); + p->pTableTemp = Vec_WrdEntryP( p->vCoverTable, p->nWordsTable * p->nCands ); + for ( i = 0; i < p->nCands; i++ ) + { + word * pSimCand = Vec_WrdEntryP( p->vSims, p->nWords * i ); + word * pSimTable = Vec_WrdEntryP( p->vCoverTable, p->nWordsTable * i ); + //printf( "%4d : ", i ); + //Extra_PrintBinary( stdout, (word *)pSimCand, p->nCands ); printf( "\n" ); + Vec_IntForEachEntryDouble( p->vPatPairs, iPat, iPat2, k ) + { + assert( Vec_IntEntry(p->vValues, iPat) == 0 ); + assert( Vec_IntEntry(p->vValues, iPat2) == 1 ); + if ( Abc_TtGetBit(pSimCand, iPat) != Abc_TtGetBit(pSimCand, iPat2) ) + Abc_TtXorBit(pSimTable, k/2); + } + assert( k == Vec_IntSize(p->vPatPairs) ); + } + + if ( 0 ) + { + printf( " " ); + for ( i = 0; i < p->nCands; i++ ) + printf( "%d", i % 10 ); + printf( "\n" ); + + Vec_IntForEachEntryDouble( p->vPatPairs, iPat, iPat2, i ) + { + printf( "%4d ", i/2 ); + printf( "%4d ", iPat ); + printf( "%4d ", iPat2 ); + for ( k = 0; k < p->nCands; k++ ) + { + word * pSimTable = Vec_WrdEntryP( p->vCoverTable, p->nWordsTable * k ); + printf( "%c", Abc_TtGetBit(pSimTable, i/2) ? '*' : ' ' ); + } + printf( "\n" ); + } + } + + //Gia_SimAbsCheckSolution(p); + + Vec_IntClear( p->vResub ); + Abc_TtClear( p->pTableTemp, p->nWordsTable ); + for ( i = 0; i < Vec_IntSize(p->vPatPairs)/2; i++ ) + Abc_TtXorBit( p->pTableTemp, i ); + + while ( !Abc_TtIsConst0(p->pTableTemp, p->nWordsTable) ) + { + word * pSimTable; + int iArgMax = -1, CostThis, CostMax = -1; + // compute the cost of each column + for ( i = 0; i < p->nCands; i++ ) + { + pSimTable = Vec_WrdEntryP( p->vCoverTable, p->nWordsTable * i ); + CostThis = Abc_TtCountOnesVecMask( pSimTable, p->pTableTemp, p->nWordsTable, 0 ); + if ( CostMax >= CostThis ) + continue; + CostMax = CostThis; + iArgMax = i; + } + // find the best column + Vec_IntPush( p->vResub, iArgMax ); + // delete values of this column + pSimTable = Vec_WrdEntryP( p->vCoverTable, p->nWordsTable * iArgMax ); + Abc_TtSharp( p->pTableTemp, p->pTableTemp, pSimTable, p->nWordsTable ); + } + if ( p->fVerbose ) + { + printf( "Solution %2d for covering problem [%5d x %5d]: ", Vec_IntSize(p->vResub), Vec_IntSize(p->vPatPairs)/2, p->nCands ); + Vec_IntForEachEntry( p->vResub, iPat, i ) + printf( "%6d ", iPat ); + for ( ; i < 12; i++ ) + printf( " " ); + printf( " " ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } +} +int Gia_SimAbsRefine( Gia_SimAbsMan_t * p ) +{ + int i, b, Value, iPat, iMint, iObj, Count = 0; + word ** pFanins = ABC_ALLOC( word *, Vec_IntSize(p->vResub) ); + assert( Vec_IntSize(p->vResub) > 0 ); + Vec_IntForEachEntry( p->vResub, iObj, b ) + pFanins[b] = Vec_WrdEntryP( p->vSims, p->nWords * iObj ); + Vec_IntFill( p->vTtMints, 1 << Vec_IntSize(p->vResub), -1 ); + Vec_IntForEachEntry( p->vValues, Value, i ) + { + if ( Value == -1 ) + continue; + iMint = 0; + for ( b = 0; b < Vec_IntSize(p->vResub); b++ ) + if ( Abc_TtGetBit(pFanins[b], i) ) + iMint |= 1 << b; + iPat = Vec_IntEntry( p->vTtMints, iMint ); + if ( iPat == -1 ) + { + Vec_IntWriteEntry( p->vTtMints, iMint, i ); + continue; + } + assert( Abc_TtGetBit(p->pSet[Value], i) ); + if ( Abc_TtGetBit(p->pSet[Value], iPat) ) + continue; + assert( Abc_TtGetBit(p->pSet[!Value], iPat) ); + Vec_IntPushTwo( p->vPatPairs, Value ? iPat : i, Value ? i : iPat ); + //printf( "iPat1 = %d iPat2 = %d Mint = %d\n", Value ? iPat : i, Value ? i : iPat, iMint ); + Count++; + if ( Count == 64 ) + { + ABC_FREE( pFanins ); + return 1; + } + } + //printf( "Refinement added %d minterm pairs.\n", Count ); + ABC_FREE( pFanins ); + return Count != 0; +} +Vec_Int_t * Gia_SimAbsFind( Vec_Int_t * vValues, int Value ) +{ + Vec_Int_t * vSubset = Vec_IntAlloc( 100 ); int i, Entry; + Vec_IntForEachEntry( vValues, Entry, i ) + if ( Entry == Value ) + Vec_IntPush( vSubset, i ); + return vSubset; +} +void Gia_SimAbsInit( Gia_SimAbsMan_t * p ) +{ + int n, nPairsInit = 64; + Vec_Int_t * vValue0 = Gia_SimAbsFind( p->vValues, 0 ); + Vec_Int_t * vValue1 = Gia_SimAbsFind( p->vValues, 1 ); + Vec_IntClear( p->vPatPairs ); + printf( "There are %d offset and %d onset minterms (%d pairs) and %d divisors.\n", + Vec_IntSize(vValue0), Vec_IntSize(vValue1), Vec_IntSize(vValue0)*Vec_IntSize(vValue1), p->nCands ); + Abc_Random( 1 ); + assert( Vec_IntSize(vValue0) > 0 ); + assert( Vec_IntSize(vValue1) > 0 ); + for ( n = 0; n < nPairsInit; n++ ) + Vec_IntPushTwo( p->vPatPairs, + Vec_IntEntry(vValue0, Abc_Random(0) % Vec_IntSize(vValue0)), + Vec_IntEntry(vValue1, Abc_Random(0) % Vec_IntSize(vValue1)) ); + Vec_IntFree( vValue0 ); + Vec_IntFree( vValue1 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_SimAbsPerformOne( Gia_Man_t * pGia, word * pOffSet, word * pOnSet, Vec_Wrd_t * vSimsCands, int nWords, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Vec_Int_t * vResub = Vec_IntAlloc( 10 ); + Gia_SimAbsMan_t * p = Gia_SimAbsAlloc( pGia, pOffSet, pOnSet, vSimsCands, nWords, vResub, fVerbose ); + Gia_SimAbsInit( p ); + while ( 1 ) + { + Gia_SimAbsSolve( p ); + if ( !Gia_SimAbsRefine( p ) ) + break; + } + Gia_SimAbsFree( p ); + Abc_PrintTime( 1, "Resubstitution time", Abc_Clock() - clk ); + return vResub; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +typedef struct Gia_RsbMan_t_ Gia_RsbMan_t; +struct Gia_RsbMan_t_ +{ + Gia_Man_t * pGia; + word * pOffSet; + word * pOnSet; + int nWords; + int nWordsT; + Vec_Wrd_t * vSims; + Vec_Wrd_t * vSimsT; + Vec_Int_t * vCands; + Vec_Int_t * vObjs; + Vec_Int_t * vObjs2; + Vec_Wec_t * vSets[2]; + word * pSet[3]; + Vec_Int_t * vActive; +}; +Gia_RsbMan_t * Gia_RsbAlloc( Gia_Man_t * pGia, word * pOffSet, word * pOnSet, Vec_Wrd_t * vSims, int nWords, Vec_Wrd_t * vSimsT, int nWordsT, Vec_Int_t * vCands ) +{ + int i, iObj; + Gia_RsbMan_t * p = ABC_CALLOC( Gia_RsbMan_t, 1 ); + assert( nWords <= 1024 ); + assert( Vec_WrdSize(vSims) == 64 * nWords * nWordsT ); + assert( Vec_WrdSize(vSims) == Vec_WrdSize(vSimsT) ); + p->pGia = pGia; + p->pOffSet = pOffSet; + p->pOnSet = pOnSet; + p->nWords = nWords; + p->nWordsT = nWordsT; + p->vSims = vSims; + p->vSimsT = vSimsT; + p->vCands = vCands; + p->vObjs = Vec_IntAlloc( 100 ); + p->vObjs2 = Vec_IntAlloc( 100 ); + p->vSets[0] = Vec_WecAlloc( 1024 ); + p->vSets[1] = Vec_WecAlloc( 1024 ); + p->pSet[0] = ABC_CALLOC( word, nWordsT ); + p->pSet[1] = ABC_CALLOC( word, nWordsT ); + p->pSet[2] = ABC_CALLOC( word, nWordsT ); + p->vActive = Vec_IntAlloc( 100 ); + Vec_IntForEachEntry( vCands, iObj, i ) + { + assert( iObj < nWordsT * 64 ); + Abc_TtSetBit( p->pSet[0], iObj ); + } + Vec_WecPushLevel( p->vSets[0] ); + Vec_WecPushLevel( p->vSets[1] ); + for ( i = 0; i < 64*nWords; i++ ) + { + int Value0 = Abc_TtGetBit( pOffSet, i ); + int Value1 = Abc_TtGetBit( pOnSet, i ); + if ( Value0 && !Value1 ) + Vec_WecPush( p->vSets[0], 0, i ); + else if ( !Value0 && Value1 ) + Vec_WecPush( p->vSets[1], 0, i ); + else assert( !Value0 || !Value1 ); + } + assert( Vec_WecSize(p->vSets[0]) == 1 ); + assert( Vec_WecSize(p->vSets[1]) == 1 ); + Abc_Random( 1 ); + //Extra_PrintBinary2( stdout, (unsigned*)pOffSet, 64*nWords ); printf( "\n" ); + //Extra_PrintBinary2( stdout, (unsigned*)pOnSet, 64*nWords ); printf( "\n" ); + return p; +} +void Gia_RsbFree( Gia_RsbMan_t * p ) +{ + Vec_IntFree( p->vActive ); + Vec_IntFree( p->vObjs ); + Vec_IntFree( p->vObjs2 ); + Vec_WecFree( p->vSets[0] ); + Vec_WecFree( p->vSets[1] ); + ABC_FREE( p->pSet[0] ); + ABC_FREE( p->pSet[1] ); + ABC_FREE( p->pSet[2] ); + ABC_FREE( p ); +} + + +int Gia_RsbCost( Gia_RsbMan_t * p ) +{ + Vec_Int_t * vLevel[2]; int i, Cost = 0; + Vec_WecForEachLevelTwo( p->vSets[0], p->vSets[1], vLevel[0], vLevel[1], i ) + Cost += Vec_IntSize(vLevel[0]) * Vec_IntSize(vLevel[1]); + return Cost; +} +void Gia_RsbPrint( Gia_RsbMan_t * p ) +{ + Vec_Int_t * vLevel[2]; + int n, i, nLeaves = 1 << Vec_IntSize(p->vObjs); + assert( Vec_WecSize(p->vSets[0]) == nLeaves ); + assert( Vec_WecSize(p->vSets[1]) == nLeaves ); + printf( "Database for %d objects and cost %d:\n", Vec_IntSize(p->vObjs), Gia_RsbCost(p) ); + Vec_WecForEachLevelTwo( p->vSets[0], p->vSets[1], vLevel[0], vLevel[1], i ) + { + for ( n = 0; n < 2; n++ ) + { + printf( "%5d : ", i ); + Extra_PrintBinary2( stdout, (unsigned*)&i, Vec_IntSize(p->vObjs) ); printf( " %d ", n ); + Vec_IntPrint( vLevel[n] ); + } + } +} +void Gia_RsbUpdateAdd( Gia_RsbMan_t * p, int iObj ) +{ + int n, i, nLeaves = 1 << Vec_IntSize(p->vObjs); + assert( Vec_WecSize(p->vSets[0]) == nLeaves ); + assert( Vec_WecSize(p->vSets[1]) == nLeaves ); + for ( i = 0; i < nLeaves; i++ ) + { + for ( n = 0; n < 2; n++ ) + { + Vec_Int_t * vLevelN = Vec_WecPushLevel(p->vSets[n]); + Vec_Int_t * vLevel = Vec_WecEntry(p->vSets[n], i); + int iMint, j, k = 0; + Vec_IntForEachEntry( vLevel, iMint, j ) + { + if ( Abc_TtGetBit(Vec_WrdEntryP(p->vSims, p->nWords*iObj), iMint) ) + Vec_IntPush( vLevelN, iMint ); + else + Vec_IntWriteEntry( vLevel, k++, iMint ); + } + Vec_IntShrink( vLevel, k ); + } + } + Vec_IntPush( p->vObjs, iObj ); + assert( Vec_WecSize(p->vSets[0]) == 2*nLeaves ); + assert( Vec_WecSize(p->vSets[1]) == 2*nLeaves ); +} +void Gia_RsbUpdateRemove( Gia_RsbMan_t * p, int Index ) +{ + Vec_Int_t * vLevel[2], * vTemp[2][2]; + int k = 0, m, m2, nLeaves = 1 << Vec_IntSize(p->vObjs); + assert( Index < Vec_IntSize(p->vObjs) ); + assert( Vec_WecSize(p->vSets[0]) == nLeaves ); + assert( Vec_WecSize(p->vSets[1]) == nLeaves ); + for ( m = 0; m < nLeaves; m++ ) + { + if ( m & (1 << Index) ) + continue; + m2 = m ^ (1 << Index); + vTemp[0][0] = Vec_WecEntry(p->vSets[0], m); + vTemp[0][1] = Vec_WecEntry(p->vSets[1], m); + vTemp[1][0] = Vec_WecEntry(p->vSets[0], m2); + vTemp[1][1] = Vec_WecEntry(p->vSets[1], m2); + Vec_IntAppend( vTemp[0][0], vTemp[1][0] ); + Vec_IntAppend( vTemp[0][1], vTemp[1][1] ); + Vec_IntClear( vTemp[1][0] ); + Vec_IntClear( vTemp[1][1] ); + } + Vec_IntDrop( p->vObjs, Index ); + Vec_WecForEachLevelTwo( p->vSets[0], p->vSets[1], vLevel[0], vLevel[1], m ) + { + if ( m & (1 << Index) ) + continue; + ABC_SWAP( Vec_Int_t, Vec_WecArray(p->vSets[0])[k], Vec_WecArray(p->vSets[0])[m] ); + ABC_SWAP( Vec_Int_t, Vec_WecArray(p->vSets[1])[k], Vec_WecArray(p->vSets[1])[m] ); + k++; + } + assert( k == nLeaves/2 ); + Vec_WecShrink( p->vSets[0], k ); + Vec_WecShrink( p->vSets[1], k ); +} +int Gia_RsbRemovalCost( Gia_RsbMan_t * p, int Index ) +{ + Vec_Int_t * vTemp[2][2]; + //unsigned Mask = Abc_InfoMask( Index ); + int m, m2, Cost = 0, nLeaves = 1 << Vec_IntSize(p->vObjs); + assert( Vec_WecSize(p->vSets[0]) == (1 << Vec_IntSize(p->vObjs)) ); + assert( Vec_WecSize(p->vSets[1]) == (1 << Vec_IntSize(p->vObjs)) ); + for ( m = 0; m < nLeaves; m++ ) + { + if ( m & (1 << Index) ) + continue; + m2 = m ^ (1 << Index); + vTemp[0][0] = Vec_WecEntry(p->vSets[0], m); + vTemp[0][1] = Vec_WecEntry(p->vSets[1], m); + vTemp[1][0] = Vec_WecEntry(p->vSets[0], m2); + vTemp[1][1] = Vec_WecEntry(p->vSets[1], m2); + Cost += (Vec_IntSize(vTemp[0][0]) + Vec_IntSize(vTemp[1][0])) * (Vec_IntSize(vTemp[0][1]) + Vec_IntSize(vTemp[1][1])); + } + return Cost; +} +int Gia_RsbFindNodeToRemove( Gia_RsbMan_t * p, int * pMinCost ) +{ + int i, iObj, iMin = -1, CostMin = ABC_INFINITY; + Vec_IntForEachEntry( p->vObjs, iObj, i ) + { + int Cost = Gia_RsbRemovalCost( p, i ); + if ( CostMin > Cost ) + { + CostMin = Cost; + iMin = i; + } + } + if ( pMinCost ) + *pMinCost = CostMin; + return iMin; +} + +void Gia_RsbFindMints( Gia_RsbMan_t * p, int * pMint0, int * pMint1 ) +{ + int iSetI = Abc_Random(0) % Vec_IntSize(p->vActive); + int iSet = Vec_IntEntry( p->vActive, iSetI ); + Vec_Int_t * vArray0 = Vec_WecEntry(p->vSets[0], iSet); + Vec_Int_t * vArray1 = Vec_WecEntry(p->vSets[1], iSet); + int iMint0i = Abc_Random(0) % Vec_IntSize(vArray0); + int iMint1i = Abc_Random(0) % Vec_IntSize(vArray1); + int iMint0 = Vec_IntEntry( vArray0, iMint0i ); + int iMint1 = Vec_IntEntry( vArray1, iMint1i ); + *pMint0 = iMint0; + *pMint1 = iMint1; +} +int Gia_RsbFindNode( Gia_RsbMan_t * p ) +{ + int i, iObj, nNodes, nNodesNew = -1, nNodesOld = -1, Mint0, Mint1, Shift; + Abc_TtCopy( p->pSet[1], p->pSet[0], p->nWordsT, 0 ); + Vec_IntForEachEntry( p->vObjs, iObj, i ) + { + assert( Abc_TtGetBit(p->pSet[1], iObj) ); + Abc_TtXorBit(p->pSet[1], iObj); + } + Abc_TtCopy( p->pSet[2], p->pSet[1], p->nWordsT, 0 ); + Gia_RsbFindMints( p, &Mint0, &Mint1 ); + nNodes = Abc_TtAndXorSum( p->pSet[1], Vec_WrdEntryP(p->vSimsT, p->nWordsT*Mint0), Vec_WrdEntryP(p->vSimsT, p->nWordsT*Mint1), p->nWordsT ); + for ( i = 0; i < 5 && nNodes > 1; i++ ) + { + nNodesOld = nNodes; + Abc_TtCopy( p->pSet[2], p->pSet[1], p->nWordsT, 0 ); + Gia_RsbFindMints( p, &Mint0, &Mint1 ); + nNodesNew = Abc_TtAndXorSum( p->pSet[1], Vec_WrdEntryP(p->vSimsT, p->nWordsT*Mint0), Vec_WrdEntryP(p->vSimsT, p->nWordsT*Mint1), p->nWordsT ); + assert( nNodesNew <= nNodes ); + if ( nNodesNew < nNodes ) + i = 0; + nNodes = nNodesNew; + } + Shift = Abc_Random(0) % (64*p->nWordsT); + for ( i = 0; i < 64*p->nWordsT; i++ ) + { + int Index = (i+Shift) % (64*p->nWordsT); + if ( Abc_TtGetBit( p->pSet[2], Index ) ) + return Index; + } + assert( 0 ); + return -1; +} +int Gia_RsbCollectValid( Gia_RsbMan_t * p ) +{ + Vec_Int_t * vLevel[2]; int i; + Vec_IntClear( p->vActive ); + assert( Vec_WecSize(p->vSets[0]) == Vec_WecSize(p->vSets[1]) ); + Vec_WecForEachLevelTwo( p->vSets[0], p->vSets[1], vLevel[0], vLevel[1], i ) + if ( Vec_IntSize(vLevel[0]) && Vec_IntSize(vLevel[1]) ) + Vec_IntPush( p->vActive, i ); + if ( Vec_IntSize(p->vActive) == 0 ) + return 0; + return 1; +} +Vec_Int_t * Gia_RsbSolve( Gia_RsbMan_t * p ) +{ + int i, iMin; + Vec_IntClear( p->vObjs ); + while ( Gia_RsbCollectValid(p) ) + Gia_RsbUpdateAdd( p, Gia_RsbFindNode(p) ); + for ( i = 0; i < 100; i++ ) + { + int k, nUndo = 1 + Abc_Random(0) % Vec_IntSize(p->vObjs); + for ( k = 0; k < nUndo; k++ ) + { + iMin = Gia_RsbFindNodeToRemove( p, NULL );// &MinCost ); + Gia_RsbUpdateRemove( p, iMin ); + } + while ( Gia_RsbCollectValid(p) ) + Gia_RsbUpdateAdd( p, Gia_RsbFindNode(p) ); + if ( Vec_IntSize(p->vObjs2) == 0 || Vec_IntSize(p->vObjs2) > Vec_IntSize(p->vObjs) ) + { + Vec_IntClear( p->vObjs2 ); + Vec_IntAppend( p->vObjs2, p->vObjs ); + } + } + //Gia_RsbPrint( p ); + return Vec_IntDup( p->vObjs2 ); +} +Vec_Int_t * Gia_RsbSetFind( word * pOffSet, word * pOnSet, Vec_Wrd_t * vSims, int nWords, Vec_Wrd_t * vSimsT, int nWordsT, Vec_Int_t * vCands ) +{ + Gia_RsbMan_t * p = Gia_RsbAlloc( NULL, pOffSet, pOnSet, vSims, nWords, vSimsT, nWordsT, vCands ); + Vec_Int_t * vObjs = Gia_RsbSolve( p ); + Gia_RsbFree( p ); + Vec_IntSort( vObjs, 0 ); + return vObjs; +} + +/**Function************************************************************* + + Synopsis [Improving quality of simulation patterns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_SimQualityOne( Gia_Man_t * p, Vec_Int_t * vPat, int fPoOnly ) +{ + int i, Id, Value, nWords = Abc_Bit6WordNum( 1+Gia_ManCiNum(p) ); + Vec_Wrd_t * vTemp, * vSims, * vSimsPi = Vec_WrdStart( Gia_ManCiNum(p) * nWords ); + Vec_Int_t * vRes; + assert( Vec_IntSize(vPat) == Gia_ManCiNum(p) ); + Vec_IntForEachEntry( vPat, Value, i ) + { + word * pSim = Vec_WrdEntryP( vSimsPi, i*nWords ); + if ( Value ) + Abc_TtFill( pSim, nWords ); + Abc_TtXorBit( pSim, i+1 ); + } + vTemp = p->vSimsPi; + p->vSimsPi = vSimsPi; + vSims = Gia_ManSimPatSim( p ); + p->vSimsPi = vTemp; + if ( fPoOnly ) + { + vRes = Vec_IntStart( Gia_ManCoNum(p) ); + Gia_ManForEachCoId( p, Id, i ) + { + word * pSim = Vec_WrdEntryP( vSims, Id*nWords ); + if ( pSim[0] & 1 ) + Abc_TtNot( pSim, nWords ); + Vec_IntWriteEntry( vRes, i, Abc_TtCountOnesVec(pSim, nWords) ); + } + assert( Vec_IntSize(vRes) == Gia_ManCoNum(p) ); + } + else + { + vRes = Vec_IntStart( Gia_ManObjNum(p) ); + Gia_ManForEachAndId( p, Id ) + { + word * pSim = Vec_WrdEntryP( vSims, Id*nWords ); + if ( pSim[0] & 1 ) + Abc_TtNot( pSim, nWords ); + Vec_IntWriteEntry( vRes, Id, Abc_TtCountOnesVec(pSim, nWords) ); + } + assert( Vec_IntSize(vRes) == Gia_ManObjNum(p) ); + } + Vec_WrdFree( vSims ); + Vec_WrdFree( vSimsPi ); + return vRes; +} +void Gia_SimQualityTest( Gia_Man_t * p ) +{ + Vec_Int_t * vPat, * vRes; + int k, m, nMints = (1 << Gia_ManCiNum(p)); + assert( Gia_ManCiNum(p) <= 10 ); + for ( m = 0; m < nMints; m++ ) + { + printf( "%d : ", m ); + Extra_PrintBinary( stdout, (unsigned*)&m, Gia_ManCiNum(p) ); + printf( " " ); + vPat = Vec_IntAlloc( Gia_ManCiNum(p) ); + for ( k = 0; k < Gia_ManCiNum(p); k++ ) + Vec_IntPush( vPat, (m >> k) & 1 ); + vRes = Gia_SimQualityOne( p, vPat, 1 ); + printf( "%d ", Vec_IntSum(vRes) ); + Vec_IntFree( vRes ); + Vec_IntFree( vPat ); + printf( "\n" ); + } +} +Vec_Int_t * Gia_SimGenerateStats( Gia_Man_t * p ) +{ + Vec_Int_t * vTotal = Vec_IntStart( Gia_ManObjNum(p) ); + Vec_Int_t * vRes, * vPat; + int i, k, Value; + Abc_Random(1); + for ( i = 0; i < 1000; i++ ) + { + vPat = Vec_IntAlloc( Gia_ManCiNum(p) ); + for ( k = 0; k < Gia_ManCiNum(p); k++ ) + Vec_IntPush( vPat, Abc_Random(0) & 1 ); + vRes = Gia_SimQualityOne( p, vPat, 0 ); + assert( Vec_IntSize(vRes) == Gia_ManObjNum(p) ); + Vec_IntForEachEntry( vRes, Value, k ) + Vec_IntAddToEntry( vTotal, k, Value ); + Vec_IntFree( vRes ); + Vec_IntFree( vPat ); + } + //Vec_IntPrint( vTotal ); + return vTotal; +} +double Gia_SimComputeScore( Gia_Man_t * p, Vec_Int_t * vTotal, Vec_Int_t * vThis ) +{ + double TotalScore = 0; + int i, Total, This; + assert( Vec_IntSize(vTotal) == Vec_IntSize(vThis) ); + Vec_IntForEachEntryTwo( vTotal, vThis, Total, This, i ) + { + if ( Total == 0 ) + Total = 1; + TotalScore += 1000.0*This/Total; + } + return TotalScore == 0 ? 1.0 : TotalScore/Gia_ManAndNum(p); +} +int Gia_SimQualityPatternsMax( Gia_Man_t * p, Vec_Int_t * vPat, int Iter, int fVerbose, Vec_Int_t * vStats ) +{ + int k, MaxIn = -1; + Vec_Int_t * vTries = Vec_IntAlloc( 100 ); + Vec_Int_t * vRes = Gia_SimQualityOne( p, vPat, 0 ); + double Value, InitValue, MaxValue = InitValue = Gia_SimComputeScore( p, vStats, vRes ); + Vec_IntFree( vRes ); + + if ( fVerbose ) + printf( "Iter %5d : Init = %6.3f ", Iter, InitValue ); + + for ( k = 0; k < Gia_ManCiNum(p); k++ ) + { + Vec_IntArray(vPat)[k] ^= 1; + //Vec_IntPrint( vPat ); + + vRes = Gia_SimQualityOne( p, vPat, 0 ); + Value = Gia_SimComputeScore( p, vStats, vRes ); + if ( MaxValue <= Value ) + { + if ( MaxValue < Value ) + Vec_IntClear( vTries ); + Vec_IntPush( vTries, k ); + MaxValue = Value; + MaxIn = k; + } + Vec_IntFree( vRes ); + + Vec_IntArray(vPat)[k] ^= 1; + } + MaxIn = Vec_IntSize(vTries) ? Vec_IntEntry( vTries, rand()%Vec_IntSize(vTries) ) : -1; + if ( fVerbose ) + { + printf( "Final = %6.3f Ratio = %4.2f Tries = %5d ", MaxValue, MaxValue/InitValue, Vec_IntSize(vTries) ); + printf( "Choosing %5d\r", MaxIn ); + } + Vec_IntFree( vTries ); + return MaxIn; +} +Vec_Int_t * Gia_ManPatCollectOne( Gia_Man_t * p, Vec_Wrd_t * vPatterns, int n, int nWords ) +{ + Vec_Int_t * vPat = Vec_IntAlloc( Gia_ManCiNum(p) ); int k; + for ( k = 0; k < Gia_ManCiNum(p); k++ ) + Vec_IntPush( vPat, Abc_TtGetBit( Vec_WrdEntryP(vPatterns, k*nWords), n ) ); + return vPat; +} +void Gia_ManPatUpdateOne( Gia_Man_t * p, Vec_Wrd_t * vPatterns, int n, int nWords, Vec_Int_t * vPat ) +{ + int k, Value; + Vec_IntForEachEntry( vPat, Value, k ) + { + word * pSim = Vec_WrdEntryP( vPatterns, k*nWords ); + if ( Abc_TtGetBit(pSim, n) != Value ) + Abc_TtXorBit( pSim, n ); + } +} +void Gia_ManPatDistImprove( Gia_Man_t * p, int fVerbose ) +{ + int n, k, nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + double InitValue, InitTotal = 0, FinalValue, FinalTotal = 0; + Vec_Int_t * vPat, * vRes, * vStats = Gia_SimGenerateStats( p ); + Vec_Wrd_t * vPatterns = p->vSimsPi; p->vSimsPi = NULL; + Abc_Random(1); + for ( n = 0; n < 64*nWords; n++ ) + { + abctime clk = Abc_Clock(); +// if ( n == 32 ) +// break; + + vPat = Gia_ManPatCollectOne( p, vPatterns, n, nWords ); + vRes = Gia_SimQualityOne( p, vPat, 0 ); + InitValue = Gia_SimComputeScore(p, vStats, vRes); + InitTotal += InitValue; + Vec_IntFree( vRes ); + + for ( k = 0; k < 100; k++ ) + { + int MaxIn = Gia_SimQualityPatternsMax( p, vPat, k, fVerbose, vStats ); + if ( MaxIn == -1 ) + break; + assert( MaxIn >= 0 && MaxIn < Gia_ManCiNum(p) ); + Vec_IntArray(vPat)[MaxIn] ^= 1; + } + //Vec_IntPrint( vPat ); + + vRes = Gia_SimQualityOne( p, vPat, 0 ); + FinalValue = Gia_SimComputeScore(p, vStats, vRes); + FinalTotal += FinalValue; + Vec_IntFree( vRes ); + + if ( fVerbose ) + { + printf( "Pat %5d : Tries = %5d InitValue = %6.3f FinalValue = %6.3f Ratio = %4.2f ", + n, k, InitValue, FinalValue, FinalValue/InitValue ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + + Gia_ManPatUpdateOne( p, vPatterns, n, nWords, vPat ); + Vec_IntFree( vPat ); + } + Vec_IntFree( vStats ); + if ( fVerbose ) + printf( "\n" ); + printf( "Improved %d patterns with average init value %.2f and average final value %.2f.\n", + 64*nWords, 1.0*InitTotal/(64*nWords), 1.0*FinalTotal/(64*nWords) ); + p->vSimsPi = vPatterns; +} + +/**Function************************************************************* + + Synopsis [Improving quality of simulation patterns.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_SimCollectRare( Gia_Man_t * p, Vec_Wrd_t * vPatterns, int RareLimit ) +{ + Vec_Int_t * vRareCounts = Vec_IntAlloc( 100 ); // (node, rare_count) pairs + int Id, nWords = Vec_WrdSize(vPatterns) / Gia_ManCiNum(p), TotalBits = 64*nWords; + Vec_Wrd_t * vSims, * vTemp = p->vSimsPi; + assert( Vec_WrdSize(vPatterns) % Gia_ManCiNum(p) == 0 ); + p->vSimsPi = vPatterns; + vSims = Gia_ManSimPatSim( p ); + p->vSimsPi = vTemp; + Gia_ManForEachAndId( p, Id ) + { + word * pSim = Vec_WrdEntryP( vSims, Id*nWords ); + int Count = Abc_TtCountOnesVec( pSim, nWords ); + int fRareOne = Count < TotalBits/2; // fRareOne is 1 if rare value is 1 + int CountRare = fRareOne ? Count : TotalBits - Count; + assert( CountRare <= TotalBits/2 ); + if ( CountRare <= RareLimit ) + Vec_IntPushTwo( vRareCounts, Abc_Var2Lit(Id, fRareOne), CountRare ); + } + Vec_WrdFree( vSims ); + return vRareCounts; +} +Vec_Flt_t * Gia_SimQualityImpact( Gia_Man_t * p, Vec_Int_t * vPat, Vec_Int_t * vRareCounts ) +{ + Vec_Flt_t * vQuoIncs = Vec_FltStart( Gia_ManCiNum(p) ); + int nWordsNew = Abc_Bit6WordNum( 1+Gia_ManCiNum(p) ); + Vec_Wrd_t * vSimsPiNew = Vec_WrdStart( Gia_ManCiNum(p) * nWordsNew ); + Vec_Wrd_t * vTemp, * vSims; + int i, k, Value, RareLit, RareCount; + assert( Vec_IntSize(vPat) == Gia_ManCiNum(p) ); + Vec_IntForEachEntry( vPat, Value, i ) + { + word * pSim = Vec_WrdEntryP( vSimsPiNew, i*nWordsNew ); + if ( Value ) + Abc_TtFill( pSim, nWordsNew ); + Abc_TtXorBit( pSim, i+1 ); + } + vTemp = p->vSimsPi; + p->vSimsPi = vSimsPiNew; + vSims = Gia_ManSimPatSim( p ); + p->vSimsPi = vTemp; + Vec_IntForEachEntryDouble( vRareCounts, RareLit, RareCount, i ) + { + float Incrm = (float)1.0/(RareCount+1); + int RareObj = Abc_Lit2Var(RareLit); + int RareVal = Abc_LitIsCompl(RareLit); + word * pSim = Vec_WrdEntryP( vSims, RareObj*nWordsNew ); + int OrigVal = pSim[0] & 1; + if ( OrigVal ) + Abc_TtNot( pSim, nWordsNew ); + for ( k = 0; k < Gia_ManCiNum(p); k++ ) + if ( Abc_TtGetBit(pSim, k+1) ) // value changed + Vec_FltAddToEntry( vQuoIncs, k, OrigVal != RareVal ? Incrm : -Incrm ); + } + Vec_WrdFree( vSims ); + Vec_WrdFree( vSimsPiNew ); + return vQuoIncs; +} +Vec_Int_t * Gia_SimCollectBest( Vec_Flt_t * vQuo ) +{ + Vec_Int_t * vRes; int i; + float Value, ValueMax = Vec_FltFindMax( vQuo ); + if ( ValueMax <= 0 ) + return NULL; + vRes = Vec_IntAlloc( 100 ); // variables with max quo + Vec_FltForEachEntry( vQuo, Value, i ) + if ( Value == ValueMax ) + Vec_IntPush( vRes, i ); + return vRes; +} +float Gia_ManPatGetQuo( Gia_Man_t * p, Vec_Int_t * vRareCounts, Vec_Wrd_t * vSims, int n, int nWords ) +{ + float Quality = 0; + int RareLit, RareCount, i; + assert( Vec_WrdSize(vSims) == Gia_ManObjNum(p) ); + Vec_IntForEachEntryDouble( vRareCounts, RareLit, RareCount, i ) + { + float Incrm = (float)1.0/(RareCount+1); + int RareObj = Abc_Lit2Var(RareLit); + int RareVal = Abc_LitIsCompl(RareLit); + word * pSim = Vec_WrdEntryP( vSims, RareObj*nWords ); + if ( Abc_TtGetBit(pSim, n) == RareVal ) + Quality += Incrm; + } + return Quality; +} +float Gia_ManPatGetTotalQuo( Gia_Man_t * p, int RareLimit, Vec_Wrd_t * vPatterns, int nWords ) +{ + float Total = 0; int n; + Vec_Int_t * vRareCounts = Gia_SimCollectRare( p, vPatterns, RareLimit ); + Vec_Wrd_t * vSims, * vTemp = p->vSimsPi; + p->vSimsPi = vPatterns; + vSims = Gia_ManSimPatSim( p ); + p->vSimsPi = vTemp; + for ( n = 0; n < 64*nWords; n++ ) + Total += Gia_ManPatGetQuo( p, vRareCounts, vSims, n, nWords ); + Vec_IntFree( vRareCounts ); + Vec_WrdFree( vSims ); + return Total; +} +float Gia_ManPatGetOneQuo( Gia_Man_t * p, int RareLimit, Vec_Wrd_t * vPatterns, int nWords, int n ) +{ + float Total = 0; + Vec_Int_t * vRareCounts = Gia_SimCollectRare( p, vPatterns, RareLimit ); + Vec_Wrd_t * vSims, * vTemp = p->vSimsPi; + p->vSimsPi = vPatterns; + vSims = Gia_ManSimPatSim( p ); + p->vSimsPi = vTemp; + Total += Gia_ManPatGetQuo( p, vRareCounts, vSims, n, nWords ); + Vec_IntFree( vRareCounts ); + Vec_WrdFree( vSims ); + return Total; +} +void Gia_ManPatRareImprove( Gia_Man_t * p, int RareLimit, int fVerbose ) +{ + abctime clk = Abc_Clock(); + float FinalTotal, InitTotal; + int n, nRares = 0, nChanges = 0, nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + Vec_Wrd_t * vPatterns = p->vSimsPi; p->vSimsPi = NULL; + InitTotal = Gia_ManPatGetTotalQuo( p, RareLimit, vPatterns, nWords ); + for ( n = 0; n < 64*nWords; n++ ) + { + abctime clk = Abc_Clock(); + Vec_Int_t * vRareCounts = Gia_SimCollectRare( p, vPatterns, RareLimit ); + Vec_Int_t * vPat = Gia_ManPatCollectOne( p, vPatterns, n, nWords ); + Vec_Flt_t * vQuoIncs = Gia_SimQualityImpact( p, vPat, vRareCounts ); + Vec_Int_t * vBest = Gia_SimCollectBest( vQuoIncs ); + if ( fVerbose ) + { + float PatQuo = Gia_ManPatGetOneQuo( p, RareLimit, vPatterns, nWords, n ); + printf( "Pat %5d : Rare = %4d Cands = %3d Value = %8.3f Change = %8.3f ", + n, Vec_IntSize(vRareCounts)/2, vBest ? Vec_IntSize(vBest) : 0, + PatQuo, vBest ? Vec_FltEntry(vQuoIncs, Vec_IntEntry(vBest,0)) : 0 ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + } + if ( vBest != NULL ) + { + int VarBest = Vec_IntEntry( vBest, rand()%Vec_IntSize(vBest) ); + Abc_TtXorBit( Vec_WrdEntryP(vPatterns, VarBest*nWords), n ); + nChanges++; + } + nRares = Vec_IntSize(vRareCounts)/2; + Vec_IntFree( vRareCounts ); + Vec_IntFree( vPat ); + Vec_FltFree( vQuoIncs ); + Vec_IntFreeP( &vBest ); + } + if ( fVerbose ) + printf( "\n" ); + FinalTotal = Gia_ManPatGetTotalQuo( p, RareLimit, vPatterns, nWords ); + p->vSimsPi = vPatterns; + + printf( "Improved %d out of %d patterns using %d rare nodes: %.2f -> %.2f. ", + nChanges, 64*nWords, nRares, InitTotal, FinalTotal ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [Trying vectorized simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimTest( Gia_Man_t * pGia ) +{ + int n, nWords = 4; + Vec_Wrd_t * vSim1, * vSim2; + Vec_Wrd_t * vSim0 = Vec_WrdStartRandom( Gia_ManCiNum(pGia) * nWords ); + abctime clk = Abc_Clock(); + + pGia->vSimsPi = vSim0; + for ( n = 0; n < 20; n++ ) + { + vSim1 = Gia_ManSimPatSim( pGia ); + Vec_WrdFree( vSim1 ); + } + Abc_PrintTime( 1, "Time1", Abc_Clock() - clk ); + + clk = Abc_Clock(); + for ( n = 0; n < 20; n++ ) + { + vSim2 = Gia_ManSimPatSim2( pGia ); + Vec_WrdFree( vSim2 ); + } + Abc_PrintTime( 1, "Time2", Abc_Clock() - clk ); + + pGia->vSimsPi = NULL; + Vec_WrdFree( vSim0 ); +} + +/**Function************************************************************* + + Synopsis [Trying compiled simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSimGen( Gia_Man_t * pGia ) +{ + int nWords = 4; + Gia_Obj_t * pObj; + Vec_Wrd_t * vSim0 = Vec_WrdStartRandom( Gia_ManCiNum(pGia) * nWords ); + FILE * pFile = fopen( "comp_sim.c", "wb" ); + int i, k, Id; + fprintf( pFile, "#include \n" ); + fprintf( pFile, "#include \n" ); + fprintf( pFile, "#include \n" ); + fprintf( pFile, "int main()\n" ); + fprintf( pFile, "{\n" ); + fprintf( pFile, " clock_t clkThis = clock();\n" ); + fprintf( pFile, " unsigned long Res = 0;\n" ); + fprintf( pFile, " int i;\n" ); + fprintf( pFile, " srand(time(NULL));\n" ); + fprintf( pFile, " for ( i = 0; i < 2000; i++ )\n" ); + fprintf( pFile, " {\n" ); + for ( k = 0; k < nWords; k++ ) + fprintf( pFile, " unsigned long s%07d_%d = 0x%08x%08x;\n", 0, k, 0, 0 ); + Gia_ManForEachCiId( pGia, Id, i ) + { + //word * pSim = Vec_WrdEntryP(vSim0, i*nWords); + //unsigned * pSimU = (unsigned *)pSim; + for ( k = 0; k < nWords; k++ ) + fprintf( pFile, " unsigned long s%07d_%d = ((unsigned long)rand() << 48) | ((unsigned long)rand() << 32) | ((unsigned long)rand() << 16) | (unsigned long)rand();\n", Id, k ); + } + Gia_ManForEachAnd( pGia, pObj, Id ) + { + for ( k = 0; k < nWords; k++ ) + fprintf( pFile, " unsigned long s%07d_%d = %cs%07d_%d & %cs%07d_%d;\n", Id, k, + Gia_ObjFaninC0(pObj) ? '~' : ' ', Gia_ObjFaninId0(pObj, Id), k, + Gia_ObjFaninC1(pObj) ? ' ' : '~', Gia_ObjFaninId1(pObj, Id), k ); + } + Gia_ManForEachCoId( pGia, Id, i ) + { + pObj = Gia_ManObj(pGia, Id); + for ( k = 0; k < nWords; k++ ) + fprintf( pFile, " Res ^= %cs%07d_%d;\n", Gia_ObjFaninC0(pObj) ? '~' : ' ', Gia_ObjFaninId0(pObj, Id), k ); + } + Vec_WrdFree( vSim0 ); + fprintf( pFile, " }\n" ); + fprintf( pFile, " printf( \"Res = 0x%%08x \", (unsigned)Res );\n" ); + fprintf( pFile, " printf( \"Time = %%6.2f sec\\n\", (float)(clock() - clkThis)/CLOCKS_PER_SEC );\n" ); + fprintf( pFile, " return 1;\n" ); + fprintf( pFile, "}\n" ); + fclose( pFile ); +} + + +/**Function************************************************************* + + Synopsis [Trying vectorized simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSimTwo( Gia_Man_t * p0, Gia_Man_t * p1, int nWords, int nRounds, int TimeLimit, int fVerbose ) +{ + Vec_Wrd_t * vSim0, * vSim1, * vSim2; + abctime clk = Abc_Clock(); + int n, i, RetValue = 1; + int TimeStop = TimeLimit ? TimeLimit * CLOCKS_PER_SEC + Abc_Clock() : 0; // in CPU ticks + printf( "Simulating %d round with %d machine words.\n", nRounds, nWords ); + Abc_RandomW(0); + for ( n = 0; RetValue && n < nRounds; n++ ) + { + if ( TimeStop && Abc_Clock() > TimeStop ) + { + printf( "Computation timed out after %d seconds and %d rounds.\n", TimeLimit, n ); + break; + } + vSim0 = Vec_WrdStartRandom( Gia_ManCiNum(p0) * nWords ); + p0->vSimsPi = vSim0; + p1->vSimsPi = vSim0; + vSim1 = Gia_ManSimPatSim( p0 ); + vSim2 = Gia_ManSimPatSim( p1 ); + for ( i = 0; i < Gia_ManCoNum(p0); i++ ) + { + word * pSim1 = Vec_WrdEntryP(vSim1, Gia_ObjId(p0, Gia_ManCo(p0, i))*nWords); + word * pSim2 = Vec_WrdEntryP(vSim2, Gia_ObjId(p1, Gia_ManCo(p1, i))*nWords); + if ( memcmp(pSim1, pSim2, sizeof(word)*nWords) ) + { + printf( "Output %d failed simulation at round %d. ", i, n ); + RetValue = 0; + break; + } + } + Vec_WrdFree( vSim1 ); + Vec_WrdFree( vSim2 ); + Vec_WrdFree( vSim0 ); + p0->vSimsPi = NULL; + p1->vSimsPi = NULL; + } + if ( RetValue == 1 ) + printf( "Simulation did not detect a bug. " ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Serialization.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSim2ArrayOne( Vec_Wrd_t * vSimsPi, Vec_Int_t * vRes ) +{ + word * pInfo = Vec_WrdArray(vSimsPi); int w, i; + word * pCare = pInfo + Vec_WrdSize(vSimsPi); + Vec_IntClear( vRes ); + for ( w = 0; w < Vec_WrdSize(vSimsPi); w++ ) + if ( pCare[w] ) + for ( i = 0; i < 64; i++ ) + if ( Abc_TtGetBit(pCare, w*64+i) ) + Vec_IntPush( vRes, Abc_Var2Lit(w*64+i, Abc_TtGetBit(pInfo, w*64+i)) ); + Vec_IntPush( vRes, Vec_WrdSize(vSimsPi) ); +} +Vec_Wec_t * Gia_ManSim2Array( Vec_Ptr_t * vSims ) +{ + Vec_Wec_t * vRes = Vec_WecStart( Vec_PtrSize(vSims) ); + Vec_Int_t * vLevel; int i; + Vec_WecForEachLevel( vRes, vLevel, i ) + Gia_ManSim2ArrayOne( (Vec_Wrd_t *)Vec_PtrEntry(vSims, i), vLevel ); + return vRes; +} + +Vec_Wrd_t * Gia_ManArray2SimOne( Vec_Int_t * vRes ) +{ + int i, iLit, nWords = Vec_IntEntryLast(vRes); + Vec_Wrd_t * vSimsPi = Vec_WrdStart( 2*nWords ); + word * pInfo = Vec_WrdArray(vSimsPi); + word * pCare = pInfo + nWords; + Vec_IntPop( vRes ); + Vec_IntForEachEntry( vRes, iLit, i ) + { + Abc_TtXorBit( pCare, Abc_Lit2Var(iLit) ); + if ( Abc_LitIsCompl(iLit) ) + Abc_TtXorBit( pInfo, Abc_Lit2Var(iLit) ); + } + Vec_IntPush( vRes, nWords ); + Vec_WrdShrink( vSimsPi, Vec_WrdSize(vSimsPi)/2 ); + return vSimsPi; +} +Vec_Ptr_t * Gia_ManArray2Sim( Vec_Wec_t * vRes ) +{ + Vec_Ptr_t * vSims = Vec_PtrAlloc( Vec_WecSize(vRes) ); + Vec_Int_t * vLevel; int i; + Vec_WecForEachLevel( vRes, vLevel, i ) + Vec_PtrPush( vSims, Gia_ManArray2SimOne(vLevel) ); + return vSims; +} + +void Gia_ManSimArrayTest( Vec_Wrd_t * vSimsPi ) +{ + Vec_Ptr_t * vTemp = Vec_PtrAlloc( 2 ); + Vec_PtrPushTwo( vTemp, vSimsPi, vSimsPi ); + { + Vec_Wec_t * vRes = Gia_ManSim2Array( vTemp ); + Vec_WecDumpBin( "temp.sims", vRes, 1 ); + { + Vec_Wec_t * vRes = Vec_WecReadBin( "temp.sims", 1 ); + Vec_Ptr_t * vTemp2 = Gia_ManArray2Sim( vRes ); + Vec_Wrd_t * vSimsPi2 = (Vec_Wrd_t *)Vec_PtrEntry( vTemp2, 0 ); + Vec_Wrd_t * vSimsPi3 = (Vec_Wrd_t *)Vec_PtrEntry( vTemp2, 1 ); + + Abc_TtAnd( Vec_WrdArray(vSimsPi), Vec_WrdArray(vSimsPi), Vec_WrdArray(vSimsPi)+Vec_WrdSize(vSimsPi), Vec_WrdSize(vSimsPi), 0 ); + + vSimsPi->nSize *= 2; + vSimsPi2->nSize *= 2; + vSimsPi3->nSize *= 2; + Vec_WrdDumpHex( "test1.hex", vSimsPi, 1, 1 ); + Vec_WrdDumpHex( "test2.hex", vSimsPi2, 1, 1 ); + Vec_WrdDumpHex( "test3.hex", vSimsPi3, 1, 1 ); + vSimsPi->nSize /= 2; + vSimsPi2->nSize /= 2; + vSimsPi3->nSize /= 2; + + if ( Vec_WrdEqual( vSimsPi, vSimsPi2 ) ) + printf( "Success.\n" ); + else + printf( "Failure.\n" ); + if ( Vec_WrdEqual( vSimsPi, vSimsPi3 ) ) + printf( "Success.\n" ); + else + printf( "Failure.\n" ); + Vec_WrdFree( vSimsPi2 ); + Vec_WrdFree( vSimsPi3 ); + Vec_PtrFree( vTemp2 ); + Vec_WecFree( vRes ); + } + Vec_WecFree( vRes ); + } + Vec_PtrFree( vTemp ); +} + + +/**Function************************************************************* + + Synopsis [Serialization.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPtrWrdDumpBin( char * pFileName, Vec_Ptr_t * p, int fVerbose ) +{ + Vec_Wrd_t * vLevel; + int i, nSize, RetValue; + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for writing.\n", pFileName ); + return; + } + nSize = Vec_PtrSize(p); + RetValue = fwrite( &nSize, 1, sizeof(int), pFile ); + Vec_PtrForEachEntry( Vec_Wrd_t *, p, vLevel, i ) + { + nSize = Vec_WrdSize(vLevel); + RetValue += fwrite( &nSize, 1, sizeof(int), pFile ); + RetValue += fwrite( Vec_WrdArray(vLevel), 1, sizeof(word)*nSize, pFile ); + } + fclose( pFile ); + if ( fVerbose ) + printf( "Written %d arrays into file \"%s\".\n", Vec_PtrSize(p), pFileName ); +} +Vec_Ptr_t * Gia_ManPtrWrdReadBin( char * pFileName, int fVerbose ) +{ + Vec_Ptr_t * p = NULL; Vec_Wrd_t * vLevel; int i, nSize, RetValue; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for reading.\n", pFileName ); + return NULL; + } + fseek( pFile, 0, SEEK_END ); + nSize = ftell( pFile ); + if ( nSize == 0 ) + { + printf( "The input file is empty.\n" ); + fclose( pFile ); + return NULL; + } + if ( nSize % (int)sizeof(int) > 0 ) + { + printf( "Cannot read file with integers because it is not aligned at 4 bytes (remainder = %d).\n", nSize % (int)sizeof(int) ); + fclose( pFile ); + return NULL; + } + rewind( pFile ); + RetValue = fread( &nSize, 1, sizeof(int), pFile ); + assert( RetValue == 4 ); + p = Vec_PtrAlloc( nSize ); + for ( i = 0; i < nSize; i++ ) + Vec_PtrPush( p, Vec_WrdAlloc(100) ); + Vec_PtrForEachEntry( Vec_Wrd_t *, p, vLevel, i ) + { + RetValue = fread( &nSize, 1, sizeof(int), pFile ); + assert( RetValue == 4 ); + Vec_WrdFill( vLevel, nSize, 0 ); + RetValue = fread( Vec_WrdArray(vLevel), 1, sizeof(word)*nSize, pFile ); + assert( RetValue == 8*nSize ); + } + fclose( pFile ); + if ( fVerbose ) + printf( "Read %d arrays from file \"%s\".\n", Vec_PtrSize(p), pFileName ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManProcessBuffs( Gia_Man_t * pHie, Vec_Wrd_t * vSimsH, int nWords, Vec_Mem_t * vStore, Vec_Int_t * vLabels ) +{ + Vec_Int_t * vPoSigs = Vec_IntAlloc( Gia_ManBufNum(pHie) ); + Vec_Int_t * vMap; + Vec_Wec_t * vNodes = Vec_WecStart( Gia_ManBufNum(pHie) ); + Gia_Obj_t * pObj; int i, Sig, Value; + Gia_ManForEachBuf( pHie, pObj, i ) + { + word * pSim = Vec_WrdEntryP(vSimsH, Gia_ObjId(pHie, pObj)*nWords); + int fCompl = pSim[0] & 1; + if ( fCompl ) + Abc_TtNot( pSim, nWords ); + Vec_IntPush( vPoSigs, Vec_MemHashInsert(vStore, pSim) ); + if ( fCompl ) + Abc_TtNot( pSim, nWords ); + } + Vec_IntPrint( vPoSigs ); + vMap = Vec_IntStartFull( Vec_MemEntryNum(vStore) ); + Vec_IntForEachEntry( vPoSigs, Sig, i ) + { + assert( Vec_IntEntry(vMap, Sig) == -1 ); + Vec_IntWriteEntry( vMap, Sig, i ); + } + Vec_IntForEachEntry( vLabels, Sig, i ) + { + if ( Sig < 0 ) + continue; + Value = Vec_IntEntry(vMap, Sig); + if ( Value == -1 ) + continue; + assert( Value >= 0 && Value < Gia_ManBufNum(pHie) ); + Vec_WecPush( vNodes, Value, i ); + } + Vec_WecPrint( vNodes, 0 ); + Vec_WecFree( vNodes ); + Vec_IntFree( vMap ); + Vec_IntFree( vPoSigs ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManUpdateCoPhase( Gia_Man_t * pNew, Gia_Man_t * pOld ) +{ + Gia_Obj_t * pObj; int i; + Gia_ManSetPhase( pNew ); + Gia_ManSetPhase( pOld ); + Gia_ManForEachCo( pNew, pObj, i ) + if ( pObj->fPhase ^ Gia_ManCo(pOld, i)->fPhase ) + { + printf( "Updating out %d.\n", i ); + Gia_ObjFlipFaninC0( pObj ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCompareSims( Gia_Man_t * pHie, Gia_Man_t * pFlat, int nWords, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Vec_Wrd_t * vSims = pFlat->vSimsPi = pHie->vSimsPi = Vec_WrdStartRandom( Gia_ManCiNum(pFlat) * nWords ); + Vec_Wrd_t * vSims0 = Gia_ManSimPatSim( pFlat ); + Vec_Wrd_t * vSims1 = Gia_ManSimPatSim( pHie ); + Vec_Int_t * vLabels = Vec_IntStartFull( Gia_ManObjNum(pFlat) ); + Gia_Obj_t * pObj; int fCompl, Value, * pSpot, * pSpot2, i, nC0s = 0, nC1s = 0, nUnique = 0, nFound[3] = {0}, nBoundary = 0, nMatched = 0; + Vec_Mem_t * vStore = Vec_MemAlloc( nWords, 12 ); // 2^12 N-word entries per page + pFlat->vSimsPi = NULL; + pHie->vSimsPi = NULL; + Vec_WrdFree( vSims ); + + printf( "Comparing two AIGs using %d simulation words.\n", nWords ); + printf( "Hierarchical: " ); Gia_ManPrintStats( pHie, NULL ); + printf( "Flat: " ); Gia_ManPrintStats( pFlat, NULL ); + + Vec_MemHashAlloc( vStore, 1 << 12 ); + Gia_ManForEachCand( pFlat, pObj, i ) + { + word * pSim = Vec_WrdEntryP(vSims0, i*nWords); + nC0s += Abc_TtIsConst0(pSim, nWords); + nC1s += Abc_TtIsConst1(pSim, nWords); + fCompl = pSim[0] & 1; + if ( fCompl ) + Abc_TtNot( pSim, nWords ); + Value = Vec_MemHashInsert( vStore, pSim ); + if ( fCompl ) + Abc_TtNot( pSim, nWords ); + Vec_IntWriteEntry( vLabels, i, Value ); + } + nUnique = Vec_MemEntryNum( vStore ); + printf( "Simulating %d patterns through the second (flat) AIG leads to %d unique objects (%.2f %% out of %d). Const0 = %d. Const1 = %d.\n", + 64*nWords, nUnique, 100.0*nUnique/Gia_ManCandNum(pFlat), Gia_ManCandNum(pFlat), nC0s, nC1s ); + + assert( Gia_ManCiNum(pFlat) == Gia_ManCiNum(pHie) ); + Gia_ManForEachCand( pHie, pObj, i ) + { + word * pSim = Vec_WrdEntryP(vSims1, i*nWords); + pSpot = Vec_MemHashLookup( vStore, pSim ); + Abc_TtNot( pSim, nWords ); + pSpot2 = Vec_MemHashLookup( vStore, pSim ); + Abc_TtNot( pSim, nWords ); + nBoundary += Gia_ObjIsBuf(pObj); + if ( *pSpot != -1 || *pSpot2 != -1 ) + { + nMatched++; + continue; + } + //Extra_PrintBinary( stdout, (unsigned *)pSim, 64*nWords ); printf("\n"); + nFound[1] += Gia_ObjIsBuf(pObj); + nFound[2]++; + //if ( Gia_ObjIsBuf(pObj) ) + // printf( "%d(%d) ", i, nBoundary-1 ); + } + Gia_ManProcessBuffs( pHie, vSims1, nWords, vStore, vLabels ); + Vec_MemHashFree( vStore ); + Vec_MemFree( vStore ); + Vec_WrdFree( vSims0 ); + Vec_WrdFree( vSims1 ); + Vec_IntFree( vLabels ); + + printf( "The first (hierarchical) AIG has %d (%.2f %%) matches, %d (%.2f %%) mismatches, including %d (%.2f %%) on the boundary. ", + nMatched, 100.0*nMatched /Abc_MaxInt(1, Gia_ManCandNum(pHie)), + nFound[2], 100.0*nFound[2]/Abc_MaxInt(1, Gia_ManCandNum(pHie)), + nFound[1], 100.0*nFound[1]/Abc_MaxInt(1, nBoundary) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Gia_ManRelTfos( Gia_Man_t * p, Vec_Int_t * vObjs ) +{ + Gia_Obj_t * pObj; + Vec_Wec_t * vNodes = Vec_WecStart( Vec_IntSize(vObjs)+1 ); + Vec_Int_t * vSigns = Vec_IntStart( Gia_ManObjNum(p) ); + int n, k, i, iObj, * pSigns = Vec_IntArray(vSigns); + assert( Vec_IntSize(vObjs) < 32 ); + Vec_IntForEachEntry( vObjs, iObj, i ) + pSigns[iObj] |= 1 << i; + Gia_ManForEachAnd( p, pObj, i ) + { + if ( pSigns[i] == 0 ) + for ( n = 0; n < 2; n++ ) + pSigns[i] |= pSigns[Gia_ObjFaninId(pObj, i, n)]; + if ( pSigns[i] == 0 ) + continue; + Vec_WecPush( vNodes, Vec_IntSize(vObjs), i ); + for ( k = 0; k < Vec_IntSize(vObjs); k++ ) + if ( (pSigns[i] >> k) & 1 ) + Vec_WecPush( vNodes, k, i ); + } + Vec_IntFree( vSigns ); + return vNodes; +} +Vec_Wrd_t * Gia_ManRelDerive( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Wrd_t * vSims ) +{ + int nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); Gia_Obj_t * pObj; + int i, m, iVar, iMint = 0, nMints = 1 << Vec_IntSize(vObjs); + Vec_Wrd_t * vCopy = Vec_WrdDup(vSims); Vec_Int_t * vLevel; + Vec_Wrd_t * vRel = Vec_WrdStart( Gia_ManCoNum(p) * nWords * nMints ); + Vec_Wec_t * vNodes = Gia_ManRelTfos( p, vObjs ); + Vec_WecPrint( vNodes, 0 ); + Gia_ManForEachAnd( p, pObj, i ) + assert( pObj->fPhase == 0 ); + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + pObj->fPhase = 1; + vLevel = Vec_WecEntry( vNodes, Vec_IntSize(vObjs) ); + Gia_ManForEachObjVec( vLevel, p, pObj, i ) + if ( pObj->fPhase ) + Abc_TtClear( Vec_WrdEntryP(vCopy, Gia_ObjId(p, pObj)*nWords), nWords ); + else + Gia_ManSimPatSimAnd( p, Gia_ObjId(p, pObj), pObj, nWords, vCopy ); + for ( m = 0; m < nMints; m++ ) + { + Gia_ManForEachCo( p, pObj, i ) + { + word * pSimO = Vec_WrdEntryP(vCopy, Gia_ObjId(p, pObj)*nWords); + word * pSimF = Vec_WrdEntryP(vCopy, Gia_ObjFaninId0p(p, pObj)*nWords); + word * pSimR = Vec_WrdEntryP(vRel, (iMint*Gia_ManCoNum(p) + i)*nWords); + Abc_TtXor( pSimR, pSimF, pSimO, nWords, Gia_ObjFaninC0(pObj) ); + } + if ( m == nMints-1 ) + break; + iVar = Abc_TtSuppFindFirst( (m+1) ^ ((m+1) >> 1) ^ (m) ^ ((m) >> 1) ); + vLevel = Vec_WecEntry( vNodes, iVar ); + assert( Vec_IntEntry(vLevel, 0) == Vec_IntEntry(vObjs, iVar) ); + Abc_TtNot( Vec_WrdEntryP(vCopy, Vec_IntEntry(vObjs, iVar)*nWords), nWords ); + Gia_ManForEachObjVec( vLevel, p, pObj, i ) + if ( !pObj->fPhase ) + Gia_ManSimPatSimAnd( p, Gia_ObjId(p, pObj), pObj, nWords, vCopy ); + iMint ^= 1 << iVar; + } + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + pObj->fPhase = 0; + Vec_WrdFree( vCopy ); + Vec_WecFree( vNodes ); + return vRel; +} +Vec_Wrd_t * Gia_ManRelDerive2( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Wrd_t * vSims ) +{ + int nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); Gia_Obj_t * pObj; + int i, Id, m, Index, nMints = 1 << Vec_IntSize(vObjs); + Vec_Wrd_t * vPos, * vRel = Vec_WrdStart( Gia_ManCoNum(p) * nWords * nMints ); + for ( m = 0; m < nMints; m++ ) + { + Gia_Man_t * pNew = Gia_ManDup( p ); + Gia_ManForEachAnd( pNew, pObj, i ) + { + if ( (Index = Vec_IntFind(vObjs, Gia_ObjFaninId0(pObj, i))) >= 0 ) + pObj->iDiff0 = i, pObj->fCompl0 ^= (m >> Index) & 1; + if ( (Index = Vec_IntFind(vObjs, Gia_ObjFaninId1(pObj, i))) >= 0 ) + pObj->iDiff1 = i, pObj->fCompl1 ^= (m >> Index) & 1; + } + vPos = Gia_ManSimPatSimOut( pNew, p->vSimsPi, 1 ); + Gia_ManForEachCoId( p, Id, i ) + Abc_TtXor( Vec_WrdEntryP(vRel, (m*Gia_ManCoNum(p) + i)*nWords), Vec_WrdEntryP(vPos, i*nWords), Vec_WrdEntryP(vSims, Id*nWords), nWords, 0 ); + Vec_WrdFree( vPos ); + Gia_ManStop( pNew ); + } + return vRel; +} +void Gia_ManRelPrint( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Wrd_t * vSims, Vec_Wrd_t * vRel ) +{ + int w, nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + int i, Id, m, nMints = 1 << Vec_IntSize(vObjs); + printf( "Relation has %d inputs and %d outputs:\n", Gia_ManCiNum(p), Vec_IntSize(vObjs) ); + for ( w = 0; w < 64*nWords; w++ ) + { + Gia_ManForEachCiId( p, Id, i ) + printf( "%d", Abc_TtGetBit(Vec_WrdEntryP(vSims, Id*nWords), w) ); + printf( " " ); + Vec_IntForEachEntry( vObjs, Id, i ) + printf( "%d", Abc_TtGetBit(Vec_WrdEntryP(vSims, Id*nWords), w) ); + printf( " " ); + Gia_ManForEachCoId( p, Id, i ) + printf( "%d", Abc_TtGetBit(Vec_WrdEntryP(vSims, Id*nWords), w) ); + printf( " " ); + for ( m = 0; m < nMints; m++ ) + { + printf( " " ); + for ( i = 0; i < Vec_IntSize(vObjs); i++ ) + printf( "%d", (m >> i) & 1 ); + printf( "=" ); + Gia_ManForEachCoId( p, Id, i ) + printf( "%d", Abc_TtGetBit(Vec_WrdEntryP(vRel, (m*Gia_ManCoNum(p)+i)*nWords), w) ); + } + printf( "\n" ); + } +} +void Gia_ManRelPrint2( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Wrd_t * vSims, Vec_Wrd_t * vRel ) +{ + int w, nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + int i, Id, m, nMints = 1 << Vec_IntSize(vObjs); + int nWordsM = Abc_Truth6WordNum(Vec_IntSize(vObjs)); + Vec_Wrd_t * vRes = Vec_WrdStart( 64*nWords * nWordsM ); + printf( "Relation has %d inputs and %d outputs:\n", Gia_ManCiNum(p), Vec_IntSize(vObjs) ); + for ( w = 0; w < 64*nWords; w++ ) + { + int iMint = 0; + int nValid = 0; + Gia_ManForEachCiId( p, Id, i ) + printf( "%d", Abc_TtGetBit(Vec_WrdEntryP(vSims, Id*nWords), w) ); + printf( " " ); + Vec_IntForEachEntry( vObjs, Id, i ) + { + printf( "%d", Abc_TtGetBit(Vec_WrdEntryP(vSims, Id*nWords), w) ); + if ( Abc_TtGetBit(Vec_WrdEntryP(vSims, Id*nWords), w) ) + iMint |= 1 << i; + } + printf( " " ); + Gia_ManForEachCoId( p, Id, i ) + printf( "%d", Abc_TtGetBit(Vec_WrdEntryP(vSims, Id*nWords), w) ); + printf( " " ); + for ( m = 0; m < nMints; m++ ) + { + int Count = 0; + Gia_ManForEachCoId( p, Id, i ) + Count += Abc_TtGetBit(Vec_WrdEntryP(vRel, (m*Gia_ManCoNum(p)+i)*nWords), w); + printf( "%d", Count == 0 ); + nValid += Count > 0; + if ( Count == 0 ) + Abc_TtSetBit( Vec_WrdEntryP(vRes, w*nWordsM), m ); + } + printf( " " ); + for ( m = 0; m < nMints; m++ ) + printf( "%d", Abc_TtGetBit(Vec_WrdEntryP(vRes, w*nWordsM), m) ); + printf( " " ); + assert( Abc_TtGetBit(Vec_WrdEntryP(vRes, w*nWordsM), iMint) ); + for ( i = 0; i < Vec_IntSize(vObjs); i++ ) + if ( Abc_TtGetBit(Vec_WrdEntryP(vRes, w*nWordsM), iMint ^ (1 << i)) ) + printf( "-" ); + else + printf( "%d", (iMint >> i) & 1 ); + printf( " %d", nMints-nValid ); + printf( "\n" ); + } + Vec_WrdFree( vRes ); +} +Vec_Int_t * Gia_ManRelInitObjs() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + /* + Vec_IntPush( vRes, 33 ); + Vec_IntPush( vRes, 52 ); + Vec_IntPush( vRes, 53 ); + Vec_IntPush( vRes, 65 ); + Vec_IntPush( vRes, 79 ); + Vec_IntPush( vRes, 81 ); + */ + /* + Vec_IntPush( vRes, 60 ); + Vec_IntPush( vRes, 61 ); + Vec_IntPush( vRes, 71 ); + Vec_IntPush( vRes, 72 ); + */ + /* + Vec_IntPush( vRes, 65 ); + Vec_IntPush( vRes, 79 ); + Vec_IntPush( vRes, 81 ); + */ + Vec_IntPush( vRes, 52 ); + Vec_IntPush( vRes, 54 ); + Vec_IntPrint( vRes ); + return vRes; +} +void Gia_ManRelDeriveTest2( Gia_Man_t * p ) +{ + Vec_Int_t * vObjs = Gia_ManRelInitObjs(); + Vec_Wrd_t * vSims, * vRel, * vRel2; int nWords; + Vec_WrdFreeP( &p->vSimsPi ); + p->vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(p) ); + nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + vSims = Gia_ManSimPatSim( p ); + vRel = Gia_ManRelDerive( p, vObjs, vSims ); + vRel2 = Gia_ManRelDerive2( p, vObjs, vSims ); + //assert( !memcmp(vRel2->pArray, vRel->pArray, sizeof(word)*Vec_WrdSize(vRel)) ); + Gia_ManRelPrint2( p, vObjs, vSims, vRel ); + Vec_WrdFree( vRel2 ); + Vec_WrdFree( vRel ); + Vec_WrdFree( vSims ); + Vec_IntFree( vObjs ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManRelInitIns() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 12 ); + Vec_IntPush( vRes, 18 ); + Vec_IntPush( vRes, 21 ); + Vec_IntPush( vRes, 34 ); + Vec_IntPush( vRes, 45 ); + Vec_IntPush( vRes, 59 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitOuts() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 65 ); + Vec_IntPush( vRes, 66 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitMffc( Gia_Man_t * p, Vec_Int_t * vOuts ) +{ + Gia_Obj_t * pObj; int i; + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); + Vec_IntSort( vOuts, 0 ); + Gia_ManIncrementTravId( p ); + Gia_ManForEachObjVec( vOuts, p, pObj, i ) + Gia_ObjSetTravIdCurrent( p, pObj ); + Gia_ManIncrementTravId( p ); + Gia_ManForEachCo( p, pObj, i ) + if ( !Gia_ObjIsTravIdPrevious(p, Gia_ObjFanin0(pObj)) ) + Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin0(pObj) ); + Gia_ManForEachAndReverse( p, pObj, i ) + if ( Gia_ObjIsTravIdPrevious(p, pObj) ) + continue; + else if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + { + if ( !Gia_ObjIsTravIdPrevious(p, Gia_ObjFanin0(pObj)) ) + Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin0(pObj) ); + if ( !Gia_ObjIsTravIdPrevious(p, Gia_ObjFanin1(pObj)) ) + Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin1(pObj) ); + } + Gia_ManForEachAnd( p, pObj, i ) + if ( !Gia_ObjIsTravIdCurrent(p, pObj) ) + Vec_IntPush( vRes, i ); + printf( "MFFC: " ); + Vec_IntPrint( vRes ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitDivs( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vOuts ) +{ + Gia_Obj_t * pObj; int i; + Vec_Int_t * vMffc = Gia_ManRelInitMffc( p, vOuts ); + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); + Vec_IntSort( vIns, 0 ); + + Gia_ManIncrementTravId( p ); + Gia_ManForEachObjVec( vMffc, p, pObj, i ) + Gia_ObjSetTravIdCurrent( p, pObj ); + Vec_IntFree( vMffc ); + + Vec_IntPush( vRes, 0 ); + Vec_IntAppend( vRes, vIns ); + + Gia_ManIncrementTravId( p ); + Gia_ManForEachObjVec( vIns, p, pObj, i ) + Gia_ObjSetTravIdCurrent( p, pObj ); + + Gia_ManForEachAnd( p, pObj, i ) + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + continue; + else if ( Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin0(pObj)) && Gia_ObjIsTravIdCurrent(p, Gia_ObjFanin1(pObj)) ) + { + if ( !Gia_ObjIsTravIdPrevious(p, pObj) ) + Vec_IntPush( vRes, i ); + Gia_ObjSetTravIdCurrent( p, pObj ); + } + printf( "Divisors: " ); + Vec_IntPrint( vRes ); + return vRes; +} + +Vec_Int_t * Gia_ManRelDeriveSimple( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Int_t * vIns, Vec_Int_t * vOuts ) +{ + Vec_Int_t * vRes = Vec_IntStartFull( 1 << Vec_IntSize(vIns) ); + int w, nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + for ( w = 0; w < 64*nWords; w++ ) + { + int i, iObj, iMint = 0, iMint2 = 0; + Vec_IntForEachEntry( vIns, iObj, i ) + if ( Abc_TtGetBit(Vec_WrdEntryP(vSims, iObj*nWords), w) ) + iMint |= 1 << i; + if ( Vec_IntEntry(vRes, iMint) >= 0 ) + continue; + Vec_IntForEachEntry( vOuts, iObj, i ) + if ( Abc_TtGetBit(Vec_WrdEntryP(vSims, iObj*nWords), w) ) + iMint2 |= 1 << i; + Vec_IntWriteEntry( vRes, iMint, iMint2 ); + } + return vRes; +} + +void Gia_ManRelSolve( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Int_t * vIns, Vec_Int_t * vOuts, Vec_Int_t * vRel, Vec_Int_t * vDivs ) +{ + extern Mini_Aig_t * Exa4_ManGenTest( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes, int TimeOut, int fOnlyAnd, int fFancy, int fOrderNodes, int fUniqFans, int fVerbose, int fCard, char * pGuide ); + + int i, m, iObj, Entry, iMint = 0, nMints = Vec_IntSize(vRel) - Vec_IntCountEntry(vRel, -1); + Vec_Wrd_t * vSimsIn = Vec_WrdStart( nMints ); + Vec_Wrd_t * vSimsOut = Vec_WrdStart( nMints ); + int Entry0 = Vec_IntEntry( vRel, 0 ); + + word Value, Phase = 0; + int nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + Vec_IntForEachEntry( vDivs, iObj, i ) + if ( Vec_WrdEntry(vSims, iObj*nWords) & 1 ) + Phase |= 1 << i; + + assert( Entry0 >= 0 ); + printf( "Entry0 = %d\n", Entry0 ); + Entry0 ^= 1; +// for ( m = 0; m < nMints; m++ ) + Vec_IntForEachEntry( vRel, Entry, m ) + { + if ( Entry == -1 ) + continue; + Abc_TtSetBit( Vec_WrdEntryP(vSimsOut, iMint), Entry0 ^ Entry ); + + Value = 0; + Vec_IntForEachEntry( vDivs, iObj, i ) + if ( Abc_TtGetBit(Vec_WrdEntryP(vSims, iObj*nWords), m) ) + Abc_TtSetBit( &Value, i ); + Vec_WrdEntryP(vSimsOut, iMint)[0] = Value ^ Phase; + + iMint++; + } + assert( iMint == nMints ); + printf( "Created %d minterms.\n", iMint ); + Exa4_ManGenTest( vSimsIn, vSimsOut, Vec_IntSize(vIns), Vec_IntSize(vDivs), Vec_IntSize(vOuts), 10, 0, 0, 0, 0, 0, 1, 0, NULL ); + Vec_WrdFree( vSimsIn ); + Vec_WrdFree( vSimsOut ); +} +void Gia_ManRelDeriveTest( Gia_Man_t * p ) +{ + Vec_Int_t * vIns = Gia_ManRelInitIns(); + Vec_Int_t * vOuts = Gia_ManRelInitOuts(); + Vec_Wrd_t * vSims; Vec_Int_t * vRel, * vDivs; int nWords; + Vec_WrdFreeP( &p->vSimsPi ); + p->vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(p) ); + nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + vSims = Gia_ManSimPatSim( p ); + vRel = Gia_ManRelDeriveSimple( p, vSims, vIns, vOuts ); + vDivs = Gia_ManRelInitDivs( p, vIns, vOuts ); + //printf( "Neg = %d\n", Vec_IntCountEntry(vRel, -1) ); + + Gia_ManRelSolve( p, vSims, vIns, vOuts, vRel, vDivs ); + + Vec_IntFree( vDivs ); + Vec_IntPrint( vRel ); + Vec_IntFree( vRel ); + Vec_WrdFree( vSims ); + Vec_IntFree( vIns ); + Vec_IntFree( vOuts ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManRelOutsTfo_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vTfo ) +{ + if ( Gia_ObjIsTravIdPrevious(p, pObj) ) + return 1; + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return 0; + if ( pObj->fPhase ) + { + Gia_ObjSetTravIdPrevious(p, pObj); + return 1; + } + if ( Gia_ObjIsAnd(pObj) ) + { + int Val0 = Gia_ManRelOutsTfo_rec( p, Gia_ObjFanin0(pObj), vTfo ); + int Val1 = Gia_ManRelOutsTfo_rec( p, Gia_ObjFanin1(pObj), vTfo ); + if ( Val0 || Val1 ) + { + Gia_ObjSetTravIdPrevious(p, pObj); + Vec_IntPush( vTfo, Gia_ObjId(p, pObj) ); + return 1; + } + } + Gia_ObjSetTravIdCurrent(p, pObj); + return 0; +} +Vec_Int_t * Gia_ManRelOutsTfo( Gia_Man_t * p, Vec_Int_t * vOuts ) +{ + Gia_Obj_t * pObj; int i; + Vec_Int_t * vTfo = Vec_IntAlloc( 100 ); + Gia_ManIncrementTravId( p ); + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrentId( p, 0 ); + Gia_ManCleanPhase( p ); + Gia_ManForEachObjVec( vOuts, p, pObj, i ) + pObj->fPhase = 1; + Gia_ManForEachCo( p, pObj, i ) + if ( Gia_ManRelOutsTfo_rec( p, Gia_ObjFanin0(pObj), vTfo ) ) + Vec_IntPush( vTfo, Gia_ObjId(p, pObj) ); + Gia_ManForEachObjVec( vOuts, p, pObj, i ) + pObj->fPhase = 0; + //Vec_IntPrint( vTfo ); + return vTfo; +} +void Gia_ManSimPatSimTfo( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Int_t * vTfo ) +{ + Gia_Obj_t * pObj; + int i, nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + Gia_ManForEachObjVec( vTfo, p, pObj, i ) + if ( Gia_ObjIsAnd(pObj) ) + Gia_ManSimPatSimAnd( p, Gia_ObjId(p, pObj), pObj, nWords, vSims ); + else + Gia_ManSimPatSimPo( p, Gia_ObjId(p, pObj), pObj, nWords, vSims ); +} +void Gia_ManSimPatSimMiter( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Wrd_t * vSims2, word * pSims, int nWords ) +{ + Gia_Obj_t * pObj; int i; + Gia_ManForEachCo( p, pObj, i ) + Abc_TtOrXor( pSims, Vec_WrdEntryP(vSims, Gia_ObjId(p, pObj)*nWords), Vec_WrdEntryP(vSims2, Gia_ObjId(p, pObj)*nWords), nWords ); + Abc_TtNot( pSims, nWords ); +} +Vec_Wrd_t * Gia_ManRelDeriveRel( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vDivs, Vec_Int_t * vOuts, Vec_Wrd_t * vSims ) +{ + extern void Extra_BitMatrixTransposeP( Vec_Wrd_t * vSimsIn, int nWordsIn, Vec_Wrd_t * vSimsOut, int nWordsOut ); + int i, o, iObj, nMintsO = 1 << Vec_IntSize(vOuts); + int nWords = Vec_WrdSize(p->vSimsPi) / Gia_ManCiNum(p); + Vec_Wrd_t * vSims2 = Vec_WrdDup( vSims ); + Vec_Wrd_t * vRel = Vec_WrdStart( nWords * 64 ); + Vec_Wrd_t * vRel2 = Vec_WrdStart( nWords * 64 ); + Vec_Int_t * vTfo = Gia_ManRelOutsTfo( p, vOuts ); + assert( 1 + Vec_IntSize(vIns) + Vec_IntSize(vDivs) + nMintsO <= 64 ); + assert( Vec_WrdSize(p->vSimsPi) % Gia_ManCiNum(p) == 0 ); + Vec_IntForEachEntry( vIns, iObj, o ) + memcpy( Vec_WrdEntryP(vRel, nWords*o), Vec_WrdEntryP(vSims, iObj*nWords), sizeof(word)*nWords ); + Vec_IntForEachEntry( vDivs, iObj, o ) + memcpy( Vec_WrdEntryP(vRel, nWords*(Vec_IntSize(vIns)+o)), Vec_WrdEntryP(vSims, iObj*nWords), sizeof(word)*nWords ); + for ( o = 0; o < nMintsO; o++ ) + { + word * pRes = Vec_WrdEntryP(vRel, nWords*(Vec_IntSize(vIns)+Vec_IntSize(vDivs)+o)); + Vec_IntForEachEntry( vOuts, iObj, i ) + memset( Vec_WrdEntryP(vSims2, iObj*nWords), ((o >> i) & 1) ? 0xFF : 0x00, sizeof(word)*nWords ); + Gia_ManSimPatSimTfo( p, vSims2, vTfo ); + Gia_ManSimPatSimMiter( p, vSims, vSims2, pRes, nWords ); + } + Extra_BitMatrixTransposeP( vRel, nWords, vRel2, 1 ); + Vec_IntFree( vTfo ); + Vec_WrdFree( vSims2 ); + Vec_WrdFree( vRel ); + return vRel2; +} +void Gia_ManRelDeriveSims( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vDivs, Vec_Int_t * vOuts, Vec_Wrd_t * vSims, Vec_Wrd_t * vRel, Vec_Wrd_t ** pvSimsIn, Vec_Wrd_t ** pvSimsOut ) +{ + Vec_Wrd_t * vVals = Vec_WrdStartFull( 1 << Vec_IntSize(vIns) ); + Vec_Wrd_t * vSets = Vec_WrdStartFull( 1 << Vec_IntSize(vIns) ); + int m, nMints = 1 << Gia_ManCiNum(p), nCares = 0; + int nMintsI = 1 << Vec_IntSize(vIns); + int nShift = Vec_IntSize(vIns) + Vec_IntSize(vDivs); + int MaskI = Abc_Tt6Mask( Vec_IntSize(vIns) ); + int MaskD = Abc_Tt6Mask( nShift ); + for ( m = 0; m < nMints; m++ ) + { + word Sign = Vec_WrdEntry( vRel, m ); + *Vec_WrdEntryP( vVals, (int)Sign & MaskI ) = (int)Sign & MaskD; + *Vec_WrdEntryP( vSets, (int)Sign & MaskI ) &= Sign >> nShift; + } + for ( m = 0; m < nMintsI; m++ ) + if ( ~Vec_WrdEntry(vSets, m) ) + nCares++; + assert( *pvSimsIn == NULL ); + assert( *pvSimsOut == NULL ); + *pvSimsIn = Vec_WrdAlloc( nCares ); + *pvSimsOut = Vec_WrdAlloc( nCares ); + for ( m = 0; m < nMintsI; m++ ) + if ( ~Vec_WrdEntry(vSets, m) ) + { + Vec_WrdPush( *pvSimsIn, Vec_WrdEntry(vVals, m) << 1 ); + Vec_WrdPush( *pvSimsOut, Vec_WrdEntry(vSets, m) ); + } + assert( Vec_WrdSize(*pvSimsIn) == nCares ); + Vec_WrdFree( vSets ); + Vec_WrdFree( vVals ); +} + +int Gia_ManRelCheck_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( Gia_ObjIsTravIdPrevious(p, pObj) ) + return 1; + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return 0; + if ( pObj->fPhase ) + { + Gia_ObjSetTravIdPrevious(p, pObj); + return 1; + } + if ( Gia_ObjIsAnd(pObj) ) + { + int Val0 = Gia_ManRelCheck_rec( p, Gia_ObjFanin0(pObj) ); + int Val1 = Gia_ManRelCheck_rec( p, Gia_ObjFanin1(pObj) ); + if ( Val0 && Val1 ) + { + Gia_ObjSetTravIdPrevious(p, pObj); + return 1; + } + } + Gia_ObjSetTravIdCurrent(p, pObj); + return 0; +} +int Gia_ManRelCheck( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vDivs, Vec_Int_t * vOuts ) +{ + Gia_Obj_t * pObj; int i, Res = 1; + Gia_ManIncrementTravId( p ); + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrentId( p, 0 ); + Gia_ManCleanPhase( p ); + Gia_ManForEachObjVec( vIns, p, pObj, i ) + pObj->fPhase = 1; + Gia_ManForEachObjVec( vDivs, p, pObj, i ) + if ( !Gia_ManRelCheck_rec( p, pObj ) ) + Res = 0; + Gia_ManForEachObjVec( vOuts, p, pObj, i ) + if ( !Gia_ManRelCheck_rec( p, pObj ) ) + Res = 0; + Gia_ManForEachObjVec( vIns, p, pObj, i ) + pObj->fPhase = 0; + return Res; +} +void Gia_ManRelCompute( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vDivs, Vec_Int_t * vOuts, Vec_Wrd_t ** pvSimsIn, Vec_Wrd_t ** pvSimsOut ) +{ + Vec_Wrd_t * vSims, * vRel; + //Vec_Wrd_t * vSimsDiv = NULL, * vSimsOut = NULL; + + Vec_WrdFreeP( &p->vSimsPi ); + p->vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(p) ); + + if ( !Gia_ManRelCheck( p, vIns, vDivs, vOuts ) ) + printf( "Window is NOT consistent.\n" ); + else + printf( "Window is consistent.\n" ); + + vSims = Gia_ManSimPatSim( p ); + vRel = Gia_ManRelDeriveRel( p, vIns, vDivs, vOuts, vSims ); + + Gia_ManRelDeriveSims( p, vIns, vDivs, vOuts, vSims, vRel, pvSimsIn, pvSimsOut ); + + Vec_WrdFree( vRel ); + Vec_WrdFree( vSims ); + Vec_WrdFreeP( &p->vSimsPi ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +/* +Vec_Int_t * Gia_ManRelInitIns1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 22 ); + Vec_IntPush( vRes, 41 ); + Vec_IntPush( vRes, 45 ); + Vec_IntPush( vRes, 59 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitDivs1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 46 ); + Vec_IntPush( vRes, 47 ); + Vec_IntPush( vRes, 48 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitOuts1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 65 ); + Vec_IntPush( vRes, 66 ); + return vRes; +} +*/ + +Vec_Int_t * Gia_ManRelInitIns1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 22 ); + Vec_IntPush( vRes, 25 ); + Vec_IntPush( vRes, 42 ); + Vec_IntPush( vRes, 59 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitDivs1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 43 ); + Vec_IntPush( vRes, 44 ); + Vec_IntPush( vRes, 45 ); + Vec_IntPush( vRes, 46 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitOuts1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 60 ); + Vec_IntPush( vRes, 61 ); + return vRes; +} + +/* +Vec_Int_t * Gia_ManRelInitIns1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 22 ); + Vec_IntPush( vRes, 25 ); + Vec_IntPush( vRes, 42 ); + Vec_IntPush( vRes, 50 ); + Vec_IntPush( vRes, 67 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitDivs1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 43 ); + Vec_IntPush( vRes, 44 ); + Vec_IntPush( vRes, 45 ); + Vec_IntPush( vRes, 46 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitOuts1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 73 ); + Vec_IntPush( vRes, 74 ); + return vRes; +} +*/ + +/* +Vec_Int_t * Gia_ManRelInitIns1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 43 ); + Vec_IntPush( vRes, 46 ); + //Vec_IntPush( vRes, 49 ); + Vec_IntPush( vRes, 50 ); + Vec_IntPush( vRes, 67 ); + Vec_IntPush( vRes, 75 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitDivs1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + return vRes; +} +Vec_Int_t * Gia_ManRelInitOuts1() +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, 73 ); + Vec_IntPush( vRes, 86 ); + Vec_IntPush( vRes, 88 ); + return vRes; +} +*/ + +void Gia_ManRelDeriveTest1( Gia_Man_t * p ) +{ + extern void Exa6_WriteFile2( char * pFileName, int nVars, int nDivs, int nOuts, Vec_Wrd_t * vSimsDiv, Vec_Wrd_t * vSimsOut ); + + word Entry; int i; + Vec_Int_t * vIns = Gia_ManRelInitIns1(); + Vec_Int_t * vDivs = Gia_ManRelInitDivs1(); + Vec_Int_t * vOuts = Gia_ManRelInitOuts1(); + + Vec_Wrd_t * vSimsDiv = NULL, * vSimsOut = NULL; + Gia_ManRelCompute( p, vIns, vDivs, vOuts, &vSimsDiv, &vSimsOut ); + + printf( "Inputs:\n" ); + Vec_WrdForEachEntry( vSimsDiv, Entry, i ) + Abc_TtPrintBits( &Entry, 1 + Vec_IntSize(vIns) + Vec_IntSize(vDivs) ); + printf( "Outputs:\n" ); + Vec_WrdForEachEntry( vSimsOut, Entry, i ) + Abc_TtPrintBits( &Entry, 1 << Vec_IntSize(vOuts) ); + printf( "\n" ); + + Exa6_WriteFile2( "mul44_i5_n0_t3_s11.rel", Vec_IntSize(vIns), Vec_IntSize(vDivs), Vec_IntSize(vOuts), vSimsDiv, vSimsOut ); + + Vec_WrdFree( vSimsDiv ); + Vec_WrdFree( vSimsOut ); + + Vec_IntFree( vIns ); + Vec_IntFree( vDivs ); + Vec_IntFree( vOuts ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManChangeTest3( Gia_Man_t * p ) +{ + extern void Exa6_WriteFile2( char * pFileName, int nVars, int nDivs, int nOuts, Vec_Wrd_t * vSimsDiv, Vec_Wrd_t * vSimsOut ); + extern void Exa_ManExactPrint( Vec_Wrd_t * vSimsDiv, Vec_Wrd_t * vSimsOut, int nDivs, int nOuts ); + extern Mini_Aig_t * Exa_ManExactSynthesis6Int( Vec_Wrd_t * vSimsDiv, Vec_Wrd_t * vSimsOut, int nVars, int nDivs, int nOuts, int nNodes, int fOnlyAnd, int fVerbose, char * pFileName ); + extern Gia_Man_t * Gia_ManDupMini( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vDivs, Vec_Int_t * vOuts, Mini_Aig_t * pMini ); + + Gia_Man_t * pNew = NULL; + Mini_Aig_t * pMini = NULL; + Vec_Int_t * vIns = Gia_ManRelInitIns1(); + Vec_Int_t * vDivs = Gia_ManRelInitDivs1(); + Vec_Int_t * vOuts = Gia_ManRelInitOuts1(); + int nNodes = 4; + + Vec_Wrd_t * vSimsDiv = NULL, * vSimsOut = NULL; + Gia_ManRelCompute( p, vIns, vDivs, vOuts, &vSimsDiv, &vSimsOut ); + Exa_ManExactPrint( vSimsDiv, vSimsOut, 1 + Vec_IntSize(vIns) + Vec_IntSize(vDivs), Vec_IntSize(vOuts) ); + //Exa6_WriteFile2( "mul44_i%d_n%d_t%d_s%d.rel", Vec_IntSize(vIns), Vec_IntSize(vDivs), Vec_IntSize(vOuts), nNodes ); + pMini = Exa_ManExactSynthesis6Int( vSimsDiv, vSimsOut, Vec_IntSize(vIns), Vec_IntSize(vDivs), Vec_IntSize(vOuts), nNodes, 1, 1, NULL ); + if ( pMini ) + { + pNew = Gia_ManDupMini( p, vIns, vDivs, vOuts, pMini ); + Mini_AigStop( pMini ); + } + Vec_WrdFree( vSimsDiv ); + Vec_WrdFree( vSimsOut ); + + Vec_IntFree( vIns ); + Vec_IntFree( vDivs ); + Vec_IntFree( vOuts ); + return pNew; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Str_t * Gia_ManComputeRange( Gia_Man_t * p ) +{ + Vec_Wrd_t * vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(p) ); + Vec_Wrd_t * vSims = Gia_ManSimPatSimOut( p, vSimsPi, 1 ); + int n, nWords = Vec_WrdSize(vSimsPi) / Gia_ManCiNum(p); + int i, nLimit = Gia_ManCiNum(p) < 6 ? 1 << Gia_ManCiNum(p) : 64*nWords; + Vec_Str_t * vOut = Vec_StrAlloc( nLimit*(Gia_ManCoNum(p) + 3)+1 ); + assert( Vec_WrdSize(vSims) == nWords * Gia_ManCoNum(p) ); + for ( n = 0; n < nLimit; n++ ) + { + for ( i = 0; i < Gia_ManCoNum(p); i++ ) + Vec_StrPush( vOut, (char)('0' + Abc_TtGetBit(Vec_WrdEntryP(vSims, i*nWords), n)) ); + Vec_StrPush( vOut, ' ' ); + Vec_StrPush( vOut, '1' ); + Vec_StrPush( vOut, '\n' ); + } + Vec_StrPush( vOut, '\0' ); + Vec_WrdFree( vSims ); + Vec_WrdFree( vSimsPi ); + return vOut; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManComparePrint( Gia_Man_t * p, Gia_Man_t * q ) +{ + Vec_Wrd_t * vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(p) ); + Vec_Wrd_t * vSimsP = Gia_ManSimPatSimOut( p, vSimsPi, 0 ); + Vec_Wrd_t * vSimsQ = Gia_ManSimPatSimOut( q, vSimsPi, 0 ); + int i, k, nWords = Vec_WrdSize(vSimsPi) / Gia_ManCiNum(p), Count = 0; + Gia_Obj_t * pObjP, * pObjQ; + Gia_ManSetPhase( p ); + Gia_ManSetPhase( q ); + Gia_ManForEachObj( p, pObjP, i ) { + word * pSim = Vec_WrdEntryP( vSimsP, i * nWords ); + if ( pSim[0] & 1 ) Abc_TtNot( pSim, nWords ); + } + Gia_ManForEachObj( q, pObjQ, i ) { + word * pSim = Vec_WrdEntryP( vSimsQ, i * nWords ); + if ( pSim[0] & 1 ) Abc_TtNot( pSim, nWords ); + } + Gia_ManForEachAnd( q, pObjQ, i ) { + word * pSimQ = Vec_WrdEntryP( vSimsQ, i * nWords ); + int fFirst = 1; + Gia_ManForEachObj( p, pObjP, k ) { + word * pSimP = Vec_WrdEntryP( vSimsP, k * nWords ); + if ( !Abc_TtEqual(pSimQ, pSimP, nWords) ) + continue; + if ( fFirst ) { + printf( "%5d :", i ); + fFirst = 0; + Count++; + } + printf( " %5d(%d)", k, pObjQ->fPhase ^ pObjP->fPhase ); + } + if ( !fFirst ) + printf( "\n"); + } + printf( "Found %d equivalent nodes.\n", Count ); + Vec_WrdFree( vSimsP ); + Vec_WrdFree( vSimsQ ); + Vec_WrdFree( vSimsPi ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaSort.c b/yosys/abc/src/aig/gia/giaSort.c new file mode 100644 index 00000000000..d64a80c52a9 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaSort.c @@ -0,0 +1,273 @@ +/**CFile**************************************************************** + + FileName [gia.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [This is implementation of qsort in MiniSat.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int num_cmp1( int * x, int * y) { return ((*x) < (*y)) ? -1 : (((*x) > (*y)) ? 1 : 0); } +static int num_cmp2( int * x, int * y) { return (*x) < (*y); } +static inline void selectionsort(int* array, int size, int(*comp)(const void *, const void *)) +{ + int i, j, best_i; + int tmp; + for (i = 0; i < size-1; i++){ + best_i = i; + for (j = i+1; j < size; j++){ + if (comp(array + j, array + best_i)) + best_i = j; + } + tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp; + } +} +static void sort_rec(int* array, int size, int(*comp)(const void *, const void *)) +{ + if (size <= 15) + selectionsort(array, size, comp); + else{ + int pivot = array[size/2]; + int tmp; + int i = -1; + int j = size; + for(;;){ + do i++; while(comp(array + i, &pivot)); + do j--; while(comp(&pivot, array + j)); + if (i >= j) break; + tmp = array[i]; array[i] = array[j]; array[j] = tmp; + } + sort_rec(array , i , comp); + sort_rec(&array[i], size-i, comp); + } +} +void minisat_sort(int* array, int size, int(*comp)(const void *, const void *)) +{ + sort_rec(array,size,comp); +} + + +/**Function************************************************************* + + Synopsis [This is implementation of qsort in MiniSat.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void selectionsort2(int* array, int size) +{ + int i, j, best_i; + int tmp; + for (i = 0; i < size-1; i++){ + best_i = i; + for (j = i+1; j < size; j++){ + if (array[j] < array[best_i]) + best_i = j; + } + tmp = array[i]; array[i] = array[best_i]; array[best_i] = tmp; + } +} +static void sort_rec2(int* array, int size) +{ + if (size <= 15) + selectionsort2(array, size); + else{ + int pivot = array[size/2]; + int tmp; + int i = -1; + int j = size; + for(;;){ + do i++; while(array[i] < pivot); + do j--; while(pivot < array[j]); + if (i >= j) break; + tmp = array[i]; array[i] = array[j]; array[j] = tmp; + } + sort_rec2(array , i ); + sort_rec2(&array[i], size-i); + } +} +void minisat_sort2(int* array, int size) +{ + sort_rec2(array,size); +} + +/**Function************************************************************* + + Synopsis [This is implementation of qsort in MiniSat.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Gia_SortGetTest( int nSize ) +{ + int i, * pArray; + srand( 0 ); + pArray = ABC_ALLOC( int, nSize ); + for ( i = 0; i < nSize; i++ ) + pArray[i] = rand(); + return pArray; +} +void Gia_SortVerifySorted( int * pArray, int nSize ) +{ + int i; + for ( i = 1; i < nSize; i++ ) + assert( pArray[i-1] <= pArray[i] ); +} +void Gia_SortTest() +{ + int nSize = 100000000; + int * pArray; + abctime clk = Abc_Clock(); + + printf( "Sorting %d integers\n", nSize ); + pArray = Gia_SortGetTest( nSize ); +clk = Abc_Clock(); + qsort( pArray, (size_t)nSize, 4, (int (*)(const void *, const void *)) num_cmp1 ); +ABC_PRT( "qsort ", Abc_Clock() - clk ); + Gia_SortVerifySorted( pArray, nSize ); + ABC_FREE( pArray ); + + pArray = Gia_SortGetTest( nSize ); +clk = Abc_Clock(); + minisat_sort( pArray, nSize, (int (*)(const void *, const void *)) num_cmp2 ); +ABC_PRT( "minisat", Abc_Clock() - clk ); + Gia_SortVerifySorted( pArray, nSize ); + ABC_FREE( pArray ); + + pArray = Gia_SortGetTest( nSize ); +clk = Abc_Clock(); + minisat_sort2( pArray, nSize ); +ABC_PRT( "minisat with inlined comparison", Abc_Clock() - clk ); + Gia_SortVerifySorted( pArray, nSize ); + ABC_FREE( pArray ); +} + +/**Function************************************************************* + + Synopsis [This is implementation of qsort in MiniSat.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void selectionsort3(float* array, int* perm, int size) +{ + float tmpf; + int tmpi; + int i, j, best_i; + for (i = 0; i < size-1; i++){ + best_i = i; + for (j = i+1; j < size; j++){ + if (array[j] < array[best_i]) + best_i = j; + } + tmpf = array[i]; array[i] = array[best_i]; array[best_i] = tmpf; + tmpi = perm[i]; perm[i] = perm[best_i]; perm[best_i] = tmpi; + } +} +static void sort_rec3(float* array, int* perm, int size) +{ + if (size <= 15) + selectionsort3(array, perm, size); + else{ + float pivot = array[size/2]; + float tmpf; + int tmpi; + int i = -1; + int j = size; + for(;;){ + do i++; while(array[i] < pivot); + do j--; while(pivot < array[j]); + if (i >= j) break; + tmpf = array[i]; array[i] = array[j]; array[j] = tmpf; + tmpi = perm[i]; perm[i] = perm[j]; perm[j] = tmpi; + } + sort_rec3(array , perm, i ); + sort_rec3(&array[i], &perm[i], size-i); + } +} +void minisat_sort3(float* array, int* perm, int size) +{ + sort_rec3(array, perm, size); +} + +/**Function************************************************************* + + Synopsis [Sorts the array of floating point numbers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Gia_SortFloats( float * pArray, int * pPerm, int nSize ) +{ + int i; + if ( pPerm == NULL ) + { + pPerm = ABC_ALLOC( int, nSize ); + for ( i = 0; i < nSize; i++ ) + pPerm[i] = i; + } + minisat_sort3( pArray, pPerm, nSize ); +// for ( i = 1; i < nSize; i++ ) +// assert( pArray[i-1] <= pArray[i] ); + return pPerm; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaSpeedup.c b/yosys/abc/src/aig/gia/giaSpeedup.c new file mode 100644 index 00000000000..b9f4f03716b --- /dev/null +++ b/yosys/abc/src/aig/gia/giaSpeedup.c @@ -0,0 +1,806 @@ +/**CFile**************************************************************** + + FileName [gia.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "map/if/if.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Sorts the pins in the decreasing order of delays.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_LutDelayTraceSortPins( Gia_Man_t * p, int iObj, int * pPinPerm, float * pPinDelays ) +{ + int iFanin, i, j, best_i, temp; + assert( Gia_ObjIsLut(p, iObj) ); + // start the trivial permutation and collect pin delays + Gia_LutForEachFanin( p, iObj, iFanin, i ) + { + pPinPerm[i] = i; + pPinDelays[i] = Gia_ObjTimeArrival(p, iFanin); + } + // selection sort the pins in the decreasible order of delays + // this order will match the increasing order of LUT input pins + for ( i = 0; i < Gia_ObjLutSize(p, iObj)-1; i++ ) + { + best_i = i; + for ( j = i+1; j < Gia_ObjLutSize(p, iObj); j++ ) + if ( pPinDelays[pPinPerm[j]] > pPinDelays[pPinPerm[best_i]] ) + best_i = j; + if ( best_i == i ) + continue; + temp = pPinPerm[i]; + pPinPerm[i] = pPinPerm[best_i]; + pPinPerm[best_i] = temp; + } + // verify + assert( Gia_ObjLutSize(p, iObj) == 0 || pPinPerm[0] < Gia_ObjLutSize(p, iObj) ); + for ( i = 1; i < Gia_ObjLutSize(p, iObj); i++ ) + { + assert( pPinPerm[i] < Gia_ObjLutSize(p, iObj) ); + assert( pPinDelays[pPinPerm[i-1]] >= pPinDelays[pPinPerm[i]] ); + } +} + +/**Function************************************************************* + + Synopsis [Sorts the pins in the decreasing order of delays.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_LutWhereIsPin( Gia_Man_t * p, int iFanout, int iFanin, int * pPinPerm ) +{ + int i; + for ( i = 0; i < Gia_ObjLutSize(p, iFanout); i++ ) + if ( Gia_ObjLutFanin(p, iFanout, pPinPerm[i]) == iFanin ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Computes the arrival times for the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Gia_ObjComputeArrival( Gia_Man_t * p, int iObj, int fUseSorting ) +{ + If_LibLut_t * pLutLib = (If_LibLut_t *)p->pLutLib; + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + int k, iFanin, pPinPerm[32]; + float pPinDelays[32]; + float tArrival, * pDelays; + if ( Gia_ObjIsCi(pObj) ) + return Gia_ObjTimeArrival(p, iObj); + if ( Gia_ObjIsCo(pObj) ) + return Gia_ObjTimeArrival(p, Gia_ObjFaninId0p(p, pObj) ); + assert( Gia_ObjIsLut(p, iObj) ); + tArrival = -TIM_ETERNITY; + if ( pLutLib == NULL ) + { + Gia_LutForEachFanin( p, iObj, iFanin, k ) + if ( tArrival < Gia_ObjTimeArrival(p, iFanin) + 1.0 ) + tArrival = Gia_ObjTimeArrival(p, iFanin) + 1.0; + } + else if ( !pLutLib->fVarPinDelays ) + { + pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)]; + Gia_LutForEachFanin( p, iObj, iFanin, k ) + if ( tArrival < Gia_ObjTimeArrival(p, iFanin) + pDelays[0] ) + tArrival = Gia_ObjTimeArrival(p, iFanin) + pDelays[0]; + } + else + { + pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)]; + if ( fUseSorting ) + { + Gia_LutDelayTraceSortPins( p, iObj, pPinPerm, pPinDelays ); + Gia_LutForEachFanin( p, iObj, iFanin, k ) + if ( tArrival < Gia_ObjTimeArrival( p, Gia_ObjLutFanin(p,iObj,pPinPerm[k])) + pDelays[k] ) + tArrival = Gia_ObjTimeArrival( p, Gia_ObjLutFanin(p,iObj,pPinPerm[k])) + pDelays[k]; + } + else + { + Gia_LutForEachFanin( p, iObj, iFanin, k ) + if ( tArrival < Gia_ObjTimeArrival(p, iFanin) + pDelays[k] ) + tArrival = Gia_ObjTimeArrival(p, iFanin) + pDelays[k]; + } + } + if ( Gia_ObjLutSize(p, iObj) == 0 ) + tArrival = 0.0; + return tArrival; +} + + +/**Function************************************************************* + + Synopsis [Propagates the required times through the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Gia_ObjPropagateRequired( Gia_Man_t * p, int iObj, int fUseSorting ) +{ + If_LibLut_t * pLutLib = (If_LibLut_t *)p->pLutLib; + int k, iFanin, pPinPerm[32]; + float pPinDelays[32]; + float tRequired = 0.0; // Suppress "might be used uninitialized" + float * pDelays; + assert( Gia_ObjIsLut(p, iObj) ); + if ( pLutLib == NULL ) + { + tRequired = Gia_ObjTimeRequired( p, iObj) - (float)1.0; + Gia_LutForEachFanin( p, iObj, iFanin, k ) + if ( Gia_ObjTimeRequired(p, iFanin) > tRequired ) + Gia_ObjSetTimeRequired( p, iFanin, tRequired ); + } + else if ( !pLutLib->fVarPinDelays ) + { + pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)]; + tRequired = Gia_ObjTimeRequired(p, iObj) - pDelays[0]; + Gia_LutForEachFanin( p, iObj, iFanin, k ) + if ( Gia_ObjTimeRequired(p, iFanin) > tRequired ) + Gia_ObjSetTimeRequired( p, iFanin, tRequired ); + } + else + { + pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)]; + if ( fUseSorting ) + { + Gia_LutDelayTraceSortPins( p, iObj, pPinPerm, pPinDelays ); + Gia_LutForEachFanin( p, iObj, iFanin, k ) + { + tRequired = Gia_ObjTimeRequired( p, iObj) - pDelays[k]; + if ( Gia_ObjTimeRequired( p, Gia_ObjLutFanin(p, iObj,pPinPerm[k])) > tRequired ) + Gia_ObjSetTimeRequired( p, Gia_ObjLutFanin(p, iObj,pPinPerm[k]), tRequired ); + } + } + else + { + Gia_LutForEachFanin( p, iObj, iFanin, k ) + { + tRequired = Gia_ObjTimeRequired(p, iObj) - pDelays[k]; + if ( Gia_ObjTimeRequired(p, iFanin) > tRequired ) + Gia_ObjSetTimeRequired( p, iFanin, tRequired ); + } + } + } + return tRequired; +} + +/**Function************************************************************* + + Synopsis [Computes the delay trace of the given network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Gia_ManDelayTraceLut( Gia_Man_t * p ) +{ + int fUseSorting = 1; + If_LibLut_t * pLutLib = (If_LibLut_t *)p->pLutLib; + Vec_Int_t * vObjs; + Gia_Obj_t * pObj; + float tArrival, tArrivalCur, tRequired, tSlack; + int i, iObj; + + // get the library + if ( pLutLib && pLutLib->LutMax < Gia_ManLutSizeMax(p) ) + { + printf( "The max LUT size (%d) is less than the max fanin count (%d).\n", + pLutLib->LutMax, Gia_ManLutSizeMax(p) ); + return -TIM_ETERNITY; + } + + // initialize the arrival times + Gia_ManTimeStart( p ); + Gia_ManLevelNum( p ); + + // propagate arrival times + if ( p->pManTime ) + Tim_ManIncrementTravId( (Tim_Man_t *)p->pManTime ); + Gia_ManForEachObj( p, pObj, i ) + { + if ( !Gia_ObjIsCi(pObj) && !Gia_ObjIsCo(pObj) && !Gia_ObjIsLut(p, i) ) + continue; + tArrival = Gia_ObjComputeArrival( p, i, fUseSorting ); + if ( Gia_ObjIsCi(pObj) && p->pManTime ) + { + tArrival = Tim_ManGetCiArrival( (Tim_Man_t *)p->pManTime, Gia_ObjCioId(pObj) ); +//printf( "%.3f ", tArrival ); + } + if ( Gia_ObjIsCo(pObj) && p->pManTime ) + Tim_ManSetCoArrival( (Tim_Man_t *)p->pManTime, Gia_ObjCioId(pObj), tArrival ); + Gia_ObjSetTimeArrival( p, i, tArrival ); + } + + // get the latest arrival times + tArrival = -TIM_ETERNITY; + Gia_ManForEachCo( p, pObj, i ) + { + tArrivalCur = Gia_ObjTimeArrivalObj( p, Gia_ObjFanin0(pObj) ); + Gia_ObjSetTimeArrival( p, Gia_ObjId(p,pObj), tArrivalCur ); + if ( tArrival < tArrivalCur ) + tArrival = tArrivalCur; + } + + // initialize the required times + if ( p->pManTime ) + { + Tim_ManIncrementTravId( (Tim_Man_t *)p->pManTime ); + Tim_ManInitPoRequiredAll( (Tim_Man_t *)p->pManTime, tArrival ); + } + else + { + Gia_ManForEachCo( p, pObj, i ) + Gia_ObjSetTimeRequiredObj( p, pObj, tArrival ); + } + + // propagate the required times + vObjs = Gia_ManOrderReverse( p ); + Vec_IntForEachEntry( vObjs, iObj, i ) + { + pObj = Gia_ManObj(p, iObj); + if ( Gia_ObjIsLut(p, iObj) ) + { + Gia_ObjPropagateRequired( p, iObj, fUseSorting ); + } + else if ( Gia_ObjIsCi(pObj) ) + { + if ( p->pManTime ) + Tim_ManSetCiRequired( (Tim_Man_t *)p->pManTime, Gia_ObjCioId(pObj), Gia_ObjTimeRequired(p, iObj) ); + } + else if ( Gia_ObjIsCo(pObj) ) + { + if ( p->pManTime ) + { + tRequired = Tim_ManGetCoRequired( (Tim_Man_t *)p->pManTime, Gia_ObjCioId(pObj) ); + Gia_ObjSetTimeRequired( p, iObj, tRequired ); + } + if ( Gia_ObjTimeRequired(p, Gia_ObjFaninId0p(p, pObj)) > Gia_ObjTimeRequired(p, iObj) ) + Gia_ObjSetTimeRequired(p, Gia_ObjFaninId0p(p, pObj), Gia_ObjTimeRequired(p, iObj) ); + } + + // set slack for this object + tSlack = Gia_ObjTimeRequired(p, iObj) - Gia_ObjTimeArrival(p, iObj); + assert( tSlack + 0.01 > 0.0 ); + Gia_ObjSetTimeSlack( p, iObj, tSlack < 0.0 ? 0.0 : tSlack ); + } + Vec_IntFree( vObjs ); + return tArrival; +} + +#if 0 + +/**Function************************************************************* + + Synopsis [Computes the required times for the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Gia_ObjComputeRequired( Gia_Man_t * p, int iObj, int fUseSorting ) +{ + If_LibLut_t * pLutLib = p->pLutLib; + int pPinPerm[32]; + float pPinDelays[32]; + Gia_Obj_t * pFanout; + float tRequired, tDelay, * pDelays; + int k, iFanin; + if ( Gia_ObjIsCo(iObj) ) + return Gia_ObjTimeRequired( p, iObj); + tRequired = TIM_ETERNITY; + if ( pLutLib == NULL ) + { + Gia_ObjForEachFanout( iObj, pFanout, k ) + { + tDelay = Gia_ObjIsCo(pFanout)? 0.0 : 1.0; + if ( tRequired > Gia_ObjTimeRequired( p, pFanout) - tDelay ) + tRequired = Gia_ObjTimeRequired( p, pFanout) - tDelay; + } + } + else if ( !pLutLib->fVarPinDelays ) + { + Gia_ObjForEachFanout( iObj, pFanout, k ) + { + pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, pFanout)]; + tDelay = Gia_ObjIsCo(pFanout)? 0.0 : pDelays[0]; + if ( tRequired > Gia_ObjTimeRequired( p, pFanout) - tDelay ) + tRequired = Gia_ObjTimeRequired( p, pFanout) - tDelay; + } + } + else + { + if ( fUseSorting ) + { + Gia_ObjForEachFanout( iObj, pFanout, k ) + { + pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, pFanout)]; + Gia_LutDelayTraceSortPins( p, pFanout, pPinPerm, pPinDelays ); + iFanin = Gia_LutWhereIsPin( p, pFanout, iObj, pPinPerm ); + assert( Gia_ObjLutFanin( p, pFanout, pPinPerm[iFanin]) == iObj ); + tDelay = Gia_ObjIsCo(pFanout)? 0.0 : pDelays[iFanin]; + if ( tRequired > Gia_ObjTimeRequired( p, pFanout) - tDelay ) + tRequired = Gia_ObjTimeRequired( p, pFanout) - tDelay; + } + } + else + { + Gia_ObjForEachFanout( iObj, pFanout, k ) + { + pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, pFanout)]; + iFanin = Gia_ObjFindFanin( p, pFanout, iObj ); + assert( Gia_ObjLutFanin(p, pFanout, iFanin) == iObj ); + tDelay = Gia_ObjIsCo(pFanout)? 0.0 : pDelays[iFanin]; + if ( tRequired > Gia_ObjTimeRequired( p, pFanout) - tDelay ) + tRequired = Gia_ObjTimeRequired( p, pFanout) - tDelay; + } + } + } + return tRequired; +} + +/**Function************************************************************* + + Synopsis [Computes the arrival times for the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_LutVerifyTiming( Gia_Man_t * p ) +{ + int iObj; + float tArrival, tRequired; + int i; + Gia_LutForEachObj( p, iObj, i ) + { + if ( Gia_ObjIsCi(iObj) && Gia_ObjFanoutNum(iObj) == 0 ) + continue; + tArrival = Gia_ObjComputeArrival( p, iObj, 1 ); + tRequired = Gia_ObjComputeRequired( p, iObj, 1 ); + if ( !Gia_LutTimeEqual( tArrival, Gia_ObjTimeArrival( p, iObj), (float)0.01 ) ) + printf( "Gia_LutVerifyTiming(): Object %d has different arrival time (%.2f) from computed (%.2f).\n", + iObj->Id, Gia_ObjTimeArrival( p, iObj), tArrival ); + if ( !Gia_LutTimeEqual( tRequired, Gia_ObjTimeRequired( p, iObj), (float)0.01 ) ) + printf( "Gia_LutVerifyTiming(): Object %d has different required time (%.2f) from computed (%.2f).\n", + iObj->Id, Gia_ObjTimeRequired( p, iObj), tRequired ); + } + return 1; +} + +#endif + +/**Function************************************************************* + + Synopsis [Prints the delay trace for the given network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Gia_ManDelayTraceLutPrint( Gia_Man_t * p, int fVerbose ) +{ + If_LibLut_t * pLutLib = (If_LibLut_t *)p->pLutLib; + int i, Nodes, * pCounters; + float tArrival, tDelta, nSteps, Num; + // get the library + if ( pLutLib && pLutLib->LutMax < Gia_ManLutSizeMax(p) ) + { + printf( "The max LUT size (%d) is less than the max fanin count (%d).\n", + pLutLib->LutMax, Gia_ManLutSizeMax(p) ); + return -ABC_INFINITY; + } + // decide how many steps + nSteps = pLutLib ? 20 : Gia_ManLutLevel(p, NULL); + pCounters = ABC_ALLOC( int, nSteps + 1 ); + memset( pCounters, 0, sizeof(int)*(nSteps + 1) ); + // perform delay trace + tArrival = Gia_ManDelayTraceLut( p ); + tDelta = tArrival / nSteps; + // count how many nodes have slack in the corresponding intervals + Gia_ManForEachLut( p, i ) + { + if ( Gia_ObjLutSize(p, i) == 0 ) + continue; + Num = Gia_ObjTimeSlack(p, i) / tDelta; + if ( Num > nSteps ) + continue; + assert( Num >=0 && Num <= nSteps ); + pCounters[(int)Num]++; + } + // print the results + if ( fVerbose ) + { + printf( "Max delay = %6.2f. Delay trace using %s model:\n", tArrival, pLutLib? "LUT library" : "unit-delay" ); + Nodes = 0; + for ( i = 0; i < nSteps; i++ ) + { + Nodes += pCounters[i]; + printf( "%3d %s : %5d (%6.2f %%)\n", pLutLib? 5*(i+1) : i+1, + pLutLib? "%":"lev", Nodes, 100.0*Nodes/Gia_ManLutNum(p) ); + } + } + ABC_FREE( pCounters ); + Gia_ManTimeStop( p ); + return tArrival; +} + +/**Function************************************************************* + + Synopsis [Determines timing-critical edges of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Gia_LutDelayTraceTCEdges( Gia_Man_t * p, int iObj, float tDelta ) +{ + If_LibLut_t * pLutLib = (If_LibLut_t *)p->pLutLib; + int pPinPerm[32]; + float pPinDelays[32]; + float tRequired, * pDelays; + unsigned uResult = 0; + int k, iFanin; + tRequired = Gia_ObjTimeRequired( p, iObj ); + if ( pLutLib == NULL ) + { + Gia_LutForEachFanin( p, iObj, iFanin, k ) + if ( tRequired < Gia_ObjTimeArrival(p, iFanin) + 1.0 + tDelta ) + uResult |= (1 << k); + } + else if ( !pLutLib->fVarPinDelays ) + { + pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)]; + Gia_LutForEachFanin( p, iObj, iFanin, k ) + if ( tRequired < Gia_ObjTimeArrival(p, iFanin) + pDelays[0] + tDelta ) + uResult |= (1 << k); + } + else + { + pDelays = pLutLib->pLutDelays[Gia_ObjLutSize(p, iObj)]; + Gia_LutDelayTraceSortPins( p, iObj, pPinPerm, pPinDelays ); + Gia_LutForEachFanin( p, iObj, iFanin, k ) + if ( tRequired < Gia_ObjTimeArrival( p, Gia_ObjLutFanin(p, iObj,pPinPerm[k])) + pDelays[k] + tDelta ) + uResult |= (1 << pPinPerm[k]); + } + return uResult; +} + +/**Function************************************************************* + + Synopsis [Adds strashed nodes for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSpeedupObj_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return 1; + Gia_ObjSetTravIdCurrent( p, pObj ); + if ( Gia_ObjIsCi(pObj) ) + return 0; + assert( Gia_ObjIsAnd(pObj) ); + if ( !Gia_ManSpeedupObj_rec( p, Gia_ObjFanin0(pObj), vNodes ) ) + return 0; + if ( !Gia_ManSpeedupObj_rec( p, Gia_ObjFanin1(pObj), vNodes ) ) + return 0; + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Adds strashed nodes for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSpeedupObj( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vLeaves, Vec_Int_t * vTimes ) +{ + Vec_Int_t * vNodes; + Gia_Obj_t * pTemp = NULL; + int pCofs[32], nCofs, nSkip, i, k, iResult, iObj; + // mark the leaves + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); + Gia_ManForEachObjVec( vLeaves, p, pTemp, i ) + Gia_ObjSetTravIdCurrent( p, pTemp ); + // collect the AIG nodes + vNodes = Vec_IntAlloc( 100 ); + if ( !Gia_ManSpeedupObj_rec( p, pObj, vNodes ) ) + { + printf( "Bad node!!!\n" ); + Vec_IntFree( vNodes ); + return; + } + // derive cofactors + nCofs = (1 << Vec_IntSize(vTimes)); + for ( i = 0; i < nCofs; i++ ) + { + Gia_ManForEachObjVec( vLeaves, p, pTemp, k ) + pTemp->Value = Abc_Var2Lit( Gia_ObjId(p, pTemp), 0 ); + Gia_ManForEachObjVec( vTimes, p, pTemp, k ) + pTemp->Value = ((i & (1<Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pTemp), Gia_ObjFanin1Copy(pTemp) ); + pCofs[i] = pTemp->Value; + } + Vec_IntFree( vNodes ); + // collect the resulting tree + Gia_ManForEachObjVec( vTimes, p, pTemp, k ) + for ( nSkip = (1<pLutLib != NULL); + void * pTempTim = NULL; + unsigned * puTCEdges; + assert( Gia_ManHasMapping(p) ); + if ( !fUseLutLib && p->pManTime ) + { + pTempTim = p->pManTime; + p->pManTime = Tim_ManDup( (Tim_Man_t *)pTempTim, 1 ); + } + // perform delay trace + tArrival = Gia_ManDelayTraceLut( p ); + tDelta = fUseLutLib ? tArrival*Percentage/100.0 : 1.0; + if ( fVerbose ) + { + printf( "Max delay = %.2f. Delta = %.2f. ", tArrival, tDelta ); + printf( "Using %s model. ", fUseLutLib ? "LUT library" : "unit-delay" ); + if ( fUseLutLib ) + printf( "Percentage = %d. ", Percentage ); + printf( "\n" ); + } + // mark the timing critical nodes and edges + puTCEdges = ABC_CALLOC( unsigned, Gia_ManObjNum(p) ); + Gia_ManForEachLut( p, iObj ) + { + if ( Gia_ObjTimeSlack(p, iObj) >= tDelta ) + continue; + puTCEdges[iObj] = Gia_LutDelayTraceTCEdges( p, iObj, tDelta ); + } + if ( fVerbose ) + { + Counter = CounterRes = 0; + Gia_ManForEachLut( p, iObj ) + { + Gia_LutForEachFanin( p, iObj, iFanin, k ) + if ( !Gia_ObjIsCi(Gia_ManObj(p, iFanin)) && Gia_ObjTimeSlack(p, iFanin) < tDelta ) + Counter++; + CounterRes += Gia_WordCountOnes( puTCEdges[iObj] ); + } + printf( "Edges: Total = %7d. 0-slack = %7d. Critical = %7d. Ratio = %4.2f\n", + Gia_ManLutFaninCount(p), Counter, CounterRes, Counter? 1.0*CounterRes/Counter : 0.0 ); + } + + // start the resulting network + pNew = Gia_ManDup( p ); + Gia_ManHashStart( pNew ); + nNodesNew = 1000 + 3 * Gia_ManObjNum(pNew); + pNew->pNexts = ABC_CALLOC( int, nNodesNew ); + pNew->pReprs = ABC_CALLOC( Gia_Rpr_t, nNodesNew ); + for ( i = 0; i < nNodesNew; i++ ) + Gia_ObjSetRepr( pNew, i, GIA_VOID ); + + // collect nodes to be used for resynthesis + Counter = CounterRes = 0; + vTimeCries = Vec_IntAlloc( 16 ); + vTimeFanins = Vec_IntAlloc( 16 ); + Gia_ManForEachLut( p, iObj ) + { + if ( Gia_ObjTimeSlack(p, iObj) >= tDelta ) + continue; + // count the number of non-PI timing-critical nodes + nTimeCris = 0; + Gia_LutForEachFanin( p, iObj, iFanin, k ) + if ( !Gia_ObjIsCi(Gia_ManObj(p, iFanin)) && (puTCEdges[iObj] & (1< Degree) ) + if ( (Vec_IntSize(vTimeCries) == 0 || Vec_IntSize(vTimeCries) > Degree) ) + continue; + CounterRes++; + // collect second generation nodes + Vec_IntClear( vTimeFanins ); + Gia_LutForEachFanin( p, iObj, iFanin, k ) + { + if ( Gia_ObjIsCi(Gia_ManObj(p, iFanin)) ) + Vec_IntPushUnique( vTimeFanins, iFanin ); + else + Gia_LutForEachFanin( p, iFanin, iFanin2, k2 ) + Vec_IntPushUnique( vTimeFanins, iFanin2 ); + } + // print the results + if ( fVeryVerbose ) + { + printf( "%5d Node %5d : %d %2d %2d ", Counter, iObj, + nTimeCris, Vec_IntSize(vTimeCries), Vec_IntSize(vTimeFanins) ); + Gia_LutForEachFanin( p, iObj, iFanin, k ) + printf( "%d(%.2f)%s ", iFanin, Gia_ObjTimeSlack(p, iFanin), (puTCEdges[iObj] & (1< Degree ) + continue; + // order the fanins in the increasing order of criticalily + if ( Vec_IntSize(vTimeCries) > 1 ) + { + iFanin = Vec_IntEntry( vTimeCries, 0 ); + iFanin2 = Vec_IntEntry( vTimeCries, 1 ); + if ( Gia_ObjTimeSlack(p, iFanin) < Gia_ObjTimeSlack(p, iFanin2) ) + { + Vec_IntWriteEntry( vTimeCries, 0, iFanin2 ); + Vec_IntWriteEntry( vTimeCries, 1, iFanin ); + } + } + if ( Vec_IntSize(vTimeCries) > 2 ) + { + iFanin = Vec_IntEntry( vTimeCries, 1 ); + iFanin2 = Vec_IntEntry( vTimeCries, 2 ); + if ( Gia_ObjTimeSlack(p, iFanin) < Gia_ObjTimeSlack(p, iFanin2) ) + { + Vec_IntWriteEntry( vTimeCries, 1, iFanin2 ); + Vec_IntWriteEntry( vTimeCries, 2, iFanin ); + } + iFanin = Vec_IntEntry( vTimeCries, 0 ); + iFanin2 = Vec_IntEntry( vTimeCries, 1 ); + if ( Gia_ObjTimeSlack(p, iFanin) < Gia_ObjTimeSlack(p, iFanin2) ) + { + Vec_IntWriteEntry( vTimeCries, 0, iFanin2 ); + Vec_IntWriteEntry( vTimeCries, 1, iFanin ); + } + } + // add choice + Gia_ManSpeedupObj( pNew, p, Gia_ManObj(p,iObj), vTimeFanins, vTimeCries ); + // quit if the number of nodes is large + if ( Gia_ManObjNum(pNew) > nNodesNew - 100 ) + { + printf( "Speedup stopped adding choices because there was too many to add.\n" ); + break; + } + } + Gia_ManTimeStop( p ); + Vec_IntFree( vTimeCries ); + Vec_IntFree( vTimeFanins ); + ABC_FREE( puTCEdges ); + if ( fVerbose ) + printf( "Nodes: Total = %7d. 0-slack = %7d. Workable = %7d. Ratio = %4.2f\n", + Gia_ManLutNum(p), Counter, CounterRes, Counter? 1.0*CounterRes/Counter : 0.0 ); + if ( pTempTim ) + { + Tim_ManStop( (Tim_Man_t *)p->pManTime ); + p->pManTime = pTempTim; + } + // derive AIG with choices +//Gia_ManPrintStats( pNew, 0 ); + pTemp = Gia_ManEquivToChoices( pNew, 1 ); + Gia_ManStop( pNew ); +//Gia_ManPrintStats( pTemp, 0 ); +// pNew = Gia_ManDupOrderDfsChoices( pTemp ); +// Gia_ManStop( pTemp ); +//Gia_ManPrintStats( pNew, 0 ); +// return pNew; + return pTemp; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaSplit.c b/yosys/abc/src/aig/gia/giaSplit.c new file mode 100644 index 00000000000..2bdccfff99f --- /dev/null +++ b/yosys/abc/src/aig/gia/giaSplit.c @@ -0,0 +1,578 @@ +/**CFile**************************************************************** + + FileName [giaSplit.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Structural AIG splitting.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSplit.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/extra/extra.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Spl_Man_t_ Spl_Man_t; +struct Spl_Man_t_ +{ + // input data + Gia_Man_t * pGia; // user AIG with nodes marked + int iObj; // object ID + int Limit; // limit on AIG nodes + int fReverse; // enable reverse search + // intermediate + Vec_Bit_t * vMarksCIO; // CI/CO marks + Vec_Bit_t * vMarksIn; // input marks + Vec_Bit_t * vMarksNo; // node marks + Vec_Bit_t * vMarksAnd; // AND node marks + Vec_Int_t * vRoots; // nodes pointing to Nodes + Vec_Int_t * vNodes; // nodes used in the window + Vec_Int_t * vLeaves; // nodes pointed by Nodes + Vec_Int_t * vAnds; // AND nodes used in the window + // temporary + Vec_Int_t * vFanouts; // fanouts of the node + Vec_Int_t * vCands; // candidate nodes + Vec_Int_t * vInputs; // non-trivial inputs +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Transforming to the internal LUT representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Spl_ManToWecMapping( Gia_Man_t * p ) +{ + Vec_Wec_t * vMapping = Vec_WecStart( Gia_ManObjNum(p) ); + int Obj, Fanin, k; + assert( Gia_ManHasMapping(p) ); + Gia_ManForEachLut( p, Obj ) + Gia_LutForEachFanin( p, Obj, Fanin, k ) + Vec_WecPush( vMapping, Obj, Fanin ); + return vMapping; +} +Vec_Int_t * Spl_ManFromWecMapping( Gia_Man_t * p, Vec_Wec_t * vMap ) +{ + Vec_Int_t * vMapping, * vVec; int i, k, Obj; + assert( Gia_ManHasMapping2(p) ); + vMapping = Vec_IntAlloc( Gia_ManObjNum(p) + Vec_WecSizeSize(vMap) + 2*Vec_WecSizeUsed(vMap) ); + Vec_IntFill( vMapping, Gia_ManObjNum(p), 0 ); + Vec_WecForEachLevel( vMap, vVec, i ) + if ( Vec_IntSize(vVec) > 0 ) + { + Vec_IntWriteEntry( vMapping, i, Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, Vec_IntSize(vVec) ); + Vec_IntForEachEntry( vVec, Obj, k ) + Vec_IntPush( vMapping, Obj ); + Vec_IntPush( vMapping, i ); + } + assert( Vec_IntSize(vMapping) < 16 || Vec_IntSize(vMapping) == Vec_IntCap(vMapping) ); + return vMapping; +} + + +/**Function************************************************************* + + Synopsis [Creating manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Spl_Man_t * Spl_ManAlloc( Gia_Man_t * pGia, int Limit, int fReverse ) +{ + int i, iObj; + Spl_Man_t * p = ABC_CALLOC( Spl_Man_t, 1 ); + p->pGia = pGia; + p->Limit = Limit; + p->fReverse = fReverse; + // intermediate + p->vMarksCIO = Vec_BitStart( Gia_ManObjNum(pGia) ); + p->vMarksIn = Vec_BitStart( Gia_ManObjNum(pGia) ); + p->vMarksNo = Vec_BitStart( Gia_ManObjNum(pGia) ); + p->vMarksAnd = Vec_BitStart( Gia_ManObjNum(pGia) ); + p->vRoots = Vec_IntAlloc( 100 ); + p->vNodes = Vec_IntAlloc( 100 ); + p->vLeaves = Vec_IntAlloc( 100 ); + p->vAnds = Vec_IntAlloc( 100 ); + // temporary + p->vFanouts = Vec_IntAlloc( 100 ); + p->vCands = Vec_IntAlloc( 100 ); + p->vInputs = Vec_IntAlloc( 100 ); + // mark CIs/COs + Vec_BitWriteEntry( p->vMarksCIO, 0, 1 ); + Gia_ManForEachCiId( pGia, iObj, i ) + Vec_BitWriteEntry( p->vMarksCIO, iObj, 1 ); + Gia_ManForEachCoId( pGia, iObj, i ) + Vec_BitWriteEntry( p->vMarksCIO, iObj, 1 ); + // mapping + ABC_FREE( pGia->pRefs ); + Gia_ManCreateRefs( pGia ); + Gia_ManSetLutRefs( pGia ); + assert( Gia_ManHasMapping(pGia) ); + assert( !Gia_ManHasMapping2(pGia) ); + pGia->vMapping2 = Spl_ManToWecMapping( pGia ); + Vec_IntFreeP( &pGia->vMapping ); + // fanout + Gia_ManStaticFanoutStart( pGia ); + return p; +} +void Spl_ManStop( Spl_Man_t * p ) +{ + // fanout + Gia_ManStaticFanoutStop( p->pGia ); + // mapping + assert( !Gia_ManHasMapping(p->pGia) ); + assert( Gia_ManHasMapping2(p->pGia) ); + p->pGia->vMapping = Spl_ManFromWecMapping( p->pGia, p->pGia->vMapping2 ); + Vec_WecFreeP( &p->pGia->vMapping2 ); + // intermediate + Vec_BitFree( p->vMarksCIO ); + Vec_BitFree( p->vMarksIn ); + Vec_BitFree( p->vMarksNo ); + Vec_BitFree( p->vMarksAnd ); + Vec_IntFree( p->vRoots ); + Vec_IntFree( p->vNodes ); + Vec_IntFree( p->vLeaves ); + Vec_IntFree( p->vAnds ); + // temporary + Vec_IntFree( p->vFanouts ); + Vec_IntFree( p->vCands ); + Vec_IntFree( p->vInputs ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Takes Nodes and Marks. Returns Leaves and Roots.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Spl_ManWinFindLeavesRoots( Spl_Man_t * p ) +{ + Vec_Int_t * vVec; + int iObj, iFan, i, k; + // collect leaves +/* + Vec_IntClear( p->vLeaves ); + Gia_ManForEachLut2Vec( p->vNodes, p->pGia, vVec, iObj, i ) + { + assert( Vec_BitEntry(p->vMarksNo, iObj) ); + Vec_IntForEachEntry( vVec, iFan, k ) + if ( !Vec_BitEntry(p->vMarksNo, iFan) ) + { + Vec_BitWriteEntry(p->vMarksNo, iFan, 1); + Vec_IntPush( p->vLeaves, iFan ); + } + } + Vec_IntForEachEntry( p->vLeaves, iFan, i ) + Vec_BitWriteEntry(p->vMarksNo, iFan, 0); +*/ + Vec_IntClear( p->vLeaves ); + Vec_IntForEachEntry( p->vAnds, iObj, i ) + { + Gia_Obj_t * pObj = Gia_ManObj( p->pGia, iObj ); + assert( Vec_BitEntry(p->vMarksAnd, iObj) ); + iFan = Gia_ObjFaninId0( pObj, iObj ); + if ( !Vec_BitEntry(p->vMarksAnd, iFan) ) + { + assert( Gia_ObjIsLut2(p->pGia, iFan) || Vec_BitEntry(p->vMarksCIO, iFan) ); + Vec_BitWriteEntry(p->vMarksAnd, iFan, 1); + Vec_IntPush( p->vLeaves, iFan ); + } + iFan = Gia_ObjFaninId1( pObj, iObj ); + if ( !Vec_BitEntry(p->vMarksAnd, iFan) ) + { + assert( Gia_ObjIsLut2(p->pGia, iFan) || Vec_BitEntry(p->vMarksCIO, iFan) ); + Vec_BitWriteEntry(p->vMarksAnd, iFan, 1); + Vec_IntPush( p->vLeaves, iFan ); + } + } + Vec_IntForEachEntry( p->vLeaves, iFan, i ) + Vec_BitWriteEntry(p->vMarksAnd, iFan, 0); + + // collect roots + Vec_IntClear( p->vRoots ); + Gia_ManForEachLut2Vec( p->vNodes, p->pGia, vVec, iObj, i ) + Vec_IntForEachEntry( vVec, iFan, k ) + Gia_ObjLutRefDecId( p->pGia, iFan ); + Vec_IntForEachEntry( p->vAnds, iObj, i ) + if ( Gia_ObjLutRefNumId(p->pGia, iObj) ) + Vec_IntPush( p->vRoots, iObj ); + Gia_ManForEachLut2Vec( p->vNodes, p->pGia, vVec, iObj, i ) + Vec_IntForEachEntry( vVec, iFan, k ) + Gia_ObjLutRefIncId( p->pGia, iFan ); +} + + + + +/**Function************************************************************* + + Synopsis [Computes LUTs that are fanouts of the node outside of the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Spl_ManLutFanouts_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vFanouts, Vec_Bit_t * vMarksNo, Vec_Bit_t * vMarksCIO ) +{ + int iFanout, i; + if ( Vec_BitEntry(vMarksNo, iObj) || Vec_BitEntry(vMarksCIO, iObj) ) + return; + if ( Gia_ObjIsLut2(p, iObj) ) + { + Vec_BitWriteEntry( vMarksCIO, iObj, 1 ); + Vec_IntPush( vFanouts, iObj ); + return; + } + Gia_ObjForEachFanoutStaticId( p, iObj, iFanout, i ) + Spl_ManLutFanouts_rec( p, iFanout, vFanouts, vMarksNo, vMarksCIO ); +} +int Spl_ManLutFanouts( Gia_Man_t * p, int iObj, Vec_Int_t * vFanouts, Vec_Bit_t * vMarksNo, Vec_Bit_t * vMarksCIO ) +{ + int i, iFanout; + assert( Gia_ObjIsLut2(p, iObj) ); + Vec_IntClear( vFanouts ); + Gia_ObjForEachFanoutStaticId( p, iObj, iFanout, i ) + Spl_ManLutFanouts_rec( p, iFanout, vFanouts, vMarksNo, vMarksCIO ); + // clean up + Vec_IntForEachEntry( vFanouts, iFanout, i ) + Vec_BitWriteEntry( vMarksCIO, iFanout, 0 ); + return Vec_IntSize(vFanouts); +} + + +/**Function************************************************************* + + Synopsis [Returns the number of fanins beloning to the set.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Spl_ManCountMarkedFanins( Gia_Man_t * p, int iObj, Vec_Bit_t * vMarks ) +{ + int i, iFan, Count = 0; + Vec_Int_t * vFanins = Gia_ObjLutFanins2(p, iObj); + Vec_IntForEachEntry( vFanins, iFan, i ) + if ( Vec_BitEntry(vMarks, iFan) ) + Count++; + return Count; +} +int Spl_ManFindGoodCand( Spl_Man_t * p ) +{ + int i, iObj; + int Res = 0, InCount, InCountMax = -1; + // mark leaves + Vec_IntForEachEntry( p->vInputs, iObj, i ) + Vec_BitWriteEntry( p->vMarksIn, iObj, 1 ); + // find candidate with maximum input overlap + Vec_IntForEachEntry( p->vCands, iObj, i ) + { + InCount = Spl_ManCountMarkedFanins( p->pGia, iObj, p->vMarksIn ); + if ( InCountMax < InCount ) + { + InCountMax = InCount; + Res = iObj; + } + } + // unmark leaves + Vec_IntForEachEntry( p->vInputs, iObj, i ) + Vec_BitWriteEntry( p->vMarksIn, iObj, 0 ); + return Res; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Spl_ManFindOne( Spl_Man_t * p ) +{ + Vec_Int_t * vVec; + int nFanouts, iObj, iFan, i, k; + int Res = 0; + + // deref + Gia_ManForEachLut2Vec( p->vNodes, p->pGia, vVec, iObj, i ) + Vec_IntForEachEntry( vVec, iFan, k ) + Gia_ObjLutRefDecId( p->pGia, iFan ); + + // collect external nodes + if ( p->fReverse && (Vec_IntSize(p->vNodes) & 1) ) + { + Vec_IntForEachEntry( p->vNodes, iObj, i ) + { + if ( Gia_ObjLutRefNumId(p->pGia, iObj) == 0 ) + continue; + assert( Gia_ObjLutRefNumId(p->pGia, iObj) > 0 ); + if ( Gia_ObjLutRefNumId(p->pGia, iObj) >= 5 ) // skip nodes with high fanout! + continue; + nFanouts = Spl_ManLutFanouts( p->pGia, iObj, p->vFanouts, p->vMarksNo, p->vMarksCIO ); + if ( Gia_ObjLutRefNumId(p->pGia, iObj) == 1 && nFanouts == 1 ) + { + Res = Vec_IntEntry(p->vFanouts, 0); + goto finish; + } + //Vec_IntAppend( p->vCands, p->vFanouts ); + } + } + + // consider LUT inputs - get one that has no refs + Vec_IntClear( p->vCands ); + Vec_IntClear( p->vInputs ); + Gia_ManForEachLut2Vec( p->vNodes, p->pGia, vVec, iObj, i ) + Vec_IntForEachEntry( vVec, iFan, k ) + if ( !Vec_BitEntry(p->vMarksNo, iFan) && !Vec_BitEntry(p->vMarksCIO, iFan) && !Gia_ObjLutRefNumId(p->pGia, iFan) ) + { + Vec_IntPush( p->vCands, iFan ); + Vec_IntPush( p->vInputs, iFan ); + } + Res = Spl_ManFindGoodCand( p ); + if ( Res ) + goto finish; + + // collect candidates + Vec_IntClear( p->vCands ); + Vec_IntClear( p->vInputs ); + Gia_ManForEachLut2Vec( p->vNodes, p->pGia, vVec, iObj, i ) + Vec_IntForEachEntry( vVec, iFan, k ) + if ( !Vec_BitEntry(p->vMarksNo, iFan) && !Vec_BitEntry(p->vMarksCIO, iFan) ) + { + Vec_IntPush( p->vCands, iFan ); + Vec_IntPush( p->vInputs, iFan ); + } + + // all inputs have refs - collect external nodes + Vec_IntForEachEntry( p->vNodes, iObj, i ) + { + if ( Gia_ObjLutRefNumId(p->pGia, iObj) == 0 ) + continue; + assert( Gia_ObjLutRefNumId(p->pGia, iObj) > 0 ); + if ( Gia_ObjLutRefNumId(p->pGia, iObj) >= 5 ) // skip nodes with high fanout! + continue; + nFanouts = Spl_ManLutFanouts( p->pGia, iObj, p->vFanouts, p->vMarksNo, p->vMarksCIO ); + if ( Gia_ObjLutRefNumId(p->pGia, iObj) == 1 && nFanouts == 1 ) + { + Res = Vec_IntEntry(p->vFanouts, 0); + goto finish; + } + Vec_IntAppend( p->vCands, p->vFanouts ); + } + + // choose among not-so-good ones + Res = Spl_ManFindGoodCand( p ); + if ( Res ) + goto finish; + + // get the first candidate + if ( Res == 0 && Vec_IntSize(p->vCands) > 0 ) + Res = Vec_IntEntry( p->vCands, 0 ); + +finish: + // ref + Gia_ManForEachLut2Vec( p->vNodes, p->pGia, vVec, iObj, i ) + Vec_IntForEachEntry( vVec, iFan, k ) + Gia_ObjLutRefIncId( p->pGia, iFan ); + return Res; +} + + + +/**Function************************************************************* + + Synopsis [Computing window for one pivot node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Spl_ManLutMffcSize( Gia_Man_t * p, int iObj, Vec_Int_t * vTemp, Vec_Bit_t * vMarksAnd ) +{ + int iTemp, i, k = 0; + assert( Gia_ObjIsLut2(p, iObj) ); +//Vec_IntPrint( Gia_ObjLutFanins2(p, iObj) ); + Gia_ManIncrementTravId( p ); + Gia_ManCollectAnds( p, &iObj, 1, vTemp, Gia_ObjLutFanins2(p, iObj) ); + Vec_IntForEachEntry( vTemp, iTemp, i ) + if ( !Vec_BitEntry(vMarksAnd, iTemp) ) + Vec_IntWriteEntry( vTemp, k++, iTemp ); + Vec_IntShrink( vTemp, k ); + return k; +} +void Spl_ManAddNode( Spl_Man_t * p, int iPivot, Vec_Int_t * vCands ) +{ + int i, iObj; + Vec_IntPush( p->vNodes, iPivot ); + Vec_BitWriteEntry( p->vMarksNo, iPivot, 1 ); + Vec_IntAppend( p->vAnds, vCands ); + Vec_IntForEachEntry( vCands, iObj, i ) + Vec_BitWriteEntry( p->vMarksAnd, iObj, 1 ); +} +int Spl_ManComputeOne( Spl_Man_t * p, int iPivot ) +{ + int CountAdd, iObj, i; + assert( Gia_ObjIsLut2(p->pGia, iPivot) ); +//Gia_ManPrintCone2( p->pGia, Gia_ManObj(p->pGia, iPivot) ); + // assume it was previously filled in + Vec_IntForEachEntry( p->vNodes, iObj, i ) + Vec_BitWriteEntry( p->vMarksNo, iObj, 0 ); + Vec_IntForEachEntry( p->vAnds, iObj, i ) + Vec_BitWriteEntry( p->vMarksAnd, iObj, 0 ); + // double check that it is empty + //Gia_ManForEachLut2( p->pGia, iObj ) + // assert( !Vec_BitEntry(p->vMarksNo, iObj) ); + //Gia_ManForEachLut2( p->pGia, iObj ) + // assert( !Vec_BitEntry(p->vMarksAnd, iObj) ); + // clean arrays + Vec_IntClear( p->vNodes ); + Vec_IntClear( p->vAnds ); + // add root node + Spl_ManLutMffcSize( p->pGia, iPivot, p->vCands, p->vMarksAnd ); + Spl_ManAddNode( p, iPivot, p->vCands ); + if ( Vec_IntSize(p->vAnds) > p->Limit ) + return 0; + //printf( "%d ", iPivot ); + // add one node at a time + while ( (iObj = Spl_ManFindOne(p)) ) + { + assert( Gia_ObjIsLut2(p->pGia, iObj) ); + assert( !Vec_BitEntry(p->vMarksNo, iObj) ); + CountAdd = Spl_ManLutMffcSize( p->pGia, iObj, p->vCands, p->vMarksAnd ); + if ( Vec_IntSize(p->vAnds) + CountAdd > p->Limit ) + break; + Spl_ManAddNode( p, iObj, p->vCands ); + //printf( "+%d ", iObj ); + } + //printf( "\n" ); + Vec_IntSort( p->vNodes, 0 ); + Vec_IntSort( p->vAnds, 0 ); + Spl_ManWinFindLeavesRoots( p ); + Vec_IntSort( p->vLeaves, 0 ); + Vec_IntSort( p->vRoots, 0 ); + return 1; +} + +/**Function************************************************************* + + Synopsis [External procedures.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManComputeOneWin( Gia_Man_t * pGia, int iPivot, Vec_Int_t ** pvRoots, Vec_Int_t ** pvNodes, Vec_Int_t ** pvLeaves, Vec_Int_t ** pvAnds ) +{ + Spl_Man_t * p = (Spl_Man_t *)pGia->pSatlutWinman; + assert( p != NULL ); + if ( iPivot == -1 ) + { + Spl_ManStop( p ); + pGia->pSatlutWinman = NULL; + return 0; + } + if ( !Spl_ManComputeOne( p, iPivot ) ) + { + *pvRoots = NULL; + *pvNodes = NULL; + *pvLeaves = NULL; + *pvAnds = NULL; + return 0; + } + *pvRoots = p->vRoots; + *pvNodes = p->vNodes; + *pvLeaves = p->vLeaves; + *pvAnds = p->vAnds; + // Vec_IntPrint( p->vNodes ); + return Vec_IntSize(p->vAnds); +} +void Gia_ManComputeOneWinStart( Gia_Man_t * pGia, int nAnds, int fReverse ) +{ + assert( pGia->pSatlutWinman == NULL ); + pGia->pSatlutWinman = Spl_ManAlloc( pGia, nAnds, fReverse ); +} + +/**Function************************************************************* + + Synopsis [Testing procedure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Spl_ManComputeOneTest( Gia_Man_t * pGia ) +{ + int iLut, Count; + Gia_ManComputeOneWinStart( pGia, 64, 0 ); + Gia_ManForEachLut2( pGia, iLut ) + { + Vec_Int_t * vRoots, * vNodes, * vLeaves, * vAnds; + Count = Gia_ManComputeOneWin( pGia, iLut, &vRoots, &vNodes, &vLeaves, &vAnds ); + printf( "Obj = %6d : Leaf = %2d. Node = %2d. Root = %2d. AND = %3d.\n", + iLut, Vec_IntSize(vLeaves), Vec_IntSize(vNodes), Vec_IntSize(vRoots), Count ); + } + Gia_ManComputeOneWin( pGia, -1, NULL, NULL, NULL, NULL ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaStg.c b/yosys/abc/src/aig/gia/giaStg.c new file mode 100644 index 00000000000..9b6d49b600e --- /dev/null +++ b/yosys/abc/src/aig/gia/giaStg.c @@ -0,0 +1,528 @@ +/**CFile**************************************************************** + + FileName [gia.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: gia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/extra/extra.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintStateEncoding( Vec_Vec_t * vCodes, int nBits ) +{ + char * pBuffer; + Vec_Int_t * vVec; + int i, k, Bit; + pBuffer = ABC_ALLOC( char, nBits + 1 ); + pBuffer[nBits] = 0; + Vec_VecForEachLevelInt( vCodes, vVec, i ) + { + printf( "%6d : ", i+1 ); + memset( pBuffer, '-', (size_t)nBits ); + Vec_IntForEachEntry( vVec, Bit, k ) + { + assert( Bit < nBits ); + pBuffer[Bit] = '1'; + } + printf( "%s\n", pBuffer ); + } + ABC_FREE( pBuffer ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCreateOrGate( Gia_Man_t * p, Vec_Int_t * vLits ) +{ + if ( Vec_IntSize(vLits) == 0 ) + return 0; + while ( Vec_IntSize(vLits) > 1 ) + { + int i, k = 0, Lit1, Lit2, LitRes; + Vec_IntForEachEntryDouble( vLits, Lit1, Lit2, i ) + { + LitRes = Gia_ManHashOr( p, Lit1, Lit2 ); + Vec_IntWriteEntry( vLits, k++, LitRes ); + } + if ( Vec_IntSize(vLits) & 1 ) + Vec_IntWriteEntry( vLits, k++, Vec_IntEntryLast(vLits) ); + Vec_IntShrink( vLits, k ); + } + assert( Vec_IntSize(vLits) == 1 ); + return Vec_IntEntry(vLits, 0); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Vec_t * Gia_ManAssignCodes( int kHot, int nStates, int * pnBits ) +{ + Vec_Vec_t * vCodes; + int s, i1, i2, i3, i4, i5, nBits; + assert( nStates > 0 ); + assert( kHot >= 1 && kHot <= 5 ); + vCodes = Vec_VecStart( nStates ); + *pnBits = -1; + if ( kHot == 1 ) + { + for ( i1 = 0; i1 < nStates; i1++ ) + Vec_VecPushInt( vCodes, i1, i1 ); + *pnBits = nStates; + return vCodes; + } + if ( kHot == 2 ) + { + for ( nBits = kHot; nBits < ABC_INFINITY; nBits++ ) + if ( nBits * (nBits-1) / 2 >= nStates ) + break; + *pnBits = nBits; + s = 0; + for ( i1 = 0; i1 < nBits; i1++ ) + for ( i2 = i1 + 1; i2 < nBits; i2++ ) + { + Vec_VecPushInt( vCodes, s, i1 ); + Vec_VecPushInt( vCodes, s, i2 ); + if ( ++s == nStates ) + return vCodes; + } + } + if ( kHot == 3 ) + { + for ( nBits = kHot; nBits < ABC_INFINITY; nBits++ ) + if ( nBits * (nBits-1) * (nBits-2) / 6 >= nStates ) + break; + *pnBits = nBits; + s = 0; + for ( i1 = 0; i1 < nBits; i1++ ) + for ( i2 = i1 + 1; i2 < nBits; i2++ ) + for ( i3 = i2 + 1; i3 < nBits; i3++ ) + { + Vec_VecPushInt( vCodes, s, i1 ); + Vec_VecPushInt( vCodes, s, i2 ); + Vec_VecPushInt( vCodes, s, i3 ); + if ( ++s == nStates ) + return vCodes; + } + } + if ( kHot == 4 ) + { + for ( nBits = kHot; nBits < ABC_INFINITY; nBits++ ) + if ( nBits * (nBits-1) * (nBits-2) * (nBits-3) / 24 >= nStates ) + break; + *pnBits = nBits; + s = 0; + for ( i1 = 0; i1 < nBits; i1++ ) + for ( i2 = i1 + 1; i2 < nBits; i2++ ) + for ( i3 = i2 + 1; i3 < nBits; i3++ ) + for ( i4 = i3 + 1; i4 < nBits; i4++ ) + { + Vec_VecPushInt( vCodes, s, i1 ); + Vec_VecPushInt( vCodes, s, i2 ); + Vec_VecPushInt( vCodes, s, i3 ); + Vec_VecPushInt( vCodes, s, i4 ); + if ( ++s == nStates ) + return vCodes; + } + } + if ( kHot == 5 ) + { + for ( nBits = kHot; nBits < ABC_INFINITY; nBits++ ) + if ( nBits * (nBits-1) * (nBits-2) * (nBits-3) * (nBits-4) / 120 >= nStates ) + break; + *pnBits = nBits; + s = 0; + for ( i1 = 0; i1 < nBits; i1++ ) + for ( i2 = i1 + 1; i2 < nBits; i2++ ) + for ( i3 = i2 + 1; i3 < nBits; i3++ ) + for ( i4 = i3 + 1; i4 < nBits; i4++ ) + for ( i5 = i4 + 1; i5 < nBits; i5++ ) + { + Vec_VecPushInt( vCodes, s, i1 ); + Vec_VecPushInt( vCodes, s, i2 ); + Vec_VecPushInt( vCodes, s, i3 ); + Vec_VecPushInt( vCodes, s, i4 ); + Vec_VecPushInt( vCodes, s, i5 ); + if ( ++s == nStates ) + return vCodes; + } + } + assert( 0 ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManStgKHot( Vec_Int_t * vLines, int nIns, int nOuts, int nStates, int kHot, int fVerbose ) +{ + Gia_Man_t * p, * pTemp; + Vec_Int_t * vInMints, * vCurs, * vVec; + Vec_Vec_t * vLitsNext, * vLitsOuts, * vCodes; + int i, b, k, nBits, LitC, Lit; + assert( Vec_IntSize(vLines) % 4 == 0 ); + + // produce state encoding + vCodes = Gia_ManAssignCodes( kHot, nStates, &nBits ); + assert( Vec_VecSize(vCodes) == nStates ); + if ( fVerbose ) + Gia_ManPrintStateEncoding( vCodes, nBits ); + + // start manager + p = Gia_ManStart( 10000 ); + p->pName = Abc_UtilStrsav( "stg" ); + for ( i = 0; i < nIns + nBits; i++ ) + Gia_ManAppendCi(p); + + // create input minterms + Gia_ManHashAlloc( p ); + vInMints = Vec_IntAlloc( 1 << nIns ); + for ( i = 0; i < (1 << nIns); i++ ) + { + for ( Lit = 1, b = 0; b < nIns; b++ ) + Lit = Gia_ManHashAnd( p, Lit, Abc_Var2Lit( b+1, !((i >> b) & 1) ) ); + Vec_IntPush( vInMints, Lit ); + } + + // create current states + vCurs = Vec_IntAlloc( nStates ); + Vec_VecForEachLevelInt( vCodes, vVec, i ) + { + Lit = 1; + Vec_IntForEachEntry( vVec, b, k ) + { + assert( b >= 0 && b < nBits ); + Lit = Gia_ManHashAnd( p, Lit, Abc_Var2Lit(1+nIns+b, (b= 0 && iMint < (1<= 0 && iCur < nStates ); + assert( iNext >= 0 && iNext < nStates ); + assert( iOut >= 0 && iOut < (1<> b) & 1 ) + Vec_VecPushInt( vLitsOuts, b, LitC ); + } + Vec_IntFree( vInMints ); + Vec_IntFree( vCurs ); + Vec_VecFree( vCodes ); + + // create POs + Vec_VecForEachLevelInt( vLitsOuts, vVec, b ) + Gia_ManAppendCo( p, Gia_ManCreateOrGate(p, vVec) ); + Vec_VecFree( vLitsOuts ); + + // create next states + Vec_VecForEachLevelInt( vLitsNext, vVec, b ) + Gia_ManAppendCo( p, Abc_LitNotCond( Gia_ManCreateOrGate(p, vVec), (bpName = Abc_UtilStrsav( "stg" ); + for ( i = 0; i < nIns + nStates; i++ ) + Gia_ManAppendCi(p); + + // create input minterms + Gia_ManHashAlloc( p ); + vInMints = Vec_IntAlloc( 1 << nIns ); + for ( i = 0; i < (1 << nIns); i++ ) + { + for ( Lit = 1, b = 0; b < nIns; b++ ) + Lit = Gia_ManHashAnd( p, Lit, Abc_Var2Lit( b+1, !((i >> b) & 1) ) ); + Vec_IntPush( vInMints, Lit ); + } + + // create current states + vCurs = Vec_IntAlloc( nStates ); + for ( i = 0; i < nStates; i++ ) + Vec_IntPush( vCurs, Abc_Var2Lit( 1+nIns+i, !i ) ); + + // go through the lines + vLitsNext = Vec_VecStart( nStates ); + vLitsOuts = Vec_VecStart( nOuts ); + for ( i = 0; i < Vec_IntSize(vLines); ) + { + int iMint = Vec_IntEntry(vLines, i++); + int iCur = Vec_IntEntry(vLines, i++) - 1; + int iNext = Vec_IntEntry(vLines, i++) - 1; + int iOut = Vec_IntEntry(vLines, i++); + assert( iMint >= 0 && iMint < (1<= 0 && iCur < nStates ); + assert( iNext >= 0 && iNext < nStates ); + assert( iOut >= 0 && iOut < (1<> b) & 1 ) + { +// Lit = Gia_ManHashOr( p, LitC, Vec_IntEntry(vOuts, b) ); +// Vec_IntWriteEntry( vOuts, b, Lit ); + Vec_VecPushInt( vLitsOuts, b, LitC ); + } + } + Vec_IntFree( vInMints ); + Vec_IntFree( vCurs ); + + // create POs + Vec_VecForEachLevelInt( vLitsOuts, vVec, i ) + Gia_ManAppendCo( p, Gia_ManCreateOrGate(p, vVec) ); + Vec_VecFree( vLitsOuts ); + + // create next states + Vec_VecForEachLevelInt( vLitsNext, vVec, i ) + Gia_ManAppendCo( p, Abc_LitNotCond( Gia_ManCreateOrGate(p, vVec), !i ) ); + Vec_VecFree( vLitsNext ); + + Gia_ManSetRegNum( p, nStates ); + Gia_ManHashStop( p ); + + p = Gia_ManCleanup( pTemp = p ); + Gia_ManStop( pTemp ); + assert( !Gia_ManHasDangling(p) ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManStgPrint( FILE * pFile, Vec_Int_t * vLines, int nIns, int nOuts, int nStates ) +{ + int i, nDigits = Abc_Base10Log( nStates ); + assert( Vec_IntSize(vLines) % 4 == 0 ); + for ( i = 0; i < Vec_IntSize(vLines); i += 4 ) + { + int iMint = Vec_IntEntry(vLines, i ); + int iCur = Vec_IntEntry(vLines, i+1) - 1; + int iNext = Vec_IntEntry(vLines, i+2) - 1; + int iOut = Vec_IntEntry(vLines, i+3); + assert( iMint >= 0 && iMint < (1<= 0 && iCur < nStates ); + assert( iNext >= 0 && iNext < nStates ); + assert( iOut >= 0 && iOut < (1< +#define unlink _unlink +#else +#include +#endif + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Processing on a single core.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_StochProcessSingle( Gia_Man_t * p, char * pScript, int Rand, int TimeSecs ) +{ + Gia_Man_t * pTemp, * pNew = Gia_ManDup( p ); + Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), Gia_ManDup(p) ); + if ( Abc_FrameIsBatchMode() ) + { + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), pScript) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pScript ); + return NULL; + } + } + else + { + Abc_FrameSetBatchMode( 1 ); + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), pScript) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pScript ); + return NULL; + } + Abc_FrameSetBatchMode( 0 ); + } + pTemp = Abc_FrameReadGia(Abc_FrameGetGlobalFrame()); + if ( Gia_ManAndNum(pNew) > Gia_ManAndNum(pTemp) ) + { + Gia_ManStop( pNew ); + pNew = Gia_ManDup( pTemp ); + } + return pNew; +} +void Gia_StochProcessArray( Vec_Ptr_t * vGias, char * pScript, int TimeSecs, int fVerbose ) +{ + Gia_Man_t * pGia, * pNew; int i; + Vec_Int_t * vRands = Vec_IntAlloc( Vec_PtrSize(vGias) ); + Abc_Random(1); + for ( i = 0; i < Vec_PtrSize(vGias); i++ ) + Vec_IntPush( vRands, Abc_Random(0) % 0x1000000 ); + Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) + { + pNew = Gia_StochProcessSingle( pGia, pScript, Vec_IntEntry(vRands, i), TimeSecs ); + Gia_ManStop( pGia ); + Vec_PtrWriteEntry( vGias, i, pNew ); + } + Vec_IntFree( vRands ); +} + +/**Function************************************************************* + + Synopsis [Processing on many cores.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_StochProcessOne( Gia_Man_t * p, char * pScript, int Rand, int TimeSecs ) +{ + Gia_Man_t * pNew; + char FileName[100], Command[1000]; + sprintf( FileName, "%06x.aig", Rand ); + Gia_AigerWrite( p, FileName, 0, 0, 0 ); + sprintf( Command, "./abc -q \"&read %s; %s; &write %s\"", FileName, pScript, FileName ); +#if defined(__wasm) + if ( 1 ) +#else + if ( system( (char *)Command ) ) +#endif + { + fprintf( stderr, "The following command has returned non-zero exit status:\n" ); + fprintf( stderr, "\"%s\"\n", (char *)Command ); + fprintf( stderr, "Sorry for the inconvenience.\n" ); + fflush( stdout ); + unlink( FileName ); + return Gia_ManDup(p); + } + pNew = Gia_AigerRead( FileName, 0, 0, 0 ); + unlink( FileName ); + if ( pNew && Gia_ManAndNum(pNew) < Gia_ManAndNum(p) ) + return pNew; + Gia_ManStopP( &pNew ); + return Gia_ManDup(p); +} + +/**Function************************************************************* + + Synopsis [Generic concurrent processing.] + + Description [User-defined problem-specific data and the way to process it.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +typedef struct StochSynData_t_ +{ + Gia_Man_t * pIn; + Gia_Man_t * pOut; + char * pScript; + int Rand; + int TimeOut; +} StochSynData_t; + +int Gia_StochProcess1( void * p ) +{ + StochSynData_t * pData = (StochSynData_t *)p; + assert( pData->pIn != NULL ); + assert( pData->pOut == NULL ); + pData->pOut = Gia_StochProcessOne( pData->pIn, pData->pScript, pData->Rand, pData->TimeOut ); + return 1; +} + +void Gia_StochProcess( Vec_Ptr_t * vGias, char * pScript, int nProcs, int TimeSecs, int fVerbose ) +{ + if ( nProcs <= 2 ) { + if ( fVerbose ) + printf( "Running non-concurrent synthesis.\n" ), fflush(stdout); + Gia_StochProcessArray( vGias, pScript, TimeSecs, fVerbose ); + return; + } + StochSynData_t * pData = ABC_CALLOC( StochSynData_t, Vec_PtrSize(vGias) ); + Vec_Ptr_t * vData = Vec_PtrAlloc( Vec_PtrSize(vGias) ); + Gia_Man_t * pGia; int i; + Abc_Random(1); + Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) { + pData[i].pIn = pGia; + pData[i].pOut = NULL; + pData[i].pScript = pScript; + pData[i].Rand = Abc_Random(0) % 0x1000000; + pData[i].TimeOut = TimeSecs; + Vec_PtrPush( vData, pData+i ); + } + if ( fVerbose ) + printf( "Running concurrent synthesis with %d processes.\n", nProcs ), fflush(stdout); + Util_ProcessThreads( Gia_StochProcess1, vData, nProcs, TimeSecs, fVerbose ); + // replace old AIGs by new AIGs + Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) { + Gia_ManStop( pGia ); + Vec_PtrWriteEntry( vGias, i, pData[i].pOut ); + } + Vec_PtrFree( vData ); + ABC_FREE( pData ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDupMapping( Gia_Man_t * pNew, Gia_Man_t * p ) +{ + Gia_Obj_t * pObj, * pFanin; int i, k; + Vec_Int_t * vMapping = p->vMapping ? Vec_IntAlloc( Vec_IntSize(p->vMapping) ) : NULL; + if ( p->vMapping == NULL ) + return; + Vec_IntFill( vMapping, Gia_ManObjNum(p), 0 ); + Gia_ManForEachLut( p, i ) + { + pObj = Gia_ManObj( p, i ); + Vec_IntWriteEntry( vMapping, Abc_Lit2Var(pObj->Value), Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, Gia_ObjLutSize(p, i) ); + Gia_LutForEachFaninObj( p, i, pFanin, k ) + Vec_IntPush( vMapping, Abc_Lit2Var(pFanin->Value) ); + Vec_IntPush( vMapping, Abc_Lit2Var(pObj->Value) ); + } + pNew->vMapping = vMapping; +} +Gia_Man_t * Gia_ManDupWithMapping( Gia_Man_t * pGia ) +{ + Gia_Man_t * pCopy = Gia_ManDup(pGia); + Gia_ManDupMapping( pCopy, pGia ); + return pCopy; +} +void Gia_ManStochSynthesis( Vec_Ptr_t * vAigs, char * pScript ) +{ + Gia_Man_t * pGia, * pNew; int i; + Vec_PtrForEachEntry( Gia_Man_t *, vAigs, pGia, i ) + { + Gia_Man_t * pCopy = Gia_ManDupWithMapping(pGia); + Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pGia ); + if ( Abc_FrameIsBatchMode() ) + { + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), pScript) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pScript ); + return; + } + } + else + { + Abc_FrameSetBatchMode( 1 ); + if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), pScript) ) + { + Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pScript ); + Abc_FrameSetBatchMode( 0 ); + return; + } + Abc_FrameSetBatchMode( 0 ); + } + pNew = Abc_FrameReadGia(Abc_FrameGetGlobalFrame()); + if ( Gia_ManHasMapping(pNew) && Gia_ManHasMapping(pCopy) ) + { + if ( Gia_ManLutNum(pNew) < Gia_ManLutNum(pCopy) ) + { + Gia_ManStop( pCopy ); + pCopy = Gia_ManDupWithMapping( pNew ); + } + } + else + { + if ( Gia_ManAndNum(pNew) < Gia_ManAndNum(pCopy) ) + { + Gia_ManStop( pCopy ); + pCopy = Gia_ManDup( pNew ); + } + } + Vec_PtrWriteEntry( vAigs, i, pCopy ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCollectNodes_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vAnds ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjUpdateTravIdCurrentId( p, iObj ) ) + return; + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) || iObj == 0 ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManCollectNodes_rec( p, Gia_ObjFaninId0(pObj, iObj), vAnds ); + Gia_ManCollectNodes_rec( p, Gia_ObjFaninId1(pObj, iObj), vAnds ); + Vec_IntPush( vAnds, iObj ); +} +void Gia_ManCollectNodes( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos ) +{ + int i, iObj; + if ( !Gia_ManHasMapping(p) ) + return; + Vec_IntClear( vAnds ); + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vCis, iObj, i ) + Gia_ObjSetTravIdCurrentId( p, iObj ); + Vec_IntForEachEntry( vCos, iObj, i ) + Gia_ManCollectNodes_rec( p, iObj, vAnds ); +} +Gia_Man_t * Gia_ManDupDivideOne( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos ) +{ + Vec_Int_t * vMapping; int i; + Gia_Man_t * pNew; Gia_Obj_t * pObj; + pNew = Gia_ManStart( 1+Vec_IntSize(vCis)+Vec_IntSize(vAnds)+Vec_IntSize(vCos) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObjVec( vCis, p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachObjVec( vAnds, p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachObjVec( vCos, p, pObj, i ) + Gia_ManAppendCo( pNew, pObj->Value ); + assert( Gia_ManCiNum(pNew) > 0 && Gia_ManCoNum(pNew) > 0 ); + if ( !Gia_ManHasMapping(p) ) + return pNew; + vMapping = Vec_IntAlloc( 4*Gia_ManObjNum(pNew) ); + Vec_IntFill( vMapping, Gia_ManObjNum(pNew), 0 ); + Gia_ManForEachObjVec( vAnds, p, pObj, i ) + { + Gia_Obj_t * pFanin; int k; + int iObj = Gia_ObjId(p, pObj); + if ( !Gia_ObjIsLut(p, iObj) ) + continue; + Vec_IntWriteEntry( vMapping, Abc_Lit2Var(pObj->Value), Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, Gia_ObjLutSize(p, iObj) ); + Gia_LutForEachFaninObj( p, iObj, pFanin, k ) + Vec_IntPush( vMapping, Abc_Lit2Var(pFanin->Value) ); + Vec_IntPush( vMapping, Abc_Lit2Var(pObj->Value) ); + } + pNew->vMapping = vMapping; + return pNew; +} +Vec_Ptr_t * Gia_ManDupDivide( Gia_Man_t * p, Vec_Wec_t * vCis, Vec_Wec_t * vAnds, Vec_Wec_t * vCos, char * pScript, int nProcs, int TimeOut ) +{ + Vec_Ptr_t * vAigs = Vec_PtrAlloc( Vec_WecSize(vCis) ); int i; + for ( i = 0; i < Vec_WecSize(vCis); i++ ) + { + Gia_ManCollectNodes( p, Vec_WecEntry(vCis, i), Vec_WecEntry(vAnds, i), Vec_WecEntry(vCos, i) ); + Vec_PtrPush( vAigs, Gia_ManDupDivideOne(p, Vec_WecEntry(vCis, i), Vec_WecEntry(vAnds, i), Vec_WecEntry(vCos, i)) ); + } + //Gia_ManStochSynthesis( vAigs, pScript ); + Gia_StochProcess( vAigs, pScript, nProcs, TimeOut, 0 ); + return vAigs; +} +Gia_Man_t * Gia_ManDupStitch( Gia_Man_t * p, Vec_Wec_t * vCis, Vec_Wec_t * vAnds, Vec_Wec_t * vCos, Vec_Ptr_t * vAigs, int fHash ) +{ + Gia_Man_t * pGia, * pNew; + Gia_Obj_t * pObj; int i, k; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManCleanValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + if ( fHash ) + Gia_ManHashAlloc( pNew ); + Vec_PtrForEachEntry( Gia_Man_t *, vAigs, pGia, i ) + { + Vec_Int_t * vCi = Vec_WecEntry( vCis, i ); + Vec_Int_t * vCo = Vec_WecEntry( vCos, i ); + Gia_ManCleanValue( pGia ); + Gia_ManConst0(pGia)->Value = 0; + Gia_ManForEachObjVec( vCi, p, pObj, k ) + Gia_ManCi(pGia, k)->Value = pObj->Value; + if ( fHash ) + Gia_ManForEachAnd( pGia, pObj, k ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else + Gia_ManForEachAnd( pGia, pObj, k ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachObjVec( vCo, p, pObj, k ) + pObj->Value = Gia_ObjFanin0Copy(Gia_ManCo(pGia, k)); + } + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + if ( fHash ) + { + pNew = Gia_ManCleanup( pGia = pNew ); + Gia_ManStop( pGia ); + } + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} +Gia_Man_t * Gia_ManDupStitchMap( Gia_Man_t * p, Vec_Wec_t * vCis, Vec_Wec_t * vAnds, Vec_Wec_t * vCos, Vec_Ptr_t * vAigs ) +{ + Vec_Int_t * vMapping; int n; + Gia_Man_t * pGia, * pNew = Gia_ManDupStitch( p, vCis, vAnds, vCos, vAigs, !Gia_ManHasMapping(p) ); + if ( !Gia_ManHasMapping(p) ) + return pNew; + vMapping = Vec_IntAlloc( Vec_IntSize(p->vMapping) ); + Vec_IntFill( vMapping, Gia_ManObjNum(pNew), 0 ); + Vec_PtrForEachEntry( Gia_Man_t *, vAigs, pGia, n ) + { + Gia_Obj_t * pFanin; int iObj, k; + //printf( "Gia %d has %d Luts\n", n, Gia_ManLutNum(pGia) ); + + Gia_ManForEachLut( pGia, iObj ) + { + Gia_Obj_t * pObj = Gia_ManObj( pGia, iObj ); + Vec_IntWriteEntry( vMapping, Abc_Lit2Var(pObj->Value), Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, Gia_ObjLutSize(pGia, iObj) ); + Gia_LutForEachFaninObj( pGia, iObj, pFanin, k ) + Vec_IntPush( vMapping, Abc_Lit2Var(pFanin->Value) ); + Vec_IntPush( vMapping, Abc_Lit2Var(pObj->Value) ); + } + } + pNew->vMapping = vMapping; + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Gia_ManStochNodes( Gia_Man_t * p, int nMaxSize, int Seed ) +{ + Vec_Wec_t * vRes = Vec_WecAlloc( 100 ); + Vec_Int_t * vPart = Vec_WecPushLevel( vRes ); + int i, iStart = Seed % Gia_ManCoNum(p); + //Gia_ManLevelNum( p ); + Gia_ManIncrementTravId( p ); + for ( i = 0; i < Gia_ManCoNum(p); i++ ) + { + Gia_Obj_t * pObj = Gia_ManCo( p, (iStart+i) % Gia_ManCoNum(p) ); + if ( Vec_IntSize(vPart) > nMaxSize ) + vPart = Vec_WecPushLevel( vRes ); + Gia_ManCollectNodes_rec( p, Gia_ObjFaninId0p(p, pObj), vPart ); + } + if ( Vec_IntSize(vPart) == 0 ) + Vec_WecShrink( vRes, Vec_WecSize(vRes)-1 ); + //Vec_WecPrint( vRes, 0 ); + return vRes; +} +Vec_Wec_t * Gia_ManStochInputs( Gia_Man_t * p, Vec_Wec_t * vAnds ) +{ + Vec_Wec_t * vRes = Vec_WecAlloc( 100 ); + Vec_Int_t * vLevel; Gia_Obj_t * pObj; int i, k, iObj, iFan, f; + Vec_WecForEachLevel( vAnds, vLevel, i ) + { + Vec_Int_t * vVec = Vec_WecPushLevel( vRes ); + assert( Vec_IntSize(vVec) == 0 ); + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vLevel, iObj, k ) + Gia_ObjSetTravIdCurrentId( p, iObj ); + if ( Gia_ManHasMapping(p) ) + { + Vec_IntForEachEntry( vLevel, iObj, k ) + if ( Gia_ObjIsLut(p, iObj) ) + Gia_LutForEachFanin( p, iObj, iFan, f ) + if ( !Gia_ObjUpdateTravIdCurrentId(p, iFan) ) + Vec_IntPush( vVec, iFan ); + } + else + { + Gia_ManForEachObjVec( vLevel, p, pObj, k ) + { + iObj = Gia_ObjFaninId0p(p, pObj); + if ( !Gia_ObjUpdateTravIdCurrentId(p, iObj) ) + Vec_IntPush( vVec, iObj ); + iObj = Gia_ObjFaninId1p(p, pObj); + if ( !Gia_ObjUpdateTravIdCurrentId(p, iObj) ) + Vec_IntPush( vVec, iObj ); + } + } + assert( Vec_IntSize(vVec) > 0 ); + } + return vRes; +} +Vec_Wec_t * Gia_ManStochOutputs( Gia_Man_t * p, Vec_Wec_t * vAnds ) +{ + Vec_Wec_t * vRes = Vec_WecAlloc( 100 ); + Vec_Int_t * vLevel; Gia_Obj_t * pObj; int i, k, iObj, iFan, f; + if ( Gia_ManHasMapping(p) ) + { + Gia_ManSetLutRefs( p ); + Vec_WecForEachLevel( vAnds, vLevel, i ) + { + Vec_Int_t * vVec = Vec_WecPushLevel( vRes ); + assert( Vec_IntSize(vVec) == 0 ); + Vec_IntForEachEntry( vLevel, iObj, k ) + if ( Gia_ObjIsLut(p, iObj) ) + Gia_LutForEachFanin( p, iObj, iFan, f ) + Gia_ObjLutRefDecId( p, iFan ); + Vec_IntForEachEntry( vLevel, iObj, k ) + if ( Gia_ObjIsLut(p, iObj) ) + if ( Gia_ObjLutRefNumId(p, iObj) ) + Vec_IntPush( vVec, iObj ); + Vec_IntForEachEntry( vLevel, iObj, k ) + if ( Gia_ObjIsLut(p, iObj) ) + Gia_LutForEachFanin( p, iObj, iFan, f ) + Gia_ObjLutRefIncId( p, iFan ); + assert( Vec_IntSize(vVec) > 0 ); + } + } + else + { + Gia_ManCreateRefs( p ); + Vec_WecForEachLevel( vAnds, vLevel, i ) + { + Vec_Int_t * vVec = Vec_WecPushLevel( vRes ); + Gia_ManForEachObjVec( vLevel, p, pObj, k ) + { + Gia_ObjRefDecId( p, Gia_ObjFaninId0p(p, pObj) ); + Gia_ObjRefDecId( p, Gia_ObjFaninId1p(p, pObj) ); + } + Gia_ManForEachObjVec( vLevel, p, pObj, k ) + if ( Gia_ObjRefNum(p, pObj) ) + Vec_IntPush( vVec, Gia_ObjId(p, pObj) ); + Gia_ManForEachObjVec( vLevel, p, pObj, k ) + { + Gia_ObjRefIncId( p, Gia_ObjFaninId0p(p, pObj) ); + Gia_ObjRefIncId( p, Gia_ObjFaninId1p(p, pObj) ); + } + } + } + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManStochSyn( int nMaxSize, int nIters, int TimeOut, int Seed, int fVerbose, char * pScript, int nProcs ) +{ + abctime nTimeToStop = TimeOut ? Abc_Clock() + TimeOut * CLOCKS_PER_SEC : 0; + abctime clkStart = Abc_Clock(); + int fMapped = Gia_ManHasMapping(Abc_FrameReadGia(Abc_FrameGetGlobalFrame())); + int nLutEnd, nLutBeg = fMapped ? Gia_ManLutNum(Abc_FrameReadGia(Abc_FrameGetGlobalFrame())) : 0; + int i, nEnd, nBeg = Gia_ManAndNum(Abc_FrameReadGia(Abc_FrameGetGlobalFrame())); + Abc_Random(1); + for ( i = 0; i < 10+Seed; i++ ) + Abc_Random(0); + if ( fVerbose ) + printf( "Running %d iterations of script \"%s\".\n", nIters, pScript ); + for ( i = 0; i < nIters; i++ ) + { + abctime clk = Abc_Clock(); + Gia_Man_t * pGia = Gia_ManDupWithMapping( Abc_FrameReadGia(Abc_FrameGetGlobalFrame()) ); + Vec_Wec_t * vAnds = Gia_ManStochNodes( pGia, nMaxSize, Abc_Random(0) & 0x7FFFFFFF ); + Vec_Wec_t * vIns = Gia_ManStochInputs( pGia, vAnds ); + Vec_Wec_t * vOuts = Gia_ManStochOutputs( pGia, vAnds ); + Vec_Ptr_t * vAigs = Gia_ManDupDivide( pGia, vIns, vAnds, vOuts, pScript, nProcs, TimeOut ); + Gia_Man_t * pNew = Gia_ManDupStitchMap( pGia, vIns, vAnds, vOuts, vAigs ); + int fMapped = Gia_ManHasMapping(pGia) && Gia_ManHasMapping(pNew); + Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pNew ); + if ( fVerbose ) + printf( "Iteration %3d : Using %3d partitions. Reducing %6d to %6d %s. ", + i, Vec_PtrSize(vAigs), fMapped ? Gia_ManLutNum(pGia) : Gia_ManAndNum(pGia), + fMapped ? Gia_ManLutNum(pNew) : Gia_ManAndNum(pNew), + fMapped ? "LUTs" : "ANDs" ); + if ( fVerbose ) + Abc_PrintTime( 0, "Time", Abc_Clock() - clk ); + Gia_ManStop( pGia ); + Vec_PtrFreeFunc( vAigs, (void (*)(void *)) Gia_ManStop ); + Vec_WecFree( vAnds ); + Vec_WecFree( vIns ); + Vec_WecFree( vOuts ); + if ( nTimeToStop && Abc_Clock() > nTimeToStop ) + { + printf( "Runtime limit (%d sec) is reached after %d iterations.\n", TimeOut, i ); + break; + } + } + fMapped &= Gia_ManHasMapping(Abc_FrameReadGia(Abc_FrameGetGlobalFrame())); + nLutEnd = fMapped ? Gia_ManLutNum(Abc_FrameReadGia(Abc_FrameGetGlobalFrame())) : 0; + nEnd = Gia_ManAndNum(Abc_FrameReadGia(Abc_FrameGetGlobalFrame())); + if ( fVerbose ) + printf( "Cumulatively reduced %d %s after %d iterations. ", + fMapped ? nLutBeg - nLutEnd : nBeg - nEnd, fMapped ? "LUTs" : "ANDs", nIters ); + if ( fVerbose ) + Abc_PrintTime( 0, "Total time", Abc_Clock() - clkStart ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaStr.c b/yosys/abc/src/aig/gia/giaStr.c new file mode 100644 index 00000000000..a87662a8586 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaStr.c @@ -0,0 +1,1871 @@ +/**CFile**************************************************************** + + FileName [giaStr.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [AIG structuring.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaStr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/util/utilNam.h" +#include "misc/vec/vecWec.h" +#include "misc/tim/tim.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define STR_SUPER 100 +#define MAX_TREE 10000 + +enum { + STR_NONE = 0, + STR_CONST0 = 1, + STR_PI = 2, + STR_AND = 3, + STR_XOR = 4, + STR_MUX = 5, + STR_BUF = 6, + STR_PO = 7, + STR_UNUSED = 8 +}; + +typedef struct Str_Obj_t_ Str_Obj_t; +struct Str_Obj_t_ +{ + unsigned Type : 4; // object type + unsigned nFanins : 28; // fanin count + int iOffset; // place where fanins are stored + int iTop; // top level MUX + int iCopy; // copy of this node +}; +typedef struct Str_Ntk_t_ Str_Ntk_t; +struct Str_Ntk_t_ +{ + int nObjs; // object count + int nObjsAlloc; // alloc objects + Str_Obj_t * pObjs; // objects + Vec_Int_t vFanins; // object fanins + int nObjCount[STR_UNUSED]; + int nTrees; + int nGroups; + int DelayGain; +}; +typedef struct Str_Man_t_ Str_Man_t; +struct Str_Man_t_ +{ + // user data + Gia_Man_t * pOld; // manager + int nLutSize; // LUT size + int fCutMin; // cut minimization + // internal data + Str_Ntk_t * pNtk; // balanced network + // AIG under construction + Gia_Man_t * pNew; // newly constructed + Vec_Int_t * vDelays; // delays of each object +}; + +static inline Str_Obj_t * Str_NtkObj( Str_Ntk_t * p, int i ) { assert( i < p->nObjs ); return p->pObjs + i; } +static inline int Str_ObjFaninId( Str_Ntk_t * p, Str_Obj_t * pObj, int i ) { return Abc_Lit2Var( Vec_IntEntry(&p->vFanins, pObj->iOffset + i) ); } +static inline Str_Obj_t * Str_ObjFanin( Str_Ntk_t * p, Str_Obj_t * pObj, int i ) { return Str_NtkObj( p, Str_ObjFaninId(p, pObj, i) ); } +static inline int Str_ObjFaninC( Str_Ntk_t * p, Str_Obj_t * pObj, int i ) { return Abc_LitIsCompl( Vec_IntEntry(&p->vFanins, pObj->iOffset + i) ); } +static inline int Str_ObjFaninCopy( Str_Ntk_t * p, Str_Obj_t * pObj, int i ) { return Abc_LitNotCond( Str_ObjFanin(p, pObj, i)->iCopy, Str_ObjFaninC(p, pObj, i) ); } +static inline int Str_ObjId( Str_Ntk_t * p, Str_Obj_t * pObj ) { return pObj - p->pObjs; } + +#define Str_NtkManForEachObj( p, pObj ) \ + for ( pObj = p->pObjs; Str_ObjId(p, pObj) < p->nObjs; pObj++ ) +#define Str_NtkManForEachObjVec( vVec, p, pObj, i ) \ + for ( i = 0; (i < Vec_IntSize(vVec)) && ((pObj) = Str_NtkObj(p, Vec_IntEntry(vVec,i))); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Logic network manipulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Str_ObjCreate( Str_Ntk_t * p, int Type, int nFanins, int * pFanins ) +{ + Str_Obj_t * pObj = p->pObjs + p->nObjs; int i; + assert( p->nObjs < p->nObjsAlloc ); + pObj->Type = Type; + pObj->nFanins = nFanins; + pObj->iOffset = Vec_IntSize(&p->vFanins); + pObj->iTop = pObj->iCopy = -1; + for ( i = 0; i < nFanins; i++ ) + { + Vec_IntPush( &p->vFanins, pFanins[i] ); + assert( pFanins[i] >= 0 ); + } + p->nObjCount[Type]++; + return Abc_Var2Lit( p->nObjs++, 0 ); +} +static inline Str_Ntk_t * Str_NtkCreate( int nObjsAlloc, int nFaninsAlloc ) +{ + Str_Ntk_t * p; + p = ABC_CALLOC( Str_Ntk_t, 1 ); + p->pObjs = ABC_ALLOC( Str_Obj_t, nObjsAlloc ); + p->nObjsAlloc = nObjsAlloc; + Str_ObjCreate( p, STR_CONST0, 0, NULL ); + Vec_IntGrow( &p->vFanins, nFaninsAlloc ); + return p; +} +static inline void Str_NtkDelete( Str_Ntk_t * p ) +{ +// printf( "Total delay gain = %d.\n", p->DelayGain ); + ABC_FREE( p->vFanins.pArray ); + ABC_FREE( p->pObjs ); + ABC_FREE( p ); +} +static inline void Str_NtkPs( Str_Ntk_t * p, abctime clk ) +{ + printf( "Network contains %d ands, %d xors, %d muxes (%d trees in %d groups). ", + p->nObjCount[STR_AND], p->nObjCount[STR_XOR], p->nObjCount[STR_MUX], p->nTrees, p->nGroups ); + Abc_PrintTime( 1, "Time", clk ); +} +static inline void Str_ObjReadGroup( Str_Ntk_t * p, Str_Obj_t * pObj, int * pnGroups, int * pnMuxes ) +{ + Str_Obj_t * pObj1, * pObj2; + *pnGroups = *pnMuxes = 0; + if ( pObj->iTop == 0 ) + return; + pObj1 = Str_NtkObj( p, pObj->iTop ); + pObj2 = Str_NtkObj( p, pObj1->iTop ); + *pnMuxes = pObj1 - pObj + 1; + *pnGroups = (pObj2 - pObj + 1) / *pnMuxes; +} +static inline void Str_NtkPrintGroups( Str_Ntk_t * p ) +{ + Str_Obj_t * pObj; + int nGroups, nMuxes; + Str_NtkManForEachObj( p, pObj ) + if ( pObj->Type == STR_MUX && pObj->iTop > 0 ) + { + Str_ObjReadGroup( p, pObj, &nGroups, &nMuxes ); + pObj += nGroups * nMuxes - 1; + printf( "%d x %d ", nGroups, nMuxes ); + } + printf( "\n" ); +} +Gia_Man_t * Str_NtkToGia( Gia_Man_t * pGia, Str_Ntk_t * p ) +{ + Gia_Man_t * pNew, * pTemp; + Str_Obj_t * pObj; int k; + assert( pGia->pMuxes == NULL ); + pNew = Gia_ManStart( 3 * Gia_ManObjNum(pGia) / 2 ); + pNew->pName = Abc_UtilStrsav( pGia->pName ); + pNew->pSpec = Abc_UtilStrsav( pGia->pSpec ); + Gia_ManHashStart( pNew ); + Str_NtkManForEachObj( p, pObj ) + { + if ( pObj->Type == STR_PI ) + pObj->iCopy = Gia_ManAppendCi( pNew ); + else if ( pObj->Type == STR_AND ) + { + pObj->iCopy = 1; + for ( k = 0; k < (int)pObj->nFanins; k++ ) + pObj->iCopy = Gia_ManHashAnd( pNew, pObj->iCopy, Str_ObjFaninCopy(p, pObj, k) ); + } + else if ( pObj->Type == STR_XOR ) + { + pObj->iCopy = 0; + for ( k = 0; k < (int)pObj->nFanins; k++ ) + pObj->iCopy = Gia_ManHashXor( pNew, pObj->iCopy, Str_ObjFaninCopy(p, pObj, k) ); + } + else if ( pObj->Type == STR_MUX ) + pObj->iCopy = Gia_ManHashMux( pNew, Str_ObjFaninCopy(p, pObj, 2), Str_ObjFaninCopy(p, pObj, 1), Str_ObjFaninCopy(p, pObj, 0) ); + else if ( pObj->Type == STR_PO ) + pObj->iCopy = Gia_ManAppendCo( pNew, Str_ObjFaninCopy(p, pObj, 0) ); + else if ( pObj->Type == STR_CONST0 ) + pObj->iCopy = 0; + else assert( 0 ); + } + Gia_ManHashStop( pNew ); +// assert( Gia_ManObjNum(pNew) <= Gia_ManObjNum(pGia) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Constructs a normalized AIG without structural hashing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupMuxesNoHash( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj, * pFan0, * pFan1, * pFanC; + int i, iLit0, iLit1, fCompl; + assert( p->pMuxes == NULL ); + ABC_FREE( p->pRefs ); + Gia_ManCreateRefs( p ); + // discount nodes with one fanout pointed to by MUX type + Gia_ManForEachAnd( p, pObj, i ) + { + if ( !Gia_ObjIsMuxType(pObj) ) + continue; + Gia_ObjRefDec(p, Gia_ObjFanin0(pObj)); + Gia_ObjRefDec(p, Gia_ObjFanin1(pObj)); + } + // start the new manager + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc ); + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + { + if ( !Gia_ObjRefNumId(p, i) ) + continue; + if ( !Gia_ObjIsMuxType(pObj) ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) ) + { + iLit0 = Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan0)); + iLit1 = Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan1)); + fCompl = Abc_LitIsCompl(iLit0) ^ Abc_LitIsCompl(iLit1); + pObj->Value = fCompl ^ Gia_ManAppendXorReal( pNew, Abc_LitRegular(iLit0), Abc_LitRegular(iLit1) ); + } + else + { + pFanC = Gia_ObjRecognizeMux( pObj, &pFan1, &pFan0 ); + iLit0 = Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan0)); + iLit1 = Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan1)); + if ( iLit0 == iLit1 ) + pObj->Value = iLit0; + else if ( Abc_Lit2Var(iLit0) == Abc_Lit2Var(iLit1) ) + { + iLit1 = Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFanC)); + fCompl = Abc_LitIsCompl(iLit0) ^ Abc_LitIsCompl(iLit1); + pObj->Value = fCompl ^ Gia_ManAppendXorReal( pNew, Abc_LitRegular(iLit0), Abc_LitRegular(iLit1) ); + } + else + pObj->Value = Gia_ManAppendMuxReal( pNew, Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFanC)), Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan1)), Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan0)) ); + } + } + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + assert( !Gia_ManHasDangling(pNew) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Constructs AIG ordered for balancing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Str_MuxInputsCollect_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) +{ + if ( !pObj->fMark0 ) + { + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); + return; + } + Vec_IntPush( vNodes, Gia_ObjFaninId2p(p, pObj) ); + Str_MuxInputsCollect_rec( p, Gia_ObjFanin0(pObj), vNodes ); + Str_MuxInputsCollect_rec( p, Gia_ObjFanin1(pObj), vNodes ); +} +void Str_MuxInputsCollect( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) +{ + assert( !pObj->fMark0 ); + pObj->fMark0 = 1; + Vec_IntClear( vNodes ); + Str_MuxInputsCollect_rec( p, pObj, vNodes ); + pObj->fMark0 = 0; +} +void Str_MuxStructCollect_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) +{ + if ( !pObj->fMark0 ) + return; + Str_MuxStructCollect_rec( p, Gia_ObjFanin0(pObj), vNodes ); + Str_MuxStructCollect_rec( p, Gia_ObjFanin1(pObj), vNodes ); + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); +} +void Str_MuxStructCollect( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) +{ + assert( !pObj->fMark0 ); + pObj->fMark0 = 1; + Vec_IntClear( vNodes ); + Str_MuxStructCollect_rec( p, pObj, vNodes ); + pObj->fMark0 = 0; +} +void Str_MuxStructDump_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Str_t * vStr ) +{ + if ( !pObj->fMark0 ) + return; + Vec_StrPush( vStr, '[' ); + Vec_StrPush( vStr, '(' ); + Vec_StrPrintNum( vStr, Gia_ObjFaninId2p(p, pObj) ); + Vec_StrPush( vStr, ')' ); + Str_MuxStructDump_rec( p, Gia_ObjFaninC2(p, pObj) ? Gia_ObjFanin0(pObj) : Gia_ObjFanin1(pObj), vStr ); + Vec_StrPush( vStr, '|' ); + Str_MuxStructDump_rec( p, Gia_ObjFaninC2(p, pObj) ? Gia_ObjFanin1(pObj) : Gia_ObjFanin0(pObj), vStr ); + Vec_StrPush( vStr, ']' ); +} +void Str_MuxStructDump( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Str_t * vStr ) +{ + assert( !pObj->fMark0 ); + pObj->fMark0 = 1; + Vec_StrClear( vStr ); + Str_MuxStructDump_rec( p, pObj, vStr ); + Vec_StrPush( vStr, '\0' ); + pObj->fMark0 = 0; +} +int Str_ManMuxCountOne( char * p ) +{ + int Count = 0; + for ( ; *p; p++ ) + Count += (*p == '['); + return Count; +} +Vec_Wec_t * Str_ManDeriveTrees( Gia_Man_t * p ) +{ + int fPrintStructs = 0; + Abc_Nam_t * pNames; + Vec_Wec_t * vGroups; + Vec_Str_t * vStr; + Gia_Obj_t * pObj, * pFanin; + int i, iStructId, fFound; + assert( p->pMuxes != NULL ); + // mark MUXes whose only fanout is a MUX + ABC_FREE( p->pRefs ); + Gia_ManCreateRefs( p ); + Gia_ManForEachMuxId( p, i ) + { + pObj = Gia_ManObj(p, i); + pFanin = Gia_ObjFanin0(pObj); + if ( Gia_ObjIsMux(p, pFanin) && Gia_ObjRefNum(p, pFanin) == 1 ) + pFanin->fMark0 = 1; + pFanin = Gia_ObjFanin1(pObj); + if ( Gia_ObjIsMux(p, pFanin) && Gia_ObjRefNum(p, pFanin) == 1 ) + pFanin->fMark0 = 1; + } + // traverse for top level MUXes + vStr = Vec_StrAlloc( 1000 ); + pNames = Abc_NamStart( 10000, 50 ); + vGroups = Vec_WecAlloc( 1000 ); + Vec_WecPushLevel( vGroups ); + Gia_ManForEachMuxId( p, i ) + { + // skip internal + pObj = Gia_ManObj(p, i); + if ( pObj->fMark0 ) + continue; + // skip trees of size one + if ( !Gia_ObjFanin0(pObj)->fMark0 && !Gia_ObjFanin1(pObj)->fMark0 ) + continue; + // hash the tree + Str_MuxStructDump( p, pObj, vStr ); + iStructId = Abc_NamStrFindOrAdd( pNames, Vec_StrArray(vStr), &fFound ); + if ( !fFound ) Vec_WecPushLevel( vGroups ); + assert( Abc_NamObjNumMax(pNames) == Vec_WecSize(vGroups) ); + Vec_IntPush( Vec_WecEntry(vGroups, iStructId), i ); + } + if ( fPrintStructs ) + { + char * pTemp; + Abc_NamManForEachObj( pNames, pTemp, i ) + { + printf( "%5d : ", i ); + printf( "Occur = %4d ", Vec_IntSize(Vec_WecEntry(vGroups,i)) ); + printf( "Size = %4d ", Str_ManMuxCountOne(pTemp) ); + printf( "%s\n", pTemp ); + } + } + Abc_NamStop( pNames ); + Vec_StrFree( vStr ); + return vGroups; +} +Vec_Int_t * Str_ManCreateRoots( Vec_Wec_t * vGroups, int nObjs ) +{ // map tree MUXes into their classes + Vec_Int_t * vRoots; + Vec_Int_t * vGroup; + int i, k, Entry; + vRoots = Vec_IntStartFull( nObjs ); + Vec_WecForEachLevel( vGroups, vGroup, i ) + Vec_IntForEachEntry( vGroup, Entry, k ) + Vec_IntWriteEntry( vRoots, Entry, i ); + return vRoots; +} + +void Str_MuxTraverse_rec( Gia_Man_t * p, int i ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjIsTravIdCurrentId(p, i) ) + return; + Gia_ObjSetTravIdCurrentId(p, i); + pObj = Gia_ManObj(p, i); + if ( !Gia_ObjIsAnd(pObj) ) + return; + Str_MuxTraverse_rec(p, Gia_ObjFaninId0(pObj, i) ); + Str_MuxTraverse_rec(p, Gia_ObjFaninId1(pObj, i) ); + if ( Gia_ObjIsMux(p, pObj) ) + Str_MuxTraverse_rec(p, Gia_ObjFaninId2(p, i) ); +} +void Str_ManCheckOverlap( Gia_Man_t * p, Vec_Wec_t * vGroups ) +{ // check that members of each group are not in the TFI of each other + Vec_Int_t * vGroup, * vGroup2; + int i, k, n, iObj, iObj2; + +// vGroup = Vec_WecEntry(vGroups, 7); +// Vec_IntForEachEntry( vGroup, iObj, n ) +// Gia_ManPrintCone2( p, Gia_ManObj(p, iObj) ), printf( "\n" ); + + Vec_WecForEachLevel( vGroups, vGroup, i ) + Vec_IntForEachEntry( vGroup, iObj, k ) + { + if ( Vec_IntSize(vGroup) == 1 ) + continue; + // high light the cone + Gia_ManIncrementTravId( p ); + Str_MuxTraverse_rec( p, iObj ); + // check that none of the others are highlighted + Vec_IntForEachEntry( vGroup, iObj2, n ) + if ( iObj != iObj2 && Gia_ObjIsTravIdCurrentId(p, iObj2) ) + break; + if ( n == Vec_IntSize(vGroup) ) + continue; + // split the group into individual trees + Vec_IntForEachEntryStart( vGroup, iObj2, n, 1 ) + { + vGroup2 = Vec_WecPushLevel( vGroups ); + vGroup = Vec_WecEntry( vGroups, i ); + Vec_IntPush( vGroup2, iObj2 ); + } + Vec_IntShrink( vGroup, 1 ); + +/* + // this does not work because there can be a pair of independent trees + // with another tree squeezed in between them, so that there is a combo loop + + // divide this group + nNew = 0; + vGroup2 = Vec_WecPushLevel( vGroups ); + vGroup = Vec_WecEntry( vGroups, i ); + Vec_IntForEachEntry( vGroup, iObj2, n ) + { + if ( iObj != iObj2 && Gia_ObjIsTravIdCurrentId(p, iObj2) ) + Vec_IntPush( vGroup2, iObj2 ); + else + Vec_IntWriteEntry( vGroup, nNew++, iObj2 ); + } + Vec_IntShrink( vGroup, nNew ); + i--; + break; +*/ + +/* + // check that none of the others are highlighted + Vec_IntForEachEntry( vGroup, iObj, n ) + if ( n != k && Gia_ObjIsTravIdCurrentId(p, iObj) ) + { + printf( "Overlap of TFI cones of trees %d and %d in group %d of size %d!\n", k, n, i, Vec_IntSize(vGroup) ); + Vec_IntShrink( vGroup, 1 ); + break; + } +*/ + } +} + +/**Function************************************************************* + + Synopsis [Simplify multi-input AND/XOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSimplifyXor( Vec_Int_t * vSuper ) +{ + int i, k = 0, Prev = -1, This, fCompl = 0; + Vec_IntForEachEntry( vSuper, This, i ) + { + if ( This == 0 ) + continue; + if ( This == 1 ) + fCompl ^= 1; + else if ( Prev != This ) + Vec_IntWriteEntry( vSuper, k++, This ), Prev = This; + else + Prev = -1, k--; + } + Vec_IntShrink( vSuper, k ); + if ( Vec_IntSize( vSuper ) == 0 ) + Vec_IntPush( vSuper, fCompl ); + else if ( fCompl ) + Vec_IntWriteEntry( vSuper, 0, Abc_LitNot(Vec_IntEntry(vSuper, 0)) ); +} +static inline void Gia_ManSimplifyAnd( Vec_Int_t * vSuper ) +{ + int i, k = 0, Prev = -1, This; + Vec_IntForEachEntry( vSuper, This, i ) + { + if ( This == 0 ) + { Vec_IntFill(vSuper, 1, 0); return; } + if ( This == 1 ) + continue; + if ( Prev == -1 || Abc_Lit2Var(Prev) != Abc_Lit2Var(This) ) + Vec_IntWriteEntry( vSuper, k++, This ), Prev = This; + else if ( Prev != This ) + { Vec_IntFill(vSuper, 1, 0); return; } + } + Vec_IntShrink( vSuper, k ); + if ( Vec_IntSize( vSuper ) == 0 ) + Vec_IntPush( vSuper, 1 ); +} + +/**Function************************************************************* + + Synopsis [Collect multi-input AND/XOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSuperCollectXor_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + assert( !Gia_IsComplement(pObj) ); + if ( !Gia_ObjIsXor(pObj) || + Gia_ObjRefNum(p, pObj) > 1 || +// Gia_ObjRefNum(p, pObj) > 3 || +// (Gia_ObjRefNum(p, pObj) == 2 && (Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) == 1 || Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) == 1)) || + Vec_IntSize(p->vSuper) > STR_SUPER ) + { + Vec_IntPush( p->vSuper, Gia_ObjToLit(p, pObj) ); + return; + } + assert( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ); + Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin1(pObj) ); +} +static inline void Gia_ManSuperCollectAnd_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( Gia_IsComplement(pObj) || + !Gia_ObjIsAndReal(p, pObj) || + Gia_ObjRefNum(p, pObj) > 1 || +// Gia_ObjRefNum(p, pObj) > 3 || +// (Gia_ObjRefNum(p, pObj) == 2 && (Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) == 1 || Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) == 1)) || + Vec_IntSize(p->vSuper) > STR_SUPER ) + { + Vec_IntPush( p->vSuper, Gia_ObjToLit(p, pObj) ); + return; + } + Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild0(pObj) ); + Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild1(pObj) ); +} +static inline void Gia_ManSuperCollect( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( p->vSuper == NULL ) + p->vSuper = Vec_IntAlloc( STR_SUPER ); + else + Vec_IntClear( p->vSuper ); + if ( Gia_ObjIsXor(pObj) ) + { + assert( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) ); + Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ManSuperCollectXor_rec( p, Gia_ObjFanin1(pObj) ); + Vec_IntSort( p->vSuper, 0 ); + Gia_ManSimplifyXor( p->vSuper ); + } + else if ( Gia_ObjIsAndReal(p, pObj) ) + { + Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild0(pObj) ); + Gia_ManSuperCollectAnd_rec( p, Gia_ObjChild1(pObj) ); + Vec_IntSort( p->vSuper, 0 ); + Gia_ManSimplifyAnd( p->vSuper ); + } + else assert( 0 ); + assert( Vec_IntSize(p->vSuper) > 0 ); +} + +/**Function************************************************************* + + Synopsis [Constructs AIG ordered for balancing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Str_ManNormalize_rec( Str_Ntk_t * pNtk, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Wec_t * vGroups, Vec_Int_t * vRoots ) +{ + int i, k, iVar, iLit, iBeg, iEnd; + if ( ~pObj->Value ) + return; + pObj->Value = 0; + assert( Gia_ObjIsAnd(pObj) ); + if ( Gia_ObjIsMux(p, pObj) ) + { + Vec_Int_t * vGroup; + Gia_Obj_t * pRoot, * pMux; + int pFanins[3]; + if ( Vec_IntEntry(vRoots, Gia_ObjId(p, pObj)) == -1 ) + { + Str_ManNormalize_rec( pNtk, p, Gia_ObjFanin0(pObj), vGroups, vRoots ); + Str_ManNormalize_rec( pNtk, p, Gia_ObjFanin1(pObj), vGroups, vRoots ); + Str_ManNormalize_rec( pNtk, p, Gia_ObjFanin2(p, pObj), vGroups, vRoots ); + pFanins[0] = Gia_ObjFanin0Copy(pObj); + pFanins[1] = Gia_ObjFanin1Copy(pObj); + pFanins[2] = Gia_ObjFanin2Copy(p, pObj); + if ( Abc_LitIsCompl(pFanins[2]) ) + { + pFanins[2] = Abc_LitNot(pFanins[2]); + ABC_SWAP( int, pFanins[0], pFanins[1] ); + } + pObj->Value = Str_ObjCreate( pNtk, STR_MUX, 3, pFanins ); + return; + } + vGroup = Vec_WecEntry( vGroups, Vec_IntEntry(vRoots, Gia_ObjId(p, pObj)) ); + // build data-inputs for each tree + Gia_ManForEachObjVec( vGroup, p, pRoot, i ) + { + Str_MuxInputsCollect( p, pRoot, p->vSuper ); + iBeg = Vec_IntSize( p->vStore ); + Vec_IntAppend( p->vStore, p->vSuper ); + iEnd = Vec_IntSize( p->vStore ); + Vec_IntForEachEntryStartStop( p->vStore, iVar, k, iBeg, iEnd ) + Str_ManNormalize_rec( pNtk, p, Gia_ManObj(p, iVar), vGroups, vRoots ); + Vec_IntShrink( p->vStore, iBeg ); + } + // build internal structures + Gia_ManForEachObjVec( vGroup, p, pRoot, i ) + { + Str_MuxStructCollect( p, pRoot, p->vSuper ); + Gia_ManForEachObjVec( p->vSuper, p, pMux, k ) + { + pFanins[0] = Gia_ObjFanin0Copy(pMux); + pFanins[1] = Gia_ObjFanin1Copy(pMux); + pFanins[2] = Gia_ObjFanin2Copy(p, pMux); + if ( Abc_LitIsCompl(pFanins[2]) ) + { + pFanins[2] = Abc_LitNot(pFanins[2]); + ABC_SWAP( int, pFanins[0], pFanins[1] ); + } + pMux->Value = Str_ObjCreate( pNtk, STR_MUX, 3, pFanins ); + } + assert( ~pRoot->Value ); + // set mapping + Gia_ManForEachObjVec( p->vSuper, p, pMux, k ) + Str_NtkObj(pNtk, Abc_Lit2Var(pMux->Value))->iTop = Abc_Lit2Var(pRoot->Value); + pNtk->nTrees++; + } + assert( ~pObj->Value ); + // set mapping + pObj = Gia_ManObj( p, Vec_IntEntryLast(vGroup) ); + Gia_ManForEachObjVec( vGroup, p, pRoot, i ) + Str_NtkObj(pNtk, Abc_Lit2Var(pRoot->Value))->iTop = Abc_Lit2Var(pObj->Value); + pNtk->nGroups++; + //printf( "%d x %d ", Vec_IntSize(vGroup), Vec_IntSize(p->vSuper) ); + return; + } + // find supergate + Gia_ManSuperCollect( p, pObj ); + // save entries + iBeg = Vec_IntSize( p->vStore ); + Vec_IntAppend( p->vStore, p->vSuper ); + iEnd = Vec_IntSize( p->vStore ); + // call recursively + Vec_IntForEachEntryStartStop( p->vStore, iLit, i, iBeg, iEnd ) + { + Gia_Obj_t * pTemp = Gia_ManObj( p, Abc_Lit2Var(iLit) ); + Str_ManNormalize_rec( pNtk, p, pTemp, vGroups, vRoots ); + Vec_IntWriteEntry( p->vStore, i, Abc_LitNotCond(pTemp->Value, Abc_LitIsCompl(iLit)) ); + } + assert( Vec_IntSize(p->vStore) == iEnd ); + // consider general case + pObj->Value = Str_ObjCreate( pNtk, Gia_ObjIsXor(pObj) ? STR_XOR : STR_AND, iEnd-iBeg, Vec_IntEntryP(p->vStore, iBeg) ); + Vec_IntShrink( p->vStore, iBeg ); +} +Str_Ntk_t * Str_ManNormalizeInt( Gia_Man_t * p, Vec_Wec_t * vGroups, Vec_Int_t * vRoots ) +{ + Str_Ntk_t * pNtk; + Gia_Obj_t * pObj; + int i, iFanin; + assert( p->pMuxes != NULL ); + if ( p->vSuper == NULL ) + p->vSuper = Vec_IntAlloc( STR_SUPER ); + if ( p->vStore == NULL ) + p->vStore = Vec_IntAlloc( STR_SUPER ); + Gia_ManFillValue( p ); + pNtk = Str_NtkCreate( Gia_ManObjNum(p) + 10000, 1 + Gia_ManCoNum(p) + 2 * Gia_ManAndNum(p) + Gia_ManMuxNum(p) + 10000 ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Str_ObjCreate( pNtk, STR_PI, 0, NULL ); + else if ( Gia_ObjIsCo(pObj) ) + { + Str_ManNormalize_rec( pNtk, p, Gia_ObjFanin0(pObj), vGroups, vRoots ); + iFanin = Gia_ObjFanin0Copy(pObj); + pObj->Value = Str_ObjCreate( pNtk, STR_PO, 1, &iFanin ); + } + } + //assert( pNtk->nObjs <= Gia_ManObjNum(p) ); + return pNtk; +} +Str_Ntk_t * Str_ManNormalize( Gia_Man_t * p ) +{ + Str_Ntk_t * pNtk; + Gia_Man_t * pMuxes = Gia_ManDupMuxes( p, 5 ); + Vec_Wec_t * vGroups = Str_ManDeriveTrees( pMuxes ); + Vec_Int_t * vRoots; + Str_ManCheckOverlap( pMuxes, vGroups ); + vRoots = Str_ManCreateRoots( vGroups, Gia_ManObjNum(pMuxes) ); + pNtk = Str_ManNormalizeInt( pMuxes, vGroups, vRoots ); + Gia_ManCleanMark0( pMuxes ); + Gia_ManStop( pMuxes ); + Vec_IntFree( vRoots ); + Vec_WecFree( vGroups ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Delay computation] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Str_Delay2( int d0, int d1, int nLutSize ) +{ + int n, d = Abc_MaxInt( d0 >> 4, d1 >> 4 ); + n = (d == (d0 >> 4)) ? (d0 & 15) : 1; + n += (d == (d1 >> 4)) ? (d1 & 15) : 1; + return (d << 4) + (n > nLutSize ? 18 : n); +} +static inline int Str_Delay3( int d0, int d1, int d2, int nLutSize ) +{ + int n, d = Abc_MaxInt( Abc_MaxInt(d0 >> 4, d1 >> 4), d2 >> 4 ); + n = (d == (d0 >> 4)) ? (d0 & 15) : 1; + n += (d == (d1 >> 4)) ? (d1 & 15) : 1; + n += (d == (d2 >> 4)) ? (d2 & 15) : 1; + return (d << 4) + (n > nLutSize ? 19 : n); +} +static inline int Str_ObjDelay( Gia_Man_t * pNew, int iObj, int nLutSize, Vec_Int_t * vDelay ) +{ + int Delay = Vec_IntEntry( vDelay, iObj ); + if ( Delay == 0 ) + { + if ( Gia_ObjIsMuxId(pNew, iObj) ) + { + int d0 = Vec_IntEntry( vDelay, Gia_ObjFaninId0(Gia_ManObj(pNew, iObj), iObj) ); + int d1 = Vec_IntEntry( vDelay, Gia_ObjFaninId1(Gia_ManObj(pNew, iObj), iObj) ); + int d2 = Vec_IntEntry( vDelay, Gia_ObjFaninId2(pNew, iObj) ); + Delay = Str_Delay3( d0, d1, d2, nLutSize ); + } + else + { + int d0 = Vec_IntEntry( vDelay, Gia_ObjFaninId0(Gia_ManObj(pNew, iObj), iObj) ); + int d1 = Vec_IntEntry( vDelay, Gia_ObjFaninId1(Gia_ManObj(pNew, iObj), iObj) ); + Delay = Str_Delay2( d0, d1, nLutSize ); + } + Vec_IntWriteEntry( vDelay, iObj, Delay ); + } + return Delay; +} + + + +/**Function************************************************************* + + Synopsis [Transposing 64-bit matrix.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void transpose64( word A[64] ) +{ + int j, k; + word t, m = 0x00000000FFFFFFFF; + for ( j = 32; j != 0; j = j >> 1, m = m ^ (m << j) ) + { + for ( k = 0; k < 64; k = (k + j + 1) & ~j ) + { + t = (A[k] ^ (A[k+j] >> j)) & m; + A[k] = A[k] ^ t; + A[k+j] = A[k+j] ^ (t << j); + } + } +} + +/**Function************************************************************* + + Synopsis [Perform affinity computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Str_ManNum( Gia_Man_t * p, int iObj ) { return Vec_IntEntry(&p->vCopies, iObj); } +static inline void Str_ManSetNum( Gia_Man_t * p, int iObj, int Num ) { Vec_IntWriteEntry(&p->vCopies, iObj, Num); } + +int Str_ManVectorAffinity( Gia_Man_t * p, Vec_Int_t * vSuper, Vec_Int_t * vDelay, word * Matrix, int nLimit ) +{ + int fVerbose = 0; + int * Levels = NULL; + int nSize = Vec_IntSize(vSuper); + int Prev = nSize, nLevels = 1; + int i, k, iLit, iFanin, nSizeNew; + word Mask; + assert( nSize > 2 ); + assert( nSize <= nLimit ); + if ( nSize > 64 ) + { + for ( i = 0; i < 64; i++ ) + Matrix[i] = 0; + return 0; + } + Levels = ABC_ALLOC( int, nLimit+256 ); + // mark current nodes + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vSuper, iLit, i ) + { + Gia_ObjSetTravIdCurrentId( p, Abc_Lit2Var(iLit) ); + Str_ManSetNum( p, Abc_Lit2Var(iLit), i ); + Matrix[i] = ((word)1) << (63-i); + Levels[i] = 0; + } + // collect 64 nodes + Vec_IntForEachEntry( vSuper, iLit, i ) + { + Gia_Obj_t * pObj = Gia_ManObj( p, Abc_Lit2Var(iLit) ); + if ( Gia_ObjIsAnd(pObj) ) + { + for ( k = 0; k < 2; k++ ) + { + iFanin = k ? Gia_ObjFaninId1p(p, pObj) : Gia_ObjFaninId0p(p, pObj); + if ( !Gia_ObjIsTravIdCurrentId(p, iFanin) ) + { + if ( Vec_IntSize(vSuper) == nLimit ) + break; + Gia_ObjSetTravIdCurrentId( p, iFanin ); + Matrix[Vec_IntSize(vSuper)] = 0; + Levels[Vec_IntSize(vSuper)] = nLevels; + Str_ManSetNum( p, iFanin, Vec_IntSize(vSuper) ); + Vec_IntPush( vSuper, Abc_Var2Lit(iFanin, 0) ); + } + Matrix[Str_ManNum(p, iFanin)] |= Matrix[i]; + } + } + if ( Gia_ObjIsMux(p, pObj) ) + { + iFanin = Gia_ObjFaninId2p(p, pObj); + if ( !Gia_ObjIsTravIdCurrentId(p, iFanin) ) + { + if ( Vec_IntSize(vSuper) == nLimit ) + break; + Gia_ObjSetTravIdCurrentId( p, iFanin ); + Matrix[Vec_IntSize(vSuper)] = 0; + Levels[Vec_IntSize(vSuper)] = nLevels; + Str_ManSetNum( p, iFanin, Vec_IntSize(vSuper) ); + Vec_IntPush( vSuper, Abc_Var2Lit(iFanin, 0) ); + } + Matrix[Str_ManNum(p, iFanin)] |= Matrix[i]; + } + if ( Prev == i ) + Prev = Vec_IntSize(vSuper), nLevels++; + if ( nLevels == 8 ) + break; + } + + // remove those that have all 1s or only one 1 + Mask = (~(word)0) << (64 - nSize); + for ( k = i = 0; i < Vec_IntSize(vSuper); i++ ) + { + assert( Matrix[i] ); + if ( (Matrix[i] & (Matrix[i] - 1)) == 0 ) + continue; + if ( Matrix[i] == Mask ) + continue; + Matrix[k] = Matrix[i]; + Levels[k] = Levels[i]; + k++; + if ( k == 64 ) + break; + } + // clean the remaining ones + for ( i = k; i < 64; i++ ) + Matrix[i] = 0; + nSizeNew = k; + if ( nSizeNew == 0 ) + { + Vec_IntShrink( vSuper, nSize ); + ABC_FREE( Levels ); + return 0; + } +/* + // report + if ( fVerbose && nSize > 20 ) + { + for ( i = 0; i < nSizeNew; i++ ) + Extra_PrintBinary( stdout, Matrix+i, 64 ), printf( "\n" ); + printf( "\n" ); + } +*/ + transpose64( Matrix ); + + // report + if ( fVerbose && nSize > 10 ) + { + printf( "Gate inputs = %d. Collected fanins = %d. All = %d. Good = %d. Levels = %d\n", + nSize, Vec_IntSize(vSuper) - nSize, Vec_IntSize(vSuper), nSizeNew, nLevels ); + printf( " " ); + for ( i = 0; i < nSizeNew; i++ ) + printf( "%d", Levels[i] ); + printf( "\n" ); + for ( i = 0; i < nSize; i++ ) + { + printf( "%6d : ", Abc_Lit2Var(Vec_IntEntry(vSuper, i)) ); + printf( "%3d ", Vec_IntEntry(vDelay, i) >> 4 ); + printf( "%3d ", Vec_IntEntry(vDelay, i) & 15 ); +// Extra_PrintBinary( stdout, Matrix+i, 64 ), printf( "\n" ); + } + i = 0; + } + ABC_FREE( Levels ); + Vec_IntShrink( vSuper, nSize ); + return nSizeNew; +} + +/**Function************************************************************* + + Synopsis [Count 1s.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Str_CountBits( word i ) +{ + if ( i == 0 ) + return 0; + i = (i & (i - 1)); + if ( i == 0 ) + return 1; + i = (i & (i - 1)); + if ( i == 0 ) + return 2; + i = i - ((i >> 1) & 0x5555555555555555); + i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333); + i = ((i + (i >> 4)) & 0x0F0F0F0F0F0F0F0F); + return (i*(0x0101010101010101))>>56; +} + +static inline void Str_PrintState( int * pCost, int * pSuper, word * pMatrix, int nSize ) +{ + int i; + for ( i = 0; i < nSize; i++ ) + { + printf( "%6d : ", i ); + printf( "%6d : ", Abc_Lit2Var(pSuper[i]) ); + printf( "%3d ", pCost[i] >> 4 ); + printf( "%3d ", pCost[i] & 15 ); +// Extra_PrintBinary( stdout, pMatrix+i, 64 ), printf( "\n" ); + } + printf( "\n" ); +} + + +/**Function************************************************************* + + Synopsis [Perform balancing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Str_NtkBalanceMulti2( Gia_Man_t * pNew, Str_Ntk_t * p, Str_Obj_t * pObj, Vec_Int_t * vDelay, int nLutSize ) +{ + int k; + pObj->iCopy = (pObj->Type == STR_AND); + for ( k = 0; k < (int)pObj->nFanins; k++ ) + { + if ( pObj->Type == STR_AND ) + pObj->iCopy = Gia_ManHashAnd( pNew, pObj->iCopy, Str_ObjFaninCopy(p, pObj, k) ); + else + pObj->iCopy = Gia_ManHashXorReal( pNew, pObj->iCopy, Str_ObjFaninCopy(p, pObj, k) ); + Str_ObjDelay( pNew, Abc_Lit2Var(pObj->iCopy), nLutSize, vDelay ); + } +} + +int Str_NtkBalanceTwo( Gia_Man_t * pNew, Str_Ntk_t * p, Str_Obj_t * pObj, int i, int j, Vec_Int_t * vDelay, int * pCost, int * pSuper, word * pMatrix, int nSize, int nLutSize, int CostBest ) +{ + int k, iLitRes, Delay; + assert( i < j ); +// printf( "Merging node %d and %d\n", i, j ); + if ( pObj->Type == STR_AND ) + iLitRes = Gia_ManHashAnd( pNew, pSuper[i], pSuper[j] ); + else + iLitRes = Gia_ManHashXorReal( pNew, pSuper[i], pSuper[j] ); + Delay = Str_ObjDelay( pNew, Abc_Lit2Var(iLitRes), nLutSize, vDelay ); + // update + pCost[i] = Delay; + pSuper[i] = iLitRes; + pMatrix[i] |= pMatrix[j]; +// assert( (pCost[i] & 15) == CostBest || CostBest == -1 ); + // remove entry j + nSize--; + for ( k = j; k < nSize; k++ ) + { + pCost[k] = pCost[k+1]; + pSuper[k] = pSuper[k+1]; + pMatrix[k] = pMatrix[k+1]; + } + // move up the first one + nSize--; + for ( k = 0; k < nSize; k++ ) + { + if ( pCost[k] <= pCost[k+1] ) + break; + ABC_SWAP( int, pCost[k], pCost[k+1] ); + ABC_SWAP( int, pSuper[k], pSuper[k+1] ); + ABC_SWAP( word, pMatrix[k], pMatrix[k+1] ); + } + return iLitRes; +} + +void Str_NtkBalanceMulti( Gia_Man_t * pNew, Str_Ntk_t * p, Str_Obj_t * pObj, Vec_Int_t * vDelay, int nLutSize ) +{ + word * pMatrix = ABC_ALLOC( word, pObj->nFanins+256 ); + Vec_Int_t * vSuper = pNew->vSuper; + Vec_Int_t * vCosts = pNew->vStore; + int * pSuper = Vec_IntArray(vSuper); + int * pCost = Vec_IntArray(vCosts); + int k, iLit, MatrixSize = 0; + assert( (int)pObj->nFanins <= Vec_IntCap(vSuper) ); + assert( (int)pObj->nFanins <= Vec_IntCap(vCosts) ); + + // collect nodes + Vec_IntClear( vSuper ); + for ( k = 0; k < (int)pObj->nFanins; k++ ) + Vec_IntPush( vSuper, Str_ObjFaninCopy(p, pObj, k) ); + Vec_IntSort( vSuper, 0 ); + if ( pObj->Type == STR_AND ) + Gia_ManSimplifyAnd( vSuper ); + else + Gia_ManSimplifyXor( vSuper ); + assert( Vec_IntSize(vSuper) > 0 ); + if ( Vec_IntSize(vSuper) == 1 ) + { + pObj->iCopy = Vec_IntEntry(vSuper, 0); + ABC_FREE( pMatrix ); + return; + } + if ( Vec_IntSize(vSuper) == 2 ) + { + pObj->iCopy = Str_NtkBalanceTwo( pNew, p, pObj, 0, 1, vDelay, pCost, pSuper, pMatrix, 2, nLutSize, -1 ); + ABC_FREE( pMatrix ); + return; + } + + // sort by cost + Vec_IntClear( vCosts ); + Vec_IntForEachEntry( vSuper, iLit, k ) + Vec_IntPush( vCosts, Vec_IntEntry(vDelay, Abc_Lit2Var(iLit)) ); + Vec_IntSelectSortCost2( pSuper, Vec_IntSize(vSuper), pCost ); + + // compute affinity + if ( Vec_IntSize(vSuper) < 64 ) + MatrixSize = Str_ManVectorAffinity( pNew, vSuper, vCosts, pMatrix, pObj->nFanins ); + + // start the new product + while ( Vec_IntSize(vSuper) > 2 ) + { + // pair the first entry with another one on the same level + int i, iStop, iBest,iBest2; + int CostNew, CostBest, CostBest2; + int OccurNew, OccurBest, OccurBest2; + + if ( Vec_IntSize(vSuper) > 64 ) + { + Str_NtkBalanceTwo( pNew, p, pObj, 0, 1, vDelay, pCost, pSuper, pMatrix, Vec_IntSize(vSuper), nLutSize, -1 ); + vSuper->nSize--; + vCosts->nSize--; + continue; + } + + // compute affinity + if ( Vec_IntSize(vSuper) == 64 ) + MatrixSize = Str_ManVectorAffinity( pNew, vSuper, vCosts, pMatrix, pObj->nFanins ); + assert( Vec_IntSize(vSuper) <= 64 ); +// Str_PrintState( pCost, pSuper, pMatrix, Vec_IntSize(vSuper) ); + + // if the first two are PIs group them + if ( pCost[0] == 17 && pCost[1] == 17 ) + { + Str_NtkBalanceTwo( pNew, p, pObj, 0, 1, vDelay, pCost, pSuper, pMatrix, Vec_IntSize(vSuper), nLutSize, 2 ); + vSuper->nSize--; + vCosts->nSize--; + continue; + } + + // find the end of the level + for ( iStop = 0; iStop < Vec_IntSize(vSuper); iStop++ ) + if ( (pCost[iStop] >> 4) != (pCost[0] >> 4) ) + break; + // if there is only one this level, pair it with the best match in the next level + if ( iStop == 1 ) + { + iBest = iStop, OccurBest = Str_CountBits(pMatrix[0] & pMatrix[iStop]); + for ( i = iStop + 1; i < Vec_IntSize(vSuper); i++ ) + { + if ( (pCost[i] >> 4) != (pCost[iStop] >> 4) ) + break; + OccurNew = Str_CountBits(pMatrix[0] & pMatrix[i]); + if ( OccurBest < OccurNew ) + iBest = i, OccurBest = OccurNew; + } + assert( iBest > 0 && iBest < Vec_IntSize(vSuper) ); + Str_NtkBalanceTwo( pNew, p, pObj, 0, iBest, vDelay, pCost, pSuper, pMatrix, Vec_IntSize(vSuper), nLutSize, -1 ); + vSuper->nSize--; + vCosts->nSize--; + continue; + } + // pair the first entry with another one on the same level + iBest = -1; CostBest = -1; OccurBest2 = -1; OccurBest = -1; + for ( i = 1; i < iStop; i++ ) + { + CostNew = (pCost[0] & 15) + (pCost[i] & 15); + if ( CostNew > nLutSize ) + continue; + OccurNew = Str_CountBits(pMatrix[0] & pMatrix[i]); + if ( CostBest < CostNew || (CostBest == CostNew && OccurBest < OccurNew) ) + CostBest = CostNew, iBest = i, OccurBest = OccurNew; + } + // if the best found is perfect, take it + if ( CostBest == nLutSize ) + { + assert( iBest > 0 && iBest < Vec_IntSize(vSuper) ); + Str_NtkBalanceTwo( pNew, p, pObj, 0, iBest, vDelay, pCost, pSuper, pMatrix, Vec_IntSize(vSuper), nLutSize, CostBest ); + vSuper->nSize--; + vCosts->nSize--; + continue; + } + // find the best pair on this level + iBest = iBest2 = -1; CostBest = CostBest2 = -1, OccurBest = OccurBest2 = -1; + for ( i = 0; i < iStop; i++ ) + for ( k = i+1; k < iStop; k++ ) + { + CostNew = (pCost[i] & 15) + (pCost[k] & 15); + OccurNew = Str_CountBits(pMatrix[i] & pMatrix[k]); + if ( CostNew <= nLutSize ) // the same level + { + if ( OccurBest < OccurNew || (OccurBest == OccurNew && CostBest < CostNew )) + CostBest = CostNew, iBest = (i << 16) | k, OccurBest = OccurNew; + } + else // overflow to the next level + { + if ( OccurBest2 < OccurNew || (OccurBest2 == OccurNew && CostBest2 < CostNew) ) + CostBest2 = CostNew, iBest2 = (i << 16) | k, OccurBest2 = OccurNew; + } + } + if ( iBest >= 0 ) + { + assert( iBest > 0 ); + Str_NtkBalanceTwo( pNew, p, pObj, iBest>>16, iBest&0xFFFF, vDelay, pCost, pSuper, pMatrix, Vec_IntSize(vSuper), nLutSize, CostBest ); + vSuper->nSize--; + vCosts->nSize--; + continue; + } + // take any remaining pair + assert( iBest2 > 0 ); + Str_NtkBalanceTwo( pNew, p, pObj, iBest2>>16, iBest2&0xFFFF, vDelay, pCost, pSuper, pMatrix, Vec_IntSize(vSuper), nLutSize, -1 ); + vSuper->nSize--; + vCosts->nSize--; + continue; + } + pObj->iCopy = Str_NtkBalanceTwo( pNew, p, pObj, 0, 1, vDelay, pCost, pSuper, pMatrix, 2, nLutSize, -1 ); + ABC_FREE( pMatrix ); + +/* + // simple + pObj->iCopy = (pObj->Type == STR_AND); + for ( k = 0; k < Vec_IntSize(vSuper); k++ ) + { + if ( pObj->Type == STR_AND ) + pObj->iCopy = Gia_ManHashAnd( pNew, pObj->iCopy, Vec_IntEntry(vSuper, k) ); + else + pObj->iCopy = Gia_ManHashXorReal( pNew, pObj->iCopy, Vec_IntEntry(vSuper, k) ); + Str_ObjDelay( pNew, Abc_Lit2Var(pObj->iCopy), nLutSize, vDelay ); + } +*/ +} +void Str_NtkBalanceMux( Gia_Man_t * pNew, Str_Ntk_t * p, Str_Obj_t * pObj, Vec_Int_t * vDelay, int nLutSize, int nGroups, int nMuxes, int fRecursive, int fOptArea, int fVerbose ) +{ + extern int Str_MuxRestructure( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize, int fRecursive, int fOptArea, int fVerbose ); + int n, m, iRes, fUseRestruct = 1; + if ( fUseRestruct ) + { + for ( n = 0; n < nGroups; n++ ) + { + iRes = Str_MuxRestructure( pNew, p, Str_ObjId(p, pObj), nMuxes, vDelay, nLutSize, fRecursive, fOptArea, fVerbose ); + if ( iRes == -1 ) + { + for ( m = 0; m < nMuxes; m++, pObj++ ) + { + pObj->iCopy = Gia_ManHashMuxReal( pNew, Str_ObjFaninCopy(p, pObj, 2), Str_ObjFaninCopy(p, pObj, 1), Str_ObjFaninCopy(p, pObj, 0) ); + Str_ObjDelay( pNew, Abc_Lit2Var(pObj->iCopy), nLutSize, vDelay ); + } + } + else + { + pObj += nMuxes - 1; + pObj->iCopy = iRes; + pObj++; + } + } + } + else + { + for ( n = 0; n < nGroups * nMuxes; n++, pObj++ ) + { + pObj->iCopy = Gia_ManHashMuxReal( pNew, Str_ObjFaninCopy(p, pObj, 2), Str_ObjFaninCopy(p, pObj, 1), Str_ObjFaninCopy(p, pObj, 0) ); + Str_ObjDelay( pNew, Abc_Lit2Var(pObj->iCopy), nLutSize, vDelay ); + } + } +} +Gia_Man_t * Str_NtkBalance( Gia_Man_t * pGia, Str_Ntk_t * p, int nLutSize, int fUseMuxes, int fRecursive, int fOptArea, int fVerbose ) +{ + Gia_Man_t * pNew, * pTemp; + Vec_Int_t * vDelay; + Str_Obj_t * pObj; + int nGroups, nMuxes, CioId; + int arrTime, Delay = 0; + assert( nLutSize < 16 ); + assert( pGia->pMuxes == NULL ); + pNew = Gia_ManStart( Gia_ManObjNum(pGia) ); + pNew->pName = Abc_UtilStrsav( pGia->pName ); + pNew->pSpec = Abc_UtilStrsav( pGia->pSpec ); + pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc ); + Vec_IntFill( &pNew->vCopies, pNew->nObjsAlloc, -1 ); + if ( pNew->vSuper == NULL ) + pNew->vSuper = Vec_IntAlloc( 1000 ); + if ( pNew->vStore == NULL ) + pNew->vStore = Vec_IntAlloc( 1000 ); + vDelay = Vec_IntStart( 2*pNew->nObjsAlloc ); + Gia_ManHashStart( pNew ); + if ( pGia->pManTime != NULL ) // Tim_Man with unit delay 16 + { + Tim_ManInitPiArrivalAll( (Tim_Man_t *)pGia->pManTime, 17 ); + Tim_ManIncrementTravId( (Tim_Man_t *)pGia->pManTime ); + } + Str_NtkManForEachObj( p, pObj ) + { + if ( pObj->Type == STR_PI ) + { + pObj->iCopy = Gia_ManAppendCi( pNew ); + arrTime = 17; + if ( pGia->pManTime != NULL ) + { + CioId = Gia_ObjCioId( Gia_ManObj(pNew, Abc_Lit2Var(pObj->iCopy)) ); + arrTime = (int)Tim_ManGetCiArrival( (Tim_Man_t *)pGia->pManTime, CioId ); + } + Vec_IntWriteEntry( vDelay, Abc_Lit2Var(pObj->iCopy), arrTime ); + } + else if ( pObj->Type == STR_AND || pObj->Type == STR_XOR ) + Str_NtkBalanceMulti( pNew, p, pObj, vDelay, nLutSize ); + else if ( pObj->Type == STR_MUX && pObj->iTop >= 0 && fUseMuxes ) + { + Str_ObjReadGroup( p, pObj, &nGroups, &nMuxes ); + assert( nGroups * nMuxes >= 2 ); + Str_NtkBalanceMux( pNew, p, pObj, vDelay, nLutSize, nGroups, nMuxes, fRecursive, fOptArea, fVerbose ); + pObj += nGroups * nMuxes - 1; + } + else if ( pObj->Type == STR_MUX ) + { + pObj->iCopy = Gia_ManHashMuxReal( pNew, Str_ObjFaninCopy(p, pObj, 2), Str_ObjFaninCopy(p, pObj, 1), Str_ObjFaninCopy(p, pObj, 0) ); + Str_ObjDelay( pNew, Abc_Lit2Var(pObj->iCopy), nLutSize, vDelay ); + } + else if ( pObj->Type == STR_PO ) + { + pObj->iCopy = Gia_ManAppendCo( pNew, Str_ObjFaninCopy(p, pObj, 0) ); + arrTime = Vec_IntEntry(vDelay, Abc_Lit2Var(Str_ObjFaninCopy(p, pObj, 0)) ); + Delay = Abc_MaxInt( Delay, arrTime ); + if ( pGia->pManTime != NULL ) + { + CioId = Gia_ObjCioId( Gia_ManObj(pNew, Abc_Lit2Var(pObj->iCopy)) ); + Tim_ManSetCoArrival( (Tim_Man_t *)pGia->pManTime, CioId, (float)arrTime ); + } + } + else if ( pObj->Type == STR_CONST0 ) + pObj->iCopy = 0, Vec_IntWriteEntry(vDelay, 0, 17); + else assert( 0 ); + } + if ( fVerbose ) + printf( "Max delay = %d. Old objs = %d. New objs = %d.\n", Delay >> 4, Gia_ManObjNum(pGia), Gia_ManObjNum(pNew) ); + Vec_IntFree( vDelay ); + ABC_FREE( pNew->vCopies.pArray ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia) ); + pNew = Gia_ManDupNoMuxes( pTemp = pNew, 0 ); + Gia_ManStop( pTemp ); +// if ( pGia->pManTime != NULL ) +// pNew->pManTime = Tim_ManDup( (Tim_Man_t *)pGia->pManTime, 0 ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Test normalization procedure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManLutBalance( Gia_Man_t * p, int nLutSize, int fUseMuxes, int fRecursive, int fOptArea, int fVerbose ) +{ + Str_Ntk_t * pNtk; + Gia_Man_t * pNew; + abctime clk = Abc_Clock(); + if ( p->pManTime && Tim_ManBoxNum((Tim_Man_t*)p->pManTime) && Gia_ManIsNormalized(p) ) + { + Tim_Man_t * pTimOld = (Tim_Man_t *)p->pManTime; + p->pManTime = Tim_ManDup( pTimOld, 16 ); + pNew = Gia_ManDupUnnormalize( p ); + if ( pNew == NULL ) + return NULL; + Gia_ManTransferTiming( pNew, p ); + p = pNew; + // optimize + pNtk = Str_ManNormalize( p ); + pNew = Str_NtkBalance( p, pNtk, nLutSize, fUseMuxes, fRecursive, fOptArea, fVerbose ); + Gia_ManTransferTiming( pNew, p ); + Gia_ManStop( p ); + // normalize + pNew = Gia_ManDupNormalize( p = pNew, 0 ); + Gia_ManTransferTiming( pNew, p ); + Gia_ManStop( p ); + // cleanup + Tim_ManStop( (Tim_Man_t *)pNew->pManTime ); + pNew->pManTime = pTimOld; + assert( Gia_ManIsNormalized(pNew) ); + } + else + { + pNtk = Str_ManNormalize( p ); + // Str_NtkPrintGroups( pNtk ); + pNew = Str_NtkBalance( p, pNtk, nLutSize, fUseMuxes, fRecursive, fOptArea, fVerbose ); + Gia_ManTransferTiming( pNew, p ); + } + if ( fVerbose ) + Str_NtkPs( pNtk, Abc_Clock() - clk ); + Str_NtkDelete( pNtk ); + return pNew; +} + + + + + +/**Function************************************************************* + + Synopsis [Perform MUX restructuring.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +typedef struct Str_Edg_t_ Str_Edg_t; +struct Str_Edg_t_ +{ + int Fan; // fanin ID + int fCompl; // fanin complement + int FanDel; // fanin delay + int Copy; // fanin copy +}; + +typedef struct Str_Mux_t_ Str_Mux_t; // 64 bytes +struct Str_Mux_t_ +{ + int Id; // node ID + int Delay; // node delay + int Copy; // node copy + int nLutSize; // LUT size + Str_Edg_t Edge[3]; // fanins +}; + +static inline Str_Mux_t * Str_MuxFanin( Str_Mux_t * pMux, int i ) { return pMux - pMux->Id + pMux->Edge[i].Fan; } +static inline int Str_MuxHasFanin( Str_Mux_t * pMux, int i ) { return pMux->Edge[i].Fan > 0 && Str_MuxFanin(pMux, i)->Copy != -2; } + +void Str_MuxDelayPrint_rec( Str_Mux_t * pMux, int i ) +{ + int fShowDelay = 1; + Str_Mux_t * pFanin; + if ( pMux->Edge[i].Fan <= 0 ) + { + printf( "%d", -pMux->Edge[i].Fan ); + if ( fShowDelay ) + printf( "{%d}", pMux->Edge[i].FanDel ); + return; + } + pFanin = Str_MuxFanin( pMux, i ); + printf( "[ " ); + if ( pFanin->Edge[0].fCompl ) + printf( "!" ); + Str_MuxDelayPrint_rec( pFanin, 0 ); + printf( "|" ); + if ( pFanin->Edge[1].fCompl ) + printf( "!" ); + Str_MuxDelayPrint_rec( pFanin, 1 ); + printf( "(" ); + if ( pFanin->Edge[2].fCompl ) + printf( "!" ); + Str_MuxDelayPrint_rec( pFanin, 2 ); + printf( ")" ); + printf( " ]" ); +} +int Str_MuxDelayEdge_rec( Str_Mux_t * pMux, int i ) +{ + if ( pMux->Edge[i].Fan > 0 ) + { + Str_Mux_t * pFanin = Str_MuxFanin( pMux, i ); + Str_MuxDelayEdge_rec( pFanin, 0 ); + Str_MuxDelayEdge_rec( pFanin, 1 ); + pMux->Edge[i].FanDel = Str_Delay3( pFanin->Edge[0].FanDel, pFanin->Edge[1].FanDel, pFanin->Edge[2].FanDel, pFanin->nLutSize ); + } + return pMux->Edge[i].FanDel; +} +void Str_MuxCreate( Str_Mux_t * pTree, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize ) +{ + Str_Obj_t * pObj; + Str_Mux_t * pMux; + int i, k, nPis = 0; + assert( nMuxes >= 2 ); + memset( pTree, 0, sizeof(Str_Mux_t) * (nMuxes + 1) ); + pTree->nLutSize = nLutSize; + pTree->Edge[0].Fan = 1; + for ( i = 1; i <= nMuxes; i++ ) + { + pMux = pTree + i; + pMux->Id = i; + pMux->nLutSize = nLutSize; + pMux->Delay = pMux->Copy = -1; + // assign fanins + pObj = Str_NtkObj( pNtk, iMux + nMuxes - i ); + assert( pObj->Type == STR_MUX ); + for ( k = 0; k < 3; k++ ) + { + pMux->Edge[k].fCompl = Str_ObjFaninC(pNtk, pObj, k); + if ( Str_ObjFaninId(pNtk, pObj, k) >= iMux ) + pMux->Edge[k].Fan = iMux + nMuxes - Str_ObjFaninId(pNtk, pObj, k); + else + { + pMux->Edge[k].Fan = -nPis++; // count external inputs, including controls + pMux->Edge[k].Copy = Str_ObjFanin(pNtk, pObj, k)->iCopy; + pMux->Edge[k].FanDel = Vec_IntEntry( vDelay, Abc_Lit2Var(pMux->Edge[k].Copy) ); + } + } + } +} +int Str_MuxToGia_rec( Gia_Man_t * pNew, Str_Mux_t * pMux, int i, Vec_Int_t * vDelay ) +{ + if ( pMux->Edge[i].Fan > 0 ) + { + Str_Mux_t * pFanin = Str_MuxFanin( pMux, i ); + int iLit0 = Str_MuxToGia_rec( pNew, pFanin, 0, vDelay ); + int iLit1 = Str_MuxToGia_rec( pNew, pFanin, 1, vDelay ); + assert( pFanin->Edge[2].Fan <= 0 ); + assert( pFanin->Edge[2].fCompl == 0 ); + pMux->Edge[i].Copy = Gia_ManHashMuxReal( pNew, pFanin->Edge[2].Copy, iLit1, iLit0 ); + Str_ObjDelay( pNew, Abc_Lit2Var(pMux->Edge[i].Copy), pFanin->nLutSize, vDelay ); + } + return Abc_LitNotCond( pMux->Edge[i].Copy, pMux->Edge[i].fCompl ); +} +void Str_MuxChangeOnce( Str_Mux_t * pTree, int * pPath, int i, int k, Str_Mux_t * pBackup, Gia_Man_t * pNew, Vec_Int_t * vDelay ) +{ + Str_Mux_t * pSpots[3]; + int pInds[3], MidFan, MidCom, MidDel, MidCop, c; + int iRes, iCond, fCompl; + // save backup + assert( i + 1 < k ); + if ( pBackup ) + { + pBackup[0] = pTree[ Abc_Lit2Var(pPath[k]) ]; + pBackup[1] = pTree[ Abc_Lit2Var(pPath[i+1])]; + pBackup[2] = pTree[ Abc_Lit2Var(pPath[i]) ]; + } + // perform changes + pSpots[0] = pTree + Abc_Lit2Var(pPath[k]); + pSpots[1] = pTree + Abc_Lit2Var(pPath[i+1]); + pSpots[2] = pTree + Abc_Lit2Var(pPath[i]); + pInds[0] = Abc_LitIsCompl(pPath[k]); + pInds[1] = Abc_LitIsCompl(pPath[i+1]); + pInds[2] = Abc_LitIsCompl(pPath[i]); + // check + assert( pSpots[0]->Edge[pInds[0]].Fan > 0 ); + assert( pSpots[1]->Edge[pInds[1]].Fan > 0 ); + // collect complement + fCompl = 0; + for ( c = i+1; c < k; c++ ) + fCompl ^= pTree[Abc_Lit2Var(pPath[c])].Edge[Abc_LitIsCompl(pPath[c])].fCompl; + // remember bottom side + MidFan = pSpots[2]->Edge[!pInds[2]].Fan; + MidCom = pSpots[2]->Edge[!pInds[2]].fCompl; + MidDel = pSpots[2]->Edge[!pInds[2]].FanDel; + MidCop = pSpots[2]->Edge[!pInds[2]].Copy; + // update bottom + pSpots[2]->Edge[!pInds[2]].Fan = pSpots[0]->Edge[pInds[0]].Fan; + pSpots[2]->Edge[!pInds[2]].fCompl = 0; + // update top + pSpots[0]->Edge[pInds[0]].Fan = pSpots[2]->Id; + // update middle + pSpots[1]->Edge[pInds[1]].Fan = MidFan; + pSpots[1]->Edge[pInds[1]].fCompl ^= MidCom; + pSpots[1]->Edge[pInds[1]].FanDel = MidDel; + pSpots[1]->Edge[pInds[1]].Copy = MidCop; + // update delay of the control + for ( c = i + 1; c < k; c++ ) + pSpots[2]->Edge[2].FanDel = Str_Delay2( pSpots[2]->Edge[2].FanDel, pTree[Abc_Lit2Var(pPath[c])].Edge[2].FanDel, pTree->nLutSize ); + if ( pNew == NULL ) + return; + // create AND gates + iRes = 1; + for ( c = i; c < k; c++ ) + { + assert( pTree[Abc_Lit2Var(pPath[c])].Edge[2].fCompl == 0 ); + iCond = pTree[Abc_Lit2Var(pPath[c])].Edge[2].Copy; + iCond = Abc_LitNotCond( iCond, !Abc_LitIsCompl(pPath[c]) ); + iRes = Gia_ManHashAnd( pNew, iRes, iCond ); + Str_ObjDelay( pNew, Abc_Lit2Var(iRes), pTree->nLutSize, vDelay ); + } + // complement the condition + pSpots[2]->Edge[2].Copy = Abc_LitNotCond( iRes, !Abc_LitIsCompl(pPath[i]) ); + // complement the path + pSpots[2]->Edge[pInds[2]].fCompl ^= fCompl; +} +void Str_MuxChangeUndo( Str_Mux_t * pTree, int * pPath, int i, int k, Str_Mux_t * pBackup ) +{ + pTree[ Abc_Lit2Var(pPath[k]) ] = pBackup[0]; + pTree[ Abc_Lit2Var(pPath[i+1])] = pBackup[1]; + pTree[ Abc_Lit2Var(pPath[i]) ] = pBackup[2]; +} +int Str_MuxFindPathEdge_rec( Str_Mux_t * pMux, int i, int * pPath, int * pnLength ) +{ + extern int Str_MuxFindPath_rec( Str_Mux_t * pMux, int * pPath, int * pnLength ); + if ( pMux->Edge[i].Fan > 0 && !Str_MuxFindPath_rec(Str_MuxFanin(pMux, i), pPath, pnLength) ) + return 0; + pPath[ (*pnLength)++ ] = Abc_Var2Lit(pMux->Id, i); + return 1; +} +int Str_MuxFindPath_rec( Str_Mux_t * pMux, int * pPath, int * pnLength ) +{ + int i, DelayMax = Abc_MaxInt( pMux->Edge[0].FanDel, Abc_MaxInt(pMux->Edge[1].FanDel, pMux->Edge[2].FanDel) ); + for ( i = 0; i < 2; i++ ) + if ( pMux->Edge[i].FanDel == DelayMax ) + return Str_MuxFindPathEdge_rec( pMux, i, pPath, pnLength ); + if ( pMux->Edge[2].FanDel == DelayMax ) + return 0; + assert( 0 ); + return -1; +} +// return node whose both branches are non-trivial +Str_Mux_t * Str_MuxFindBranching( Str_Mux_t * pRoot, int i ) +{ + Str_Mux_t * pMux; + if ( pRoot->Edge[i].Fan <= 0 ) + return NULL; + pMux = Str_MuxFanin( pRoot, i ); + while ( 1 ) + { + if ( pMux->Edge[0].Fan <= 0 && pMux->Edge[1].Fan <= 0 ) + return NULL; + if ( pMux->Edge[0].Fan > 0 && pMux->Edge[1].Fan > 0 ) + return pMux; + if ( pMux->Edge[0].Fan > 0 ) + pMux = Str_MuxFanin( pMux, 0 ); + if ( pMux->Edge[1].Fan > 0 ) + pMux = Str_MuxFanin( pMux, 1 ); + } + assert( 0 ); + return NULL; +} +int Str_MuxTryOnce( Gia_Man_t * pNew, Str_Ntk_t * pNtk, Str_Mux_t * pTree, Str_Mux_t * pRoot, int Edge, Vec_Int_t * vDelay, int fVerbose ) +{ + int pPath[MAX_TREE]; + Str_Mux_t pBackup[3]; + int Delay, DelayBest = Str_MuxDelayEdge_rec( pRoot, Edge ), DelayInit = DelayBest; + int i, k, nLength = 0, ForkBest = -1, nChecks = 0; + int RetValue = Str_MuxFindPathEdge_rec( pRoot, Edge, pPath, &nLength ); + if ( RetValue == 0 ) + return 0; + if ( fVerbose ) + printf( "Trying node %d with path of length %d.\n", pRoot->Id, nLength ); + for ( i = 0; i < nLength; i++ ) + for ( k = i+2; k < nLength; k++ ) + { + Str_MuxChangeOnce( pTree, pPath, i, k, pBackup, NULL, NULL ); + Delay = Str_MuxDelayEdge_rec( pRoot, Edge ); + Str_MuxChangeUndo( pTree, pPath, i, k, pBackup ); + if ( DelayBest > Delay || (ForkBest > 0 && DelayBest == Delay) ) + DelayBest = Delay, ForkBest = (i << 16) | k; + if ( fVerbose ) + printf( "%2d %2d -> %3d (%3d)\n", i, k, Delay, DelayBest ); + nChecks++; + } + if ( ForkBest == -1 ) + { + if ( fVerbose ) + printf( "Did not find!\n" ); + return 0; + } +// Str_MuxDelayPrint_rec( pRoot, Edge ); printf( "\n" ); + Str_MuxChangeOnce( pTree, pPath, ForkBest >> 16, ForkBest & 0xFFFF, NULL, pNew, vDelay ); +// Str_MuxDelayPrint_rec( pRoot, Edge ); printf( "\n" ); + if ( fVerbose ) + printf( "Node %6d (%3d %3d) : Checks = %d. Delay: %d -> %d.\n", + pRoot->Id, ForkBest >> 16, ForkBest & 0xFFFF, nChecks, DelayInit, DelayBest ); + if ( fVerbose ) + printf( "\n" ); + return 1; +} +int Str_MuxRestruct_rec( Gia_Man_t * pNew, Str_Ntk_t * pNtk, Str_Mux_t * pTree, Str_Mux_t * pRoot, int Edge, Vec_Int_t * vDelay, int fVerbose ) +{ + int fChanges = 0; + Str_Mux_t * pMux = Str_MuxFindBranching( pRoot, Edge ); + if ( pMux != NULL ) + fChanges |= Str_MuxRestruct_rec( pNew, pNtk, pTree, pMux, 0, vDelay, fVerbose ); + if ( pMux != NULL ) + fChanges |= Str_MuxRestruct_rec( pNew, pNtk, pTree, pMux, 1, vDelay, fVerbose ); + fChanges |= Str_MuxTryOnce( pNew, pNtk, pTree, pRoot, Edge, vDelay, fVerbose ); + return fChanges; +} +int Str_MuxRestructure2( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize, int fVerbose ) +{ + int Limit = MAX_TREE; + Str_Mux_t pTree[MAX_TREE]; + int Delay, Delay2, fChanges = 0; + if ( nMuxes >= Limit ) + return -1; + assert( nMuxes < Limit ); + Str_MuxCreate( pTree, pNtk, iMux, nMuxes, vDelay, nLutSize ); + Delay = Str_MuxDelayEdge_rec( pTree, 0 ); + while ( 1 ) + { + if ( !Str_MuxRestruct_rec(pNew, pNtk, pTree, pTree, 0, vDelay, fVerbose) ) + break; + fChanges = 1; + } + if ( !fChanges ) + return -1; + Delay2 = Str_MuxDelayEdge_rec( pTree, 0 ); +// printf( "Improved delay for tree %d with %d MUXes (%d -> %d).\n", iMux, nMuxes, Delay, Delay2 ); + pNtk->DelayGain += Delay - Delay2; + return Str_MuxToGia_rec( pNew, pTree, 0, vDelay ); +} +int Str_MuxRestructure1( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize, int fVerbose ) +{ + int Limit = MAX_TREE; + Str_Mux_t pTree[MAX_TREE]; + int Delay, Delay2, fChanges = 0; + if ( nMuxes >= Limit ) + return -1; + assert( nMuxes < Limit ); + Str_MuxCreate( pTree, pNtk, iMux, nMuxes, vDelay, nLutSize ); + Delay = Str_MuxDelayEdge_rec( pTree, 0 ); + while ( 1 ) + { + if ( !Str_MuxTryOnce(pNew, pNtk, pTree, pTree, 0, vDelay, fVerbose) ) + break; + fChanges = 1; + } + if ( !fChanges ) + return -1; + Delay2 = Str_MuxDelayEdge_rec( pTree, 0 ); +// printf( "Improved delay for tree %d with %d MUXes (%d -> %d).\n", iMux, nMuxes, Delay, Delay2 ); + pNtk->DelayGain += Delay - Delay2; + return Str_MuxToGia_rec( pNew, pTree, 0, vDelay ); +} +int Str_MuxRestructure( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize, int fRecursive, int fOptArea, int fVerbose ) +{ + extern int Str_MuxRestructureArea( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize, int fVerbose ); + if ( fOptArea ) + { + if ( nMuxes < 2 ) + return Str_MuxRestructure1( pNew, pNtk, iMux, nMuxes, vDelay, nLutSize, fVerbose ); + return Str_MuxRestructureArea( pNew, pNtk, iMux, nMuxes, vDelay, nLutSize, fVerbose ); + } + if ( fRecursive ) + return Str_MuxRestructure2( pNew, pNtk, iMux, nMuxes, vDelay, nLutSize, fVerbose ); + return Str_MuxRestructure1( pNew, pNtk, iMux, nMuxes, vDelay, nLutSize, fVerbose ); +} + +/**Function************************************************************* + + Synopsis [Perform MUX restructuring for area.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Str_MuxRestructAreaThree( Gia_Man_t * pNew, Str_Mux_t * pMux, Vec_Int_t * vDelay, int fVerbose ) +{ + int iRes; + Str_Mux_t * pFanin0 = Str_MuxFanin( pMux, 0 ); + Str_Mux_t * pFanin1 = Str_MuxFanin( pMux, 1 ); + assert( pMux->Copy == -1 ); + pMux->Copy = -2; + if ( pFanin0->Edge[2].Copy == pFanin1->Edge[2].Copy ) + return 0; + iRes = Gia_ManHashMuxReal( pNew, pMux->Edge[2].Copy, pFanin1->Edge[2].Copy, pFanin0->Edge[2].Copy ); + Str_ObjDelay( pNew, Abc_Lit2Var(iRes), pMux->nLutSize, vDelay ); + pFanin0->Edge[2].Copy = pFanin1->Edge[2].Copy = iRes; +// printf( "Created triple\n" ); + return 0; +} +int Str_MuxRestructArea_rec( Gia_Man_t * pNew, Str_Mux_t * pTree, Str_Mux_t * pRoot, int i, Vec_Int_t * vDelay, int fVerbose ) +{ + int Path[4]; + int fSkipMoving = 1; + Str_Mux_t * pMux, * pFanin0, * pFanin1; + int nMuxes0, nMuxes1; + if ( pRoot->Edge[i].Fan <= 0 ) + return 0; + pMux = Str_MuxFanin( pRoot, i ); + nMuxes0 = Str_MuxRestructArea_rec( pNew, pTree, pMux, 0, vDelay, fVerbose ); + nMuxes1 = Str_MuxRestructArea_rec( pNew, pTree, pMux, 1, vDelay, fVerbose ); + if ( nMuxes0 + nMuxes1 < 2 ) + return 1 + nMuxes0 + nMuxes1; + if ( nMuxes0 + nMuxes1 == 2 ) + { + if ( nMuxes0 == 2 || nMuxes1 == 2 ) + { + pFanin0 = Str_MuxFanin( pMux, (int)(nMuxes1 == 2) ); + assert( Str_MuxHasFanin(pFanin0, 0) != Str_MuxHasFanin(pFanin0, 1) ); + Path[2] = Abc_Var2Lit(pRoot->Id, i); + Path[1] = Abc_Var2Lit(pMux->Id, (int)(nMuxes1 == 2) ); + Path[0] = Abc_Var2Lit(pFanin0->Id, Str_MuxHasFanin(pFanin0, 1)); + Str_MuxChangeOnce( pTree, Path, 0, 2, NULL, pNew, vDelay ); + } + Str_MuxRestructAreaThree( pNew, Str_MuxFanin(pRoot, i), vDelay, fVerbose ); + return 0; + } + assert( nMuxes0 + nMuxes1 == 3 || nMuxes0 + nMuxes1 == 4 ); + assert( nMuxes0 == 2 || nMuxes1 == 2 ); + if ( fSkipMoving ) + { + Str_MuxRestructAreaThree( pNew, pMux, vDelay, fVerbose ); + return 0; + } + if ( nMuxes0 == 2 ) + { + pFanin0 = Str_MuxFanin( pMux, 0 ); + assert( Str_MuxHasFanin(pFanin0, 0) != Str_MuxHasFanin(pFanin0, 1) ); + Path[3] = Abc_Var2Lit(pRoot->Id, i); + Path[2] = Abc_Var2Lit(pMux->Id, 0 ); + Path[1] = Abc_Var2Lit(pFanin0->Id, Str_MuxHasFanin(pFanin0, 1)); + pFanin1 = Str_MuxFanin( pFanin0, Str_MuxHasFanin(pFanin0, 1) ); + assert( !Str_MuxHasFanin(pFanin1, 0) && !Str_MuxHasFanin(pFanin1, 1) ); + Path[0] = Abc_Var2Lit(pFanin1->Id, 0); + Str_MuxChangeOnce( pTree, Path, 0, 3, NULL, pNew, vDelay ); + } + if ( nMuxes1 == 2 ) + { + pFanin0 = Str_MuxFanin( pMux, 1 ); + assert( Str_MuxHasFanin(pFanin0, 0) != Str_MuxHasFanin(pFanin0, 1) ); + Path[3] = Abc_Var2Lit(pRoot->Id, i); + Path[2] = Abc_Var2Lit(pMux->Id, 1 ); + Path[1] = Abc_Var2Lit(pFanin0->Id, Str_MuxHasFanin(pFanin0, 1)); + pFanin1 = Str_MuxFanin( pFanin0, Str_MuxHasFanin(pFanin0, 1) ); + assert( !Str_MuxHasFanin(pFanin1, 0) && !Str_MuxHasFanin(pFanin1, 1) ); + Path[0] = Abc_Var2Lit(pFanin1->Id, 0); + Str_MuxChangeOnce( pTree, Path, 0, 3, NULL, pNew, vDelay ); + } + Str_MuxRestructAreaThree( pNew, pMux, vDelay, fVerbose ); + return nMuxes0 + nMuxes1 - 2; +} +int Str_MuxRestructureArea( Gia_Man_t * pNew, Str_Ntk_t * pNtk, int iMux, int nMuxes, Vec_Int_t * vDelay, int nLutSize, int fVerbose ) +{ + int Limit = MAX_TREE; + Str_Mux_t pTree[MAX_TREE]; + int Result; + if ( nMuxes >= Limit ) + return -1; + assert( nMuxes < Limit ); + Str_MuxCreate( pTree, pNtk, iMux, nMuxes, vDelay, nLutSize ); + Result = Str_MuxRestructArea_rec( pNew, pTree, pTree, 0, vDelay, fVerbose ); + assert( Result >= 0 && Result <= 2 ); + return Str_MuxToGia_rec( pNew, pTree, 0, vDelay ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaSupMin.c b/yosys/abc/src/aig/gia/giaSupMin.c new file mode 100644 index 00000000000..248587a073b --- /dev/null +++ b/yosys/abc/src/aig/gia/giaSupMin.c @@ -0,0 +1,165 @@ +/**CFile**************************************************************** + + FileName [giaSupMin.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Support minimization for AIGs with don't-cares.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSupMin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "bool/kit/kit.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// decomposition manager +typedef struct Gia_ManSup_t_ Gia_ManSup_t; +struct Gia_ManSup_t_ +{ + int nVarsMax; // the max number of variables + int nWordsMax; // the max number of words + Vec_Ptr_t * vTruthVars; // elementary truth tables + Vec_Ptr_t * vTruthNodes; // internal truth tables + // current problem + Gia_Man_t * pGia; + int iData; + int iCare; + Vec_Int_t * vConeCare; + Vec_Int_t * vConeData; + unsigned * pTruthIn; + unsigned * pTruthOut; +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts Decmetry manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_ManSup_t * Gia_ManSupStart( int nVarsMax ) +{ + Gia_ManSup_t * p; + assert( nVarsMax <= 20 ); + p = ABC_CALLOC( Gia_ManSup_t, 1 ); + p->nVarsMax = nVarsMax; + p->nWordsMax = Kit_TruthWordNum( p->nVarsMax ); + p->vTruthVars = Vec_PtrAllocTruthTables( p->nVarsMax ); + p->vTruthNodes = Vec_PtrAllocSimInfo( 512, p->nWordsMax ); + p->vConeCare = Vec_IntAlloc( 512 ); + p->vConeData = Vec_IntAlloc( 512 ); + p->pTruthIn = ABC_ALLOC( unsigned, p->nWordsMax ); + p->pTruthOut = ABC_ALLOC( unsigned, p->nWordsMax ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops Decmetry manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSupStop( Gia_ManSup_t * p ) +{ + ABC_FREE( p->pTruthIn ); + ABC_FREE( p->pTruthOut ); + Vec_IntFreeP( &p->vConeCare ); + Vec_IntFreeP( &p->vConeData ); + Vec_PtrFreeP( &p->vTruthVars ); + Vec_PtrFreeP( &p->vTruthNodes ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSupExperimentOne( Gia_ManSup_t * p, Gia_Obj_t * pData, Gia_Obj_t * pCare ) +{ + int iData = Gia_ObjId( p->pGia, Gia_Regular(pData) ); + int iCare = Gia_ObjId( p->pGia, Gia_Regular(pCare) ); + if ( !Gia_ObjIsAnd(Gia_Regular(pCare)) ) + { + Abc_Print( 1, "Enable is not an AND.\n" ); + return; + } + Abc_Print( 1, "DataSupp = %6d. DataCone = %6d. CareSupp = %6d. CareCone = %6d.", + Gia_ManSuppSize( p->pGia, &iData, 1 ), + Gia_ManConeSize( p->pGia, &iData, 1 ), + Gia_ManSuppSize( p->pGia, &iCare, 1 ), + Gia_ManConeSize( p->pGia, &iCare, 1 ) ); + Abc_Print( 1, "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSupExperiment( Gia_Man_t * pGia, Vec_Int_t * vPairs ) +{ + Gia_ManSup_t * p; + Gia_Obj_t * pData, * pCare; + int i; + p = Gia_ManSupStart( 16 ); + p->pGia = pGia; + assert( Vec_IntSize(vPairs) % 2 == 0 ); + for ( i = 0; i < Vec_IntSize(vPairs)/2; i++ ) + { + Abc_Print( 1, "%6d : ", i ); + pData = Gia_ManPo( pGia, Vec_IntEntry(vPairs, 2*i+0) ); + pCare = Gia_ManPo( pGia, Vec_IntEntry(vPairs, 2*i+1) ); + Gia_ManSupExperimentOne( p, Gia_ObjChild0(pData), Gia_ObjChild0(pCare) ); + } + Gia_ManSupStop( p ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaSupp.c b/yosys/abc/src/aig/gia/giaSupp.c new file mode 100644 index 00000000000..272c94c6453 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaSupp.c @@ -0,0 +1,886 @@ +/**CFile**************************************************************** + + FileName [giaSupp.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Support minimization for AIGs.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSupp.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "sat/satoko/satoko.h" + +#ifdef ABC_USE_CUDD +#include "bdd/extrab/extraBdd.h" +#endif + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#ifdef ABC_USE_CUDD + +struct Gia_ManMin_t_ +{ + // problem formulation + Gia_Man_t * pGia; + int iLits[2]; + // structural information + Vec_Int_t * vCis[2]; + Vec_Int_t * vObjs[2]; + Vec_Int_t * vCleared; + // intermediate functions + DdManager * dd; + Vec_Ptr_t * vFuncs; + Vec_Int_t * vSupp; +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Create/delete the data representation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_ManMin_t * Gia_ManSuppStart( Gia_Man_t * pGia ) +{ + Gia_ManMin_t * p; + p = ABC_CALLOC( Gia_ManMin_t, 1 ); + p->pGia = pGia; + p->vCis[0] = Vec_IntAlloc( 512 ); + p->vCis[1] = Vec_IntAlloc( 512 ); + p->vObjs[0] = Vec_IntAlloc( 512 ); + p->vObjs[1] = Vec_IntAlloc( 512 ); + p->vCleared = Vec_IntAlloc( 512 ); + p->dd = Cudd_Init( 0, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); +// Cudd_AutodynEnable( p->dd, CUDD_REORDER_SYMM_SIFT ); + Cudd_AutodynDisable( p->dd ); + p->vFuncs = Vec_PtrAlloc( 10000 ); + p->vSupp = Vec_IntAlloc( 10000 ); + return p; +} +void Gia_ManSuppStop( Gia_ManMin_t * p ) +{ + Vec_IntFreeP( &p->vCis[0] ); + Vec_IntFreeP( &p->vCis[1] ); + Vec_IntFreeP( &p->vObjs[0] ); + Vec_IntFreeP( &p->vObjs[1] ); + Vec_IntFreeP( &p->vCleared ); + Vec_PtrFreeP( &p->vFuncs ); + Vec_IntFreeP( &p->vSupp ); + printf( "Refs = %d. \n", Cudd_CheckZeroRef( p->dd ) ); + Cudd_Quit( p->dd ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Compute variables, which are not in the support.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManFindRemoved( Gia_ManMin_t * p ) +{ + extern void ddSupportStep2( DdNode * f, int * support ); + extern void ddClearFlag2( DdNode * f ); + + //int fVerbose = 1; + int nBddLimit = 100000; + int nPart0 = Vec_IntSize(p->vCis[0]); + int n, i, iObj, nVars = 0; + DdNode * bFunc0, * bFunc1, * bFunc; + Vec_PtrFillExtra( p->vFuncs, Gia_ManObjNum(p->pGia), NULL ); + // assign variables + for ( n = 0; n < 2; n++ ) + Vec_IntForEachEntry( p->vCis[n], iObj, i ) + Vec_PtrWriteEntry( p->vFuncs, iObj, Cudd_bddIthVar(p->dd, nVars++) ); + // create nodes + for ( n = 0; n < 2; n++ ) + Vec_IntForEachEntry( p->vObjs[n], iObj, i ) + { + Gia_Obj_t * pObj = Gia_ManObj( p->pGia, iObj ); + bFunc0 = Cudd_NotCond( (DdNode *)Vec_PtrEntry(p->vFuncs, Gia_ObjFaninId0(pObj, iObj)), Gia_ObjFaninC0(pObj) ); + bFunc1 = Cudd_NotCond( (DdNode *)Vec_PtrEntry(p->vFuncs, Gia_ObjFaninId1(pObj, iObj)), Gia_ObjFaninC1(pObj) ); + bFunc = Cudd_bddAndLimit( p->dd, bFunc0, bFunc1, nBddLimit ); + assert( bFunc != NULL ); + Cudd_Ref( bFunc ); + Vec_PtrWriteEntry( p->vFuncs, iObj, bFunc ); + } + // create new node + bFunc0 = Cudd_NotCond( (DdNode *)Vec_PtrEntry(p->vFuncs, Abc_Lit2Var(p->iLits[0])), Abc_LitIsCompl(p->iLits[0]) ); + bFunc1 = Cudd_NotCond( (DdNode *)Vec_PtrEntry(p->vFuncs, Abc_Lit2Var(p->iLits[1])), Abc_LitIsCompl(p->iLits[1]) ); + bFunc = Cudd_bddAndLimit( p->dd, bFunc0, bFunc1, nBddLimit ); + assert( bFunc != NULL ); + Cudd_Ref( bFunc ); + //if ( fVerbose ) Extra_bddPrint( p->dd, bFunc ), printf( "\n" ); + // collect support + Vec_IntFill( p->vSupp, nVars, 0 ); + ddSupportStep2( Cudd_Regular(bFunc), Vec_IntArray(p->vSupp) ); + ddClearFlag2( Cudd_Regular(bFunc) ); + // find variables not present in the support + Vec_IntClear( p->vCleared ); + for ( i = 0; i < nVars; i++ ) + if ( Vec_IntEntry(p->vSupp, i) == 0 ) + Vec_IntPush( p->vCleared, i < nPart0 ? Vec_IntEntry(p->vCis[0], i) : Vec_IntEntry(p->vCis[1], i-nPart0) ); + //printf( "%d(%d)%d ", Cudd_SupportSize(p->dd, bFunc), Vec_IntSize(p->vCleared), Cudd_DagSize(bFunc) ); + // deref results + Cudd_RecursiveDeref( p->dd, bFunc ); + for ( n = 0; n < 2; n++ ) + Vec_IntForEachEntry( p->vObjs[n], iObj, i ) + Cudd_RecursiveDeref( p->dd, (DdNode *)Vec_PtrEntry(p->vFuncs, iObj) ); + //Vec_IntPrint( p->vCleared ); + return Vec_IntSize(p->vCleared); +} + +/**Function************************************************************* + + Synopsis [Compute variables, which are not in the support.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManRebuildOne( Gia_ManMin_t * p, int n ) +{ + int i, iObj, iGiaLitNew = -1; + Vec_Int_t * vTempIns = p->vCis[n]; + Vec_Int_t * vTempNds = p->vObjs[n]; + Vec_Int_t * vCopies = &p->pGia->vCopies; + Vec_IntFillExtra( vCopies, Gia_ManObjNum(p->pGia), -1 ); + assert( p->iLits[n] >= 2 ); + // process inputs + Vec_IntForEachEntry( vTempIns, iObj, i ) + Vec_IntWriteEntry( vCopies, iObj, Abc_Var2Lit(iObj, 0) ); + // process constants + assert( Vec_IntSize(p->vCleared) > 0 ); + Vec_IntForEachEntry( p->vCleared, iObj, i ) + Vec_IntWriteEntry( vCopies, iObj, 0 ); + if ( Vec_IntSize(vTempNds) == 0 ) + iGiaLitNew = Vec_IntEntry( vCopies, Abc_Lit2Var(p->iLits[n]) ); + else + { + Vec_IntForEachEntry( vTempNds, iObj, i ) + { + Gia_Obj_t * pObj = Gia_ManObj( p->pGia, iObj ); + int iGiaLit0 = Vec_IntEntry( vCopies, Gia_ObjFaninId0p(p->pGia, pObj) ); + int iGiaLit1 = Vec_IntEntry( vCopies, Gia_ObjFaninId1p(p->pGia, pObj) ); + iGiaLit0 = Abc_LitNotCond( iGiaLit0, Gia_ObjFaninC0(pObj) ); + iGiaLit1 = Abc_LitNotCond( iGiaLit1, Gia_ObjFaninC1(pObj) ); + iGiaLitNew = Gia_ManHashAnd( p->pGia, iGiaLit0, iGiaLit1 ); + Vec_IntWriteEntry( vCopies, iObj, iGiaLitNew ); + } + assert( Abc_Lit2Var(p->iLits[n]) == iObj ); + } + return Abc_LitNotCond( iGiaLitNew, Abc_LitIsCompl(p->iLits[n]) ); +} + +/**Function************************************************************* + + Synopsis [Collect nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManGatherSupp_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vCis, Vec_Int_t * vObjs ) +{ + int Val0, Val1; + Gia_Obj_t * pObj; + if ( Gia_ObjIsTravIdPreviousId(p, iObj) ) + return 1; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return 0; + Gia_ObjSetTravIdCurrentId(p, iObj); + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + { + Vec_IntPush( vCis, iObj ); + return 0; + } + assert( Gia_ObjIsAnd(pObj) ); + Val0 = Gia_ManGatherSupp_rec( p, Gia_ObjFaninId0(pObj, iObj), vCis, vObjs ); + Val1 = Gia_ManGatherSupp_rec( p, Gia_ObjFaninId1(pObj, iObj), vCis, vObjs ); + Vec_IntPush( vObjs, iObj ); + return Val0 || Val1; +} +int Gia_ManGatherSupp( Gia_ManMin_t * p ) +{ + int n, Overlap = 0; + Gia_ManIncrementTravId( p->pGia ); + for ( n = 0; n < 2; n++ ) + { + Vec_IntClear( p->vCis[n] ); + Vec_IntClear( p->vObjs[n] ); + Gia_ManIncrementTravId( p->pGia ); + Overlap = Gia_ManGatherSupp_rec( p->pGia, Abc_Lit2Var(p->iLits[n]), p->vCis[n], p->vObjs[n] ); + assert( n || !Overlap ); + } + return Overlap; +} + +/**Function************************************************************* + + Synopsis [Takes a literal and returns a support-minized literal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSupportAnd( Gia_ManMin_t * p, int iLit0, int iLit1 ) +{ + int iLitNew0, iLitNew1; + p->iLits[0] = iLit0; + p->iLits[1] = iLit1; + if ( iLit0 < 2 || iLit1 < 2 || !Gia_ManGatherSupp(p) || !Gia_ManFindRemoved(p) ) + return Gia_ManHashAnd( p->pGia, iLit0, iLit1 ); + iLitNew0 = Gia_ManRebuildOne( p, 0 ); + iLitNew1 = Gia_ManRebuildOne( p, 1 ); + return Gia_ManHashAnd( p->pGia, iLitNew0, iLitNew1 ); +} + + +#else + +Gia_ManMin_t * Gia_ManSuppStart( Gia_Man_t * pGia ) { return NULL; } +int Gia_ManSupportAnd( Gia_ManMin_t * p, int iLit0, int iLit1 ) { return 0; } +void Gia_ManSuppStop( Gia_ManMin_t * p ) {} + +#endif + + +/**Function************************************************************* + + Synopsis [Testbench.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManSupportAndTest( Gia_Man_t * pGia ) +{ + Gia_ManMin_t * pMan; + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i; + Gia_ManFillValue( pGia ); + pNew = Gia_ManStart( Gia_ManObjNum(pGia) ); + pNew->pName = Abc_UtilStrsav( pGia->pName ); + pNew->pSpec = Abc_UtilStrsav( pGia->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManConst0(pGia)->Value = 0; + pMan = Gia_ManSuppStart( pNew ); + Gia_ManForEachObj1( pGia, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + { +// pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + pObj->Value = Gia_ManSupportAnd( pMan, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + else assert( 0 ); + + if ( i % 10000 == 0 ) + printf( "%d\n", i ); + } + Gia_ManSuppStop( pMan ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + + + + +struct Gia_Man2Min_t_ +{ + // problem formulation + Gia_Man_t * pGia; + int iLits[2]; + // structural information + Vec_Int_t * vCis[2]; + Vec_Int_t * vObjs[2]; + // SAT solving + satoko_t * pSat; // SAT solver + Vec_Wrd_t * vSims; // simulation + Vec_Ptr_t * vFrontier; // CNF construction + Vec_Ptr_t * vFanins; // CNF construction + Vec_Int_t * vSatVars; // nodes + int nCisOld; // previous number of CIs + int iPattern; // the next pattern to write + int nSatSat; + int nSatUnsat; + int nCalls; + int nSims; + int nSupps; +}; + +static inline int Gia_Min2ObjSatId( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Gia_ObjCopyArray(p, Gia_ObjId(p, pObj)); } +static inline int Gia_Min2ObjSetSatId( Gia_Man_t * p, Gia_Obj_t * pObj, int Num ) { assert(Gia_Min2ObjSatId(p, pObj) == -1); Gia_ObjSetCopyArray(p, Gia_ObjId(p, pObj), Num); return Num; } +static inline void Gia_Min2ObjCleanSatId( Gia_Man_t * p, Gia_Obj_t * pObj ) { assert(Gia_Min2ObjSatId(p, pObj) != -1); Gia_ObjSetCopyArray(p, Gia_ObjId(p, pObj), -1); } + + +/**Function************************************************************* + + Synopsis [Create/delete the data representation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man2Min_t * Gia_Man2SuppStart( Gia_Man_t * pGia ) +{ + Gia_Man2Min_t * p; + p = ABC_CALLOC( Gia_Man2Min_t, 1 ); + p->pGia = pGia; + p->vCis[0] = Vec_IntAlloc( 512 ); + p->vCis[1] = Vec_IntAlloc( 512 ); + p->vObjs[0] = Vec_IntAlloc( 512 ); + p->vObjs[1] = Vec_IntAlloc( 512 ); + // SAT solving + p->pSat = satoko_create(); + p->vSims = Vec_WrdAlloc( 1000 ); + p->vFrontier = Vec_PtrAlloc( 1000 ); + p->vFanins = Vec_PtrAlloc( 100 ); + p->vSatVars = Vec_IntAlloc( 100 ); + p->iPattern = 1; + satoko_options(p->pSat)->learnt_ratio = 0; // prevent garbage collection + return p; +} +void Gia_Man2SuppStop( Gia_Man2Min_t * p ) +{ +// printf( "Total calls = %8d. Supps = %6d. Sims = %6d. SAT = %6d. UNSAT = %6d.\n", +// p->nCalls, p->nSupps, p->nSims, p->nSatSat, p->nSatUnsat ); + Vec_IntFreeP( &p->vCis[0] ); + Vec_IntFreeP( &p->vCis[1] ); + Vec_IntFreeP( &p->vObjs[0] ); + Vec_IntFreeP( &p->vObjs[1] ); + Gia_ManCleanMark01( p->pGia ); + satoko_destroy( p->pSat ); + Vec_WrdFreeP( &p->vSims ); + Vec_PtrFreeP( &p->vFrontier ); + Vec_PtrFreeP( &p->vFanins ); + Vec_IntFreeP( &p->vSatVars ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Adds clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_Min2AddClausesMux( Gia_Man_t * p, Gia_Obj_t * pNode, satoko_t * pSat ) +{ + int fPolarFlip = 0; + Gia_Obj_t * pNodeI, * pNodeT, * pNodeE; + int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; + + assert( !Gia_IsComplement( pNode ) ); + assert( pNode->fMark0 ); + // get nodes (I = if, T = then, E = else) + pNodeI = Gia_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); + // get the variable numbers + VarF = Gia_Min2ObjSatId(p, pNode); + VarI = Gia_Min2ObjSatId(p, pNodeI); + VarT = Gia_Min2ObjSatId(p, Gia_Regular(pNodeT)); + VarE = Gia_Min2ObjSatId(p, Gia_Regular(pNodeE)); + // get the complementation flags + fCompT = Gia_IsComplement(pNodeT); + fCompE = Gia_IsComplement(pNodeE); + + // f = ITE(i, t, e) + + // i' + t' + f + // i' + t + f' + // i + e' + f + // i + e + f' + + // create four clauses + pLits[0] = Abc_Var2Lit(VarI, 1); + pLits[1] = Abc_Var2Lit(VarT, 1^fCompT); + pLits[2] = Abc_Var2Lit(VarF, 0); + if ( fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = Abc_LitNot( pLits[0] ); + if ( Gia_Regular(pNodeT)->fPhase ) pLits[1] = Abc_LitNot( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = Abc_LitNot( pLits[2] ); + } + RetValue = satoko_add_clause( pSat, pLits, 3 ); + assert( RetValue ); + pLits[0] = Abc_Var2Lit(VarI, 1); + pLits[1] = Abc_Var2Lit(VarT, 0^fCompT); + pLits[2] = Abc_Var2Lit(VarF, 1); + if ( fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = Abc_LitNot( pLits[0] ); + if ( Gia_Regular(pNodeT)->fPhase ) pLits[1] = Abc_LitNot( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = Abc_LitNot( pLits[2] ); + } + RetValue = satoko_add_clause( pSat, pLits, 3 ); + assert( RetValue ); + pLits[0] = Abc_Var2Lit(VarI, 0); + pLits[1] = Abc_Var2Lit(VarE, 1^fCompE); + pLits[2] = Abc_Var2Lit(VarF, 0); + if ( fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = Abc_LitNot( pLits[0] ); + if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = Abc_LitNot( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = Abc_LitNot( pLits[2] ); + } + RetValue = satoko_add_clause( pSat, pLits, 3 ); + assert( RetValue ); + pLits[0] = Abc_Var2Lit(VarI, 0); + pLits[1] = Abc_Var2Lit(VarE, 0^fCompE); + pLits[2] = Abc_Var2Lit(VarF, 1); + if ( fPolarFlip ) + { + if ( pNodeI->fPhase ) pLits[0] = Abc_LitNot( pLits[0] ); + if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = Abc_LitNot( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = Abc_LitNot( pLits[2] ); + } + RetValue = satoko_add_clause( pSat, pLits, 3 ); + assert( RetValue ); + + // two additional clauses + // t' & e' -> f' + // t & e -> f + + // t + e + f' + // t' + e' + f + + if ( VarT == VarE ) + { +// assert( fCompT == !fCompE ); + return; + } + + pLits[0] = Abc_Var2Lit(VarT, 0^fCompT); + pLits[1] = Abc_Var2Lit(VarE, 0^fCompE); + pLits[2] = Abc_Var2Lit(VarF, 1); + if ( fPolarFlip ) + { + if ( Gia_Regular(pNodeT)->fPhase ) pLits[0] = Abc_LitNot( pLits[0] ); + if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = Abc_LitNot( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = Abc_LitNot( pLits[2] ); + } + RetValue = satoko_add_clause( pSat, pLits, 3 ); + assert( RetValue ); + pLits[0] = Abc_Var2Lit(VarT, 1^fCompT); + pLits[1] = Abc_Var2Lit(VarE, 1^fCompE); + pLits[2] = Abc_Var2Lit(VarF, 0); + if ( fPolarFlip ) + { + if ( Gia_Regular(pNodeT)->fPhase ) pLits[0] = Abc_LitNot( pLits[0] ); + if ( Gia_Regular(pNodeE)->fPhase ) pLits[1] = Abc_LitNot( pLits[1] ); + if ( pNode->fPhase ) pLits[2] = Abc_LitNot( pLits[2] ); + } + RetValue = satoko_add_clause( pSat, pLits, 3 ); + assert( RetValue ); +} +void Gia_Min2AddClausesSuper( Gia_Man_t * p, Gia_Obj_t * pNode, Vec_Ptr_t * vSuper, satoko_t * pSat ) +{ + int fPolarFlip = 0; + Gia_Obj_t * pFanin; + int * pLits, nLits, RetValue, i; + assert( !Gia_IsComplement(pNode) ); + assert( Gia_ObjIsAnd( pNode ) ); + // create storage for literals + nLits = Vec_PtrSize(vSuper) + 1; + pLits = ABC_ALLOC( int, nLits ); + // suppose AND-gate is A & B = C + // add !A => !C or A + !C + Vec_PtrForEachEntry( Gia_Obj_t *, vSuper, pFanin, i ) + { + pLits[0] = Abc_Var2Lit(Gia_Min2ObjSatId(p, Gia_Regular(pFanin)), Gia_IsComplement(pFanin)); + pLits[1] = Abc_Var2Lit(Gia_Min2ObjSatId(p, pNode), 1); + if ( fPolarFlip ) + { + if ( Gia_Regular(pFanin)->fPhase ) pLits[0] = Abc_LitNot( pLits[0] ); + if ( pNode->fPhase ) pLits[1] = Abc_LitNot( pLits[1] ); + } + RetValue = satoko_add_clause( pSat, pLits, 2 ); + assert( RetValue ); + } + // add A & B => C or !A + !B + C + Vec_PtrForEachEntry( Gia_Obj_t *, vSuper, pFanin, i ) + { + pLits[i] = Abc_Var2Lit(Gia_Min2ObjSatId(p, Gia_Regular(pFanin)), !Gia_IsComplement(pFanin)); + if ( fPolarFlip ) + { + if ( Gia_Regular(pFanin)->fPhase ) pLits[i] = Abc_LitNot( pLits[i] ); + } + } + pLits[nLits-1] = Abc_Var2Lit(Gia_Min2ObjSatId(p, pNode), 0); + if ( fPolarFlip ) + { + if ( pNode->fPhase ) pLits[nLits-1] = Abc_LitNot( pLits[nLits-1] ); + } + RetValue = satoko_add_clause( pSat, pLits, nLits ); + assert( RetValue ); + ABC_FREE( pLits ); +} + +/**Function************************************************************* + + Synopsis [Adds clauses and returns CNF variable of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_Min2CollectSuper_rec( Gia_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes ) +{ + // if the new node is complemented or a PI, another gate begins + if ( Gia_IsComplement(pObj) || Gia_ObjIsCi(pObj) || + (!fFirst && Gia_ObjValue(pObj) > 1) || + (fUseMuxes && pObj->fMark0) ) + { + Vec_PtrPushUnique( vSuper, pObj ); + return; + } + // go through the branches + Gia_Min2CollectSuper_rec( Gia_ObjChild0(pObj), vSuper, 0, fUseMuxes ); + Gia_Min2CollectSuper_rec( Gia_ObjChild1(pObj), vSuper, 0, fUseMuxes ); +} +void Gia_Min2CollectSuper( Gia_Obj_t * pObj, int fUseMuxes, Vec_Ptr_t * vSuper ) +{ + assert( !Gia_IsComplement(pObj) ); + assert( !Gia_ObjIsCi(pObj) ); + Vec_PtrClear( vSuper ); + Gia_Min2CollectSuper_rec( pObj, vSuper, 1, fUseMuxes ); +} +void Gia_Min2ObjAddToFrontier( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Ptr_t * vFrontier, satoko_t * pSat, Vec_Int_t * vSatVars ) +{ + assert( !Gia_IsComplement(pObj) ); + assert( !Gia_ObjIsConst0(pObj) ); + if ( Gia_Min2ObjSatId(p, pObj) >= 0 ) + return; + assert( Gia_Min2ObjSatId(p, pObj) == -1 ); + Vec_IntPush( vSatVars, Gia_ObjId(p, pObj) ); + Gia_Min2ObjSetSatId( p, pObj, satoko_add_variable(pSat, 0) ); + if ( Gia_ObjIsAnd(pObj) ) + Vec_PtrPush( vFrontier, pObj ); +} +int Gia_Min2ObjGetCnfVar( Gia_Man2Min_t * p, int iObj ) +{ + Gia_Obj_t * pObj = Gia_ManObj(p->pGia, iObj); + Gia_Obj_t * pNode, * pFanin; + int i, k, fUseMuxes = 1; + if ( Gia_Min2ObjSatId(p->pGia, pObj) >= 0 ) + return Gia_Min2ObjSatId(p->pGia, pObj); + if ( Gia_ObjIsCi(pObj) ) + { + Vec_IntPush( p->vSatVars, iObj ); + return Gia_Min2ObjSetSatId( p->pGia, pObj, satoko_add_variable(p->pSat, 0) ); + } + assert( Gia_ObjIsAnd(pObj) ); + // start the frontier + Vec_PtrClear( p->vFrontier ); + Gia_Min2ObjAddToFrontier( p->pGia, pObj, p->vFrontier, p->pSat, p->vSatVars ); + // explore nodes in the frontier + Vec_PtrForEachEntry( Gia_Obj_t *, p->vFrontier, pNode, i ) + { + assert( Gia_Min2ObjSatId(p->pGia,pNode) >= 0 ); + if ( fUseMuxes && pNode->fMark0 ) + { + Vec_PtrClear( p->vFanins ); + Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin0( Gia_ObjFanin0(pNode) ) ); + Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin0( Gia_ObjFanin1(pNode) ) ); + Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin1( Gia_ObjFanin0(pNode) ) ); + Vec_PtrPushUnique( p->vFanins, Gia_ObjFanin1( Gia_ObjFanin1(pNode) ) ); + Vec_PtrForEachEntry( Gia_Obj_t *, p->vFanins, pFanin, k ) + Gia_Min2ObjAddToFrontier( p->pGia, Gia_Regular(pFanin), p->vFrontier, p->pSat, p->vSatVars ); + Gia_Min2AddClausesMux( p->pGia, pNode, p->pSat ); + } + else + { + Gia_Min2CollectSuper( pNode, fUseMuxes, p->vFanins ); + Vec_PtrForEachEntry( Gia_Obj_t *, p->vFanins, pFanin, k ) + Gia_Min2ObjAddToFrontier( p->pGia, Gia_Regular(pFanin), p->vFrontier, p->pSat, p->vSatVars ); + Gia_Min2AddClausesSuper( p->pGia, pNode, p->vFanins, p->pSat ); + } + assert( Vec_PtrSize(p->vFanins) > 1 ); + } + return Gia_Min2ObjSatId(p->pGia,pObj); +} + +/**Function************************************************************* + + Synopsis [Returns 0 if the node is not a constant.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_Min2ManSimulate( Gia_Man2Min_t * p ) +{ + word Sim0, Sim1; int n, i, iObj; + p->nSims++; + // add random values to new CIs + Vec_WrdFillExtra( p->vSims, Gia_ManObjNum(p->pGia), 0 ); + for ( i = p->nCisOld; i < Gia_ManCiNum(p->pGia); i++ ) + Vec_WrdWriteEntry( p->vSims, Gia_ManCiIdToId(p->pGia, i), Gia_ManRandomW( 0 ) << 1 ); + p->nCisOld = Gia_ManCiNum(p->pGia); + // simulate internal nodes + for ( n = 0; n < 2; n++ ) + Vec_IntForEachEntry( p->vObjs[n], iObj, i ) + { + Gia_Obj_t * pObj = Gia_ManObj( p->pGia, iObj ); + Sim0 = Vec_WrdEntry( p->vSims, Gia_ObjFaninId0p(p->pGia, pObj) ); + Sim1 = Vec_WrdEntry( p->vSims, Gia_ObjFaninId1p(p->pGia, pObj) ); + Sim0 = Gia_ObjFaninC0(pObj) ? ~Sim0 : Sim0; + Sim1 = Gia_ObjFaninC1(pObj) ? ~Sim1 : Sim1; + Vec_WrdWriteEntry( p->vSims, iObj, Sim0 & Sim1 ); + } + Sim0 = Vec_WrdEntry( p->vSims, Abc_Lit2Var(p->iLits[0]) ); + Sim1 = Vec_WrdEntry( p->vSims, Abc_Lit2Var(p->iLits[1]) ); + Sim0 = Abc_LitIsCompl(p->iLits[0]) ? ~Sim0 : Sim0; + Sim1 = Abc_LitIsCompl(p->iLits[1]) ? ~Sim1 : Sim1; +// assert( (Sim0 & Sim1) != ~0 ); + return (Sim0 & Sim1) == 0; +} + +/**Function************************************************************* + + Synopsis [Internal simulation APIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_Min2SimSetInputBit( Gia_Man2Min_t * p, int iObj, int Bit, int iPattern ) +{ + word * pSim = Vec_WrdEntryP( p->vSims, iObj ); + assert( iPattern > 0 && iPattern < 64 ); + if ( Abc_InfoHasBit( (unsigned*)pSim, iPattern ) != Bit ) + Abc_InfoXorBit( (unsigned*)pSim, iPattern ); +} +int Gia_Min2ManSolve( Gia_Man2Min_t * p ) +{ + int iObj0 = Abc_Lit2Var(p->iLits[0]); + int iObj1 = Abc_Lit2Var(p->iLits[1]); + int n, i, status, iVar0, iVar1, iTemp; + assert( iObj0 > 0 && iObj1 > 0 ); +// Vec_IntForEachEntry( &p->pGia->vCopies, iTemp, i ) +// assert( iTemp == -1 ); + Vec_IntFillExtra( &p->pGia->vCopies, Gia_ManObjNum(p->pGia), -1 ); + Vec_IntClear( p->vSatVars ); + assert( satoko_varnum(p->pSat) == 0 ); + iVar0 = Gia_Min2ObjGetCnfVar( p, iObj0 ); + iVar1 = Gia_Min2ObjGetCnfVar( p, iObj1 ); + satoko_assump_push( p->pSat, Abc_Var2Lit(iVar0, Abc_LitIsCompl(p->iLits[0])) ); + satoko_assump_push( p->pSat, Abc_Var2Lit(iVar1, Abc_LitIsCompl(p->iLits[1])) ); + status = satoko_solve( p->pSat ); + satoko_assump_pop( p->pSat ); + satoko_assump_pop( p->pSat ); + if ( status == SATOKO_SAT ) + { + //printf( "Disproved %d %d\n", p->iLits[0], p->iLits[1] ); + assert( Gia_Min2ManSimulate(p) == 1 ); + for ( n = 0; n < 2; n++ ) + Vec_IntForEachEntry( p->vCis[n], iTemp, i ) + Gia_Min2SimSetInputBit( p, iTemp, satoko_var_polarity(p->pSat, Gia_Min2ObjSatId(p->pGia, Gia_ManObj(p->pGia, iTemp))) == SATOKO_LIT_TRUE, p->iPattern ); + //assert( Gia_Min2ManSimulate(p) == 0 ); + p->iPattern = p->iPattern == 63 ? 1 : p->iPattern + 1; + p->nSatSat++; + } + //printf( "supp %d node %d vars %d\n", + // Vec_IntSize(p->vCis[0]) + Vec_IntSize(p->vCis[1]), + // Vec_IntSize(p->vObjs[0]) + Vec_IntSize(p->vObjs[1]), + // Vec_IntSize(p->vSatVars) ); + satoko_rollback( p->pSat ); + Vec_IntForEachEntry( p->vSatVars, iTemp, i ) + Gia_Min2ObjCleanSatId( p->pGia, Gia_ManObj(p->pGia, iTemp) ); + return status == SATOKO_UNSAT; +} + +/**Function************************************************************* + + Synopsis [Collect nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_Min2ManGatherSupp_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vCis, Vec_Int_t * vObjs ) +{ + int Val0, Val1; + Gia_Obj_t * pObj; + if ( Gia_ObjIsTravIdPreviousId(p, iObj) ) + return 1; + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return 0; + Gia_ObjSetTravIdCurrentId(p, iObj); + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + { + Vec_IntPush( vCis, iObj ); + return 0; + } + assert( Gia_ObjIsAnd(pObj) ); + Val0 = Gia_Min2ManGatherSupp_rec( p, Gia_ObjFaninId0(pObj, iObj), vCis, vObjs ); + Val1 = Gia_Min2ManGatherSupp_rec( p, Gia_ObjFaninId1(pObj, iObj), vCis, vObjs ); + Vec_IntPush( vObjs, iObj ); + return Val0 || Val1; +} +int Gia_Min2ManGatherSupp( Gia_Man2Min_t * p ) +{ + int n, Overlap = 0; + p->nSupps++; + Gia_ManIncrementTravId( p->pGia ); + for ( n = 0; n < 2; n++ ) + { + Vec_IntClear( p->vCis[n] ); + Vec_IntClear( p->vObjs[n] ); + Gia_ManIncrementTravId( p->pGia ); + Overlap = Gia_Min2ManGatherSupp_rec( p->pGia, Abc_Lit2Var(p->iLits[n]), p->vCis[n], p->vObjs[n] ); + assert( n || !Overlap ); + } + return Overlap; +} + +/**Function************************************************************* + + Synopsis [Takes a literal and returns a support-minized literal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_Man2SupportAnd( Gia_Man2Min_t * p, int iLit0, int iLit1 ) +{ + p->nCalls++; + //return Gia_ManHashAnd( p->pGia, iLit0, iLit1 ); + p->iLits[0] = iLit0; + p->iLits[1] = iLit1; + if ( iLit0 < 2 || iLit1 < 2 || Abc_Lit2Var(iLit0) == Abc_Lit2Var(iLit1) || Gia_ManHashLookupInt(p->pGia, iLit0, iLit1) || + !Gia_Min2ManGatherSupp(p) || !Gia_Min2ManSimulate(p) || !Gia_Min2ManSolve(p) ) + return Gia_ManHashAnd( p->pGia, iLit0, iLit1 ); + //printf( "%d %d\n", iLit0, iLit1 ); + p->nSatUnsat++; + return 0; +} + +/**Function************************************************************* + + Synopsis [Testbench.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_Man2SupportAndTest( Gia_Man_t * pGia ) +{ + Gia_Man2Min_t * pMan; + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i; + Gia_ManRandomW( 1 ); + Gia_ManFillValue( pGia ); + pNew = Gia_ManStart( Gia_ManObjNum(pGia) ); + pNew->pName = Abc_UtilStrsav( pGia->pName ); + pNew->pSpec = Abc_UtilStrsav( pGia->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManConst0(pGia)->Value = 0; + pMan = Gia_Man2SuppStart( pNew ); + Gia_ManForEachObj1( pGia, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + { +// pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + pObj->Value = Gia_Man2SupportAnd( pMan, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + else assert( 0 ); + + //if ( i % 10000 == 0 ) + // printf( "%d\n", i ); + } + Gia_Man2SuppStop( pMan ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaSupps.c b/yosys/abc/src/aig/gia/giaSupps.c new file mode 100644 index 00000000000..558411eda2b --- /dev/null +++ b/yosys/abc/src/aig/gia/giaSupps.c @@ -0,0 +1,1154 @@ +/**CFile**************************************************************** + + FileName [giaSupp.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Support computation manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSupp.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig/gia/gia.h" +#include "base/main/mainInt.h" +#include "base/io/ioResub.h" +#include "misc/util/utilTruth.h" +#include "misc/extra/extra.h" +#include "misc/vec/vecHsh.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Supp_Man_t_ Supp_Man_t; +struct Supp_Man_t_ +{ + // user data + int nIters; // optimization rounds + int nRounds; // optimization rounds + int nWords; // the number of simulation words + int nDivWords; // the number of divisor words + Vec_Wrd_t * vIsfs; // functions to synthesize + Vec_Int_t * vCands; // candidate divisors + Vec_Int_t * vWeights; // divisor weights (optional) + Vec_Wrd_t * vSims; // simulation values + Vec_Wrd_t * vSimsC; // simulation values + Gia_Man_t * pGia; // used for object names + // computed data + Vec_Wrd_t * vDivs[2]; // simulation values + Vec_Wrd_t * vDivsC[2]; // simulation values + Vec_Wrd_t * vPats[2]; // simulation values + Vec_Ptr_t * vMatrix; // simulation values + Vec_Wrd_t * vMask; // simulation values + Vec_Wrd_t * vRowTemp; // simulation values + Vec_Int_t * vCosts; // candidate costs + Hsh_VecMan_t * pHash; // subsets considered + Vec_Wrd_t * vSFuncs; // ISF storage + Vec_Int_t * vSStarts; // subset function starts + Vec_Int_t * vSCount; // subset function count + Vec_Int_t * vSPairs; // subset pair count + Vec_Int_t * vTemp; // temporary + Vec_Int_t * vTempSets; // temporary + Vec_Int_t * vTempPairs; // temporary + Vec_Wec_t * vSolutions; // solutions for each node count +}; + +extern void Extra_BitMatrixTransposeP( Vec_Wrd_t * vSimsIn, int nWordsIn, Vec_Wrd_t * vSimsOut, int nWordsOut ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Supp_ManFuncInit( Vec_Wrd_t * vFuncs, int nWords ) +{ + int i, k = 0, nFuncs = Vec_WrdSize(vFuncs) / nWords / 2; + assert( 2 * nFuncs * nWords == Vec_WrdSize(vFuncs) ); + for ( i = 0; i < nFuncs; i++ ) + { + word * pFunc0 = Vec_WrdEntryP(vFuncs, (2*i+0)*nWords); + word * pFunc1 = Vec_WrdEntryP(vFuncs, (2*i+1)*nWords); + if ( Abc_TtIsConst0(pFunc0, nWords) || Abc_TtIsConst0(pFunc1, nWords) ) + continue; + if ( k < i ) Abc_TtCopy( Vec_WrdEntryP(vFuncs, (2*k+0)*nWords), pFunc0, nWords, 0 ); + if ( k < i ) Abc_TtCopy( Vec_WrdEntryP(vFuncs, (2*k+1)*nWords), pFunc1, nWords, 0 ); + k++; + } + Vec_WrdShrink( vFuncs, 2*k*nWords ); + return k; +} +int Supp_ManCostInit( Vec_Wrd_t * vFuncs, int nWords ) +{ + int Res = 0, i, nFuncs = Vec_WrdSize(vFuncs) / nWords / 2; + assert( 2 * nFuncs * nWords == Vec_WrdSize(vFuncs) ); + for ( i = 0; i < nFuncs; i++ ) + { + word * pFunc0 = Vec_WrdEntryP(vFuncs, (2*i+0)*nWords); + word * pFunc1 = Vec_WrdEntryP(vFuncs, (2*i+1)*nWords); + Res += Abc_TtCountOnesVec(pFunc0, nWords) * Abc_TtCountOnesVec(pFunc1, nWords); + } + assert( nFuncs < 128 ); + assert( Res < (1 << 24) ); + return (nFuncs << 24) | Res; +} +void Supp_ManInit( Supp_Man_t * p ) +{ + int Value, nFuncs, iSet = Hsh_VecManAdd( p->pHash, p->vTemp ); // empty set + assert( iSet == 0 ); + Vec_IntPush( p->vSStarts, Vec_WrdSize(p->vSFuncs) ); + Vec_WrdAppend( p->vSFuncs, p->vIsfs ); + nFuncs = Supp_ManFuncInit( p->vSFuncs, p->nWords ); + assert( Vec_WrdSize(p->vSFuncs) == 2 * nFuncs * p->nWords ); + Value = Supp_ManCostInit(p->vSFuncs, p->nWords); + Vec_IntPush( p->vSCount, Value >> 24 ); + Vec_IntPush( p->vSPairs, Value & 0xFFFFFF ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Supp_DeriveLines( Supp_Man_t * p ) +{ + int n, i, iObj, nWords = p->nWords; + int nDivWords = Abc_Bit6WordNum( Vec_IntSize(p->vCands) ); + //Vec_IntPrint( p->vCands ); + for ( n = 0; n < 2; n++ ) + { + p->vDivs[n] = Vec_WrdStart( 64*nWords*nDivWords ); + p->vPats[n] = Vec_WrdStart( 64*nWords*nDivWords ); + //p->vDivsC[n] = Vec_WrdStart( 64*nWords*nDivWords ); + if ( p->vSimsC ) + Vec_IntForEachEntry( p->vCands, iObj, i ) + Abc_TtAndSharp( Vec_WrdEntryP(p->vDivsC[n], i*nWords), Vec_WrdEntryP(p->vSimsC, iObj*nWords), Vec_WrdEntryP(p->vSims, iObj*nWords), nWords, !n ); + else + Vec_IntForEachEntry( p->vCands, iObj, i ) + Abc_TtCopy( Vec_WrdEntryP(p->vDivs[n], i*nWords), Vec_WrdEntryP(p->vSims, iObj*nWords), nWords, !n ); + Extra_BitMatrixTransposeP( p->vDivs[n], nWords, p->vPats[n], nDivWords ); + } + return nDivWords; +} +Supp_Man_t * Supp_ManCreate( Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * vWeights, Vec_Wrd_t * vSims, Vec_Wrd_t * vSimsC, int nWords, Gia_Man_t * pGia, int nIters, int nRounds ) +{ + Supp_Man_t * p = ABC_CALLOC( Supp_Man_t, 1 ); + p->nIters = nIters; + p->nRounds = nRounds; + p->nWords = nWords; + p->vIsfs = vIsfs; + p->vCands = vCands; + p->vWeights = vWeights; + p->vSims = vSims; + p->vSimsC = vSimsC; + p->pGia = pGia; + // computed data + p->nDivWords = Supp_DeriveLines( p ); + p->vMatrix = Vec_PtrAlloc( 100 ); + p->vMask = Vec_WrdAlloc( 100 ); + p->vRowTemp = Vec_WrdStart( 64*p->nDivWords ); + p->vCosts = Vec_IntStart( Vec_IntSize(p->vCands) ); + p->pHash = Hsh_VecManStart( 1000 ); + p->vSFuncs = Vec_WrdAlloc( 1000 ); + p->vSStarts = Vec_IntAlloc( 1000 ); + p->vSCount = Vec_IntAlloc( 1000 ); + p->vSPairs = Vec_IntAlloc( 1000 ); + p->vSolutions = Vec_WecStart( 16 ); + p->vTemp = Vec_IntAlloc( 10 ); + p->vTempSets = Vec_IntAlloc( 10 ); + p->vTempPairs = Vec_IntAlloc( 10 ); + Supp_ManInit( p ); + return p; +} +int Supp_DeriveLines2( Supp_Man_t * p ) +{ + assert( Vec_WrdSize(p->vSims) % p->nWords == 0 ); + int n, nDivWords = Abc_Bit6WordNum( Vec_WrdSize(p->vSims) / p->nWords ); + for ( n = 0; n < 2; n++ ) + { + p->vDivs[n] = Vec_WrdStart( 64*p->nWords*nDivWords ); + p->vPats[n] = Vec_WrdStart( 64*p->nWords*nDivWords ); + Abc_TtCopy( Vec_WrdArray(p->vDivs[n]), Vec_WrdArray(p->vSims), Vec_WrdSize(p->vSims), !n ); + Extra_BitMatrixTransposeP( p->vDivs[n], p->nWords, p->vPats[n], nDivWords ); + } + return nDivWords; +} +Supp_Man_t * Supp_ManCreate2( Vec_Wrd_t * vIsfs, Vec_Wrd_t * vSims, Vec_Int_t * vWeights, int nWords, int nIters, int nRounds ) +{ + Supp_Man_t * p = ABC_CALLOC( Supp_Man_t, 1 ); + assert( Vec_WrdSize(vSims)%nWords == 0 ); + p->nIters = nIters; + p->nRounds = nRounds; + p->nWords = nWords; + p->vIsfs = vIsfs; + p->vCands = Vec_IntStartNatural( Vec_WrdSize(vSims)/nWords ); + p->vWeights = NULL; + p->vSims = vSims; + p->vSimsC = NULL; + p->pGia = NULL; + // computed data + p->nDivWords = Supp_DeriveLines2( p ); + p->vMatrix = Vec_PtrAlloc( 100 ); + p->vMask = Vec_WrdAlloc( 100 ); + p->vRowTemp = Vec_WrdStart( 64*p->nDivWords ); + p->vCosts = Vec_IntStart( Vec_IntSize(p->vCands) ); + p->pHash = Hsh_VecManStart( 1000 ); + p->vSFuncs = Vec_WrdAlloc( 1000 ); + p->vSStarts = Vec_IntAlloc( 1000 ); + p->vSCount = Vec_IntAlloc( 1000 ); + p->vSPairs = Vec_IntAlloc( 1000 ); + p->vSolutions = Vec_WecStart( 16 ); + p->vTemp = Vec_IntAlloc( 10 ); + p->vTempSets = Vec_IntAlloc( 10 ); + p->vTempPairs = Vec_IntAlloc( 10 ); + Supp_ManInit( p ); + return p; +} +void Supp_ManCleanMatrix( Supp_Man_t * p ) +{ + Vec_Wrd_t * vTemp; int i; + Vec_PtrForEachEntry( Vec_Wrd_t *, p->vMatrix, vTemp, i ) + Vec_WrdFreeP( &vTemp ); + Vec_PtrClear( p->vMatrix ); +} +void Supp_ManDelete( Supp_Man_t * p ) +{ + Supp_ManCleanMatrix( p ); + Vec_WrdFreeP( &p->vDivs[0] ); + Vec_WrdFreeP( &p->vDivs[1] ); + Vec_WrdFreeP( &p->vDivsC[0] ); + Vec_WrdFreeP( &p->vDivsC[1] ); + Vec_WrdFreeP( &p->vPats[0] ); + Vec_WrdFreeP( &p->vPats[1] ); + Vec_PtrFreeP( &p->vMatrix ); + Vec_WrdFreeP( &p->vMask ); + Vec_WrdFreeP( &p->vRowTemp ); + Vec_IntFreeP( &p->vCosts ); + Hsh_VecManStop( p->pHash ); + Vec_WrdFreeP( &p->vSFuncs ); + Vec_IntFreeP( &p->vSStarts ); + Vec_IntFreeP( &p->vSCount ); + Vec_IntFreeP( &p->vSPairs ); + Vec_WecFreeP( &p->vSolutions ); + Vec_IntFreeP( &p->vTemp ); + Vec_IntFreeP( &p->vTempSets ); + Vec_IntFreeP( &p->vTempPairs ); + if ( p->vSims == NULL ) + Vec_IntFreeP( &p->vCands ); + ABC_FREE( p ); +} +int Supp_ManMemory( Supp_Man_t * p ) +{ + int nMem = sizeof(Supp_Man_t); + nMem += 2*(int)Vec_WrdMemory( p->vDivs[0] ); + nMem += 2*(int)Vec_WrdMemory( p->vPats[0] ); + nMem += (Vec_PtrSize(p->vMatrix)+1)*(int)Vec_WrdMemory( p->vRowTemp ); + nMem += (int)Vec_WrdMemory( p->vMask ); + nMem += (int)Vec_IntMemory( p->vCosts ); + nMem += (int)Hsh_VecManMemory( p->pHash ); + nMem += (int)Vec_WrdMemory( p->vSFuncs ); + nMem += (int)Vec_IntMemory( p->vSStarts ); + nMem += (int)Vec_IntMemory( p->vSCount ); + nMem += (int)Vec_IntMemory( p->vSPairs ); + nMem += (int)Vec_WecMemory( p->vSolutions ); + nMem += (int)Vec_IntMemory( p->vTemp ); + nMem += (int)Vec_IntMemory( p->vTempSets ); + nMem += (int)Vec_IntMemory( p->vTempPairs ); + return nMem; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Supp_ArrayWeight( Vec_Int_t * vRes, Vec_Int_t * vWeights ) +{ + int i, iObj, Cost = 0; + if ( !vWeights ) + return Vec_IntSize(vRes); + Vec_IntForEachEntry( vRes, iObj, i ) + Cost += Vec_IntEntry(vWeights, iObj); + return Cost; +} +int Supp_SetWeight( Supp_Man_t * p, int iSet ) +{ + return Supp_ArrayWeight( Hsh_VecReadEntry(p->pHash, iSet), p->vWeights ); +} +int Supp_SetSize( Supp_Man_t * p, int iSet ) +{ + return Vec_IntSize( Hsh_VecReadEntry(p->pHash, iSet) ); +} +int Supp_SetFuncNum( Supp_Man_t * p, int iSet ) +{ + return Vec_IntEntry(p->vSCount, iSet); +} +int Supp_SetPairNum( Supp_Man_t * p, int iSet ) +{ + return Vec_IntEntry(p->vSPairs, iSet); +} +void Supp_SetConvert( Vec_Int_t * vSet, Vec_Int_t * vCands ) +{ + int i, iObj; + Vec_IntForEachEntry( vSet, iObj, i ) + Vec_IntWriteEntry( vSet, i, Vec_IntEntry(vCands, iObj) ); +} +void Supp_PrintNodes( Gia_Man_t * pGia, Vec_Int_t * vObjs, int Skip, int Limit ) +{ + int i, iObj; + //printf( "Considering %d targets: ", Vec_IntSize(vObjs) ); + Vec_IntForEachEntryStart( vObjs, iObj, i, Skip ) + { + if ( iObj < 0 ) + continue; + printf( "(%d)", iObj ); + if ( pGia && pGia->vWeights && Vec_IntEntry(pGia->vWeights, iObj) > 0 ) + printf( "(%d)", Vec_IntEntry(pGia->vWeights, iObj) ); + if ( pGia ) + printf( " %s ", Gia_ObjName(pGia, iObj)+2 ); + else + printf( " n%d ", iObj ); + if ( i >= Limit ) + { + printf( "... " ); + break; + } + } + printf( "Cost = %d", Supp_ArrayWeight(vObjs, pGia ? pGia->vWeights : NULL) ); + printf( "\n" ); +} +void Supp_PrintOne( Supp_Man_t * p, int iSet ) +{ + Vec_Int_t * vSet = Hsh_VecReadEntry(p->pHash, iSet); + printf( "Set %5d : ", iSet ); + printf( "Funcs %2d ", Supp_SetFuncNum(p, iSet) ); + printf( "Pairs %4d ", Supp_SetPairNum(p, iSet) ); + printf( "Start %8d ", Vec_IntEntry(p->vSStarts, iSet) ); + printf( "Weight %4d ", Supp_ArrayWeight(vSet, p->vWeights) ); + Vec_IntClearAppend( p->vTemp, vSet ); + Supp_SetConvert( p->vTemp, p->vCands ); + Supp_PrintNodes( p->pGia, p->vTemp, 0, 6 ); +} +int Supp_ManRefine1( Supp_Man_t * p, int iSet, int iObj ) +{ + word * pSet = Vec_WrdEntryP( p->vSims, Vec_IntEntry(p->vCands, iObj)*p->nWords ); + word * pIsf; int nFuncs = Vec_IntEntry(p->vSCount, iSet); + int i, n, f, w, nFuncsNew = 0, Mark = Vec_WrdSize(p->vSFuncs), Res = 0; + if ( Vec_WrdSize(p->vSFuncs) + 4*nFuncs*p->nWords > Vec_WrdCap(p->vSFuncs) ) + Vec_WrdGrow( p->vSFuncs, 2*Vec_WrdCap(p->vSFuncs) ); + pIsf = Vec_WrdEntryP( p->vSFuncs, Vec_IntEntry(p->vSStarts, iSet) ); + for ( i = 0; i < nFuncs; i++ ) + { + word * pFunc[2] = { pIsf + (2*i+0)*p->nWords, pIsf + (2*i+1)*p->nWords }; + for ( f = 0; f < 2; f++ ) + { + int nOnes[2], Start = Vec_WrdSize(p->vSFuncs); + for ( n = 0; n < 2; n++ ) + { + word * pLimit = Vec_WrdLimit(p->vSFuncs); + if ( f ) + for ( w = 0; w < p->nWords; w++ ) + Vec_WrdPush( p->vSFuncs, pFunc[n][w] & pSet[w] ); + else + for ( w = 0; w < p->nWords; w++ ) + Vec_WrdPush( p->vSFuncs, pFunc[n][w] & ~pSet[w] ); + nOnes[n] = Abc_TtCountOnesVec( pLimit, p->nWords ); + } + if ( nOnes[0] && nOnes[1] ) + Res += nOnes[0] * nOnes[1]; + else + Vec_WrdShrink( p->vSFuncs, Start ); + } + } + assert( Res < (1 << 24) ); + nFuncsNew = (Vec_WrdSize(p->vSFuncs) - Mark)/2/p->nWords; + assert( nFuncsNew < 128 ); + assert( nFuncsNew >= 0 && nFuncsNew <= 2*nFuncs ); + return (nFuncsNew << 24) | Res; +} +void Supp_ManRefine( Supp_Man_t * p, int iSet, int iObj, int * pnFuncs, int * pnPairs ) +{ + word * pDivs0 = Vec_WrdEntryP( p->vDivs[0], iObj*p->nWords ); + word * pDivs1 = Vec_WrdEntryP( p->vDivs[1], iObj*p->nWords ); + word * pIsf; int nFuncs = Supp_SetFuncNum(p, iSet); + int i, f, w, nFuncsNew = 0, Mark = Vec_WrdSize(p->vSFuncs), Res = 0; + if ( Vec_WrdSize(p->vSFuncs) + 6*nFuncs*p->nWords > Vec_WrdCap(p->vSFuncs) ) + Vec_WrdGrow( p->vSFuncs, 2*Vec_WrdCap(p->vSFuncs) ); + if ( Vec_WrdSize(p->vSFuncs) == Vec_IntEntry(p->vSStarts, iSet) ) + pIsf = Vec_WrdLimit( p->vSFuncs ); + else + pIsf = Vec_WrdEntryP( p->vSFuncs, Vec_IntEntry(p->vSStarts, iSet) ); + for ( i = 0; i < nFuncs; i++ ) + { + word * pFunc[2] = { pIsf + (2*i+0)*p->nWords, pIsf + (2*i+1)*p->nWords }; + for ( f = 0; f < 3; f++ ) + { + int nOnes[2], Start = Vec_WrdSize(p->vSFuncs); + word * pLimit[2] = { Vec_WrdLimit(p->vSFuncs), Vec_WrdLimit(p->vSFuncs) + p->nWords }; + if ( f == 0 ) + { + for ( w = 0; w < p->nWords; w++ ) + Vec_WrdPush( p->vSFuncs, pFunc[0][w] & pDivs0[w] ); + for ( w = 0; w < p->nWords; w++ ) + Vec_WrdPush( p->vSFuncs, pFunc[1][w] & ~pDivs1[w] ); + } + else if ( f == 1 ) + { + for ( w = 0; w < p->nWords; w++ ) + Vec_WrdPush( p->vSFuncs, pFunc[0][w] & pDivs1[w] ); + for ( w = 0; w < p->nWords; w++ ) + Vec_WrdPush( p->vSFuncs, pFunc[1][w] & ~pDivs0[w] ); + } + else + { + for ( w = 0; w < p->nWords; w++ ) + Vec_WrdPush( p->vSFuncs, pFunc[0][w] & ~pDivs0[w] & ~pDivs1[w] ); + for ( w = 0; w < p->nWords; w++ ) + Vec_WrdPush( p->vSFuncs, pFunc[1][w] ); + } + nOnes[0] = Abc_TtCountOnesVec( pLimit[0], p->nWords ); + nOnes[1] = Abc_TtCountOnesVec( pLimit[1], p->nWords ); + if ( nOnes[0] && nOnes[1] ) + Res += nOnes[0] * nOnes[1]; + else + Vec_WrdShrink( p->vSFuncs, Start ); + } + } + assert( Res < (1 << 24) ); + nFuncsNew = (Vec_WrdSize(p->vSFuncs) - Mark)/2/p->nWords; + *pnFuncs = nFuncsNew; + *pnPairs = Res; +} +int Supp_ManSubsetAdd( Supp_Man_t * p, int iSet, int iObj, int fVerbose ) +{ + int iSetNew, nEntries = Hsh_VecSize( p->pHash ); + Vec_Int_t * vSet = Hsh_VecReadEntry( p->pHash, iSet ); + Vec_IntClear( p->vTemp ); + Vec_IntAppend( p->vTemp, vSet ); + Vec_IntPushOrder( p->vTemp, iObj ); + assert( Vec_IntIsOrdered(p->vTemp, 0) ); + iSetNew = Hsh_VecManAdd( p->pHash, p->vTemp ); + if ( iSetNew == nEntries ) // new entry + { + int nFuncs, nPairs; + Vec_IntPush( p->vSStarts, Vec_WrdSize(p->vSFuncs) ); + Supp_ManRefine( p, iSet, iObj, &nFuncs, &nPairs ); + Vec_IntPush( p->vSCount, nFuncs ); + Vec_IntPush( p->vSPairs, nPairs ); + assert( Hsh_VecSize(p->pHash) == Vec_IntSize(p->vSStarts) ); + assert( Hsh_VecSize(p->pHash) == Vec_IntSize(p->vSCount) ); + assert( Hsh_VecSize(p->pHash) == Vec_IntSize(p->vSPairs) ); + if ( Supp_SetFuncNum(p, iSetNew) == 0 && Supp_SetSize(p, iSetNew) < Vec_WecSize(p->vSolutions) ) + Vec_WecPush( p->vSolutions, Supp_SetSize(p, iSetNew), iSetNew ); + if ( fVerbose ) + Supp_PrintOne( p, iSetNew ); + } + return iSetNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Supp_ComputePair1( Supp_Man_t * p, int iSet ) +{ + int Random = 0xFFFFFF & Abc_Random(0); + int nFuncs = Vec_IntEntry(p->vSCount, iSet); + int iFunc = Random % nFuncs; + word * pIsf = Vec_WrdEntryP( p->vSFuncs, Vec_IntEntry(p->vSStarts, iSet) ); + word * pFunc[2] = { pIsf + (2*iFunc+0)*p->nWords, pIsf + (2*iFunc+1)*p->nWords }; + int iBit0 = ((Random >> 16) & 1) ? Abc_TtFindFirstBit2(pFunc[0], p->nWords) : Abc_TtFindLastBit2(pFunc[0], p->nWords); + int iBit1 = ((Random >> 17) & 1) ? Abc_TtFindFirstBit2(pFunc[1], p->nWords) : Abc_TtFindLastBit2(pFunc[1], p->nWords); + if ( 1 ) + { + Vec_Int_t * vSet = Hsh_VecReadEntry( p->pHash, iSet ); int i, iObj; + Vec_IntForEachEntry( vSet, iObj, i ) + { + word * pSet = Vec_WrdEntryP( p->vSims, Vec_IntEntry(p->vCands, iObj)*p->nWords ); + assert( Abc_TtGetBit(pSet, iBit0) == Abc_TtGetBit(pSet, iBit1) ); + } + } + return (iBit0 << 16) | iBit1; +} +int Supp_ComputePair( Supp_Man_t * p, int iSet ) +{ + int Random = 0xFFFFFF & Abc_Random(0); + int nFuncs = Vec_IntEntry(p->vSCount, iSet); + int iFunc = Random % nFuncs; + word * pIsf = Vec_WrdEntryP( p->vSFuncs, Vec_IntEntry(p->vSStarts, iSet) ); + word * pFunc[2] = { pIsf + (2*iFunc+0)*p->nWords, pIsf + (2*iFunc+1)*p->nWords }; + int iBit0 = ((Random >> 16) & 1) ? Abc_TtFindFirstBit2(pFunc[0], p->nWords) : Abc_TtFindLastBit2(pFunc[0], p->nWords); + int iBit1 = ((Random >> 17) & 1) ? Abc_TtFindFirstBit2(pFunc[1], p->nWords) : Abc_TtFindLastBit2(pFunc[1], p->nWords); + if ( 1 ) + { + Vec_Int_t * vSet = Hsh_VecReadEntry( p->pHash, iSet ); int i, iObj; + Vec_IntForEachEntry( vSet, iObj, i ) + { + word * pSet0 = Vec_WrdEntryP( p->vDivs[0], iObj*p->nWords ); + word * pSet1 = Vec_WrdEntryP( p->vDivs[1], iObj*p->nWords ); + int Value00 = Abc_TtGetBit(pSet0, iBit0); + int Value01 = Abc_TtGetBit(pSet0, iBit1); + int Value10 = Abc_TtGetBit(pSet1, iBit0); + int Value11 = Abc_TtGetBit(pSet1, iBit1); + assert( !Value00 || !Value11 ); + assert( !Value01 || !Value10 ); + } + } + return (iBit0 << 16) | iBit1; +} +Vec_Int_t * Supp_Compute64Pairs( Supp_Man_t * p, Vec_Int_t * vSets ) +{ + int i; + Vec_IntClear( p->vTempPairs ); + for ( i = 0; i < 64; i++ ) + { + int Rand = 0xFFFFFF & Abc_Random(0); + int iSet = Vec_IntEntry( vSets, Rand % Vec_IntSize(vSets) ); + Vec_IntPush( p->vTempPairs, Supp_ComputePair(p, iSet) ); + } + return p->vTempPairs; +} +void Supp_ManFillBlock( Supp_Man_t * p, Vec_Int_t * vPairs, Vec_Wrd_t * vRes ) +{ + int i, Pair; + assert( Vec_IntSize(vPairs) == 64 ); + Vec_IntForEachEntry( vPairs, Pair, i ) + { + int iBit0 = Pair >> 16, iBit1 = Pair & 0xFFFF; + word * pPat00 = Vec_WrdEntryP(p->vPats[0], iBit0*p->nDivWords); + word * pPat01 = Vec_WrdEntryP(p->vPats[0], iBit1*p->nDivWords); + word * pPat10 = Vec_WrdEntryP(p->vPats[1], iBit0*p->nDivWords); + word * pPat11 = Vec_WrdEntryP(p->vPats[1], iBit1*p->nDivWords); + word * pPat = Vec_WrdEntryP(p->vRowTemp, i*p->nDivWords); + Abc_TtAnd( pPat, pPat00, pPat11, p->nDivWords, 0 ); + Abc_TtOrAnd( pPat, pPat01, pPat10, p->nDivWords ); + } + Extra_BitMatrixTransposeP( p->vRowTemp, p->nDivWords, vRes, 1 ); +} +void Supp_ManAddPatterns( Supp_Man_t * p, Vec_Int_t * vSets ) +{ + Vec_Int_t * vPairs = Supp_Compute64Pairs( p, vSets ); + Vec_Wrd_t * vRow = Vec_WrdStart( 64*p->nDivWords ); + Supp_ManFillBlock( p, vPairs, vRow ); + Vec_PtrPush( p->vMatrix, vRow ); +} +Vec_Int_t * Supp_ManCollectOnes( word * pSim, int nWords ) +{ + Vec_Int_t * vRes = Vec_IntAlloc( 100 ); int i; + for ( i = 0; i < 64*nWords; i++ ) + if ( Abc_TtGetBit(pSim, i) ) + Vec_IntPush( vRes, i ); + return vRes; +} +Vec_Int_t * Supp_Compute64PairsFunc( Supp_Man_t * p, Vec_Int_t * vBits0, Vec_Int_t * vBits1 ) +{ + int i; + Vec_IntClear( p->vTempPairs ); + for ( i = 0; i < 64; i++ ) + { + int Random = 0xFFFFFF & Abc_Random(0); + int iBit0 = Vec_IntEntry( vBits0, (Random & 0xFFF) % Vec_IntSize(vBits0) ); + int iBit1 = Vec_IntEntry( vBits1, (Random >> 12) % Vec_IntSize(vBits1) ); + Vec_IntPush( p->vTempPairs, (iBit0 << 16) | iBit1 ); + } + return p->vTempPairs; +} +void Supp_ManAddPatternsFunc( Supp_Man_t * p, int nBatches ) +{ + int b; + Vec_Int_t * vBits0 = Supp_ManCollectOnes( Vec_WrdEntryP(p->vSFuncs, 0*p->nWords), p->nWords ); + Vec_Int_t * vBits1 = Supp_ManCollectOnes( Vec_WrdEntryP(p->vSFuncs, 1*p->nWords), p->nWords ); + for ( b = 0; b < nBatches; b++ ) + { + Vec_Int_t * vPairs = Supp_Compute64PairsFunc( p, vBits0, vBits1 ); + Vec_Wrd_t * vRow = Vec_WrdStart( 64*p->nDivWords ); + Supp_ManFillBlock( p, vPairs, vRow ); + Vec_PtrPush( p->vMatrix, vRow ); + } + Vec_IntFree( vBits0 ); + Vec_IntFree( vBits1 ); +} +int Supp_FindNextDiv( Supp_Man_t * p, int Pair ) +{ + int iDiv, iBit0 = Pair >> 16, iBit1 = Pair & 0xFFFF; + word * pPat00 = Vec_WrdEntryP(p->vPats[0], iBit0*p->nDivWords); + word * pPat01 = Vec_WrdEntryP(p->vPats[0], iBit1*p->nDivWords); + word * pPat10 = Vec_WrdEntryP(p->vPats[1], iBit0*p->nDivWords); + word * pPat11 = Vec_WrdEntryP(p->vPats[1], iBit1*p->nDivWords); + int iDiv1 = Abc_TtFindFirstAndBit2( pPat00, pPat11, p->nDivWords ); + int iDiv2 = Abc_TtFindFirstAndBit2( pPat01, pPat10, p->nDivWords ); + iDiv1 = iDiv1 == -1 ? ABC_INFINITY : iDiv1; + iDiv2 = iDiv2 == -1 ? ABC_INFINITY : iDiv2; + iDiv = Abc_MinInt( iDiv1, iDiv2 ); + // return -1 if the pair cannot be distinguished by any divisor + // in this case the original resub problem has no solution + if ( iDiv == ABC_INFINITY ) + return -1; + assert( iDiv >= 0 && iDiv < Vec_IntSize(p->vCands) ); + return iDiv; +} +int Supp_ManRandomSolution( Supp_Man_t * p, int iSet, int fVerbose ) +{ + Vec_IntClear( p->vTempSets ); + while ( Supp_SetFuncNum(p, iSet) > 0 ) + { + int Pair = Supp_ComputePair( p, iSet ); + int iDiv = Supp_FindNextDiv( p, Pair ); + if ( iDiv == -1 ) + return -1; + iSet = Supp_ManSubsetAdd( p, iSet, iDiv, fVerbose ); + if ( Supp_SetFuncNum(p, iSet) > 0 ) + Vec_IntPush( p->vTempSets, iSet ); + } + if ( Vec_IntSize(p->vTempSets) < 2 ) + return iSet; + Supp_ManAddPatterns( p, p->vTempSets ); + return iSet; +} +int Supp_ManSubsetRemove( Supp_Man_t * p, int iSet, int iPos ) +{ + int i, iSetNew = 0, nSize = Supp_SetSize(p, iSet); + for ( i = 0; i < nSize; i++ ) + if ( i != iPos && Supp_SetFuncNum(p, iSetNew) > 0 ) + iSetNew = Supp_ManSubsetAdd( p, iSetNew, Vec_IntEntry(Hsh_VecReadEntry(p->pHash, iSet), i), 0 ); + return iSetNew; +} +int Supp_ManMinimize( Supp_Man_t * p, int iSet0, int r, int fVerbose ) +{ + int i, nSize = Supp_SetSize(p, iSet0); + Vec_Int_t * vPerm = Vec_IntStartNatural( Supp_SetSize(p, iSet0) ); + Vec_IntRandomizeOrder( vPerm ); + Vec_IntClear( p->vTempSets ); + if ( fVerbose ) + printf( "Removing items from %d:\n", iSet0 ); + // make sure we first try to remove items with higher weight + for ( i = 0; i < nSize; i++ ) + { + int Index = Vec_IntEntry( vPerm, i ); + int iSet = Supp_ManSubsetRemove( p, iSet0, Index ); + if ( fVerbose ) + printf( "Item %2d : ", Index ); + if ( fVerbose ) + Supp_PrintOne( p, iSet ); + if ( Supp_SetFuncNum(p, iSet) == 0 ) + { + Vec_IntFree( vPerm ); + return Supp_ManMinimize( p, iSet, r, fVerbose ); + } + Vec_IntPush( p->vTempSets, iSet ); + } + Supp_ManAddPatterns( p, p->vTempSets ); + Vec_IntFree( vPerm ); + return iSet0; +} +int Supp_ManFindNextObj( Supp_Man_t * p, int fVerbose ) +{ + Vec_Wrd_t * vTemp; int r, k, iDiv; + word Sim, * pMask = Vec_WrdArray(p->vMask); + assert( Vec_WrdSize(p->vMask) == Vec_PtrSize(p->vMatrix) ); + Vec_IntFill( p->vCosts, Vec_IntSize(p->vCosts), 0 ); + Vec_PtrForEachEntry( Vec_Wrd_t *, p->vMatrix, vTemp, r ) + Vec_WrdForEachEntryStop( vTemp, Sim, k, Vec_IntSize(p->vCosts) ) + Vec_IntAddToEntry( p->vCosts, k, Abc_TtCountOnes(Sim & pMask[r]) ); + iDiv = Vec_IntArgMax( p->vCosts ); + if ( fVerbose ) + printf( "Choosing divisor %d with weight %d.\n", iDiv, Vec_IntEntry(p->vCosts, iDiv) ); + Vec_PtrForEachEntry( Vec_Wrd_t *, p->vMatrix, vTemp, r ) + pMask[r] &= ~Vec_WrdEntry( vTemp, iDiv ); + return iDiv; +} +int Supp_ManReconstruct( Supp_Man_t * p, int fVerbose ) +{ + int iSet = 0; + Vec_WrdFill( p->vMask, Vec_PtrSize(p->vMatrix), ~(word)0 ); + if ( fVerbose ) + printf( "\nBuilding a new set:\n" ); + while ( Supp_SetPairNum(p, iSet) ) + { + int iDiv = Supp_ManFindNextObj( p, fVerbose ); + iSet = Supp_ManSubsetAdd( p, iSet, iDiv, fVerbose ); + if ( Abc_TtIsConst0(Vec_WrdArray(p->vMask), Vec_WrdSize(p->vMask)) ) + break; + } + if ( fVerbose ) + printf( "Adding random part:\n" ); + return Supp_ManRandomSolution( p, iSet, fVerbose ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int s_Counter = 0; + +void Supp_DeriveDumpSims( FILE * pFile, Vec_Wrd_t * vDivs, int nWords ) +{ + int i, k, nDivs = Vec_WrdSize(vDivs)/nWords; + for ( i = 0; i < nDivs; i++ ) + { + word * pSim = Vec_WrdEntryP(vDivs, i*nWords); + for ( k = 0; k < 64*nWords; k++ ) + fprintf( pFile, "%c", '0'+Abc_TtGetBit(pSim, k) ); + fprintf( pFile, "\n" ); + } +} +void Supp_DeriveDumpSimsC( FILE * pFile, Vec_Wrd_t * vDivs[2], int nWords ) +{ + int i, k, nDivs = Vec_WrdSize(vDivs[0])/nWords; + for ( i = 0; i < nDivs; i++ ) + { + word * pSim0 = Vec_WrdEntryP(vDivs[0], i*nWords); + word * pSim1 = Vec_WrdEntryP(vDivs[1], i*nWords); + for ( k = 0; k < 64*nWords; k++ ) + if ( Abc_TtGetBit(pSim0, k) ) + fprintf( pFile, "0" ); + else if ( Abc_TtGetBit(pSim1, k) ) + fprintf( pFile, "1" ); + else + fprintf( pFile, "-" ); + fprintf( pFile, "\n" ); + } +} +void Supp_DeriveDumpProb( Vec_Wrd_t * vIsfs, Vec_Wrd_t * vDivs, int nWords ) +{ + char Buffer[100]; int nDivs = Vec_WrdSize(vDivs)/nWords; + int RetValue = sprintf( Buffer, "%02d.resub", s_Counter ); + FILE * pFile = fopen( Buffer, "wb" ); + if ( pFile == NULL ) + printf( "Cannot open output file.\n" ); + fprintf( pFile, "resyn %d %d %d %d\n", 0, nDivs, 1, 64*nWords ); + //fprintf( pFile, "%d %d %d %d\n", 0, nDivs, 1, 64*nWords ); + Supp_DeriveDumpSims( pFile, vDivs, nWords ); + Supp_DeriveDumpSims( pFile, vIsfs, nWords ); + fclose ( pFile ); + RetValue = 0; +} +void Supp_DeriveDumpProbC( Vec_Wrd_t * vIsfs, Vec_Wrd_t * vDivs[2], int nWords ) +{ + char Buffer[100]; int nDivs = Vec_WrdSize(vDivs[0])/nWords; + int RetValue = sprintf( Buffer, "%02d.resub", s_Counter ); + FILE * pFile = fopen( Buffer, "wb" ); + if ( pFile == NULL ) + printf( "Cannot open output file.\n" ); + fprintf( pFile, "resyn %d %d %d %d\n", 0, nDivs, 1, 64*nWords ); + //fprintf( pFile, "%d %d %d %d\n", 0, nDivs, 1, 64*nWords ); + Supp_DeriveDumpSimsC( pFile, vDivs, nWords ); + Supp_DeriveDumpSims( pFile, vIsfs, nWords ); + fclose ( pFile ); + RetValue = 0; +} +void Supp_DeriveDumpSol( Vec_Int_t * vSet, Vec_Int_t * vRes, int nDivs ) +{ + char Buffer[100]; + int RetValue = sprintf( Buffer, "%02d.sol", s_Counter ); + int i, iLit, iLitRes = -1, nSupp = Vec_IntSize(vSet); + FILE * pFile = fopen( Buffer, "wb" ); + if ( pFile == NULL ) + printf( "Cannot open output file.\n" ); + fprintf( pFile, "sol name aig %d\n", Vec_IntSize(vRes)/2 ); + //Vec_IntPrint( vSet ); + //Vec_IntPrint( vRes ); + Vec_IntForEachEntry( vRes, iLit, i ) + { + assert( iLit != 2 && iLit != 3 ); + if ( iLit < 2 ) + iLitRes = iLit; + else if ( iLit-4 < 2*nSupp ) + { + int iDiv = Vec_IntEntry(vSet, Abc_Lit2Var(iLit-4)); + assert( iDiv >= 0 && iDiv < nDivs ); + iLitRes = Abc_Var2Lit(1+iDiv, Abc_LitIsCompl(iLit)); + } + else + iLitRes = iLit + 2*((nDivs+1)-(nSupp+2)); + fprintf( pFile, "%d ", iLitRes ); + } + if ( Vec_IntSize(vRes) & 1 ) + fprintf( pFile, "%d ", iLitRes ); + fprintf( pFile, "\n" ); + fclose( pFile ); + RetValue = 0; + printf( "Dumped solution info file \"%s\".\n", Buffer ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Supp_DeriveDumpProb2( Vec_Wrd_t * vIsfs, Vec_Wrd_t * vDivs, int nWords, Vec_Int_t * vSupp, Vec_Int_t * vRes ) +{ + char Buffer[100]; int i, k, Temp, nDivs = Vec_WrdSize(vDivs)/nWords; + int RetValue = sprintf( Buffer, "%02d.pla", s_Counter ); + FILE * pFile = fopen( Buffer, "wb" ); + if ( pFile == NULL ) + printf( "Cannot open output file.\n" ); +// fprintf( pFile, "resyn %d %d %d %d\n", 0, nDivs, 1, 64*nWords ); + fprintf( pFile, ".i %d\n", nDivs ); + fprintf( pFile, ".o %d\n", 1 ); + fprintf( pFile, ".p %d\n", 64*nWords ); + for ( i = 0; i < 64*nWords; i++ ) { + for ( k = 0; k < nDivs; k++ ) + fprintf( pFile, "%d", Abc_TtGetBit(Vec_WrdEntryP(vDivs, k*nWords), i) ); +// fprintf( pFile, " %d\n", Abc_TtGetBit(Vec_WrdEntryP(vIsfs, 1*nWords), i) ); + if ( Abc_TtGetBit(Vec_WrdEntryP(vIsfs, 0*nWords), i) ) + fprintf( pFile, " 0\n" ); + else if ( Abc_TtGetBit(Vec_WrdEntryP(vIsfs, 1*nWords), i) ) + fprintf( pFile, " 1\n" ); + else + fprintf( pFile, " -\n" ); + } + fprintf( pFile, ".e\n" ); + + fprintf( pFile, "\n.s" ); + Vec_IntForEachEntryStart( vSupp, Temp, i, 2 ) + fprintf( pFile, " %d", Temp ); + fprintf( pFile, "\n.a" ); + Vec_IntForEachEntry( vRes, Temp, i ) + fprintf( pFile, " %d", Temp ); + fprintf( pFile, "\n" ); + fclose ( pFile ); + RetValue = 0; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Supp_ManFindBestSolution( Supp_Man_t * p, Vec_Wec_t * vSols, int fVerbose, Vec_Int_t ** pvDivs ) +{ + Vec_Int_t * vLevel, * vRes = NULL; + int i, k, iSet, nFuncs = 0, Count = 0; + int iSolBest = -1, Cost, CostBest = ABC_INFINITY; + Vec_WecForEachLevel( vSols, vLevel, i ) + { + Count += Vec_IntSize(vLevel) > 0; + Vec_IntForEachEntry( vLevel, iSet, k ) + { + if ( fVerbose ) + printf( "%3d : ", nFuncs++ ); + Cost = Gia_ManEvalSolutionOne( p->pGia, p->vSims, p->vIsfs, p->vCands, Hsh_VecReadEntry(p->pHash, iSet), p->nWords, fVerbose ); + if ( Cost == -1 ) + continue; + if ( CostBest > Cost ) + { + CostBest = Cost; + iSolBest = iSet; + } + if ( nFuncs > 5 ) + break; + } + if ( Count == 2 || k < Vec_IntSize(vLevel) ) + break; + } + if ( iSolBest > 0 && (CostBest >> 2) < 50 ) + { + Vec_Int_t * vDivs2 = Vec_IntAlloc( 100 ); + Vec_Int_t * vSet = Hsh_VecReadEntry( p->pHash, iSolBest ); int i, iObj; + vRes = Gia_ManDeriveSolutionOne( p->pGia, p->vSims, p->vIsfs, p->vCands, vSet, p->nWords, CostBest & 3 ); + assert( !vRes || Vec_IntSize(vRes) == 2*(CostBest >> 2)+1 ); + if ( vRes && pvDivs ) + { + Vec_IntClear( *pvDivs ); + Vec_IntPushTwo( *pvDivs, -1, -1 ); + Vec_IntPushTwo( vDivs2, -1, -1 ); + Vec_IntForEachEntry( vSet, iObj, i ) { + Vec_IntPush( *pvDivs, Vec_IntEntry(p->vCands, iObj) ); + Vec_IntPush( vDivs2, iObj ); + } + } + //Supp_DeriveDumpProbC( p->vIsfs, p->vDivsC, p->nWords ); + //Supp_DeriveDumpProb( p->vIsfs, p->vDivs[1], p->nWords ); + //Supp_DeriveDumpSol( vSet, vRes, Vec_WrdSize(p->vDivs[1])/p->nWords ); + //Supp_DeriveDumpProb2( p->vIsfs, p->vDivs[1], p->nWords, vDivs2, vRes ); + Vec_IntFree( vDivs2 ); + s_Counter++; + } + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Supp_FindGivenOne( Supp_Man_t * p ) +{ + int i, iObj, iSet = 0; + Vec_Int_t * vSet = Vec_IntStart( 2 ); + //extern void Patch_GenerateSet11( Gia_Man_t * p, Vec_Int_t * vDivs, Vec_Int_t * vCands ); + //Patch_GenerateSet11( p->pGia, vSet, p->vCands ); + Vec_IntDrop( vSet, 0 ); + Vec_IntDrop( vSet, 0 ); + Vec_IntForEachEntry( vSet, iObj, i ) + iSet = Supp_ManSubsetAdd( p, iSet, iObj, 1 ); + Vec_IntFree( vSet ); + return iSet; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Supp_ManCompute( Vec_Wrd_t * vIsfs, Vec_Int_t * vCands, Vec_Int_t * vWeights, Vec_Wrd_t * vSims, Vec_Wrd_t * vSimsC, int nWords, Gia_Man_t * pGia, Vec_Int_t ** pvDivs, int nIters, int nRounds, int fVerbose ) +{ + int fVeryVerbose = 0; + int i, r, iSet, iBest = -1; + abctime clk = Abc_Clock(); + Vec_Int_t * vRes = NULL; + Supp_Man_t * p; + if ( vCands ) + p = Supp_ManCreate( vIsfs, vCands, vWeights, vSims, vSimsC, nWords, pGia, nIters, nRounds ); + else + p = Supp_ManCreate2( vIsfs, vSims, NULL, nWords, nIters, nRounds ); + if ( Supp_SetFuncNum(p, 0) == 0 ) + { + Supp_ManDelete( p ); + Vec_IntClear( *pvDivs ); + Vec_IntPushTwo( *pvDivs, -1, -1 ); + vRes = Vec_IntAlloc( 1 ); + Vec_IntPush( vRes, Abc_TtIsConst0(Vec_WrdArray(vIsfs), nWords) ); + return vRes; + } + if ( fVerbose ) + printf( "Using %d divisors with %d words. Problem has %d functions and %d minterm pairs.\n", + Vec_IntSize(p->vCands), p->nWords, Supp_SetFuncNum(p, 0), Supp_SetPairNum(p, 0) ); + //iBest = Supp_FindGivenOne( p ); + if ( iBest == -1 ) + for ( i = 0; i < p->nIters; i++ ) + { + Supp_ManAddPatternsFunc( p, i ); + iSet = Supp_ManRandomSolution( p, 0, fVeryVerbose ); + if ( iSet == -1 ) { + Supp_ManDelete( p ); + return NULL; + } + for ( r = 0; r < p->nRounds; r++ ) + { + if ( fVeryVerbose ) + printf( "\n\nITER %d ROUND %d\n", i, r ); + iSet = Supp_ManMinimize( p, iSet, r, fVeryVerbose ); + if ( iBest == -1 || Supp_SetWeight(p, iBest) > Supp_SetWeight(p, iSet) ) + //if ( Supp_SetSize(p, iBest) > Supp_SetSize(p, iSet) ) + { + if ( fVeryVerbose ) + printf( "\nThe best solution found:\n" ); + if ( fVeryVerbose ) + Supp_PrintOne( p, iSet ); + iBest = iSet; + } + iSet = Supp_ManReconstruct( p, fVeryVerbose ); + if ( iSet == -1 ) { + Supp_ManDelete( p ); + return NULL; + } + } + if ( fVeryVerbose ) + printf( "Matrix size %d.\n", Vec_PtrSize(p->vMatrix) ); + Supp_ManCleanMatrix( p ); + } + if ( fVerbose ) + { + printf( "Explored %d divisor sets. Found %d solutions. Memory usage %.2f MB. ", + Hsh_VecSize(p->pHash), Vec_WecSizeSize(p->vSolutions), 1.0*Supp_ManMemory(p)/(1<<20) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + printf( "The best solution: " ); + if ( iBest == -1 ) + printf( "No solution.\n" ); + else + Supp_PrintOne( p, iBest ); + } + vRes = Supp_ManFindBestSolution( p, p->vSolutions, fVerbose, pvDivs ); + //Vec_IntPrint( vRes ); + Supp_ManDelete( p ); +// if ( vRes && Vec_IntSize(vRes) == 0 ) +// Vec_IntFreeP( &vRes ); + return vRes; +} +void Supp_ManComputeTest( Gia_Man_t * p ) +{ + Vec_Wrd_t * vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(p) ); + Vec_Wrd_t * vSims = Gia_ManSimPatSimOut( p, vSimsPi, 0 ); + int i, iPoId, nWords = Vec_WrdSize(vSimsPi) / Gia_ManCiNum(p); + Vec_Wrd_t * vIsfs = Vec_WrdStart( 2*nWords ); + Vec_Int_t * vCands = Vec_IntAlloc( 4 ); + Vec_Int_t * vRes; + +// for ( i = 0; i < Gia_ManCiNum(p)+5; i++ ) + for ( i = 0; i < Gia_ManCiNum(p); i++ ) + Vec_IntPush( vCands, 1+i ); + + iPoId = Gia_ObjId(p, Gia_ManPo(p, 0)); + Abc_TtCopy( Vec_WrdEntryP(vIsfs, 0*nWords), Vec_WrdEntryP(vSims, iPoId*nWords), nWords, 1 ); + Abc_TtCopy( Vec_WrdEntryP(vIsfs, 1*nWords), Vec_WrdEntryP(vSims, iPoId*nWords), nWords, 0 ); + + vRes = Supp_ManCompute( vIsfs, vCands, NULL, vSims, NULL, nWords, p, NULL, 1, 1, 0 ); + Vec_IntPrint( vRes ); + + Vec_WrdFree( vSimsPi ); + Vec_WrdFree( vSims ); + Vec_WrdFree( vIsfs ); + Vec_IntFree( vCands ); + Vec_IntFree( vRes ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Supp_RecordSolution( char * pFileName, Vec_Int_t * vDivs, Vec_Int_t * vRes ) +{ + FILE * pFile = fopen( pFileName, "ab" ); + if ( pFile == NULL ) { + printf( "Cannot open file \"%s\" for writing.\n", pFileName ); + return; + } + int i, Temp; + fprintf( pFile, "\n.s" ); + Vec_IntForEachEntryStart( vDivs, Temp, i, 2 ) + fprintf( pFile, " %d", Temp ); + fprintf( pFile, "\n.a" ); + Vec_IntForEachEntry( vRes, Temp, i ) + fprintf( pFile, " %d", Temp-2 ); + fprintf( pFile, "\n" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Supp_GenerateGia( Vec_Int_t * vRes, Vec_Int_t * vDivs ) +{ + int i, nAddOn = 2, nIns = Vec_IntSize(vDivs)-2; + int iLit0, iLit1, iTopLit = Vec_IntEntryLast(vRes); + assert( Vec_IntSize(vRes) > 0 ); + assert( Vec_IntSize(vRes) % 2 == 1 ); + Gia_Man_t * pNew = Gia_ManStart( 100 ); + pNew->pName = Abc_UtilStrsav( "resub" ); + for ( i = 0; i < nIns; i++ ) + Gia_ManAppendCi(pNew); + Vec_IntForEachEntryDouble( vRes, iLit0, iLit1, i ) { + if ( iLit0 < iLit1 ) + Gia_ManAppendAnd( pNew, iLit0-nAddOn, iLit1-nAddOn ); + else if ( iLit0 > iLit1 ) + Gia_ManAppendXor( pNew, iLit0-nAddOn, iLit1-nAddOn ); + else assert( 0 ); + } + Gia_ManAppendCo(pNew, iTopLit-nAddOn); + return pNew; +} +Gia_Man_t * Supp_ManSolveOne( char * pFileName, int nIters, int nRounds, int fWriteSol, int fVerbose ) +{ + //Abc_Random(1); + Abc_RData_t * p = Abc_ReadPla( pFileName ); + if ( p == NULL ) return NULL; + assert( p->nOuts == 1 ); + Vec_Int_t * vDivs = Vec_IntAlloc( 100 ); + Vec_Int_t * vRes = Supp_ManCompute( p->vSimsOut, NULL, NULL, p->vSimsIn, NULL, p->nSimWords, NULL, &vDivs, nIters, nRounds, fVerbose ); + if ( fVerbose && vDivs ) printf( "Divisors: " ), Vec_IntPrint( vDivs ); + if ( fVerbose && vRes ) printf( "Solution: " ), Vec_IntPrint( vRes ); + Gia_Man_t * pNew = vRes ? Supp_GenerateGia( vRes, vDivs ) : NULL; + if ( fWriteSol && vDivs && vRes ) + Supp_RecordSolution( pFileName, vDivs, vRes ); + Vec_IntFreeP( &vRes ); + Vec_IntFreeP( &vDivs ); + Abc_RDataStop( p ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaSweep.c b/yosys/abc/src/aig/gia/giaSweep.c new file mode 100644 index 00000000000..8a7fcbd074a --- /dev/null +++ b/yosys/abc/src/aig/gia/giaSweep.c @@ -0,0 +1,801 @@ +/**CFile**************************************************************** + + FileName [giaSweep.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Sweeping of GIA manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSweep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "giaAig.h" +#include "proof/dch/dch.h" +#include "misc/tim/tim.h" +#include "proof/cec/cec.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Mark GIA nodes that feed into POs.] + + Description [Returns the array of classes of remaining registers.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManMarkSeqGiaWithBoxes_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vRoots ) +{ + Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; + int i, iBox, nBoxIns, nBoxOuts, iShift, nRealCis; + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ManMarkSeqGiaWithBoxes_rec( p, Gia_ObjFanin0(pObj), vRoots ); + Gia_ManMarkSeqGiaWithBoxes_rec( p, Gia_ObjFanin1(pObj), vRoots ); + return; + } + assert( Gia_ObjIsCi(pObj) ); + nRealCis = Tim_ManPiNum(pManTime); + if ( Gia_ObjCioId(pObj) < nRealCis ) + { + int nRegs = Gia_ManRegBoxNum(p); + int iFlop = Gia_ObjCioId(pObj) - (nRealCis - nRegs); + assert( iFlop >= 0 && iFlop < nRegs ); + pObj = Gia_ManCo( p, Gia_ManPoNum(p) - nRegs + iFlop ); + Vec_IntPush( vRoots, Gia_ObjId(p, pObj) ); + return; + } + // get the box + iBox = Tim_ManBoxForCi( pManTime, Gia_ObjCioId(pObj) ); + nBoxIns = Tim_ManBoxInputNum(pManTime, iBox); + nBoxOuts = Tim_ManBoxOutputNum(pManTime, iBox); + // mark all outputs + iShift = Tim_ManBoxOutputFirst(pManTime, iBox); + for ( i = 0; i < nBoxOuts; i++ ) + Gia_ObjSetTravIdCurrent(p, Gia_ManCi(p, iShift + i)); + // traverse from inputs + iShift = Tim_ManBoxInputFirst(pManTime, iBox); + for ( i = 0; i < nBoxIns; i++ ) + Gia_ObjSetTravIdCurrent(p, Gia_ManCo(p, iShift + i)); + for ( i = 0; i < nBoxIns; i++ ) + Gia_ManMarkSeqGiaWithBoxes_rec( p, Gia_ObjFanin0(Gia_ManCo(p, iShift + i)), vRoots ); +} +void Gia_ManMarkSeqGiaWithBoxes( Gia_Man_t * p, int fSeq ) +{ + // CI order: real PIs + flop outputs + box outputs + // CO order: box inputs + real POs + flop inputs + Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; + Vec_Int_t * vRoots; + Gia_Obj_t * pObj; + int nRealCis = Tim_ManPiNum(pManTime); + int nRealCos = Tim_ManPoNum(pManTime); + int i, nRegs = fSeq ? Gia_ManRegBoxNum(p) : 0; + assert( Gia_ManRegNum(p) == 0 ); + assert( Gia_ManBoxNum(p) > 0 ); + // mark the terminals + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); + for ( i = 0; i < nRealCis - nRegs; i++ ) + Gia_ObjSetTravIdCurrent( p, Gia_ManPi(p, i) ); + // collect flops reachable from the POs + vRoots = Vec_IntAlloc( Gia_ManRegBoxNum(p) ); + for ( i = Gia_ManPoNum(p) - nRealCos; i < Gia_ManPoNum(p) - nRegs; i++ ) + { + Gia_ObjSetTravIdCurrent( p, Gia_ManPo(p, i) ); + Gia_ManMarkSeqGiaWithBoxes_rec( p, Gia_ObjFanin0(Gia_ManPo(p, i)), vRoots ); + } + // collect flops reachable from roots + if ( fSeq ) + { + Gia_ManForEachObjVec( vRoots, p, pObj, i ) + { + assert( Gia_ObjIsCo(pObj) ); + Gia_ObjSetTravIdCurrent( p, pObj ); + Gia_ManMarkSeqGiaWithBoxes_rec( p, Gia_ObjFanin0(pObj), vRoots ); + } + //printf( "Explored %d flops\n", Vec_IntSize(vRoots) ); + } + Vec_IntFree( vRoots ); +} +Gia_Man_t * Gia_ManDupWithBoxes( Gia_Man_t * p, int fSeq ) +{ + Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + Vec_Int_t * vBoxesLeft; + int curCi, curCo, nBoxIns, nBoxOuts; + int i, k, iShift, nMarked; + assert( Gia_ManBoxNum(p) > 0 ); + // mark useful boxes + Gia_ManMarkSeqGiaWithBoxes( p, fSeq ); + // duplicate marked entries + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObj1( p, pObj, i ) + { + if ( !Gia_ObjIsTravIdCurrent(p, pObj) ) + continue; + if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi(pNew); + else if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + else assert( 0 ); + } + assert( !Gia_ManHasDangling(pNew) ); + // collect remaining flops + if ( fSeq ) + { + pNew->vRegClasses = Vec_IntAlloc( Gia_ManRegBoxNum(p) ); + if ( p->vRegInits ) + pNew->vRegInits = Vec_IntAlloc( Gia_ManRegBoxNum(p) ); + iShift = Gia_ManPoNum(p) - Gia_ManRegBoxNum(p); + for ( i = 0; i < Gia_ManRegBoxNum(p); i++ ) + if ( Gia_ObjIsTravIdCurrent(p, Gia_ManCo(p, iShift + i)) ) + { + Vec_IntPush( pNew->vRegClasses, Vec_IntEntry(p->vRegClasses, i) ); + if ( p->vRegInits ) + Vec_IntPush( pNew->vRegInits, Vec_IntEntry(p->vRegInits, i) ); + } + } + else + { + if ( p->vRegClasses ) + pNew->vRegClasses = Vec_IntDup( p->vRegClasses ); + if ( p->vRegInits ) + pNew->vRegInits = Vec_IntDup( p->vRegInits ); + } + // collect remaining boxes + vBoxesLeft = Vec_IntAlloc( Gia_ManBoxNum(p) ); + curCi = Tim_ManPiNum(pManTime); + curCo = 0; + for ( i = 0; i < Gia_ManBoxNum(p); i++ ) + { + nBoxIns = Tim_ManBoxInputNum(pManTime, i); + nBoxOuts = Tim_ManBoxOutputNum(pManTime, i); + nMarked = 0; + for ( k = 0; k < nBoxIns; k++ ) + nMarked += Gia_ObjIsTravIdCurrent( p, Gia_ManCo(p, curCo + k) ); + for ( k = 0; k < nBoxOuts; k++ ) + nMarked += Gia_ObjIsTravIdCurrent( p, Gia_ManCi(p, curCi + k) ); + curCo += nBoxIns; + curCi += nBoxOuts; + // check presence + assert( nMarked == 0 || nMarked == nBoxIns + nBoxOuts ); + if ( nMarked ) + Vec_IntPush( vBoxesLeft, i ); + } + curCo += Tim_ManPoNum(pManTime); + assert( curCi == Gia_ManCiNum(p) ); + assert( curCo == Gia_ManCoNum(p) ); + // update timing manager + pNew->pManTime = Gia_ManUpdateTimMan2( p, vBoxesLeft, Gia_ManRegBoxNum(p) - Gia_ManRegBoxNum(pNew) ); + // update extra STG + assert( p->pAigExtra != NULL ); + assert( pNew->pAigExtra == NULL ); + pNew->pAigExtra = Gia_ManUpdateExtraAig2( p->pManTime, p->pAigExtra, vBoxesLeft ); + assert( Gia_ManCiNum(pNew) == Tim_ManPiNum((Tim_Man_t*)pNew->pManTime) + Gia_ManCoNum(pNew->pAigExtra) ); + Vec_IntFree( vBoxesLeft ); + pNew->nAnd2Delay = p->nAnd2Delay; + return pNew; +} + +/**Function************************************************************* + + Synopsis [Mark GIA nodes that feed into POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManFraigCheckCis( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + for ( assert( Gia_ObjIsCi(pObj) ); Gia_ObjIsCi(pObj); pObj-- ) + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return 1; + return 0; +} +Gia_Obj_t * Gia_ManFraigMarkCis( Gia_Man_t * p, Gia_Obj_t * pObj, int fMark ) +{ + for ( assert( Gia_ObjIsCi(pObj) ); Gia_ObjIsCi(pObj); pObj-- ) + if ( fMark ) + Gia_ObjSetTravIdCurrent( p, pObj ); + return pObj; +} +Gia_Obj_t * Gia_ManFraigMarkCos( Gia_Man_t * p, Gia_Obj_t * pObj, int fMark ) +{ + for ( assert( Gia_ObjIsCo(pObj) ); Gia_ObjIsCo(pObj); pObj-- ) + if ( fMark ) + { + Gia_ObjSetTravIdCurrent( p, pObj ); + Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin0(pObj) ); + } + return pObj; +} +Gia_Obj_t * Gia_ManFraigMarkAnd( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + for ( assert( Gia_ObjIsAnd(pObj) ); Gia_ObjIsAnd(pObj); pObj-- ) + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + { + Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin0(pObj) ); + Gia_ObjSetTravIdCurrent( p, Gia_ObjFanin1(pObj) ); + } + return pObj; +} +Gia_Man_t * Gia_ManFraigCreateGia( Gia_Man_t * p ) +{ + Vec_Int_t * vBoxPres; + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i, fLabelPos; + assert( p->pManTime != NULL ); + // start marks + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); + vBoxPres = Vec_IntAlloc( 1000 ); + // mark primary outputs + fLabelPos = 1; + pObj = Gia_ManObj( p, Gia_ManObjNum(p) - 1 ); + assert( Gia_ObjIsCo(pObj) ); + while ( Gia_ObjIsCo(pObj) ) + { + pObj = Gia_ManFraigMarkCos( p, pObj, fLabelPos ); + if ( Gia_ObjIsAnd(pObj) ) + pObj = Gia_ManFraigMarkAnd( p, pObj ); + assert( Gia_ObjIsCi(pObj) ); + fLabelPos = Gia_ManFraigCheckCis(p, pObj); + pObj = Gia_ManFraigMarkCis( p, pObj, fLabelPos ); + Vec_IntPush( vBoxPres, fLabelPos ); + } + Vec_IntPop( vBoxPres ); + Vec_IntReverseOrder( vBoxPres ); + assert( Gia_ObjIsConst0(pObj) ); + // mark primary inputs + Gia_ManForEachObj1( p, pObj, i ) + if ( Gia_ObjIsCi(pObj) ) + Gia_ObjSetTravIdCurrent( p, pObj ); + else + break; + // duplicate marked entries + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachObj1( p, pObj, i ) + { + if ( !Gia_ObjIsTravIdCurrent(p, pObj) ) + continue; + if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi(pNew); + else if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + else assert( 0 ); + } + // update timing manager + pNew->pManTime = Gia_ManUpdateTimMan( p, vBoxPres ); + // update extra STG + assert( p->pAigExtra != NULL ); + assert( pNew->pAigExtra == NULL ); + pNew->pAigExtra = Gia_ManUpdateExtraAig( p->pManTime, p->pAigExtra, vBoxPres ); + Vec_IntFree( vBoxPres ); +// assert( Gia_ManPiNum(pNew) == Tim_ManCiNum(pNew->pManTime) ); +// assert( Gia_ManPoNum(pNew) == Tim_ManCoNum(pNew->pManTime) ); +// assert( Gia_ManPiNum(pNew) == Tim_ManPiNum(pNew->pManTime) + Gia_ManPoNum(pNew->pAigExtra) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ObjFanin0CopyRepr( Gia_Man_t * p, Gia_Obj_t * pObj, int * pReprs ) +{ + int fanId = Gia_ObjFaninId0p( p, pObj ); + if ( pReprs[fanId] == -1 ) + return Gia_ObjFanin0Copy( pObj ); + assert( Abc_Lit2Var(pReprs[fanId]) < Gia_ObjId(p, pObj) ); + return Abc_LitNotCond( Gia_ObjValue(Gia_ManObj(p, Abc_Lit2Var(pReprs[fanId]))), Gia_ObjFaninC0(pObj) ^ Abc_LitIsCompl(pReprs[fanId]) ); +} +int Gia_ObjFanin1CopyRepr( Gia_Man_t * p, Gia_Obj_t * pObj, int * pReprs ) +{ + int fanId = Gia_ObjFaninId1p( p, pObj ); + if ( pReprs[fanId] == -1 ) + return Gia_ObjFanin1Copy( pObj ); + assert( Abc_Lit2Var(pReprs[fanId]) < Gia_ObjId(p, pObj) ); + return Abc_LitNotCond( Gia_ObjValue(Gia_ManObj(p, Abc_Lit2Var(pReprs[fanId]))), Gia_ObjFaninC1(pObj) ^ Abc_LitIsCompl(pReprs[fanId]) ); +} +Gia_Man_t * Gia_ManFraigReduceGia( Gia_Man_t * p, int * pReprs ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + assert( pReprs != NULL ); + assert( Gia_ManRegNum(p) == 0 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue( p ); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachObj( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0CopyRepr(p, pObj, pReprs), Gia_ObjFanin1CopyRepr(p, pObj, pReprs) ); + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0CopyRepr(p, pObj, pReprs) ); + else if ( Gia_ObjIsConst0(pObj) ) + pObj->Value = 0; + else assert( 0 ); + } + Gia_ManHashStop( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Compute the set of CIs representing carry-outs of boxes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManComputeCarryOuts( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; + int i, iLast, iBox, nBoxes = Tim_ManBoxNum( pManTime ); + Vec_Int_t * vCarryOuts = Vec_IntAlloc( nBoxes ); + + // Create and populate reference count (and free later) only if not already + // done. + int createRefs = (p->pRefs == NULL); + if (createRefs) { + Gia_ManCreateRefs( p ); + } + + for ( i = 0; i < nBoxes; i++ ) + { + iLast = Tim_ManBoxInputLast( pManTime, i ); + pObj = Gia_ObjFanin0( Gia_ManCo(p, iLast) ); + if ( !Gia_ObjIsCi(pObj) ) + continue; + iBox = Tim_ManBoxForCi( pManTime, Gia_ObjCioId(pObj) ); + if ( iBox == -1 ) + continue; + assert( Gia_ObjIsCi(pObj) ); + if ( Gia_ObjCioId(pObj) == Tim_ManBoxOutputLast(pManTime, iBox) ) { + Vec_IntPush( vCarryOuts, Gia_ObjId(p, pObj) ); + + // We have identified a carry connection. Check if the carry out + // of the destination box is unconnected. If so then add it to + // the carry list as well. + iLast = Tim_ManBoxOutputLast(pManTime, i); + pObj = Gia_ManCi(p, iLast); + if ( Gia_ObjRefNum(p, pObj) == 0 ) { + Vec_IntPush( vCarryOuts, Gia_ObjId(p, pObj) ); + } + } + } + + if (createRefs) { + ABC_FREE( p->pRefs ); + } + + return vCarryOuts; +} + +/**Function************************************************************* + + Synopsis [Checks integriting of complex flops and carry-chains.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCheckIntegrityWithBoxes( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + Vec_Int_t * vCarryOuts; + int i, nCountReg = 0, nCountCarry = 0; + if ( p->pManTime == NULL ) + return; + ABC_FREE( p->pRefs ); + Gia_ManCreateRefs( p ); + for ( i = Gia_ManPoNum(p) - Gia_ManRegBoxNum(p); i < Gia_ManPoNum(p); i++ ) + { + pObj = Gia_ObjFanin0( Gia_ManPo(p, i) ); + assert( Gia_ObjIsCi(pObj) ); + if ( Gia_ObjRefNum(p, pObj) > 1 ) + nCountReg++; + } + vCarryOuts = Gia_ManComputeCarryOuts( p ); + Gia_ManForEachObjVec( vCarryOuts, p, pObj, i ) + if ( Gia_ObjRefNum(p, pObj) > 1 ) + nCountCarry++; + Vec_IntFree( vCarryOuts ); + if ( nCountReg || nCountCarry ) + printf( "Warning: AIG with boxes has internal fanout in %d complex flops and %d carries.\n", nCountReg, nCountCarry ); + ABC_FREE( p->pRefs ); +} + +/**Function************************************************************* + + Synopsis [Computes representatives in terms of the original objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Gia_ManFraigSelectReprs( Gia_Man_t * p, Gia_Man_t * pClp, int fVerbose, int pFlopTypes[3] ) +{ + Gia_Obj_t * pObj; + Vec_Int_t * vCarryOuts; + Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; + int * pReprs = ABC_FALLOC( int, Gia_ManObjNum(p) ); + int * pClp2Gia = ABC_FALLOC( int, Gia_ManObjNum(pClp) ); + int i, iLitClp, iLitClp2, iReprClp, fCompl; + int nConsts = 0, nReprs = 0; + assert( pManTime != NULL ); + // count the number of equivalent objects + Gia_ManForEachObj1( pClp, pObj, i ) + { + if ( Gia_ObjIsCo(pObj) ) + continue; + if ( i == Gia_ObjReprSelf(pClp, i) ) + continue; + if ( Gia_ObjReprSelf(pClp, i) == 0 ) + nConsts++; + else + nReprs++; + } + if ( fVerbose ) + printf( "Computed %d const objects and %d other objects.\n", nConsts, nReprs ); + nConsts = nReprs = 0; + + // mark flop input boxes + Gia_ManCleanMark0( p ); + for ( i = Gia_ManPoNum(p) - Gia_ManRegBoxNum(p); i < Gia_ManPoNum(p); i++ ) + { + pObj = Gia_ObjFanin0( Gia_ManPo(p, i) ); + assert( Gia_ObjIsCi(pObj) ); + pObj->fMark0 = 1; + } + // mark connects between last box inputs and first box outputs + vCarryOuts = Gia_ManComputeCarryOuts( p ); + Gia_ManForEachObjVec( vCarryOuts, p, pObj, i ) + pObj->fMark0 = 1; + if ( fVerbose ) + printf( "Fixed %d flop inputs and %d box/box connections (out of %d non-flop boxes).\n", + Gia_ManRegBoxNum(p), Vec_IntSize(vCarryOuts), Gia_ManNonRegBoxNum(p) ); + Vec_IntFree( vCarryOuts ); + + // collect equivalent node info + pFlopTypes[0] = pFlopTypes[1] = pFlopTypes[2] = 0; + Gia_ManForEachRo( pClp, pObj, i ) + { + Gia_Obj_t * pRepr = Gia_ObjReprObj(pClp, i); + if ( pRepr && pRepr != pObj ) + { + if ( pRepr == Gia_ManConst0(pClp) ) + pFlopTypes[0]++; + else if ( Gia_ObjIsRo(pClp, pRepr) ) + pFlopTypes[1]++; + } + } + + // compute representatives + pClp2Gia[0] = 0; + Gia_ManSetPhase( pClp ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsCo(pObj) ) + continue; + if ( Gia_ObjIsCi(pObj) && pObj->fMark0 ) // skip CI pointed by CO + continue; + assert( Gia_ObjIsCi(pObj) || Gia_ObjIsAnd(pObj) ); + iLitClp = Gia_ObjValue(pObj); + if ( iLitClp == -1 ) + continue; + iReprClp = Gia_ObjReprSelf( pClp, Abc_Lit2Var(iLitClp) ); + if ( pClp2Gia[iReprClp] == -1 ) + pClp2Gia[iReprClp] = i; + else + { + iLitClp2 = Gia_ObjValue( Gia_ManObj(p, pClp2Gia[iReprClp]) ); + assert( Gia_ObjReprSelf(pClp, Abc_Lit2Var(iLitClp)) == Gia_ObjReprSelf(pClp, Abc_Lit2Var(iLitClp2)) ); + fCompl = Abc_LitIsCompl(iLitClp) ^ Abc_LitIsCompl(iLitClp2); + fCompl ^= Gia_ManObj(pClp, Abc_Lit2Var(iLitClp))->fPhase; + fCompl ^= Gia_ManObj(pClp, Abc_Lit2Var(iLitClp2))->fPhase; + pReprs[i] = Abc_Var2Lit( pClp2Gia[iReprClp], fCompl ); + assert( Abc_Lit2Var(pReprs[i]) < i ); + if ( pClp2Gia[iReprClp] == 0 ) + nConsts++; + else + nReprs++; + } + } + ABC_FREE( pClp2Gia ); + Gia_ManForEachCi( p, pObj, i ) + pObj->fMark0 = 0; + if ( fVerbose ) + printf( "Found %d const objects and %d other objects.\n", nConsts, nReprs ); + return pReprs; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManFraigSweepPerform( Gia_Man_t * p, void * pPars ) +{ + Aig_Man_t * pNew; + pNew = Gia_ManToAigSimple( p ); + assert( Gia_ManObjNum(p) == Aig_ManObjNum(pNew) ); + Dch_ComputeEquivalences( pNew, (Dch_Pars_t *)pPars ); + Gia_ManReprFromAigRepr( pNew, p ); + Aig_ManStop( pNew ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManFraigSweepSimple( Gia_Man_t * p, void * pPars ) +{ + Gia_Man_t * pNew; + assert( p->pManTime == NULL || Gia_ManBoxNum(p) == 0 ); + Gia_ManFraigSweepPerform( p, pPars ); + pNew = Gia_ManEquivReduce( p, 1, 0, 0, 0 ); + if ( pNew == NULL ) + pNew = Gia_ManDup(p); + Gia_ManTransferTiming( pNew, p ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Computes equivalences for one clock domain.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSweepComputeOneDomainEquivs( Gia_Man_t * p, Vec_Int_t * vRegClasses, int iDom, void * pParsS, int fConst, int fEquiv, int fVerbose ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + Vec_Int_t * vPerm; + int i, Class, nFlops; + int nDoms = Vec_IntFindMax(vRegClasses); + assert( iDom >= 1 && iDom <= nDoms ); + assert( p->pManTime == NULL ); + assert( Gia_ManRegNum(p) > 0 ); + // create required flop permutation + vPerm = Vec_IntAlloc( Gia_ManRegNum(p) ); + Vec_IntForEachEntry( vRegClasses, Class, i ) + if ( Class != iDom ) + Vec_IntPush( vPerm, i ); + nFlops = Vec_IntSize( vPerm ); + Vec_IntForEachEntry( vRegClasses, Class, i ) + if ( Class == iDom ) + Vec_IntPush( vPerm, i ); + nFlops = Vec_IntSize(vPerm) - nFlops; + assert( Vec_IntSize(vPerm) == Gia_ManRegNum(p) ); + // derive new AIG + pNew = Gia_ManDupPermFlop( p, vPerm ); + assert( Gia_ManObjNum(pNew) == Gia_ManObjNum(p) ); + Vec_IntFree( vPerm ); + // perform computation of equivalences + pNew->nRegs = nFlops; + if ( pParsS ) + Cec_ManLSCorrespondenceClasses( pNew, (Cec_ParCor_t *)pParsS ); + else + Gia_ManSeqCleanupClasses( pNew, fConst, fEquiv, fVerbose ); + pNew->nRegs = Gia_ManRegNum(p); + // make new point to old + Gia_ManForEachObj( p, pObj, i ) + { + assert( !Abc_LitIsCompl(pObj->Value) ); + Gia_ManObj(pNew, Abc_Lit2Var(pObj->Value))->Value = Abc_Var2Lit(i, 0); + } + // transfer + Gia_ManDupRemapEquiv( p, pNew ); + Gia_ManStop( pNew ); +} +Gia_Man_t * Gia_ManSweepWithBoxesAndDomains( Gia_Man_t * p, void * pParsS, int fConst, int fEquiv, int fVerbose, int fVerbEquivs ) +{ + Gia_Man_t * pClp, * pNew, * pTemp; + int nDoms = Vec_IntFindMax(p->vRegClasses); + int * pReprs, iDom, pFlopTypes[3] = {0}; + assert( Gia_ManRegNum(p) == 0 ); + assert( p->pAigExtra != NULL ); + assert( nDoms > 1 ); + // order AIG objects + pNew = Gia_ManDupUnnormalize( p ); + if ( pNew == NULL ) + return NULL; + Gia_ManTransferTiming( pNew, p ); + // iterate over domains + for ( iDom = 1; iDom <= nDoms; iDom++ ) + { + int nFlopsNew, nFlops = Vec_IntCountEntry(pNew->vRegClasses, iDom); + if ( nFlops < 2 ) + continue; + // find global equivalences + pClp = Gia_ManDupCollapse( pNew, pNew->pAigExtra, NULL, 1 ); + //Gia_DumpAiger( pClp, p->pSpec, iDom, 2 ); + //Gia_ManPrintStats( pClp, NULL ); + // compute equivalences + Gia_ManSweepComputeOneDomainEquivs( pClp, pNew->vRegClasses, iDom, pParsS, fConst, fEquiv, fVerbose ); + // transfer equivalences + pReprs = Gia_ManFraigSelectReprs( pNew, pClp, fVerbose, pFlopTypes ); + Gia_ManStop( pClp ); + // reduce AIG + Gia_ManTransferTiming( p, pNew ); + pNew = Gia_ManFraigReduceGia( pTemp = pNew, pReprs ); + Gia_ManTransferTiming( pNew, p ); + Gia_ManStop( pTemp ); + ABC_FREE( pReprs ); + // derive new AIG + pNew = Gia_ManDupWithBoxes( pTemp = pNew, 1 ); + Gia_ManStop( pTemp ); + // report + nFlopsNew = Vec_IntCountEntry(pNew->vRegClasses, iDom); + pFlopTypes[2] = nFlops - nFlopsNew - (pFlopTypes[0] + pFlopTypes[1]); + if ( fVerbEquivs ) + { + printf( "Domain %2d : %5d -> %5d : ", iDom, nFlops, nFlopsNew ); + printf( "EqConst =%4d. EqFlop =%4d. Dangling =%4d. Unused =%4d.\n", + pFlopTypes[0], pFlopTypes[1], Abc_MaxInt(0, pFlopTypes[2]), Abc_MaxInt(0, -pFlopTypes[2]) ); + //Gia_ManPrintStats( pNew, NULL ); + } + } + // normalize the result + pNew = Gia_ManDupNormalize( pTemp = pNew, 0 ); + Gia_ManTransferTiming( pNew, pTemp ); + Gia_ManStop( pTemp ); + // check integrity + //Gia_ManCheckIntegrityWithBoxes( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Reduces root model with scorr.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManSweepWithBoxes( Gia_Man_t * p, void * pParsC, void * pParsS, int fConst, int fEquiv, int fVerbose, int fVerbEquivs ) +{ + Gia_Man_t * pClp, * pNew, * pTemp; + int * pReprs, pFlopTypes[3] = {0}; + int nFlopsNew, nFlops; + assert( Gia_ManRegNum(p) == 0 ); + assert( p->pAigExtra != NULL ); + // consider seq synthesis with multiple clock domains + if ( pParsC == NULL && Gia_ManClockDomainNum(p) > 1 ) + return Gia_ManSweepWithBoxesAndDomains( p, pParsS, fConst, fEquiv, fVerbose, fVerbEquivs ); + // order AIG objects + pNew = Gia_ManDupUnnormalize( p ); + if ( pNew == NULL ) + return NULL; + Gia_ManTransferTiming( pNew, p ); + nFlops = Vec_IntCountEntry(pNew->vRegClasses, 1); + // find global equivalences + pClp = Gia_ManDupCollapse( pNew, pNew->pAigExtra, NULL, pParsC ? 0 : 1 ); + //Gia_DumpAiger( pClp, p->pSpec, 1, 1 ); + // compute equivalences + if ( pParsC ) + Gia_ManFraigSweepPerform( pClp, pParsC ); + else if ( pParsS ) + Cec_ManLSCorrespondenceClasses( pClp, (Cec_ParCor_t *)pParsS ); + else + Gia_ManSeqCleanupClasses( pClp, fConst, fEquiv, fVerbose ); + // transfer equivalences + pReprs = Gia_ManFraigSelectReprs( pNew, pClp, fVerbose, pFlopTypes ); + Gia_ManStop( pClp ); + // reduce AIG + Gia_ManTransferTiming( p, pNew ); + pNew = Gia_ManFraigReduceGia( pTemp = pNew, pReprs ); + Gia_ManTransferTiming( pNew, p ); + Gia_ManStop( pTemp ); + ABC_FREE( pReprs ); + // derive new AIG + pNew = Gia_ManDupWithBoxes( pTemp = pNew, pParsC ? 0 : 1 ); + Gia_ManStop( pTemp ); + // report + nFlopsNew = Vec_IntCountEntry(pNew->vRegClasses, 1); + pFlopTypes[2] = nFlops - nFlopsNew - (pFlopTypes[0] + pFlopTypes[1]); + if ( fVerbEquivs ) + { + printf( "Domain %2d : %5d -> %5d : ", 1, nFlops, nFlopsNew ); + printf( "EqConst =%4d. EqFlop =%4d. Dangling =%4d. Unused =%4d.\n", + pFlopTypes[0], pFlopTypes[1], Abc_MaxInt(0, pFlopTypes[2]), Abc_MaxInt(0, -pFlopTypes[2]) ); + } + // normalize the result + pNew = Gia_ManDupNormalize( pTemp = pNew, 0 ); + Gia_ManTransferTiming( pNew, pTemp ); + Gia_ManStop( pTemp ); + // check integrity + //Gia_ManCheckIntegrityWithBoxes( pNew ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaSweeper.c b/yosys/abc/src/aig/gia/giaSweeper.c new file mode 100644 index 00000000000..de3f4049524 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaSweeper.c @@ -0,0 +1,1185 @@ +/**CFile**************************************************************** + + FileName [giaSweeper.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Incremental SAT sweeper.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSweeper.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "base/main/main.h" +#include "sat/bsat/satSolver.h" +#include "proof/ssc/ssc.h" + +ABC_NAMESPACE_IMPL_START + +/* + +SAT sweeping/equivalence checking requires the following steps: +- Creating probes + These APIs should be called for all internal points in the logic, which may be used as + - nodes representing conditions to be used as constraints + - nodes representing functions to be equivalence checked + - nodes representing functions needed by the user at the end of SAT sweeping + Creating new probe using Gia_SweeperProbeCreate(): int Gia_SweeperProbeCreate( Gia_Man_t * p, int iLit ); + Delete existing probe using Gia_SweeperProbeDelete(): int Gia_SweeperProbeDelete( Gia_Man_t * p, int ProbeId ); + Update existing probe using Gia_SweeperProbeUpdate(): int Gia_SweeperProbeUpdate( Gia_Man_t * p, int ProbeId, int iLit ); + Comments: + - a probe is identified by its 0-based ID, which is returned by above procedures + - GIA literal of the probe is returned by int Gia_SweeperProbeLit( Gia_Man_t * p, int ProbeId ) +- Adding/removing conditions on the current path by calling Gia_SweeperCondPush() and Gia_SweeperCondPop() + extern void Gia_SweeperCondPush( Gia_Man_t * p, int ProbeId ); + extern void Gia_SweeperCondPop( Gia_Man_t * p ); +- Performing equivalence checking by calling int Gia_SweeperCheckEquiv( Gia_Man_t * pGia, int Probe1, int Probe2 ) + (resource limits, such as the number of conflicts, will be controllable by dedicated GIA APIs) +- The resulting AIG to be returned to the user by calling Gia_SweeperExtractUserLogic() + Gia_Man_t * Gia_SweeperExtractUserLogic( Gia_Man_t * p, Vec_Int_t * vProbeIds, Vec_Ptr_t * vOutNames ) + +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Swp_Man_t_ Swp_Man_t; +struct Swp_Man_t_ +{ + Gia_Man_t * pGia; // GIA manager under construction + int nConfMax; // conflict limit in seconds + int nTimeOut; // runtime limit in seconds + Vec_Int_t * vProbes; // probes + Vec_Int_t * vCondProbes; // conditions as probes + Vec_Int_t * vCondAssump; // conditions as SAT solver literals + // equivalence checking + sat_solver * pSat; // SAT solver + Vec_Int_t * vId2Lit; // mapping of Obj IDs into SAT literal + Vec_Int_t * vFront; // temporary frontier + Vec_Int_t * vFanins; // temporary fanins + Vec_Int_t * vCexSwp; // sweeper counter-example + Vec_Int_t * vCexUser; // user-visible counter-example + int nSatVars; // counter of SAT variables + // statistics + int nSatCalls; + int nSatCallsSat; + int nSatCallsUnsat; + int nSatCallsUndec; + int nSatProofs; + abctime timeStart; + abctime timeTotal; + abctime timeCnf; + abctime timeSat; + abctime timeSatSat; + abctime timeSatUnsat; + abctime timeSatUndec; +}; + +static inline int Swp_ManObj2Lit( Swp_Man_t * p, int Id ) { return Vec_IntGetEntry( p->vId2Lit, Id ); } +static inline int Swp_ManLit2Lit( Swp_Man_t * p, int Lit ) { assert( Vec_IntEntry(p->vId2Lit, Abc_Lit2Var(Lit)) ); return Abc_Lit2LitL( Vec_IntArray(p->vId2Lit), Lit ); } +static inline void Swp_ManSetObj2Lit( Swp_Man_t * p, int Id, int Lit ) { assert( Lit > 0 ); Vec_IntSetEntry( p->vId2Lit, Id, Lit ); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creating/deleting the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Swp_Man_t * Swp_ManStart( Gia_Man_t * pGia ) +{ + Swp_Man_t * p; + int Lit; + assert( Vec_IntSize(&pGia->vHTable) ); + pGia->pData = p = ABC_CALLOC( Swp_Man_t, 1 ); + p->pGia = pGia; + p->nConfMax = 1000; + p->vProbes = Vec_IntAlloc( 100 ); + p->vCondProbes = Vec_IntAlloc( 100 ); + p->vCondAssump = Vec_IntAlloc( 100 ); + p->vId2Lit = Vec_IntAlloc( 10000 ); + p->vFront = Vec_IntAlloc( 100 ); + p->vFanins = Vec_IntAlloc( 100 ); + p->vCexSwp = Vec_IntAlloc( 100 ); + p->pSat = sat_solver_new(); + p->nSatVars = 1; + sat_solver_setnvars( p->pSat, 1000 ); + Swp_ManSetObj2Lit( p, 0, (Lit = Abc_Var2Lit(p->nSatVars++, 0)) ); + Lit = Abc_LitNot(Lit); + sat_solver_addclause( p->pSat, &Lit, &Lit + 1 ); + p->timeStart = Abc_Clock(); + return p; +} +static inline void Swp_ManStop( Gia_Man_t * pGia ) +{ + Swp_Man_t * p = (Swp_Man_t *)pGia->pData; + sat_solver_delete( p->pSat ); + Vec_IntFree( p->vFanins ); + Vec_IntFree( p->vCexSwp ); + Vec_IntFree( p->vId2Lit ); + Vec_IntFree( p->vFront ); + Vec_IntFree( p->vProbes ); + Vec_IntFree( p->vCondProbes ); + Vec_IntFree( p->vCondAssump ); + ABC_FREE( p ); + pGia->pData = NULL; +} +Gia_Man_t * Gia_SweeperStart( Gia_Man_t * pGia ) +{ + if ( pGia == NULL ) + pGia = Gia_ManStart( 10000 ); + if ( Vec_IntSize(&pGia->vHTable) == 0 ) + Gia_ManHashStart( pGia ); + // recompute fPhase and fMark1 to mark multiple fanout nodes if AIG is already defined!!! + + Swp_ManStart( pGia ); + pGia->fSweeper = 1; + return pGia; +} +void Gia_SweeperStop( Gia_Man_t * pGia ) +{ + pGia->fSweeper = 0; + Swp_ManStop( pGia ); + Gia_ManHashStop( pGia ); +// Gia_ManStop( pGia ); +} +int Gia_SweeperIsRunning( Gia_Man_t * pGia ) +{ + return (pGia->pData != NULL); +} +double Gia_SweeperMemUsage( Gia_Man_t * pGia ) +{ + Swp_Man_t * p = (Swp_Man_t *)pGia->pData; + double nMem = sizeof(Swp_Man_t); + nMem += Vec_IntCap(p->vProbes); + nMem += Vec_IntCap(p->vCondProbes); + nMem += Vec_IntCap(p->vCondAssump); + nMem += Vec_IntCap(p->vId2Lit); + nMem += Vec_IntCap(p->vFront); + nMem += Vec_IntCap(p->vFanins); + nMem += Vec_IntCap(p->vCexSwp); + return 4.0 * nMem; +} +void Gia_SweeperPrintStats( Gia_Man_t * pGia ) +{ + Swp_Man_t * p = (Swp_Man_t *)pGia->pData; + double nMemSwp = Gia_SweeperMemUsage(pGia); + double nMemGia = (double)Gia_ManObjNum(pGia)*(sizeof(Gia_Obj_t) + sizeof(int)); + double nMemSat = sat_solver_memory(p->pSat); + double nMemTot = nMemSwp + nMemGia + nMemSat; + printf( "SAT sweeper statistics:\n" ); + printf( "Memory usage:\n" ); + ABC_PRMP( "Sweeper ", nMemSwp, nMemTot ); + ABC_PRMP( "AIG manager ", nMemGia, nMemTot ); + ABC_PRMP( "SAT solver ", nMemSat, nMemTot ); + ABC_PRMP( "TOTAL ", nMemTot, nMemTot ); + printf( "Runtime usage:\n" ); + p->timeTotal = Abc_Clock() - p->timeStart; + ABC_PRTP( "CNF construction", p->timeCnf, p->timeTotal ); + ABC_PRTP( "SAT solving ", p->timeSat, p->timeTotal ); + ABC_PRTP( " Sat ", p->timeSatSat, p->timeTotal ); + ABC_PRTP( " Unsat ", p->timeSatUnsat, p->timeTotal ); + ABC_PRTP( " Undecided ", p->timeSatUndec, p->timeTotal ); + ABC_PRTP( "TOTAL RUNTIME ", p->timeTotal, p->timeTotal ); + printf( "GIA: " ); + Gia_ManPrintStats( pGia, NULL ); + printf( "SAT calls = %d. Sat = %d. Unsat = %d. Undecided = %d. Proofs = %d.\n", + p->nSatCalls, p->nSatCallsSat, p->nSatCallsUnsat, p->nSatCallsUndec, p->nSatProofs ); + Sat_SolverPrintStats( stdout, p->pSat ); +} + +/**Function************************************************************* + + Synopsis [Setting resource limits.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_SweeperSetConflictLimit( Gia_Man_t * p, int nConfMax ) +{ + Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; + pSwp->nConfMax = nConfMax; +} +void Gia_SweeperSetRuntimeLimit( Gia_Man_t * p, int nSeconds ) +{ + Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; + pSwp->nTimeOut = nSeconds; +} +Vec_Int_t * Gia_SweeperGetCex( Gia_Man_t * p ) +{ + Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; + assert( pSwp->vCexUser == NULL || Vec_IntSize(pSwp->vCexUser) == Gia_ManPiNum(p) ); + return pSwp->vCexUser; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +// create new probe +int Gia_SweeperProbeCreate( Gia_Man_t * p, int iLit ) +{ + Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; + int ProbeId = Vec_IntSize(pSwp->vProbes); + assert( iLit >= 0 ); + Vec_IntPush( pSwp->vProbes, iLit ); + return ProbeId; +} +// delete existing probe +int Gia_SweeperProbeDelete( Gia_Man_t * p, int ProbeId ) +{ + Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; + int iLit = Vec_IntEntry(pSwp->vProbes, ProbeId); + assert( iLit >= 0 ); + Vec_IntWriteEntry(pSwp->vProbes, ProbeId, -1); + return iLit; +} +// update existing probe +int Gia_SweeperProbeUpdate( Gia_Man_t * p, int ProbeId, int iLitNew ) +{ + Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; + int iLit = Vec_IntEntry(pSwp->vProbes, ProbeId); + assert( iLit >= 0 ); + Vec_IntWriteEntry(pSwp->vProbes, ProbeId, iLitNew); + return iLit; +} +// returns literal associated with the probe +int Gia_SweeperProbeLit( Gia_Man_t * p, int ProbeId ) +{ + Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; + int iLit = Vec_IntEntry(pSwp->vProbes, ProbeId); + assert( iLit >= 0 ); + return iLit; +} + +/**Function************************************************************* + + Synopsis [This procedure returns indexes of all currently defined valid probes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_SweeperCollectValidProbeIds( Gia_Man_t * p ) +{ + Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; + Vec_Int_t * vProbeIds = Vec_IntAlloc( 1000 ); + int iLit, ProbeId; + Vec_IntForEachEntry( pSwp->vProbes, iLit, ProbeId ) + { + if ( iLit < 0 ) continue; + Vec_IntPush( vProbeIds, ProbeId ); + } + return vProbeIds; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_SweeperCondPush( Gia_Man_t * p, int ProbeId ) +{ + Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; + Vec_IntPush( pSwp->vCondProbes, ProbeId ); +} +int Gia_SweeperCondPop( Gia_Man_t * p ) +{ + Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; + return Vec_IntPop( pSwp->vCondProbes ); +} +Vec_Int_t * Gia_SweeperCondVector( Gia_Man_t * p ) +{ + Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; + return pSwp->vCondProbes; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Gia_ManExtract_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vObjIds ) +{ + if ( !Gia_ObjIsAnd(pObj) ) + return; + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + Gia_ManExtract_rec( p, Gia_ObjFanin0(pObj), vObjIds ); + Gia_ManExtract_rec( p, Gia_ObjFanin1(pObj), vObjIds ); + Vec_IntPush( vObjIds, Gia_ObjId(p, pObj) ); +} +Gia_Man_t * Gia_SweeperExtractUserLogic( Gia_Man_t * p, Vec_Int_t * vProbeIds, Vec_Ptr_t * vInNames, Vec_Ptr_t * vOutNames ) +{ + Vec_Int_t * vObjIds, * vValues; + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, ProbeId; + assert( vInNames == NULL || Gia_ManPiNum(p) == Vec_PtrSize(vInNames) ); + assert( vOutNames == NULL || Vec_IntSize(vProbeIds) == Vec_PtrSize(vOutNames) ); + // create new + Gia_ManIncrementTravId( p ); + vObjIds = Vec_IntAlloc( 1000 ); + Vec_IntForEachEntry( vProbeIds, ProbeId, i ) + { + pObj = Gia_Lit2Obj( p, Gia_SweeperProbeLit(p, ProbeId) ); + Gia_ManExtract_rec( p, Gia_Regular(pObj), vObjIds ); + } + // create new manager + pNew = Gia_ManStart( 1 + Gia_ManPiNum(p) + Vec_IntSize(vObjIds) + Vec_IntSize(vProbeIds) + 100 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + // create internal nodes + Gia_ManHashStart( pNew ); + vValues = Vec_IntAlloc( Vec_IntSize(vObjIds) ); + Gia_ManForEachObjVec( vObjIds, p, pObj, i ) + { + Vec_IntPush( vValues, pObj->Value ); + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + Gia_ManHashStop( pNew ); + // create outputs + Vec_IntForEachEntry( vProbeIds, ProbeId, i ) + { + pObj = Gia_Lit2Obj( p, Gia_SweeperProbeLit(p, ProbeId) ); + Gia_ManAppendCo( pNew, Gia_Regular(pObj)->Value ^ Gia_IsComplement(pObj) ); + } + // return the values back + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = 0; + Gia_ManForEachObjVec( vObjIds, p, pObj, i ) + pObj->Value = Vec_IntEntry( vValues, i ); + Vec_IntFree( vObjIds ); + Vec_IntFree( vValues ); + // duplicate if needed + if ( Gia_ManHasDangling(pNew) ) + { + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + } + // copy names if present + if ( vInNames ) + pNew->vNamesIn = Vec_PtrDupStr( vInNames ); + if ( vOutNames ) + pNew->vNamesOut = Vec_PtrDupStr( vOutNames ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_SweeperLogicDump( Gia_Man_t * p, Vec_Int_t * vProbeIds, int fDumpConds, char * pFileName ) +{ + Gia_Man_t * pGiaOuts = Gia_SweeperExtractUserLogic( p, vProbeIds, NULL, NULL ); + Vec_Int_t * vProbeConds = Gia_SweeperCondVector( p ); + printf( "Dumping logic cones" ); + if ( fDumpConds && Vec_IntSize(vProbeConds) > 0 ) + { + Gia_Man_t * pGiaCond = Gia_SweeperExtractUserLogic( p, vProbeConds, NULL, NULL ); + Gia_ManDupAppendShare( pGiaOuts, pGiaCond ); + pGiaOuts->nConstrs = Gia_ManPoNum(pGiaCond); + Gia_ManHashStop( pGiaOuts ); + Gia_ManStop( pGiaCond ); + printf( " and conditions" ); + } + Gia_AigerWrite( pGiaOuts, pFileName, 0, 0, 0 ); + Gia_ManStop( pGiaOuts ); + printf( " into file \"%s\".\n", pFileName ); +} + +/**Function************************************************************* + + Synopsis [Sweeper cleanup.] + + Description [Returns new GIA with sweeper defined, which is the same + as the original sweeper, with all the dangling logic removed and SAT + solver restarted. The probe IDs are guaranteed to have the same logic + functions as in the original manager.] + + SideEffects [The input manager is deleted inside this procedure.] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_SweeperCleanup( Gia_Man_t * p, char * pCommLime ) +{ + Swp_Man_t * pSwp = (Swp_Man_t *)p->pData; + Vec_Int_t * vObjIds; + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; + int i, iLit, ProbeId; + + // collect all internal nodes pointed to by currently-used probes + Gia_ManIncrementTravId( p ); + vObjIds = Vec_IntAlloc( 1000 ); + Vec_IntForEachEntry( pSwp->vProbes, iLit, ProbeId ) + { + if ( iLit < 0 ) continue; + pObj = Gia_Lit2Obj( p, iLit ); + Gia_ManExtract_rec( p, Gia_Regular(pObj), vObjIds ); + } + // create new manager + pNew = Gia_ManStart( 1 + Gia_ManPiNum(p) + Vec_IntSize(vObjIds) + 100 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachPi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + // create internal nodes + Gia_ManHashStart( pNew ); + Gia_ManForEachObjVec( vObjIds, p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManHashStop( pNew ); + // create outputs + Vec_IntForEachEntry( pSwp->vProbes, iLit, ProbeId ) + { + if ( iLit < 0 ) continue; + pObj = Gia_Lit2Obj( p, iLit ); + iLit = Gia_Regular(pObj)->Value ^ Gia_IsComplement(pObj); + Vec_IntWriteEntry( pSwp->vProbes, ProbeId, iLit ); + } + Vec_IntFree( vObjIds ); + // duplicate if needed + if ( Gia_ManHasDangling(pNew) ) + { + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + } + // execute command line + if ( pCommLime ) + { + // set pNew to be current GIA in ABC + Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pNew ); + // execute command line pCommLine using Abc_CmdCommandExecute() + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), pCommLime ); + // get pNew to be current GIA in ABC + pNew = Abc_FrameGetGia( Abc_FrameGetGlobalFrame() ); + } + // restart the SAT solver + Vec_IntClear( pSwp->vId2Lit ); + sat_solver_delete( pSwp->pSat ); + pSwp->pSat = sat_solver_new(); + pSwp->nSatVars = 1; + sat_solver_setnvars( pSwp->pSat, 1000 ); + Swp_ManSetObj2Lit( pSwp, 0, (iLit = Abc_Var2Lit(pSwp->nSatVars++, 0)) ); + iLit = Abc_LitNot(iLit); + sat_solver_addclause( pSwp->pSat, &iLit, &iLit + 1 ); + pSwp->timeStart = Abc_Clock(); + // return the result + pNew->pData = p->pData; p->pData = NULL; + Gia_ManStop( p ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Addes clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Gia_ManAddClausesMux( Swp_Man_t * p, Gia_Obj_t * pNode ) +{ + Gia_Obj_t * pNodeI, * pNodeT, * pNodeE; + int pLits[4], LitF, LitI, LitT, LitE, RetValue; + assert( !Gia_IsComplement( pNode ) ); + assert( Gia_ObjIsMuxType( pNode ) ); + // get nodes (I = if, T = then, E = else) + pNodeI = Gia_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); + // get the Litiable numbers + LitF = Swp_ManLit2Lit( p, Gia_Obj2Lit(p->pGia,pNode) ); + LitI = Swp_ManLit2Lit( p, Gia_Obj2Lit(p->pGia,pNodeI) ); + LitT = Swp_ManLit2Lit( p, Gia_Obj2Lit(p->pGia,pNodeT) ); + LitE = Swp_ManLit2Lit( p, Gia_Obj2Lit(p->pGia,pNodeE) ); + + // f = ITE(i, t, e) + + // i' + t' + f + // i' + t + f' + // i + e' + f + // i + e + f' + + // create four clauses + pLits[0] = Abc_LitNotCond(LitI, 1); + pLits[1] = Abc_LitNotCond(LitT, 1); + pLits[2] = Abc_LitNotCond(LitF, 0); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + pLits[0] = Abc_LitNotCond(LitI, 1); + pLits[1] = Abc_LitNotCond(LitT, 0); + pLits[2] = Abc_LitNotCond(LitF, 1); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + pLits[0] = Abc_LitNotCond(LitI, 0); + pLits[1] = Abc_LitNotCond(LitE, 1); + pLits[2] = Abc_LitNotCond(LitF, 0); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + pLits[0] = Abc_LitNotCond(LitI, 0); + pLits[1] = Abc_LitNotCond(LitE, 0); + pLits[2] = Abc_LitNotCond(LitF, 1); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + + // two additional clauses + // t' & e' -> f' + // t & e -> f + + // t + e + f' + // t' + e' + f + + if ( LitT == LitE ) + { +// assert( fCompT == !fCompE ); + return; + } + + pLits[0] = Abc_LitNotCond(LitT, 0); + pLits[1] = Abc_LitNotCond(LitE, 0); + pLits[2] = Abc_LitNotCond(LitF, 1); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + pLits[0] = Abc_LitNotCond(LitT, 1); + pLits[1] = Abc_LitNotCond(LitE, 1); + pLits[2] = Abc_LitNotCond(LitF, 0); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); +} + +/**Function************************************************************* + + Synopsis [Addes clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Gia_ManAddClausesSuper( Swp_Man_t * p, Gia_Obj_t * pNode, Vec_Int_t * vSuper ) +{ + int i, RetValue, Lit, LitNode, pLits[2]; + assert( !Gia_IsComplement(pNode) ); + assert( Gia_ObjIsAnd( pNode ) ); + // suppose AND-gate is A & B = C + // add !A => !C or A + !C + // add !B => !C or B + !C + LitNode = Swp_ManLit2Lit( p, Gia_Obj2Lit(p->pGia,pNode) ); + Vec_IntForEachEntry( vSuper, Lit, i ) + { + pLits[0] = Swp_ManLit2Lit( p, Lit ); + pLits[1] = Abc_LitNot( LitNode ); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( RetValue ); + // update literals + Vec_IntWriteEntry( vSuper, i, Abc_LitNot(pLits[0]) ); + } + // add A & B => C or !A + !B + C + Vec_IntPush( vSuper, LitNode ); + RetValue = sat_solver_addclause( p->pSat, Vec_IntArray(vSuper), Vec_IntArray(vSuper) + Vec_IntSize(vSuper) ); + assert( RetValue ); + (void) RetValue; +} + + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Gia_ManCollectSuper_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper ) +{ + // stop at complements, shared, PIs, and MUXes + if ( Gia_IsComplement(pObj) || pObj->fMark1 || Gia_ObjIsCi(pObj) || Gia_ObjIsMuxType(pObj) ) + { + Vec_IntPushUnique( vSuper, Gia_Obj2Lit(p, pObj) ); + return; + } + Gia_ManCollectSuper_rec( p, Gia_ObjChild0(pObj), vSuper ); + Gia_ManCollectSuper_rec( p, Gia_ObjChild1(pObj), vSuper ); +} +static void Gia_ManCollectSuper( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSuper ) +{ + assert( !Gia_IsComplement(pObj) ); + assert( Gia_ObjIsAnd(pObj) ); + Vec_IntClear( vSuper ); + Gia_ManCollectSuper_rec( p, Gia_ObjChild0(pObj), vSuper ); + Gia_ManCollectSuper_rec( p, Gia_ObjChild1(pObj), vSuper ); +} + +/**Function************************************************************* + + Synopsis [Updates the solver clause database.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Gia_ManObjAddToFrontier( Swp_Man_t * p, int Id, Vec_Int_t * vFront ) +{ + Gia_Obj_t * pObj; + if ( Id == 0 || Swp_ManObj2Lit(p, Id) ) + return; + pObj = Gia_ManObj( p->pGia, Id ); + Swp_ManSetObj2Lit( p, Id, Abc_Var2Lit(p->nSatVars++, pObj->fPhase) ); + sat_solver_setnvars( p->pSat, p->nSatVars + 100 ); + if ( Gia_ObjIsAnd(pObj) ) + Vec_IntPush( vFront, Id ); +} +static void Gia_ManCnfNodeAddToSolver( Swp_Man_t * p, int NodeId ) +{ + Gia_Obj_t * pNode; + int i, k, Id, Lit; + abctime clk; + // quit if CNF is ready + if ( NodeId == 0 || Swp_ManObj2Lit(p, NodeId) ) + return; +clk = Abc_Clock(); + // start the frontier + Vec_IntClear( p->vFront ); + Gia_ManObjAddToFrontier( p, NodeId, p->vFront ); + // explore nodes in the frontier + Gia_ManForEachObjVec( p->vFront, p->pGia, pNode, i ) + { + // create the supergate + assert( Swp_ManObj2Lit(p, Gia_ObjId(p->pGia, pNode)) ); + if ( Gia_ObjIsMuxType(pNode) ) + { + Vec_IntClear( p->vFanins ); + Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId0p( p->pGia, Gia_ObjFanin0(pNode) ) ); + Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId0p( p->pGia, Gia_ObjFanin1(pNode) ) ); + Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId1p( p->pGia, Gia_ObjFanin0(pNode) ) ); + Vec_IntPushUnique( p->vFanins, Gia_ObjFaninId1p( p->pGia, Gia_ObjFanin1(pNode) ) ); + Vec_IntForEachEntry( p->vFanins, Id, k ) + Gia_ManObjAddToFrontier( p, Id, p->vFront ); + Gia_ManAddClausesMux( p, pNode ); + } + else + { + Gia_ManCollectSuper( p->pGia, pNode, p->vFanins ); + Vec_IntForEachEntry( p->vFanins, Lit, k ) + Gia_ManObjAddToFrontier( p, Abc_Lit2Var(Lit), p->vFront ); + Gia_ManAddClausesSuper( p, pNode, p->vFanins ); + } + assert( Vec_IntSize(p->vFanins) > 1 ); + } +p->timeCnf += Abc_Clock() - clk; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Vec_Int_t * Gia_ManGetCex( Gia_Man_t * pGia, Vec_Int_t * vId2Lit, sat_solver * pSat, Vec_Int_t * vCex ) +{ + Gia_Obj_t * pObj; + int i, LitSat, Value; + Vec_IntClear( vCex ); + Gia_ManForEachPi( pGia, pObj, i ) + { + if ( Gia_ObjId(pGia, pObj) >= Vec_IntSize(vId2Lit) ) + { + Vec_IntPush( vCex, 2 ); + continue; + } + LitSat = Vec_IntEntry( vId2Lit, Gia_ObjId(pGia, pObj) ); + if ( LitSat == 0 ) + { + Vec_IntPush( vCex, 2 ); + continue; + } + assert( LitSat > 0 ); + Value = sat_solver_var_value(pSat, Abc_Lit2Var(LitSat)) ^ Abc_LitIsCompl(LitSat); + Vec_IntPush( vCex, Value ); + } + return vCex; +} + +/**Function************************************************************* + + Synopsis [Runs equivalence test for probes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_SweeperCheckEquiv( Gia_Man_t * pGia, int Probe1, int Probe2 ) +{ + Swp_Man_t * p = (Swp_Man_t *)pGia->pData; + int iLitOld, iLitNew, iLitAig, pLitsSat[2], RetValue, RetValue1, ProbeId, i; + abctime clk; + p->nSatCalls++; + assert( p->pSat != NULL ); + p->vCexUser = NULL; + + // get the literals + iLitOld = Gia_SweeperProbeLit( pGia, Probe1 ); + iLitNew = Gia_SweeperProbeLit( pGia, Probe2 ); + // if the literals are identical, the probes are equivalent + if ( iLitOld == iLitNew ) + return 1; + // if the literals are opposites, the probes are not equivalent + if ( Abc_LitRegular(iLitOld) == Abc_LitRegular(iLitNew) ) + { + Vec_IntFill( p->vCexSwp, Gia_ManPiNum(pGia), 2 ); + p->vCexUser = p->vCexSwp; + return 0; + } + // order the literals + if ( iLitOld < iLitNew ) + ABC_SWAP( int, iLitOld, iLitNew ); + assert( iLitOld > iLitNew ); + + // create logic cones and the array of assumptions + Vec_IntClear( p->vCondAssump ); + Vec_IntForEachEntry( p->vCondProbes, ProbeId, i ) + { + iLitAig = Gia_SweeperProbeLit( pGia, ProbeId ); + Gia_ManCnfNodeAddToSolver( p, Abc_Lit2Var(iLitAig) ); + Vec_IntPush( p->vCondAssump, Abc_LitNot(Swp_ManLit2Lit(p, iLitAig)) ); + } + Gia_ManCnfNodeAddToSolver( p, Abc_Lit2Var(iLitOld) ); + Gia_ManCnfNodeAddToSolver( p, Abc_Lit2Var(iLitNew) ); + sat_solver_compress( p->pSat ); + + // set the SAT literals + pLitsSat[0] = Swp_ManLit2Lit( p, iLitOld ); + pLitsSat[1] = Swp_ManLit2Lit( p, iLitNew ); + + // solve under assumptions + // A = 1; B = 0 OR A = 1; B = 1 + Vec_IntPush( p->vCondAssump, pLitsSat[0] ); + Vec_IntPush( p->vCondAssump, Abc_LitNot(pLitsSat[1]) ); + + // set runtime limit for this call + if ( p->nTimeOut ) + sat_solver_set_runtime_limit( p->pSat, p->nTimeOut * CLOCKS_PER_SEC + Abc_Clock() ); + +clk = Abc_Clock(); + RetValue1 = sat_solver_solve( p->pSat, Vec_IntArray(p->vCondAssump), Vec_IntArray(p->vCondAssump) + Vec_IntSize(p->vCondAssump), + (ABC_INT64_T)p->nConfMax, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + Vec_IntShrink( p->vCondAssump, Vec_IntSize(p->vCondAssump) - 2 ); +p->timeSat += Abc_Clock() - clk; + if ( RetValue1 == l_False ) + { + pLitsSat[0] = Abc_LitNot( pLitsSat[0] ); + RetValue = sat_solver_addclause( p->pSat, pLitsSat, pLitsSat + 2 ); + assert( RetValue ); + pLitsSat[0] = Abc_LitNot( pLitsSat[0] ); +p->timeSatUnsat += Abc_Clock() - clk; + p->nSatCallsUnsat++; + } + else if ( RetValue1 == l_True ) + { + p->vCexUser = Gia_ManGetCex( p->pGia, p->vId2Lit, p->pSat, p->vCexSwp ); +p->timeSatSat += Abc_Clock() - clk; + p->nSatCallsSat++; + return 0; + } + else // if ( RetValue1 == l_Undef ) + { +p->timeSatUndec += Abc_Clock() - clk; + p->nSatCallsUndec++; + return -1; + } + + // if the old node was constant 0, we already know the answer + if ( Gia_ManIsConstLit(iLitNew) ) + { + p->nSatProofs++; + return 1; + } + + // solve under assumptions + // A = 0; B = 1 OR A = 0; B = 0 + Vec_IntPush( p->vCondAssump, Abc_LitNot(pLitsSat[0]) ); + Vec_IntPush( p->vCondAssump, pLitsSat[1] ); + +clk = Abc_Clock(); + RetValue1 = sat_solver_solve( p->pSat, Vec_IntArray(p->vCondAssump), Vec_IntArray(p->vCondAssump) + Vec_IntSize(p->vCondAssump), + (ABC_INT64_T)p->nConfMax, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + Vec_IntShrink( p->vCondAssump, Vec_IntSize(p->vCondAssump) - 2 ); +p->timeSat += Abc_Clock() - clk; + if ( RetValue1 == l_False ) + { + pLitsSat[1] = Abc_LitNot( pLitsSat[1] ); + RetValue = sat_solver_addclause( p->pSat, pLitsSat, pLitsSat + 2 ); + assert( RetValue ); + pLitsSat[1] = Abc_LitNot( pLitsSat[1] ); +p->timeSatUnsat += Abc_Clock() - clk; + p->nSatCallsUnsat++; + } + else if ( RetValue1 == l_True ) + { + p->vCexUser = Gia_ManGetCex( p->pGia, p->vId2Lit, p->pSat, p->vCexSwp ); +p->timeSatSat += Abc_Clock() - clk; + p->nSatCallsSat++; + return 0; + } + else // if ( RetValue1 == l_Undef ) + { +p->timeSatUndec += Abc_Clock() - clk; + p->nSatCallsUndec++; + return -1; + } + // return SAT proof + p->nSatProofs++; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the set of conditions is UNSAT (0 if SAT; -1 if undecided).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_SweeperCondCheckUnsat( Gia_Man_t * pGia ) +{ + Swp_Man_t * p = (Swp_Man_t *)pGia->pData; + int RetValue, ProbeId, iLitAig, i; + abctime clk; + assert( p->pSat != NULL ); + p->nSatCalls++; + p->vCexUser = NULL; + + // create logic cones and the array of assumptions + Vec_IntClear( p->vCondAssump ); + Vec_IntForEachEntry( p->vCondProbes, ProbeId, i ) + { + iLitAig = Gia_SweeperProbeLit( pGia, ProbeId ); + Gia_ManCnfNodeAddToSolver( p, Abc_Lit2Var(iLitAig) ); + Vec_IntPush( p->vCondAssump, Abc_LitNot(Swp_ManLit2Lit(p, iLitAig)) ); + } + sat_solver_compress( p->pSat ); + + // set runtime limit for this call + if ( p->nTimeOut ) + sat_solver_set_runtime_limit( p->pSat, p->nTimeOut * CLOCKS_PER_SEC + Abc_Clock() ); + +clk = Abc_Clock(); + RetValue = sat_solver_solve( p->pSat, Vec_IntArray(p->vCondAssump), Vec_IntArray(p->vCondAssump) + Vec_IntSize(p->vCondAssump), + (ABC_INT64_T)p->nConfMax, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); +p->timeSat += Abc_Clock() - clk; + if ( RetValue == l_False ) + { + assert( Vec_IntSize(p->vCondProbes) > 0 ); +p->timeSatUnsat += Abc_Clock() - clk; + p->nSatCallsUnsat++; + p->nSatProofs++; + return 1; + } + else if ( RetValue == l_True ) + { + p->vCexUser = Gia_ManGetCex( p->pGia, p->vId2Lit, p->pSat, p->vCexSwp ); +p->timeSatSat += Abc_Clock() - clk; + p->nSatCallsSat++; + return 0; + } + else // if ( RetValue1 == l_Undef ) + { +p->timeSatUndec += Abc_Clock() - clk; + p->nSatCallsUndec++; + return -1; + } +} + +/**Function************************************************************* + + Synopsis [Performs grafting from another manager.] + + Description [Returns the array of resulting literals in the destination manager.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_SweeperGraft( Gia_Man_t * pDst, Vec_Int_t * vProbes, Gia_Man_t * pSrc ) +{ + Vec_Int_t * vOutLits; + Gia_Obj_t * pObj; + int i; + assert( Gia_SweeperIsRunning(pDst) ); + if ( vProbes ) + assert( Vec_IntSize(vProbes) == Gia_ManPiNum(pSrc) ); + else + assert( Gia_ManPiNum(pDst) == Gia_ManPiNum(pSrc) ); + Gia_ManForEachPi( pSrc, pObj, i ) + pObj->Value = vProbes ? Gia_SweeperProbeLit(pDst, Vec_IntEntry(vProbes, i)) : Gia_Obj2Lit(pDst,Gia_ManPi(pDst, i)); + Gia_ManForEachAnd( pSrc, pObj, i ) + pObj->Value = Gia_ManHashAnd( pDst, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + vOutLits = Vec_IntAlloc( Gia_ManPoNum(pSrc) ); + Gia_ManForEachPo( pSrc, pObj, i ) + Vec_IntPush( vOutLits, Gia_ObjFanin0Copy(pObj) ); + return vOutLits; +} + +/**Function************************************************************* + + Synopsis [Performs conditional sweeping of the cone.] + + Description [Returns the result as a new GIA manager with as many inputs + as the original manager and as many outputs as there are logic cones.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_SweeperSweep( Gia_Man_t * p, Vec_Int_t * vProbeOuts, int nWords, int nConfs, int fVerify, int fVerbose ) +{ + Vec_Int_t * vProbeConds; + Gia_Man_t * pGiaCond, * pGiaOuts, * pGiaRes; + Ssc_Pars_t Pars, * pPars = &Pars; + Ssc_ManSetDefaultParams( pPars ); + pPars->nWords = nWords; + pPars->nBTLimit = nConfs; + pPars->fVerify = fVerify; + pPars->fVerbose = fVerbose; + // sweeper is running + assert( Gia_SweeperIsRunning(p) ); + // extract conditions and logic cones + vProbeConds = Gia_SweeperCondVector( p ); + pGiaCond = Gia_SweeperExtractUserLogic( p, vProbeConds, NULL, NULL ); + pGiaOuts = Gia_SweeperExtractUserLogic( p, vProbeOuts, NULL, NULL ); + Gia_ManSetPhase( pGiaOuts ); + // if there is no conditions, define constant true constraint (constant 0 output) + if ( Gia_ManPoNum(pGiaCond) == 0 ) + Gia_ManAppendCo( pGiaCond, Gia_ManConst0Lit() ); + // perform sweeping under constraints + pGiaRes = Ssc_PerformSweeping( pGiaOuts, pGiaCond, pPars ); + Gia_ManStop( pGiaCond ); + Gia_ManStop( pGiaOuts ); + return pGiaRes; +} + +/**Function************************************************************* + + Synopsis [Procedure to perform conditional fraig sweeping on separate logic cones.] + + Description [The procedure takes GIA with the sweeper defined. The sweeper + is assumed to have some conditions currently pushed, which will be used + as constraints for fraig sweeping. The second argument (vProbes) contains + the array of probe IDs pointing to the user's logic cones to be SAT swept. + Finally, the optional command line (pCommLine) is an ABC command line + to be applied to the resulting GIA after SAT sweeping before it is + grafted back into the original GIA manager. The return value is the status + (success/failure) and the array of original probes possibly pointing to the + new literals in the original GIA manager, corresponding to the user's + logic cones after sweeping, synthesis and grafting.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_SweeperFraig( Gia_Man_t * p, Vec_Int_t * vProbeIds, char * pCommLime, int nWords, int nConfs, int fVerify, int fVerbose ) +{ + Gia_Man_t * pNew; + Vec_Int_t * vLits; + int ProbeId, i; + // sweeper is running + assert( Gia_SweeperIsRunning(p) ); + // sweep the logic + pNew = Gia_SweeperSweep( p, vProbeIds, nWords, nConfs, fVerify, fVerbose ); + if ( pNew == NULL ) + return 0; + // execute command line + if ( pCommLime ) + { + // set pNew to be current GIA in ABC + Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pNew ); + // execute command line pCommLine using Abc_CmdCommandExecute() + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), pCommLime ); + // get pNew to be current GIA in ABC + pNew = Abc_FrameGetGia( Abc_FrameGetGlobalFrame() ); + } + // return logic back into the main manager + vLits = Gia_SweeperGraft( p, NULL, pNew ); + Gia_ManStop( pNew ); + // update the array of probes + Vec_IntForEachEntry( vProbeIds, ProbeId, i ) + Gia_SweeperProbeUpdate( p, ProbeId, Vec_IntEntry(vLits, i) ); + Vec_IntFree( vLits ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Executes given command line for the logic defined by the probes.] + + Description [ ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_SweeperRun( Gia_Man_t * p, Vec_Int_t * vProbeIds, char * pCommLime, int fVerbose ) +{ + Gia_Man_t * pNew; + Vec_Int_t * vLits; + int ProbeId, i; + // sweeper is running + assert( Gia_SweeperIsRunning(p) ); + // sweep the logic + pNew = Gia_SweeperExtractUserLogic( p, vProbeIds, NULL, NULL ); + // execute command line + if ( pCommLime ) + { + if ( fVerbose ) + printf( "GIA manager statistics before and after applying \"%s\":\n", pCommLime ); + if ( fVerbose ) + Gia_ManPrintStats( pNew, NULL ); + // set pNew to be current GIA in ABC + Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pNew ); + // execute command line pCommLine using Abc_CmdCommandExecute() + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), pCommLime ); + // get pNew to be current GIA in ABC + pNew = Abc_FrameGetGia( Abc_FrameGetGlobalFrame() ); + if ( fVerbose ) + Gia_ManPrintStats( pNew, NULL ); + } + // return logic back into the main manager + vLits = Gia_SweeperGraft( p, NULL, pNew ); + Gia_ManStop( pNew ); + // update the array of probes + Vec_IntForEachEntry( vProbeIds, ProbeId, i ) + Gia_SweeperProbeUpdate( p, ProbeId, Vec_IntEntry(vLits, i) ); + Vec_IntFree( vLits ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Sweeper sweeper test.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_SweeperFraigTest( Gia_Man_t * pInit, int nWords, int nConfs, int fVerbose ) +{ + Gia_Man_t * p, * pGia; + Gia_Obj_t * pObj; + Vec_Int_t * vOuts; + int i; + // add one-hotness constraints + p = Gia_ManDupOneHot( pInit ); + // create sweeper + Gia_SweeperStart( p ); + // collect outputs and create conditions + vOuts = Vec_IntAlloc( Gia_ManPoNum(p) ); + Gia_ManForEachPo( p, pObj, i ) + if ( i < Gia_ManPoNum(p) - p->nConstrs ) // this is the user's output + Vec_IntPush( vOuts, Gia_SweeperProbeCreate( p, Gia_ObjFaninLit0p(p, pObj) ) ); + else // this is a constraint + Gia_SweeperCondPush( p, Gia_SweeperProbeCreate( p, Gia_ObjFaninLit0p(p, pObj) ) ); + // perform the sweeping + pGia = Gia_SweeperSweep( p, vOuts, nWords, nConfs, fVerbose, 0 ); +// pGia = Gia_ManDup( p ); + Vec_IntFree( vOuts ); + // sop the sweeper + Gia_SweeperStop( p ); + Gia_ManStop( p ); + return pGia; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaSwitch.c b/yosys/abc/src/aig/gia/giaSwitch.c new file mode 100644 index 00000000000..26e29591cf8 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaSwitch.c @@ -0,0 +1,864 @@ +/**CFile**************************************************************** + + FileName [giaSwitch.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Computing switching activity.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaSwitch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "giaAig.h" +#include "base/main/main.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// switching estimation parameters +typedef struct Gia_ParSwi_t_ Gia_ParSwi_t; +struct Gia_ParSwi_t_ +{ + // user-controlled parameters + int nWords; // the number of machine words + int nIters; // the number of timeframes + int nPref; // the number of first timeframes to skip + int nRandPiFactor; // PI trans prob (-1=3/8; 0=1/2; 1=1/4; 2=1/8, etc) + int fProbOne; // collect probability of one + int fProbTrans; // collect probatility of Swiing + int fVerbose; // enables verbose output +}; + +typedef struct Gia_ManSwi_t_ Gia_ManSwi_t; +struct Gia_ManSwi_t_ +{ + Gia_Man_t * pAig; + Gia_ParSwi_t * pPars; + int nWords; + // simulation information + unsigned * pDataSim; // simulation data + unsigned * pDataSimCis; // simulation data for CIs + unsigned * pDataSimCos; // simulation data for COs + int * pData1; // switching data +}; + +static inline unsigned * Gia_SwiData( Gia_ManSwi_t * p, int i ) { return p->pDataSim + i * p->nWords; } +static inline unsigned * Gia_SwiDataCi( Gia_ManSwi_t * p, int i ) { return p->pDataSimCis + i * p->nWords; } +static inline unsigned * Gia_SwiDataCo( Gia_ManSwi_t * p, int i ) { return p->pDataSimCos + i * p->nWords; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [This procedure sets default parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSetDefaultParamsSwi( Gia_ParSwi_t * p ) +{ + memset( p, 0, sizeof(Gia_ParSwi_t) ); + p->nWords = 10; // the number of machine words of simulatation data + p->nIters = 48; // the number of all timeframes to simulate + p->nPref = 16; // the number of first timeframes to skip when computing switching + p->nRandPiFactor = 0; // primary input transition probability (-1=3/8; 0=1/2; 1=1/4; 2=1/8, etc) + p->fProbOne = 0; // compute probability of signal being one (if 0, compute probability of switching) + p->fProbTrans = 1; // compute signal transition probability (if 0, compute transition probability using probability of being one) + p->fVerbose = 0; // enables verbose output +} + +/**Function************************************************************* + + Synopsis [Creates fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_ManSwi_t * Gia_ManSwiCreate( Gia_Man_t * pAig, Gia_ParSwi_t * pPars ) +{ + Gia_ManSwi_t * p; + p = ABC_ALLOC( Gia_ManSwi_t, 1 ); + memset( p, 0, sizeof(Gia_ManSwi_t) ); + p->pAig = Gia_ManFront( pAig ); + p->pPars = pPars; + p->nWords = pPars->nWords; + p->pDataSim = ABC_ALLOC( unsigned, p->nWords * p->pAig->nFront ); + p->pDataSimCis = ABC_ALLOC( unsigned, p->nWords * Gia_ManCiNum(p->pAig) ); + p->pDataSimCos = ABC_ALLOC( unsigned, p->nWords * Gia_ManCoNum(p->pAig) ); + p->pData1 = ABC_CALLOC( int, Gia_ManObjNum(pAig) ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSwiDelete( Gia_ManSwi_t * p ) +{ + Gia_ManStop( p->pAig ); + ABC_FREE( p->pData1 ); + ABC_FREE( p->pDataSim ); + ABC_FREE( p->pDataSimCis ); + ABC_FREE( p->pDataSimCos ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSwiSimInfoRandom( Gia_ManSwi_t * p, unsigned * pInfo, int nProbNum ) +{ + unsigned Mask = 0; + int w, i; + if ( nProbNum == -1 ) + { // 3/8 = 1/4 + 1/8 + Mask = (Gia_ManRandom( 0 ) & Gia_ManRandom( 0 )) | + (Gia_ManRandom( 0 ) & Gia_ManRandom( 0 ) & Gia_ManRandom( 0 )); + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] ^= Mask; + } + else if ( nProbNum > 0 ) + { + Mask = Gia_ManRandom( 0 ); + for ( i = 0; i < nProbNum; i++ ) + Mask &= Gia_ManRandom( 0 ); + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] ^= Mask; + } + else if ( nProbNum == 0 ) + { + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = Gia_ManRandom( 0 ); + } + else + assert( 0 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSwiSimInfoRandomShift( Gia_ManSwi_t * p, unsigned * pInfo, int nProbNum ) +{ + unsigned Mask = 0; + int w, i; + if ( nProbNum == -1 ) + { // 3/8 = 1/4 + 1/8 + Mask = (Gia_ManRandom( 0 ) & Gia_ManRandom( 0 )) | + (Gia_ManRandom( 0 ) & Gia_ManRandom( 0 ) & Gia_ManRandom( 0 )); + } + else if ( nProbNum >= 0 ) + { + Mask = Gia_ManRandom( 0 ); + for ( i = 0; i < nProbNum; i++ ) + Mask &= Gia_ManRandom( 0 ); + } + else + assert( 0 ); + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = (pInfo[w] << 16) | ((pInfo[w] ^ Mask) & 0xffff); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSwiSimInfoZero( Gia_ManSwi_t * p, unsigned * pInfo ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSwiSimInfoOne( Gia_ManSwi_t * p, unsigned * pInfo ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = ~0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSwiSimInfoCopy( Gia_ManSwi_t * p, unsigned * pInfo, unsigned * pInfo0 ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSwiSimInfoCopyShift( Gia_ManSwi_t * p, unsigned * pInfo, unsigned * pInfo0 ) +{ + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = (pInfo[w] << 16) | (pInfo0[w] & 0xffff); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSwiSimulateCi( Gia_ManSwi_t * p, Gia_Obj_t * pObj, int iCi ) +{ + unsigned * pInfo = Gia_SwiData( p, Gia_ObjValue(pObj) ); + unsigned * pInfo0 = Gia_SwiDataCi( p, iCi ); + int w; + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSwiSimulateCo( Gia_ManSwi_t * p, int iCo, Gia_Obj_t * pObj ) +{ + unsigned * pInfo = Gia_SwiDataCo( p, iCo ); + unsigned * pInfo0 = Gia_SwiData( p, Gia_ObjDiff0(pObj) ); + int w; + if ( Gia_ObjFaninC0(pObj) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = ~pInfo0[w]; + else + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSwiSimulateNode( Gia_ManSwi_t * p, Gia_Obj_t * pObj ) +{ + unsigned * pInfo = Gia_SwiData( p, Gia_ObjValue(pObj) ); + unsigned * pInfo0 = Gia_SwiData( p, Gia_ObjDiff0(pObj) ); + unsigned * pInfo1 = Gia_SwiData( p, Gia_ObjDiff1(pObj) ); + int w; + if ( Gia_ObjFaninC0(pObj) ) + { + if ( Gia_ObjFaninC1(pObj) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = ~(pInfo0[w] | pInfo1[w]); + else + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = ~pInfo0[w] & pInfo1[w]; + } + else + { + if ( Gia_ObjFaninC1(pObj) ) + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w] & ~pInfo1[w]; + else + for ( w = p->nWords-1; w >= 0; w-- ) + pInfo[w] = pInfo0[w] & pInfo1[w]; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSwiSimInfoInit( Gia_ManSwi_t * p ) +{ + int i = 0; + for ( ; i < Gia_ManPiNum(p->pAig); i++ ) + Gia_ManSwiSimInfoRandom( p, Gia_SwiDataCi(p, i), 0 ); + for ( ; i < Gia_ManCiNum(p->pAig); i++ ) + Gia_ManSwiSimInfoZero( p, Gia_SwiDataCi(p, i) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSwiSimInfoTransfer( Gia_ManSwi_t * p, int nProbNum ) +{ + int i = 0, nShift = Gia_ManPoNum(p->pAig)-Gia_ManPiNum(p->pAig); + for ( ; i < Gia_ManPiNum(p->pAig); i++ ) + Gia_ManSwiSimInfoRandom( p, Gia_SwiDataCi(p, i), nProbNum ); + for ( ; i < Gia_ManCiNum(p->pAig); i++ ) + Gia_ManSwiSimInfoCopy( p, Gia_SwiDataCi(p, i), Gia_SwiDataCo(p, nShift+i) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSwiSimInfoTransferShift( Gia_ManSwi_t * p, int nProbNum ) +{ + int i = 0, nShift = Gia_ManPoNum(p->pAig)-Gia_ManPiNum(p->pAig); + for ( ; i < Gia_ManPiNum(p->pAig); i++ ) + Gia_ManSwiSimInfoRandomShift( p, Gia_SwiDataCi(p, i), nProbNum ); + for ( ; i < Gia_ManCiNum(p->pAig); i++ ) + Gia_ManSwiSimInfoCopyShift( p, Gia_SwiDataCi(p, i), Gia_SwiDataCo(p, nShift+i) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManSwiSimInfoCountOnes( Gia_ManSwi_t * p, int iPlace ) +{ + unsigned * pInfo; + int w, Counter = 0; + pInfo = Gia_SwiData( p, iPlace ); + for ( w = p->nWords-1; w >= 0; w-- ) + Counter += Gia_WordCountOnes( pInfo[w] ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Gia_ManSwiSimInfoCountTrans( Gia_ManSwi_t * p, int iPlace ) +{ + unsigned * pInfo; + int w, Counter = 0; + pInfo = Gia_SwiData( p, iPlace ); + for ( w = p->nWords-1; w >= 0; w-- ) + Counter += 2*Gia_WordCountOnes( (pInfo[w] ^ (pInfo[w] >> 16)) & 0xffff ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManSwiSimulateRound( Gia_ManSwi_t * p, int fCount ) +{ + Gia_Obj_t * pObj; + int i;//, iCis = 0, iCos = 0; + assert( p->pAig->nFront > 0 ); + assert( Gia_ManConst0(p->pAig)->Value == 0 ); + Gia_ManSwiSimInfoZero( p, Gia_SwiData(p, 0) ); + Gia_ManForEachObj1( p->pAig, pObj, i ) + { + if ( Gia_ObjIsAndOrConst0(pObj) ) + { + assert( Gia_ObjValue(pObj) < p->pAig->nFront ); + Gia_ManSwiSimulateNode( p, pObj ); + } + else if ( Gia_ObjIsCo(pObj) ) + { + assert( Gia_ObjValue(pObj) == GIA_NONE ); +// Gia_ManSwiSimulateCo( p, iCos++, pObj ); + Gia_ManSwiSimulateCo( p, Gia_ObjCioId(pObj), pObj ); + } + else // if ( Gia_ObjIsCi(pObj) ) + { + assert( Gia_ObjValue(pObj) < p->pAig->nFront ); +// Gia_ManSwiSimulateCi( p, pObj, iCis++ ); + Gia_ManSwiSimulateCi( p, pObj, Gia_ObjCioId(pObj) ); + } + if ( fCount && !Gia_ObjIsCo(pObj) ) + { + if ( p->pPars->fProbTrans ) + p->pData1[i] += Gia_ManSwiSimInfoCountTrans( p, Gia_ObjValue(pObj) ); + else + p->pData1[i] += Gia_ManSwiSimInfoCountOnes( p, Gia_ObjValue(pObj) ); + } + } +// assert( Gia_ManCiNum(p->pAig) == iCis ); +// assert( Gia_ManCoNum(p->pAig) == iCos ); +} + +/**Function************************************************************* + + Synopsis [Computes switching activity of one node.] + + Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Gia_ManSwiComputeSwitching( int nOnes, int nSimWords ) +{ + int nTotal = 32 * nSimWords; + return (float)2.0 * nOnes / nTotal * (nTotal - nOnes) / nTotal; +} + +/**Function************************************************************* + + Synopsis [Computes switching activity of one node.] + + Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Gia_ManSwiComputeProbOne( int nOnes, int nSimWords ) +{ + int nTotal = 32 * nSimWords; + return (float)nOnes / nTotal; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManSwiSimulate( Gia_Man_t * pAig, Gia_ParSwi_t * pPars ) +{ + Gia_ManSwi_t * p; + Gia_Obj_t * pObj; + Vec_Int_t * vSwitching; + float * pSwitching; + int i; + abctime clk, clkTotal = Abc_Clock(); + if ( pPars->fProbOne && pPars->fProbTrans ) + printf( "Conflict of options: Can either compute probability of 1, or probability of switching by observing transitions.\n" ); + // create manager + clk = Abc_Clock(); + p = Gia_ManSwiCreate( pAig, pPars ); + if ( pPars->fVerbose ) + { + printf( "Obj = %8d (%8d). F = %6d. ", + pAig->nObjs, Gia_ManCiNum(pAig) + Gia_ManAndNum(pAig), p->pAig->nFront ); + printf( "AIG = %7.2f MB. F-mem = %7.2f MB. Other = %7.2f MB. ", + 12.0*Gia_ManObjNum(p->pAig)/(1<<20), + 4.0*p->nWords*p->pAig->nFront/(1<<20), + 4.0*p->nWords*(Gia_ManCiNum(p->pAig) + Gia_ManCoNum(p->pAig))/(1<<20) ); + ABC_PRT( "Time", Abc_Clock() - clk ); + } + // perform simulation + Gia_ManRandom( 1 ); + Gia_ManSwiSimInfoInit( p ); + for ( i = 0; i < pPars->nIters; i++ ) + { + Gia_ManSwiSimulateRound( p, i >= pPars->nPref ); + if ( i == pPars->nIters - 1 ) + break; + if ( pPars->fProbTrans ) + Gia_ManSwiSimInfoTransferShift( p, pPars->nRandPiFactor ); + else + Gia_ManSwiSimInfoTransfer( p, pPars->nRandPiFactor ); + } + if ( pPars->fVerbose ) + { + printf( "Simulated %d frames with %d words. ", pPars->nIters, pPars->nWords ); + ABC_PRT( "Simulation time", Abc_Clock() - clkTotal ); + } + // derive the result + vSwitching = Vec_IntStart( Gia_ManObjNum(pAig) ); + pSwitching = (float *)vSwitching->pArray; + if ( pPars->fProbOne ) + { + Gia_ManForEachObj( pAig, pObj, i ) + pSwitching[i] = Gia_ManSwiComputeProbOne( p->pData1[i], pPars->nWords*(pPars->nIters-pPars->nPref) ); + Gia_ManForEachCo( pAig, pObj, i ) + { + if ( Gia_ObjFaninC0(pObj) ) + pSwitching[Gia_ObjId(pAig,pObj)] = (float)1.0-pSwitching[Gia_ObjId(pAig,Gia_ObjFanin0(pObj))]; + else + pSwitching[Gia_ObjId(pAig,pObj)] = pSwitching[Gia_ObjId(pAig,Gia_ObjFanin0(pObj))]; + } + } + else if ( pPars->fProbTrans ) + { + Gia_ManForEachObj( pAig, pObj, i ) + pSwitching[i] = Gia_ManSwiComputeSwitching( p->pData1[i], pPars->nWords*(pPars->nIters-pPars->nPref) ); + } + else + { + Gia_ManForEachObj( pAig, pObj, i ) + pSwitching[i] = Gia_ManSwiComputeSwitching( p->pData1[i], pPars->nWords*(pPars->nIters-pPars->nPref) ); + } +/* + printf( "PI: " ); + Gia_ManForEachPi( pAig, pObj, i ) + printf( "%d=%d (%f) ", i, p->pData1[Gia_ObjId(pAig,pObj)], pSwitching[Gia_ObjId(pAig,pObj)] ); + printf( "\n" ); + + printf( "LO: " ); + Gia_ManForEachRo( pAig, pObj, i ) + printf( "%d=%d (%f) ", i, p->pData1[Gia_ObjId(pAig,pObj)], pSwitching[Gia_ObjId(pAig,pObj)] ); + printf( "\n" ); + + printf( "PO: " ); + Gia_ManForEachPo( pAig, pObj, i ) + printf( "%d=%d (%f) ", i, p->pData1[Gia_ObjId(pAig,pObj)], pSwitching[Gia_ObjId(pAig,pObj)] ); + printf( "\n" ); + + printf( "LI: " ); + Gia_ManForEachRi( pAig, pObj, i ) + printf( "%d=%d (%f) ", i, p->pData1[Gia_ObjId(pAig,pObj)], pSwitching[Gia_ObjId(pAig,pObj)] ); + printf( "\n" ); +*/ + Gia_ManSwiDelete( p ); + return vSwitching; + +} +/**Function************************************************************* + + Synopsis [Computes probability of switching (or of being 1).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManComputeSwitchProbs( Gia_Man_t * pGia, int nFrames, int nPref, int fProbOne ) +{ + Gia_ParSwi_t Pars, * pPars = &Pars; + // set the default parameters + Gia_ManSetDefaultParamsSwi( pPars ); + // override some of the defaults + pPars->nIters = nFrames; // set number of total timeframes + if ( Abc_FrameReadFlag("seqsimframes") ) + pPars->nIters = atoi( Abc_FrameReadFlag("seqsimframes") ); + pPars->nPref = nPref; // set number of first timeframes to skip + // decide what should be computed + if ( fProbOne ) + { + // if the user asked to compute propability of 1, we do not need transition information + pPars->fProbOne = 1; // enable computing probabiblity of being one + pPars->fProbTrans = 0; // disable computing transition probability + } + else + { + // if the user asked for transition propabability, we do not need to compute probability of 1 + pPars->fProbOne = 0; // disable computing probabiblity of being one + pPars->fProbTrans = 1; // enable computing transition probability + } + // perform the computation of switching activity + return Gia_ManSwiSimulate( pGia, pPars ); +} +Vec_Int_t * Gia_ManComputeSwitchProbs2( Gia_Man_t * pGia, int nFrames, int nPref, int fProbOne, int nRandPiFactor ) +{ + Gia_ParSwi_t Pars, * pPars = &Pars; + // set the default parameters + Gia_ManSetDefaultParamsSwi( pPars ); + pPars->nRandPiFactor = nRandPiFactor; + // override some of the defaults + pPars->nIters = nFrames; // set number of total timeframes + if ( Abc_FrameReadFlag("seqsimframes") ) + pPars->nIters = atoi( Abc_FrameReadFlag("seqsimframes") ); + pPars->nPref = nPref; // set number of first timeframes to skip + // decide what should be computed + if ( fProbOne ) + { + // if the user asked to compute propability of 1, we do not need transition information + pPars->fProbOne = 1; // enable computing probabiblity of being one + pPars->fProbTrans = 0; // disable computing transition probability + } + else + { + // if the user asked for transition propabability, we do not need to compute probability of 1 + pPars->fProbOne = 0; // disable computing probabiblity of being one + pPars->fProbTrans = 1; // enable computing transition probability + } + // perform the computation of switching activity + return Gia_ManSwiSimulate( pGia, pPars ); +} +Vec_Int_t * Saig_ManComputeSwitchProbs( Aig_Man_t * pAig, int nFrames, int nPref, int fProbOne ) +{ + Vec_Int_t * vSwitching, * vResult; + Gia_Man_t * p; + Aig_Obj_t * pObj; + int i; + // translate AIG into the intermediate form (takes care of choices if present!) + p = Gia_ManFromAigSwitch( pAig ); + // perform the computation of switching activity + vSwitching = Gia_ManComputeSwitchProbs( p, nFrames, nPref, fProbOne ); + // transfer the computed result to the original AIG + vResult = Vec_IntStart( Aig_ManObjNumMax(pAig) ); + Aig_ManForEachObj( pAig, pObj, i ) + { +// if ( Aig_ObjIsCo(pObj) ) +// printf( "%d=%f\n", i, Abc_Int2Float( Vec_IntEntry(vSwitching, Abc_Lit2Var(pObj->iData)) ) ); + Vec_IntWriteEntry( vResult, i, Vec_IntEntry(vSwitching, Abc_Lit2Var(pObj->iData)) ); + } + // delete intermediate results + Vec_IntFree( vSwitching ); + Gia_ManStop( p ); + return vResult; +} + +/**Function************************************************************* + + Synopsis [Computes probability of switching (or of being 1).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Gia_ManEvaluateSwitching( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + float SwitchTotal = 0.0; + int i; + assert( p->pSwitching ); + ABC_FREE( p->pRefs ); + Gia_ManCreateRefs( p ); + Gia_ManForEachObj( p, pObj, i ) + SwitchTotal += (float)Gia_ObjRefNum(p, pObj) * p->pSwitching[i] / 255; + return SwitchTotal; +} + +/**Function************************************************************* + + Synopsis [Computes probability of switching (or of being 1).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +/* +float Gia_ManComputeSwitching( Gia_Man_t * p, int nFrames, int nPref, int fProbOne ) +{ + Gia_Man_t * pDfs; + Gia_Obj_t * pObj, * pObjDfs; + Vec_Int_t * vSwitching; + float * pSwitching, Switch, SwitchTotal = 0.0; + int i; + // derives the DFS ordered AIG + if ( Gia_ManHasMapping(p) ) + Gia_ManSetRefsMapped(p); + else + Gia_ManCreateRefs( p ); +// pDfs = Gia_ManDupOrderDfs( p ); + pDfs = Gia_ManDup( p ); + assert( Gia_ManObjNum(pDfs) == Gia_ManObjNum(p) ); + // perform the computation of switching activity + vSwitching = Gia_ManComputeSwitchProbs( pDfs, nFrames, nPref, fProbOne ); + // transfer the computed result to the original AIG + ABC_FREE( p->pSwitching ); + p->pSwitching = ABC_CALLOC( unsigned char, Gia_ManObjNum(p) ); + pSwitching = (float *)vSwitching->pArray; + Gia_ManForEachObj( p, pObj, i ) + { + pObjDfs = Gia_ObjFromLit( pDfs, pObj->Value ); + Switch = pSwitching[ Gia_ObjId(pDfs, pObjDfs) ]; + p->pSwitching[i] = (char)((Switch >= 1.0) ? 255 : (int)((0.002 + Switch) * 255)); // 0.00196 = (1/255)/2 + if ( Gia_ObjIsCi(pObj) || (Gia_ObjIsAnd(pObj) && (!Gia_ManHasMapping(p) || Gia_ObjIsLut(p, i))) ) + { + SwitchTotal += (float)Gia_ObjRefNum(p, pObj) * p->pSwitching[i] / 255; +// printf( "%d = %.2f\n", i, (float)Gia_ObjRefNum(p, pObj) * p->pSwitching[i] / 255 ); + } + } + Vec_IntFree( vSwitching ); + Gia_ManStop( pDfs ); + return SwitchTotal; +} +*/ +float Gia_ManComputeSwitching( Gia_Man_t * p, int nFrames, int nPref, int fProbOne ) +{ + Vec_Int_t * vSwitching = Gia_ManComputeSwitchProbs( p, nFrames, nPref, fProbOne ); + float * pSwi = (float *)Vec_IntArray(vSwitching), SwiTotal = 0; + Gia_Obj_t * pObj; + int i, k, iFan; + if ( Gia_ManHasMapping(p) ) + { + Gia_ManForEachLut( p, i ) + Gia_LutForEachFanin( p, i, iFan, k ) + SwiTotal += pSwi[iFan]; + } + else + { + Gia_ManForEachAnd( p, pObj, i ) + SwiTotal += pSwi[Gia_ObjFaninId0(pObj, i)] + pSwi[Gia_ObjFaninId1(pObj, i)]; + } + if ( 0 ) + { + Gia_ManForEachObj( p, pObj, i ) + { + printf( "Switch %6.2f ", pSwi[i] ); + Gia_ObjPrint( p, pObj ); + } + } + Vec_IntFree( vSwitching ); + return SwiTotal; +} + +/**Function************************************************************* + + Synopsis [Determine probability of being 1 at the outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Flt_t * Gia_ManPrintOutputProb( Gia_Man_t * p ) +{ + Vec_Flt_t * vSimData; + Gia_Man_t * pDfs = Gia_ManDup( p ); + assert( Gia_ManObjNum(pDfs) == Gia_ManObjNum(p) ); + vSimData = (Vec_Flt_t *)Gia_ManComputeSwitchProbs( pDfs, (Gia_ManRegNum(p) ? 16 : 1), 0, 1 ); + Gia_ManStop( pDfs ); + return vSimData; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaTim.c b/yosys/abc/src/aig/gia/giaTim.c new file mode 100644 index 00000000000..fc40835cba7 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaTim.c @@ -0,0 +1,1076 @@ +/**CFile**************************************************************** + + FileName [giaTim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Procedures with hierarchy/timing manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaTim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "giaAig.h" +#include "misc/tim/tim.h" +#include "misc/extra/extra.h" +#include "proof/cec/cec.h" +#include "proof/fra/fra.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the number of boxes in the AIG with boxes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManBoxNum( Gia_Man_t * p ) +{ + return p->pManTime ? Tim_ManBoxNum((Tim_Man_t *)p->pManTime) : 0; +} +int Gia_ManRegBoxNum( Gia_Man_t * p ) +{ + return p->vRegClasses ? Vec_IntSize(p->vRegClasses) : 0; +} +int Gia_ManNonRegBoxNum( Gia_Man_t * p ) +{ + return Gia_ManBoxNum(p) - Gia_ManRegBoxNum(p); +} +int Gia_ManBlackBoxNum( Gia_Man_t * p ) +{ + return Tim_ManBlackBoxNum((Tim_Man_t *)p->pManTime); +} +int Gia_ManBoxCiNum( Gia_Man_t * p ) +{ + return p->pManTime ? Gia_ManCiNum(p) - Tim_ManPiNum((Tim_Man_t *)p->pManTime) : 0; +} +int Gia_ManBoxCoNum( Gia_Man_t * p ) +{ + return p->pManTime ? Gia_ManCoNum(p) - Tim_ManPoNum((Tim_Man_t *)p->pManTime) : 0; +} +int Gia_ManClockDomainNum( Gia_Man_t * p ) +{ + int i, nDoms, Count = 0; + if ( p->vRegClasses == NULL ) + return 0; + nDoms = Vec_IntFindMax(p->vRegClasses); + assert( Vec_IntCountEntry(p->vRegClasses, 0) == 0 ); + for ( i = 1; i <= nDoms; i++ ) + if ( Vec_IntCountEntry(p->vRegClasses, i) > 0 ) + Count++; + return Count; +} + +/**Function************************************************************* + + Synopsis [Returns one if this is a seq AIG with non-trivial boxes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManIsSeqWithBoxes( Gia_Man_t * p ) +{ + return (Gia_ManRegNum(p) > 0 && Gia_ManBoxNum(p) > 0); +} + +/**Function************************************************************* + + Synopsis [Makes sure the manager is normalized.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManIsNormalized( Gia_Man_t * p ) +{ + int i, nOffset; + nOffset = 1; + for ( i = 0; i < Gia_ManCiNum(p); i++ ) + if ( !Gia_ObjIsCi( Gia_ManObj(p, nOffset+i) ) ) + return 0; + nOffset = 1 + Gia_ManCiNum(p) + Gia_ManAndNum(p); + for ( i = 0; i < Gia_ManCoNum(p); i++ ) + if ( !Gia_ObjIsCo( Gia_ManObj(p, nOffset+i) ) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG in the DFS order while putting CIs first.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupNormalize( Gia_Man_t * p, int fHashMapping ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + if ( !Gia_ManIsSeqWithBoxes(p) ) + { + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + } + else + { + // current CI order: PIs + FOs + NewCIs + // desired reorder: PIs + NewCIs + FOs + int nCIs = Tim_ManPiNum( (Tim_Man_t *)p->pManTime ); + int nAll = Tim_ManCiNum( (Tim_Man_t *)p->pManTime ); + int nPis = nCIs - Gia_ManRegNum(p); + assert( nAll == Gia_ManCiNum(p) ); + assert( nPis > 0 ); + // copy PIs first + for ( i = 0; i < nPis; i++ ) + Gia_ManCi(p, i)->Value = Gia_ManAppendCi(pNew); + // copy new CIs second + for ( i = nCIs; i < nAll; i++ ) + Gia_ManCi(p, i)->Value = Gia_ManAppendCi(pNew); + // copy flops last + for ( i = nCIs - Gia_ManRegNum(p); i < nCIs; i++ ) + Gia_ManCi(p, i)->Value = Gia_ManAppendCi(pNew); + printf( "Warning: Shuffled CI order to be correct sequential AIG.\n" ); + } + if ( fHashMapping ) Gia_ManHashAlloc( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + if ( Gia_ObjIsBuf(pObj) ) + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( fHashMapping ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( fHashMapping ) Gia_ManHashStop( pNew ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew->nConstrs = p->nConstrs; + assert( Gia_ManIsNormalized(pNew) ); + Gia_ManDupRemapEquiv( pNew, p ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Reorders flops for sequential AIGs with boxes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupUnshuffleInputs( Gia_Man_t * p ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i, nCIs, nAll, nPis; + // sanity checks + assert( Gia_ManIsNormalized(p) ); + assert( Gia_ManIsSeqWithBoxes(p) ); + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + // change input order + // desired reorder: PIs + NewCIs + FOs + // current CI order: PIs + FOs + NewCIs + nCIs = Tim_ManPiNum( (Tim_Man_t *)p->pManTime ); + nAll = Tim_ManCiNum( (Tim_Man_t *)p->pManTime ); + nPis = nCIs - Gia_ManRegNum(p); + assert( nAll == Gia_ManCiNum(p) ); + assert( nPis > 0 ); + // copy PIs first + for ( i = 0; i < nPis; i++ ) + Gia_ManCi(p, i)->Value = Gia_ManAppendCi(pNew); + // copy flops second + for ( i = nAll - Gia_ManRegNum(p); i < nAll; i++ ) + Gia_ManCi(p, i)->Value = Gia_ManAppendCi(pNew); + // copy new CIs last + for ( i = nPis; i < nAll - Gia_ManRegNum(p); i++ ) + Gia_ManCi(p, i)->Value = Gia_ManAppendCi(pNew); + printf( "Warning: Unshuffled CI order to be correct AIG with boxes.\n" ); + // other things + Gia_ManForEachAnd( p, pObj, i ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew->nConstrs = p->nConstrs; + assert( Gia_ManIsNormalized(pNew) ); + Gia_ManDupRemapEquiv( pNew, p ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Find the ordering of AIG objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManOrderWithBoxes_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return 0; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( Gia_ObjIsCi(pObj) ) + { + p->iData2 = Gia_ObjCioId(pObj); + return 1; + } + assert( Gia_ObjIsAnd(pObj) ); + if ( Gia_ObjIsBuf(pObj) ) + { + if ( Gia_ManOrderWithBoxes_rec( p, Gia_ObjFanin0(pObj), vNodes ) ) + return 1; + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); + return 0; + } + if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) ) + if ( Gia_ManOrderWithBoxes_rec( p, Gia_ObjSiblObj(p, Gia_ObjId(p, pObj)), vNodes ) ) + return 1; + if ( Gia_ManOrderWithBoxes_rec( p, Gia_ObjFanin0(pObj), vNodes ) ) + return 1; + if ( Gia_ManOrderWithBoxes_rec( p, Gia_ObjFanin1(pObj), vNodes ) ) + return 1; + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); + return 0; +} +Vec_Int_t * Gia_ManOrderWithBoxes( Gia_Man_t * p ) +{ + Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; + Vec_Int_t * vNodes; + Gia_Obj_t * pObj; + int i, k, curCi, curCo; + assert( pManTime != NULL ); + assert( Gia_ManIsNormalized( p ) ); + // start trav IDs + Gia_ManIncrementTravId( p ); + // start the array + vNodes = Vec_IntAlloc( Gia_ManObjNum(p) ); + // include constant + Vec_IntPush( vNodes, 0 ); + Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); + // include primary inputs + for ( i = 0; i < Tim_ManPiNum(pManTime); i++ ) + { + pObj = Gia_ManCi( p, i ); + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); + Gia_ObjSetTravIdCurrent( p, pObj ); + assert( Gia_ObjId(p, pObj) == i+1 ); + } + // for each box, include box nodes + curCi = Tim_ManPiNum(pManTime); + curCo = 0; + for ( i = 0; i < Tim_ManBoxNum(pManTime); i++ ) + { + // add internal nodes + for ( k = 0; k < Tim_ManBoxInputNum(pManTime, i); k++ ) + { + pObj = Gia_ManCo( p, curCo + k ); + if ( Gia_ManOrderWithBoxes_rec( p, Gia_ObjFanin0(pObj), vNodes ) ) + { + int iCiNum = p->iData2; + int iBoxNum = Tim_ManBoxFindFromCiNum( pManTime, iCiNum ); + printf( "The command has to terminate. Boxes are not in a topological order.\n" ); + printf( "The following information may help debugging (numbers are 0-based):\n" ); + printf( "Input %d of BoxA %d (1stCI = %d; 1stCO = %d) has TFI with CI %d,\n", + k, i, Tim_ManBoxOutputFirst(pManTime, i), Tim_ManBoxInputFirst(pManTime, i), iCiNum ); + printf( "which corresponds to output %d of BoxB %d (1stCI = %d; 1stCO = %d).\n", + iCiNum - Tim_ManBoxOutputFirst(pManTime, iBoxNum), iBoxNum, + Tim_ManBoxOutputFirst(pManTime, iBoxNum), Tim_ManBoxInputFirst(pManTime, iBoxNum) ); + printf( "In a correct topological order, BoxB should precede BoxA.\n" ); + Vec_IntFree( vNodes ); + p->iData2 = 0; + return NULL; + } + } + // add POs corresponding to box inputs + for ( k = 0; k < Tim_ManBoxInputNum(pManTime, i); k++ ) + { + pObj = Gia_ManCo( p, curCo + k ); + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); + } + curCo += Tim_ManBoxInputNum(pManTime, i); + // add PIs corresponding to box outputs + for ( k = 0; k < Tim_ManBoxOutputNum(pManTime, i); k++ ) + { + pObj = Gia_ManCi( p, curCi + k ); + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); + Gia_ObjSetTravIdCurrent( p, pObj ); + } + curCi += Tim_ManBoxOutputNum(pManTime, i); + } + // add remaining nodes + for ( i = Tim_ManCoNum(pManTime) - Tim_ManPoNum(pManTime); i < Tim_ManCoNum(pManTime); i++ ) + { + pObj = Gia_ManCo( p, i ); + Gia_ManOrderWithBoxes_rec( p, Gia_ObjFanin0(pObj), vNodes ); + } + // add POs + for ( i = Tim_ManCoNum(pManTime) - Tim_ManPoNum(pManTime); i < Tim_ManCoNum(pManTime); i++ ) + { + pObj = Gia_ManCo( p, i ); + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); + } + curCo += Tim_ManPoNum(pManTime); + // verify counts + assert( curCi == Gia_ManCiNum(p) ); + assert( curCo == Gia_ManCoNum(p) ); + //assert( Vec_IntSize(vNodes) == Gia_ManObjNum(p) ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG according to the timing manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupUnnormalize( Gia_Man_t * p ) +{ + Vec_Int_t * vNodes; + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + assert( !Gia_ManBufNum(p) ); + vNodes = Gia_ManOrderWithBoxes( p ); + if ( vNodes == NULL ) + return NULL; + Gia_ManFillValue( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + if ( Gia_ManHasChoices(p) ) + pNew->pSibls = ABC_CALLOC( int, Gia_ManObjNum(p) ); + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsAnd(pObj) ) + { + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) ) + pNew->pSibls[Abc_Lit2Var(pObj->Value)] = Abc_Lit2Var(Gia_ObjSiblObj(p, Gia_ObjId(p, pObj))->Value); + } + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + else if ( Gia_ObjIsConst0(pObj) ) + pObj->Value = 0; + else assert( 0 ); + } + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + Vec_IntFree( vNodes ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Remaps the AIG from the old manager into the new manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCleanupRemap( Gia_Man_t * p, Gia_Man_t * pGia ) +{ + Gia_Obj_t * pObj, * pObjGia; + int i, iPrev; + Gia_ManForEachObj1( p, pObj, i ) + { + iPrev = Gia_ObjValue(pObj); + if ( iPrev == ~0 ) + continue; + pObjGia = Gia_ManObj( pGia, Abc_Lit2Var(iPrev) ); + if ( pObjGia->Value == ~0 ) + Gia_ObjSetValue( pObj, pObjGia->Value ); + else + Gia_ObjSetValue( pObj, Abc_LitNotCond(pObjGia->Value, Abc_LitIsCompl(iPrev)) ); + } +} + +/**Function************************************************************* + + Synopsis [Computes level with boxes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManLevelWithBoxes_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return 0; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( Gia_ObjIsCi(pObj) ) + return 1; + assert( Gia_ObjIsAnd(pObj) ); + if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) ) + Gia_ManLevelWithBoxes_rec( p, Gia_ObjSiblObj(p, Gia_ObjId(p, pObj)) ); + if ( Gia_ManLevelWithBoxes_rec( p, Gia_ObjFanin0(pObj) ) ) + return 1; + if ( Gia_ManLevelWithBoxes_rec( p, Gia_ObjFanin1(pObj) ) ) + return 1; + Gia_ObjSetAndLevel( p, pObj ); + return 0; +} +int Gia_ManLevelWithBoxes( Gia_Man_t * p ) +{ + int nAnd2Delay = p->nAnd2Delay ? p->nAnd2Delay : 1; + Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; + Gia_Obj_t * pObj, * pObjIn; + int i, k, j, curCi, curCo, LevelMax; + assert( Gia_ManRegNum(p) == 0 ); + assert( Gia_ManBufNum(p) == 0 ); + // copy const and real PIs + Gia_ManCleanLevels( p, Gia_ManObjNum(p) ); + Gia_ObjSetLevel( p, Gia_ManConst0(p), 0 ); + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); + for ( i = 0; i < Tim_ManPiNum(pManTime); i++ ) + { + pObj = Gia_ManCi( p, i ); + Gia_ObjSetLevel( p, pObj, Tim_ManGetCiArrival(pManTime, i) / nAnd2Delay ); + Gia_ObjSetTravIdCurrent( p, pObj ); + } + // create logic for each box + curCi = Tim_ManPiNum(pManTime); + curCo = 0; + for ( i = 0; i < Tim_ManBoxNum(pManTime); i++ ) + { + int nBoxInputs = Tim_ManBoxInputNum( pManTime, i ); + int nBoxOutputs = Tim_ManBoxOutputNum( pManTime, i ); + float * pDelayTable = Tim_ManBoxDelayTable( pManTime, i ); + // compute level for TFI of box inputs + for ( k = 0; k < nBoxInputs; k++ ) + { + pObj = Gia_ManCo( p, curCo + k ); + if ( Gia_ManLevelWithBoxes_rec( p, Gia_ObjFanin0(pObj) ) ) + { + printf( "Boxes are not in a topological order. Switching to level computation without boxes.\n" ); + return Gia_ManLevelNum( p ); + } + // set box input level + Gia_ObjSetCoLevel( p, pObj ); + } + // compute level for box outputs + for ( k = 0; k < nBoxOutputs; k++ ) + { + pObj = Gia_ManCi( p, curCi + k ); + Gia_ObjSetTravIdCurrent( p, pObj ); + // evaluate delay of this output + LevelMax = 0; + assert( nBoxInputs == (int)pDelayTable[1] ); + for ( j = 0; j < nBoxInputs && (pObjIn = Gia_ManCo(p, curCo + j)); j++ ) + if ( (int)pDelayTable[3+k*nBoxInputs+j] != -ABC_INFINITY ) + LevelMax = Abc_MaxInt( LevelMax, Gia_ObjLevel(p, pObjIn) + ((int)pDelayTable[3+k*nBoxInputs+j] / nAnd2Delay) ); + // set box output level + Gia_ObjSetLevel( p, pObj, LevelMax ); + } + curCo += nBoxInputs; + curCi += nBoxOutputs; + } + // add remaining nodes + p->nLevels = 0; + for ( i = Tim_ManCoNum(pManTime) - Tim_ManPoNum(pManTime); i < Tim_ManCoNum(pManTime); i++ ) + { + pObj = Gia_ManCo( p, i ); + Gia_ManLevelWithBoxes_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ObjSetCoLevel( p, pObj ); + p->nLevels = Abc_MaxInt( p->nLevels, Gia_ObjLevel(p, pObj) ); + } + curCo += Tim_ManPoNum(pManTime); + // verify counts + assert( curCi == Gia_ManCiNum(p) ); + assert( curCo == Gia_ManCoNum(p) ); +// printf( "Max level is %d.\n", p->nLevels ); + return p->nLevels; +} + +/**Function************************************************************* + + Synopsis [Computes level with boxes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManLutLevelWithBoxes_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + int iObj, k, iFan, Level = 0; + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return 0; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( Gia_ObjIsCi(pObj) ) + return 1; + assert( Gia_ObjIsAnd(pObj) ); + iObj = Gia_ObjId( p, pObj ); + Gia_LutForEachFanin( p, iObj, iFan, k ) + { + if ( Gia_ManLutLevelWithBoxes_rec( p, Gia_ManObj(p, iFan) ) ) + return 1; + Level = Abc_MaxInt( Level, Gia_ObjLevelId(p, iFan) ); + } + Gia_ObjSetLevelId( p, iObj, Level + 1 ); + return 0; +} +int Gia_ManLutLevelWithBoxes( Gia_Man_t * p ) +{ +// int nAnd2Delay = p->nAnd2Delay ? p->nAnd2Delay : 1; + Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; + Gia_Obj_t * pObj, * pObjIn; + int i, k, j, curCi, curCo, LevelMax; + assert( Gia_ManRegNum(p) == 0 ); + if ( pManTime == NULL ) + return Gia_ManLutLevel(p, NULL); + // copy const and real PIs + Gia_ManCleanLevels( p, Gia_ManObjNum(p) ); + Gia_ObjSetLevel( p, Gia_ManConst0(p), 0 ); + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); + for ( i = 0; i < Tim_ManPiNum(pManTime); i++ ) + { + pObj = Gia_ManCi( p, i ); +// Gia_ObjSetLevel( p, pObj, Tim_ManGetCiArrival(pManTime, i) / nAnd2Delay ); + Gia_ObjSetLevel( p, pObj, 0 ); + Gia_ObjSetTravIdCurrent( p, pObj ); + } + // create logic for each box + curCi = Tim_ManPiNum(pManTime); + curCo = 0; + for ( i = 0; i < Tim_ManBoxNum(pManTime); i++ ) + { + int nBoxInputs = Tim_ManBoxInputNum( pManTime, i ); + int nBoxOutputs = Tim_ManBoxOutputNum( pManTime, i ); + float * pDelayTable = Tim_ManBoxDelayTable( pManTime, i ); + // compute level for TFI of box inputs + for ( k = 0; k < nBoxInputs; k++ ) + { + pObj = Gia_ManCo( p, curCo + k ); + if ( Gia_ManLutLevelWithBoxes_rec( p, Gia_ObjFanin0(pObj) ) ) + { + printf( "Boxes are not in a topological order. Switching to level computation without boxes.\n" ); + return Gia_ManLevelNum( p ); + } + // set box input level + Gia_ObjSetCoLevel( p, pObj ); + } + // compute level for box outputs + for ( k = 0; k < nBoxOutputs; k++ ) + { + pObj = Gia_ManCi( p, curCi + k ); + Gia_ObjSetTravIdCurrent( p, pObj ); + // evaluate delay of this output + LevelMax = 0; + assert( nBoxInputs == (int)pDelayTable[1] ); + for ( j = 0; j < nBoxInputs && (pObjIn = Gia_ManCo(p, curCo + j)); j++ ) + if ( (int)pDelayTable[3+k*nBoxInputs+j] != -ABC_INFINITY ) +// LevelMax = Abc_MaxInt( LevelMax, Gia_ObjLevel(p, pObjIn) + ((int)pDelayTable[3+k*nBoxInputs+j] / nAnd2Delay) ); + LevelMax = Abc_MaxInt( LevelMax, Gia_ObjLevel(p, pObjIn) + 1 ); + // set box output level + Gia_ObjSetLevel( p, pObj, LevelMax ); + } + curCo += nBoxInputs; + curCi += nBoxOutputs; + } + // add remaining nodes + p->nLevels = 0; + for ( i = Tim_ManCoNum(pManTime) - Tim_ManPoNum(pManTime); i < Tim_ManCoNum(pManTime); i++ ) + { + pObj = Gia_ManCo( p, i ); + Gia_ManLutLevelWithBoxes_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ObjSetCoLevel( p, pObj ); + p->nLevels = Abc_MaxInt( p->nLevels, Gia_ObjLevel(p, pObj) ); + } + curCo += Tim_ManPoNum(pManTime); + // verify counts + assert( curCi == Gia_ManCiNum(p) ); + assert( curCo == Gia_ManCoNum(p) ); +// printf( "Max level is %d.\n", p->nLevels ); + return p->nLevels; +} + +/**Function************************************************************* + + Synopsis [Update hierarchy/timing manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Gia_ManUpdateTimMan( Gia_Man_t * p, Vec_Int_t * vBoxPres ) +{ + Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; + assert( pManTime != NULL ); + assert( Vec_IntSize(vBoxPres) == Tim_ManBoxNum(pManTime) ); + return Tim_ManTrim( pManTime, vBoxPres ); +} +void * Gia_ManUpdateTimMan2( Gia_Man_t * p, Vec_Int_t * vBoxesLeft, int nTermsDiff ) +{ + Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; + assert( pManTime != NULL ); + assert( Vec_IntSize(vBoxesLeft) <= Tim_ManBoxNum(pManTime) ); + return Tim_ManReduce( pManTime, vBoxesLeft, nTermsDiff ); +} + +/**Function************************************************************* + + Synopsis [Update AIG of the holes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManUpdateExtraAig( void * pTime, Gia_Man_t * p, Vec_Int_t * vBoxPres ) +{ + Gia_Man_t * pNew; + Tim_Man_t * pManTime = (Tim_Man_t *)pTime; + Vec_Int_t * vOutPres = Vec_IntAlloc( 100 ); + int i, k, curPo = 0; + assert( Vec_IntSize(vBoxPres) == Tim_ManBoxNum(pManTime) ); + assert( Gia_ManCoNum(p) == Tim_ManCiNum(pManTime) - Tim_ManPiNum(pManTime) ); + for ( i = 0; i < Tim_ManBoxNum(pManTime); i++ ) + { + for ( k = 0; k < Tim_ManBoxOutputNum(pManTime, i); k++ ) + Vec_IntPush( vOutPres, Vec_IntEntry(vBoxPres, i) ); + curPo += Tim_ManBoxOutputNum(pManTime, i); + } + assert( curPo == Gia_ManCoNum(p) ); + pNew = Gia_ManDupOutputVec( p, vOutPres ); + Vec_IntFree( vOutPres ); + return pNew; +} +Gia_Man_t * Gia_ManUpdateExtraAig2( void * pTime, Gia_Man_t * p, Vec_Int_t * vBoxesLeft ) +{ + Gia_Man_t * pNew; + Tim_Man_t * pManTime = (Tim_Man_t *)pTime; + int nRealPis = Tim_ManPiNum(pManTime); + Vec_Int_t * vOutsLeft = Vec_IntAlloc( 100 ); + int i, k, iBox, iOutFirst; + assert( Vec_IntSize(vBoxesLeft) <= Tim_ManBoxNum(pManTime) ); + assert( Gia_ManCoNum(p) == Tim_ManCiNum(pManTime) - nRealPis ); + Vec_IntForEachEntry( vBoxesLeft, iBox, i ) + { + iOutFirst = Tim_ManBoxOutputFirst(pManTime, iBox) - nRealPis; + for ( k = 0; k < Tim_ManBoxOutputNum(pManTime, iBox); k++ ) + Vec_IntPush( vOutsLeft, iOutFirst + k ); + } + pNew = Gia_ManDupSelectedOutputs( p, vOutsLeft ); + Vec_IntFree( vOutsLeft ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates AIG while moving the last CIs to be after PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupMoveLast( Gia_Man_t * p, int iInsert, int nItems ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + int i; + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + if ( i < iInsert ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachCi( p, pObj, i ) + if ( i >= Gia_ManCiNum(p) - nItems ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachCi( p, pObj, i ) + if ( i >= iInsert && i < Gia_ManCiNum(p) - nItems ) + pObj->Value = Gia_ManAppendCi( pNew ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsCi(pObj) ) + continue; + if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + else assert( 0 ); + } + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Computes AIG with boxes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManDupCollapse_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Gia_Man_t * pNew ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + assert( Gia_ObjIsAnd(pObj) ); + if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) ) + Gia_ManDupCollapse_rec( p, Gia_ObjSiblObj(p, Gia_ObjId(p, pObj)), pNew ); + Gia_ManDupCollapse_rec( p, Gia_ObjFanin0(pObj), pNew ); + Gia_ManDupCollapse_rec( p, Gia_ObjFanin1(pObj), pNew ); +// assert( !~pObj->Value ); + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + if ( Gia_ObjSibl(p, Gia_ObjId(p, pObj)) ) + pNew->pSibls[Abc_Lit2Var(pObj->Value)] = Abc_Lit2Var(Gia_ObjSiblObj(p, Gia_ObjId(p, pObj))->Value); +} +Gia_Man_t * Gia_ManDupCollapse( Gia_Man_t * p, Gia_Man_t * pBoxes, Vec_Int_t * vBoxPres, int fSeq ) +{ + // this procedure assumes that sequential AIG with boxes is unshuffled to have valid boxes + Tim_Man_t * pManTime = (Tim_Man_t *)p->pManTime; + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pObjBox; + int i, k, curCi, curCo, nBBins = 0, nBBouts = 0, nNewPis = 0; + assert( !fSeq || p->vRegClasses ); + //assert( Gia_ManRegNum(p) == 0 ); + assert( Gia_ManCiNum(p) == Tim_ManPiNum(pManTime) + Gia_ManCoNum(pBoxes) ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + if ( Gia_ManHasChoices(p) ) + pNew->pSibls = ABC_CALLOC( int, Gia_ManObjNum(p) ); + Gia_ManHashAlloc( pNew ); + // copy const and real PIs + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManIncrementTravId( p ); + Gia_ObjSetTravIdCurrent( p, Gia_ManConst0(p) ); + for ( i = 0; i < Tim_ManPiNum(pManTime); i++ ) + { + pObj = Gia_ManCi( p, i ); + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ObjSetTravIdCurrent( p, pObj ); + } + // create logic for each box + curCi = Tim_ManPiNum(pManTime); + curCo = 0; + for ( i = 0; i < Tim_ManBoxNum(pManTime); i++ ) + { + // clean boxes + Gia_ManIncrementTravId( pBoxes ); + Gia_ObjSetTravIdCurrent( pBoxes, Gia_ManConst0(pBoxes) ); + Gia_ManConst0(pBoxes)->Value = 0; + // add internal nodes + //printf( "%d ", Tim_ManBoxIsBlack(pManTime, i) ); + if ( Tim_ManBoxIsBlack(pManTime, i) ) + { + int fSkip = (vBoxPres != NULL && !Vec_IntEntry(vBoxPres, i)); + for ( k = 0; k < Tim_ManBoxInputNum(pManTime, i); k++ ) + { + pObj = Gia_ManCo( p, curCo + k ); + Gia_ManDupCollapse_rec( p, Gia_ObjFanin0(pObj), pNew ); + pObj->Value = fSkip ? -1 : Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + nBBouts++; + } + for ( k = 0; k < Tim_ManBoxOutputNum(pManTime, i); k++ ) + { + pObj = Gia_ManCi( p, curCi + k ); + pObj->Value = fSkip ? 0 : Gia_ManAppendCi(pNew); + Gia_ObjSetTravIdCurrent( p, pObj ); + nBBins++; + nNewPis += !fSkip; + } + } + else + { + for ( k = 0; k < Tim_ManBoxInputNum(pManTime, i); k++ ) + { + // build logic + pObj = Gia_ManCo( p, curCo + k ); + Gia_ManDupCollapse_rec( p, Gia_ObjFanin0(pObj), pNew ); + // transfer to the PI + pObjBox = Gia_ManCi( pBoxes, k ); + pObjBox->Value = Gia_ObjFanin0Copy(pObj); + Gia_ObjSetTravIdCurrent( pBoxes, pObjBox ); + } + for ( k = 0; k < Tim_ManBoxOutputNum(pManTime, i); k++ ) + { + // build logic + pObjBox = Gia_ManCo( pBoxes, curCi - Tim_ManPiNum(pManTime) + k ); + Gia_ManDupCollapse_rec( pBoxes, Gia_ObjFanin0(pObjBox), pNew ); + // transfer to the PI + pObj = Gia_ManCi( p, curCi + k ); + pObj->Value = Gia_ObjFanin0Copy(pObjBox); + Gia_ObjSetTravIdCurrent( p, pObj ); + } + } + curCo += Tim_ManBoxInputNum(pManTime, i); + curCi += Tim_ManBoxOutputNum(pManTime, i); + } + //printf( "\n" ); + // add remaining nodes + for ( i = Tim_ManCoNum(pManTime) - Tim_ManPoNum(pManTime); i < Tim_ManCoNum(pManTime); i++ ) + { + pObj = Gia_ManCo( p, i ); + Gia_ManDupCollapse_rec( p, Gia_ObjFanin0(pObj), pNew ); + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + curCo += Tim_ManPoNum(pManTime); + // verify counts + assert( curCi == Gia_ManCiNum(p) ); + assert( curCo == Gia_ManCoNum(p) ); + Gia_ManSetRegNum( pNew, (fSeq && p->vRegClasses) ? Vec_IntSize(p->vRegClasses) : Gia_ManRegNum(p) ); + Gia_ManHashStop( pNew ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManCleanupRemap( p, pTemp ); + Gia_ManStop( pTemp ); + if ( nNewPis ) + { + pNew = Gia_ManDupMoveLast( pTemp = pNew, Tim_ManPiNum(pManTime)-Gia_ManRegNum(pNew), nNewPis ); + Gia_ManCleanupRemap( p, pTemp ); + Gia_ManStop( pTemp ); + } +/* + printf( "%d = %d - %d Diff = %d\n", + Tim_ManPoNum(pManTime), Gia_ManCoNum(pNew), nBBouts, + Tim_ManPoNum(pManTime) - (Gia_ManCoNum(pNew) - nBBouts) ); + + printf( "%d = %d - %d Diff = %d\n\n", + Tim_ManPiNum(pManTime), Gia_ManCiNum(pNew), nBBins, + Tim_ManPiNum(pManTime) - (Gia_ManCiNum(pNew) - nBBins) ); +*/ + assert( vBoxPres != NULL || Tim_ManPoNum(pManTime) == Gia_ManCoNum(pNew) - nBBouts ); + assert( vBoxPres != NULL || Tim_ManPiNum(pManTime) == Gia_ManCiNum(pNew) - nBBins ); + // implement initial state if given + if ( fSeq && p->vRegInits && Vec_IntSum(p->vRegInits) ) + { + char * pInit = ABC_ALLOC( char, Vec_IntSize(p->vRegInits) + 1 ); + Gia_Obj_t * pObj; + int i; + assert( Vec_IntSize(p->vRegInits) == Gia_ManRegNum(pNew) ); + Gia_ManForEachRo( pNew, pObj, i ) + { + if ( Vec_IntEntry(p->vRegInits, i) == 0 ) + pInit[i] = '0'; + else if ( Vec_IntEntry(p->vRegInits, i) == 1 ) + pInit[i] = '1'; + else + pInit[i] = 'X'; + } + pInit[i] = 0; + pNew = Gia_ManDupZeroUndc( pTemp = pNew, pInit, 0, 0, 1 ); + pNew->nConstrs = pTemp->nConstrs; pTemp->nConstrs = 0; + Gia_ManStop( pTemp ); + ABC_FREE( pInit ); + } + return pNew; +} + +/**Function************************************************************* + + Synopsis [Verify XAIG against its spec.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManVerifyWithBoxes( Gia_Man_t * pGia, int nBTLimit, int nTimeLim, int fSeq, int fDumpFiles, int fVerbose, char * pFileSpec ) +{ + int Status = -1; + Gia_Man_t * pSpec, * pGia0, * pGia1, * pMiter; + Vec_Int_t * vBoxPres = NULL; + if ( pFileSpec == NULL && pGia->pSpec == NULL ) + { + printf( "Spec file is not given. Use standard flow.\n" ); + return Status; + } + if ( Gia_ManBoxNum(pGia) && pGia->pAigExtra == NULL ) + { + printf( "Design has no box logic. Use standard flow.\n" ); + return Status; + } + // read original AIG + pSpec = Gia_AigerRead( pFileSpec ? pFileSpec : pGia->pSpec, 0, 0, 0 ); + if ( Gia_ManBoxNum(pSpec) && pSpec->pAigExtra == NULL ) + { + Gia_ManStop( pSpec ); + printf( "Spec has no box logic. Use standard flow.\n" ); + return Status; + } + // prepare miter + if ( pGia->pManTime == NULL && pSpec->pManTime == NULL ) + { + pGia0 = Gia_ManDup( pSpec ); + pGia1 = Gia_ManDup( pGia ); + } + else + { + // if timing managers have different number of black boxes, + // it is possible that some of the boxes are swept away + if ( pSpec->pManTime && Tim_ManBlackBoxNum((Tim_Man_t *)pSpec->pManTime) > 0 && Gia_ManBoxNum(pGia) > 0 ) + { + // specification cannot have fewer boxes than implementation + if ( Gia_ManBoxNum(pSpec) < Gia_ManBoxNum(pGia) ) + { + printf( "Spec has less boxes than the design. Cannot proceed.\n" ); + return Status; + } + // to align the boxes, find what boxes of pSpec are dropped in pGia + if ( Gia_ManBoxNum(pSpec) > Gia_ManBoxNum(pGia) ) + { + vBoxPres = Tim_ManAlignTwo( (Tim_Man_t *)pSpec->pManTime, (Tim_Man_t *)pGia->pManTime ); + if ( vBoxPres == NULL ) + { + printf( "Boxes of spec and design cannot be aligned. Cannot proceed.\n" ); + return Status; + } + } + } + // collapse two designs + if ( Gia_ManBoxNum(pSpec) > 0 ) + pGia0 = Gia_ManDupCollapse( pSpec, pSpec->pAigExtra, vBoxPres, fSeq ); + else + pGia0 = Gia_ManDup( pSpec ); + if ( Gia_ManBoxNum(pGia) > 0 ) + pGia1 = Gia_ManDupCollapse( pGia, pGia->pAigExtra, NULL, fSeq ); + else + pGia1 = Gia_ManDup( pGia ); + Vec_IntFreeP( &vBoxPres ); + } + if ( fDumpFiles ) + { + char pFileName0[1000], pFileName1[1000]; + char * pNameGeneric = Extra_FileNameGeneric( pFileSpec ? pFileSpec : pGia->pSpec ); + sprintf( pFileName0, "%s_spec.aig", pNameGeneric ); + sprintf( pFileName1, "%s_impl.aig", pNameGeneric ); + Gia_AigerWrite( pGia0, pFileName0, 0, 0, 0 ); + Gia_AigerWrite( pGia1, pFileName1, 0, 0, 0 ); + ABC_FREE( pNameGeneric ); + printf( "Dumped two parts of the miter into files \"%s\" and \"%s\".\n", pFileName0, pFileName1 ); + } + // compute the miter + if ( fSeq ) + { + pMiter = Gia_ManMiter( pGia0, pGia1, 0, 0, 1, 0, fVerbose ); + if ( pMiter ) + { + Aig_Man_t * pMan; + Fra_Sec_t SecPar, * pSecPar = &SecPar; + Fra_SecSetDefaultParams( pSecPar ); + pSecPar->fRetimeFirst = 0; + pSecPar->nBTLimit = nBTLimit; + pSecPar->TimeLimit = nTimeLim; + pSecPar->fVerbose = fVerbose; + pMan = Gia_ManToAig( pMiter, 0 ); + Gia_ManStop( pMiter ); + Status = Fra_FraigSec( pMan, pSecPar, NULL ); + Aig_ManStop( pMan ); + } + } + else + { + pMiter = Gia_ManMiter( pGia0, pGia1, 0, 1, 0, 0, fVerbose ); + if ( pMiter ) + { + Cec_ParCec_t ParsCec, * pPars = &ParsCec; + Cec_ManCecSetDefaultParams( pPars ); + pPars->nBTLimit = nBTLimit; + pPars->TimeLimit = nTimeLim; + pPars->fVerbose = fVerbose; + Status = Cec_ManVerify( pMiter, pPars ); + if ( pPars->iOutFail >= 0 ) + Abc_Print( 1, "Verification failed for at least one output (%d).\n", pPars->iOutFail ); + Gia_ManStop( pMiter ); + } + } + Gia_ManStop( pGia0 ); + Gia_ManStop( pGia1 ); + Gia_ManStop( pSpec ); + return Status; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaTis.c b/yosys/abc/src/aig/gia/giaTis.c new file mode 100644 index 00000000000..750b52c8489 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaTis.c @@ -0,0 +1,213 @@ +/**CFile**************************************************************** + + FileName [giaTis.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Technology independent synthesis.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaTis.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives GIA with MUXes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManTisDupMuxes( Gia_Man_t * p ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pFan0, * pFan1, * pFanC; + int i; + assert( p->pMuxes == NULL ); + ABC_FREE( p->pRefs ); + Gia_ManCreateRefs( p ); + // start the new manager + pNew = Gia_ManStart( 5000 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->pMuxes = ABC_CALLOC( unsigned, pNew->nObjsAlloc ); + // create constant + Gia_ManConst0(p)->Value = 0; + // create PIs + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi( pNew ); + // create internal nodes + Gia_ManHashStart( pNew ); + Gia_ManForEachAnd( p, pObj, i ) + { + if ( !Gia_ObjIsMuxType(pObj) || (Gia_ObjRefNum(p, Gia_ObjFanin0(pObj)) > 1 && Gia_ObjRefNum(p, Gia_ObjFanin1(pObj)) > 1) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjRecognizeExor(pObj, &pFan0, &pFan1) ) + pObj->Value = Gia_ManHashXorReal( pNew, Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan0)), Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan1)) ); + else + { + pFanC = Gia_ObjRecognizeMux( pObj, &pFan1, &pFan0 ); + pObj->Value = Gia_ManHashMuxReal( pNew, Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFanC)), Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan1)), Gia_ObjLitCopy(p, Gia_ObjToLit(p, pFan0)) ); + } + } + Gia_ManHashStop( pNew ); + // create ROs + Gia_ManForEachCo( p, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + // perform cleanup + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManTisCollectMffc_rec( Gia_Man_t * p, int Id, Vec_Int_t * vMffc, Vec_Int_t * vLeaves ) +{ + Gia_Obj_t * pObj; + if ( Gia_ObjIsTravIdCurrentId(p, Id) ) + return; + Gia_ObjSetTravIdCurrentId(p, Id); + if ( Gia_ObjRefNumId(p, Id) > 1 ) + { + Vec_IntPush( vLeaves, Id ); + return; + } + pObj = Gia_ManObj( p, Id ); + if ( Gia_ObjIsCi(pObj) ) + { + Vec_IntPush( vLeaves, Id ); + return; + } + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManTisCollectMffc_rec( p, Gia_ObjFaninId0(pObj, Id), vMffc, vLeaves ); + Gia_ManTisCollectMffc_rec( p, Gia_ObjFaninId1(pObj, Id), vMffc, vLeaves ); + if ( Gia_ObjIsMuxId(p, Id) ) + Gia_ManTisCollectMffc_rec( p, Gia_ObjFaninId2(p, Id), vMffc, vLeaves ); + Vec_IntPush( vMffc, Id ); +} +void Gia_ManTisCollectMffc( Gia_Man_t * p, int Id, Vec_Int_t * vMffc, Vec_Int_t * vLeaves ) +{ + Gia_Obj_t * pObj = Gia_ManObj( p, Id ); + assert( Gia_ObjIsAnd(pObj) ); + Vec_IntClear( vMffc ); + Vec_IntClear( vLeaves ); + Gia_ManIncrementTravId( p ); + Gia_ManTisCollectMffc_rec( p, Gia_ObjFaninId0(pObj, Id), vMffc, vLeaves ); + Gia_ManTisCollectMffc_rec( p, Gia_ObjFaninId1(pObj, Id), vMffc, vLeaves ); + if ( Gia_ObjIsMuxId(p, Id) ) + Gia_ManTisCollectMffc_rec( p, Gia_ObjFaninId2(p, Id), vMffc, vLeaves ); + Vec_IntPush( vMffc, Id ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManTisPrintMffc( Gia_Man_t * p, int Id, Vec_Int_t * vMffc, Vec_Int_t * vLeaves ) +{ + Gia_Obj_t * pObj; + int i; + printf( "MFFC %d has %d nodes and %d leaves:\n", Id, Vec_IntSize(vMffc), Vec_IntSize(vLeaves) ); + Gia_ManForEachObjVecReverse( vMffc, p, pObj, i ) + { + printf( "Node %2d : ", Vec_IntSize(vMffc) - 1 - i ); + Gia_ObjPrint( p, pObj ); + } + Gia_ManForEachObjVec( vLeaves, p, pObj, i ) + { + printf( "Leaf %2d : ", i ); + Gia_ObjPrint( p, pObj ); + } + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManTisTest( Gia_Man_t * pInit ) +{ + Gia_Man_t * p; + Gia_Obj_t * pObj; + Vec_Int_t * vMffc, * vLeaves; + int i; + vMffc = Vec_IntAlloc( 10 ); + vLeaves = Vec_IntAlloc( 10 ); + p = Gia_ManTisDupMuxes( pInit ); + Gia_ManCreateRefs( p ); + Gia_ManForEachAnd( p, pObj, i ) + { + if ( Gia_ObjRefNumId(p, i) == 1 ) + continue; + Gia_ManTisCollectMffc( p, i, vMffc, vLeaves ); + Gia_ManTisPrintMffc( p, i, vMffc, vLeaves ); + } + Gia_ManForEachCo( p, pObj, i ) + { + if ( Gia_ObjRefNumId(p, Gia_ObjFaninId0p(p, pObj)) > 1 ) + continue; + Gia_ManTisCollectMffc( p, Gia_ObjFaninId0p(p, pObj), vMffc, vLeaves ); + Gia_ManTisPrintMffc( p, Gia_ObjFaninId0p(p, pObj), vMffc, vLeaves ); + } + Gia_ManStop( p ); + Vec_IntFree( vMffc ); + Vec_IntFree( vLeaves ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaTranStoch.c b/yosys/abc/src/aig/gia/giaTranStoch.c new file mode 100644 index 00000000000..f7b300c0d06 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaTranStoch.c @@ -0,0 +1,433 @@ +/**CFile**************************************************************** + + FileName [giaTranStoch.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Implementation of transduction method.] + + Author [Yukio Miyasaka] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 2023.] + + Revision [$Id: giaTranStoch.c,v 1.00 2023/05/10 00:00:00 Exp $] + +***********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#define unlink _unlink +#else +#include +#endif + +#ifdef ABC_USE_PTHREADS + +#ifdef _WIN32 +#include "../lib/pthread.h" +#else +#include +#endif + +#endif + +ABC_NAMESPACE_IMPL_START + +extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); +extern Abc_Ntk_t * Abc_NtkIf( Abc_Ntk_t * pNtk, If_Par_t * pPars ); +extern int Abc_NtkPerformMfs( Abc_Ntk_t * pNtk, Sfm_Par_t * pPars ); +extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); +extern int Abc_NtkFxPerform( Abc_Ntk_t * pNtk, int nNewNodesMax, int nLitCountMax, int fCanonDivs, int fVerbose, int fVeryVerbose ); + +Abc_Ntk_t * Gia_ManTranStochPut( Gia_Man_t * pGia ) { + Abc_Ntk_t * pNtk; + Aig_Man_t * pMan = Gia_ManToAig( pGia, 0 ); + pNtk = Abc_NtkFromAigPhase( pMan ); + Aig_ManStop( pMan ); + return pNtk; +} +Abc_Ntk_t * Gia_ManTranStochIf( Abc_Ntk_t * pNtk ) { + If_Par_t Pars, * pPars = &Pars; + If_ManSetDefaultPars( pPars ); + pPars->pLutLib = (If_LibLut_t *)Abc_FrameReadLibLut(); + pPars->nLutSize = pPars->pLutLib->LutMax; + return Abc_NtkIf( pNtk, pPars ); +} +void Gia_ManTranStochMfs2( Abc_Ntk_t * pNtk ) { + Sfm_Par_t Pars, * pPars = &Pars; + Sfm_ParSetDefault( pPars ); + Abc_NtkPerformMfs( pNtk, pPars ); +} +Gia_Man_t * Gia_ManTranStochGet( Abc_Ntk_t * pNtk ) { + Gia_Man_t * pGia; + Aig_Man_t * pAig = Abc_NtkToDar( pNtk, 0, 1 ); + pGia = Gia_ManFromAig( pAig ); + Aig_ManStop( pAig ); + return pGia; +} +void Gia_ManTranStochFx( Abc_Ntk_t * pNtk ) { + Fxu_Data_t Params, * p = &Params; + Abc_NtkSetDefaultFxParams( p ); + Abc_NtkFxPerform( pNtk, p->nNodesExt, p->LitCountMax, p->fCanonDivs, p->fVerbose, p->fVeryVerbose ); + Abc_NtkFxuFreeInfo( p ); +} +Gia_Man_t * Gia_ManTranStochRefactor( Gia_Man_t * pGia ) { + Gia_Man_t * pNew; + Aig_Man_t * pAig, * pTemp; + Dar_RefPar_t Pars, * pPars = &Pars; + Dar_ManDefaultRefParams( pPars ); + pPars->fUseZeros = 1; + pAig = Gia_ManToAig( pGia, 0 ); + Dar_ManRefactor( pAig, pPars ); + pAig = Aig_ManDupDfs( pTemp = pAig ); + Aig_ManStop( pTemp ); + pNew = Gia_ManFromAig( pAig ); + Aig_ManStop( pAig ); + return pNew; +} + +struct Gia_ManTranStochParam { + Gia_Man_t * pStart; + int nSeed; + int nHops; + int nRestarts; + int nSeedBase; + int fMspf; + int fMerge; + int fResetHop; + int fZeroCostHop; + int fRefactor; + int fTruth; + int fNewLine; + Gia_Man_t * pExdc; + int nVerbose; + +#ifdef ABC_USE_PTHREADS + int nSp; + int nIte; + Gia_Man_t * pRes; + int fWorking; + pthread_mutex_t * mutex; +#endif +}; + +typedef struct Gia_ManTranStochParam Gia_ManTranStochParam; + +void Gia_ManTranStochLock( Gia_ManTranStochParam * p ) { +#ifdef ABC_USE_PTHREADS + if ( p->fWorking ) + pthread_mutex_lock( p->mutex ); +#endif +} +void Gia_ManTranStochUnlock( Gia_ManTranStochParam * p ) { +#ifdef ABC_USE_PTHREADS + if ( p->fWorking ) + pthread_mutex_unlock( p->mutex ); +#endif +} + +Gia_Man_t * Gia_ManTranStochOpt1( Gia_ManTranStochParam * p, Gia_Man_t * pOld ) { + Gia_Man_t * pGia, * pNew; + int i = 0, n; + pGia = Gia_ManDup( pOld ); + do { + n = Gia_ManAndNum( pGia ); + if ( p->fTruth ) + pNew = Gia_ManTransductionTt( pGia, (p->fMerge? 8: 7), p->fMspf, p->nSeed++, 0, 0, 0, 0, p->pExdc, p->fNewLine, p->nVerbose > 0? p->nVerbose - 1: 0 ); + else + pNew = Gia_ManTransductionBdd( pGia, (p->fMerge? 8: 7), p->fMspf, p->nSeed++, 0, 0, 0, 0, p->pExdc, p->fNewLine, p->nVerbose > 0? p->nVerbose - 1: 0 ); + Gia_ManStop( pGia ); + pGia = pNew; + if ( p->fRefactor ) { + pNew = Gia_ManTranStochRefactor( pGia ); + Gia_ManStop( pGia ); + pGia = pNew; + } else { + Gia_ManTranStochLock( p ); + pNew = Gia_ManCompress2( pGia, 1, 0 ); + Gia_ManTranStochUnlock( p ); + Gia_ManStop( pGia ); + pGia = pNew; + } + if ( p->nVerbose ) + printf( "* ite %d : #nodes = %5d\n", i, Gia_ManAndNum( pGia ) ); + i++; + } while ( n > Gia_ManAndNum( pGia ) ); + return pGia; +} + +Gia_Man_t * Gia_ManTranStochOpt2( Gia_ManTranStochParam * p ) { + int i, n = Gia_ManAndNum( p->pStart ); + Gia_Man_t * pGia, * pBest, * pNew; + Abc_Ntk_t * pNtk, * pNtkRes; + pGia = Gia_ManDup( p->pStart ); + pBest = Gia_ManDup( pGia ); + for ( i = 0; 1; i++ ) { + pNew = Gia_ManTranStochOpt1( p, pGia ); + Gia_ManStop( pGia ); + pGia = pNew; + if ( n > Gia_ManAndNum( pGia ) ) { + n = Gia_ManAndNum( pGia ); + Gia_ManStop( pBest ); + pBest = Gia_ManDup( pGia ); + if ( p->fResetHop ) + i = 0; + } + if ( i == p->nHops ) + break; + if ( p->fZeroCostHop ) { + pNew = Gia_ManTranStochRefactor( pGia ); + Gia_ManStop( pGia ); + pGia = pNew; + } else { + Gia_ManTranStochLock( p ); + pNtk = Gia_ManTranStochPut( pGia ); + Gia_ManTranStochUnlock( p ); + Gia_ManStop( pGia ); + pNtkRes = Gia_ManTranStochIf( pNtk ); + Abc_NtkDelete( pNtk ); + pNtk = pNtkRes; + Gia_ManTranStochMfs2( pNtk ); + Gia_ManTranStochLock( p ); + pNtkRes = Abc_NtkStrash( pNtk, 0, 1, 0 ); + Gia_ManTranStochUnlock( p ); + Abc_NtkDelete( pNtk ); + pNtk = pNtkRes; + pGia = Gia_ManTranStochGet( pNtk ); + Abc_NtkDelete( pNtk ); + } + if ( p->nVerbose ) + printf( "* hop %d : #nodes = %5d\n", i, Gia_ManAndNum( pGia ) ); + } + Gia_ManStop( pGia ); + return pBest; +} + +Gia_Man_t * Gia_ManTranStochOpt3( Gia_ManTranStochParam * p ) { + int i, n = Gia_ManAndNum( p->pStart ); + Gia_Man_t * pBest, * pNew; + pBest = Gia_ManDup( p->pStart ); + for ( i = 0; i <= p->nRestarts; i++ ) { + p->nSeed = 1234 * (i + p->nSeedBase); + pNew = Gia_ManTranStochOpt2( p ); + if ( p->nRestarts && p->nVerbose ) + printf( "* res %2d : #nodes = %5d\n", i, Gia_ManAndNum( pNew ) ); + if ( n > Gia_ManAndNum( pNew ) ) { + n = Gia_ManAndNum( pNew ); + Gia_ManStop( pBest ); + pBest = pNew; + } else { + Gia_ManStop( pNew ); + } + } + return pBest; +} + +#ifdef ABC_USE_PTHREADS +void * Gia_ManTranStochWorkerThread( void * pArg ) { + Gia_ManTranStochParam * p = (Gia_ManTranStochParam *)pArg; + volatile int * pPlace = &p->fWorking; + while ( 1 ) { + while ( *pPlace == 0 ); + assert( p->fWorking ); + if ( p->pStart == NULL ) { + pthread_exit( NULL ); + assert( 0 ); + return NULL; + } + p->nSeed = 1234 * (p->nIte + p->nSeedBase); + p->pRes = Gia_ManTranStochOpt2( p ); + p->fWorking = 0; + } + assert( 0 ); + return NULL; +} +#endif + +Gia_Man_t * Gia_ManTranStoch( Gia_Man_t * pGia, int nRestarts, int nHops, int nSeedBase, int fMspf, int fMerge, int fResetHop, int fZeroCostHop, int fRefactor, int fTruth, int fSingle, int fOriginalOnly, int fNewLine, Gia_Man_t * pExdc, int nThreads, int nVerbose ) { + int i, j = 0; + Gia_Man_t * pNew, * pBest, * pStart; + Abc_Ntk_t * pNtk, * pNtkRes; Vec_Ptr_t * vpStarts; + Gia_ManTranStochParam Par, *p = &Par; + p->nRestarts = nRestarts; + p->nHops = nHops; + p->nSeedBase = nSeedBase; + p->fMspf = fMspf; + p->fMerge = fMerge; + p->fResetHop = fResetHop; + p->fZeroCostHop = fZeroCostHop; + p->fRefactor = fRefactor; + p->fTruth = fTruth; + p->fNewLine = fNewLine; + p->pExdc = pExdc; + p->nVerbose = nVerbose; +#ifdef ABC_USE_PTHREADS + p->fWorking = 0; +#endif + // setup start points + vpStarts = Vec_PtrAlloc( 4 ); + Vec_PtrPush( vpStarts, Gia_ManDup( pGia ) ); + if ( !fOriginalOnly ) { + { // &put; collapse; st; &get; + pNtk = Gia_ManTranStochPut( pGia ); + pNtkRes = Abc_NtkCollapse( pNtk, ABC_INFINITY, 0, 1, 0, 0, 0 ); + Abc_NtkDelete( pNtk ); + pNtk = pNtkRes; + pNtkRes = Abc_NtkStrash( pNtk, 0, 1, 0 ); + Abc_NtkDelete( pNtk ); + pNtk = pNtkRes; + pNew = Gia_ManTranStochGet( pNtk ); + Abc_NtkDelete( pNtk ); + Vec_PtrPush( vpStarts, pNew ); + } + { // &ttopt; + pNew = Gia_ManTtopt( pGia, Gia_ManCiNum( pGia ), Gia_ManCoNum( pGia ), 100 ); + Vec_PtrPush( vpStarts, pNew ); + } + { // &put; collapse; sop; fx; + pNtk = Gia_ManTranStochPut( pGia ); + pNtkRes = Abc_NtkCollapse( pNtk, ABC_INFINITY, 0, 1, 0, 0, 0 ); + Abc_NtkDelete( pNtk ); + pNtk = pNtkRes; + Abc_NtkToSop( pNtk, -1, ABC_INFINITY ); + Gia_ManTranStochFx( pNtk ); + pNtkRes = Abc_NtkStrash( pNtk, 0, 1, 0 ); + Abc_NtkDelete( pNtk ); + pNtk = pNtkRes; + pNew = Gia_ManTranStochGet( pNtk ); + Abc_NtkDelete( pNtk ); + Vec_PtrPush( vpStarts, pNew ); + } + } + if ( fSingle ) { + pBest = (Gia_Man_t *)Vec_PtrEntry( vpStarts, 0 ); + for ( i = 1; i < Vec_PtrSize( vpStarts ); i++ ) { + pStart = (Gia_Man_t *)Vec_PtrEntry( vpStarts, i ); + if ( Gia_ManAndNum( pStart ) < Gia_ManAndNum( pBest ) ) { + Gia_ManStop( pBest ); + pBest = pStart; + j = i; + } else { + Gia_ManStop( pStart ); + } + } + Vec_PtrClear( vpStarts ); + Vec_PtrPush( vpStarts, pBest ); + } + // optimize + pBest = Gia_ManDup( pGia ); + if ( nThreads == 1 ) { + Vec_PtrForEachEntry( Gia_Man_t *, vpStarts, pStart, i ) { + if ( p->nVerbose ) + printf( "*begin starting point %d: #nodes = %5d\n", i + j, Gia_ManAndNum( pStart ) ); + p->pStart = pStart; + pNew = Gia_ManTranStochOpt3( p ); + if ( p->nVerbose ) + printf( "*end starting point %d: #nodes = %5d\n", i + j, Gia_ManAndNum( pNew ) ); + if ( Gia_ManAndNum( pBest ) > Gia_ManAndNum( pNew ) ) { + Gia_ManStop( pBest ); + pBest = pNew; + } else { + Gia_ManStop( pNew ); + } + Gia_ManStop( pStart ); + } + } else { +#ifdef ABC_USE_PTHREADS + static pthread_mutex_t mutex; + int k, status, nIte, fAssigned, fWorking; + Gia_ManTranStochParam ThData[100]; + pthread_t WorkerThread[100]; + p->pRes = NULL; + p->mutex = &mutex; + if ( p->nVerbose ) + p->nVerbose--; + for ( i = 0; i < nThreads; i++ ) { + ThData[i] = *p; + status = pthread_create( WorkerThread + i, NULL, Gia_ManTranStochWorkerThread, (void *)(ThData + i) ); + assert( status == 0 ); + } + Vec_PtrForEachEntry( Gia_Man_t *, vpStarts, pStart, k ) { + for ( nIte = 0; nIte <= p->nRestarts; nIte++ ) { + fAssigned = 0; + while ( !fAssigned ) { + for ( i = 0; i < nThreads; i++ ) { + if ( ThData[i].fWorking ) + continue; + if ( ThData[i].pRes != NULL ) { + if( nVerbose ) + printf( "*sp %d res %4d : #nodes = %5d\n", ThData[i].nSp, ThData[i].nIte, Gia_ManAndNum( ThData[i].pRes ) ); + if ( Gia_ManAndNum( pBest ) > Gia_ManAndNum( ThData[i].pRes ) ) { + Gia_ManStop( pBest ); + pBest = ThData[i].pRes; + } else { + Gia_ManStop( ThData[i].pRes ); + } + ThData[i].pRes = NULL; + } + ThData[i].nSp = j + k; + ThData[i].nIte = nIte; + ThData[i].pStart = pStart; + ThData[i].fWorking = 1; + fAssigned = 1; + break; + } + } + } + } + fWorking = 1; + while ( fWorking ) { + fWorking = 0; + for ( i = 0; i < nThreads; i++ ) { + if( ThData[i].fWorking ) { + fWorking = 1; + continue; + } + if ( ThData[i].pRes != NULL ) { + if( nVerbose ) + printf( "*sp %d res %4d : #nodes = %5d\n", ThData[i].nSp, ThData[i].nIte, Gia_ManAndNum( ThData[i].pRes ) ); + if ( Gia_ManAndNum( pBest ) > Gia_ManAndNum( ThData[i].pRes ) ) { + Gia_ManStop( pBest ); + pBest = ThData[i].pRes; + } else { + Gia_ManStop( ThData[i].pRes ); + } + ThData[i].pRes = NULL; + } + } + } + for ( i = 0; i < nThreads; i++ ) { + ThData[i].pStart = NULL; + ThData[i].fWorking = 1; + } +#else + printf( "ERROR: pthread is off" ); +#endif + Vec_PtrForEachEntry( Gia_Man_t *, vpStarts, pStart, i ) + Gia_ManStop( pStart ); + } + if ( nVerbose ) + printf( "best: %d\n", Gia_ManAndNum( pBest ) ); + Vec_PtrFree( vpStarts ); + ABC_FREE( pBest->pName ); + ABC_FREE( pBest->pSpec ); + pBest->pName = Abc_UtilStrsav( pGia->pName ); + pBest->pSpec = Abc_UtilStrsav( pGia->pSpec ); + return pBest; +} + +ABC_NAMESPACE_IMPL_END diff --git a/yosys/abc/src/aig/gia/giaTransduction.cpp b/yosys/abc/src/aig/gia/giaTransduction.cpp new file mode 100644 index 00000000000..f9220210f28 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaTransduction.cpp @@ -0,0 +1,166 @@ +/**CFile**************************************************************** + + FileName [giaTransduction.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Implementation of transduction method.] + + Author [Yukio Miyasaka] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 2023.] + + Revision [$Id: giaTransduction.c,v 1.00 2023/05/10 00:00:00 Exp $] + +***********************************************************************/ + +#ifndef _WIN32 + +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma warning(disable : 4786) // warning C4786: identifier was truncated to '255' characters in the browser information +#endif +#endif + +#include "giaTransduction.h" +#include "giaNewBdd.h" +#include "giaNewTt.h" + +ABC_NAMESPACE_IMPL_START + +Gia_Man_t *Gia_ManTransductionBdd(Gia_Man_t *pGia, int nType, int fMspf, int nRandom, int nSortType, int nPiShuffle, int nParameter, int fLevel, Gia_Man_t *pExdc, int fNewLine, int nVerbose) { + if(nRandom) { + srand(nRandom); + nSortType = rand() % 4; + nPiShuffle = rand(); + nParameter = rand() % 16; + } + NewBdd::Param p; + Transduction::Transduction t(pGia, nVerbose, fNewLine, nSortType, nPiShuffle, fLevel, pExdc, p); + int count = t.CountWires(); + switch(nType) { + case 0: + count -= fMspf? t.Mspf(): t.Cspf(); + break; + case 1: + count -= t.Resub(fMspf); + break; + case 2: + count -= t.ResubMono(fMspf); + break; + case 3: + count -= t.ResubShared(fMspf); + break; + case 4: + count -= t.RepeatResub(false, fMspf); + break; + case 5: + count -= t.RepeatResub(true, fMspf); + break; + case 6: { + bool fInner = (nParameter / 4) % 2; + count -= t.RepeatInner(fMspf, fInner); + break; + } + case 7: { + bool fInner = (nParameter / 4) % 2; + bool fOuter = (nParameter / 8) % 2; + count -= t.RepeatOuter(fMspf, fInner, fOuter); + break; + } + case 8: { + bool fFirstMerge = nParameter % 2; + bool fMspfMerge = fMspf? (nParameter / 2) % 2: false; + bool fInner = (nParameter / 4) % 2; + bool fOuter = (nParameter / 8) % 2; + count -= t.RepeatAll(fFirstMerge, fMspfMerge, fMspf, fInner, fOuter); + break; + } + default: + std::cout << "Unknown transduction type " << nType << std::endl; + } + assert(t.Verify()); + assert(count == t.CountWires()); + return t.GenerateAig(); +} + +Gia_Man_t *Gia_ManTransductionTt(Gia_Man_t *pGia, int nType, int fMspf, int nRandom, int nSortType, int nPiShuffle, int nParameter, int fLevel, Gia_Man_t *pExdc, int fNewLine, int nVerbose) { + if(nRandom) { + srand(nRandom); + nSortType = rand() % 4; + nPiShuffle = rand(); + nParameter = rand() % 16; + } + NewTt::Param p; + Transduction::Transduction t(pGia, nVerbose, fNewLine, nSortType, nPiShuffle, fLevel, pExdc, p); + int count = t.CountWires(); + switch(nType) { + case 0: + count -= fMspf? t.Mspf(): t.Cspf(); + break; + case 1: + count -= t.Resub(fMspf); + break; + case 2: + count -= t.ResubMono(fMspf); + break; + case 3: + count -= t.ResubShared(fMspf); + break; + case 4: + count -= t.RepeatResub(false, fMspf); + break; + case 5: + count -= t.RepeatResub(true, fMspf); + break; + case 6: { + bool fInner = (nParameter / 4) % 2; + count -= t.RepeatInner(fMspf, fInner); + break; + } + case 7: { + bool fInner = (nParameter / 4) % 2; + bool fOuter = (nParameter / 8) % 2; + count -= t.RepeatOuter(fMspf, fInner, fOuter); + break; + } + case 8: { + bool fFirstMerge = nParameter % 2; + bool fMspfMerge = fMspf? (nParameter / 2) % 2: false; + bool fInner = (nParameter / 4) % 2; + bool fOuter = (nParameter / 8) % 2; + count -= t.RepeatAll(fFirstMerge, fMspfMerge, fMspf, fInner, fOuter); + break; + } + default: + std::cout << "Unknown transduction type " << nType << std::endl; + } + assert(t.Verify()); + assert(count == t.CountWires()); + return t.GenerateAig(); +} + +ABC_NAMESPACE_IMPL_END + +#else + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + +Gia_Man_t * Gia_ManTransductionBdd(Gia_Man_t *pGia, int nType, int fMspf, int nRandom, int nSortType, int nPiShuffle, int nParameter, int fLevel, Gia_Man_t *pExdc, int fNewLine, int nVerbose) +{ + return NULL; +} +Gia_Man_t * Gia_ManTransductionTt(Gia_Man_t *pGia, int nType, int fMspf, int nRandom, int nSortType, int nPiShuffle, int nParameter, int fLevel, Gia_Man_t *pExdc, int fNewLine, int nVerbose) +{ + return NULL; +} + +ABC_NAMESPACE_IMPL_END + +#endif diff --git a/yosys/abc/src/aig/gia/giaTransduction.h b/yosys/abc/src/aig/gia/giaTransduction.h new file mode 100644 index 00000000000..6dd081e15dc --- /dev/null +++ b/yosys/abc/src/aig/gia/giaTransduction.h @@ -0,0 +1,1768 @@ +/**CFile**************************************************************** + + FileName [giaTransduction.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Implementation of transduction method.] + + Author [Yukio Miyasaka] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 2023.] + + Revision [$Id: giaTransduction.h,v 1.00 2023/05/10 00:00:00 Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__gia__giaTransduction_h +#define ABC__aig__gia__giaTransduction_h + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gia.h" + +ABC_NAMESPACE_CXX_HEADER_START + +namespace Transduction { + +enum PfState {none, cspf, mspf}; + +template +class ManUtil { +protected: + Man *man; + inline void IncRef(lit x) const { + if(x != LitMax) + man->IncRef(x); + } + inline void DecRef(lit x) const { + if(x != LitMax) + man->DecRef(x); + } + inline void Update(lit &x, lit y) const { + DecRef(x); + x = y; + IncRef(x); + } + inline void DelVec(std::vector &v) const { + for(unsigned i = 0; i < v.size(); i++) + DecRef(v[i]); + v.clear(); + } + inline void DelVec(std::vector > &v) const { + for(unsigned i = 0; i < v.size(); i++) + DelVec(v[i]); + v.clear(); + } + inline void CopyVec(std::vector &v, std::vector const &u) const { + DelVec(v); + v = u; + for(unsigned i = 0; i < v.size(); i++) + IncRef(v[i]); + } + inline void CopyVec(std::vector > &v, std::vector > const &u) const { + for(unsigned i = u.size(); i < v.size(); i++) + DelVec(v[i]); + v.resize(u.size()); + for(unsigned i = 0; i < v.size(); i++) + CopyVec(v[i], u[i]); + } + inline bool LitVecIsEq(std::vector const &v, std::vector const &u) const { + if(v.size() != u.size()) + return false; + for(unsigned i = 0; i < v.size(); i++) + if(!man->LitIsEq(v[i], u[i])) + return false; + return true; + } + inline bool LitVecIsEq(std::vector > const &v, std::vector > const &u) const { + if(v.size() != u.size()) + return false; + for(unsigned i = 0; i < v.size(); i++) + if(!LitVecIsEq(v[i], u[i])) + return false; + return true; + } + inline lit Xor(lit x, lit y) const { + lit f = man->And(x, man->LitNot(y)); + man->IncRef(f); + lit g = man->And(man->LitNot(x), y); + man->IncRef(g); + lit r = man->Or(f, g); + man->DecRef(f); + man->DecRef(g); + return r; + } +}; + +template +class TransductionBackup: ManUtil { +private: + int nObjsAlloc; + PfState state; + std::list vObjs; + std::vector > vvFis; + std::vector > vvFos; + std::vector vLevels; + std::vector vSlacks; + std::vector > vvFiSlacks; + std::vector vFs; + std::vector vGs; + std::vector > vvCs; + std::vector vUpdates; + std::vector vPfUpdates; + std::vector vFoConeShared; + template + friend class Transduction; + +public: + ~TransductionBackup() { + if(this->man) { + this->DelVec(vFs); + this->DelVec(vGs); + this->DelVec(vvCs); + } + } +}; + +template +class Transduction: ManUtil { +private: + int nVerbose; + int nSortType; + bool fLevel; + int nObjsAlloc; + int nMaxLevels; + PfState state; + std::vector vPis; + std::vector vPos; + std::list vObjs; + std::vector > vvFis; + std::vector > vvFos; + std::vector vLevels; + std::vector vSlacks; + std::vector > vvFiSlacks; + std::vector vFs; + std::vector vGs; + std::vector > vvCs; + std::vector vUpdates; + std::vector vPfUpdates; + std::vector vFoConeShared; + std::vector vPoFs; + + bool fNewLine; + abctime startclk; + +private: // Helper functions + inline bool AllFalse(std::vector const &v) const { + for(std::list::const_iterator it = vObjs.begin(); it != vObjs.end(); it++) + if(v[*it]) + return false; + return true; + } + +public: // Counting + inline int CountGates() const { + return vObjs.size(); + } + inline int CountWires() const { + int count = 0; + for(std::list::const_iterator it = vObjs.begin(); it != vObjs.end(); it++) + count += vvFis[*it].size(); + return count; + } + inline int CountNodes() const { + return CountWires() - CountGates(); + } + inline int CountLevels() const { + int count = 0; + for(unsigned i = 0; i < vPos.size(); i++) + count = std::max(count, vLevels[vvFis[vPos[i]][0] >> 1]); + return count; + } + inline void Print(std::string str, bool nl) const { + if(!fNewLine) + std::cout << "\33[2K\r"; + std::cout << str; + if(fNewLine || nl) + std::cout << std::endl; + else + std::cout << std::flush; + } + inline void PrintStats(std::string prefix, bool nl, int prefix_size = 0) const { + if(!prefix_size) + prefix_size = prefix.size(); + std::stringstream ss; + ss << std::left << std::setw(prefix_size) << prefix << ": " << std::right; + ss << "#nodes = " << std::setw(5) << CountNodes(); + if(fLevel) + ss << ", #level = " << std::setw(5) << CountLevels(); + ss << ", elapsed = " << std::setprecision(2) << std::fixed << std::setw(8) << 1.0 * (Abc_Clock() - startclk) / CLOCKS_PER_SEC << "s"; + Print(ss.str(), nl); + } + inline void PrintPfHeader(std::string prefix, int block, int block_i0) { + std::stringstream ss; + ss << "\t\t" << prefix; + if(block_i0 != -1) + ss << " (blocking Wire " << block_i0 << " -> " << block << ")"; + else if(block != -1) + ss << " (blocking Gate " << block << ")"; + Print(ss.str(), true); + } + +private: // MIAIG + void SortObjs_rec(std::list::iterator const &it) { + for(unsigned j = 0; j < vvFis[*it].size(); j++) { + int i0 = vvFis[*it][j] >> 1; + if(!vvFis[i0].empty()) { + std::list::iterator it_i0 = std::find(it, vObjs.end(), i0); + if(it_i0 != vObjs.end()) { + // if(nVerbose > 6) + // std::cout << "\t\t\t\t\t\tMove " << i0 << " before " << *it << std::endl; + vObjs.erase(it_i0); + it_i0 = vObjs.insert(it, i0); + SortObjs_rec(it_i0); + } + } + } + } + inline void Connect(int i, int f, bool fSort = false, bool fUpdate = true, lit c = LitMax) { + int i0 = f >> 1; + if(nVerbose > 5) { + std::stringstream ss; + ss << "\t\t\t\t\tadd Wire " << std::setw(5) << i0 << "(" << (f & 1) << ")" + << " -> " << std::setw(5) << i; + Print(ss.str(), true); + } + assert(std::find(vvFis[i].begin(), vvFis[i].end(), f) == vvFis[i].end()); + vvFis[i].push_back(f); + vvFos[i0].push_back(i); + if(fUpdate) + vUpdates[i] = true; + this->IncRef(c); + vvCs[i].push_back(c); + if(fSort && !vvFos[i].empty() && !vvFis[i0].empty()) { + std::list::iterator it = find(vObjs.begin(), vObjs.end(), i); + std::list::iterator it_i0 = find(it, vObjs.end(), i0); + if(it_i0 != vObjs.end()) { + // if(nVerbose > 6) + // std::cout << "\t\t\t\t\t\tMove " << i0 << " before " << *it << std::endl; + vObjs.erase(it_i0); + it_i0 = vObjs.insert(it, i0); + SortObjs_rec(it_i0); + } + } + } + inline void Disconnect(int i, int i0, unsigned j, bool fUpdate = true, bool fPfUpdate = true) { + if(nVerbose > 5) { + std::stringstream ss; + ss << "\t\t\t\t\tremove Wire " << std::setw(5) << i0 << "(" << (vvFis[i][j] & 1) << ")" + << " -> " << std::setw(5) << i; + Print(ss.str(), true); + } + vvFos[i0].erase(std::find(vvFos[i0].begin(), vvFos[i0].end(), i)); + vvFis[i].erase(vvFis[i].begin() + j); + this->DecRef(vvCs[i][j]); + vvCs[i].erase(vvCs[i].begin() + j); + if(fUpdate) + vUpdates[i] = true; + if(fPfUpdate) + vPfUpdates[i0] = true; + } + inline int Remove(int i, bool fPfUpdate = true) { + if(nVerbose > 5) { + std::stringstream ss; + ss << "\t\t\t\t\tremove Gate " << std::setw(5) << i; + Print(ss.str(), true); + } + assert(vvFos[i].empty()); + for(unsigned j = 0; j < vvFis[i].size(); j++) { + int i0 = vvFis[i][j] >> 1; + vvFos[i0].erase(std::find(vvFos[i0].begin(), vvFos[i0].end(), i)); + if(fPfUpdate) + vPfUpdates[i0] = true; + } + int count = vvFis[i].size(); + vvFis[i].clear(); + this->DecRef(vFs[i]); + this->DecRef(vGs[i]); + vFs[i] = vGs[i] = LitMax; + this->DelVec(vvCs[i]); + vUpdates[i] = vPfUpdates[i] = false; + return count; + } + inline int FindFi(int i, int i0) const { + for(unsigned j = 0; j < vvFis[i].size(); j++) + if((vvFis[i][j] >> 1) == i0) + return j; + return -1; + } + inline int Replace(int i, int f, bool fUpdate = true) { + if(nVerbose > 4) { + std::stringstream ss; + ss << "\t\t\t\treplace Gate " << std::setw(5) << i + << " by Node " << std::setw(5) << (f >> 1) << "(" << (f & 1) << ")"; + Print(ss.str(), true); + } + assert(i != (f >> 1)); + int count = 0; + for(unsigned j = 0; j < vvFos[i].size(); j++) { + int k = vvFos[i][j]; + int l = FindFi(k, i); + assert(l >= 0); + int fc = f ^ (vvFis[k][l] & 1); + if(find(vvFis[k].begin(), vvFis[k].end(), fc) != vvFis[k].end()) { + this->DecRef(vvCs[k][l]); + vvCs[k].erase(vvCs[k].begin() + l); + vvFis[k].erase(vvFis[k].begin() + l); + count++; + } else { + vvFis[k][l] = f ^ (vvFis[k][l] & 1); + vvFos[f >> 1].push_back(k); + } + if(fUpdate) + vUpdates[k] = true; + } + vvFos[i].clear(); + vPfUpdates[f >> 1] = true; + return count + Remove(i); + } + int ReplaceByConst(int i, bool c) { + if(nVerbose > 4) { + std::stringstream ss; + ss << "\t\t\t\treplace Gate " << std::setw(5) << i << " by Const " << c; + Print(ss.str(), true); + } + int count = 0; + for(unsigned j = 0; j < vvFos[i].size(); j++) { + int k = vvFos[i][j]; + int l = FindFi(k, i); + assert(l >= 0); + bool fc = c ^ (vvFis[k][l] & 1); + this->DecRef(vvCs[k][l]); + vvCs[k].erase(vvCs[k].begin() + l); + vvFis[k].erase(vvFis[k].begin() + l); + if(fc) { + if(vvFis[k].size() == 1) + count += Replace(k, vvFis[k][0]); + else + vUpdates[k] = true; + } else + count += ReplaceByConst(k, 0); + } + count += vvFos[i].size(); + vvFos[i].clear(); + return count + Remove(i); + } + inline void NewGate(int &pos) { + while(pos != nObjsAlloc && (!vvFis[pos].empty() || !vvFos[pos].empty())) + pos++; + if(nVerbose > 5) { + std::stringstream ss; + ss << "\t\t\t\t\tcreate Gate " << std::setw(5) << pos; + Print(ss.str(), true); + } + if(pos == nObjsAlloc) { + nObjsAlloc++; + vvFis.resize(nObjsAlloc); + vvFos.resize(nObjsAlloc); + if(fLevel) { + vLevels.resize(nObjsAlloc); + vSlacks.resize(nObjsAlloc); + vvFiSlacks.resize(nObjsAlloc); + } + vFs.resize(nObjsAlloc, LitMax); + vGs.resize(nObjsAlloc, LitMax); + vvCs.resize(nObjsAlloc); + vUpdates.resize(nObjsAlloc); + vPfUpdates.resize(nObjsAlloc); + } + } + void MarkFiCone_rec(std::vector &vMarks, int i) const { + if(vMarks[i]) + return; + vMarks[i] = true; + for(unsigned j = 0; j < vvFis[i].size(); j++) + MarkFiCone_rec(vMarks, vvFis[i][j] >> 1); + } + void MarkFoCone_rec(std::vector &vMarks, int i) const { + if(vMarks[i]) + return; + vMarks[i] = true; + for(unsigned j = 0; j < vvFos[i].size(); j++) + MarkFoCone_rec(vMarks, vvFos[i][j]); + } + bool IsFoConeShared_rec(std::vector &vVisits, int i, int visitor) const { + if(vVisits[i] == visitor) + return false; + if(vVisits[i]) + return true; + vVisits[i] = visitor; + for(unsigned j = 0; j < vvFos[i].size(); j++) + if(IsFoConeShared_rec(vVisits, vvFos[i][j], visitor)) + return true; + return false; + } + inline bool IsFoConeShared(int i) const { + std::vector vVisits(nObjsAlloc); + for(unsigned j = 0; j < vvFos[i].size(); j++) + if(IsFoConeShared_rec(vVisits, vvFos[i][j], j + 1)) + return true; + return false; + } + +private: // Level calculation + inline void add(std::vector &a, unsigned i) { + if(a.size() <= i) { + a.resize(i + 1); + a[i] = true; + return; + } + for(; i < a.size() && a[i]; i++) + a[i] = false; + if(i == a.size()) + a.resize(i + 1); + a[i] = true; + } + inline bool balanced(std::vector const &a) { + for(unsigned i = 0; i < a.size() - 1; i++) + if(a[i]) + return false; + return true; + } + inline bool noexcess(std::vector const &a, unsigned i) { + if(a.size() <= i) + return false; + for(unsigned j = i; j < a.size(); j++) + if(!a[j]) + return true; + for(unsigned j = 0; j < i; j++) + if(a[j]) + return false; + return true; + } + inline void ComputeLevel() { + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) { + if(vvFis[*it].size() == 2) + vLevels[*it] = std::max(vLevels[vvFis[*it][0] >> 1], vLevels[vvFis[*it][1] >> 1]) + 1; + else { + std::vector lev; + for(unsigned j = 0; j < vvFis[*it].size(); j++) + add(lev, vLevels[vvFis[*it][j] >> 1]); + if(balanced(lev)) + vLevels[*it] = (int)lev.size() - 1; + else + vLevels[*it] = (int)lev.size(); + } + } + if(nMaxLevels == -1) + nMaxLevels = CountLevels(); + for(unsigned i = 0; i < vPos.size(); i++) { + vvFiSlacks[vPos[i]].resize(1); + vvFiSlacks[vPos[i]][0] = nMaxLevels - vLevels[vvFis[vPos[i]][0] >> 1]; + } + for(std::list::reverse_iterator it = vObjs.rbegin(); it != vObjs.rend(); it++) { + vSlacks[*it] = nMaxLevels; + for(unsigned j = 0; j < vvFos[*it].size(); j++) { + int k = vvFos[*it][j]; + int l = FindFi(k, *it); + assert(l >= 0); + vSlacks[*it] = std::min(vSlacks[*it], vvFiSlacks[k][l]); + } + vvFiSlacks[*it].resize(vvFis[*it].size()); + for(unsigned j = 0; j < vvFis[*it].size(); j++) + vvFiSlacks[*it][j] = vSlacks[*it] + vLevels[*it] - 1 - vLevels[vvFis[*it][j] >> 1]; + } + } + +private: // Cost function + inline void ShufflePis(int seed) { + srand(seed); + for(int i = (int)vPis.size() - 1; i > 0; i--) + std::swap(vPis[i], vPis[rand() % (i + 1)]); + } + inline bool CostCompare(int a, int b) const { // return (cost(a) > cost(b)) + int a0 = a >> 1; + int b0 = b >> 1; + if(vvFis[a0].empty() && vvFis[b0].empty()) + return std::find(find(vPis.begin(), vPis.end(), a0), vPis.end(), b0) != vPis.end(); + if(vvFis[a0].empty() && !vvFis[b0].empty()) + return false; + if(!vvFis[a0].empty() && vvFis[b0].empty()) + return true; + if(vvFos[a0].size() > vvFos[b0].size()) + return false; + if(vvFos[a0].size() < vvFos[b0].size()) + return true; + bool ac = a & 1; + bool bc = b & 1; + switch(nSortType) { + case 0: + return std::find(find(vObjs.begin(), vObjs.end(), a0), vObjs.end(), b0) == vObjs.end(); + case 1: + return this->man->OneCount(this->man->LitNotCond(vFs[a0], ac)) < this->man->OneCount(this->man->LitNotCond(vFs[b0], bc)); + case 2: + return this->man->OneCount(vFs[a0]) < this->man->OneCount(vFs[b0]); + case 3: + return this->man->OneCount(this->man->LitNot(vFs[a0])) < this->man->OneCount(vFs[b0]); // pseudo random + default: + return false; // no sorting + } + } + inline bool SortFis(int i) { + if(nVerbose > 5) { + std::stringstream ss; + ss << "\t\t\t\tsort FIs Gate " << std::setw(5) << i; + Print(ss.str(), true); + } + bool fSort = false; + for(int p = 1; p < (int)vvFis[i].size(); p++) { + int f = vvFis[i][p]; + lit c = vvCs[i][p]; + int q = p - 1; + for(; q >= 0 && CostCompare(f, vvFis[i][q]); q--) { + vvFis[i][q + 1] = vvFis[i][q]; + vvCs[i][q + 1] = vvCs[i][q]; + } + if(q + 1 != p) { + fSort = true; + vvFis[i][q + 1] = f; + vvCs[i][q + 1] = c; + } + } + if(nVerbose > 5) + for(unsigned j = 0; j < vvFis[i].size(); j++) { + std::stringstream ss; + ss << "\t\t\t\t\tFI " << j << " = " + << std::setw(5) << (vvFis[i][j] >> 1) << "(" << (vvFis[i][j] & 1) << ")"; + Print(ss.str(), true); + } + return fSort; + } + +private: // Symbolic simulation + inline lit LitFi(int i, int j) const { + int i0 = vvFis[i][j] >> 1; + bool c0 = vvFis[i][j] & 1; + return this->man->LitNotCond(vFs[i0], c0); + } + inline lit LitFi(int i, int j, std::vector const &vFs_) const { + int i0 = vvFis[i][j] >> 1; + bool c0 = vvFis[i][j] & 1; + return this->man->LitNotCond(vFs_[i0], c0); + } + inline void Build(int i, std::vector &vFs_) const { + if(nVerbose > 6) { + std::stringstream ss; + ss << "\t\t\t\tbuilding Gate" << std::setw(5) << i; + Print(ss.str(), nVerbose > 7); + } + this->Update(vFs_[i], this->man->Const1()); + for(unsigned j = 0; j < vvFis[i].size(); j++) + this->Update(vFs_[i], this->man->And(vFs_[i], LitFi(i, j, vFs_))); + } + inline void Build(bool fPfUpdate = true) { + if(nVerbose > 6) + Print("\t\t\tBuild", true); + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) + if(vUpdates[*it]) { + lit x = vFs[*it]; + this->IncRef(x); + Build(*it, vFs); + this->DecRef(x); + if(!this->man->LitIsEq(x, vFs[*it])) + for(unsigned j = 0; j < vvFos[*it].size(); j++) + vUpdates[vvFos[*it][j]] = true; + } + if(fPfUpdate) + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) + vPfUpdates[*it] = vPfUpdates[*it] || vUpdates[*it]; + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) + vUpdates[*it] = false; + assert(AllFalse(vUpdates)); + } + void BuildFoConeCompl(int i, std::vector &vPoFsCompl) const { + if(nVerbose > 6) { + std::stringstream ss; + ss << "\t\t\tBuild with complemented Gate " << std::setw(5) << i; + Print(ss.str(), true); + } + std::vector vFsCompl; + this->CopyVec(vFsCompl, vFs); + vFsCompl[i] = this->man->LitNot(vFs[i]); + std::vector vUpdatesCompl(nObjsAlloc); + for(unsigned j = 0; j < vvFos[i].size(); j++) + vUpdatesCompl[vvFos[i][j]] = true; + for(std::list::const_iterator it = vObjs.begin(); it != vObjs.end(); it++) + if(vUpdatesCompl[*it]) { + Build(*it, vFsCompl); + if(!this->man->LitIsEq(vFsCompl[*it], vFs[*it])) + for(unsigned j = 0; j < vvFos[*it].size(); j++) + vUpdatesCompl[vvFos[*it][j]] = true; + } + for(unsigned j = 0; j < vPos.size(); j++) + this->Update(vPoFsCompl[j], LitFi(vPos[j], 0, vFsCompl)); + this->DelVec(vFsCompl); + } + +private: // CSPF + inline int RemoveRedundantFis(int i, int block_i0 = -1, unsigned j = 0) { + int count = 0; + for(; j < vvFis[i].size(); j++) { + if(block_i0 == (vvFis[i][j] >> 1)) + continue; + lit x = this->man->Const1(); + this->IncRef(x); + for(unsigned jj = 0; jj < vvFis[i].size(); jj++) + if(j != jj) + this->Update(x, this->man->And(x, LitFi(i, jj))); + this->Update(x, this->man->Or(this->man->LitNot(x), vGs[i])); + this->Update(x, this->man->Or(x, LitFi(i, j))); + this->DecRef(x); + if(this->man->IsConst1(x)) { + int i0 = vvFis[i][j] >> 1; + if(nVerbose > 4) { + std::stringstream ss; + ss << "\t\t\t\t[Rrfi] remove Wire " << std::setw(5) << i0 << "(" << (vvFis[i][j] & 1) << ")" + << " -> " << std::setw(5) << i; + Print(ss.str(), true); + } + Disconnect(i, i0, j--); + count++; + } + } + return count; + } + inline void CalcG(int i) { + this->Update(vGs[i], this->man->Const1()); + for(unsigned j = 0; j < vvFos[i].size(); j++) { + int k = vvFos[i][j]; + int l = FindFi(k, i); + assert(l >= 0); + this->Update(vGs[i], this->man->And(vGs[i], vvCs[k][l])); + } + } + inline int CalcC(int i) { + int count = 0; + for(unsigned j = 0; j < vvFis[i].size(); j++) { + lit x = this->man->Const1(); + this->IncRef(x); + for(unsigned jj = j + 1; jj < vvFis[i].size(); jj++) + this->Update(x, this->man->And(x, LitFi(i, jj))); + this->Update(x, this->man->Or(this->man->LitNot(x), vGs[i])); + int i0 = vvFis[i][j] >> 1; + if(this->man->IsConst1(this->man->Or(x, LitFi(i, j)))) { + if(nVerbose > 4) { + std::stringstream ss; + ss << "\t\t\t\t[Cspf] remove Wire " << std::setw(5) << i0 << "(" << (vvFis[i][j] & 1) << ")" + << " -> " << std::setw(5) << i; + Print(ss.str(), true); + } + Disconnect(i, i0, j--); + count++; + } else if(!this->man->LitIsEq(vvCs[i][j], x)) { + this->Update(vvCs[i][j], x); + vPfUpdates[i0] = true; + } + this->DecRef(x); + } + return count; + } + int Cspf(bool fSortRemove, int block = -1, int block_i0 = -1) { + if(nVerbose > 3) + PrintPfHeader("Cspf", block, block_i0); + if(state != cspf) + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) + vPfUpdates[*it] = true; + state = cspf; + int count = 0; + for(std::list::reverse_iterator it = vObjs.rbegin(); it != vObjs.rend();) { + if(vvFos[*it].empty()) { + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\t\tremove unused Gate " << std::setw(5) << *it; + Print(ss.str(), nVerbose > 4); + } + count += Remove(*it); + it = std::list::reverse_iterator(vObjs.erase(--(it.base()))); + continue; + } + if(!vPfUpdates[*it]) { + it++; + continue; + } + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\t\tprocessing Gate " << std::setw(5) << *it + << " (" << std::setw(5) << std::distance(vObjs.rbegin(), it) + 1 + << "/" << std::setw(5) << vObjs.size() << ")"; + Print(ss.str(), nVerbose > 4); + } + CalcG(*it); + if(fSortRemove) { + if(*it != block) + SortFis(*it), count += RemoveRedundantFis(*it); + else if(block_i0 != -1) + count += RemoveRedundantFis(*it, block_i0); + } + count += CalcC(*it); + vPfUpdates[*it] = false; + assert(!vvFis[*it].empty()); + if(vvFis[*it].size() == 1) { + count += Replace(*it, vvFis[*it][0]); + it = std::list::reverse_iterator(vObjs.erase(--(it.base()))); + continue; + } + it++; + } + Build(false); + assert(AllFalse(vPfUpdates)); + if(fLevel) + ComputeLevel(); + return count; + } + +private: // MSPF + inline bool MspfCalcG(int i) { + lit g = vGs[i]; + this->IncRef(g); + std::vector vPoFsCompl(vPos.size(), LitMax); + BuildFoConeCompl(i, vPoFsCompl); + this->Update(vGs[i], this->man->Const1()); + for(unsigned j = 0; j < vPos.size(); j++) { + lit x = this->man->LitNot(this->Xor(vPoFs[j], vPoFsCompl[j])); + this->IncRef(x); + this->Update(x, this->man->Or(x, vvCs[vPos[j]][0])); + this->Update(vGs[i], this->man->And(vGs[i], x)); + this->DecRef(x); + } + this->DelVec(vPoFsCompl); + this->DecRef(g); + return !this->man->LitIsEq(vGs[i], g); + } + inline int MspfCalcC(int i, int block_i0 = -1) { + for(unsigned j = 0; j < vvFis[i].size(); j++) { + lit x = this->man->Const1(); + this->IncRef(x); + for(unsigned jj = 0; jj < vvFis[i].size(); jj++) + if(j != jj) + this->Update(x, this->man->And(x, LitFi(i, jj))); + this->Update(x, this->man->Or(this->man->LitNot(x), vGs[i])); + int i0 = vvFis[i][j] >> 1; + if(i0 != block_i0 && this->man->IsConst1(this->man->Or(x, LitFi(i, j)))) { + if(nVerbose > 4) { + std::stringstream ss; + ss << "\t\t\t\t[Mspf] remove Wire " << std::setw(5) << i0 << "(" << (vvFis[i][j] & 1) << ")" + << " -> " << std::setw(5) << i; + Print(ss.str(), true); + } + Disconnect(i, i0, j); + this->DecRef(x); + return RemoveRedundantFis(i, block_i0, j) + 1; + } else if(!this->man->LitIsEq(vvCs[i][j], x)) { + this->Update(vvCs[i][j], x); + vPfUpdates[i0] = true; + } + this->DecRef(x); + } + return 0; + } + int Mspf(bool fSort, int block = -1, int block_i0 = -1) { + if(nVerbose > 3) + PrintPfHeader("Mspf", block, block_i0); + assert(AllFalse(vUpdates)); + vFoConeShared.resize(nObjsAlloc); + if(state != mspf) + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) + vPfUpdates[*it] = true; + state = mspf; + int count = 0; + int restarts = 0; + for(std::list::reverse_iterator it = vObjs.rbegin(); it != vObjs.rend();) { + if(vvFos[*it].empty()) { + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\t\tremove unused Gate " << std::setw(5) << *it; + Print(ss.str(), nVerbose > 4); + } + count += Remove(*it); + it = std::list::reverse_iterator(vObjs.erase(--(it.base()))); + continue; + } + if(!vFoConeShared[*it] && !vPfUpdates[*it] && (vvFos[*it].size() == 1 || !IsFoConeShared(*it))) { + it++; + continue; + } + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\t\tprocessing Gate " << std::setw(5) << *it + << " (" << std::setw(5) << std::distance(vObjs.rbegin(), it) + 1 + << "/" << std::setw(5) << vObjs.size() << ")" + << ", #restarts = " << std::setw(3) << restarts; + Print(ss.str(), nVerbose > 4); + } + if(vvFos[*it].size() == 1 || !IsFoConeShared(*it)) { + if(vFoConeShared[*it]) { + vFoConeShared[*it] = false; + lit g = vGs[*it]; + this->IncRef(g); + CalcG(*it); + this->DecRef(g); + if(g == vGs[*it] && !vPfUpdates[*it]) { + it++; + continue; + } + } else + CalcG(*it); + } else { + vFoConeShared[*it] = true; + if(!MspfCalcG(*it) && !vPfUpdates[*it]) { + it++; + continue; + } + bool IsConst1 = this->man->IsConst1(this->man->Or(vGs[*it], vFs[*it])); + bool IsConst0 = IsConst1? false: this->man->IsConst1(this->man->Or(vGs[*it], this->man->LitNot(vFs[*it]))); + if(IsConst1 || IsConst0) { + count += ReplaceByConst(*it, (int)IsConst1); + vObjs.erase(--(it.base())); + Build(); + it = vObjs.rbegin(); + restarts++; + continue; + } + } + if(fSort && block != *it) + SortFis(*it); + if(int diff = (block == *it)? MspfCalcC(*it, block_i0): MspfCalcC(*it)) { + count += diff; + assert(!vvFis[*it].empty()); + if(vvFis[*it].size() == 1) { + count += Replace(*it, vvFis[*it][0]); + vObjs.erase(--(it.base())); + } + Build(); + it = vObjs.rbegin(); + restarts++; + continue; + } + vPfUpdates[*it] = false; + it++; + } + assert(AllFalse(vUpdates)); + assert(AllFalse(vPfUpdates)); + if(fLevel) + ComputeLevel(); + return count; + } + +private: // Merge/decompose one + inline int TrivialMergeOne(int i) { + int count = 0; + std::vector vFisOld = vvFis[i]; + std::vector vCsOld = vvCs[i]; + vvFis[i].clear(); + vvCs[i].clear(); + for(unsigned j = 0; j < vFisOld.size(); j++) { + int i0 = vFisOld[j] >> 1; + int c0 = vFisOld[j] & 1; + if(vvFis[i0].empty() || vvFos[i0].size() > 1 || c0) { + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\t[TrivialMerge] adding Wire " << std::setw(5) << i0 << "(" << c0 << ")" + << " -> " << std::setw(5) << i; + Print(ss.str(), true); + } + vvFis[i].push_back(vFisOld[j]); + vvCs[i].push_back(vCsOld[j]); + continue; + } + vPfUpdates[i] = vPfUpdates[i] | vPfUpdates[i0]; + vvFos[i0].erase(find(vvFos[i0].begin(), vvFos[i0].end(), i)); + count++; + typename std::vector::iterator itfi = vFisOld.begin() + j; + typename std::vector::iterator itc = vCsOld.begin() + j; + for(unsigned jj = 0; jj < vvFis[i0].size(); jj++) { + int f = vvFis[i0][jj]; + std::vector::iterator it = find(vvFis[i].begin(), vvFis[i].end(), f); + if(it == vvFis[i].end()) { + vvFos[f >> 1].push_back(i); + itfi = vFisOld.insert(itfi, f); + itc = vCsOld.insert(itc, vvCs[i0][jj]); + this->IncRef(*itc); + itfi++; + itc++; + count--; + } else { + assert(state == none); + } + } + count += Remove(i0, false); + vObjs.erase(find(vObjs.begin(), vObjs.end(), i0)); + vFisOld.erase(itfi); + this->DecRef(*itc); + vCsOld.erase(itc); + j--; + } + return count; + } + inline int TrivialDecomposeOne(std::list::iterator const &it, int &pos) { + if(nVerbose > 2) { + std::stringstream ss; + ss << "\tTrivialDecompose Gate " << std::setw(5) << *it; + Print(ss.str() , nVerbose > 3); + } + assert(vvFis[*it].size() > 2); + int count = 2 - vvFis[*it].size(); + while(vvFis[*it].size() > 2) { + int f0 = vvFis[*it].back(); + lit c0 = vvCs[*it].back(); + Disconnect(*it, f0 >> 1, vvFis[*it].size() - 1, false, false); + int f1 = vvFis[*it].back(); + lit c1 = vvCs[*it].back(); + Disconnect(*it, f1 >> 1, vvFis[*it].size() - 1, false, false); + NewGate(pos); + Connect(pos, f1, false, false, c1); + Connect(pos, f0, false, false, c0); + if(!vPfUpdates[*it]) { + if(state == cspf) + this->Update(vGs[pos], vGs[*it]); + else if(state == mspf) { + lit x = this->man->Const1(); + this->IncRef(x); + for(unsigned j = 0; j < vvFis[*it].size(); j++) + this->Update(x, this->man->And(x, LitFi(*it, j))); + this->Update(vGs[pos], this->man->Or(this->man->LitNot(x), vGs[*it])); + this->DecRef(x); + } + } + Connect(*it, pos << 1, false, false, vGs[pos]); + vObjs.insert(it, pos); + Build(pos, vFs); + } + return count; + } + inline int BalancedDecomposeOne(std::list::iterator const &it, int &pos) { + if(nVerbose > 2) { + std::stringstream ss; + ss << "\tBalancedDecompose Gate " << std::setw(5) << *it; + Print(ss.str(), nVerbose > 3); + } + assert(fLevel); + assert(vvFis[*it].size() > 2); + for(int p = 1; p < (int)vvFis[*it].size(); p++) { + int f = vvFis[*it][p]; + lit c = vvCs[*it][p]; + int q = p - 1; + for(; q >= 0 && vLevels[f >> 1] > vLevels[vvFis[*it][q] >> 1]; q--) { + vvFis[*it][q + 1] = vvFis[*it][q]; + vvCs[*it][q + 1] = vvCs[*it][q]; + } + if(q + 1 != p) { + vvFis[*it][q + 1] = f; + vvCs[*it][q + 1] = c; + } + } + int count = 2 - vvFis[*it].size(); + while(vvFis[*it].size() > 2) { + int f0 = vvFis[*it].back(); + lit c0 = vvCs[*it].back(); + Disconnect(*it, f0 >> 1, vvFis[*it].size() - 1, false, false); + int f1 = vvFis[*it].back(); + lit c1 = vvCs[*it].back(); + Disconnect(*it, f1 >> 1, vvFis[*it].size() - 1, false, false); + NewGate(pos); + Connect(pos, f1, false, false, c1); + Connect(pos, f0, false, false, c0); + Connect(*it, pos << 1, false, false); + Build(pos, vFs); + vLevels[pos] = std::max(vLevels[f0 >> 1], vLevels[f1 >> 1]) + 1; + vObjs.insert(it, pos); + int f = vvFis[*it].back(); + lit c = vvCs[*it].back(); + int q = (int)vvFis[*it].size() - 2; + for(; q >= 0 && vLevels[f >> 1] > vLevels[vvFis[*it][q] >> 1]; q--) { + vvFis[*it][q + 1] = vvFis[*it][q]; + vvCs[*it][q + 1] = vvCs[*it][q]; + } + if(q + 1 != (int)vvFis[*it].size() - 1) { + vvFis[*it][q + 1] = f; + vvCs[*it][q + 1] = c; + } + } + vPfUpdates[*it] = true; + return count; + } + +public: // Merge/decompose + int TrivialMerge() { + int count = 0; + for(std::list::reverse_iterator it = vObjs.rbegin(); it != vObjs.rend();) { + count += TrivialMergeOne(*it); + it++; + } + return count; + } + int TrivialDecompose() { + int count = 0; + int pos = vPis.size() + 1; + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) + if(vvFis[*it].size() > 2) + count += TrivialDecomposeOne(it, pos); + return count; + } + int Decompose() { + int count = 0; + int pos = vPis.size() + 1; + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) { + std::set s1(vvFis[*it].begin(), vvFis[*it].end()); + assert(s1.size() == vvFis[*it].size()); + std::list::iterator it2 = it; + for(it2++; it2 != vObjs.end(); it2++) { + std::set s2(vvFis[*it2].begin(), vvFis[*it2].end()); + std::set s; + std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), std::inserter(s, s.begin())); + if(s.size() > 1) { + if(s == s1) { + if(s == s2) { + if(nVerbose > 2) { + std::stringstream ss; + ss << "\treplace Gate " << std::setw(5) << *it2 + << " by Gate " << std::setw(5) << *it; + Print(ss.str() , nVerbose > 3); + } + count += Replace(*it2, *it << 1, false); + it2 = vObjs.erase(it2); + it2--; + } else { + if(nVerbose > 2) { + std::stringstream ss; + ss << "\tdecompose Gate " << std::setw(5) << *it2 + << " by Gate " << std::setw(5) << *it; + Print(ss.str() , nVerbose > 3); + } + for(std::set::iterator it3 = s.begin(); it3 != s.end(); it3++) { + unsigned j = find(vvFis[*it2].begin(), vvFis[*it2].end(), *it3) - vvFis[*it2].begin(); + Disconnect(*it2, *it3 >> 1, j, false); + } + count += s.size(); + if(std::find(vvFis[*it2].begin(), vvFis[*it2].end(), *it << 1) == vvFis[*it2].end()) { + Connect(*it2, *it << 1, false, false); + count--; + } + vPfUpdates[*it2] = true; + } + continue; + } + if(s == s2) { + it = vObjs.insert(it, *it2); + vObjs.erase(it2); + } else { + NewGate(pos); + if(nVerbose > 2) { + std::stringstream ss; + ss << "\tdecompose Gate " << std::setw(5) << *it + << " and " << std::setw(5) << *it2 + << " by a new Gate " << std::setw(5) << pos; + Print(ss.str() , nVerbose > 3); + } + if(nVerbose > 4) { + std::stringstream ss; + ss << "\t\tIntersection:"; + for(std::set::iterator it3 = s.begin(); it3 != s.end(); it3++) + ss << " " << (*it3 >> 1) << "(" << (*it3 & 1) << ")"; + Print(ss.str(), true); + } + for(std::set::iterator it3 = s.begin(); it3 != s.end(); it3++) + Connect(pos, *it3, false, false); + count -= s.size(); + it = vObjs.insert(it, pos); + Build(pos, vFs); + vPfUpdates[*it] = true; + } + s1 = s; + it2 = it; + } + } + if(vvFis[*it].size() > 2) + count += TrivialDecomposeOne(it, pos); + } + return count; + } + +private: // Save/load + inline void Save(TransductionBackup &b) const { + b.man = this->man; + b.nObjsAlloc = nObjsAlloc; + b.state = state; + b.vObjs = vObjs; + b.vvFis = vvFis; + b.vvFos = vvFos; + b.vLevels = vLevels; + b.vSlacks = vSlacks; + b.vvFiSlacks = vvFiSlacks; + this->CopyVec(b.vFs, vFs); + this->CopyVec(b.vGs, vGs); + this->CopyVec(b.vvCs, vvCs); + b.vUpdates = vUpdates; + b.vPfUpdates = vPfUpdates; + b.vFoConeShared = vFoConeShared; + } + inline void Load(TransductionBackup const &b) { + nObjsAlloc = b.nObjsAlloc; + state = b.state; + vObjs = b.vObjs; + vvFis = b.vvFis; + vvFos = b.vvFos; + vLevels = b.vLevels; + vSlacks = b.vSlacks; + vvFiSlacks = b.vvFiSlacks; + this->CopyVec(vFs, b.vFs); + this->CopyVec(vGs, b.vGs); + this->CopyVec(vvCs, b.vvCs); + vUpdates = b.vUpdates; + vPfUpdates = b.vPfUpdates; + vFoConeShared = b.vFoConeShared; + } + +private: // Connectable condition + inline bool TryConnect(int i, int i0, bool c0) { + int f = (i0 << 1) ^ (int)c0; + if(find(vvFis[i].begin(), vvFis[i].end(), f) == vvFis[i].end()) { + lit x = this->man->Or(this->man->LitNot(vFs[i]), vGs[i]); + this->IncRef(x); + if(this->man->IsConst1(this->man->Or(x, this->man->LitNotCond(vFs[i0], c0)))) { + this->DecRef(x); + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\t[TryConnect] adding Wire " << std::setw(5) << i0 << "(" << c0 << ")" + << " -> " << std::setw(5) << i; + Print(ss.str(), true); + } + Connect(i, f, true); + return true; + } + this->DecRef(x); + } + return false; + } + +public: // Resubs + int Resub(bool fMspf) { + int count = fMspf? Mspf(true): Cspf(true); + int nodes = CountNodes(); + TransductionBackup b; + Save(b); + int count_ = count; + std::list targets = vObjs; + for(std::list::reverse_iterator it = targets.rbegin(); it != targets.rend(); it++) { + if(nVerbose > 1) { + std::stringstream ss; + ss << "[Resub] processing Gate " << std::setw(5) << *it + << " (" << std::setw(5) << std::distance(targets.rbegin(), it) + 1 + << "/" << std::setw(5) << targets.size() << ")"; + PrintStats(ss.str(), nVerbose > 2); + } + if(vvFos[*it].empty()) + continue; + count += TrivialMergeOne(*it); + std::vector lev; + if(fLevel) { + for(unsigned j = 0; j < vvFis[*it].size(); j++) + add(lev, vLevels[vvFis[*it][j] >> 1]); + if((int)lev.size() > vLevels[*it] + vSlacks[*it]) { + Load(b); + count = count_; + continue; + } + lev.resize(vLevels[*it] + vSlacks[*it]); + } + bool fConnect = false; + std::vector vMarks(nObjsAlloc); + MarkFoCone_rec(vMarks, *it); + std::list targets2 = vObjs; + for(std::list::iterator it2 = targets2.begin(); it2 != targets2.end(); it2++) { + if(fLevel && (int)lev.size() > vLevels[*it] + vSlacks[*it]) + break; + if(!vMarks[*it2] && !vvFos[*it2].empty()) + if(!fLevel || noexcess(lev, vLevels[*it2])) + if(TryConnect(*it, *it2, false) || TryConnect(*it, *it2, true)) { + fConnect = true; + count--; + if(fLevel) + add(lev, vLevels[*it2]); + } + } + if(fConnect) { + if(fMspf) { + Build(); + count += Mspf(true, *it); + } else { + vPfUpdates[*it] = true; + count += Cspf(true, *it); + } + if(!vvFos[*it].empty()) { + vPfUpdates[*it] = true; + count += fMspf? Mspf(true): Cspf(true); + } + } + if(nodes < CountNodes()) { + Load(b); + count = count_; + continue; + } + if(!vvFos[*it].empty() && vvFis[*it].size() > 2) { + std::list::iterator it2 = find(vObjs.begin(), vObjs.end(), *it); + int pos = nObjsAlloc; + if(fLevel) + count += BalancedDecomposeOne(it2, pos) + (fMspf? Mspf(true): Cspf(true)); + else + count += TrivialDecomposeOne(it2, pos); + } + nodes = CountNodes(); + Save(b); + count_ = count; + } + if(nVerbose) + PrintStats("Resub", true, 11); + return count; + } + int ResubMono(bool fMspf) { + int count = fMspf? Mspf(true): Cspf(true); + std::list targets = vObjs; + for(std::list::reverse_iterator it = targets.rbegin(); it != targets.rend(); it++) { + if(nVerbose > 1) { + std::stringstream ss; + ss << "[ResubMono] processing Gate " << std::setw(5) << *it + << " (" << std::setw(5) << std::distance(targets.rbegin(), it) + 1 + << "/" << std::setw(5) << targets.size() << ")"; + PrintStats(ss.str(), nVerbose > 2); + } + if(vvFos[*it].empty()) + continue; + count += TrivialMergeOne(*it); + TransductionBackup b; + Save(b); + int count_ = count; + for(unsigned i = 0; i < vPis.size(); i++) { + if(vvFos[*it].empty()) + break; + if(nVerbose > 2) { + std::stringstream ss; + ss << "\ttrying a new fanin PI " << std::setw(2) << i; + PrintStats(ss.str(), nVerbose > 3); + } + if(TryConnect(*it, vPis[i], false) || TryConnect(*it, vPis[i], true)) { + count--; + int diff; + if(fMspf) { + Build(); + diff = Mspf(true, *it, vPis[i]); + } else { + vPfUpdates[*it] = true; + diff = Cspf(true, *it, vPis[i]); + } + if(diff) { + count += diff; + if(!vvFos[*it].empty()) { + vPfUpdates[*it] = true; + count += fMspf? Mspf(true): Cspf(true); + } + if(fLevel && CountLevels() > nMaxLevels) { + Load(b); + count = count_; + } else { + Save(b); + count_ = count; + } + } else { + Load(b); + count = count_; + } + } + } + if(vvFos[*it].empty()) + continue; + std::vector vMarks(nObjsAlloc); + MarkFoCone_rec(vMarks, *it); + std::list targets2 = vObjs; + for(std::list::iterator it2 = targets2.begin(); it2 != targets2.end(); it2++) { + if(vvFos[*it].empty()) + break; + if(nVerbose > 2) { + std::stringstream ss; + ss << "\ttrying a new fanin Gate " << std::setw(5) << *it2 + << " (" << std::setw(5) << std::distance(targets2.begin(), it2) + 1 + << "/" << std::setw(5) << targets2.size() << ")"; + PrintStats(ss.str(), nVerbose > 3); + } + if(!vMarks[*it2] && !vvFos[*it2].empty()) + if(TryConnect(*it, *it2, false) || TryConnect(*it, *it2, true)) { + count--; + int diff; + if(fMspf) { + Build(); + diff = Mspf(true, *it, *it2); + } else { + vPfUpdates[*it] = true; + diff = Cspf(true, *it, *it2); + } + if(diff) { + count += diff; + if(!vvFos[*it].empty()) { + vPfUpdates[*it] = true; + count += fMspf? Mspf(true): Cspf(true); + } + if(fLevel && CountLevels() > nMaxLevels) { + Load(b); + count = count_; + } else { + Save(b); + count_ = count; + } + } else { + Load(b); + count = count_; + } + } + } + if(vvFos[*it].empty()) + continue; + if(vvFis[*it].size() > 2) { + std::list::iterator it2 = find(vObjs.begin(), vObjs.end(), *it); + int pos = nObjsAlloc; + if(fLevel) + count += BalancedDecomposeOne(it2, pos) + (fMspf? Mspf(true): Cspf(true)); + else + count += TrivialDecomposeOne(it2, pos); + } + } + if(nVerbose) + PrintStats("ResubMono", true, 11); + return count; + } + int ResubShared(bool fMspf) { + int count = fMspf? Mspf(true): Cspf(true); + std::list targets = vObjs; + for(std::list::reverse_iterator it = targets.rbegin(); it != targets.rend(); it++) { + if(nVerbose > 1) { + std::stringstream ss; + ss << "[ResubShared] processing Gate " << std::setw(5) << *it + << " (" << std::setw(5) << std::distance(targets.rbegin(), it) + 1 + << "/" << std::setw(5) << targets.size() << ")"; + PrintStats(ss.str(), nVerbose > 2); + } + if(vvFos[*it].empty()) + continue; + count += TrivialMergeOne(*it); + bool fConnect = false; + for(unsigned i = 0; i < vPis.size(); i++) + if(TryConnect(*it, vPis[i], false) || TryConnect(*it, vPis[i], true)) { + fConnect |= true; + count--; + } + std::vector vMarks(nObjsAlloc); + MarkFoCone_rec(vMarks, *it); + for(std::list::iterator it2 = targets.begin(); it2 != targets.end(); it2++) + if(!vMarks[*it2] && !vvFos[*it2].empty()) + if(TryConnect(*it, *it2, false) || TryConnect(*it, *it2, true)) { + fConnect |= true; + count--; + } + if(fConnect) { + if(fMspf) { + Build(); + count += Mspf(true, *it); + } else { + vPfUpdates[*it] = true; + count += Cspf(true, *it); + } + if(!vvFos[*it].empty()) { + vPfUpdates[*it] = true; + count += fMspf? Mspf(true): Cspf(true); + } + } + } + count += Decompose(); + if(nVerbose) + PrintStats("ResubShared", true, 11); + return count; + } + +public: // Optimization scripts + int RepeatResub(bool fMono, bool fMspf) { + int count = 0; + while(int diff = fMono? ResubMono(fMspf): Resub(fMspf)) + count += diff; + return count; + } + int RepeatInner(bool fMspf, bool fInner) { + int count = 0; + while(int diff = RepeatResub(true, fMspf) + RepeatResub(false, fMspf)) { + count += diff; + if(!fInner) + break; + } + return count; + } + int RepeatOuter(bool fMspf, bool fInner, bool fOuter) { + int count = 0; + while(int diff = fMspf? RepeatInner(false, fInner) + RepeatInner(true, fInner): RepeatInner(false, fInner)) { + count += diff; + if(!fOuter) + break; + } + return count; + } + int RepeatAll(bool fFirstMerge, bool fMspfMerge, bool fMspfResub, bool fInner, bool fOuter) { + TransductionBackup b; + Save(b); + int count = 0; + int diff = 0; + if(fFirstMerge) + diff = ResubShared(fMspfMerge); + diff += RepeatOuter(fMspfResub, fInner, fOuter); + if(diff > 0) { + count = diff; + Save(b); + diff = 0; + } + while(true) { + diff += ResubShared(fMspfMerge) + RepeatOuter(fMspfResub, fInner, fOuter); + if(diff > 0) { + count += diff; + Save(b); + diff = 0; + } else { + Load(b); + break; + } + } + return count; + } + +public: // Cspf/mspf + int Cspf() { + return Cspf(true); + } + int Mspf() { + return Mspf(true); + } + +private: // Setup + void ImportAig(Gia_Man_t *pGia) { + int i; + Gia_Obj_t *pObj; + nObjsAlloc = Gia_ManObjNum(pGia); + vvFis.resize(nObjsAlloc); + vvFos.resize(nObjsAlloc); + if(fLevel) { + vLevels.resize(nObjsAlloc); + vSlacks.resize(nObjsAlloc); + vvFiSlacks.resize(nObjsAlloc); + } + vFs.resize(nObjsAlloc, LitMax); + vGs.resize(nObjsAlloc, LitMax); + vvCs.resize(nObjsAlloc); + vUpdates.resize(nObjsAlloc); + vPfUpdates.resize(nObjsAlloc); + std::vector v(Gia_ManObjNum(pGia), -1); + int nObjs = 0; + v[Gia_ObjId(pGia, Gia_ManConst0(pGia))] = nObjs << 1; + nObjs++; + Gia_ManForEachCi(pGia, pObj, i) { + v[Gia_ObjId(pGia, pObj)] = nObjs << 1; + vPis.push_back(nObjs); + nObjs++; + } + Gia_ManForEachAnd(pGia, pObj, i) { + int id = Gia_ObjId(pGia, pObj); + if(nVerbose > 5) { + std::stringstream ss; + ss << "\t\t\t\timport Gate " << std::setw(5) << id; + Print(ss.str(), true); + } + int i0 = Gia_ObjId(pGia, Gia_ObjFanin0(pObj)); + int i1 = Gia_ObjId(pGia, Gia_ObjFanin1(pObj)); + int c0 = Gia_ObjFaninC0(pObj); + int c1 = Gia_ObjFaninC1(pObj); + if(i0 == i1) { + if(c0 == c1) + v[id] = v[i0] ^ c0; + else + v[id] = 0; + } else { + Connect(nObjs , v[i0] ^ c0); + Connect(nObjs, v[i1] ^ c1); + v[id] = nObjs << 1; + vObjs.push_back(nObjs); + nObjs++; + } + } + Gia_ManForEachCo(pGia, pObj, i) { + if(nVerbose > 5) { + std::stringstream ss; + ss << "\t\t\t\timport PO " << std::setw(2) << i; + Print(ss.str(), true); + } + int i0 = Gia_ObjId(pGia, Gia_ObjFanin0(pObj)); + int c0 = Gia_ObjFaninC0(pObj); + Connect(nObjs, v[i0] ^ c0); + vPos.push_back(nObjs); + nObjs++; + } + } + void Aig2Bdd(Gia_Man_t *pGia, std::vector &vNodes) { + if(nVerbose > 6) + Print("\t\t\tBuild Exdc", true); + int i; + Gia_Obj_t *pObj; + std::vector vCounts(pGia->nObjs); + Gia_ManStaticFanoutStart(pGia); + Gia_ManForEachAnd(pGia, pObj, i) + vCounts[Gia_ObjId(pGia, pObj)] = Gia_ObjFanoutNum(pGia, pObj); + Gia_ManStaticFanoutStop(pGia); + std::vector nodes(pGia->nObjs); + nodes[Gia_ObjId(pGia, Gia_ManConst0(pGia))] = this->man->Const0(); + Gia_ManForEachCi(pGia, pObj, i) + nodes[Gia_ObjId(pGia, pObj)] = this->man->IthVar(i); + Gia_ManForEachAnd(pGia, pObj, i) { + int id = Gia_ObjId(pGia, pObj); + if(nVerbose > 6) { + std::stringstream ss; + ss << "\t\t\t\tbuilding Exdc (" << i << " / " << Gia_ManAndNum(pGia) << ")"; + Print(ss.str(), nVerbose > 7); + } + int i0 = Gia_ObjId(pGia, Gia_ObjFanin0(pObj)); + int i1 = Gia_ObjId(pGia, Gia_ObjFanin1(pObj)); + bool c0 = Gia_ObjFaninC0(pObj); + bool c1 = Gia_ObjFaninC1(pObj); + nodes[id] = this->man->And(this->man->LitNotCond(nodes[i0], c0), this->man->LitNotCond(nodes[i1], c1)); + this->IncRef(nodes[id]); + vCounts[i0]--; + if(!vCounts[i0]) + this->DecRef(nodes[i0]); + vCounts[i1]--; + if(!vCounts[i1]) + this->DecRef(nodes[i1]); + } + Gia_ManForEachCo(pGia, pObj, i) { + int i0 = Gia_ObjId(pGia, Gia_ObjFanin0(pObj)); + bool c0 = Gia_ObjFaninC0(pObj); + vNodes.push_back(this->man->LitNotCond(nodes[i0], c0)); + } + } + void RemoveConstOutputs() { + bool fRemoved = false; + for(unsigned i = 0; i < vPos.size(); i++) { + int i0 = vvFis[vPos[i]][0] >> 1; + lit c = vvCs[vPos[i]][0]; + if(i0) { + if(this->man->IsConst1(this->man->Or(LitFi(vPos[i], 0), c))) { + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\tPO " << std::setw(2) << i << " is Const 1"; + Print(ss.str(), true); + } + Disconnect(vPos[i], i0, 0, false, false); + Connect(vPos[i], 1, false, false, c); + fRemoved |= vvFos[i0].empty(); + } else if(this->man->IsConst1(this->man->Or(this->man->LitNot(LitFi(vPos[i], 0)), c))) { + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\tPO " << std::setw(2) << i << " is Const 0"; + Print(ss.str(), true); + } + Disconnect(vPos[i], i0, 0, false, false); + Connect(vPos[i], 0, false, false, c); + fRemoved |= vvFos[i0].empty(); + } + } + } + if(fRemoved) { + for(std::list::reverse_iterator it = vObjs.rbegin(); it != vObjs.rend();) { + if(vvFos[*it].empty()) { + if(nVerbose > 3) { + std::stringstream ss; + ss << "\t\tremove unused Gate " << std::setw(5) << *it; + Print(ss.str(), true); + } + Remove(*it, false); + it = std::list::reverse_iterator(vObjs.erase(--(it.base()))); + continue; + } + it++; + } + } + } + +public: // Constructor + Transduction(Gia_Man_t *pGia, int nVerbose, bool fNewLine, int nSortType, int nPiShuffle, bool fLevel, Gia_Man_t *pExdc, Param &p): nVerbose(nVerbose), nSortType(nSortType), fLevel(fLevel), fNewLine(fNewLine) { + startclk = Abc_Clock(); + p.nGbc = 1; + p.nReo = 4000; + if(nSortType && nSortType < 4) + p.fCountOnes = true; + this->man = new Man(Gia_ManCiNum(pGia), p); + ImportAig(pGia); + this->Update(vFs[0], this->man->Const0()); + for(unsigned i = 0; i < vPis.size(); i++) + this->Update(vFs[i + 1], this->man->IthVar(i)); + nMaxLevels = -1; + Build(false); + this->man->Reorder(); + this->man->TurnOffReo(); + if(pExdc) { + std::vector vExdc; + Aig2Bdd(pExdc, vExdc); + for(unsigned i = 0; i < vPos.size(); i++) + vvCs[vPos[i]][0] = vExdc.size() == 1? vExdc[0]: vExdc[i]; + } else + for(unsigned i = 0; i < vPos.size(); i++) + this->Update(vvCs[vPos[i]][0], this->man->Const0()); + RemoveConstOutputs(); + vPoFs.resize(vPos.size(), LitMax); + for(unsigned i = 0; i < vPos.size(); i++) + this->Update(vPoFs[i], LitFi(vPos[i], 0)); + state = none; + if(nPiShuffle) + ShufflePis(nPiShuffle); + if(fLevel) + ComputeLevel(); + if(nVerbose) + PrintStats("Init", true, 11); + } + ~Transduction() { + if(nVerbose) + PrintStats("End", true, 11); + this->DelVec(vFs); + this->DelVec(vGs); + this->DelVec(vvCs); + this->DelVec(vPoFs); + //assert(this->man->CountNodes() == (int)vPis.size() + 1); + //assert(!this->man->Ref(this->man->Const0())); + delete this->man; + } + +public: // Output + Gia_Man_t *GenerateAig() const { + Gia_Man_t * pGia, *pTemp; + pGia = Gia_ManStart(1 + vPis.size() + CountNodes() + vPos.size()); + Gia_ManHashAlloc(pGia); + std::vector values(nObjsAlloc); + values[0] = Gia_ManConst0Lit(); + for(unsigned i = 0; i < vPis.size(); i++) + values[i + 1] = Gia_ManAppendCi(pGia); + for(std::list::const_iterator it = vObjs.begin(); it != vObjs.end(); it++) { + assert(vvFis[*it].size() > 1); + int i0 = vvFis[*it][0] >> 1; + int i1 = vvFis[*it][1] >> 1; + int c0 = vvFis[*it][0] & 1; + int c1 = vvFis[*it][1] & 1; + int r = Gia_ManHashAnd(pGia, Abc_LitNotCond(values[i0], c0), Abc_LitNotCond(values[i1], c1)); + for(unsigned i = 2; i < vvFis[*it].size(); i++) { + int ii = vvFis[*it][i] >> 1; + int ci = vvFis[*it][i] & 1; + r = Gia_ManHashAnd(pGia, r, Abc_LitNotCond(values[ii], ci)); + } + values[*it] = r; + } + for(unsigned i = 0; i < vPos.size(); i++) { + int i0 = vvFis[vPos[i]][0] >> 1; + int c0 = vvFis[vPos[i]][0] & 1; + Gia_ManAppendCo(pGia, Abc_LitNotCond(values[i0], c0)); + } + pGia = Gia_ManCleanup(pTemp = pGia); + Gia_ManStop(pTemp); + return pGia; + } + +public: // Debug and print + PfState State() const { + return state; + } + bool BuildDebug() { + for(std::list::iterator it = vObjs.begin(); it != vObjs.end(); it++) + vUpdates[*it] = true; + std::vector vFsOld; + CopyVec(vFsOld, vFs); + Build(false); + bool r = LitVecIsEq(vFsOld, vFs); + DelVec(vFsOld); + return r; + } + bool CspfDebug() { + std::vector vGsOld; + this->CopyVec(vGsOld, vGs); + std::vector > vvCsOld; + this->CopyVec(vvCsOld, vvCs); + state = none; + Cspf(false); + bool r = this->LitVecIsEq(vGsOld, vGs) && this->LitVecIsEq(vvCsOld, vvCs); + this->DelVec(vGsOld); + this->DelVec(vvCsOld); + return r; + } + bool MspfDebug() { + std::vector vGsOld; + this->CopyVec(vGsOld, vGs); + std::vector > vvCsOld; + this->CopyVec(vvCsOld, vvCs); + state = none; + Mspf(false); + bool r = this->LitVecIsEq(vGsOld, vGs) && this->LitVecIsEq(vvCsOld, vvCs); + this->DelVec(vGsOld); + this->DelVec(vvCsOld); + return r; + } + bool Verify() const { + for(unsigned j = 0; j < vPos.size(); j++) { + lit x = this->Xor(LitFi(vPos[j], 0), vPoFs[j]); + this->IncRef(x); + this->Update(x, this->man->And(x, this->man->LitNot(vvCs[vPos[j]][0]))); + this->DecRef(x); + if(!this->man->IsConst0(x)) + return false; + } + return true; + } + void PrintObjs() const { + for(std::list::const_iterator it = vObjs.begin(); it != vObjs.end(); it++) { + std::cout << "Gate " << *it << ":"; + if(fLevel) + std::cout << " Level = " << vLevels[*it] << ", Slack = " << vSlacks[*it]; + std::cout << std::endl; + std::string delim = ""; + std::cout << "\tFis: "; + for(unsigned j = 0; j < vvFis[*it].size(); j++) { + std::cout << delim << (vvFis[*it][j] >> 1) << "(" << (vvFis[*it][j] & 1) << ")"; + delim = ", "; + } + std::cout << std::endl; + delim = ""; + std::cout << "\tFos: "; + for(unsigned j = 0; j < vvFos[*it].size(); j++) { + std::cout << delim << vvFos[*it][j]; + delim = ", "; + } + std::cout << std::endl; + } + } +}; + +} + +ABC_NAMESPACE_CXX_HEADER_END + +#endif diff --git a/yosys/abc/src/aig/gia/giaTruth.c b/yosys/abc/src/aig/gia/giaTruth.c new file mode 100644 index 00000000000..0845eae96c7 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaTruth.c @@ -0,0 +1,818 @@ +/**CFile**************************************************************** + + FileName [giaTruth.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Truth table computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaTruth.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "misc/vec/vecMem.h" +#include "misc/vec/vecWec.h" +#include "misc/util/utilTruth.h" +#include "opt/dau/dau.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static word s_Truth6[6] = { + ABC_CONST(0xAAAAAAAAAAAAAAAA), + ABC_CONST(0xCCCCCCCCCCCCCCCC), + ABC_CONST(0xF0F0F0F0F0F0F0F0), + ABC_CONST(0xFF00FF00FF00FF00), + ABC_CONST(0xFFFF0000FFFF0000), + ABC_CONST(0xFFFFFFFF00000000) +}; + +static inline word * Gla_ObjTruthElem( Gia_Man_t * p, int i ) { return (word *)Vec_PtrEntry( p->vTtInputs, i ); } +static inline word * Gla_ObjTruthNodeId( Gia_Man_t * p, int Id ) { return Vec_WrdArray(p->vTtMemory) + p->nTtWords * Id; } +static inline word * Gla_ObjTruthNode( Gia_Man_t * p, Gia_Obj_t * pObj ) { return Vec_WrdArray(p->vTtMemory) + p->nTtWords * Gia_ObjNum(p, pObj); } +static inline word * Gla_ObjTruthFree1( Gia_Man_t * p ) { return Vec_WrdArray(p->vTtMemory) + Vec_WrdSize(p->vTtMemory) - p->nTtWords * 1; } +static inline word * Gla_ObjTruthFree2( Gia_Man_t * p ) { return Vec_WrdArray(p->vTtMemory) + Vec_WrdSize(p->vTtMemory) - p->nTtWords * 2; } +static inline word * Gla_ObjTruthConst0( Gia_Man_t * p, word * pDst ) { int w; for ( w = 0; w < p->nTtWords; w++ ) pDst[w] = 0; return pDst; } +static inline word * Gla_ObjTruthDup( Gia_Man_t * p, word * pDst, word * pSrc, int c ) { int w; for ( w = 0; w < p->nTtWords; w++ ) pDst[w] = c ? ~pSrc[w] : pSrc[w]; return pDst; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Compute truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word Gia_LutComputeTruth6Simple_rec( Gia_Man_t * p, int iObj ) +{ + word Truth0, Truth1, Truth; + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); + if ( Gia_ObjIsConst0(pObj) ) + return 0; + if ( Gia_ObjIsCi(pObj) ) + return s_Truths6[Gia_ObjCioId(pObj)]; + Truth0 = Gia_LutComputeTruth6Simple_rec( p, Gia_ObjFaninId0(pObj, iObj) ); + Truth1 = Gia_LutComputeTruth6Simple_rec( p, Gia_ObjFaninId1(pObj, iObj) ); + Truth0 = Gia_ObjFaninC0(pObj) ? ~Truth0 : Truth0; + Truth1 = Gia_ObjFaninC1(pObj) ? ~Truth1 : Truth1; + Truth = Gia_ObjIsXor(pObj) ? Truth0 ^ Truth1 : Truth0 & Truth1; + return Truth; +} +word Gia_LutComputeTruth6Simple( Gia_Man_t * p, int iPo ) +{ + Gia_Obj_t * pObj = Gia_ManPo( p, iPo ); + word Truth = Gia_LutComputeTruth6Simple_rec( p, Gia_ObjFaninId0p(p, pObj) ); + return Gia_ObjFaninC0(pObj) ? ~Truth : Truth; +} + +word Gia_LutComputeTruth6Map_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vMap ) +{ + word Truth0, Truth1, Truth; + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); + if ( Gia_ObjIsConst0(pObj) ) + return 0; + if ( Gia_ObjIsCi(pObj) ) + return s_Truths6[Vec_IntEntry(vMap, Gia_ObjCioId(pObj))]; + Truth0 = Gia_LutComputeTruth6Map_rec( p, Gia_ObjFaninId0(pObj, iObj), vMap ); + Truth1 = Gia_LutComputeTruth6Map_rec( p, Gia_ObjFaninId1(pObj, iObj), vMap ); + Truth0 = Gia_ObjFaninC0(pObj) ? ~Truth0 : Truth0; + Truth1 = Gia_ObjFaninC1(pObj) ? ~Truth1 : Truth1; + Truth = Gia_ObjIsXor(pObj) ? Truth0 ^ Truth1 : Truth0 & Truth1; + return Truth; +} +word Gia_LutComputeTruth6Map( Gia_Man_t * p, int iPo, Vec_Int_t * vMap ) +{ + Gia_Obj_t * pObj = Gia_ManPo( p, iPo ); + word Truth = Gia_LutComputeTruth6Map_rec( p, Gia_ObjFaninId0p(p, pObj), vMap ); + return Gia_ObjFaninC0(pObj) ? ~Truth : Truth; +} + +/**Function************************************************************* + + Synopsis [Generate MUX tree of the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_Truth5ToGia( Gia_Man_t * p, int * pVarLits, int nVars, unsigned Truth, int fHash ) +{ + int Var, Lit0, Lit1; + if ( Truth == 0 ) + return 0; + if ( ~Truth == 0 ) + return 1; + assert( nVars > 0 ); + // find the topmost var + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Abc_Tt5HasVar( Truth, Var ) ) + break; + assert( Var >= 0 ); + // cofactor + Lit0 = Gia_Truth5ToGia( p, pVarLits, Var, Abc_Tt5Cofactor0(Truth, Var), fHash ); + Lit1 = Gia_Truth5ToGia( p, pVarLits, Var, Abc_Tt5Cofactor1(Truth, Var), fHash ); + if ( fHash ) + return Gia_ManHashMux( p, pVarLits[Var], Lit1, Lit0 ); + else + return Gia_ManAppendMux( p, pVarLits[Var], Lit1, Lit0 ); +} + +/**Function************************************************************* + + Synopsis [Generate MUX tree of the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_Truth6ToGia( Gia_Man_t * p, int * pVarLits, int nVars, word Truth, int fHash ) +{ + int Var, Lit0, Lit1; + if ( Truth == 0 ) + return 0; + if ( ~Truth == 0 ) + return 1; + assert( nVars > 0 ); + // find the topmost var + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Abc_Tt6HasVar( Truth, Var ) ) + break; + assert( Var >= 0 ); + // cofactor + Lit0 = Gia_Truth6ToGia( p, pVarLits, Var, Abc_Tt6Cofactor0(Truth, Var), fHash ); + Lit1 = Gia_Truth6ToGia( p, pVarLits, Var, Abc_Tt6Cofactor1(Truth, Var), fHash ); + if ( fHash ) + return Gia_ManHashMux( p, pVarLits[Var], Lit1, Lit0 ); + else + return Gia_ManAppendMux( p, pVarLits[Var], Lit1, Lit0 ); +} +void Gia_Truth6ToGiaTest( Gia_Man_t * p ) +{ + int Size = 5; + word Truth, TruthNew; + Vec_Int_t * vMap = Vec_IntStartFull( Gia_ManCiNum(p) ); + Vec_Int_t * vSupp = Vec_IntStart( 100 ); + int nCos = Gia_ManCoNum(p), Count = 0; + int i, k, Id, ObjId, iLitNew; + Gia_ManHashAlloc( p ); + Gia_ManForEachCoId( p, Id, i ) + { + Gia_ManCollectCis( p, &Id, 1, vSupp ); // ObjIds + if ( Vec_IntSize(vSupp) <= Size && i < nCos ) + { + int pVarLits[6]; + Vec_IntForEachEntry( vSupp, ObjId, k ) + { + int CioId = Gia_ObjCioId(Gia_ManObj(p, ObjId)); + Vec_IntWriteEntry( vMap, CioId, k ); + pVarLits[k] = Abc_Var2Lit( ObjId, 0 ); + } + Truth = Gia_LutComputeTruth6Map( p, i, vMap ); + if ( Size == 5 ) + iLitNew = Gia_Truth5ToGia( p, pVarLits, Vec_IntSize(vSupp), (unsigned)Truth, 1 ); + else + iLitNew = Gia_Truth6ToGia( p, pVarLits, Vec_IntSize(vSupp), Truth, 1 ); + Gia_ManAppendCo( p, iLitNew ); + TruthNew = Gia_LutComputeTruth6Map( p, Gia_ManCoNum(p)-1, vMap ); + Vec_IntForEachEntry( vSupp, ObjId, k ) + { + int CioId = Gia_ObjCioId(Gia_ManObj(p, ObjId)); + Vec_IntWriteEntry( vMap, CioId, -1 ); + } + if ( Truth != TruthNew ) + printf( "Error for output %d.\n", i ); + Count++; + //Dau_DsdPrintFromTruth( &Truth, Vec_IntSize(vSupp) ); + } + } + Gia_ManHashStop( p ); + printf( "Finished processing %d outputs.\n", Count ); + Vec_IntFree( vSupp ); + Vec_IntFree( vMap ); +} + +/**Function************************************************************* + + Synopsis [Compute truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word Gia_LutComputeTruth6_rec( Gia_Man_t * p, int iNode, Vec_Wrd_t * vTruths ) +{ + Gia_Obj_t * pObj; + word Truth0, Truth1; + if ( Gia_ObjIsTravIdCurrentId(p, iNode) ) + return Vec_WrdEntry(vTruths, iNode); + Gia_ObjSetTravIdCurrentId(p, iNode); + pObj = Gia_ManObj( p, iNode ); + assert( Gia_ObjIsAnd(pObj) ); + Truth0 = Gia_LutComputeTruth6_rec( p, Gia_ObjFaninId0p(p, pObj), vTruths ); + Truth1 = Gia_LutComputeTruth6_rec( p, Gia_ObjFaninId1p(p, pObj), vTruths ); + if ( Gia_ObjFaninC0(pObj) ) + Truth0 = ~Truth0; + if ( Gia_ObjFaninC1(pObj) ) + Truth1 = ~Truth1; + Vec_WrdWriteEntry( vTruths, iNode, Truth0 & Truth1 ); + return Truth0 & Truth1; +} +word Gia_LutComputeTruth6( Gia_Man_t * p, int iObj, Vec_Wrd_t * vTruths ) +{ + int k, iFan; + assert( Gia_ObjIsLut(p, iObj) ); + Gia_ManIncrementTravId( p ); + Gia_LutForEachFanin( p, iObj, iFan, k ) + { + Vec_WrdWriteEntry( vTruths, iFan, s_Truths6[k] ); + Gia_ObjSetTravIdCurrentId( p, iFan ); + } + return Gia_LutComputeTruth6_rec( p, iObj, vTruths ); +} + +/**Function************************************************************* + + Synopsis [Computes truth table of a 6-LUT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ObjComputeTruthTable6Lut_rec( Gia_Man_t * p, int iObj, Vec_Wrd_t * vTemp ) +{ + word uTruth0, uTruth1; + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return; + Gia_ObjSetTravIdCurrentId(p, iObj); + assert( Gia_ObjIsAnd(pObj) ); + Gia_ObjComputeTruthTable6Lut_rec( p, Gia_ObjFaninId0p(p, pObj), vTemp ); + Gia_ObjComputeTruthTable6Lut_rec( p, Gia_ObjFaninId1p(p, pObj), vTemp ); + uTruth0 = Vec_WrdEntry( vTemp, Gia_ObjFaninId0p(p, pObj) ); + uTruth0 = Gia_ObjFaninC0(pObj) ? ~uTruth0 : uTruth0; + uTruth1 = Vec_WrdEntry( vTemp, Gia_ObjFaninId1p(p, pObj) ); + uTruth1 = Gia_ObjFaninC1(pObj) ? ~uTruth1 : uTruth1; + Vec_WrdWriteEntry( vTemp, iObj, uTruth0 & uTruth1 ); +} +word Gia_ObjComputeTruthTable6Lut( Gia_Man_t * p, int iObj, Vec_Wrd_t * vTemp ) +{ + int i, Fanin; + assert( Vec_WrdSize(vTemp) == Gia_ManObjNum(p) ); + assert( Gia_ObjIsLut(p, iObj) ); + Gia_ManIncrementTravId( p ); + Gia_LutForEachFanin( p, iObj, Fanin, i ) + { + Gia_ObjSetTravIdCurrentId( p, Fanin ); + Vec_WrdWriteEntry( vTemp, Fanin, s_Truth6[i] ); + } + assert( i <= 6 ); + Gia_ObjComputeTruthTable6Lut_rec( p, iObj, vTemp ); + return Vec_WrdEntry( vTemp, iObj ); +} + +/**Function************************************************************* + + Synopsis [Computes truth table up to 6 inputs in terms of CIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word Gia_ObjComputeTruth6( Gia_Man_t * p, int iObj, Vec_Int_t * vSupp, Vec_Wrd_t * vTemp ) +{ + int i, Fanin; + assert( Vec_WrdSize(vTemp) == Gia_ManObjNum(p) ); + assert( Vec_IntSize(vSupp) <= 6 ); + Gia_ManIncrementTravId( p ); + Vec_IntForEachEntry( vSupp, Fanin, i ) + { + Gia_ObjSetTravIdCurrentId( p, Fanin ); + Vec_WrdWriteEntry( vTemp, Fanin, s_Truth6[i] ); + } + Gia_ObjComputeTruthTable6Lut_rec( p, iObj, vTemp ); + return Vec_WrdEntry( vTemp, iObj ); +} +void Gia_ObjComputeTruth6CisSupport_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vSupp ) +{ + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return; + Gia_ObjSetTravIdCurrentId(p, iObj); + if ( Gia_ObjIsCi(pObj) ) + { + Vec_IntPushOrder( vSupp, iObj ); + return; + } + assert( Gia_ObjIsAnd(pObj) ); + Gia_ObjComputeTruth6CisSupport_rec( p, Gia_ObjFaninId0p(p, pObj), vSupp ); + Gia_ObjComputeTruth6CisSupport_rec( p, Gia_ObjFaninId1p(p, pObj), vSupp ); +} +word Gia_ObjComputeTruth6Cis( Gia_Man_t * p, int iLit, Vec_Int_t * vSupp, Vec_Wrd_t * vTemp ) +{ + int iObj = Abc_Lit2Var(iLit); + Vec_IntClear( vSupp ); + if ( !iObj ) return Abc_LitIsCompl(iLit) ? ~(word)0 : (word)0; + Gia_ManIncrementTravId( p ); + Gia_ObjComputeTruth6CisSupport_rec( p, iObj, vSupp ); + if ( Vec_IntSize(vSupp) > 6 ) + return 0; + Gia_ObjComputeTruth6( p, iObj, vSupp, vTemp ); + return Abc_LitIsCompl(iLit) ? ~Vec_WrdEntry(vTemp, iObj) : Vec_WrdEntry(vTemp, iObj); +} + +/**Function************************************************************* + + Synopsis [Computes truth table up to 6 inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ObjComputeTruthTable6_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Wrd_t * vTruths ) +{ + word uTruth0, uTruth1; + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + assert( !pObj->fMark0 ); + assert( Gia_ObjIsAnd(pObj) ); + Gia_ObjComputeTruthTable6_rec( p, Gia_ObjFanin0(pObj), vTruths ); + Gia_ObjComputeTruthTable6_rec( p, Gia_ObjFanin1(pObj), vTruths ); + uTruth0 = Vec_WrdEntry( vTruths, Gia_ObjFanin0(pObj)->Value ); + uTruth0 = Gia_ObjFaninC0(pObj) ? ~uTruth0 : uTruth0; + uTruth1 = Vec_WrdEntry( vTruths, Gia_ObjFanin1(pObj)->Value ); + uTruth1 = Gia_ObjFaninC1(pObj) ? ~uTruth1 : uTruth1; + pObj->Value = Vec_WrdSize(vTruths); + Vec_WrdPush( vTruths, uTruth0 & uTruth1 ); +} +word Gia_ObjComputeTruthTable6( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vSupp, Vec_Wrd_t * vTruths ) +{ + Gia_Obj_t * pLeaf; + int i; + assert( Vec_IntSize(vSupp) <= 6 ); + assert( Gia_ObjIsAnd(pObj) ); + assert( !pObj->fMark0 ); + Vec_WrdClear( vTruths ); + Gia_ManIncrementTravId( p ); + Gia_ManForEachObjVec( vSupp, p, pLeaf, i ) + { + assert( pLeaf->fMark0 || Gia_ObjIsRo(p, pLeaf) ); + pLeaf->Value = Vec_WrdSize(vTruths); + Vec_WrdPush( vTruths, s_Truth6[i] ); + Gia_ObjSetTravIdCurrent(p, pLeaf); + } + Gia_ObjComputeTruthTable6_rec( p, pObj, vTruths ); + return Vec_WrdEntryLast( vTruths ); +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes reachable from the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ObjCollectInternal_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( !Gia_ObjIsAnd(pObj) ) + return; + if ( pObj->fMark0 ) + return; + pObj->fMark0 = 1; + Gia_ObjCollectInternal_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ObjCollectInternal_rec( p, Gia_ObjFanin1(pObj) ); + Gia_ObjSetNum( p, pObj, Vec_IntSize(p->vTtNodes) ); + Vec_IntPush( p->vTtNodes, Gia_ObjId(p, pObj) ); +} +void Gia_ObjCollectInternal( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + Vec_IntClear( p->vTtNodes ); + Gia_ObjCollectInternal_rec( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Computing the truth table for GIA object.] + + Description [The truth table should be used by the calling application + (or saved into the user's storage) before this procedure is called again.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word * Gia_ObjComputeTruthTable( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + Gia_Obj_t * pTemp, * pRoot; + word * pTruth, * pTruthL, * pTruth0, * pTruth1; + int i; + if ( p->vTtMemory == NULL ) + { + p->nTtVars = Gia_ManPiNum( p ); + p->nTtWords = Abc_Truth6WordNum( p->nTtVars ); + p->vTtNums = Vec_IntStart( Gia_ManObjNum(p) + 1000 ); + p->vTtNodes = Vec_IntAlloc( 256 ); + p->vTtInputs = Vec_PtrAllocTruthTables( Abc_MaxInt(6, p->nTtVars) ); + p->vTtMemory = Vec_WrdStart( p->nTtWords * 256 ); + } + else + { + // make sure the number of primary inputs did not change + // since the truth table computation storage was prepared + assert( p->nTtVars == Gia_ManPiNum(p) ); + } + // extend ID numbers + if ( Vec_IntSize(p->vTtNums) < Gia_ManObjNum(p) ) + Vec_IntFillExtra( p->vTtNums, Gia_ManObjNum(p), 0 ); + // collect internal nodes + pRoot = Gia_ObjIsCo(pObj) ? Gia_ObjFanin0(pObj) : pObj; + Gia_ObjCollectInternal( p, pRoot ); + // extend TT storage + if ( Vec_WrdSize(p->vTtMemory) < p->nTtWords * (Vec_IntSize(p->vTtNodes) + 2) ) + Vec_WrdFillExtra( p->vTtMemory, p->nTtWords * (Vec_IntSize(p->vTtNodes) + 2), 0 ); + // compute the truth table for internal nodes + Gia_ManForEachObjVec( p->vTtNodes, p, pTemp, i ) + { + pTemp->fMark0 = 0; // unmark nodes marked by Gia_ObjCollectInternal() + pTruth = Gla_ObjTruthNode(p, pTemp); + pTruthL = pTruth + p->nTtWords; + pTruth0 = Gia_ObjIsAnd(Gia_ObjFanin0(pTemp)) ? Gla_ObjTruthNode(p, Gia_ObjFanin0(pTemp)) : Gla_ObjTruthElem(p, Gia_ObjCioId(Gia_ObjFanin0(pTemp)) ); + pTruth1 = Gia_ObjIsAnd(Gia_ObjFanin1(pTemp)) ? Gla_ObjTruthNode(p, Gia_ObjFanin1(pTemp)) : Gla_ObjTruthElem(p, Gia_ObjCioId(Gia_ObjFanin1(pTemp)) ); + if ( Gia_ObjFaninC0(pTemp) ) + { + if ( Gia_ObjFaninC1(pTemp) ) + while ( pTruth < pTruthL ) + *pTruth++ = ~*pTruth0++ & ~*pTruth1++; + else + while ( pTruth < pTruthL ) + *pTruth++ = ~*pTruth0++ & *pTruth1++; + } + else + { + if ( Gia_ObjFaninC1(pTemp) ) + while ( pTruth < pTruthL ) + *pTruth++ = *pTruth0++ & ~*pTruth1++; + else + while ( pTruth < pTruthL ) + *pTruth++ = *pTruth0++ & *pTruth1++; + } + } + // compute the final table + if ( Gia_ObjIsConst0(pRoot) ) + pTruth = Gla_ObjTruthConst0( p, Gla_ObjTruthFree1(p) ); + else if ( Gia_ObjIsPi(p, pRoot) ) + pTruth = Gla_ObjTruthElem( p, Gia_ObjCioId(pRoot) ); + else if ( Gia_ObjIsAnd(pRoot) ) + pTruth = Gla_ObjTruthNode( p, pRoot ); + else + pTruth = NULL; + return Gla_ObjTruthDup( p, Gla_ObjTruthFree2(p), pTruth, Gia_ObjIsCo(pObj) && Gia_ObjFaninC0(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Testing truth table computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ObjComputeTruthTableTest( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + unsigned * pTruth; + abctime clk = Abc_Clock(); + int i; + Gia_ManForEachPo( p, pObj, i ) + { + pTruth = (unsigned *)Gia_ObjComputeTruthTable( p, pObj ); +// Extra_PrintHex( stdout, pTruth, Gia_ManPiNum(p) ); printf( "\n" ); + } + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ObjComputeTruthTableStart( Gia_Man_t * p, int nVarsMax ) +{ + assert( p->vTtMemory == NULL ); + p->nTtVars = nVarsMax; + p->nTtWords = Abc_Truth6WordNum( p->nTtVars ); + p->vTtNodes = Vec_IntAlloc( 256 ); + p->vTtInputs = Vec_PtrAllocTruthTables( Abc_MaxInt(6, p->nTtVars) ); + p->vTtMemory = Vec_WrdStart( p->nTtWords * 64 ); + p->vTtNums = Vec_IntAlloc( Gia_ManObjNum(p) + 1000 ); + Vec_IntFill( p->vTtNums, Vec_IntCap(p->vTtNums), -ABC_INFINITY ); + if ( nVarsMax >= 6 ) { + word * pTruth; int i; + Vec_PtrForEachEntry( word *, p->vTtInputs, pTruth, i ) + Abc_TtFlipVar5( pTruth, nVarsMax ); + } +} +void Gia_ObjComputeTruthTableStop( Gia_Man_t * p ) +{ + p->nTtVars = 0; + p->nTtWords = 0; + Vec_IntFreeP( &p->vTtNums ); + Vec_IntFreeP( &p->vTtNodes ); + Vec_PtrFreeP( &p->vTtInputs ); + Vec_WrdFreeP( &p->vTtMemory ); +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes reachable from the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ObjCollectInternalCut_rec( Gia_Man_t * p, int iObj ) +{ + if ( Gia_ObjHasNumId(p, iObj) ) + return; + assert( Gia_ObjIsAnd(Gia_ManObj(p, iObj)) ); + Gia_ObjCollectInternalCut_rec( p, Gia_ObjFaninId0(Gia_ManObj(p, iObj), iObj) ); + Gia_ObjCollectInternalCut_rec( p, Gia_ObjFaninId1(Gia_ManObj(p, iObj), iObj) ); + Gia_ObjSetNumId( p, iObj, Vec_IntSize(p->vTtNodes) ); + Vec_IntPush( p->vTtNodes, iObj ); +} +void Gia_ObjCollectInternalCut( Gia_Man_t * p, int iRoot, Vec_Int_t * vLeaves ) +{ + int i, iObj; + assert( !Gia_ObjHasNumId(p, iRoot) ); + assert( Gia_ObjIsAnd(Gia_ManObj(p, iRoot)) ); + Vec_IntForEachEntry( vLeaves, iObj, i ) + { + if ( Gia_ObjHasNumId(p, iObj) ) // if cuts have repeated variables, skip + continue; + assert( !Gia_ObjHasNumId(p, iObj) ); + Gia_ObjSetNumId( p, iObj, -i ); + } + assert( !Gia_ObjHasNumId(p, iRoot) ); // the root cannot be one of the leaves + Vec_IntClear( p->vTtNodes ); + Vec_IntPush( p->vTtNodes, -1 ); + Gia_ObjCollectInternalCut_rec( p, iRoot ); +} + +/**Function************************************************************* + + Synopsis [Computes the truth table of pRoot in terms of leaves.] + + Description [The root cannot be one of the leaves.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word * Gia_ObjComputeTruthTableCut( Gia_Man_t * p, Gia_Obj_t * pRoot, Vec_Int_t * vLeaves ) +{ + Gia_Obj_t * pTemp; + word * pTruth, * pTruthL, * pTruth0, * pTruth1; + int i, iObj, Id0, Id1, Index = Vec_IntFind(vLeaves, Gia_ObjId(p, pRoot)); + assert( p->vTtMemory != NULL ); + assert( Vec_IntSize(vLeaves) <= p->nTtVars ); + if ( Index >= 0 ) + return Gla_ObjTruthElem( p, Index ); + if ( Gia_ObjIsConst0(pRoot) ) + { + if ( Vec_WrdSize(p->vTtMemory) < p->nTtWords ) + Vec_WrdFillExtra( p->vTtMemory, p->nTtWords, 0 ); + return Gla_ObjTruthConst0( p, Gla_ObjTruthFree1(p) ); + } + assert( Gia_ObjIsAnd(pRoot) ); + // extend ID numbers + if ( Vec_IntSize(p->vTtNums) < Gia_ManObjNum(p) ) + Vec_IntFillExtra( p->vTtNums, Gia_ManObjNum(p), -ABC_INFINITY ); + // collect internal nodes + Gia_ObjCollectInternalCut( p, Gia_ObjId(p, pRoot), vLeaves ); + // extend TT storage + if ( Vec_WrdSize(p->vTtMemory) < p->nTtWords * (Vec_IntSize(p->vTtNodes) + 2) ) + Vec_WrdFillExtra( p->vTtMemory, p->nTtWords * (Vec_IntSize(p->vTtNodes) + 2), 0 ); + // compute the truth table for internal nodes + Vec_IntForEachEntryStart( p->vTtNodes, iObj, i, 1 ) + { + assert( i == Gia_ObjNumId(p, iObj) ); + pTemp = Gia_ManObj( p, iObj ); + pTruth = Gla_ObjTruthNodeId( p, i ); + pTruthL = pTruth + p->nTtWords; + Id0 = Gia_ObjNumId( p, Gia_ObjFaninId0(pTemp, iObj) ); + Id1 = Gia_ObjNumId( p, Gia_ObjFaninId1(pTemp, iObj) ); + pTruth0 = (Id0 > 0) ? Gla_ObjTruthNodeId(p, Id0) : Gla_ObjTruthElem(p, -Id0); + pTruth1 = (Id1 > 0) ? Gla_ObjTruthNodeId(p, Id1) : Gla_ObjTruthElem(p, -Id1); + if ( Gia_ObjFaninC0(pTemp) ) + { + if ( Gia_ObjFaninC1(pTemp) ) + while ( pTruth < pTruthL ) + *pTruth++ = ~*pTruth0++ & ~*pTruth1++; + else + while ( pTruth < pTruthL ) + *pTruth++ = ~*pTruth0++ & *pTruth1++; + } + else + { + if ( Gia_ObjFaninC1(pTemp) ) + while ( pTruth < pTruthL ) + *pTruth++ = *pTruth0++ & ~*pTruth1++; + else + while ( pTruth < pTruthL ) + *pTruth++ = *pTruth0++ & *pTruth1++; + } + } + pTruth = Gla_ObjTruthNode( p, pRoot ); + // unmark leaves marked by Gia_ObjCollectInternal() + Vec_IntForEachEntry( vLeaves, iObj, i ) + Gia_ObjResetNumId( p, iObj ); + Vec_IntForEachEntryStart( p->vTtNodes, iObj, i, 1 ) + Gia_ObjResetNumId( p, iObj ); + return pTruth; +} + +/**Function************************************************************* + + Synopsis [Reduces GIA to contain isomorphic POs.] + + Description [The root cannot be one of the leaves.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManIsoNpnReduce( Gia_Man_t * p, Vec_Ptr_t ** pvPosEquivs, int fVerbose ) +{ + char pCanonPerm[16]; + int i, iObj, uCanonPhase, nVars, lastId, truthId; + int IndexCon = -1, IndexVar = -1; + Vec_Wec_t * vPosEquivs = Vec_WecAlloc( 100 ); + word * pTruth; + Gia_Obj_t * pObj; + Vec_Mem_t * vTtMem[17]; // truth table memory and hash table + Gia_Man_t * pNew = NULL; + Vec_Int_t * vLeaves = Vec_IntAlloc( 16 ); + Vec_Int_t * vFirsts; + Vec_Int_t * vTt2Class[17]; + for ( i = 0; i < 17; i++ ) + { + vTtMem[i] = Vec_MemAlloc( Abc_TtWordNum(i), 10 ); + Vec_MemHashAlloc( vTtMem[i], 1000 ); + vTt2Class[i] = Vec_IntStartFull( Gia_ManCoNum(p)+1 ); + } + Gia_ObjComputeTruthTableStart( p, 16 ); + Gia_ManForEachPo( p, pObj, i ) + { + iObj = Gia_ObjId(p, pObj); + Gia_ManCollectCis( p, &iObj, 1, vLeaves ); + if ( Vec_IntSize(vLeaves) > 16 ) + { + Vec_IntPush( Vec_WecPushLevel(vPosEquivs), i ); + continue; + } + pObj = Gia_ObjFanin0(pObj); + if ( Gia_ObjIsConst0(pObj) ) + { + if ( IndexCon == -1 ) + { + IndexCon = Vec_WecSize(vPosEquivs); + Vec_WecPushLevel(vPosEquivs); + } + Vec_WecPush( vPosEquivs, IndexCon, i ); + continue; + } + if ( Gia_ObjIsCi(pObj) ) + { + if ( IndexVar == -1 ) + { + IndexVar = Vec_WecSize(vPosEquivs); + Vec_WecPushLevel(vPosEquivs); + } + Vec_WecPush( vPosEquivs, IndexVar, i ); + continue; + } + assert( Gia_ObjIsAnd(pObj) ); + pTruth = Gia_ObjComputeTruthTableCut( p, pObj, vLeaves ); + Abc_TtMinimumBase( pTruth, NULL, Vec_IntSize(vLeaves), &nVars ); + if ( nVars == 0 ) + { + if ( IndexCon == -1 ) + { + IndexCon = Vec_WecSize(vPosEquivs); + Vec_WecPushLevel(vPosEquivs); + } + Vec_WecPush( vPosEquivs, IndexCon, i ); + continue; + } + if ( nVars == 1 ) + { + if ( IndexVar == -1 ) + { + IndexVar = Vec_WecSize(vPosEquivs); + Vec_WecPushLevel(vPosEquivs); + } + Vec_WecPush( vPosEquivs, IndexVar, i ); + continue; + } + uCanonPhase = Abc_TtCanonicize( pTruth, nVars, pCanonPerm ); + lastId = Vec_MemEntryNum( vTtMem[nVars] ); + truthId = Vec_MemHashInsert( vTtMem[nVars], pTruth ); + if ( lastId != Vec_MemEntryNum( vTtMem[nVars] ) ) // new one + { + assert( Vec_IntEntry(vTt2Class[nVars], truthId) == -1 ); + Vec_IntWriteEntry( vTt2Class[nVars], truthId, Vec_WecSize(vPosEquivs) ); + Vec_WecPushLevel(vPosEquivs); + } + assert( Vec_IntEntry(vTt2Class[nVars], truthId) >= 0 ); + Vec_WecPush( vPosEquivs, Vec_IntEntry(vTt2Class[nVars], truthId), i ); + } + Gia_ObjComputeTruthTableStop( p ); + Vec_IntFree( vLeaves ); + for ( i = 0; i < 17; i++ ) + { + Vec_MemHashFree( vTtMem[i] ); + Vec_MemFree( vTtMem[i] ); + Vec_IntFree( vTt2Class[i] ); + } + + // find the first outputs and derive GIA + vFirsts = Vec_WecCollectFirsts( vPosEquivs ); + pNew = Gia_ManDupCones( p, Vec_IntArray(vFirsts), Vec_IntSize(vFirsts), 0 ); + Vec_IntFree( vFirsts ); + // report and return + if ( fVerbose ) + { + printf( "Nontrivial classes:\n" ); + Vec_WecPrint( vPosEquivs, 1 ); + } + if ( pvPosEquivs ) + *pvPosEquivs = Vec_WecConvertToVecPtr( vPosEquivs ); + Vec_WecFree( vPosEquivs ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaTsim.c b/yosys/abc/src/aig/gia/giaTsim.c new file mode 100644 index 00000000000..7f93c5426d1 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaTsim.c @@ -0,0 +1,757 @@ +/**CFile**************************************************************** + + FileName [giaTsim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Ternary simulation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaTsim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Gia_ManTerSimInfoGet( unsigned * pInfo, int i ) +{ + return 3 & (pInfo[i >> 4] >> ((i & 15) << 1)); +} +static inline void Gia_ManTerSimInfoSet( unsigned * pInfo, int i, int Value ) +{ + assert( Value >= GIA_ZER && Value <= GIA_UND ); + Value ^= Gia_ManTerSimInfoGet( pInfo, i ); + pInfo[i >> 4] ^= (Value << ((i & 15) << 1)); +} + +static inline unsigned * Gia_ManTerStateNext( unsigned * pState, int nWords ) { return *((unsigned **)(pState + nWords)); } +static inline void Gia_ManTerStateSetNext( unsigned * pState, int nWords, unsigned * pNext ) { *((unsigned **)(pState + nWords)) = pNext; } + +// ternary simulation manager +typedef struct Gia_ManTer_t_ Gia_ManTer_t; +struct Gia_ManTer_t_ +{ + Gia_Man_t * pAig; + int nIters; + int nStateWords; + Vec_Ptr_t * vStates; + Vec_Ptr_t * vFlops; + Vec_Int_t * vRetired; // retired registers + char * pRetired; // retired registers + int * pCount0; + int * pCountX; + // hash table for states + int nBins; + unsigned ** pBins; + // simulation information + unsigned * pDataSim; // simulation data + unsigned * pDataSimCis; // simulation data for CIs + unsigned * pDataSimCos; // simulation data for COs +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_ManTer_t * Gia_ManTerCreate( Gia_Man_t * pAig ) +{ + Gia_ManTer_t * p; + p = ABC_CALLOC( Gia_ManTer_t, 1 ); + p->pAig = Gia_ManFront( pAig ); + p->nIters = 300; + p->pDataSim = ABC_ALLOC( unsigned, Abc_BitWordNum(2*p->pAig->nFront) ); + p->pDataSimCis = ABC_ALLOC( unsigned, Abc_BitWordNum(2*Gia_ManCiNum(p->pAig)) ); + p->pDataSimCos = ABC_ALLOC( unsigned, Abc_BitWordNum(2*Gia_ManCoNum(p->pAig)) ); + // allocate storage for terminary states + p->nStateWords = Abc_BitWordNum( 2*Gia_ManRegNum(pAig) ); + p->vStates = Vec_PtrAlloc( 1000 ); + p->pCount0 = ABC_CALLOC( int, Gia_ManRegNum(pAig) ); + p->pCountX = ABC_CALLOC( int, Gia_ManRegNum(pAig) ); + p->nBins = Abc_PrimeCudd( 500 ); + p->pBins = ABC_CALLOC( unsigned *, p->nBins ); + p->vRetired = Vec_IntAlloc( 100 ); + p->pRetired = ABC_CALLOC( char, Gia_ManRegNum(pAig) ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManTerStatesFree( Vec_Ptr_t * vStates ) +{ + unsigned * pTemp; + int i; + Vec_PtrForEachEntry( unsigned *, vStates, pTemp, i ) + ABC_FREE( pTemp ); + Vec_PtrFree( vStates ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManTerDelete( Gia_ManTer_t * p ) +{ + if ( p->vStates ) + Gia_ManTerStatesFree( p->vStates ); + if ( p->vFlops ) + Gia_ManTerStatesFree( p->vFlops ); + Gia_ManStop( p->pAig ); + Vec_IntFree( p->vRetired ); + ABC_FREE( p->pRetired ); + ABC_FREE( p->pCount0 ); + ABC_FREE( p->pCountX ); + ABC_FREE( p->pBins ); + ABC_FREE( p->pDataSim ); + ABC_FREE( p->pDataSimCis ); + ABC_FREE( p->pDataSimCos ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManTerSimulateCi( Gia_ManTer_t * p, Gia_Obj_t * pObj, int iCi ) +{ + Gia_ManTerSimInfoSet( p->pDataSim, Gia_ObjValue(pObj), Gia_ManTerSimInfoGet(p->pDataSimCis, iCi) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManTerSimulateCo( Gia_ManTer_t * p, int iCo, Gia_Obj_t * pObj ) +{ + int Value = Gia_ManTerSimInfoGet( p->pDataSim, Gia_ObjDiff0(pObj) ); + Gia_ManTerSimInfoSet( p->pDataSimCos, iCo, Gia_XsimNotCond( Value, Gia_ObjFaninC0(pObj) ) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManTerSimulateNode( Gia_ManTer_t * p, Gia_Obj_t * pObj ) +{ + int Value0 = Gia_ManTerSimInfoGet( p->pDataSim, Gia_ObjDiff0(pObj) ); + int Value1 = Gia_ManTerSimInfoGet( p->pDataSim, Gia_ObjDiff1(pObj) ); + Gia_ManTerSimInfoSet( p->pDataSim, Gia_ObjValue(pObj), Gia_XsimAndCond( Value0, Gia_ObjFaninC0(pObj), Value1, Gia_ObjFaninC1(pObj) ) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManTerSimInfoInit( Gia_ManTer_t * p ) +{ + int i = 0; + for ( ; i < Gia_ManPiNum(p->pAig); i++ ) + Gia_ManTerSimInfoSet( p->pDataSimCis, i, GIA_UND ); + for ( ; i < Gia_ManCiNum(p->pAig); i++ ) + Gia_ManTerSimInfoSet( p->pDataSimCis, i, GIA_ZER ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManTerSimInfoTransfer( Gia_ManTer_t * p ) +{ + int i = 0; + for ( ; i < Gia_ManPiNum(p->pAig); i++ ) + Gia_ManTerSimInfoSet( p->pDataSimCis, i, GIA_UND ); + for ( ; i < Gia_ManCiNum(p->pAig); i++ ) + Gia_ManTerSimInfoSet( p->pDataSimCis, i, Gia_ManTerSimInfoGet( p->pDataSimCos, Gia_ManCoNum(p->pAig)-Gia_ManCiNum(p->pAig)+i ) ); +} + + +/**Function************************************************************* + + Synopsis [Computes hash value of the node using its simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManTerStateHash( unsigned * pState, int nWords, int nTableSize ) +{ + static int s_FPrimes[128] = { + 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, + 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, + 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, + 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, + 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, + 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, + 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, + 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, + 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, + 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, + 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, + 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, + 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 + }; + unsigned uHash; + int i; + uHash = 0; + for ( i = 0; i < nWords; i++ ) + uHash ^= pState[i] * s_FPrimes[i & 0x7F]; + return uHash % nTableSize; +} + +/**Function************************************************************* + + Synopsis [Inserts value into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Gia_ManTerStateLookup( unsigned * pState, int nWords, unsigned ** pBins, int nBins ) +{ + unsigned * pEntry; + int Hash = Gia_ManTerStateHash( pState, nWords, nBins ); + for ( pEntry = pBins[Hash]; pEntry; pEntry = Gia_ManTerStateNext(pEntry, nWords) ) + if ( !memcmp( pEntry, pState, sizeof(unsigned) * nWords ) ) + return pEntry; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Inserts value into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManTerStateInsert( unsigned * pState, int nWords, unsigned ** pBins, int nBins ) +{ + int Hash = Gia_ManTerStateHash( pState, nWords, nBins ); + assert( !Gia_ManTerStateLookup( pState, nWords, pBins, nBins ) ); + Gia_ManTerStateSetNext( pState, nWords, pBins[Hash] ); + pBins[Hash] = pState; +} + +/**Function************************************************************* + + Synopsis [Allocs new ternary state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Gia_ManTerStateAlloc( int nWords ) +{ + return (unsigned *)ABC_CALLOC( char, sizeof(unsigned) * nWords + sizeof(unsigned *) ); +} + +/**Function************************************************************* + + Synopsis [Creates new ternary state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Gia_ManTerStateCreate( Gia_ManTer_t * p ) +{ + int i, Value, nPis = Gia_ManPiNum(p->pAig); + unsigned * pRes = Gia_ManTerStateAlloc( p->nStateWords ); + for ( i = nPis; i < Gia_ManCiNum(p->pAig); i++ ) + { + Value = Gia_ManTerSimInfoGet( p->pDataSimCis, i ); + Gia_ManTerSimInfoSet( pRes, i-nPis, Value ); + if ( Value == GIA_ZER ) + p->pCount0[i-nPis]++; + if ( Value == GIA_UND ) + p->pCountX[i-nPis]++; + } + Vec_PtrPush( p->vStates, pRes ); + return pRes; +} + +/**Function************************************************************* + + Synopsis [Performs one round of ternary simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManTerSimulateRound( Gia_ManTer_t * p ) +{ + Gia_Obj_t * pObj; + int i, iCis = 0, iCos = 0; + assert( p->pAig->nFront > 0 ); + assert( Gia_ManConst0(p->pAig)->Value == 0 ); + Gia_ManTerSimInfoSet( p->pDataSim, 0, GIA_ZER ); + Gia_ManForEachObj1( p->pAig, pObj, i ) + { + if ( Gia_ObjIsAndOrConst0(pObj) ) + { + assert( Gia_ObjValue(pObj) < p->pAig->nFront ); + Gia_ManTerSimulateNode( p, pObj ); + } + else if ( Gia_ObjIsCi(pObj) ) + { + assert( Gia_ObjValue(pObj) < p->pAig->nFront ); + Gia_ManTerSimulateCi( p, pObj, iCis++ ); + } + else // if ( Gia_ObjIsCo(pObj) ) + { + assert( Gia_ObjValue(pObj) == GIA_NONE ); + Gia_ManTerSimulateCo( p, iCos++, pObj ); + } + } + assert( Gia_ManCiNum(p->pAig) == iCis ); + assert( Gia_ManCoNum(p->pAig) == iCos ); +} + +/**Function************************************************************* + + Synopsis [Retires a set of registers to speed up convergence.] + + Description [Retire all non-ternary registers which has max number + of ternary values so far.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManTerRetire2( Gia_ManTer_t * p, unsigned * pState ) +{ + int i, Entry, iMaxTerValue = -1; + // find non-retired register with this value + for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) + if ( Gia_ManTerSimInfoGet( pState, i ) != GIA_UND && !p->pRetired[i] && iMaxTerValue < p->pCountX[i] ) + iMaxTerValue = p->pCountX[i]; + assert( iMaxTerValue >= 0 ); + // retire the first registers with this value + for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) + if ( Gia_ManTerSimInfoGet( pState, i ) != GIA_UND && !p->pRetired[i] && iMaxTerValue == p->pCountX[i] ) + { + assert( p->pRetired[i] == 0 ); + p->pRetired[i] = 1; + Vec_IntPush( p->vRetired, i ); + if ( iMaxTerValue == 0 ) + break; + } + // update all the retired registers + Vec_IntForEachEntry( p->vRetired, Entry, i ) + Gia_ManTerSimInfoSet( p->pDataSimCis, Gia_ManPiNum(p->pAig)+Entry, GIA_UND ); + return Vec_IntSize(p->vRetired); +} + +/**Function************************************************************* + + Synopsis [Retires a set of registers to speed up convergence.] + + Description [Retire all non-ternary registers which has max number + of ternary values so far.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManTerRetire( Gia_ManTer_t * p, unsigned * pThis, unsigned * pPrev ) +{ + int i, Entry; + // find registers whose value has changed + Vec_IntClear( p->vRetired ); + for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) + if ( Gia_ManTerSimInfoGet( pThis, i ) != Gia_ManTerSimInfoGet( pPrev, i ) ) + Vec_IntPush( p->vRetired, i ); + // set all of them to zero + Vec_IntForEachEntry( p->vRetired, Entry, i ) + Gia_ManTerSimInfoSet( p->pDataSimCis, Gia_ManPiNum(p->pAig)+Entry, GIA_UND ); + return Vec_IntSize(p->vRetired); +} + +/**Function************************************************************* + + Synopsis [Inserts value into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManTerStatePrint( unsigned * pState, int nRegs, int iNum ) +{ + int i, nZeros = 0, nOnes = 0, nDcs = 0; + printf( " %4d : ", iNum ); + for ( i = 0; i < nRegs; i++ ) + { + if ( Gia_ManTerSimInfoGet(pState, i) == GIA_ZER ) + printf( "0" ), nZeros++; + else if ( Gia_ManTerSimInfoGet(pState, i) == GIA_ONE ) + printf( "1" ), nOnes++; + else if ( Gia_ManTerSimInfoGet(pState, i) == GIA_UND ) + printf( "x" ), nDcs++; + else + assert( 0 ); + } + printf( " (0=%4d, 1=%4d, x=%4d)\n", nZeros, nOnes, nDcs ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManTerAnalyze2( Vec_Ptr_t * vStates, int nRegs ) +{ + unsigned * pTemp, * pStates = (unsigned *)Vec_PtrPop( vStates ); + int i, w, nZeros, nConsts, nStateWords; + // detect constant zero registers + nStateWords = Abc_BitWordNum( 2*nRegs ); + memset( pStates, 0, sizeof(int) * nStateWords ); + Vec_PtrForEachEntry( unsigned *, vStates, pTemp, i ) + for ( w = 0; w < nStateWords; w++ ) + pStates[w] |= pTemp[w]; + // count the number of zeros + nZeros = 0; + for ( i = 0; i < nRegs; i++ ) + if ( Gia_ManTerSimInfoGet(pStates, i) == GIA_ZER ) + nZeros++; + printf( "Found %d constant registers.\n", nZeros ); + // detect non-ternary registers + memset( pStates, 0, sizeof(int) * nStateWords ); + Vec_PtrForEachEntry( unsigned *, vStates, pTemp, i ) + for ( w = 0; w < nStateWords; w++ ) + pStates[w] |= (~(pTemp[w] ^ (pTemp[w] >> 1)) & 0x55555555); + // count the nonternary registers + nConsts = 0; + for ( i = 0; i < nRegs; i++ ) + if ( Gia_ManTerSimInfoGet(pStates, i) == 0 ) + nConsts++; + printf( "Found %d non-ternary registers.\n", nConsts ); + // return the state back + Vec_PtrPush( vStates, pStates ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManTerAnalyze( Gia_ManTer_t * p ) +{ + int i, nZeros = 0, nConsts = 0; + for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) + if ( p->pCount0[i] == Vec_PtrSize(p->vStates) ) + nZeros++; + else if ( p->pCountX[i] == 0 ) + nConsts++; +// printf( "Found %d constant registers.\n", nZeros ); +// printf( "Found %d non-ternary registers.\n", nConsts ); +} + + + +/**Function************************************************************* + + Synopsis [Transposes state vector for non-ternary registers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Gia_ManTerTranspose( Gia_ManTer_t * p ) +{ + Vec_Ptr_t * vFlops; + unsigned * pState, * pFlop; + int i, k, nFlopWords; + vFlops = Vec_PtrAlloc( 100 ); + nFlopWords = Abc_BitWordNum( 2*Vec_PtrSize(p->vStates) ); + for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) + { + if ( p->pCount0[i] == Vec_PtrSize(p->vStates) ) + continue; + if ( p->pCountX[i] > 0 ) + continue; + pFlop = Gia_ManTerStateAlloc( nFlopWords ); + Vec_PtrPush( vFlops, pFlop ); + Vec_PtrForEachEntry( unsigned *, p->vStates, pState, k ) + Gia_ManTerSimInfoSet( pFlop, k, Gia_ManTerSimInfoGet(pState, i) ); +//Gia_ManTerStatePrint( pFlop, Vec_PtrSize(p->vStates), i ); + } + return vFlops; +} + +/**Function************************************************************* + + Synopsis [Transposes state vector for non-ternary registers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManFindEqualFlop( Vec_Ptr_t * vFlops, int iFlop, int nFlopWords ) +{ + unsigned * pFlop, * pTemp; + int i; + pFlop = (unsigned *)Vec_PtrEntry( vFlops, iFlop ); + Vec_PtrForEachEntryStop( unsigned *, vFlops, pTemp, i, iFlop ) + if ( !memcmp( pTemp, pFlop, sizeof(unsigned) * nFlopWords ) ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Creates map of registers to replace.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Gia_ManTerCreateMap( Gia_ManTer_t * p, int fVerbose ) +{ + int * pCi2Lit; + Gia_Obj_t * pObj; + Vec_Int_t * vMapKtoI; + int i, iRepr, nFlopWords, Counter0 = 0, CounterE = 0; + nFlopWords = Abc_BitWordNum( 2*Vec_PtrSize(p->vStates) ); + p->vFlops = Gia_ManTerTranspose( p ); + pCi2Lit = ABC_FALLOC( int, Gia_ManCiNum(p->pAig) ); + vMapKtoI = Vec_IntAlloc( 100 ); + for ( i = 0; i < Gia_ManRegNum(p->pAig); i++ ) + if ( p->pCount0[i] == Vec_PtrSize(p->vStates) ) + pCi2Lit[Gia_ManPiNum(p->pAig)+i] = 0, Counter0++; + else if ( p->pCountX[i] == 0 ) + { + iRepr = Gia_ManFindEqualFlop( p->vFlops, Vec_IntSize(vMapKtoI), nFlopWords ); + Vec_IntPush( vMapKtoI, i ); + if ( iRepr < 0 ) + continue; + pObj = Gia_ManCi( p->pAig, Gia_ManPiNum(p->pAig)+Vec_IntEntry(vMapKtoI, iRepr) ); + pCi2Lit[Gia_ManPiNum(p->pAig)+i] = Abc_Var2Lit( Gia_ObjId( p->pAig, pObj ), 0 ); + CounterE++; + } + Vec_IntFree( vMapKtoI ); + if ( fVerbose ) + printf( "Transforming %d const and %d equiv registers.\n", Counter0, CounterE ); + return pCi2Lit; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_ManTer_t * Gia_ManTerSimulate( Gia_Man_t * pAig, int fVerbose ) +{ + Gia_ManTer_t * p; + unsigned * pState, * pPrev, * pLoop; + int i, Counter; + abctime clk, clkTotal = Abc_Clock(); + assert( Gia_ManRegNum(pAig) > 0 ); + // create manager + clk = Abc_Clock(); + p = Gia_ManTerCreate( pAig ); + if ( 0 ) + { + printf( "Obj = %8d (%8d). F = %6d. ", + pAig->nObjs, Gia_ManCiNum(pAig) + Gia_ManAndNum(pAig), p->pAig->nFront ); + printf( "AIG = %7.2f MB. F-mem = %7.2f MB. Other = %7.2f MB. ", + 12.0*Gia_ManObjNum(p->pAig)/(1<<20), + 4.0*Abc_BitWordNum(2 * p->pAig->nFront)/(1<<20), + 4.0*Abc_BitWordNum(2 * (Gia_ManCiNum(pAig) + Gia_ManCoNum(pAig)))/(1<<20) ); + ABC_PRT( "Time", Abc_Clock() - clk ); + } + // perform simulation + Gia_ManTerSimInfoInit( p ); + // hash the first state + pState = Gia_ManTerStateCreate( p ); + Gia_ManTerStateInsert( pState, p->nStateWords, p->pBins, p->nBins ); +//Gia_ManTerStatePrint( pState, Gia_ManRegNum(pAig), 0 ); + // perform simuluation till convergence + pPrev = NULL; + for ( i = 0; ; i++ ) + { + Gia_ManTerSimulateRound( p ); + Gia_ManTerSimInfoTransfer( p ); + pState = Gia_ManTerStateCreate( p ); +//Gia_ManTerStatePrint( pState, Gia_ManRegNum(pAig), i+1 ); + if ( (pLoop = Gia_ManTerStateLookup(pState, p->nStateWords, p->pBins, p->nBins)) ) + { + pAig->nTerStates = Vec_PtrSize( p->vStates ); + pAig->nTerLoop = Vec_PtrFind( p->vStates, pLoop ); + break; + } + Gia_ManTerStateInsert( pState, p->nStateWords, p->pBins, p->nBins ); + if ( i >= p->nIters && i % 10 == 0 ) + { + Counter = Gia_ManTerRetire( p, pState, pPrev ); +// Counter = Gia_ManTerRetire2( p, pState ); +// if ( fVerbose ) +// printf( "Retired %d registers.\n", Counter ); + } + pPrev = pState; + } + if ( fVerbose ) + { + printf( "Ternary simulation saturated after %d iterations. ", i+1 ); + ABC_PRT( "Time", Abc_Clock() - clkTotal ); + } + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManReduceConst( Gia_Man_t * pAig, int fVerbose ) +{ + Gia_ManTer_t * p; + Gia_Man_t * pNew = NULL; + int * pCi2Lit; + p = Gia_ManTerSimulate( pAig, fVerbose ); + Gia_ManTerAnalyze( p ); + pCi2Lit = Gia_ManTerCreateMap( p, fVerbose ); + Gia_ManTerDelete( p ); + pNew = Gia_ManDupDfsCiMap( pAig, pCi2Lit, NULL ); + ABC_FREE( pCi2Lit ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaTtopt.cpp b/yosys/abc/src/aig/gia/giaTtopt.cpp new file mode 100644 index 00000000000..7f16b0d06ae --- /dev/null +++ b/yosys/abc/src/aig/gia/giaTtopt.cpp @@ -0,0 +1,1224 @@ +/**CFile**************************************************************** + + FileName [giaTtopt.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Truth-table-based logic synthesis.] + + Author [Yukio Miyasaka] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaTtopt.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifdef _WIN32 +#ifndef __MINGW32__ +#pragma warning(disable : 4786) // warning C4786: identifier was truncated to '255' characters in the browser information +#endif +#endif + +#include +#include +#include +#include + +#include "gia.h" +#include "misc/vec/vecHash.h" + +ABC_NAMESPACE_IMPL_START + +namespace Ttopt { + +class TruthTable { +public: + static const int ww; // word width + static const int lww; // log word width + typedef std::bitset<64> bsw; + + int nInputs; + int nSize; + int nTotalSize; + int nOutputs; + std::vector t; + + std::vector > vvIndices; + std::vector > vvRedundantIndices; + std::vector vLevels; + + std::vector > savedt; + std::vector > > vvIndicesSaved; + std::vector > > vvRedundantIndicesSaved; + std::vector > vLevelsSaved; + + static const word ones[]; + static const word swapmask[]; + + TruthTable(int nInputs, int nOutputs): nInputs(nInputs), nOutputs(nOutputs) { + srand(0xABC); + if(nInputs >= lww) { + nSize = 1 << (nInputs - lww); + nTotalSize = nSize * nOutputs; + t.resize(nTotalSize); + } else { + nSize = 0; + nTotalSize = ((1 << nInputs) * nOutputs + ww - 1) / ww; + t.resize(nTotalSize); + } + vLevels.resize(nInputs); + for(int i = 0; i < nInputs; i++) { + vLevels[i] = i; + } + } + + virtual void Save(unsigned i) { + if(savedt.size() < i + 1) { + savedt.resize(i + 1); + vLevelsSaved.resize(i + 1); + } + savedt[i] = t; + vLevelsSaved[i] = vLevels; + } + + virtual void Load(unsigned i) { + assert(i < savedt.size()); + t = savedt[i]; + vLevels = vLevelsSaved[i]; + } + + virtual void SaveIndices(unsigned i) { + if(vvIndicesSaved.size() < i + 1) { + vvIndicesSaved.resize(i + 1); + vvRedundantIndicesSaved.resize(i + 1); + } + vvIndicesSaved[i] = vvIndices; + vvRedundantIndicesSaved[i] = vvRedundantIndices; + } + + virtual void LoadIndices(unsigned i) { + vvIndices = vvIndicesSaved[i]; + vvRedundantIndices = vvRedundantIndicesSaved[i]; + } + + word GetValue(int index_lev, int lev) { + assert(index_lev >= 0); + assert(nInputs - lev <= lww); + int logwidth = nInputs - lev; + int index = index_lev >> (lww - logwidth); + int pos = (index_lev % (1 << (lww - logwidth))) << logwidth; + return (t[index] >> pos) & ones[logwidth]; + } + + int IsEq(int index1, int index2, int lev, bool fCompl = false) { + assert(index1 >= 0); + assert(index2 >= 0); + int logwidth = nInputs - lev; + bool fEq = true; + if(logwidth > lww) { + int nScopeSize = 1 << (logwidth - lww); + for(int i = 0; i < nScopeSize && (fEq || fCompl); i++) { + fEq &= (t[nScopeSize * index1 + i] == t[nScopeSize * index2 + i]); + fCompl &= (t[nScopeSize * index1 + i] == ~t[nScopeSize * index2 + i]); + } + } else { + word value = GetValue(index1, lev) ^ GetValue(index2, lev); + fEq &= !value; + fCompl &= !(value ^ ones[logwidth]); + } + return 2 * fCompl + fEq; + } + + bool Imply(int index1, int index2, int lev) { + assert(index1 >= 0); + assert(index2 >= 0); + int logwidth = nInputs - lev; + if(logwidth > lww) { + int nScopeSize = 1 << (logwidth - lww); + for(int i = 0; i < nScopeSize; i++) { + if(t[nScopeSize * index1 + i] & ~t[nScopeSize * index2 + i]) { + return false; + } + } + return true; + } + return !(GetValue(index1, lev) & (GetValue(index2, lev) ^ ones[logwidth])); + } + + int BDDNodeCountLevel(int lev) { + return vvIndices[lev].size() - vvRedundantIndices[lev].size(); + } + + int BDDNodeCount() { + int count = 1; // const node + for(int i = 0; i < nInputs; i++) { + count += BDDNodeCountLevel(i); + } + return count; + } + + int BDDFind(int index, int lev) { + int logwidth = nInputs - lev; + if(logwidth > lww) { + int nScopeSize = 1 << (logwidth - lww); + bool fZero = true; + bool fOne = true; + for(int i = 0; i < nScopeSize && (fZero || fOne); i++) { + word value = t[nScopeSize * index + i]; + fZero &= !value; + fOne &= !(~value); + } + if(fZero || fOne) { + return -2 ^ (int)fOne; + } + for(unsigned j = 0; j < vvIndices[lev].size(); j++) { + int index2 = vvIndices[lev][j]; + bool fEq = true; + bool fCompl = true; + for(int i = 0; i < nScopeSize && (fEq || fCompl); i++) { + fEq &= (t[nScopeSize * index + i] == t[nScopeSize * index2 + i]); + fCompl &= (t[nScopeSize * index + i] == ~t[nScopeSize * index2 + i]); + } + if(fEq || fCompl) { + return (j << 1) ^ (int)fCompl; + } + } + } else { + word value = GetValue(index, lev); + if(!value) { + return -2; + } + if(!(value ^ ones[logwidth])) { + return -1; + } + for(unsigned j = 0; j < vvIndices[lev].size(); j++) { + int index2 = vvIndices[lev][j]; + word value2 = value ^ GetValue(index2, lev); + if(!(value2)) { + return j << 1; + } + if(!(value2 ^ ones[logwidth])) { + return (j << 1) ^ 1; + } + } + } + return -3; + } + + virtual int BDDBuildOne(int index, int lev) { + int r = BDDFind(index, lev); + if(r >= -2) { + return r; + } + vvIndices[lev].push_back(index); + return (vvIndices[lev].size() - 1) << 1; + } + + virtual void BDDBuildStartup() { + vvIndices.clear(); + vvIndices.resize(nInputs); + vvRedundantIndices.clear(); + vvRedundantIndices.resize(nInputs); + for(int i = 0; i < nOutputs; i++) { + BDDBuildOne(i, 0); + } + } + + virtual void BDDBuildLevel(int lev) { + for(unsigned i = 0; i < vvIndices[lev-1].size(); i++) { + int index = vvIndices[lev-1][i]; + int cof0 = BDDBuildOne(index << 1, lev); + int cof1 = BDDBuildOne((index << 1) ^ 1, lev); + if(cof0 == cof1) { + vvRedundantIndices[lev-1].push_back(index); + } + } + } + + virtual int BDDBuild() { + BDDBuildStartup(); + for(int i = 1; i < nInputs; i++) { + BDDBuildLevel(i); + } + return BDDNodeCount(); + } + + virtual int BDDRebuild(int lev) { + vvIndices[lev].clear(); + vvIndices[lev+1].clear(); + for(int i = lev; i < lev + 2; i++) { + if(!i) { + for(int j = 0; j < nOutputs; j++) { + BDDBuildOne(j, 0); + } + } else { + vvRedundantIndices[i-1].clear(); + BDDBuildLevel(i); + } + } + if(lev < nInputs - 2) { + vvRedundantIndices[lev+1].clear(); + for(unsigned i = 0; i < vvIndices[lev+1].size(); i++) { + int index = vvIndices[lev+1][i]; + if(IsEq(index << 1, (index << 1) ^ 1, lev + 2)) { + vvRedundantIndices[lev+1].push_back(index); + } + } + } + return BDDNodeCount(); + } + + virtual void Swap(int lev) { + assert(lev < nInputs - 1); + std::vector::iterator it0 = std::find(vLevels.begin(), vLevels.end(), lev); + std::vector::iterator it1 = std::find(vLevels.begin(), vLevels.end(), lev + 1); + std::swap(*it0, *it1); + if(nInputs - lev - 1 > lww) { + int nScopeSize = 1 << (nInputs - lev - 2 - lww); + for(int i = nScopeSize; i < nTotalSize; i += (nScopeSize << 2)) { + for(int j = 0; j < nScopeSize; j++) { + std::swap(t[i + j], t[i + nScopeSize + j]); + } + } + } else if(nInputs - lev - 1 == lww) { + for(int i = 0; i < nTotalSize; i += 2) { + t[i+1] ^= t[i] >> (ww / 2); + t[i] ^= t[i+1] << (ww / 2); + t[i+1] ^= t[i] >> (ww / 2); + } + } else { + for(int i = 0; i < nTotalSize; i++) { + int d = nInputs - lev - 2; + int shamt = 1 << d; + t[i] ^= (t[i] >> shamt) & swapmask[d]; + t[i] ^= (t[i] & swapmask[d]) << shamt; + t[i] ^= (t[i] >> shamt) & swapmask[d]; + } + } + } + + void SwapIndex(int &index, int d) { + if((index >> d) % 4 == 1) { + index += 1 << d; + } else if((index >> d) % 4 == 2) { + index -= 1 << d; + } + } + + virtual int BDDSwap(int lev) { + Swap(lev); + for(int i = lev + 2; i < nInputs; i++) { + for(unsigned j = 0; j < vvIndices[i].size(); j++) { + SwapIndex(vvIndices[i][j], i - (lev + 2)); + } + } + // swapping vvRedundantIndices is unnecessary for node counting + return BDDRebuild(lev); + } + + int SiftReo() { + int best = BDDBuild(); + Save(0); + SaveIndices(0); + std::vector vars(nInputs); + int i; + for(i = 0; i < nInputs; i++) { + vars[i] = i; + } + std::vector vCounts(nInputs); + for(i = 0; i < nInputs; i++) { + vCounts[i] = BDDNodeCountLevel(vLevels[i]); + } + for(i = 1; i < nInputs; i++) { + int j = i; + while(j > 0 && vCounts[vars[j-1]] < vCounts[vars[j]]) { + std::swap(vars[j], vars[j-1]); + j--; + } + } + bool turn = true; + unsigned j; + for(j = 0; j < vars.size(); j++) { + int var = vars[j]; + bool updated = false; + int lev = vLevels[var]; + for(int i = lev; i < nInputs - 1; i++) { + int count = BDDSwap(i); + if(best > count) { + best = count; + updated = true; + Save(turn); + SaveIndices(turn); + } + } + if(lev) { + Load(!turn); + LoadIndices(!turn); + for(int i = lev - 1; i >= 0; i--) { + int count = BDDSwap(i); + if(best > count) { + best = count; + updated = true; + Save(turn); + SaveIndices(turn); + } + } + } + turn ^= updated; + Load(!turn); + LoadIndices(!turn); + } + return best; + } + + void Reo(std::vector vLevelsNew) { + for(int i = 0; i < nInputs; i++) { + int var = std::find(vLevelsNew.begin(), vLevelsNew.end(), i) - vLevelsNew.begin(); + int lev = vLevels[var]; + if(lev < i) { + for(int j = lev; j < i; j++) { + Swap(j); + } + } else if(lev > i) { + for(int j = lev - 1; j >= i; j--) { + Swap(j); + } + } + } + assert(vLevels == vLevelsNew); + } + + int RandomSiftReo(int nRound) { + int best = SiftReo(); + Save(2); + for(int i = 0; i < nRound; i++) { + std::vector vLevelsNew(nInputs); + int j; + for(j = 0; j < nInputs; j++) { + vLevelsNew[j] = j; + } + for(j = nInputs - 1; j > 0; j--) { + int d = rand() % j; + std::swap(vLevelsNew[j], vLevelsNew[d]); + } + Reo(vLevelsNew); + int r = SiftReo(); + if(best > r) { + best = r; + Save(2); + } + } + Load(2); + return best; + } + + int BDDGenerateAigRec(Gia_Man_t *pNew, std::vector const &vInputs, std::vector > &vvNodes, int index, int lev) { + int r = BDDFind(index, lev); + if(r >= 0) { + return vvNodes[lev][r >> 1] ^ (r & 1); + } + if(r >= -2) { + return r + 2; + } + int cof0 = BDDGenerateAigRec(pNew, vInputs, vvNodes, index << 1, lev + 1); + int cof1 = BDDGenerateAigRec(pNew, vInputs, vvNodes, (index << 1) ^ 1, lev + 1); + if(cof0 == cof1) { + return cof0; + } + int node; + if(Imply(index << 1, (index << 1) ^ 1, lev + 1)) { + node = Gia_ManHashOr(pNew, Gia_ManHashAnd(pNew, vInputs[lev], cof1), cof0); + } else if(Imply((index << 1) ^ 1, index << 1, lev + 1)) { + node = Gia_ManHashOr(pNew, Gia_ManHashAnd(pNew, vInputs[lev] ^ 1, cof0), cof1); + } else { + node = Gia_ManHashMux(pNew, vInputs[lev], cof1, cof0); + } + vvIndices[lev].push_back(index); + vvNodes[lev].push_back(node); + return node; + } + + virtual void BDDGenerateAig(Gia_Man_t *pNew, Vec_Int_t *vSupp) { + vvIndices.clear(); + vvIndices.resize(nInputs); + std::vector > vvNodes(nInputs); + std::vector vInputs(nInputs); + int i; + for(i = 0; i < nInputs; i++) { + vInputs[vLevels[i]] = Vec_IntEntry(vSupp, nInputs - i - 1) << 1; + } + for(i = 0; i < nOutputs; i++) { + int node = BDDGenerateAigRec(pNew, vInputs, vvNodes, i, 0); + Gia_ManAppendCo(pNew, node); + } + } +}; + +const int TruthTable::ww = 64; +const int TruthTable::lww = 6; + +const word TruthTable::ones[7] = {ABC_CONST(0x0000000000000001), + ABC_CONST(0x0000000000000003), + ABC_CONST(0x000000000000000f), + ABC_CONST(0x00000000000000ff), + ABC_CONST(0x000000000000ffff), + ABC_CONST(0x00000000ffffffff), + ABC_CONST(0xffffffffffffffff)}; + +const word TruthTable::swapmask[5] = {ABC_CONST(0x2222222222222222), + ABC_CONST(0x0c0c0c0c0c0c0c0c), + ABC_CONST(0x00f000f000f000f0), + ABC_CONST(0x0000ff000000ff00), + ABC_CONST(0x00000000ffff0000)}; + +class TruthTableReo : public TruthTable { +public: + bool fBuilt; + std::vector > vvChildren; + std::vector > > vvChildrenSaved; + + TruthTableReo(int nInputs, int nOutputs): TruthTable(nInputs, nOutputs) { + fBuilt = false; + } + + void Save(unsigned i) { + if(vLevelsSaved.size() < i + 1) { + vLevelsSaved.resize(i + 1); + } + vLevelsSaved[i] = vLevels; + } + + void Load(unsigned i) { + assert(i < vLevelsSaved.size()); + vLevels = vLevelsSaved[i]; + } + + void SaveIndices(unsigned i) { + TruthTable::SaveIndices(i); + if(vvChildrenSaved.size() < i + 1) { + vvChildrenSaved.resize(i + 1); + } + vvChildrenSaved[i] = vvChildren; + } + + void LoadIndices(unsigned i) { + TruthTable::LoadIndices(i); + vvChildren = vvChildrenSaved[i]; + } + + void BDDBuildStartup() { + vvChildren.clear(); + vvChildren.resize(nInputs); + TruthTable::BDDBuildStartup(); + } + + void BDDBuildLevel(int lev) { + for(unsigned i = 0; i < vvIndices[lev-1].size(); i++) { + int index = vvIndices[lev-1][i]; + int cof0 = BDDBuildOne(index << 1, lev); + int cof1 = BDDBuildOne((index << 1) ^ 1, lev); + vvChildren[lev-1].push_back(cof0); + vvChildren[lev-1].push_back(cof1); + if(cof0 == cof1) { + vvRedundantIndices[lev-1].push_back(index); + } + } + } + + int BDDBuild() { + if(fBuilt) { + return BDDNodeCount(); + } + fBuilt = true; + BDDBuildStartup(); + for(int i = 1; i < nInputs + 1; i++) { + BDDBuildLevel(i); + } + return BDDNodeCount(); + } + + int BDDRebuildOne(int index, int cof0, int cof1, int lev, Hash_IntMan_t *unique, std::vector &vChildrenLow) { + if(cof0 < 0 && cof0 == cof1) { + return cof0; + } + bool fCompl = cof0 & 1; + if(fCompl) { + cof0 ^= 1; + cof1 ^= 1; + } + int *place = Hash_Int2ManLookup(unique, cof0, cof1); + if(*place) { + return (Hash_IntObjData2(unique, *place) << 1) ^ (int)fCompl; + } + vvIndices[lev].push_back(index); + Hash_Int2ManInsert(unique, cof0, cof1, vvIndices[lev].size() - 1); + vChildrenLow.push_back(cof0); + vChildrenLow.push_back(cof1); + if(cof0 == cof1) { + vvRedundantIndices[lev].push_back(index); + } + return ((vvIndices[lev].size() - 1) << 1) ^ (int)fCompl; + } + + int BDDRebuild(int lev) { + vvRedundantIndices[lev].clear(); + vvRedundantIndices[lev+1].clear(); + std::vector vChildrenHigh; + std::vector vChildrenLow; + Hash_IntMan_t *unique = Hash_IntManStart(2 * vvIndices[lev+1].size()); + vvIndices[lev+1].clear(); + for(unsigned i = 0; i < vvIndices[lev].size(); i++) { + int index = vvIndices[lev][i]; + int cof0index = vvChildren[lev][i+i] >> 1; + int cof1index = vvChildren[lev][i+i+1] >> 1; + bool cof0c = vvChildren[lev][i+i] & 1; + bool cof1c = vvChildren[lev][i+i+1] & 1; + int cof00, cof01, cof10, cof11; + if(cof0index < 0) { + cof00 = -2 ^ (int)cof0c; + cof01 = -2 ^ (int)cof0c; + } else { + cof00 = vvChildren[lev+1][cof0index+cof0index] ^ (int)cof0c; + cof01 = vvChildren[lev+1][cof0index+cof0index+1] ^ (int)cof0c; + } + if(cof1index < 0) { + cof10 = -2 ^ (int)cof1c; + cof11 = -2 ^ (int)cof1c; + } else { + cof10 = vvChildren[lev+1][cof1index+cof1index] ^ (int)cof1c; + cof11 = vvChildren[lev+1][cof1index+cof1index+1] ^ (int)cof1c; + } + int newcof0 = BDDRebuildOne(index << 1, cof00, cof10, lev + 1, unique, vChildrenLow); + int newcof1 = BDDRebuildOne((index << 1) ^ 1, cof01, cof11, lev + 1, unique, vChildrenLow); + vChildrenHigh.push_back(newcof0); + vChildrenHigh.push_back(newcof1); + if(newcof0 == newcof1) { + vvRedundantIndices[lev].push_back(index); + } + } + Hash_IntManStop(unique); + vvChildren[lev] = vChildrenHigh; + vvChildren[lev+1] = vChildrenLow; + return BDDNodeCount(); + } + + void Swap(int lev) { + assert(lev < nInputs - 1); + std::vector::iterator it0 = std::find(vLevels.begin(), vLevels.end(), lev); + std::vector::iterator it1 = std::find(vLevels.begin(), vLevels.end(), lev + 1); + std::swap(*it0, *it1); + BDDRebuild(lev); + } + + int BDDSwap(int lev) { + Swap(lev); + return BDDNodeCount(); + } + + virtual void BDDGenerateAig(Gia_Man_t *pNew, Vec_Int_t *vSupp) { + abort(); + } +}; + +class TruthTableRewrite : public TruthTable { +public: + TruthTableRewrite(int nInputs, int nOutputs): TruthTable(nInputs, nOutputs) {} + + void SetValue(int index_lev, int lev, word value) { + assert(index_lev >= 0); + assert(nInputs - lev <= lww); + int logwidth = nInputs - lev; + int index = index_lev >> (lww - logwidth); + int pos = (index_lev % (1 << (lww - logwidth))) << logwidth; + t[index] &= ~(ones[logwidth] << pos); + t[index] ^= value << pos; + } + + void CopyFunc(int index1, int index2, int lev, bool fCompl) { + assert(index1 >= 0); + int logwidth = nInputs - lev; + if(logwidth > lww) { + int nScopeSize = 1 << (logwidth - lww); + if(!fCompl) { + if(index2 < 0) { + for(int i = 0; i < nScopeSize; i++) { + t[nScopeSize * index1 + i] = 0; + } + } else { + for(int i = 0; i < nScopeSize; i++) { + t[nScopeSize * index1 + i] = t[nScopeSize * index2 + i]; + } + } + } else { + if(index2 < 0) { + for(int i = 0; i < nScopeSize; i++) { + t[nScopeSize * index1 + i] = ones[lww]; + } + } else { + for(int i = 0; i < nScopeSize; i++) { + t[nScopeSize * index1 + i] = ~t[nScopeSize * index2 + i]; + } + } + } + } else { + word value = 0; + if(index2 >= 0) { + value = GetValue(index2, lev); + } + if(fCompl) { + value ^= ones[logwidth]; + } + SetValue(index1, lev, value); + } + } + + void ShiftToMajority(int index, int lev) { + assert(index >= 0); + int logwidth = nInputs - lev; + int count = 0; + if(logwidth > lww) { + int nScopeSize = 1 << (logwidth - lww); + for(int i = 0; i < nScopeSize; i++) { + count += bsw(t[nScopeSize * index + i]).count(); + } + } else { + count = bsw(GetValue(index, lev)).count(); + } + bool majority = count > (1 << (logwidth - 1)); + CopyFunc(index, -1, lev, majority); + } +}; + +class TruthTableCare : public TruthTableRewrite { +public: + std::vector originalt; + std::vector caret; + std::vector care; + + std::vector > > vvMergedIndices; + + std::vector > savedcare; + std::vector > > > vvMergedIndicesSaved; + + TruthTableCare(int nInputs, int nOutputs): TruthTableRewrite(nInputs, nOutputs) { + if(nSize) { + care.resize(nSize); + } else { + care.resize(1); + } + } + + void Save(unsigned i) { + TruthTable::Save(i); + if(savedcare.size() < i + 1) { + savedcare.resize(i + 1); + } + savedcare[i] = care; + } + + void Load(unsigned i) { + TruthTable::Load(i); + care = savedcare[i]; + } + + void SaveIndices(unsigned i) { + TruthTable::SaveIndices(i); + if(vvMergedIndicesSaved.size() < i + 1) { + vvMergedIndicesSaved.resize(i + 1); + } + vvMergedIndicesSaved[i] = vvMergedIndices; + } + + void LoadIndices(unsigned i) { + TruthTable::LoadIndices(i); + vvMergedIndices = vvMergedIndicesSaved[i]; + } + + void Swap(int lev) { + TruthTable::Swap(lev); + if(nInputs - lev - 1 > lww) { + int nScopeSize = 1 << (nInputs - lev - 2 - lww); + for(int i = nScopeSize; i < nSize; i += (nScopeSize << 2)) { + for(int j = 0; j < nScopeSize; j++) { + std::swap(care[i + j], care[i + nScopeSize + j]); + } + } + } else if(nInputs - lev - 1 == lww) { + for(int i = 0; i < nSize; i += 2) { + care[i+1] ^= care[i] >> (ww / 2); + care[i] ^= care[i+1] << (ww / 2); + care[i+1] ^= care[i] >> (ww / 2); + } + } else { + for(int i = 0; i < nSize || (i == 0 && !nSize); i++) { + int d = nInputs - lev - 2; + int shamt = 1 << d; + care[i] ^= (care[i] >> shamt) & swapmask[d]; + care[i] ^= (care[i] & swapmask[d]) << shamt; + care[i] ^= (care[i] >> shamt) & swapmask[d]; + } + } + } + + void RestoreCare() { + caret.clear(); + if(nSize) { + for(int i = 0; i < nOutputs; i++) { + caret.insert(caret.end(), care.begin(), care.end()); + } + } else { + caret.resize(nTotalSize); + for(int i = 0; i < nOutputs; i++) { + int padding = i * (1 << nInputs); + caret[padding / ww] |= care[0] << (padding % ww); + } + } + } + + word GetCare(int index_lev, int lev) { + assert(index_lev >= 0); + assert(nInputs - lev <= lww); + int logwidth = nInputs - lev; + int index = index_lev >> (lww - logwidth); + int pos = (index_lev % (1 << (lww - logwidth))) << logwidth; + return (caret[index] >> pos) & ones[logwidth]; + } + + void CopyFuncMasked(int index1, int index2, int lev, bool fCompl) { + assert(index1 >= 0); + assert(index2 >= 0); + int logwidth = nInputs - lev; + if(logwidth > lww) { + int nScopeSize = 1 << (logwidth - lww); + for(int i = 0; i < nScopeSize; i++) { + word value = t[nScopeSize * index2 + i]; + if(fCompl) { + value = ~value; + } + word cvalue = caret[nScopeSize * index2 + i]; + t[nScopeSize * index1 + i] &= ~cvalue; + t[nScopeSize * index1 + i] |= cvalue & value; + } + } else { + word one = ones[logwidth]; + word value1 = GetValue(index1, lev); + word value2 = GetValue(index2, lev); + if(fCompl) { + value2 ^= one; + } + word cvalue = GetCare(index2, lev); + value1 &= cvalue ^ one; + value1 |= cvalue & value2; + SetValue(index1, lev, value1); + } + } + + bool IsDC(int index, int lev) { + if(nInputs - lev > lww) { + int nScopeSize = 1 << (nInputs - lev - lww); + for(int i = 0; i < nScopeSize; i++) { + if(caret[nScopeSize * index + i]) { + return false; + } + } + } else if(GetCare(index, lev)) { + return false; + } + return true; + } + + int Include(int index1, int index2, int lev, bool fCompl) { + assert(index1 >= 0); + assert(index2 >= 0); + int logwidth = nInputs - lev; + bool fEq = true; + if(logwidth > lww) { + int nScopeSize = 1 << (logwidth - lww); + for(int i = 0; i < nScopeSize && (fEq || fCompl); i++) { + word cvalue = caret[nScopeSize * index2 + i]; + if(~caret[nScopeSize * index1 + i] & cvalue) { + return 0; + } + word value = t[nScopeSize * index1 + i] ^ t[nScopeSize * index2 + i]; + fEq &= !(value & cvalue); + fCompl &= !(~value & cvalue); + } + } else { + word cvalue = GetCare(index2, lev); + if((GetCare(index1, lev) ^ ones[logwidth]) & cvalue) { + return 0; + } + word value = GetValue(index1, lev) ^ GetValue(index2, lev); + fEq &= !(value & cvalue); + fCompl &= !((value ^ ones[logwidth]) & cvalue); + } + return 2 * fCompl + fEq; + } + + int Intersect(int index1, int index2, int lev, bool fCompl, bool fEq = true) { + assert(index1 >= 0); + assert(index2 >= 0); + int logwidth = nInputs - lev; + if(logwidth > lww) { + int nScopeSize = 1 << (logwidth - lww); + for(int i = 0; i < nScopeSize && (fEq || fCompl); i++) { + word value = t[nScopeSize * index1 + i] ^ t[nScopeSize * index2 + i]; + word cvalue = caret[nScopeSize * index1 + i] & caret[nScopeSize * index2 + i]; + fEq &= !(value & cvalue); + fCompl &= !(~value & cvalue); + } + } else { + word value = GetValue(index1, lev) ^ GetValue(index2, lev); + word cvalue = GetCare(index1, lev) & GetCare(index2, lev); + fEq &= !(value & cvalue); + fCompl &= !((value ^ ones[logwidth]) & cvalue); + } + return 2 * fCompl + fEq; + } + + void MergeCare(int index1, int index2, int lev) { + assert(index1 >= 0); + assert(index2 >= 0); + int logwidth = nInputs - lev; + if(logwidth > lww) { + int nScopeSize = 1 << (logwidth - lww); + for(int i = 0; i < nScopeSize; i++) { + caret[nScopeSize * index1 + i] |= caret[nScopeSize * index2 + i]; + } + } else { + word value = GetCare(index2, lev); + int index = index1 >> (lww - logwidth); + int pos = (index1 % (1 << (lww - logwidth))) << logwidth; + caret[index] |= value << pos; + } + } + + void Merge(int index1, int index2, int lev, bool fCompl) { + MergeCare(index1, index2, lev); + vvMergedIndices[lev].push_back(std::make_pair((index1 << 1) ^ (int)fCompl, index2)); + } + + int BDDBuildOne(int index, int lev) { + int r = BDDFind(index, lev); + if(r >= -2) { + if(r >= 0) { + Merge(vvIndices[lev][r >> 1], index, lev, r & 1); + } + return r; + } + vvIndices[lev].push_back(index); + return (vvIndices[lev].size() - 1) << 1; + } + + void CompleteMerge() { + for(int i = nInputs - 1; i >= 0; i--) { + for(std::vector >::reverse_iterator it = vvMergedIndices[i].rbegin(); it != vvMergedIndices[i].rend(); it++) { + CopyFunc((*it).second, (*it).first >> 1, i, (*it).first & 1); + } + } + } + + void BDDBuildStartup() { + RestoreCare(); + vvIndices.clear(); + vvIndices.resize(nInputs); + vvRedundantIndices.clear(); + vvRedundantIndices.resize(nInputs); + vvMergedIndices.clear(); + vvMergedIndices.resize(nInputs); + for(int i = 0; i < nOutputs; i++) { + if(!IsDC(i, 0)) { + BDDBuildOne(i, 0); + } + } + } + + virtual void BDDRebuildByMerge(int lev) { + for(unsigned i = 0; i < vvMergedIndices[lev].size(); i++) { + std::pair &p = vvMergedIndices[lev][i]; + MergeCare(p.first >> 1, p.second, lev); + } + } + + int BDDRebuild(int lev) { + RestoreCare(); + int i; + for(i = lev; i < nInputs; i++) { + vvIndices[i].clear(); + vvMergedIndices[i].clear(); + if(i) { + vvRedundantIndices[i-1].clear(); + } + } + for(i = 0; i < lev; i++) { + BDDRebuildByMerge(i); + } + for(i = lev; i < nInputs; i++) { + if(!i) { + for(int j = 0; j < nOutputs; j++) { + if(!IsDC(j, 0)) { + BDDBuildOne(j, 0); + } + } + } else { + BDDBuildLevel(i); + } + } + return BDDNodeCount(); + } + + int BDDSwap(int lev) { + Swap(lev); + return BDDRebuild(lev); + } + + void OptimizationStartup() { + originalt = t; + RestoreCare(); + vvIndices.clear(); + vvIndices.resize(nInputs); + vvMergedIndices.clear(); + vvMergedIndices.resize(nInputs); + for(int i = 0; i < nOutputs; i++) { + if(!IsDC(i, 0)) { + BDDBuildOne(i, 0); + } else { + ShiftToMajority(i, 0); + } + } + } + + virtual void Optimize() { + OptimizationStartup(); + for(int i = 1; i < nInputs; i++) { + for(unsigned j = 0; j < vvIndices[i-1].size(); j++) { + int index = vvIndices[i-1][j]; + BDDBuildOne(index << 1, i); + BDDBuildOne((index << 1) ^ 1, i); + } + } + CompleteMerge(); + } +}; + +class TruthTableLevelTSM : public TruthTableCare { +public: + TruthTableLevelTSM(int nInputs, int nOutputs): TruthTableCare(nInputs, nOutputs) {} + + int BDDFindTSM(int index, int lev) { + int logwidth = nInputs - lev; + if(logwidth > lww) { + int nScopeSize = 1 << (logwidth - lww); + bool fZero = true; + bool fOne = true; + for(int i = 0; i < nScopeSize && (fZero || fOne); i++) { + word value = t[nScopeSize * index + i]; + word cvalue = caret[nScopeSize * index + i]; + fZero &= !(value & cvalue); + fOne &= !(~value & cvalue); + } + if(fZero || fOne) { + return -2 ^ (int)fOne; + } + for(unsigned j = 0; j < vvIndices[lev].size(); j++) { + int index2 = vvIndices[lev][j]; + bool fEq = true; + bool fCompl = true; + for(int i = 0; i < nScopeSize && (fEq || fCompl); i++) { + word value = t[nScopeSize * index + i] ^ t[nScopeSize * index2 + i]; + word cvalue = caret[nScopeSize * index + i] & caret[nScopeSize * index2 + i]; + fEq &= !(value & cvalue); + fCompl &= !(~value & cvalue); + } + if(fEq || fCompl) { + return (index2 << 1) ^ (int)!fEq; + } + } + } else { + word one = ones[logwidth]; + word value = GetValue(index, lev); + word cvalue = GetCare(index, lev); + if(!(value & cvalue)) { + return -2; + } + if(!((value ^ one) & cvalue)) { + return -1; + } + for(unsigned j = 0; j < vvIndices[lev].size(); j++) { + int index2 = vvIndices[lev][j]; + word value2 = value ^ GetValue(index2, lev); + word cvalue2 = cvalue & GetCare(index2, lev); + if(!(value2 & cvalue2)) { + return index2 << 1; + } + if(!((value2 ^ one) & cvalue2)) { + return (index2 << 1) ^ 1; + } + } + } + return -3; + } + + int BDDBuildOne(int index, int lev) { + int r = BDDFindTSM(index, lev); + if(r >= -2) { + if(r >= 0) { + CopyFuncMasked(r >> 1, index, lev, r & 1); + Merge(r >> 1, index, lev, r & 1); + } else { + vvMergedIndices[lev].push_back(std::make_pair(r, index)); + } + return r; + } + vvIndices[lev].push_back(index); + return index << 1; + } + + int BDDBuild() { + TruthTable::Save(3); + int r = TruthTable::BDDBuild(); + TruthTable::Load(3); + return r; + } + + void BDDRebuildByMerge(int lev) { + for(unsigned i = 0; i < vvMergedIndices[lev].size(); i++) { + std::pair &p = vvMergedIndices[lev][i]; + if(p.first >= 0) { + CopyFuncMasked(p.first >> 1, p.second, lev, p.first & 1); + MergeCare(p.first >> 1, p.second, lev); + } + } + } + + int BDDRebuild(int lev) { + TruthTable::Save(3); + int r = TruthTableCare::BDDRebuild(lev); + TruthTable::Load(3); + return r; + } +}; + +} + +Gia_Man_t * Gia_ManTtopt( Gia_Man_t * p, int nIns, int nOuts, int nRounds ) +{ + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + Vec_Int_t * vSupp; + word v; + word * pTruth; + int i, g, k, nInputs; + Gia_ManLevelNum( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManForEachCi( p, pObj, k ) + Gia_ManAppendCi( pNew ); + Gia_ObjComputeTruthTableStart( p, nIns ); + Gia_ManHashStart( pNew ); + for ( g = 0; g < Gia_ManCoNum(p); g += nOuts ) + { + vSupp = Gia_ManCollectSuppNew( p, g, nOuts ); + nInputs = Vec_IntSize( vSupp ); + Ttopt::TruthTableReo tt( nInputs, nOuts ); + for ( k = 0; k < nOuts; k++ ) + { + pObj = Gia_ManCo( p, g+k ); + pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ObjFanin0(pObj), vSupp ); + if ( nInputs >= 6 ) + for ( i = 0; i < tt.nSize; i++ ) + tt.t[i + tt.nSize * k] = Gia_ObjFaninC0(pObj)? ~pTruth[i]: pTruth[i]; + else + { + i = k * (1 << nInputs); + v = (Gia_ObjFaninC0(pObj)? ~pTruth[0]: pTruth[0]) & tt.ones[nInputs]; + tt.t[i / tt.ww] |= v << (i % tt.ww); + } + } + tt.RandomSiftReo( nRounds ); + Ttopt::TruthTable tt2( nInputs, nOuts ); + tt2.t = tt.t; + tt2.Reo( tt.vLevels ); + tt2.BDDGenerateAig( pNew, vSupp ); + Vec_IntFree( vSupp ); + } + Gia_ObjComputeTruthTableStop( p ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + return pNew; +} + +Gia_Man_t * Gia_ManTtoptCare( Gia_Man_t * p, int nIns, int nOuts, int nRounds, char * pFileName, int nRarity ) +{ + int fVerbose = 0; + Gia_Man_t * pNew; + Gia_Obj_t * pObj; + Vec_Int_t * vSupp; + word v; + word * pTruth, * pCare; + int i, g, k, nInputs; + Vec_Wrd_t * vSimI = Vec_WrdReadBin( pFileName, fVerbose ); + Gia_ManLevelNum( p ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManForEachCi( p, pObj, k ) + Gia_ManAppendCi( pNew ); + Gia_ObjComputeTruthTableStart( p, nIns ); + Gia_ManHashStart( pNew ); + for ( g = 0; g < Gia_ManCoNum(p); g += nOuts ) + { + vSupp = Gia_ManCollectSuppNew( p, g, nOuts ); + nInputs = Vec_IntSize( vSupp ); + if ( nInputs == 0 ) + { + for ( k = 0; k < nOuts; k++ ) + { + pObj = Gia_ManCo( p, g+k ); + pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ObjFanin0(pObj), vSupp ); + Gia_ManAppendCo( pNew, pTruth[0] & 1 ); + } + Vec_IntFree( vSupp ); + continue; + } + Ttopt::TruthTableLevelTSM tt( nInputs, nOuts ); + for ( k = 0; k < nOuts; k++ ) + { + pObj = Gia_ManCo( p, g+k ); + pTruth = Gia_ObjComputeTruthTableCut( p, Gia_ObjFanin0(pObj), vSupp ); + if ( nInputs >= 6 ) + for ( i = 0; i < tt.nSize; i++ ) + tt.t[i + tt.nSize * k] = Gia_ObjFaninC0(pObj)? ~pTruth[i]: pTruth[i]; + else + { + i = k * (1 << nInputs); + v = (Gia_ObjFaninC0(pObj)? ~pTruth[0]: pTruth[0]) & tt.ones[nInputs]; + tt.t[i / tt.ww] |= v << (i % tt.ww); + } + } + i = 1 << Vec_IntSize( vSupp ); + pCare = Gia_ManCountFraction( p, vSimI, vSupp, nRarity, fVerbose, &i ); + tt.care[0] = pCare[0]; + for ( i = 1; i < tt.nSize; i++ ) + tt.care[i] = pCare[i]; + ABC_FREE( pCare ); + tt.RandomSiftReo( nRounds ); + tt.Optimize(); + tt.BDDGenerateAig( pNew, vSupp ); + Vec_IntFree( vSupp ); + } + Gia_ObjComputeTruthTableStop( p ); + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + Vec_WrdFreeP( &vSimI ); + return pNew; +} + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaUnate.c b/yosys/abc/src/aig/gia/giaUnate.c new file mode 100644 index 00000000000..cf8d9104dfa --- /dev/null +++ b/yosys/abc/src/aig/gia/giaUnate.c @@ -0,0 +1,255 @@ +/**CFile**************************************************************** + + FileName [giaUnate.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Computation of structural unateness.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaUnate.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Flips the first bit in all entries of the vector.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Vec_Int_t * Vec_IntFlopBit( Vec_Int_t * p ) +{ + int i; + for ( i = 0; i < p->nSize; i++ ) + { + if ( i+1 < p->nSize && Abc_Lit2Var(p->pArray[i]) == Abc_Lit2Var(p->pArray[i+1]) ) + i++; // skip variable appearing as both pos and neg literal + else + p->pArray[i] ^= 1; + } + return p; +} + +/**Function************************************************************* + + Synopsis [Compute unateness for all outputs in terms of inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Gia_ManCheckUnateVec( Gia_Man_t * p, Vec_Int_t * vCiIds, Vec_Int_t * vCoIds ) +{ + Vec_Int_t * vCiVec = vCiIds ? Vec_IntDup(vCiIds) : Vec_IntStartNatural(Gia_ManCiNum(p)); + Vec_Int_t * vCoVec = vCoIds ? Vec_IntDup(vCoIds) : Vec_IntStartNatural(Gia_ManCoNum(p)); + Vec_Wec_t * vUnatesCo = Vec_WecStart( Vec_IntSize(vCoVec) ); + Vec_Wec_t * vUnates = Vec_WecStart( Gia_ManObjNum(p) ); + Vec_Int_t * vUnate0, * vUnate1; + Gia_Obj_t * pObj; int i, CioId; + Vec_IntForEachEntry( vCiVec, CioId, i ) + { + pObj = Gia_ManCi( p, CioId ); + Vec_IntPush( Vec_WecEntry(vUnates, Gia_ObjId(p, pObj)), Abc_Var2Lit(CioId, 0) ); + } + Gia_ManForEachAnd( p, pObj, i ) + { + vUnate0 = Vec_WecEntry(vUnates, Gia_ObjFaninId0(pObj, i)); + vUnate1 = Vec_WecEntry(vUnates, Gia_ObjFaninId1(pObj, i)); + vUnate0 = Gia_ObjFaninC0(pObj) ? Vec_IntFlopBit(vUnate0) : vUnate0; + vUnate1 = Gia_ObjFaninC1(pObj) ? Vec_IntFlopBit(vUnate1) : vUnate1; + Vec_IntTwoMerge2( vUnate0, vUnate1, Vec_WecEntry(vUnates, i) ); + vUnate0 = Gia_ObjFaninC0(pObj) ? Vec_IntFlopBit(vUnate0) : vUnate0; + vUnate1 = Gia_ObjFaninC1(pObj) ? Vec_IntFlopBit(vUnate1) : vUnate1; + } + Vec_IntForEachEntry( vCoVec, CioId, i ) + { + pObj = Gia_ManCo( p, CioId ); + vUnate0 = Vec_WecEntry(vUnates, Gia_ObjFaninId0p(p, pObj)); + vUnate0 = Gia_ObjFaninC0(pObj) ? Vec_IntFlopBit(vUnate0) : vUnate0; + Vec_IntAppend( Vec_WecEntry(vUnatesCo, i), vUnate0 ); + vUnate0 = Gia_ObjFaninC0(pObj) ? Vec_IntFlopBit(vUnate0) : vUnate0; + } + Vec_WecFree( vUnates ); + Vec_IntFree( vCiVec ); + Vec_IntFree( vCoVec ); + return vUnatesCo; +} + +/**Function************************************************************* + + Synopsis [Checks unateness one function in one variable.] + + Description [Returns 0 if Co is not unate in Ci. + Returns 1 if Co is neg-unate in Ci. + Returns 2 if Co is pos-unate in Ci. + Returns 3 if Co does not depend on Ci.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCheckUnate_rec( Gia_Man_t * p, int iObj ) +{ + Gia_Obj_t * pObj; + int Res0, Res1; + if ( p->nTravIds - p->pTravIds[iObj] <= 3 ) + return p->nTravIds - p->pTravIds[iObj]; + pObj = Gia_ManObj( p, iObj ); + p->pTravIds[iObj] = p->nTravIds - 3; + if ( Gia_ObjIsCi(pObj) ) + return 3; + Res0 = Gia_ManCheckUnate_rec( p, Gia_ObjFaninId0(pObj, iObj) ); + Res1 = Gia_ManCheckUnate_rec( p, Gia_ObjFaninId1(pObj, iObj) ); + Res0 = ((Res0 == 1 || Res0 == 2) && Gia_ObjFaninC0(pObj)) ? Res0 ^ 3 : Res0; + Res1 = ((Res1 == 1 || Res1 == 2) && Gia_ObjFaninC1(pObj)) ? Res1 ^ 3 : Res1; + p->pTravIds[iObj] = p->nTravIds - (Res0 & Res1); + assert( (Res0 & Res1) <= 3 ); + return p->nTravIds - p->pTravIds[iObj]; +} +int Gia_ManCheckUnate( Gia_Man_t * p, int iCiId, int iCoId ) +{ + int Res; + int CiObjId = Gia_ObjId(p, Gia_ManCi(p, iCiId)); + int CoObjId = Gia_ObjId(p, Gia_ManCo(p, iCoId)); + Gia_Obj_t * pCoObj = Gia_ManCo(p, iCoId); + Gia_ManIncrementTravId( p ); // Co does not depend on Ci. + Gia_ManIncrementTravId( p ); // Co is pos-unate in Ci + Gia_ObjSetTravIdCurrentId( p, CiObjId ); + Gia_ManIncrementTravId( p ); // Co is neg-unate in Ci + Gia_ManIncrementTravId( p ); // Co is not unate in Ci + Res = Gia_ManCheckUnate_rec( p, Gia_ObjFaninId0(pCoObj, CoObjId) ); + return ((Res == 1 || Res == 2) && Gia_ObjFaninC0(pCoObj)) ? Res ^ 3 : Res; +} + +/**Function************************************************************* + + Synopsis [Testing procedure for all pairs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCheckUnateVecTest( Gia_Man_t * p, int fVerbose ) +{ + abctime clk = Abc_Clock(); + Vec_Wec_t * vUnates = Gia_ManCheckUnateVec( p, NULL, NULL ); + int i, o, Var, nVars = Gia_ManCiNum(p); + int nUnate = 0, nNonUnate = 0; + char * pBuffer = ABC_CALLOC( char, nVars+1 ); + if ( fVerbose ) + { + printf( "Inputs : " ); + for ( i = 0; i < nVars; i++ ) + printf( "%d", i % 10 ); + printf( "\n" ); + } + for ( o = 0; o < Gia_ManCoNum(p); o++ ) + { + Vec_Int_t * vUnate = Vec_WecEntry( vUnates, o ); + memset( pBuffer, ' ', (size_t)nVars ); + Vec_IntForEachEntry( vUnate, Var, i ) + if ( i+1 < Vec_IntSize(vUnate) && Abc_Lit2Var(Var) == Abc_Lit2Var(Vec_IntEntry(vUnate, i+1)) ) // both lits are present + pBuffer[Abc_Lit2Var(Var)] = '.', i++, nNonUnate++; // does not depend on this var + else + pBuffer[Abc_Lit2Var(Var)] = Abc_LitIsCompl(Var) ? 'n' : 'p', nUnate++; + if ( fVerbose ) + printf( "Out%4d : %s\n", o, pBuffer ); + } + ABC_FREE( pBuffer ); + // print stats + printf( "Ins/Outs = %4d/%4d. Total supp = %5d. Total unate = %5d.\n", + Gia_ManCiNum(p), Gia_ManCoNum(p), nUnate+nNonUnate, nUnate ); + ABC_PRT( "Total time", Abc_Clock() - clk ); + //Vec_WecPrint( vUnates, 0 ); + Vec_WecFree( vUnates ); +} + +/**Function************************************************************* + + Synopsis [Testing procedure for one pair.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCheckUnateTest( Gia_Man_t * p, int fComputeAll, int fVerbose ) +{ + if ( fComputeAll ) + Gia_ManCheckUnateVecTest( p, fVerbose ); + else + { + abctime clk = Abc_Clock(); + int i, o, nVars = Gia_ManCiNum(p); + int nUnate = 0, nNonUnate = 0; + char * pBuffer = ABC_CALLOC( char, nVars+1 ); + if ( fVerbose ) + { + printf( "Inputs : " ); + for ( i = 0; i < nVars; i++ ) + printf( "%d", i % 10 ); + printf( "\n" ); + } + for ( o = 0; o < Gia_ManCoNum(p); o++ ) + { + for ( i = 0; i < nVars; i++ ) + { + int Res = Gia_ManCheckUnate( p, i, o ); + if ( Res == 3 ) pBuffer[i] = ' '; + else if ( Res == 2 ) pBuffer[i] = 'p', nUnate++; + else if ( Res == 1 ) pBuffer[i] = 'n', nUnate++; + else if ( Res == 0 ) pBuffer[i] = '.', nNonUnate++; + else assert( 0 ); + } + if ( fVerbose ) + printf( "Out%4d : %s\n", o, pBuffer ); + } + ABC_FREE( pBuffer ); + // print stats + printf( "Ins/Outs = %4d/%4d. Total supp = %5d. Total unate = %5d.\n", + Gia_ManCiNum(p), Gia_ManCoNum(p), nUnate+nNonUnate, nUnate ); + ABC_PRT( "Total time", Abc_Clock() - clk ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/giaUtil.c b/yosys/abc/src/aig/gia/giaUtil.c new file mode 100644 index 00000000000..de714993586 --- /dev/null +++ b/yosys/abc/src/aig/gia/giaUtil.c @@ -0,0 +1,3573 @@ +/**CFile**************************************************************** + + FileName [giaUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Scalable AIG package.] + + Synopsis [Various utilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: giaUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "gia.h" +#include "base/main/mainInt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define NUMBER1 3716960521u +#define NUMBER2 2174103536u + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates a sequence or random numbers.] + + Description [] + + SideEffects [] + + SeeAlso [http://www.codeproject.com/KB/recipes/SimpleRNG.aspx] + +***********************************************************************/ +unsigned Gia_ManRandom( int fReset ) +{ +#ifdef _MSC_VER + static unsigned int m_z = NUMBER1; + static unsigned int m_w = NUMBER2; +#else + static __thread unsigned int m_z = NUMBER1; + static __thread unsigned int m_w = NUMBER2; +#endif + if ( fReset ) + { + m_z = NUMBER1; + m_w = NUMBER2; + } + m_z = 36969 * (m_z & 65535) + (m_z >> 16); + m_w = 18000 * (m_w & 65535) + (m_w >> 16); + return (m_z << 16) + m_w; +} +word Gia_ManRandomW( int fReset ) +{ + return ((word)Gia_ManRandom(fReset) << 32) | ((word)Gia_ManRandom(fReset) << 0); +} + + + +/**Function************************************************************* + + Synopsis [Creates random info for the primary inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManRandomInfo( Vec_Ptr_t * vInfo, int iInputStart, int iWordStart, int iWordStop ) +{ + unsigned * pInfo; + int i, w; + Vec_PtrForEachEntryStart( unsigned *, vInfo, pInfo, i, iInputStart ) + for ( w = iWordStart; w < iWordStop; w++ ) + pInfo[w] = Gia_ManRandom(0); +} + + +/**Function************************************************************* + + Synopsis [Returns the time stamp.] + + Description [The file should be closed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Gia_TimeStamp() +{ + static char Buffer[100]; + char * TimeStamp; + time_t ltime; + // get the current time + time( <ime ); + TimeStamp = asctime( localtime( <ime ) ); + TimeStamp[ strlen(TimeStamp) - 1 ] = 0; + strcpy( Buffer, TimeStamp ); + return Buffer; +} + +/**Function************************************************************* + + Synopsis [Returns the composite name of the file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Gia_FileNameGenericAppend( char * pBase, char * pSuffix ) +{ + static char Buffer[1000]; + char * pDot; + strcpy( Buffer, pBase ); + if ( (pDot = strrchr( Buffer, '.' )) ) + *pDot = 0; + strcat( Buffer, pSuffix ); + if ( (pDot = strrchr( Buffer, '\\' )) || (pDot = strrchr( Buffer, '/' )) ) + return pDot+1; + return Buffer; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Gia_GetFakeNames( int nNames, int fCaps ) +{ + Vec_Ptr_t * vNames; + char Buffer[5]; + int i; + + vNames = Vec_PtrAlloc( nNames ); + for ( i = 0; i < nNames; i++ ) + { + if ( nNames < 26 ) + { + Buffer[0] = (fCaps ? 'A' : 'a') + i; + Buffer[1] = 0; + } + else + { + Buffer[0] = (fCaps ? 'A' : 'a') + i%26; + Buffer[1] = '0' + i/26; + Buffer[2] = 0; + } + Vec_PtrPush( vNames, Extra_UtilStrsav(Buffer) ); + } + return vNames; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManIncrementTravId( Gia_Man_t * p ) +{ + if ( p->pTravIds == NULL ) + { + p->nTravIdsAlloc = Gia_ManObjNum(p) + 100; + p->pTravIds = ABC_CALLOC( int, p->nTravIdsAlloc ); + p->nTravIds = 0; + } + while ( p->nTravIdsAlloc < Gia_ManObjNum(p) ) + { + p->nTravIdsAlloc *= 2; + p->pTravIds = ABC_REALLOC( int, p->pTravIds, p->nTravIdsAlloc ); + memset( p->pTravIds + p->nTravIdsAlloc/2, 0, sizeof(int) * p->nTravIdsAlloc/2 ); + } + p->nTravIds++; +} + +/**Function************************************************************* + + Synopsis [Sets phases of the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCleanMark01( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachObj( p, pObj, i ) + pObj->fMark0 = pObj->fMark1 = 0; +} + +/**Function************************************************************* + + Synopsis [Sets phases of the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSetMark0( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachObj( p, pObj, i ) + pObj->fMark0 = 1; +} + +/**Function************************************************************* + + Synopsis [Sets phases of the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCleanMark0( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachObj( p, pObj, i ) + pObj->fMark0 = 0; +} + +/**Function************************************************************* + + Synopsis [Sets phases of the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCheckMark0( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachObj( p, pObj, i ) + assert( pObj->fMark0 == 0 ); +} + +/**Function************************************************************* + + Synopsis [Sets phases of the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSetMark1( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachObj( p, pObj, i ) + pObj->fMark1 = 1; +} + +/**Function************************************************************* + + Synopsis [Sets phases of the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCleanMark1( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachObj( p, pObj, i ) + pObj->fMark1 = 0; +} + +/**Function************************************************************* + + Synopsis [Sets phases of the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCheckMark1( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachObj( p, pObj, i ) + assert( pObj->fMark1 == 0 ); +} + +/**Function************************************************************* + + Synopsis [Cleans the value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCleanValue( Gia_Man_t * p ) +{ + int i; + for ( i = 0; i < p->nObjs; i++ ) + p->pObjs[i].Value = 0; +} + +/**Function************************************************************* + + Synopsis [Cleans the value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManFillValue( Gia_Man_t * p ) +{ + int i; + for ( i = 0; i < p->nObjs; i++ ) + p->pObjs[i].Value = ~0; +} + +/**Function************************************************************* + + Synopsis [Sets the phase of one object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ObjSetPhase( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( Gia_ObjIsAnd(pObj) ) + { + int fPhase0 = Gia_ObjPhase(Gia_ObjFanin0(pObj)) ^ Gia_ObjFaninC0(pObj); + int fPhase1 = Gia_ObjPhase(Gia_ObjFanin1(pObj)) ^ Gia_ObjFaninC1(pObj); + if ( Gia_ObjIsMux(p, pObj) ) + { + int fPhase2 = Gia_ObjPhase(Gia_ObjFanin2(p, pObj)) ^ Gia_ObjFaninC2(p, pObj); + pObj->fPhase = (fPhase2 && fPhase1) || (!fPhase2 && fPhase0); + } + else if ( Gia_ObjIsXor(pObj) ) + pObj->fPhase = fPhase0 ^ fPhase1; + else + pObj->fPhase = fPhase0 & fPhase1; + } + else if ( Gia_ObjIsCo(pObj) ) + pObj->fPhase = (Gia_ObjPhase(Gia_ObjFanin0(pObj)) ^ Gia_ObjFaninC0(pObj)); + else + pObj->fPhase = 0; +} + +/**Function************************************************************* + + Synopsis [Sets phases of the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSetPhase( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachObj( p, pObj, i ) + Gia_ObjSetPhase( p, pObj ); +} +void Gia_ManSetPhasePattern( Gia_Man_t * p, Vec_Int_t * vCiValues ) +{ + Gia_Obj_t * pObj; + int i; + assert( Gia_ManCiNum(p) == Vec_IntSize(vCiValues) ); + Gia_ManForEachObj( p, pObj, i ) + if ( Gia_ObjIsCi(pObj) ) + pObj->fPhase = Vec_IntEntry( vCiValues, Gia_ObjCioId(pObj) ); + else + Gia_ObjSetPhase( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Sets phases of the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSetPhase1( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachCi( p, pObj, i ) + pObj->fPhase = 1; + Gia_ManForEachObj( p, pObj, i ) + if ( !Gia_ObjIsCi(pObj) ) + Gia_ObjSetPhase( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Sets phases of the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCleanPhase( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachObj( p, pObj, i ) + pObj->fPhase = 0; +} + +/**Function************************************************************* + + Synopsis [Returns the number of COs whose value is 1.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCheckCoPhase( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, Counter = 0; + Gia_ManForEachCo( p, pObj, i ) + Counter += pObj->fPhase; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Prepares copies for the model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCleanLevels( Gia_Man_t * p, int Size ) +{ + if ( p->vLevels == NULL ) + p->vLevels = Vec_IntAlloc( Size ); + Vec_IntFill( p->vLevels, Size, 0 ); +} +/**Function************************************************************* + + Synopsis [Prepares copies for the model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCleanTruth( Gia_Man_t * p ) +{ + if ( p->vTruths == NULL ) + p->vTruths = Vec_IntAlloc( Gia_ManObjNum(p) ); + Vec_IntFill( p->vTruths, Gia_ManObjNum(p), -1 ); +} + +/**Function************************************************************* + + Synopsis [Assigns levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManLevelNum( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManCleanLevels( p, Gia_ManObjNum(p) ); + p->nLevels = 0; + Gia_ManForEachObj( p, pObj, i ) + { + if ( !p->fGiaSimple && Gia_ObjIsBuf(pObj) ) + Gia_ObjSetBufLevel( p, pObj ); + else if ( Gia_ObjIsAnd(pObj) ) + Gia_ObjSetGateLevel( p, pObj ); + else if ( Gia_ObjIsCo(pObj) ) + Gia_ObjSetCoLevel( p, pObj ); + else + Gia_ObjSetLevel( p, pObj, 0 ); + p->nLevels = Abc_MaxInt( p->nLevels, Gia_ObjLevel(p, pObj) ); + } + return p->nLevels; +} +int Gia_ManLevelRNum( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManCleanLevels( p, Gia_ManObjNum(p) ); + p->nLevels = 0; + Gia_ManForEachObjReverse( p, pObj, i ) + { + if ( !p->fGiaSimple && Gia_ObjIsBuf(pObj) ) + Gia_ObjUpdateLevelId( p, Gia_ObjFaninId0(pObj, i), Gia_ObjLevel(p, pObj) ); + else if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ObjUpdateLevelId( p, Gia_ObjFaninId0(pObj, i), 1+Gia_ObjLevel(p, pObj) ); + Gia_ObjUpdateLevelId( p, Gia_ObjFaninId1(pObj, i), 1+Gia_ObjLevel(p, pObj) ); + } + else if ( Gia_ObjIsCo(pObj) ) + Gia_ObjUpdateLevelId( p, Gia_ObjFaninId0(pObj, i), 1 ); + else + p->nLevels = Abc_MaxInt( p->nLevels, Gia_ObjLevel(p, pObj) ); + } + return p->nLevels; +} +float Gia_ManLevelAve( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, Ave = 0; + assert( p->vLevels ); + Gia_ManForEachCo( p, pObj, i ) + Ave += Gia_ObjLevel(p, pObj); + return (float)Ave / Gia_ManCoNum(p); +} + +/**Function************************************************************* + + Synopsis [Assigns levels using CI level information.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManGetCiLevels( Gia_Man_t * p ) +{ + Vec_Int_t * vCiLevels; + Gia_Obj_t * pObj; + int i; + if ( p->vLevels == NULL ) + return NULL; + vCiLevels = Vec_IntAlloc( Gia_ManCiNum(p) ); + Gia_ManForEachCi( p, pObj, i ) + Vec_IntPush( vCiLevels, Gia_ObjLevel(p, pObj) ); + return vCiLevels; +} +int Gia_ManSetLevels( Gia_Man_t * p, Vec_Int_t * vCiLevels ) +{ + Gia_Obj_t * pObj; + int i; + if ( vCiLevels == NULL ) + return Gia_ManLevelNum( p ); + assert( Vec_IntSize(vCiLevels) == Gia_ManCiNum(p) ); + Gia_ManCleanLevels( p, Gia_ManObjNum(p) ); + p->nLevels = 0; + Gia_ManForEachCi( p, pObj, i ) + { + Gia_ObjSetLevel( p, pObj, Vec_IntEntry(vCiLevels, i) ); + p->nLevels = Abc_MaxInt( p->nLevels, Gia_ObjLevel(p, pObj) ); + } + Gia_ManForEachObj( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + Gia_ObjSetGateLevel( p, pObj ); + else if ( Gia_ObjIsCo(pObj) ) + Gia_ObjSetCoLevel( p, pObj ); + else continue; + p->nLevels = Abc_MaxInt( p->nLevels, Gia_ObjLevel(p, pObj) ); + } + return p->nLevels; +} + +/**Function************************************************************* + + Synopsis [Compute reverse levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManReverseLevel( Gia_Man_t * p ) +{ + Vec_Int_t * vLevelRev; + Gia_Obj_t * pObj; + int i; + vLevelRev = Vec_IntStart( Gia_ManObjNum(p) ); + Gia_ManForEachAndReverse( p, pObj, i ) + { + int LevelR = Vec_IntEntry( vLevelRev, i ); + if ( Gia_ObjIsMux(p, pObj) ) + { + Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId0(pObj, i), LevelR + 2 ); + Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId1(pObj, i), LevelR + 2 ); + Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId2(p, i), LevelR + 2 ); + } + else if ( Gia_ObjIsXor(pObj) ) + { + Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId0(pObj, i), LevelR + 2 ); + Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId1(pObj, i), LevelR + 2 ); + } + else if ( Gia_ObjIsBuf(pObj) ) + { + Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId0(pObj, i), LevelR ); + } + else + { + Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId0(pObj, i), LevelR + 1 ); + Vec_IntUpdateEntry( vLevelRev, Gia_ObjFaninId1(pObj, i), LevelR + 1 ); + } + } + return vLevelRev; +} + +/**Function************************************************************* + + Synopsis [Compute required levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManRequiredLevel( Gia_Man_t * p ) +{ + Vec_Int_t * vRequired; + Gia_Obj_t * pObj; + int i, LevelMax = 0; + vRequired = Gia_ManReverseLevel( p ); + Gia_ManForEachCi( p, pObj, i ) + LevelMax = Abc_MaxInt( LevelMax, Vec_IntEntry(vRequired, Gia_ObjId(p, pObj)) ); + Gia_ManForEachObj( p, pObj, i ) + Vec_IntWriteEntry( vRequired, i, LevelMax - Vec_IntEntry(vRequired, i) ); + return vRequired; +} + +/**Function************************************************************* + + Synopsis [Compute slacks measured using the number of AIG levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManComputeSlacks( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, nLevels = Gia_ManLevelNum( p ); + Vec_Int_t * vLevelR = Gia_ManReverseLevel( p ); + Vec_Int_t * vSlacks = Vec_IntAlloc( Gia_ManObjNum(p) ); + Gia_ManForEachObj( p, pObj, i ) + Vec_IntPush( vSlacks, nLevels - Gia_ObjLevelId(p, i) - Vec_IntEntry(vLevelR, i) ); + assert( Vec_IntSize(vSlacks) == Gia_ManObjNum(p) ); + Vec_IntFree( vLevelR ); + return vSlacks; +} + +/**Function************************************************************* + + Synopsis [Assigns levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCreateValueRefs( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachObj( p, pObj, i ) + { + pObj->Value = 0; + if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ObjFanin0(pObj)->Value++; + if ( !Gia_ObjIsBuf(pObj) ) + Gia_ObjFanin1(pObj)->Value++; + } + else if ( Gia_ObjIsCo(pObj) ) + Gia_ObjFanin0(pObj)->Value++; + } +} + +/**Function************************************************************* + + Synopsis [Assigns references.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCreateRefs( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + assert( p->pRefs == NULL ); + p->pRefs = ABC_CALLOC( int, Gia_ManObjNum(p) ); + Gia_ManForEachObj( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ObjRefFanin0Inc( p, pObj ); + if ( !Gia_ObjIsBuf(pObj) ) + Gia_ObjRefFanin1Inc( p, pObj ); + if ( Gia_ObjIsMuxId(p, i) ) + Gia_ObjRefFanin2Inc( p, pObj ); + } + else if ( Gia_ObjIsCo(pObj) ) + Gia_ObjRefFanin0Inc( p, pObj ); + } +} +void Gia_ManCreateLitRefs( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + assert( p->pRefs == NULL ); + p->pRefs = ABC_CALLOC( int, 2*Gia_ManObjNum(p) ); + Gia_ManForEachObj( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + { + p->pRefs[Gia_ObjFaninLit0(pObj, i)]++; + p->pRefs[Gia_ObjFaninLit1(pObj, i)]++; + } + else if ( Gia_ObjIsCo(pObj) ) + p->pRefs[Gia_ObjFaninLit0(pObj, i)]++; + } +} + +/**Function************************************************************* + + Synopsis [Assigns references.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Gia_ManCreateMuxRefs( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj, * pCtrl, * pFan0, * pFan1; + int i, * pMuxRefs; + pMuxRefs = ABC_CALLOC( int, Gia_ManObjNum(p) ); + Gia_ManForEachObj( p, pObj, i ) + { + if ( Gia_ObjRecognizeExor( pObj, &pFan0, &pFan1 ) ) + continue; + if ( !Gia_ObjIsMuxType(pObj) ) + continue; + pCtrl = Gia_ObjRecognizeMux( pObj, &pFan0, &pFan1 ); + pMuxRefs[ Gia_ObjId(p, Gia_Regular(pCtrl)) ]++; + } + return pMuxRefs; +} + +/**Function************************************************************* + + Synopsis [Computes the maximum frontier size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManBfsForCrossCut( Gia_Man_t * p ) +{ + Vec_Int_t * vNodes = Vec_IntAlloc( Gia_ManObjNum(p) ); + Vec_Vec_t * vLevels = Gia_ManLevelize( p ); + Vec_Ptr_t * vObjs; + Gia_Obj_t * pObj; + int i, k; + Vec_VecForEachLevel( vLevels, vObjs, i ) + Vec_PtrForEachEntry( Gia_Obj_t *, vObjs, pObj, k ) + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); + Vec_VecFree( vLevels ); + return vNodes; +} + +void Gia_ManDfsForCrossCut_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + if ( Gia_ObjIsCi(pObj) ) + { + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); + return; + } + if ( Gia_ObjIsCo(pObj) ) + { + Gia_ObjFanin0(pObj)->Value++; + Gia_ManDfsForCrossCut_rec( p, Gia_ObjFanin0(pObj), vNodes ); + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); + return; + } + assert( Gia_ObjIsAnd(pObj) ); + Gia_ObjFanin0(pObj)->Value++; + Gia_ObjFanin1(pObj)->Value++; + Gia_ManDfsForCrossCut_rec( p, Gia_ObjFanin0(pObj), vNodes ); + Gia_ManDfsForCrossCut_rec( p, Gia_ObjFanin1(pObj), vNodes ); + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); +} +Vec_Int_t * Gia_ManDfsForCrossCut( Gia_Man_t * p, int fReverse ) +{ + Vec_Int_t * vNodes; + Gia_Obj_t * pObj; + int i; + Gia_ManCleanValue( p ); + vNodes = Vec_IntAlloc( Gia_ManObjNum(p) ); + Gia_ManIncrementTravId( p ); + if ( fReverse ) + { + Gia_ManForEachCoReverse( p, pObj, i ) + if ( !Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) + Gia_ManDfsForCrossCut_rec( p, pObj, vNodes ); + } + else + { + Gia_ManForEachCo( p, pObj, i ) + if ( !Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) + Gia_ManDfsForCrossCut_rec( p, pObj, vNodes ); + } + return vNodes; +} +int Gia_ManCrossCut( Gia_Man_t * p, int fReverse ) +{ + Vec_Int_t * vNodes; + Gia_Obj_t * pObj; + int i, nCutCur = 0, nCutMax = 0; + vNodes = Gia_ManDfsForCrossCut( p, fReverse ); + //vNodes = Gia_ManBfsForCrossCut( p ); + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + { + if ( pObj->Value ) + nCutCur++; + if ( nCutMax < nCutCur ) + nCutMax = nCutCur; + if ( Gia_ObjIsAnd(pObj) ) + { + if ( --Gia_ObjFanin0(pObj)->Value == 0 ) + nCutCur--; + if ( --Gia_ObjFanin1(pObj)->Value == 0 ) + nCutCur--; + } + else if ( Gia_ObjIsCo(pObj) ) + { + if ( --Gia_ObjFanin0(pObj)->Value == 0 ) + nCutCur--; + } + } + Vec_IntFree( vNodes ); + Gia_ManForEachObj( p, pObj, i ) + assert( pObj->Value == 0 ); + return nCutMax; +} + + +/**Function************************************************************* + + Synopsis [Collects PO Ids into one array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManCollectPoIds( Gia_Man_t * p ) +{ + Vec_Int_t * vStart; + int Entry, i; + vStart = Vec_IntAlloc( Gia_ManPoNum(p) ); + Vec_IntForEachEntryStop( p->vCos, Entry, i, Gia_ManPoNum(p) ) + Vec_IntPush( vStart, Entry ); + return vStart; +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ObjIsMuxType( Gia_Obj_t * pNode ) +{ + Gia_Obj_t * pNode0, * pNode1; + // check that the node is regular + assert( !Gia_IsComplement(pNode) ); + // if the node is not AND, this is not MUX + if ( !Gia_ObjIsAnd(pNode) || Gia_ObjIsBuf(pNode) ) + return 0; + // if the children are not complemented, this is not MUX + if ( !Gia_ObjFaninC0(pNode) || !Gia_ObjFaninC1(pNode) ) + return 0; + // get children + pNode0 = Gia_ObjFanin0(pNode); + pNode1 = Gia_ObjFanin1(pNode); + // if the children are not ANDs, this is not MUX + if ( !Gia_ObjIsAnd(pNode0) || !Gia_ObjIsAnd(pNode1) ) + return 0; + // otherwise the node is MUX iff it has a pair of equal grandchildren + return (Gia_ObjFanin0(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC0(pNode1))) || + (Gia_ObjFanin0(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC1(pNode1))) || + (Gia_ObjFanin1(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC0(pNode1))) || + (Gia_ObjFanin1(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC1(pNode1))); +} + + +/**Function************************************************************* + + Synopsis [Recognizes what nodes are inputs of the EXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ObjRecognizeExor( Gia_Obj_t * pObj, Gia_Obj_t ** ppFan0, Gia_Obj_t ** ppFan1 ) +{ + Gia_Obj_t * p0, * p1; + assert( !Gia_IsComplement(pObj) ); + if ( !Gia_ObjIsAnd(pObj) || Gia_ObjIsBuf(pObj) ) + return 0; + assert( Gia_ObjIsAnd(pObj) ); + p0 = Gia_ObjChild0(pObj); + p1 = Gia_ObjChild1(pObj); + if ( !Gia_IsComplement(p0) || !Gia_IsComplement(p1) ) + return 0; + p0 = Gia_Regular(p0); + p1 = Gia_Regular(p1); + if ( !Gia_ObjIsAnd(p0) || !Gia_ObjIsAnd(p1) ) + return 0; + if ( Gia_ObjFanin0(p0) != Gia_ObjFanin0(p1) || Gia_ObjFanin1(p0) != Gia_ObjFanin1(p1) ) + return 0; + if ( Gia_ObjFaninC0(p0) == Gia_ObjFaninC0(p1) || Gia_ObjFaninC1(p0) == Gia_ObjFaninC1(p1) ) + return 0; + if ( ppFan0 ) *ppFan0 = Gia_ObjChild0(p0); + if ( ppFan1 ) *ppFan1 = Gia_ObjChild1(p0); + return 1; +} + +/**Function************************************************************* + + Synopsis [Recognizes what nodes are control and data inputs of a MUX.] + + Description [If the node is a MUX, returns the control variable C. + Assigns nodes T and E to be the then and else variables of the MUX. + Node C is never complemented. Nodes T and E can be complemented. + This function also recognizes EXOR/NEXOR gates as MUXes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Obj_t * Gia_ObjRecognizeMux( Gia_Obj_t * pNode, Gia_Obj_t ** ppNodeT, Gia_Obj_t ** ppNodeE ) +{ + Gia_Obj_t * pNode0, * pNode1; + assert( !Gia_IsComplement(pNode) ); + assert( Gia_ObjIsMuxType(pNode) ); + // get children + pNode0 = Gia_ObjFanin0(pNode); + pNode1 = Gia_ObjFanin1(pNode); + + // find the control variable + if ( Gia_ObjFanin1(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC1(pNode1)) ) + { +// if ( FrGia_IsComplement(pNode1->p2) ) + if ( Gia_ObjFaninC1(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1); + return Gia_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1); + return Gia_ObjChild1(pNode0);//pNode1->p2; + } + } + else if ( Gia_ObjFanin0(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC0(pNode1)) ) + { +// if ( FrGia_IsComplement(pNode1->p1) ) + if ( Gia_ObjFaninC0(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2); + return Gia_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2); + return Gia_ObjChild0(pNode0);//pNode1->p1; + } + } + else if ( Gia_ObjFanin0(pNode0) == Gia_ObjFanin1(pNode1) && (Gia_ObjFaninC0(pNode0) ^ Gia_ObjFaninC1(pNode1)) ) + { +// if ( FrGia_IsComplement(pNode1->p1) ) + if ( Gia_ObjFaninC0(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2); + return Gia_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Gia_Not(Gia_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Gia_Not(Gia_ObjChild0(pNode1));//pNode2->p1); + return Gia_ObjChild0(pNode0);//pNode1->p1; + } + } + else if ( Gia_ObjFanin1(pNode0) == Gia_ObjFanin0(pNode1) && (Gia_ObjFaninC1(pNode0) ^ Gia_ObjFaninC0(pNode1)) ) + { +// if ( FrGia_IsComplement(pNode1->p2) ) + if ( Gia_ObjFaninC1(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1); + return Gia_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Gia_Not(Gia_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Gia_Not(Gia_ObjChild1(pNode1));//pNode2->p2); + return Gia_ObjChild1(pNode0);//pNode1->p2; + } + } + assert( 0 ); // this is not MUX + return NULL; +} +int Gia_ObjRecognizeMuxLits( Gia_Man_t * p, Gia_Obj_t * pNode, int * iLitT, int * iLitE ) +{ + Gia_Obj_t * pNodeT, * pNodeE; + Gia_Obj_t * pCtrl = Gia_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); + assert( pCtrl != NULL ); + *iLitT = Gia_Obj2Lit( p, pNodeT ); + *iLitE = Gia_Obj2Lit( p, pNodeE ); + return Gia_Obj2Lit( p, pCtrl ); +} + + +/**Function************************************************************* + + Synopsis [Dereferences the node's MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_NodeDeref_rec( Gia_Man_t * p, Gia_Obj_t * pNode ) +{ + Gia_Obj_t * pFanin; + int Counter = 0; + if ( Gia_ObjIsCi(pNode) ) + return 0; + assert( Gia_ObjIsAnd(pNode) ); + pFanin = Gia_ObjFanin0(pNode); + assert( Gia_ObjRefNum(p, pFanin) > 0 ); + if ( Gia_ObjRefDec(p, pFanin) == 0 ) + Counter += Gia_NodeDeref_rec( p, pFanin ); + pFanin = Gia_ObjFanin1(pNode); + assert( Gia_ObjRefNum(p, pFanin) > 0 ); + if ( Gia_ObjRefDec(p, pFanin) == 0 ) + Counter += Gia_NodeDeref_rec( p, pFanin ); + return Counter + 1; +} + +/**Function************************************************************* + + Synopsis [References the node's MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_NodeRef_rec( Gia_Man_t * p, Gia_Obj_t * pNode, int fMark ) +{ + Gia_Obj_t * pFanin; + int Counter = 0; + if ( Gia_ObjIsCi(pNode) ) + return 0; + assert( Gia_ObjIsAnd(pNode) ); + if ( fMark ) Gia_ObjSetTravIdCurrent(p, pNode); + pFanin = Gia_ObjFanin0(pNode); + if ( Gia_ObjRefInc(p, pFanin) == 0 ) + Counter += Gia_NodeRef_rec( p, pFanin, fMark ); + pFanin = Gia_ObjFanin1(pNode); + if ( Gia_ObjRefInc(p, pFanin) == 0 ) + Counter += Gia_NodeRef_rec( p, pFanin, fMark ); + return Counter + 1; +} + + +/**Function************************************************************* + + Synopsis [References the node's MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManPoMffcSize( Gia_Man_t * p ) +{ + Gia_ManCreateRefs( p ); + return Gia_NodeDeref_rec( p, Gia_ObjFanin0(Gia_ManPo(p, 0)) ); +} + +/**Function************************************************************* + + Synopsis [Returns the number of internal nodes in the MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_NodeMffcSize( Gia_Man_t * p, Gia_Obj_t * pNode ) +{ + int ConeSize1, ConeSize2; + assert( !Gia_IsComplement(pNode) ); + assert( Gia_ObjIsCand(pNode) ); + ConeSize1 = Gia_NodeDeref_rec( p, pNode ); + ConeSize2 = Gia_NodeRef_rec( p, pNode, 0 ); + assert( ConeSize1 == ConeSize2 ); + assert( ConeSize1 >= 0 ); + return ConeSize1; +} +int Gia_NodeMffcSizeMark( Gia_Man_t * p, Gia_Obj_t * pNode ) +{ + int ConeSize1, ConeSize2; + assert( !Gia_IsComplement(pNode) ); + assert( Gia_ObjIsCand(pNode) ); + ConeSize1 = Gia_NodeDeref_rec( p, pNode ); + Gia_ManIncrementTravId( p ); + ConeSize2 = Gia_NodeRef_rec( p, pNode, 1 ); + assert( ConeSize1 == ConeSize2 ); + assert( ConeSize1 >= 0 ); + return ConeSize1; +} + +/**Function************************************************************* + + Synopsis [Returns the number of internal nodes in the MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_NodeCollect_rec( Gia_Man_t * p, Gia_Obj_t * pNode, Vec_Int_t * vSupp ) +{ + if ( Gia_ObjIsTravIdCurrent(p, pNode) ) + return; + Gia_ObjSetTravIdCurrent(p, pNode); + if ( Gia_ObjRefNum(p, pNode) || Gia_ObjIsCi(pNode) ) + { + Vec_IntPush( vSupp, Gia_ObjId(p, pNode) ); + return; + } + assert( Gia_ObjIsAnd(pNode) ); + Gia_NodeCollect_rec( p, Gia_ObjFanin0(pNode), vSupp ); + Gia_NodeCollect_rec( p, Gia_ObjFanin1(pNode), vSupp ); +} +int Gia_NodeMffcSizeSupp( Gia_Man_t * p, Gia_Obj_t * pNode, Vec_Int_t * vSupp ) +{ + int ConeSize1, ConeSize2; + assert( !Gia_IsComplement(pNode) ); + assert( Gia_ObjIsAnd(pNode) ); + Vec_IntClear( vSupp ); + Gia_ManIncrementTravId( p ); + ConeSize1 = Gia_NodeDeref_rec( p, pNode ); + Gia_NodeCollect_rec( p, Gia_ObjFanin0(pNode), vSupp ); + Gia_NodeCollect_rec( p, Gia_ObjFanin1(pNode), vSupp ); + ConeSize2 = Gia_NodeRef_rec( p, pNode, 0 ); + assert( ConeSize1 == ConeSize2 ); + assert( ConeSize1 >= 0 ); + return ConeSize1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_NodeMffcMapping_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vMapping, Vec_Int_t * vSupp ) +{ + Gia_Obj_t * pObj; int i, iNode, Count = 1; + if ( !iObj || Vec_IntEntry(vMapping, iObj) ) + return 0; + pObj = Gia_ManObj( p, iObj ); + if ( Gia_ObjIsCi(pObj) ) + return 0; + Gia_NodeMffcSizeSupp( p, pObj, vSupp ); + Vec_IntSort( vSupp, 0 ); + Vec_IntWriteEntry( vMapping, iObj, Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, Vec_IntSize(vSupp) ); + Vec_IntAppend( vMapping, vSupp ); + Vec_IntPush( vMapping, iObj ); + Vec_IntForEachEntry( vSupp, iNode, i ) + Count += Gia_NodeMffcMapping_rec( p, iNode, vMapping, vSupp ); + return Count; +} +int Gia_NodeMffcMapping( Gia_Man_t * p ) +{ + int i, Id, Count = 0; + int * pRefsOld; + Vec_Int_t * vMapping, * vSupp = Vec_IntAlloc( 100 ); + vMapping = Vec_IntAlloc( 2 * Gia_ManObjNum(p) ); + Vec_IntFill( vMapping, Gia_ManObjNum(p), 0 ); + pRefsOld = p->pRefs; p->pRefs = NULL; + Gia_ManCreateRefs( p ); + Gia_ManForEachCoDriverId( p, Id, i ) + Count += Gia_NodeMffcMapping_rec( p, Id, vMapping, vSupp ); + p->pRefs = pRefsOld; + Vec_IntFree( vSupp ); + p->vMapping = vMapping; + //printf( "Mapping is %.2fx larger than AIG manager.\n", 1.0*Vec_IntSize(vMapping)/Gia_ManObjNum(p) ); + return Count; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if AIG has dangling nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManHasDangling( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, Counter = 0; + Gia_ManForEachObj( p, pObj, i ) + { + pObj->fMark0 = 0; + if ( Gia_ObjIsCo(pObj) ) + Gia_ObjFanin0(pObj)->fMark0 = 1; + else if ( Gia_ObjIsMux(p, pObj) ) + { + Gia_ObjFanin0(pObj)->fMark0 = 1; + Gia_ObjFanin1(pObj)->fMark0 = 1; + Gia_ObjFanin2(p, pObj)->fMark0 = 1; + } + else if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ObjFanin0(pObj)->fMark0 = 1; + Gia_ObjFanin1(pObj)->fMark0 = 1; + } + } + Gia_ManForEachAnd( p, pObj, i ) + Counter += !pObj->fMark0; + Gia_ManCleanMark0( p ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if AIG has dangling nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManMarkDangling( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, Counter = 0; + Gia_ManForEachObj( p, pObj, i ) + { + pObj->fMark0 = 0; + if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ObjFanin0(pObj)->fMark0 = 1; + Gia_ObjFanin1(pObj)->fMark0 = 1; + } + else if ( Gia_ObjIsCo(pObj) ) + Gia_ObjFanin0(pObj)->fMark0 = 1; + } + Gia_ManForEachAnd( p, pObj, i ) + Counter += !pObj->fMark0; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if AIG has dangling nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManGetDangling( Gia_Man_t * p ) +{ + Vec_Int_t * vDangles; + Gia_Obj_t * pObj; + int i; + Gia_ManForEachObj( p, pObj, i ) + { + pObj->fMark0 = 0; + if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ObjFanin0(pObj)->fMark0 = 1; + Gia_ObjFanin1(pObj)->fMark0 = 1; + } + else if ( Gia_ObjIsCo(pObj) ) + Gia_ObjFanin0(pObj)->fMark0 = 1; + } + vDangles = Vec_IntAlloc( 100 ); + Gia_ManForEachAnd( p, pObj, i ) + if ( !pObj->fMark0 ) + Vec_IntPush( vDangles, i ); + Gia_ManCleanMark0( p ); + return vDangles; +} +/**Function************************************************************* + + Synopsis [Verbose printing of the AIG node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ObjPrint( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( pObj == NULL ) + { + printf( "Object is NULL." ); + return; + } + if ( Gia_IsComplement(pObj) ) + { + printf( "Compl " ); + pObj = Gia_Not(pObj); + } + assert( !Gia_IsComplement(pObj) ); + printf( "Obj %4d : ", Gia_ObjId(p, pObj) ); + if ( Gia_ObjIsConst0(pObj) ) + printf( "constant 0" ); + else if ( Gia_ObjIsPi(p, pObj) ) + printf( "PI" ); + else if ( Gia_ObjIsPo(p, pObj) ) + printf( "PO( %4d%s )", Gia_ObjFaninId0p(p, pObj), (Gia_ObjFaninC0(pObj)? "\'" : " ") ); + else if ( Gia_ObjIsCi(pObj) ) + printf( "RO( %4d%s )", Gia_ObjFaninId0p(p, Gia_ObjRoToRi(p, pObj)), (Gia_ObjFaninC0(Gia_ObjRoToRi(p, pObj))? "\'" : " ") ); + else if ( Gia_ObjIsCo(pObj) ) + printf( "RI( %4d%s )", Gia_ObjFaninId0p(p, pObj), (Gia_ObjFaninC0(pObj)? "\'" : " ") ); +// else if ( Gia_ObjIsBuf(pObj) ) +// printf( "BUF( %d%s )", Gia_ObjFaninId0p(p, pObj), (Gia_ObjFaninC0(pObj)? "\'" : " ") ); + else if ( Gia_ObjIsXor(pObj) ) + printf( "XOR( %4d%s, %4d%s )", + Gia_ObjFaninId0p(p, pObj), (Gia_ObjFaninC0(pObj)? "\'" : " "), + Gia_ObjFaninId1p(p, pObj), (Gia_ObjFaninC1(pObj)? "\'" : " ") ); + else if ( Gia_ObjIsMuxId(p, Gia_ObjId(p, pObj)) ) + printf( "MUX( %4d%s, %4d%s, %4d%s )", + Gia_ObjFaninId2p(p, pObj), (Gia_ObjFaninC2(p, pObj)? "\'" : " "), + Gia_ObjFaninId1p(p, pObj), (Gia_ObjFaninC1(pObj)? "\'" : " "), + Gia_ObjFaninId0p(p, pObj), (Gia_ObjFaninC0(pObj)? "\'" : " ") ); + else + printf( "AND( %4d%s, %4d%s )", + Gia_ObjFaninId0p(p, pObj), (Gia_ObjFaninC0(pObj)? "\'" : " "), + Gia_ObjFaninId1p(p, pObj), (Gia_ObjFaninC1(pObj)? "\'" : " ") ); + if ( p->pRefs ) + printf( " (refs = %3d)", Gia_ObjRefNum(p, pObj) ); + if ( pObj->fMark0 ) + printf( " mark0" ); + if ( pObj->fMark1 ) + printf( " mark1" ); + if ( Gia_ManHasMapping(p) && Gia_ObjIsLut(p, Gia_ObjId(p, pObj)) ) + { + int i, iFan; + printf( " Cut = { " ); + Gia_LutForEachFanin( p, Gia_ObjId(p, pObj), iFan, i ) + printf( "%d ", iFan ); + printf( "}" ); + } + if ( Gia_ManHasMapping2(p) && Gia_ObjIsLut2(p, Gia_ObjId(p, pObj)) ) + { + int i, iFan; + printf( " Cut = { " ); + Gia_LutForEachFanin2( p, Gia_ObjId(p, pObj), iFan, i ) + printf( "%d ", iFan ); + printf( "}" ); + } + printf( "\n" ); +/* + if ( p->pRefs ) + { + Gia_Obj_t * pFanout; + int i; + int iFan = -1; // Suppress "might be used uninitialized" + printf( "\nFanouts:\n" ); + Gia_ObjForEachFanout( p, pObj, pFanout, iFan, i ) + { + printf( " " ); + printf( "Node %4d : ", Gia_ObjId(pFanout) ); + if ( Gia_ObjIsPo(pFanout) ) + printf( "PO( %4d%s )", Gia_ObjFanin0(pFanout)->Id, (Gia_ObjFaninC0(pFanout)? "\'" : " ") ); + else if ( Gia_ObjIsBuf(pFanout) ) + printf( "BUF( %d%s )", Gia_ObjFanin0(pFanout)->Id, (Gia_ObjFaninC0(pFanout)? "\'" : " ") ); + else + printf( "AND( %4d%s, %4d%s )", + Gia_ObjFanin0(pFanout)->Id, (Gia_ObjFaninC0(pFanout)? "\'" : " "), + Gia_ObjFanin1(pFanout)->Id, (Gia_ObjFaninC1(pFanout)? "\'" : " ") ); + printf( "\n" ); + } + return; + } +*/ +} +void Gia_ManPrint( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + printf( "GIA manager has %d ANDs, %d XORs, %d MUXes.\n", + Gia_ManAndNum(p) - Gia_ManXorNum(p) - Gia_ManMuxNum(p), Gia_ManXorNum(p), Gia_ManMuxNum(p) ); + Gia_ManForEachObj( p, pObj, i ) + Gia_ObjPrint( p, pObj ); +} +void Gia_ManPrintCo_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ManPrintCo_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ManPrintCo_rec( p, Gia_ObjFanin1(pObj) ); + if ( Gia_ObjIsMux(p, pObj) ) + Gia_ManPrintCo_rec( p, Gia_ObjFanin2(p, pObj) ); + } + Gia_ObjPrint( p, pObj ); +} +void Gia_ManPrintCo( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + assert( Gia_ObjIsCo(pObj) ); + printf( "TFI cone of CO number %d:\n", Gia_ObjCioId(pObj) ); + Gia_ManPrintCo_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ObjPrint( p, pObj ); +} + +void Gia_ManPrintCollect_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) +{ + if ( Vec_IntFind(vNodes, Gia_ObjId(p, pObj)) >= 0 ) + return; + assert( Gia_ObjIsAnd(pObj) ); + Gia_ManPrintCollect_rec( p, Gia_ObjFanin0(pObj), vNodes ); + Gia_ManPrintCollect_rec( p, Gia_ObjFanin1(pObj), vNodes ); + if ( Gia_ObjIsMux(p, pObj) ) + Gia_ManPrintCollect_rec( p, Gia_ObjFanin2(p, pObj), vNodes ); + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); +} +void Gia_ManPrintCone( Gia_Man_t * p, Gia_Obj_t * pObj, int * pLeaves, int nLeaves, Vec_Int_t * vNodes ) +{ + int i; + Vec_IntClear( vNodes ); + for ( i = 0; i < nLeaves; i++ ) + Vec_IntPush( vNodes, pLeaves[i] ); + Gia_ManPrintCollect_rec( p, pObj, vNodes ); + printf( "GIA logic cone for node %d:\n", Gia_ObjId(p, pObj) ); + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + Gia_ObjPrint( p, pObj ); +} +void Gia_ManPrintConeMulti( Gia_Man_t * p, Vec_Int_t * vObjs, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ) +{ + Gia_Obj_t * pObj; + int i; + Vec_IntClear( vNodes ); + Vec_IntAppend( vNodes, vLeaves ); + Gia_ManForEachObjVec( vObjs, p, pObj, i ) + Gia_ManPrintCollect_rec( p, pObj, vNodes ); + printf( "GIA logic cone for %d nodes:\n", Vec_IntSize(vObjs) ); + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + Gia_ObjPrint( p, pObj ); +} + +void Gia_ManPrintCollect2_rec( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vNodes ) +{ + if ( Vec_IntFind(vNodes, Gia_ObjId(p, pObj)) >= 0 ) + return; + if ( Gia_ObjIsCo(pObj) || Gia_ObjIsAnd(pObj) ) + Gia_ManPrintCollect2_rec( p, Gia_ObjFanin0(pObj), vNodes ); + if ( Gia_ObjIsAnd(pObj) ) + Gia_ManPrintCollect2_rec( p, Gia_ObjFanin1(pObj), vNodes ); + if ( Gia_ObjIsMux(p, pObj) ) + Gia_ManPrintCollect2_rec( p, Gia_ObjFanin2(p, pObj), vNodes ); + Vec_IntPush( vNodes, Gia_ObjId(p, pObj) ); +} +void Gia_ManPrintCone2( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + Vec_Int_t * vNodes; + int i; + vNodes = Vec_IntAlloc( 100 ); + Gia_ManPrintCollect2_rec( p, pObj, vNodes ); + printf( "GIA logic cone for node %d:\n", Gia_ObjId(p, pObj) ); + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + Gia_ObjPrint( p, pObj ); + Vec_IntFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Complements the constraint outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManInvertConstraints( Gia_Man_t * pAig ) +{ + Gia_Obj_t * pObj; + int i; + if ( Gia_ManConstrNum(pAig) == 0 ) + return; + Gia_ManForEachPo( pAig, pObj, i ) + if ( i >= Gia_ManPoNum(pAig) - Gia_ManConstrNum(pAig) ) + Gia_ObjFlipFaninC0( pObj ); +} +void Gia_ManInvertPos( Gia_Man_t * pAig ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachPo( pAig, pObj, i ) + Gia_ObjFlipFaninC0( pObj ); +} + +/**Function************************************************************* + + Synopsis [Testing the speedup due to grouping POs into batches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCollectObjs_rec( Gia_Man_t * p, int iObjId, Vec_Int_t * vObjs, int Limit ) +{ + Gia_Obj_t * pObj; + if ( Vec_IntSize(vObjs) == Limit ) + return; + if ( Gia_ObjIsTravIdCurrentId(p, iObjId) ) + return; + Gia_ObjSetTravIdCurrentId(p, iObjId); + pObj = Gia_ManObj( p, iObjId ); + if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ManCollectObjs_rec( p, Gia_ObjFaninId0p(p, pObj), vObjs, Limit ); + if ( Vec_IntSize(vObjs) == Limit ) + return; + Gia_ManCollectObjs_rec( p, Gia_ObjFaninId1p(p, pObj), vObjs, Limit ); + if ( Vec_IntSize(vObjs) == Limit ) + return; + } + Vec_IntPush( vObjs, iObjId ); +} +unsigned * Gia_ManComputePoTruthTables( Gia_Man_t * p, int nBytesMax ) +{ + int nVars = Gia_ManPiNum(p); + int nTruthWords = Abc_TruthWordNum( nVars ); + int nTruths = nBytesMax / (sizeof(unsigned) * nTruthWords); + int nTotalNodes = 0, nRounds = 0; + Vec_Int_t * vObjs; + Gia_Obj_t * pObj; + abctime clk = Abc_Clock(); + int i; + printf( "Var = %d. Words = %d. Truths = %d.\n", nVars, nTruthWords, nTruths ); + vObjs = Vec_IntAlloc( nTruths ); + Gia_ManIncrementTravId( p ); + Gia_ManForEachPo( p, pObj, i ) + { + Gia_ManCollectObjs_rec( p, Gia_ObjFaninId0p(p, pObj), vObjs, nTruths ); + if ( Vec_IntSize(vObjs) == nTruths ) + { + nRounds++; +// printf( "%d ", i ); + nTotalNodes += Vec_IntSize( vObjs ); + Vec_IntClear( vObjs ); + Gia_ManIncrementTravId( p ); + } + } +// printf( "\n" ); + nTotalNodes += Vec_IntSize( vObjs ); + Vec_IntFree( vObjs ); + + printf( "Rounds = %d. Objects = %d. Total = %d. ", nRounds, Gia_ManObjNum(p), nTotalNodes ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + + return NULL; +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if the manager are structural identical.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCompare( Gia_Man_t * p1, Gia_Man_t * p2 ) +{ + Gia_Obj_t * pObj1, * pObj2; + int i; + if ( Gia_ManObjNum(p1) != Gia_ManObjNum(p2) ) + { + printf( "AIGs have different number of objects.\n" ); + return 0; + } + Gia_ManCleanValue( p1 ); + Gia_ManCleanValue( p2 ); + Gia_ManForEachObj( p1, pObj1, i ) + { + pObj2 = Gia_ManObj( p2, i ); + if ( memcmp( pObj1, pObj2, sizeof(Gia_Obj_t) ) ) + { + printf( "Objects %d are different.\n", i ); + return 0; + } + if ( p1->pReprs && p2->pReprs ) + { + if ( memcmp( &p1->pReprs[i], &p2->pReprs[i], sizeof(Gia_Rpr_t) ) ) + { + printf( "Representatives of objects %d are different.\n", i ); + return 0; + } + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Marks nodes that appear as faninis of other nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManMarkFanoutDrivers( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachObj( p, pObj, i ) + { + pObj->fMark0 = 0; + if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ObjFanin0(pObj)->fMark0 = 1; + Gia_ObjFanin1(pObj)->fMark0 = 1; + } + else if ( Gia_ObjIsCo(pObj) ) + Gia_ObjFanin0(pObj)->fMark0 = 1; + } +} + + +/**Function************************************************************* + + Synopsis [Swaps PO number 0 with PO number i.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManSwapPos( Gia_Man_t * p, int i ) +{ + int Lit0, LitI; + assert( i >= 0 && i < Gia_ManPoNum(p) ); + if ( i == 0 ) + return; + Lit0 = Gia_ObjFaninLit0p( p, Gia_ManPo(p, 0) ); + LitI = Gia_ObjFaninLit0p( p, Gia_ManPo(p, i) ); + Gia_ManPatchCoDriver( p, 0, LitI ); + Gia_ManPatchCoDriver( p, i, Lit0 ); +} + +/**Function************************************************************* + + Synopsis [Save/load value from file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManSaveValue( Gia_Man_t * p ) +{ + Vec_Int_t * vValues; + Gia_Obj_t * pObj; + int i; + vValues = Vec_IntAlloc( Gia_ManObjNum(p) ); + Gia_ManForEachObj( p, pObj, i ) + Vec_IntPush( vValues, pObj->Value ); + return vValues; +} +void Gia_ManLoadValue( Gia_Man_t * p, Vec_Int_t * vValues ) +{ + Gia_Obj_t * pObj; + int i; + Gia_ManForEachObj( p, pObj, i ) + pObj->Value = Vec_IntEntry(vValues, i); +} + + +/**Function************************************************************* + + Synopsis [Returns the array containing the first fanout of each object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManFirstFanouts( Gia_Man_t * p ) +{ + Vec_Int_t * vFans = Vec_IntStart( Gia_ManObjNum(p) ); + Gia_Obj_t * pObj; + int i; + Gia_ManForEachObj( p, pObj, i ) + { + if ( Gia_ObjIsAnd(pObj) ) + { + if ( Vec_IntEntry(vFans, Gia_ObjFaninId0p(p, pObj)) == 0 ) + Vec_IntWriteEntry(vFans, Gia_ObjFaninId0p(p, pObj), i); + if ( Vec_IntEntry(vFans, Gia_ObjFaninId1p(p, pObj)) == 0 ) + Vec_IntWriteEntry(vFans, Gia_ObjFaninId1p(p, pObj), i); + if ( Gia_ObjIsMuxId(p, i) && Vec_IntEntry(vFans, Gia_ObjFaninId2p(p, pObj)) == 0 ) + Vec_IntWriteEntry(vFans, Gia_ObjFaninId2p(p, pObj), i); + } + else if ( Gia_ObjIsCo(pObj) ) + { + if ( Vec_IntEntry(vFans, Gia_ObjFaninId0p(p, pObj)) == 0 ) + Vec_IntWriteEntry(vFans, Gia_ObjFaninId0p(p, pObj), i); + } + } + return vFans; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if AIG has choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManHasChoices_very_old( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, Counter1 = 0, Counter2 = 0; + int nFailNoRepr = 0; + int nFailHaveRepr = 0; + int nChoiceNodes = 0; + int nChoices = 0; + if ( p->pReprs == NULL || p->pNexts == NULL ) + return 0; + // check if there are any representatives + Gia_ManForEachObj( p, pObj, i ) + { + if ( Gia_ObjReprObj( p, Gia_ObjId(p, pObj) ) ) + { +// printf( "%d ", i ); + Counter1++; + } +// if ( Gia_ObjNext( p, Gia_ObjId(p, pObj) ) ) +// Counter2++; + } +// printf( "\n" ); + Gia_ManForEachObj( p, pObj, i ) + { +// if ( Gia_ObjReprObj( p, Gia_ObjId(p, pObj) ) ) +// Counter1++; + if ( Gia_ObjNext( p, Gia_ObjId(p, pObj) ) ) + { +// printf( "%d ", i ); + Counter2++; + } + } +// printf( "\n" ); + if ( Counter1 == 0 ) + { + printf( "Warning: AIG has repr data-strucure but not reprs.\n" ); + return 0; + } + printf( "%d nodes have reprs.\n", Counter1 ); + printf( "%d nodes have nexts.\n", Counter2 ); + // check if there are any internal nodes without fanout + // make sure all nodes without fanout have representatives + // make sure all nodes with fanout have no representatives + ABC_FREE( p->pRefs ); + Gia_ManCreateRefs( p ); + Gia_ManForEachAnd( p, pObj, i ) + { + if ( Gia_ObjRefNum(p, pObj) == 0 ) + { + if ( Gia_ObjReprObj( p, Gia_ObjId(p, pObj) ) == NULL ) + nFailNoRepr++; + else + nChoices++; + } + else + { + if ( Gia_ObjReprObj( p, Gia_ObjId(p, pObj) ) != NULL ) + nFailHaveRepr++; + if ( Gia_ObjNextObj( p, Gia_ObjId(p, pObj) ) != NULL ) + nChoiceNodes++; + } + if ( Gia_ObjReprObj( p, i ) ) + assert( Gia_ObjRepr(p, i) < i ); + } + if ( nChoices == 0 ) + return 0; + if ( nFailNoRepr ) + { + printf( "Gia_ManHasChoices_very_old(): Error: %d internal nodes have no fanout and no repr.\n", nFailNoRepr ); +// return 0; + } + if ( nFailHaveRepr ) + { + printf( "Gia_ManHasChoices_very_old(): Error: %d internal nodes have both fanout and repr.\n", nFailHaveRepr ); +// return 0; + } +// printf( "Gia_ManHasChoices_very_old(): AIG has %d choice nodes with %d choices.\n", nChoiceNodes, nChoices ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Proving multi-output properties.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManGroupProve( Gia_Man_t * pInit, char * pCommLine, int nGroupSize, int fVerbose ) +{ + Abc_Frame_t * pAbc = Abc_FrameReadGlobalFrame(); + Gia_Man_t * p = Gia_ManDup( pInit ); + Gia_Man_t * pGroup; + Vec_Int_t * vOuts; + Vec_Int_t * vOutMap; + Vec_Ptr_t * vCexes; + int i, k, nGroupCur, nGroups; + abctime clk, timeComm = 0; + abctime timeStart = Abc_Clock(); + // pre-conditions + assert( nGroupSize > 0 ); + assert( pCommLine != NULL ); + assert( p->nConstrs == 0 ); + Abc_Print( 1, "RUNNING MultiProve: Group size = %d. Command line = \"%s\".\n", nGroupSize, pCommLine ); + // create output map + vOuts = Vec_IntStartNatural( Gia_ManPoNum(p) ); + vOutMap = Vec_IntAlloc( Gia_ManPoNum(p) ); + vCexes = Vec_PtrAlloc( Gia_ManPoNum(p) ); + nGroups = Gia_ManPoNum(p) / nGroupSize + (int)((Gia_ManPoNum(p) % nGroupSize) > 0); + for ( i = 0; i < nGroups; i++ ) + { + // derive the group + nGroupCur = ((i + 1) * nGroupSize < Gia_ManPoNum(p)) ? nGroupSize : Gia_ManPoNum(p) - i * nGroupSize; + pGroup = Gia_ManDupCones( p, Vec_IntArray(vOuts) + i * nGroupSize, nGroupCur, 0 ); + Abc_Print( 1, "GROUP %4d : %4d <= PoId < %4d : ", i, i * nGroupSize, i * nGroupSize + nGroupCur ); + // set the current GIA + Abc_FrameUpdateGia( pAbc, pGroup ); + // solve the group + clk = Abc_Clock(); + Cmd_CommandExecute( pAbc, pCommLine ); + timeComm += Abc_Clock() - clk; + // get the solution status + if ( nGroupSize == 1 ) + { + Vec_IntPush( vOutMap, Abc_FrameReadProbStatus(pAbc) ); + Vec_PtrPush( vCexes, Abc_FrameReadCex(pAbc) ); + } + else // if ( nGroupSize > 1 ) + { + Vec_Int_t * vStatusCur = Abc_FrameReadPoStatuses( pAbc ); + Vec_Ptr_t * vCexesCur = Abc_FrameReadCexVec( pAbc ); + assert( vStatusCur != NULL ); // only works for "bmc3" and "pdr" +// assert( vCexesCur != NULL ); + for ( k = 0; k < nGroupCur; k++ ) + { + Vec_IntPush( vOutMap, Vec_IntEntry(vStatusCur, k) ); + Vec_PtrPush( vCexes, vCexesCur ? Vec_PtrEntry(vCexesCur, k) : NULL ); + } + } + } + assert( Vec_PtrSize(vCexes) == Gia_ManPoNum(p) ); + assert( Vec_IntSize(vOutMap) == Gia_ManPoNum(p) ); + // set CEXes + if ( Vec_PtrCountZero(vCexes) < Vec_PtrSize(vCexes) ) + Abc_FrameReplaceCexVec( pAbc, &vCexes ); + else // there is no CEXes + Vec_PtrFree( vCexes ); + // report the result + Abc_Print( 1, "SUMMARY: " ); + Abc_Print( 1, "Properties = %6d. ", Gia_ManPoNum(p) ); + Abc_Print( 1, "UNSAT = %6d. ", Vec_IntCountEntry(vOutMap, 1) ); + Abc_Print( 1, "SAT = %6d. ", Vec_IntCountEntry(vOutMap, 0) ); + Abc_Print( 1, "UNDEC = %6d. ", Vec_IntCountEntry(vOutMap, -1) ); + Abc_Print( 1, "\n" ); + Abc_PrintTime( 1, "Command time", timeComm ); + Abc_PrintTime( 1, "Total time ", Abc_Clock() - timeStart ); + // cleanup + Vec_IntFree( vOuts ); + Gia_ManStop( p ); + return vOutMap; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Gia_ManPoXSim( Gia_Man_t * p, int nFrames, int fVerbose ) +{ + Vec_Int_t * vRes; + Gia_Obj_t * pObj; + int f, k, nLeft = Gia_ManPoNum(p); + vRes = Vec_IntAlloc( Gia_ManPoNum(p) ); + Vec_IntFill( vRes, Gia_ManPoNum(p), nFrames ); + Gia_ObjTerSimSet0( Gia_ManConst0(p) ); + Gia_ManForEachRi( p, pObj, k ) + Gia_ObjTerSimSet0( pObj ); + for ( f = 0; f < nFrames; f++ ) + { + Gia_ManForEachPi( p, pObj, k ) + Gia_ObjTerSimSetX( pObj ); + Gia_ManForEachRo( p, pObj, k ) + Gia_ObjTerSimRo( p, pObj ); + Gia_ManForEachAnd( p, pObj, k ) + Gia_ObjTerSimAnd( pObj ); + Gia_ManForEachCo( p, pObj, k ) + Gia_ObjTerSimCo( pObj ); + if ( fVerbose ) + { + Gia_ManForEachPo( p, pObj, k ) + Gia_ObjTerSimPrint( pObj ); + printf( "\n" ); + } + Gia_ManForEachPo( p, pObj, k ) + if ( Vec_IntEntry(vRes, k) == nFrames && Gia_ObjTerSimGetX(pObj) ) + Vec_IntWriteEntry(vRes, k, f), nLeft--; + if ( nLeft == 0 ) + break; + } + if ( fVerbose ) + { + if ( nLeft == 0 ) + printf( "Simulation converged after %d frames.\n", f+1 ); + else + printf( "Simulation terminated after %d frames.\n", nFrames ); + } +// Vec_IntPrint( vRes ); + return vRes; +} + +#define MAX_LUT_SIZE 8 +typedef struct Gia_MapLut_t_ +{ + int Type; // node type: PI=1, PO=2, LUT=3 + int Out; // ID + int StartId; // -1 + int nFans; // fanin count + float Delay; // 0.0 + int pFans[MAX_LUT_SIZE]; // fanin IDs + unsigned pTruth[MAX_LUT_SIZE<6?1:(1<<(MAX_LUT_SIZE-5))]; // the truth table +} Gia_MapLut_t; + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_AigerWriteLut( Gia_Man_t * p, char * pFileName ) +{ + Gia_Obj_t * pObj; + int i, k, iFan, iLut = 0; + int LutSizeMax = Gia_ManLutSizeMax( p ); + int nUints = Abc_TruthWordNum(LutSizeMax); + int nLuts = 1 + Gia_ManCiNum(p) + Gia_ManCoNum(p) + Gia_ManLutNum(p); + Gia_MapLut_t * pLuts = ABC_CALLOC( Gia_MapLut_t, nLuts ); + Vec_Wrd_t * vTruths = Vec_WrdStart( Gia_ManObjNum(p) ); + assert( LutSizeMax <= 6 ); + // set obj numbers + // constant + pLuts->Type = 3; + memset( pLuts->pTruth, 0xFF, sizeof(unsigned) * nUints ); + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = pLuts[iLut].Out = Abc_Var2Lit( iLut, 0 ); + iLut++; + // inputs + Gia_ManForEachCi( p, pObj, i ) + { + pLuts[iLut].Type = 1; + memset( pLuts[iLut].pTruth, 0xAA, sizeof(unsigned) * nUints ); + pObj->Value = pLuts[iLut].Out = Abc_Var2Lit( iLut, 0 ); + iLut++; + } + // nodes + Gia_ManForEachObj( p, pObj, i ) + if ( i && Gia_ObjIsLut(p, i) ) + { + word truth; + pLuts[iLut].Type = 3; + Gia_LutForEachFanin( p, i, iFan, k ) + pLuts[iLut].pFans[k] = Gia_ManObj(p, iFan)->Value; + pLuts[iLut].nFans = k; + truth = Gia_LutComputeTruth6(p, i, vTruths); + memcpy( pLuts[iLut].pTruth, &truth, sizeof(word) ); + pObj->Value = pLuts[iLut].Out = Abc_Var2Lit( iLut, 0 ); + iLut++; + } + // outputs + Gia_ManForEachCo( p, pObj, i ) + { + pLuts[iLut].Type = 2; + pLuts[iLut].pFans[0] = Gia_ObjFanin0(pObj)->Value; + if ( Gia_ObjFaninC0(pObj) ^ Gia_ObjIsConst0(Gia_ObjFanin0(pObj)) ) + memset( pLuts[iLut].pTruth, 0x55, sizeof(unsigned) * nUints ); + else + memset( pLuts[iLut].pTruth, 0xAA, sizeof(unsigned) * nUints ); + pLuts[iLut].nFans = 1; + pObj->Value = pLuts[iLut].Out = Abc_Var2Lit( iLut, 0 ); + iLut++; + } + assert( iLut == nLuts ); + // dump into a file + { + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + printf( "Cannot open file \"%s\" for writing.\n", pFileName ); + else + { + int nSize1 = nLuts * sizeof(Gia_MapLut_t); + int nSize2 = fwrite( pLuts, 1, nSize1, pFile ); + assert( nSize1 == nSize2 ); + printf( "Successfully dumped %d bytes of binary data.\n", nSize1 ); + } + fclose( pFile ); + } + ABC_FREE( pLuts ); + Vec_WrdFree( vTruths ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_DumpLutSizeDistrib( Gia_Man_t * p, char * pFileName ) +{ + FILE * pTable = fopen( pFileName, "a+" ); + int i, Counts[10] = {0}; + Gia_ManForEachLut( p, i ) + if ( Gia_ObjLutSize(p, i) > 0 && Gia_ObjLutSize(p, i) < 10 ) + Counts[ Gia_ObjLutSize(p, i) ]++; + fprintf( pTable, "%s", p->pName ); + for ( i = 1; i < 10; i++ ) + fprintf( pTable, " %d", Counts[i] ); + fprintf( pTable, "\n" ); + fclose( pTable ); +} + +/**Function************************************************************* + + Synopsis [Check if two logic cones have overlap.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManCheckSuppMark_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( pObj->fMark0 ) + return; + pObj->fMark0 = 1; + if ( Gia_ObjIsCi(pObj) ) + return; + Gia_ManCheckSuppMark_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ManCheckSuppMark_rec( p, Gia_ObjFanin1(pObj) ); +} +void Gia_ManCheckSuppUnmark_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( !pObj->fMark0 ) + return; + pObj->fMark0 = 0; + if ( Gia_ObjIsCi(pObj) ) + return; + Gia_ManCheckSuppUnmark_rec( p, Gia_ObjFanin0(pObj) ); + Gia_ManCheckSuppUnmark_rec( p, Gia_ObjFanin1(pObj) ); +} +int Gia_ManCheckSupp_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( pObj->fMark0 ) + return 1; + if ( Gia_ObjIsCi(pObj) ) + return 0; + if ( Gia_ManCheckSupp_rec( p, Gia_ObjFanin0(pObj) ) ) + return 1; + return Gia_ManCheckSupp_rec( p, Gia_ObjFanin1(pObj) ); +} +int Gia_ManCheckSuppOverlap( Gia_Man_t * p, int iNode1, int iNode2 ) +{ + int Result; + if ( iNode1 == 0 || iNode2 == 0 ) + return 0; + Gia_ManCheckSuppMark_rec( p, Gia_ManObj(p, iNode1) ); + Result = Gia_ManCheckSupp_rec( p, Gia_ManObj(p, iNode2) ); + Gia_ManCheckSuppUnmark_rec( p, Gia_ManObj(p, iNode1) ); + return Result; +} + + +/**Function************************************************************* + + Synopsis [Count PIs with fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCountPisWithFanout( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, Count = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->fMark0 = 0; + Gia_ManForEachAnd( p, pObj, i ) + { + Gia_ObjFanin0(pObj)->fMark0 = 1; + Gia_ObjFanin1(pObj)->fMark0 = 1; + } + Gia_ManForEachCo( p, pObj, i ) + Gia_ObjFanin0(pObj)->fMark0 = 1; + Gia_ManForEachCi( p, pObj, i ) + Count += pObj->fMark0; + Gia_ManForEachObj( p, pObj, i ) + pObj->fMark0 = 0; + return Count; +} + +/**Function************************************************************* + + Synopsis [Count POs driven by non-zero driver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManCountPosWithNonZeroDrivers( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, Count = 0; + Gia_ManForEachCo( p, pObj, i ) + Count += Gia_ObjFaninLit0(pObj, Gia_ObjId(p, pObj)) != 0; + return Count; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManUpdateCopy( Vec_Int_t * vCopy, Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + int i, iLit; + Vec_IntForEachEntry( vCopy, iLit, i ) + { + if ( iLit == -1 ) + continue; + pObj = Gia_ManObj( p, Abc_Lit2Var(iLit) ); + if ( !~pObj->Value ) + Vec_IntWriteEntry( vCopy, i, -1 ); + else + Vec_IntWriteEntry( vCopy, i, Abc_LitNotCond(pObj->Value, Abc_LitIsCompl(iLit)) ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManDupWithMuxPos( Gia_Man_t * p ) +{ + Vec_Int_t * vPoints = Vec_IntAlloc( 1000 ); + Vec_Int_t * vQuads = Vec_IntAlloc( 1000 ); + Vec_Bit_t * vHeads = Vec_BitStart( Gia_ManObjNum(p) ); + Vec_Bit_t * vDatas = Vec_BitStart( Gia_ManObjNum(p) ); + Gia_Obj_t * pObj, * pCtrl, * pData0, * pData1; + Gia_Man_t * pNew = Gia_ManDup( p ); int i, iObj; + assert( Gia_ManRegNum(pNew) == 0 ); + Gia_ManForEachAnd( pNew, pObj, i ) + { + if ( !Gia_ObjIsMuxType(pObj) ) + continue; + pCtrl = Gia_ObjRecognizeMux( pObj, &pData1, &pData0 ); + pCtrl = Gia_Regular(pCtrl); + pData0 = Gia_Regular(pData0); + pData1 = Gia_Regular(pData1); + Vec_IntPushTwo( vQuads, Gia_ObjId(pNew, pObj), Gia_ObjId(pNew, pCtrl) ); + Vec_IntPushTwo( vQuads, Gia_ObjId(pNew, pData0), Gia_ObjId(pNew, pData1) ); + Vec_BitWriteEntry( vHeads, Gia_ObjId(pNew, pObj), 1 ); + Vec_BitWriteEntry( vDatas, Gia_ObjId(pNew, pData0), 1 ); + Vec_BitWriteEntry( vDatas, Gia_ObjId(pNew, pData1), 1 ); + } + Gia_ManForEachCo( pNew, pObj, i ) + Gia_ObjFanin0(pObj)->fMark0 = 1; + for ( i = 0; i < Vec_IntSize(vQuads)/4; i++ ) + { + int iObj = Vec_IntEntry( vQuads, 4*i+0 ); + int iCtrl = Vec_IntEntry( vQuads, 4*i+1 ); + int iData0 = Vec_IntEntry( vQuads, 4*i+2 ); + int iData1 = Vec_IntEntry( vQuads, 4*i+3 ); + if ( (Vec_BitEntry(vHeads, iObj) && Vec_BitEntry(vDatas, iObj)) || + (Vec_BitEntry(vHeads, iData0) && Vec_BitEntry(vDatas, iData0)) || + (Vec_BitEntry(vHeads, iData1) && Vec_BitEntry(vDatas, iData1)) ) + { + Gia_Obj_t * pObj = Gia_ManObj( p, iObj ); + Gia_Obj_t * pCtrl = Gia_ManObj( p, iCtrl ); + Gia_Obj_t * pData0 = Gia_ManObj( p, iData0 ); + Gia_Obj_t * pData1 = Gia_ManObj( p, iData1 ); + if ( Gia_ObjIsAnd(pObj) && !pObj->fMark0 ) Vec_IntPush( vPoints, iObj ); + if ( Gia_ObjIsAnd(pCtrl) && !pCtrl->fMark0 ) Vec_IntPush( vPoints, iCtrl ); + if ( Gia_ObjIsAnd(pData0) && !pData0->fMark0 ) Vec_IntPush( vPoints, iData0 ); + if ( Gia_ObjIsAnd(pData1) && !pData1->fMark0 ) Vec_IntPush( vPoints, iData1 ); + } + } + Gia_ManCleanMark0( pNew ); + Vec_IntUniqify( vPoints ); + Vec_IntForEachEntry( vPoints, iObj, i ) + Gia_ManAppendCo( pNew, Abc_Var2Lit(iObj, 0) ); + Vec_IntFree( vPoints ); + Vec_IntFree( vQuads ); + Vec_BitFree( vHeads ); + Vec_BitFree( vDatas ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Collect distance info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManRingAdd( Gia_Man_t * p, int iObj, Vec_Int_t * vRes, Vec_Int_t * vDists, int Dist ) +{ + if ( Gia_ObjIsTravIdCurrentId(p, iObj) ) + return; + Gia_ObjSetTravIdCurrentId(p, iObj); + Vec_IntWriteEntry( vDists, iObj, Dist ); + Vec_IntPush( vRes, iObj ); +} +void Gia_ManCollectRing( Gia_Man_t * p, Vec_Int_t * vStart, Vec_Int_t * vRes, Vec_Int_t * vDists ) +{ + int i, k, iObj, iFan; + Vec_IntForEachEntry( vStart, iObj, i ) + { + int Weight = Vec_IntEntry( vDists, iObj ); + Gia_Obj_t * pObj = Gia_ManObj(p, iObj); + assert( Weight > 0 ); + if ( Gia_ObjIsAnd(pObj) ) + { + Gia_ManRingAdd( p, Gia_ObjFaninId0(pObj, iObj), vRes, vDists, Weight + 1*!Gia_ObjIsBuf(Gia_ObjFanin0(pObj)) ); + Gia_ManRingAdd( p, Gia_ObjFaninId1(pObj, iObj), vRes, vDists, Weight + 1*!Gia_ObjIsBuf(Gia_ObjFanin1(pObj)) ); + } + Gia_ObjForEachFanoutStaticId( p, iObj, iFan, k ) + Gia_ManRingAdd( p, iFan, vRes, vDists, Weight + 1*!Gia_ObjIsBuf(Gia_ManObj(p, iFan)) ); + } +} +Vec_Int_t * Gia_ManComputeDistanceInt( Gia_Man_t * p, int iTarg, Vec_Int_t * vObjs, int fVerbose ) +{ + int i, iObj; + Vec_Int_t * vDists, * vStart, * vNexts; + vStart = Vec_IntAlloc( 100 ); + vNexts = Vec_IntAlloc( 100 ); + vDists = Vec_IntStart( Gia_ManObjNum(p) ); + Gia_ManIncrementTravId( p ); + if ( vObjs ) + { + Vec_IntForEachEntry( vObjs, iObj, i ) + { + Gia_ObjSetTravIdCurrentId(p, iObj); + Vec_IntWriteEntry( vDists, iObj, 1 ); + Vec_IntPush( vStart, iObj ); + } + } + else + { + Gia_ObjSetTravIdCurrentId(p, iTarg); + Vec_IntWriteEntry( vDists, iTarg, 1 ); + Vec_IntPush( vStart, iTarg ); + } + for ( i = 0; ; i++ ) + { + if ( fVerbose ) + printf( "Ring %2d : %6d\n", i, Vec_IntSize(vDists)-Vec_IntCountZero(vDists) ); + Gia_ManCollectRing( p, vStart, vNexts, vDists ); + if ( Vec_IntSize(vNexts) == 0 ) + break; + Vec_IntClear( vStart ); + ABC_SWAP( Vec_Int_t, *vStart, *vNexts ); + } + Vec_IntFree( vStart ); + Vec_IntFree( vNexts ); + return vDists; +} +Vec_Int_t * Gia_ManComputeDistance( Gia_Man_t * p, int iObj, Vec_Int_t * vObjs, int fVerbose ) +{ + Vec_Int_t * vDists; + if ( p->vFanoutNums ) + vDists = Gia_ManComputeDistanceInt( p, iObj, vObjs, fVerbose ); + else + { + Gia_ManStaticFanoutStart( p ); + vDists = Gia_ManComputeDistanceInt( p, iObj, vObjs, fVerbose ); + Gia_ManStaticFanoutStop( p ); + } + return vDists; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ComputeTest() +{ + char * pStart, Line [1000]; float Total = 0; + char * pFileName = "data.txt"; + FILE * pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { printf( "Input file \"%s\" cannot be opened.\n", pFileName ); return; } + while ( fgets( Line, 1000, pFile ) != NULL ) + { + if ( !strstr(Line, "xxx") ) + continue; + if ( !strstr(Line, "yyy") ) + continue; + //printf( "%s", Line ); + pStart = strstr(Line, "zzz"); + if ( pStart == NULL ) + continue; + //printf( "%s", pStart + 4 ); + Total += -atof( pStart + 4 ); + } + printf( "Total = %.2f\n", Total ); + fclose( pFile ); +} + + +/**Function************************************************************* + + Synopsis [Computes sum total of support size of primary outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSumTotalOfSupportSizes( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; + Vec_Wec_t * vSupps = Vec_WecStart( Gia_ManObjNum(p) ); + int i, nResult = 0; + for ( i = 0; i < Gia_ManCiNum(p); i++ ) + Vec_IntPush( Vec_WecEntry(vSupps, 1+i), i ); + Gia_ManForEachAnd( p, pObj, i ) + Vec_IntTwoMerge2( Vec_WecEntry(vSupps, Gia_ObjFaninId0(pObj, i)), Vec_WecEntry(vSupps, Gia_ObjFaninId1(pObj, i)), Vec_WecEntry(vSupps, i) ); + Gia_ManForEachCo( p, pObj, i ) + nResult += Vec_IntSize( Vec_WecEntry(vSupps, Gia_ObjFaninId0p(p, pObj)) ); + Vec_WecFree( vSupps ); + return nResult; +} + +/**Function************************************************************* + + Synopsis [Computes sum total of support size of primary outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManSumTotalOfSupportSizes2( Gia_Man_t * p ) +{ + Vec_Wrd_t * vSims = Vec_WrdStart( Gia_ManObjNum(p) ); + int r, nResult = 0, nRounds = (Gia_ManCiNum(p) + 63)/64; + for ( r = 0; r < nRounds; r++ ) + { + Gia_Obj_t * pObj; + int i, Limit = r == nRounds-1 ? Gia_ManCiNum(p) % 64 : 64; + for ( i = 0; i < Limit; i++ ) + Vec_WrdWriteEntry( vSims, 1+64*r+i, (word)1 << i ); + Gia_ManForEachAnd( p, pObj, i ) + Vec_WrdWriteEntry( vSims, i, Vec_WrdEntry(vSims, Gia_ObjFaninId0(pObj, i)) | Vec_WrdEntry(vSims, Gia_ObjFaninId1(pObj, i)) ); + Gia_ManForEachCo( p, pObj, i ) + nResult += Abc_TtCountOnes( Vec_WrdEntry(vSims, Gia_ObjFaninId0p(p, pObj)) ); + for ( i = 0; i < Limit; i++ ) + Vec_WrdWriteEntry( vSims, 1+64*r+i, 0 ); + } + Vec_WrdFree( vSims ); + return nResult; +} + +/**Function************************************************************* + + Synopsis [Compute dependency.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManComputeCofs( Gia_Man_t * p, int nVars ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; int i, m; + Gia_Obj_t * pSink = Gia_ManCo(p, 0); + Vec_Int_t * vRoots = Vec_IntAlloc( 1 ); + Vec_Int_t * vNodes = Vec_IntAlloc( 1000 ); + Vec_IntPush( vRoots, Gia_ObjFaninId0p(p, pSink) ); + Gia_ManCollectTfi( p, vRoots, vNodes ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + for ( m = 0; m < (1 << nVars); m++ ) + { + for ( i = 0; i < nVars; i++ ) + Gia_ManCi(p, Gia_ManCiNum(p)-nVars+i)->Value = (m >> i) & 1; + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pSink) ); + } + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Vec_IntFree( vRoots ); + Vec_IntFree( vNodes ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Compute dependency.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManComputeCofs2( Gia_Man_t * p ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pSink; int i, o, m; + Vec_Int_t * vSupp = Vec_IntAlloc( 1000 ); + Vec_Int_t * vAnds = Vec_IntAlloc( 1000 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManForEachCi( p, pObj, i ) + { + pObj->Value = Gia_ManAppendCi(pNew); + assert( (int)pObj->Value == Abc_Var2Lit( 1 + Gia_ObjCioId(pObj), 0 ) ); + } + Gia_ManHashAlloc( pNew ); + Gia_ManForEachRi( p, pSink, o ) + { + int Fanin = Gia_ObjFaninId0p( p, pSink ); + Vec_Int_t * vNodes = Gia_ManCollectNodesCis( p, &Fanin, 1 ); + Vec_IntClear( vSupp ); + Vec_IntClear( vAnds ); + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + Vec_IntPush( Gia_ObjIsAnd(pObj) ? vAnds : vSupp, Gia_ObjId(p, pObj) ); + Vec_IntFree( vNodes ); + Vec_IntSort( vSupp, 0 ); + for ( m = 0; m < 5; m++ ) + { + Gia_ManForEachObjVec( vSupp, p, pObj, i ) + if ( i >= Vec_IntSize(vSupp)-5 ) + pObj->Value = (i == Vec_IntSize(vSupp)-5+m) ? 1 : 0; + Gia_ManForEachObjVec( vAnds, p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + //if ( m == 4 ) + // Gia_ManAppendCo( pNew, 0 ); + //else + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pSink) ); + Gia_ManAppendCo( pNew, Abc_Var2Lit( Vec_IntEntry(vSupp, Vec_IntSize(vSupp)-5+m), 0 ) ); + Gia_ManForEachObjVec( vSupp, p, pObj, i ) + if ( i >= Vec_IntSize(vSupp)-5 ) + pObj->Value = Abc_Var2Lit( 1 + Gia_ObjCioId(pObj), 0 ); + } + } + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Vec_IntFree( vSupp ); + Vec_IntFree( vAnds ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Compute dependency.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManComputeDepAig( Gia_Man_t * p, int iIn, int iOut ) +{ + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj; int i, n, iLits[2]; + Gia_Obj_t * pPivot = Gia_ManCi(p, iIn); + Gia_Obj_t * pSink = Gia_ManCo(p, iOut); + Vec_Int_t * vRoots = Vec_IntAlloc( 1 ); + Vec_Int_t * vNodes = Vec_IntAlloc( 1000 ); + Vec_IntPush( vRoots, Gia_ObjFaninId0p(p, pSink) ); + Gia_ManCollectTfi( p, vRoots, vNodes ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManHashAlloc( pNew ); + for ( n = 0; n < 2; n++ ) + { + pPivot->Value = n; + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + iLits[n] = Gia_ObjFanin0Copy(pSink); + } + Gia_ManAppendCo( pNew, Gia_ManHashAnd(pNew, iLits[1], Abc_LitNot(iLits[0])) ); + Gia_ManAppendCo( pNew, Gia_ManHashAnd(pNew, iLits[0], Abc_LitNot(iLits[1])) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + Vec_IntFree( vRoots ); + Vec_IntFree( vNodes ); + return pNew; +} +int Gia_ManComputeDep( Gia_Man_t * p, int iIn, int iOut ) +{ + extern Gia_Man_t * Cec4_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose ); + Gia_Man_t * pNew = Gia_ManComputeDepAig( p, iIn, iOut ); + Gia_Man_t * pSwp = Cec4_ManSimulateTest3( pNew, 100000, 0 ); + int iLit[2] = { Gia_ObjFaninId0p( pSwp, Gia_ManCo(pSwp, 0) ), Gia_ObjFaninId0p( pSwp, Gia_ManCo(pSwp, 1) ) }; + Gia_ManStop( pNew ); + Gia_ManStop( pSwp ); + if ( iLit[0] == 0 && iLit[1] == 0 ) + return 2; + if ( iLit[1] == 0 ) + return 1; + if ( iLit[0] == 0 ) + return 0; + return -1; +} +Gia_Man_t * Gia_ManComputeDepTest( Gia_Man_t * p ) +{ + abctime clk = Abc_Clock(); + int i; + for ( i = 0; i < Gia_ManCiNum(p); i++ ) + printf( "%3d : %3d\n", i, Gia_ManComputeDep(p, i, 0) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return Gia_ManDup(p); +} + +/**Function************************************************************* + + Synopsis [Compute support diffs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wec_t * Gia_ManComputeSupports( Gia_Man_t * p ) +{ + Vec_Wec_t * vRes = Vec_WecStart( Gia_ManCoNum(p) ); + Vec_Wec_t * vSupps = Vec_WecStart( Gia_ManObjNum(p) ); + Gia_Obj_t * pObj; int i; + for ( i = 0; i < Gia_ManCiNum(p); i++ ) + Vec_IntPush( Vec_WecEntry(vSupps, 1+i), i ); + Gia_ManForEachAnd( p, pObj, i ) + Vec_IntTwoMerge2( Vec_WecEntry(vSupps, Gia_ObjFaninId0(pObj, i)), Vec_WecEntry(vSupps, Gia_ObjFaninId1(pObj, i)), Vec_WecEntry(vSupps, i) ); + Gia_ManForEachCo( p, pObj, i ) + Vec_IntAppend( Vec_WecEntry(vRes, i), Vec_WecEntry(vSupps, Gia_ObjFaninId0p(p, pObj)) ); + Vec_WecFree( vSupps ); + return vRes; +} +Vec_Wec_t * Gia_ManComputeSharing( Vec_Wec_t * vSupps ) +{ + Vec_Wec_t * vDiffs = Vec_WecStart( Vec_WecSize(vSupps) ); + Vec_Int_t * vNew, * vOld; int i; + Vec_WecForEachLevelTwo( vDiffs, vSupps, vNew, vOld, i ) if ( i ) + Vec_IntTwoFindCommon( Vec_WecEntry(vSupps, i-1), vOld, vNew ); + return vDiffs; +} +Vec_Str_t * Gia_ManConvertDump( Gia_Man_t * p, Vec_Wec_t * vSupps ) +{ + int fPrintDep = 1; + int nSize = Gia_ManCoNum(p) * (Gia_ManCiNum(p) + 1) + 1; + Vec_Str_t * vRes = Vec_StrAlloc( nSize ); + Vec_Int_t * vLevel; int i, k, Obj; + assert( Gia_ManCoNum(p) == Vec_WecSize(vSupps) ); + Vec_StrFill( vRes, nSize-1, '_' ); + Vec_StrPush( vRes, '\0' ); + Vec_WecForEachLevel( vSupps, vLevel, i ) + { + Vec_IntForEachEntry( vLevel, Obj, k ) + { + if ( !fPrintDep ) + Vec_StrWriteEntry( vRes, i * (Gia_ManCiNum(p) + 1) + Obj, '*' ); + else + { + int Value = Gia_ManComputeDep( p, Obj, i ); + if ( Value == -1 ) + Vec_StrWriteEntry( vRes, i * (Gia_ManCiNum(p) + 1) + Obj, '*' ); + else + Vec_StrWriteEntry( vRes, i * (Gia_ManCiNum(p) + 1) + Obj, (char)('0'+Value) ); + } + } + Vec_StrWriteEntry( vRes, i * (Gia_ManCiNum(p) + 1) + Gia_ManCiNum(p), '\n' ); + //printf( "Output %d\n", i ); + } + return vRes; +} +void Gia_ManDumpSuppFile( Vec_Str_t * p, char * pFileName ) +{ + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + printf( "Cannot open file \"%s\" for writing.\n", pFileName ); + else + { + int nOuts = Vec_StrCountEntry(p, '\n'); + int nIns = Vec_StrSize(p)/Vec_StrCountEntry(p, '\n') - 1; + int nSize1 = Vec_StrSize(p) - 1; + int nSize2 = fwrite( Vec_StrArray(p), 1, nSize1, pFile ); + assert( nSize1 == nSize2 ); + printf( "Successfully dumped file \"%s\" with support data for %d outputs and %d inputs.\n", pFileName, nOuts, nIns ); + } + fclose( pFile ); +} +void Gia_ManDumpSuppFileTest3( Gia_Man_t * p, char * pFileName ) +{ + Vec_Wec_t * vSupps = Gia_ManComputeSupports( p ); + Vec_Wec_t * vDiffs = Gia_ManComputeSharing( vSupps ); + Vec_Wec_t * vDiffs2 = Gia_ManComputeSharing( vDiffs ); + Vec_Str_t * vRes = Gia_ManConvertDump( p, vDiffs2 ); + Gia_ManDumpSuppFile( vRes, pFileName ); + Vec_WecFree( vDiffs2 ); + Vec_WecFree( vDiffs ); + Vec_WecFree( vSupps ); + Vec_StrFree( vRes ); +} +void Gia_ManDumpSuppFileTest( Gia_Man_t * p, char * pFileName ) +{ + Vec_Wec_t * vSupps = Gia_ManComputeSupports( p ); + Vec_Str_t * vRes = Gia_ManConvertDump( p, vSupps ); + Gia_ManDumpSuppFile( vRes, pFileName ); + Vec_WecFree( vSupps ); + Vec_StrFree( vRes ); +} + + +/**Function************************************************************* + + Synopsis [Compute support diffs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManConvertSupp_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( !Gia_ObjIsAnd(pObj) ) + return; + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return; + Gia_ObjSetTravIdCurrent(p, pObj); + Gia_ManConvertSupp_rec( pNew, p, Gia_ObjFanin0(pObj) ); + Gia_ManConvertSupp_rec( pNew, p, Gia_ObjFanin1(pObj) ); + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); +} +Gia_Man_t * Gia_ManConvertSupp( Gia_Man_t * p ) +{ + int fOnly1 = 0; + int fVerbose = 1; + abctime clk = Abc_Clock(); + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObjPi, * pObjRi, * pObjRo; + Vec_Int_t * vSupp = Vec_IntAlloc( 100 ); + Vec_Int_t * vAnds = Vec_IntAlloc( 100 ); + int i, n, iLits[2]; + assert( Gia_ManRegNum(p) && Gia_ManRegNum(p) % 8 == 0 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachPi( p, pObjPi, i ) + pObjPi->Value = Gia_ManAppendCi( pNew ); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachRi( p, pObjRi, i ) + { + pObjRo = Gia_ObjRiToRo(p, pObjRi); + if ( (i - Gia_ManPoNum(p)) % 8 != 0 ) + continue; + if ( fOnly1 ) + { + assert( pObjRo->Value == ~0 ); + for ( n = 0; n < 2; n++ ) + { + pObjRo->Value = n; + Gia_ManIncrementTravId( p ); + Gia_ManConvertSupp_rec( pNew, p, Gia_ObjFanin0(pObjRi) ); + iLits[n] = Gia_ObjFanin0Copy(pObjRi); + } + pObjRo->Value = ~0; + Gia_ManAppendCo( pNew, Abc_LitNot(Gia_ManHashAnd( pNew, iLits[1], Abc_LitNot(iLits[0]) )) ); + } + else + { + int Fanin = Gia_ObjFaninId0p( p, pObjRi ); + Vec_Int_t * vNodes = Gia_ManCollectNodesCis( p, &Fanin, 1 ); + Gia_Obj_t * pObj; int i, m; + Vec_IntClear( vSupp ); + Vec_IntClear( vAnds ); + Gia_ManForEachObjVec( vNodes, p, pObj, i ) + Vec_IntPush( Gia_ObjIsAnd(pObj) ? vAnds : vSupp, Gia_ObjId(p, pObj) ); + Vec_IntFree( vNodes ); + Vec_IntSort( vSupp, 0 ); + for ( m = 0; m < 4; m++ ) + { + Gia_ManForEachObjVec( vSupp, p, pObj, i ) + if ( i >= Vec_IntSize(vSupp)-5 ) + pObj->Value = (i == Vec_IntSize(vSupp)-5+m) ? 1 : 0; + Gia_ManForEachObjVec( vAnds, p, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + //if ( m == 4 ) + // Gia_ManAppendCo( pNew, 0 ); + //else + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObjRi) ); + //Gia_ManAppendCo( pNew, Abc_Var2Lit( Vec_IntEntry(vSupp, Vec_IntSize(vSupp)-5+m), 0 ) ); + Gia_ManForEachObjVec( vSupp, p, pObj, i ) + if ( i >= Vec_IntSize(vSupp)-5 ) + pObj->Value = Abc_Var2Lit( 1 + Gia_ObjCioId(pObj), 0 ); + } + } + } + Vec_IntFree( vSupp ); + Vec_IntFree( vAnds ); + Gia_ManHashStop( pNew ); + //Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + if ( fVerbose ) + printf( "Transformed %d outputs, ", Gia_ManPoNum(pNew) ); + if ( fVerbose ) + Abc_PrintTime( 0, "Time", Abc_Clock() - clk ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Transform flops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManTransformCond2( Gia_Man_t * p ) +{ + int fVerbose = 1; + abctime clk = Abc_Clock(); + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObjPi, * pObjRi, * pObjRo; + int i, n, iTempLit, iLits[2]; + assert( Gia_ManRegNum(p) > 0 ); + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManFillValue(p); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObjPi, i ) + pObjPi->Value = Gia_ManAppendCi( pNew ); + Gia_ManHashAlloc( pNew ); + Gia_ManForEachRi( p, pObjRi, i ) + { + //if ( (i - Gia_ManPoNum(p)) % 8 != 0 ) + // continue; + pObjRo = Gia_ObjRiToRo(p, pObjRi); + iTempLit = pObjRo->Value; + for ( n = 0; n < 2; n++ ) + { + pObjRo->Value = n; + Gia_ManIncrementTravId( p ); + Gia_ManConvertSupp_rec( pNew, p, Gia_ObjFanin0(pObjRi) ); + iLits[n] = Gia_ObjFanin0Copy(pObjRi); + } + pObjRo->Value = iTempLit; + Gia_ManAppendCo( pNew, Abc_LitNot(Gia_ManHashAnd( pNew, iLits[1], Abc_LitNot(iLits[0]) )) ); + Gia_ManAppendCo( pNew, Abc_LitNot(Gia_ManHashAnd( pNew, iLits[0], Abc_LitNot(iLits[1]) )) ); + } + Gia_ManHashStop( pNew ); + //Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + if ( fVerbose ) + printf( "Created %d outputs. ", Gia_ManPoNum(pNew) ); + if ( fVerbose ) + Abc_PrintTime( 0, "Time", Abc_Clock() - clk ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Transform flops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Wrd_t * Gia_ManDetectSims( Gia_Man_t * p, int iCo, int nWords ) +{ + extern int Cec4_ManGeneratePatterns_rec( Gia_Man_t * p, Gia_Obj_t * pObj, int Value, Vec_Int_t * vPat, Vec_Int_t * vVisit ); + Vec_Wrd_t * vSim = Vec_WrdStart( nWords * Gia_ManCiNum(p) ); + Vec_Int_t * vPat = Vec_IntAlloc( Gia_ManCiNum(p) ); + Vec_Int_t * vVis = Vec_IntAlloc( Gia_ManAndNum(p) ); + Gia_Obj_t * pObj = Gia_ManCo( p, iCo ), * pTemp; int iLit, i, k, nTries = 0; + if ( Gia_ObjFanin0(pObj) == Gia_ManConst0(p) ) + return NULL; + Gia_ManForEachObj( p, pTemp, k ) + assert( !pTemp->fMark0 && !pTemp->fMark1 ); + for ( i = 0; i < 64*nWords; ) + { + int Res = Cec4_ManGeneratePatterns_rec( p, Gia_ObjFanin0(pObj), !Gia_ObjFaninC0(pObj), vPat, vVis ); + if ( Res ) + { + Vec_IntForEachEntry( vPat, iLit, k ) + { + if ( Abc_LitIsCompl(iLit) ) + continue; + pTemp = Gia_ManObj( p, Abc_Lit2Var(iLit) ); + assert( Gia_ObjIsCi(pTemp) ); + Abc_InfoSetBit( (unsigned *)Vec_WrdEntryP(vSim, nWords*Gia_ObjCioId(pTemp)), i ); + } + i++; + } + Gia_ManForEachObjVec( vVis, p, pTemp, k ) + pTemp->fMark0 = pTemp->fMark1 = 0; + nTries++; + } + //printf( "%d ", nTries ); + Vec_IntFree( vPat ); + Vec_IntFree( vVis ); + return vSim; +} +Vec_Wrd_t * Vec_WrdInterleave( Vec_Wrd_t * p1, Vec_Wrd_t * p2, int nWords, int nIns ) +{ + Vec_Wrd_t * p = Vec_WrdAlloc( Vec_WrdSize(p1)+Vec_WrdSize(p2) ); + int i, k; + assert( Vec_WrdSize(p1) == nWords*nIns ); + assert( Vec_WrdSize(p2) == nWords*nIns ); + for ( i = 0; i < nIns; i++ ) + { + for ( k = 0; k < nWords; k++ ) + Vec_WrdPush( p, Vec_WrdEntry(p1, i*nWords+k) ); + for ( k = 0; k < nWords; k++ ) + Vec_WrdPush( p, Vec_WrdEntry(p2, i*nWords+k) ); + } + return p; +} +Gia_Man_t * Gia_ManTransformCond( Gia_Man_t * p ) +{ + extern void Gia_ManResubPair( Vec_Wrd_t * vOn, Vec_Wrd_t * vOff, int nWords, int nIns ); + abctime clk = Abc_Clock(); + Vec_Wrd_t * vSims; + Vec_Wrd_t * vSim[4]; + Vec_Wrd_t * vInt[6]; + int i; + for ( i = 0; i < Gia_ManCoNum(p); i++ ) + { + vSims = Gia_ManDetectSims( p, i, 1 ); + if ( i >= Gia_ManCoNum(p)-4 ) + vSim[i-(Gia_ManCoNum(p)-4)] = vSims; + else + Vec_WrdFreeP( &vSims ); + //Vec_PtrPush( vAll, vSims ); + } + vInt[0] = Vec_WrdInterleave( vSim[0], vSim[1], 1, Gia_ManCiNum(p) ); + vInt[1] = Vec_WrdInterleave( vSim[0], vSim[2], 1, Gia_ManCiNum(p) ); + vInt[2] = Vec_WrdInterleave( vSim[0], vSim[3], 1, Gia_ManCiNum(p) ); + vInt[3] = Vec_WrdInterleave( vSim[1], vSim[2], 1, Gia_ManCiNum(p) ); + vInt[4] = Vec_WrdInterleave( vSim[1], vSim[3], 1, Gia_ManCiNum(p) ); + vInt[5] = Vec_WrdInterleave( vSim[2], vSim[3], 1, Gia_ManCiNum(p) ); + + Gia_ManResubPair( vInt[0], vInt[5], 2, Gia_ManCiNum(p) ); + Gia_ManResubPair( vInt[1], vInt[4], 2, Gia_ManCiNum(p) ); + Gia_ManResubPair( vInt[2], vInt[3], 2, Gia_ManCiNum(p) ); + + Gia_ManResubPair( vInt[5], vInt[0], 2, Gia_ManCiNum(p) ); + Gia_ManResubPair( vInt[4], vInt[1], 2, Gia_ManCiNum(p) ); + Gia_ManResubPair( vInt[3], vInt[2], 2, Gia_ManCiNum(p) ); + +/* + for ( i = 0; i < 4; i++ ) + for ( k = i+1; k < 4; k++ ) + Gia_ManResubPair( vSim[i], vSim[k], 1, Gia_ManCiNum(p) ); +*/ + Abc_PrintTime( 0, "Time", Abc_Clock() - clk ); + return NULL; +} +void Gia_ManWriteSol( Gia_Man_t * p, char * pFileName ) +{ + char * pBasicName = Extra_FileNameGeneric( pFileName ); + char * pFileName2 = Abc_UtilStrsavTwo( pBasicName, ".sol" ); + FILE * pFile = fopen( pFileName2, "wb" ); + ABC_FREE( pBasicName ); + if ( pFile == NULL ) + printf( "Cannot open output file \"%s\".\n", pFileName2 ); + else + { + Gia_Obj_t * pObj; int i; + Gia_ManForEachAnd( p, pObj, i ) + fprintf( pFile, "%d %d ", Gia_ObjFaninLit0(pObj, i), Gia_ObjFaninLit1(pObj, i) ); + Gia_ManForEachCo( p, pObj, i ) + fprintf( pFile, "%d %d ", Gia_ObjFaninLit0p(p, pObj), Gia_ObjFaninLit0p(p, pObj) ); + fclose( pFile ); + printf( "Finished writing solution file \"%s\".\n", pFileName2 ); + } + ABC_FREE( pFileName2 ); +} +void Gia_ManWriteResub( Gia_Man_t * p, char * pFileName ) +{ + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + printf( "Cannot open output file \"%s\".\n", pFileName ); + else + { + Vec_Wrd_t * vSimsPi = Vec_WrdStartTruthTables( Gia_ManCiNum(p) ); + Vec_Wrd_t * vSimsPo = Gia_ManSimPatSimOut( p, vSimsPi, 1 ); + int i, k, nWords = Vec_WrdSize(vSimsPi) / Gia_ManCiNum(p); + word * pTemp = ABC_ALLOC( word, nWords ); + fprintf( pFile, "%d %d %d %d\n", Gia_ManCiNum(p), 0, Gia_ManCoNum(p), 1 << Gia_ManCiNum(p) ); + for ( i = 0; i < Gia_ManCiNum(p); i++ ) + Abc_TtPrintBinary1( pFile, Vec_WrdEntryP(vSimsPi, i*nWords), Gia_ManCiNum(p) ), fprintf(pFile, "\n"); + for ( i = 0; i < (1 << Gia_ManCoNum(p)); i++ ) + { + Abc_TtFill( pTemp, nWords ); + for ( k = 0; k < Gia_ManCoNum(p); k++ ) + Abc_TtAndCompl( pTemp, pTemp, 0, Vec_WrdEntryP(vSimsPo, k*nWords), !((i>>k)&1), nWords ); + Abc_TtPrintBinary1( pFile, pTemp, Gia_ManCiNum(p) ), fprintf(pFile, "\n"); + } + ABC_FREE( pTemp ); + fclose( pFile ); + Vec_WrdFree( vSimsPi ); + Vec_WrdFree( vSimsPo ); + printf( "Finished writing resub file \"%s\".\n", pFileName ); + Gia_ManWriteSol( p, pFileName ); + } +} + + +/**Function************************************************************* + + Synopsis [Transform flops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintArray( Gia_Man_t * p ) +{ + Gia_Obj_t * pObj; int i, nSize = Gia_ManObjNum(p); + printf( "static int s_ArraySize = %d;\n", nSize ); + printf( "static int s_ArrayData[%d] = {\n", 2*nSize ); + printf( " 0, 0," ); + printf( "\n " ); + Gia_ManForEachCi( p, pObj, i ) + printf( "0, 0, " ); + printf( "\n " ); + Gia_ManForEachAnd( p, pObj, i ) + printf( "%d, %d, ", Gia_ObjFaninLit0p(p, pObj), Gia_ObjFaninLit1p(p, pObj) ); + printf( "\n " ); + Gia_ManForEachCo( p, pObj, i ) + printf( "%d, %d, ", Gia_ObjFaninLit0p(p, pObj), Gia_ObjFaninLit0p(p, pObj) ); + printf( "\n" ); + printf( "};\n" ); + +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_GetMValue( int i, int nIns, int Mint, unsigned Truth ) +{ + assert( i >= 0 && i < 16 ); + if ( i < nIns ) + return (Mint >> i) & 1; + if ( i == nIns ) + { + if ( Mint < (1 << nIns) ) + return (Truth >> Mint) & 1; + else + return ((Truth >> (Mint-(1 << nIns))) & 1) == 0; + } + else + return 1; +} +void Gia_ManTestProblem() +{ + unsigned Truth = 0xFE; + int i, j, k, c, nIns = 3, nAux = 3; + int nTotal = nIns + 1 + nAux; + int nPairs = nTotal * (nTotal - 1) / 2; + int nMints = (1 << (nIns+1)); + int M[64][100] = {{0}}; + float Value[64] = {0}; + float Solution[100] = {0}; + assert( nMints <= 64 ); + assert( nPairs <= 100 ); + // 7 nodes: 3 inputs + 1 output + 3 aux + // 7*6/2 = 21 pairs + // 16 minterms + for ( k = 0; k < nMints; k++ ) + { + for ( i = c = 0; i < nTotal; i++ ) + for ( j = i+1; j < nTotal; j++ ) + { + int iVal = Gia_GetMValue( i, nIns, k, Truth ); + int jVal = Gia_GetMValue( j, nIns, k, Truth ); + M[k][c++] = iVal == jVal ? 1 : -1; + } + Value[k] = k < (1 << nIns) ? -1 : 1; + assert( c == nPairs ); + } + + for ( k = 0; k < nMints; k++ ) + { + for ( c = 0; c < nPairs; c++ ) + printf( "%2d ", M[k][c] ); + printf( "%3f\n", Value[k] ); + } + + // solve + float Delta = 0.02; + for ( i = 0; i < 100; i++ ) + { + float Error = 0; + for ( k = 0; k < nMints; k++ ) + Error += Value[k] > 0 ? Value[k] : -Value[k]; + printf( "Round %3d : Error = %5f ", i, Error ); + for ( c = 0; c < nPairs; c++ ) + printf( "%2f ", Solution[c] ); + printf( "\n" ); + + //if ( Error < 1 ) + // Delta /= 10; + + for ( c = 0; c < nPairs; c++ ) + { + int Count = 0; + for ( k = 0; k < nMints; k++ ) + if ( (M[k][c] > 0 && Value[k] > 0) || (M[k][c] < 0 && Value[k] < 0) ) + Count++; + else + Count--; + if ( Count == 0 ) + continue; + printf( "Count = %3d ", Count ); + if ( Count > 0 ) + { + printf( "Increasing %d by %f\n", c, Delta ); + Solution[c] += Delta; + for ( k = 0; k < nMints; k++ ) + if ( M[k][c] > 0 ) + Value[k] -= Delta; + else + Value[k] -= Delta; + } + else + { + printf( "Reducing %d by %f\n", c, Delta ); + Solution[c] -= Delta; + for ( k = 0; k < nMints; k++ ) + if ( M[k][c] > 0 ) + Value[k] += Delta; + else + Value[k] += Delta; + } + } + } +} + +/**Function************************************************************* + + Synopsis [Returns 1 if this window has a topo error (forward path from an output to an input).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManWindowCheckTopoError_rec( Gia_Man_t * p, Gia_Obj_t * pObj ) +{ + if ( !Gia_ObjIsAnd(pObj) ) + return 0; + if ( Gia_ObjIsTravIdPrevious(p, pObj) ) + return 1; // there is an error + if ( Gia_ObjIsTravIdCurrent(p, pObj) ) + return 0; // there is no error; visited this node before + Gia_ObjSetTravIdPrevious(p, pObj); + if ( Gia_ManWindowCheckTopoError_rec(p, Gia_ObjFanin0(pObj)) || Gia_ManWindowCheckTopoError_rec(p, Gia_ObjFanin1(pObj)) ) + return 1; + Gia_ObjSetTravIdCurrent(p, pObj); + return 0; +} +int Gia_ManWindowCheckTopoError( Gia_Man_t * p, Vec_Int_t * vIns, Vec_Int_t * vOuts ) +{ + Gia_Obj_t * pObj; int i, fError = 0; + // outputs should be internal nodes + Gia_ManForEachObjVec( vOuts, p, pObj, i ) + assert(Gia_ObjIsAnd(pObj)); + // mark outputs + Gia_ManIncrementTravId( p ); + Gia_ManForEachObjVec( vOuts, p, pObj, i ) + Gia_ObjSetTravIdCurrent(p, pObj); + // start from inputs and make sure we do not reach any of the outputs + Gia_ManIncrementTravId( p ); + Gia_ManForEachObjVec( vIns, p, pObj, i ) + fError |= Gia_ManWindowCheckTopoError_rec(p, pObj); + return fError; +} + +/**Function************************************************************* + + Synopsis [Updates the AIG after multiple windows have been optimized.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManDupInsertWindows_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vMap, Vec_Ptr_t * vvIns, Vec_Ptr_t * vvOuts, Vec_Ptr_t * vWins ) +{ + if ( ~pObj->Value ) + return pObj->Value; + assert( Gia_ObjIsAnd(pObj) ); + if ( Vec_IntEntry(vMap, Gia_ObjId(p, pObj)) == -1 ) // this is a regular node + { + Gia_ManDupInsertWindows_rec( pNew, p, Gia_ObjFanin0(pObj), vMap, vvIns, vvOuts, vWins ); + Gia_ManDupInsertWindows_rec( pNew, p, Gia_ObjFanin1(pObj), vMap, vvIns, vvOuts, vWins ); + return pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + } + // this node is an output of a window + int iWin = Vec_IntEntry(vMap, Gia_ObjId(p, pObj)); + Vec_Int_t * vIns = (Vec_Int_t *)Vec_PtrEntry(vvIns, iWin); + Vec_Int_t * vOuts = (Vec_Int_t *)Vec_PtrEntry(vvOuts, iWin); + Gia_Man_t * pWin = (Gia_Man_t *)Vec_PtrEntry(vWins, iWin); + // build transinvite fanins of window inputs + Gia_Obj_t * pNode; int i; + Gia_ManConst0(pWin)->Value = 0; + Gia_ManForEachObjVec( vIns, p, pNode, i ) + Gia_ManPi(pWin, i)->Value = Gia_ManDupInsertWindows_rec( pNew, p, pNode, vMap, vvIns, vvOuts, vWins ); + // add window nodes + Gia_ManForEachAnd( pWin, pNode, i ) + pNode->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pNode), Gia_ObjFanin1Copy(pNode) ); + // transfer to window outputs + Gia_ManForEachObjVec( vOuts, p, pNode, i ) + pNode->Value = Gia_ObjFanin0Copy(Gia_ManPo(pWin, i)); + assert( ~pObj->Value ); + return pObj->Value; +} +Gia_Man_t * Gia_ManDupInsertWindows( Gia_Man_t * p, Vec_Ptr_t * vvIns, Vec_Ptr_t * vvOuts, Vec_Ptr_t * vWins ) +{ + // check consistency of input data + Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, k, iNode; + Vec_PtrForEachEntry( Gia_Man_t *, vWins, pTemp, i ) { + Vec_Int_t * vIns = (Vec_Int_t *)Vec_PtrEntry(vvIns, i); + Vec_Int_t * vOuts = (Vec_Int_t *)Vec_PtrEntry(vvOuts, i); + assert( Vec_IntSize(vIns) == Gia_ManPiNum(pTemp) ); + assert( Vec_IntSize(vOuts) == Gia_ManPoNum(pTemp) ); + assert( !Gia_ManWindowCheckTopoError(p, vIns, vOuts) ); + } + // create mapping of window outputs into window IDs + Vec_Int_t * vMap = Vec_IntStartFull( Gia_ManObjNum(p) ), * vOuts; + Vec_PtrForEachEntry( Vec_Int_t *, vvOuts, vOuts, i ) + Vec_IntForEachEntry( vOuts, iNode, k ) + Vec_IntWriteEntry( vMap, iNode, i ); + // create the resulting AIG by performing DFS from the POs of the original AIG + // it goes recursively through original nodes and windows until it reaches the PIs of the original AIG + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManHashAlloc( pNew ); + Gia_ManFillValue( p ); + Gia_ManConst0(p)->Value = 0; + Gia_ManForEachCi( p, pObj, i ) + pObj->Value = Gia_ManAppendCi(pNew); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManDupInsertWindows_rec( pNew, p, Gia_ObjFanin0(pObj), vMap, vvIns, vvOuts, vWins ); + Gia_ManForEachCo( p, pObj, i ) + Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + // cleanup and return + Vec_IntFree( vMap ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + //Gia_ManPrint( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Computing equivalent nodes across the two AIGs.] + + Description [Assumes that both AIGs are structurally hashed without dandling nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManCreateDualOutputMiter( Gia_Man_t * p0, Gia_Man_t * p1 ) +{ + Gia_Man_t * pNew; Gia_Obj_t * pObj; int i; + assert( Gia_ManCiNum(p0) == Gia_ManCiNum(p1) ); + assert( Gia_ManCoNum(p0) == Gia_ManCoNum(p1) ); + // start the manager + pNew = Gia_ManStart( Gia_ManObjNum(p0) + Gia_ManObjNum(p1) ); + pNew->pName = Abc_UtilStrsav( "miter" ); + Gia_ManFillValue( p0 ); + Gia_ManFillValue( p1 ); + // map combinational inputs + Gia_ManConst0(p0)->Value = 0; + Gia_ManConst0(p1)->Value = 0; + Gia_ManForEachCi( p0, pObj, i ) + Gia_ManCi(p1, i)->Value = pObj->Value = Gia_ManAppendCi( pNew ); + // map internal nodes and outputs + Gia_ManHashAlloc( pNew ); + Gia_ManForEachAnd( p0, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + assert( Gia_ManAndNum(pNew) == Gia_ManAndNum(p0) ); // the input AIG p0 is structurally hashed + Gia_ManForEachAnd( p1, pObj, i ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + // add the outputs + Gia_ManForEachCo( p0, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + Gia_ManForEachCo( p1, pObj, i ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + printf( "The two AIGs have %d structurally equivalent nodes.\n", Gia_ManAndNum(p0) + Gia_ManAndNum(p1) - Gia_ManAndNum(pNew) ); + // there should be no dangling nodes (otherwise, the second AIG may not be structurally hashed) + int nDangling = Gia_ManMarkDangling(pNew); + assert( nDangling == 0 ); + Gia_ManCleanMark01(pNew); + return pNew; +} +Vec_Int_t * Gia_ManFindMutualEquivs( Gia_Man_t * p0, Gia_Man_t * p1, int nConflictLimit, int fVerbose ) +{ + Vec_Int_t * vPairs = Vec_IntAlloc( 100 ); + // derive the miter + Gia_Man_t * pMiter = Gia_ManCreateDualOutputMiter( p0, p1 ); + //Gia_ManPrintStats( pMiter, NULL ); + //Gia_AigerWrite( pMiter, "out.aig", 0, 0, 0 ); + // perform SAT sweeping + extern Gia_Man_t * Cec4_ManSimulateTest3( Gia_Man_t * p, int nBTLimit, int fVerbose ); + Gia_Man_t * pNew = Cec4_ManSimulateTest3( pMiter, nConflictLimit, fVerbose ); + Gia_ManStop( pNew ); + // now, pMiter is annotated with the equiv class info + + // here we collect AIG node pairs with the following properties: + // - the first node belongs to p0; the second node belongs to p1 + // - both nodes are internal nodes of p0 and p1 (not primary inputs/outputs) + // - these nodes are combinationally equivalent (possibly up to the complement) + // - these nodes are "singleton" equivalences (no other nodes in p0 and p1 are equivalent to them) + // - these nodes are not structurally equivalent (that is, they have structurally different TFI logic cones) + + // count the number of nodes in each equivalence class + Vec_Int_t * vCounts = Vec_IntStart( Gia_ManObjNum(pMiter) ); + Gia_Obj_t * pObj; int i, k; + Gia_ManForEachClass( pMiter, i ) + Gia_ClassForEachObj( pMiter, i, k ) + Vec_IntAddToEntry( vCounts, i, 1 ); + + // map each miter node coming from p1 into the corresponding node in p1 + Vec_Int_t * vMap = Vec_IntStartFull( Gia_ManObjNum(pMiter) ); + int iStartP1 = 1 + Gia_ManPiNum(p0) + Gia_ManAndNum(p0); + Gia_ManForEachAnd( p1, pObj, i ) + if ( Abc_Lit2Var(pObj->Value) >= iStartP1 ) // node from p1 (not from p0) + Vec_IntWriteEntry( vMap, Abc_Lit2Var(pObj->Value), i ); + + // go through functionally (not structurally!) equivalent nodes in the second AIG + // and collect those node pairs from p0 and p1 whose equivalence class contains exactly two nodes + for ( i = iStartP1; i < Gia_ManObjNum(pMiter) - Gia_ManCoNum(pMiter); i++ ) { + assert( Gia_ObjIsAnd(Gia_ManObj(pMiter, i)) ); + int Repr = Gia_ObjRepr(pMiter, i); + if ( Repr == GIA_VOID || Repr >= iStartP1 || Vec_IntEntry(vCounts, Repr) != 2 ) + continue; + assert( Repr < iStartP1 ); // node in p0 + assert( Vec_IntEntry(vMap, i) > 0 ); // node in p1 + Vec_IntPushTwo( vPairs, Repr, Vec_IntEntry(vMap, i) ); + } + // cleanup + Vec_IntFree( vMap ); + Vec_IntFree( vCounts ); + Gia_ManStop( pMiter ); + return vPairs; +} +void Gia_ManFindMutualEquivsTest() +{ + Gia_Man_t * p0 = Gia_AigerRead( "p0.aig", 0, 0, 0 ); + Gia_Man_t * p1 = Gia_AigerRead( "p1.aig", 0, 0, 0 ); + Vec_Int_t * vPairs = Gia_ManFindMutualEquivs( p0, p1, 0, 0 ); + printf( "Pair Aig0 node Aig1 node\n" ); + int i, Obj0, Obj1; + Vec_IntForEachEntryDouble( vPairs, Obj0, Obj1, i ) + printf( "%3d %6d %6d\n", i/2, Obj0, Obj1 ); + Gia_ManStop( p0 ); + Gia_ManStop( p1 ); + Vec_IntFree( vPairs ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/gia/module.make b/yosys/abc/src/aig/gia/module.make new file mode 100644 index 00000000000..2e64d1d1b23 --- /dev/null +++ b/yosys/abc/src/aig/gia/module.make @@ -0,0 +1,115 @@ +SRC += src/aig/gia/giaAig.c \ + src/aig/gia/giaAgi.c \ + src/aig/gia/giaAiger.c \ + src/aig/gia/giaAigerExt.c \ + src/aig/gia/giaBalAig.c \ + src/aig/gia/giaBalLut.c \ + src/aig/gia/giaBalMap.c \ + src/aig/gia/giaBidec.c \ + src/aig/gia/giaCCof.c \ + src/aig/gia/giaCex.c \ + src/aig/gia/giaClp.c \ + src/aig/gia/giaCof.c \ + src/aig/gia/giaCone.c \ + src/aig/gia/giaCSatOld.c \ + src/aig/gia/giaCSat.c \ + src/aig/gia/giaCSat2.c \ + src/aig/gia/giaCSat3.c \ + src/aig/gia/giaCSatP.c \ + src/aig/gia/giaCTas.c \ + src/aig/gia/giaCut.c \ + src/aig/gia/giaDecs.c \ + src/aig/gia/giaDeep.c \ + src/aig/gia/giaDfs.c \ + src/aig/gia/giaDup.c \ + src/aig/gia/giaEdge.c \ + src/aig/gia/giaEmbed.c \ + src/aig/gia/giaEnable.c \ + src/aig/gia/giaEquiv.c \ + src/aig/gia/giaEra.c \ + src/aig/gia/giaEra2.c \ + src/aig/gia/giaEsop.c \ + src/aig/gia/giaExist.c \ + src/aig/gia/giaFalse.c \ + src/aig/gia/giaFanout.c \ + src/aig/gia/giaForce.c \ + src/aig/gia/giaFrames.c \ + src/aig/gia/giaFront.c \ + src/aig/gia/giaFx.c \ + src/aig/gia/giaGen.c \ + src/aig/gia/giaGig.c \ + src/aig/gia/giaGlitch.c \ + src/aig/gia/giaHash.c \ + src/aig/gia/giaIf.c \ + src/aig/gia/giaIff.c \ + src/aig/gia/giaIiff.c \ + src/aig/gia/giaIso.c \ + src/aig/gia/giaIso2.c \ + src/aig/gia/giaIso3.c \ + src/aig/gia/giaJf.c \ + src/aig/gia/giaKf.c \ + src/aig/gia/giaLf.c \ + src/aig/gia/giaMf.c \ + src/aig/gia/giaMan.c \ + src/aig/gia/giaMem.c \ + src/aig/gia/giaMfs.c \ + src/aig/gia/giaMini.c \ + src/aig/gia/giaMinLut.c \ + src/aig/gia/giaMinLut2.c \ + src/aig/gia/giaMulFind.c \ + src/aig/gia/giaMuxes.c \ + src/aig/gia/giaNf.c \ + src/aig/gia/giaOf.c \ + src/aig/gia/giaPack.c \ + src/aig/gia/giaPat.c \ + src/aig/gia/giaPat2.c \ + src/aig/gia/giaPf.c \ + src/aig/gia/giaQbf.c \ + src/aig/gia/giaReshape1.c \ + src/aig/gia/giaReshape2.c \ + src/aig/gia/giaResub.c \ + src/aig/gia/giaResub2.c \ + src/aig/gia/giaResub3.c \ + src/aig/gia/giaResub6.c \ + src/aig/gia/giaRetime.c \ + src/aig/gia/giaRex.c \ + src/aig/gia/giaRrr.cpp \ + src/aig/gia/giaSatEdge.c \ + src/aig/gia/giaSatLE.c \ + src/aig/gia/giaSatLut.c \ + src/aig/gia/giaSatMap.c \ + src/aig/gia/giaSatoko.c \ + src/aig/gia/giaSatSyn.c \ + src/aig/gia/giaSat3.c \ + src/aig/gia/giaScl.c \ + src/aig/gia/giaScript.c \ + src/aig/gia/giaShow.c \ + src/aig/gia/giaShrink.c \ + src/aig/gia/giaShrink6.c \ + src/aig/gia/giaShrink7.c \ + src/aig/gia/giaSif.c \ + src/aig/gia/giaSim.c \ + src/aig/gia/giaSim2.c \ + src/aig/gia/giaSimBase.c \ + src/aig/gia/giaSort.c \ + src/aig/gia/giaSpeedup.c \ + src/aig/gia/giaSplit.c \ + src/aig/gia/giaStg.c \ + src/aig/gia/giaStoch.c \ + src/aig/gia/giaStr.c \ + src/aig/gia/giaSupMin.c \ + src/aig/gia/giaSupp.c \ + src/aig/gia/giaSupps.c \ + src/aig/gia/giaSweep.c \ + src/aig/gia/giaSweeper.c \ + src/aig/gia/giaSwitch.c \ + src/aig/gia/giaTim.c \ + src/aig/gia/giaTis.c \ + src/aig/gia/giaTransduction.cpp \ + src/aig/gia/giaTranStoch.c \ + src/aig/gia/giaTruth.c \ + src/aig/gia/giaTsim.c \ + src/aig/gia/giaTtopt.cpp \ + src/aig/gia/giaUnate.c \ + src/aig/gia/giaUtil.c \ + src/aig/gia/giaBound.c diff --git a/yosys/abc/src/aig/hop/cudd2.c b/yosys/abc/src/aig/hop/cudd2.c new file mode 100644 index 00000000000..682904f7f7b --- /dev/null +++ b/yosys/abc/src/aig/hop/cudd2.c @@ -0,0 +1,360 @@ +/**CFile**************************************************************** + + FileName [cudd2.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [Recording AIGs for the BDD operations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - October 3, 2006.] + + Revision [$Id: cudd2.c,v 1.00 2006/10/03 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" +#include "misc/st/st.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Aig_CuddMan_t_ Aig_CuddMan_t; +struct Aig_CuddMan_t_ +{ + Aig_Man_t * pAig; // internal AIG package + st__table * pTable; // hash table mapping BDD nodes into AIG nodes +}; + +// static Cudd AIG manager used in this experiment +static Aig_CuddMan_t * s_pCuddMan = NULL; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Start AIG recording.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_Init( unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory, void * pCudd ) +{ + int v; + // start the BDD-to-AIG manager when the first BDD manager is allocated + if ( s_pCuddMan != NULL ) + return; + s_pCuddMan = ALLOC( Aig_CuddMan_t, 1 ); + s_pCuddMan->pAig = Aig_ManStart(); + s_pCuddMan->pTable = st__init_table( st__ptrcmp, st__ptrhash ); + for ( v = 0; v < (int)numVars; v++ ) + Aig_ObjCreatePi( s_pCuddMan->pAig ); +} + +/**Function************************************************************* + + Synopsis [Stops AIG recording.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_Quit( void * pCudd ) +{ + assert( s_pCuddMan != NULL ); + Aig_ManDumpBlif( s_pCuddMan->pAig, "aig_temp.blif", NULL, NULL ); + Aig_ManStop( s_pCuddMan->pAig ); + st__free_table( s_pCuddMan->pTable ); + free( s_pCuddMan ); + s_pCuddMan = NULL; +} + +/**Function************************************************************* + + Synopsis [Fetches AIG node corresponding to the BDD node from the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static Aig_Obj_t * Cudd2_GetArg( void * pArg ) +{ + Aig_Obj_t * pNode; + assert( s_pCuddMan != NULL ); + if ( ! st__lookup( s_pCuddMan->pTable, (char *)Aig_Regular(pArg), (char **)&pNode ) ) + { + printf( "Cudd2_GetArg(): An argument BDD is not in the hash table.\n" ); + return NULL; + } + return Aig_NotCond( pNode, Aig_IsComplement(pArg) ); +} + +/**Function************************************************************* + + Synopsis [Inserts the AIG node corresponding to the BDD node into the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static void Cudd2_SetArg( Aig_Obj_t * pNode, void * pResult ) +{ + assert( s_pCuddMan != NULL ); + if ( st__is_member( s_pCuddMan->pTable, (char *)Aig_Regular(pResult) ) ) + return; + pNode = Aig_NotCond( pNode, Aig_IsComplement(pResult) ); + st__insert( s_pCuddMan->pTable, (char *)Aig_Regular(pResult), (char *)pNode ); +} + +/**Function************************************************************* + + Synopsis [Registers constant 1 node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddOne( void * pCudd, void * pResult ) +{ + Cudd2_SetArg( Aig_ManConst1(s_pCuddMan->pAig), pResult ); +} + +/**Function************************************************************* + + Synopsis [Adds elementary variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddIthVar( void * pCudd, int iVar, void * pResult ) +{ + int v; + assert( s_pCuddMan != NULL ); + for ( v = Aig_ManPiNum(s_pCuddMan->pAig); v <= iVar; v++ ) + Aig_ObjCreatePi( s_pCuddMan->pAig ); + Cudd2_SetArg( Aig_ManPi(s_pCuddMan->pAig, iVar), pResult ); +} + +/**Function************************************************************* + + Synopsis [Performs BDD operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddAnd( void * pCudd, void * pArg0, void * pArg1, void * pResult ) +{ + Aig_Obj_t * pNode0, * pNode1, * pNode; + pNode0 = Cudd2_GetArg( pArg0 ); + pNode1 = Cudd2_GetArg( pArg1 ); + pNode = Aig_And( s_pCuddMan->pAig, pNode0, pNode1 ); + Cudd2_SetArg( pNode, pResult ); +} + +/**Function************************************************************* + + Synopsis [Performs BDD operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddOr( void * pCudd, void * pArg0, void * pArg1, void * pResult ) +{ + Cudd2_bddAnd( pCudd, Aig_Not(pArg0), Aig_Not(pArg1), Aig_Not(pResult) ); +} + +/**Function************************************************************* + + Synopsis [Performs BDD operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddNand( void * pCudd, void * pArg0, void * pArg1, void * pResult ) +{ + Cudd2_bddAnd( pCudd, pArg0, pArg1, Aig_Not(pResult) ); +} + +/**Function************************************************************* + + Synopsis [Performs BDD operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddNor( void * pCudd, void * pArg0, void * pArg1, void * pResult ) +{ + Cudd2_bddAnd( pCudd, Aig_Not(pArg0), Aig_Not(pArg1), pResult ); +} + +/**Function************************************************************* + + Synopsis [Performs BDD operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddXor( void * pCudd, void * pArg0, void * pArg1, void * pResult ) +{ + Aig_Obj_t * pNode0, * pNode1, * pNode; + pNode0 = Cudd2_GetArg( pArg0 ); + pNode1 = Cudd2_GetArg( pArg1 ); + pNode = Aig_Exor( s_pCuddMan->pAig, pNode0, pNode1 ); + Cudd2_SetArg( pNode, pResult ); +} + +/**Function************************************************************* + + Synopsis [Performs BDD operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddXnor( void * pCudd, void * pArg0, void * pArg1, void * pResult ) +{ + Cudd2_bddXor( pCudd, pArg0, pArg1, Aig_Not(pResult) ); +} + +/**Function************************************************************* + + Synopsis [Performs BDD operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddIte( void * pCudd, void * pArg0, void * pArg1, void * pArg2, void * pResult ) +{ + Aig_Obj_t * pNode0, * pNode1, * pNode2, * pNode; + pNode0 = Cudd2_GetArg( pArg0 ); + pNode1 = Cudd2_GetArg( pArg1 ); + pNode2 = Cudd2_GetArg( pArg2 ); + pNode = Aig_Mux( s_pCuddMan->pAig, pNode0, pNode1, pNode2 ); + Cudd2_SetArg( pNode, pResult ); +} + +/**Function************************************************************* + + Synopsis [Performs BDD operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddCompose( void * pCudd, void * pArg0, void * pArg1, int v, void * pResult ) +{ + Aig_Obj_t * pNode0, * pNode1, * pNode; + pNode0 = Cudd2_GetArg( pArg0 ); + pNode1 = Cudd2_GetArg( pArg1 ); + pNode = Aig_Compose( s_pCuddMan->pAig, pNode0, pNode1, v ); + Cudd2_SetArg( pNode, pResult ); +} + +/**Function************************************************************* + + Synopsis [Should be called after each containment check.] + + Description [Result should be 1 if Cudd2_bddLeq returned 1.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddLeq( void * pCudd, void * pArg0, void * pArg1, int Result ) +{ + Aig_Obj_t * pNode0, * pNode1, * pNode; + pNode0 = Cudd2_GetArg( pArg0 ); + pNode1 = Cudd2_GetArg( pArg1 ); + pNode = Aig_And( s_pCuddMan->pAig, pNode0, Aig_Not(pNode1) ); + Aig_ObjCreatePo( s_pCuddMan->pAig, pNode ); +} + +/**Function************************************************************* + + Synopsis [Should be called after each equality check.] + + Description [Result should be 1 if they are equal.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Cudd2_bddEqual( void * pCudd, void * pArg0, void * pArg1, int Result ) +{ + Aig_Obj_t * pNode0, * pNode1, * pNode; + pNode0 = Cudd2_GetArg( pArg0 ); + pNode1 = Cudd2_GetArg( pArg1 ); + pNode = Aig_Exor( s_pCuddMan->pAig, pNode0, pNode1 ); + Aig_ObjCreatePo( s_pCuddMan->pAig, pNode ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/hop/cudd2.h b/yosys/abc/src/aig/hop/cudd2.h new file mode 100644 index 00000000000..e38118f4614 --- /dev/null +++ b/yosys/abc/src/aig/hop/cudd2.h @@ -0,0 +1,86 @@ +/**CFile**************************************************************** + + FileName [cudd2.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - October 3, 2006.] + + Revision [$Id: cudd2.h,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__hop__cudd2_h +#define ABC__aig__hop__cudd2_h + + +// HA: Added for printing messages +#ifndef MSG +#define MSG(msg) (printf("%s = \n",(msg))); +#endif + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern void Cudd2_Init ( unsigned int numVars, unsigned int numVarsZ, unsigned int numSlots, unsigned int cacheSize, unsigned long maxMemory, void * pCudd ); +extern void Cudd2_Quit ( void * pCudd ); +extern void Cudd2_bddOne ( void * pCudd, void * pResult ); +extern void Cudd2_bddIthVar ( void * pCudd, int iVar, void * pResult ); +extern void Cudd2_bddAnd ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); +extern void Cudd2_bddOr ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); +extern void Cudd2_bddNand ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); +extern void Cudd2_bddNor ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); +extern void Cudd2_bddXor ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); +extern void Cudd2_bddXnor ( void * pCudd, void * pArg0, void * pArg1, void * pResult ); +extern void Cudd2_bddIte ( void * pCudd, void * pArg0, void * pArg1, void * pArg2, void * pResult ); +extern void Cudd2_bddCompose( void * pCudd, void * pArg0, void * pArg1, int v, void * pResult ); +extern void Cudd2_bddLeq ( void * pCudd, void * pArg0, void * pArg1, int Result ); +extern void Cudd2_bddEqual ( void * pCudd, void * pArg0, void * pArg1, int Result ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/yosys/abc/src/aig/hop/hop.h b/yosys/abc/src/aig/hop/hop.h new file mode 100644 index 00000000000..6b8085cc51d --- /dev/null +++ b/yosys/abc/src/aig/hop/hop.h @@ -0,0 +1,356 @@ +/**CFile**************************************************************** + + FileName [hop.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hop.h,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__hop__hop_h +#define ABC__aig__hop__hop_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#include "misc/vec/vec.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Hop_Man_t_ Hop_Man_t; +typedef struct Hop_Obj_t_ Hop_Obj_t; +typedef int Hop_Edge_t; + +// object types +typedef enum { + AIG_NONE, // 0: non-existent object + AIG_CONST1, // 1: constant 1 + AIG_PI, // 2: primary input + AIG_PO, // 3: primary output + AIG_AND, // 4: AND node + AIG_EXOR, // 5: EXOR node + AIG_VOID // 6: unused object +} Hop_Type_t; + +// the AIG node +struct Hop_Obj_t_ // 6 words +{ + union { + void * pData; // misc + int iData; }; // misc + union { + Hop_Obj_t * pNext; // strashing table + int PioNum; }; // the number of PI/PO + Hop_Obj_t * pFanin0; // fanin + Hop_Obj_t * pFanin1; // fanin + unsigned int Type : 3; // object type + unsigned int fPhase : 1; // value under 000...0 pattern + unsigned int fMarkA : 1; // multipurpose mask + unsigned int fMarkB : 1; // multipurpose mask + unsigned int nRefs : 26; // reference count (level) + int Id; // unique ID of the node +}; + +// the AIG manager +struct Hop_Man_t_ +{ + // AIG nodes + Vec_Ptr_t * vPis; // the array of PIs + Vec_Ptr_t * vPos; // the array of POs + Vec_Ptr_t * vObjs; // the array of all nodes (optional) + Hop_Obj_t * pConst1; // the constant 1 node + Hop_Obj_t Ghost; // the ghost node + // AIG node counters + int nObjs[AIG_VOID];// the number of objects by type + int nCreated; // the number of created objects + int nDeleted; // the number of deleted objects + // stuctural hash table + Hop_Obj_t ** pTable; // structural hash table + int nTableSize; // structural hash table size + // various data members + void * pData; // the temporary data + int nTravIds; // the current traversal ID + int fRefCount; // enables reference counting + int fCatchExor; // enables EXOR nodes + // memory management + Vec_Ptr_t * vChunks; // allocated memory pieces + Vec_Ptr_t * vPages; // memory pages used by nodes + Hop_Obj_t * pListFree; // the list of free nodes + // timing statistics + abctime time1; + abctime time2; +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// +extern void Hop_ManAddMemory( Hop_Man_t * p ); + +static inline int Hop_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); } +static inline int Hop_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } +static inline int Hop_InfoHasBit( unsigned * p, int i ) { return (p[(i)>>5] & (1<<((i) & 31))) > 0; } +static inline void Hop_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); } +static inline void Hop_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); } +static inline int Hop_Base2Log( unsigned n ) { int r; if ( n < 2 ) return n; for ( r = 0, n--; n; n >>= 1, r++ ) {}; return r; } +static inline int Hop_Base10Log( unsigned n ) { int r; if ( n < 2 ) return n; for ( r = 0, n--; n; n /= 10, r++ ) {}; return r; } + +static inline Hop_Obj_t * Hop_Regular( Hop_Obj_t * p ) { return (Hop_Obj_t *)((ABC_PTRUINT_T)(p) & ~01); } +static inline Hop_Obj_t * Hop_Not( Hop_Obj_t * p ) { return (Hop_Obj_t *)((ABC_PTRUINT_T)(p) ^ 01); } +static inline Hop_Obj_t * Hop_NotCond( Hop_Obj_t * p, int c ) { return (Hop_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c)); } +static inline int Hop_IsComplement( Hop_Obj_t * p ) { return (int)((ABC_PTRUINT_T)(p) & 01); } + +static inline Hop_Obj_t * Hop_ManConst0( Hop_Man_t * p ) { return Hop_Not(p->pConst1); } +static inline Hop_Obj_t * Hop_ManConst1( Hop_Man_t * p ) { return p->pConst1; } +static inline Hop_Obj_t * Hop_ManGhost( Hop_Man_t * p ) { return &p->Ghost; } +static inline Hop_Obj_t * Hop_ManPi( Hop_Man_t * p, int i ) { return (Hop_Obj_t *)Vec_PtrEntry(p->vPis, i); } +static inline Hop_Obj_t * Hop_ManPo( Hop_Man_t * p, int i ) { return (Hop_Obj_t *)Vec_PtrEntry(p->vPos, i); } +static inline Hop_Obj_t * Hop_ManObj( Hop_Man_t * p, int i ) { return p->vObjs ? (Hop_Obj_t *)Vec_PtrEntry(p->vObjs, i) : NULL; } + +static inline Hop_Edge_t Hop_EdgeCreate( int Id, int fCompl ) { return (Id << 1) | fCompl; } +static inline int Hop_EdgeId( Hop_Edge_t Edge ) { return Edge >> 1; } +static inline int Hop_EdgeIsComplement( Hop_Edge_t Edge ) { return Edge & 1; } +static inline Hop_Edge_t Hop_EdgeRegular( Hop_Edge_t Edge ) { return (Edge >> 1) << 1; } +static inline Hop_Edge_t Hop_EdgeNot( Hop_Edge_t Edge ) { return Edge ^ 1; } +static inline Hop_Edge_t Hop_EdgeNotCond( Hop_Edge_t Edge, int fCond ) { return Edge ^ fCond; } + +static inline int Hop_ManPiNum( Hop_Man_t * p ) { return p->nObjs[AIG_PI]; } +static inline int Hop_ManPoNum( Hop_Man_t * p ) { return p->nObjs[AIG_PO]; } +static inline int Hop_ManAndNum( Hop_Man_t * p ) { return p->nObjs[AIG_AND]; } +static inline int Hop_ManExorNum( Hop_Man_t * p ) { return p->nObjs[AIG_EXOR]; } +static inline int Hop_ManNodeNum( Hop_Man_t * p ) { return p->nObjs[AIG_AND]+p->nObjs[AIG_EXOR];} +static inline int Hop_ManGetCost( Hop_Man_t * p ) { return p->nObjs[AIG_AND]+3*p->nObjs[AIG_EXOR]; } +static inline int Hop_ManObjNum( Hop_Man_t * p ) { return p->nCreated - p->nDeleted; } + +static inline Hop_Type_t Hop_ObjType( Hop_Obj_t * pObj ) { return (Hop_Type_t)pObj->Type; } +static inline int Hop_ObjIsNone( Hop_Obj_t * pObj ) { return pObj->Type == AIG_NONE; } +static inline int Hop_ObjIsConst1( Hop_Obj_t * pObj ) { assert(!Hop_IsComplement(pObj)); return pObj->Type == AIG_CONST1; } +static inline int Hop_ObjIsPi( Hop_Obj_t * pObj ) { return pObj->Type == AIG_PI; } +static inline int Hop_ObjIsPo( Hop_Obj_t * pObj ) { return pObj->Type == AIG_PO; } +static inline int Hop_ObjIsAnd( Hop_Obj_t * pObj ) { return pObj->Type == AIG_AND; } +static inline int Hop_ObjIsExor( Hop_Obj_t * pObj ) { return pObj->Type == AIG_EXOR; } +static inline int Hop_ObjIsNode( Hop_Obj_t * pObj ) { return pObj->Type == AIG_AND || pObj->Type == AIG_EXOR; } +static inline int Hop_ObjIsTerm( Hop_Obj_t * pObj ) { return pObj->Type == AIG_PI || pObj->Type == AIG_PO || pObj->Type == AIG_CONST1; } +static inline int Hop_ObjIsHash( Hop_Obj_t * pObj ) { return pObj->Type == AIG_AND || pObj->Type == AIG_EXOR; } + +static inline int Hop_ObjIsMarkA( Hop_Obj_t * pObj ) { return pObj->fMarkA; } +static inline void Hop_ObjSetMarkA( Hop_Obj_t * pObj ) { pObj->fMarkA = 1; } +static inline void Hop_ObjClearMarkA( Hop_Obj_t * pObj ) { pObj->fMarkA = 0; } + +static inline void Hop_ObjSetTravId( Hop_Obj_t * pObj, int TravId ) { pObj->pData = (void *)(ABC_PTRINT_T)TravId; } +static inline void Hop_ObjSetTravIdCurrent( Hop_Man_t * p, Hop_Obj_t * pObj ) { pObj->pData = (void *)(ABC_PTRINT_T)p->nTravIds; } +static inline void Hop_ObjSetTravIdPrevious( Hop_Man_t * p, Hop_Obj_t * pObj ) { pObj->pData = (void *)(ABC_PTRINT_T)(p->nTravIds - 1); } +static inline int Hop_ObjIsTravIdCurrent( Hop_Man_t * p, Hop_Obj_t * pObj ) { return (int)((int)(ABC_PTRINT_T)pObj->pData == p->nTravIds); } +static inline int Hop_ObjIsTravIdPrevious( Hop_Man_t * p, Hop_Obj_t * pObj ) { return (int)((int)(ABC_PTRINT_T)pObj->pData == p->nTravIds - 1); } + +static inline int Hop_ObjTravId( Hop_Obj_t * pObj ) { return (int)(ABC_PTRINT_T)pObj->pData; } +static inline int Hop_ObjPhase( Hop_Obj_t * pObj ) { return pObj->fPhase; } +static inline int Hop_ObjRefs( Hop_Obj_t * pObj ) { return pObj->nRefs; } +static inline void Hop_ObjRef( Hop_Obj_t * pObj ) { pObj->nRefs++; } +static inline void Hop_ObjDeref( Hop_Obj_t * pObj ) { assert( pObj->nRefs > 0 ); pObj->nRefs--; } +static inline void Hop_ObjClearRef( Hop_Obj_t * pObj ) { pObj->nRefs = 0; } +static inline int Hop_ObjFaninC0( Hop_Obj_t * pObj ) { return Hop_IsComplement(pObj->pFanin0); } +static inline int Hop_ObjFaninC1( Hop_Obj_t * pObj ) { return Hop_IsComplement(pObj->pFanin1); } +static inline Hop_Obj_t * Hop_ObjFanin0( Hop_Obj_t * pObj ) { return Hop_Regular(pObj->pFanin0); } +static inline Hop_Obj_t * Hop_ObjFanin1( Hop_Obj_t * pObj ) { return Hop_Regular(pObj->pFanin1); } +static inline Hop_Obj_t * Hop_ObjChild0( Hop_Obj_t * pObj ) { return pObj->pFanin0; } +static inline Hop_Obj_t * Hop_ObjChild1( Hop_Obj_t * pObj ) { return pObj->pFanin1; } +static inline Hop_Obj_t * Hop_ObjChild0Copy( Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); return Hop_ObjFanin0(pObj)? Hop_NotCond((Hop_Obj_t *)Hop_ObjFanin0(pObj)->pData, Hop_ObjFaninC0(pObj)) : NULL; } +static inline Hop_Obj_t * Hop_ObjChild1Copy( Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); return Hop_ObjFanin1(pObj)? Hop_NotCond((Hop_Obj_t *)Hop_ObjFanin1(pObj)->pData, Hop_ObjFaninC1(pObj)) : NULL; } +static inline int Hop_ObjChild0CopyI( Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); return Hop_ObjFanin0(pObj)? Abc_LitNotCond(Hop_ObjFanin0(pObj)->iData, Hop_ObjFaninC0(pObj)) : -1; } +static inline int Hop_ObjChild1CopyI( Hop_Obj_t * pObj ) { assert( !Hop_IsComplement(pObj) ); return Hop_ObjFanin1(pObj)? Abc_LitNotCond(Hop_ObjFanin1(pObj)->iData, Hop_ObjFaninC1(pObj)) : -1; } +static inline int Hop_ObjLevel( Hop_Obj_t * pObj ) { return pObj->nRefs; } +static inline int Hop_ObjLevelNew( Hop_Obj_t * pObj ) { return 1 + Hop_ObjIsExor(pObj) + Abc_MaxInt(Hop_ObjFanin0(pObj)->nRefs, Hop_ObjFanin1(pObj)->nRefs); } +static inline int Hop_ObjPhaseCompl( Hop_Obj_t * pObj ) { return Hop_IsComplement(pObj)? !Hop_Regular(pObj)->fPhase : pObj->fPhase; } +static inline void Hop_ObjClean( Hop_Obj_t * pObj ) { memset( pObj, 0, sizeof(Hop_Obj_t) ); } +static inline int Hop_ObjWhatFanin( Hop_Obj_t * pObj, Hop_Obj_t * pFanin ) +{ + if ( Hop_ObjFanin0(pObj) == pFanin ) return 0; + if ( Hop_ObjFanin1(pObj) == pFanin ) return 1; + assert(0); return -1; +} +static inline int Hop_ObjFanoutC( Hop_Obj_t * pObj, Hop_Obj_t * pFanout ) +{ + if ( Hop_ObjFanin0(pFanout) == pObj ) return Hop_ObjFaninC0(pObj); + if ( Hop_ObjFanin1(pFanout) == pObj ) return Hop_ObjFaninC1(pObj); + assert(0); return -1; +} + +// create the ghost of the new node +static inline Hop_Obj_t * Hop_ObjCreateGhost( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Type_t Type ) +{ + Hop_Obj_t * pGhost; + assert( Type != AIG_AND || !Hop_ObjIsConst1(Hop_Regular(p0)) ); + assert( p1 == NULL || !Hop_ObjIsConst1(Hop_Regular(p1)) ); + assert( Type == AIG_PI || Hop_Regular(p0) != Hop_Regular(p1) ); + pGhost = Hop_ManGhost(p); + pGhost->Type = Type; + if ( Hop_Regular(p0)->Id < Hop_Regular(p1)->Id ) + { + pGhost->pFanin0 = p0; + pGhost->pFanin1 = p1; + } + else + { + pGhost->pFanin0 = p1; + pGhost->pFanin1 = p0; + } + return pGhost; +} + +// internal memory manager +static inline Hop_Obj_t * Hop_ManFetchMemory( Hop_Man_t * p ) +{ + Hop_Obj_t * pTemp; + if ( p->pListFree == NULL ) + Hop_ManAddMemory( p ); + pTemp = p->pListFree; + p->pListFree = *((Hop_Obj_t **)pTemp); + memset( pTemp, 0, sizeof(Hop_Obj_t) ); + if ( p->vObjs ) + { + assert( p->nCreated == Vec_PtrSize(p->vObjs) ); + Vec_PtrPush( p->vObjs, pTemp ); + } + pTemp->Id = p->nCreated++; + return pTemp; +} +static inline void Hop_ManRecycleMemory( Hop_Man_t * p, Hop_Obj_t * pEntry ) +{ + pEntry->Type = AIG_NONE; // distinquishes dead node from live node + *((Hop_Obj_t **)pEntry) = p->pListFree; + p->pListFree = pEntry; +} + + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +// iterator over the primary inputs +#define Hop_ManForEachPi( p, pObj, i ) \ + Vec_PtrForEachEntry( Hop_Obj_t *, p->vPis, pObj, i ) +// iterator over the primary outputs +#define Hop_ManForEachPo( p, pObj, i ) \ + Vec_PtrForEachEntry( Hop_Obj_t *, p->vPos, pObj, i ) +// iterator over all objects, including those currently not used +#define Hop_ManForEachNode( p, pObj, i ) \ + for ( i = 0; i < p->nTableSize; i++ ) \ + if ( ((pObj) = p->pTable[i]) == NULL ) {} else + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== hopBalance.c ========================================================*/ +extern Hop_Man_t * Hop_ManBalance( Hop_Man_t * p, int fUpdateLevel ); +extern Hop_Obj_t * Hop_NodeBalanceBuildSuper( Hop_Man_t * p, Vec_Ptr_t * vSuper, Hop_Type_t Type, int fUpdateLevel ); +/*=== hopCheck.c ========================================================*/ +extern int Hop_ManCheck( Hop_Man_t * p ); +/*=== hopDfs.c ==========================================================*/ +extern Vec_Ptr_t * Hop_ManDfs( Hop_Man_t * p ); +extern Vec_Ptr_t * Hop_ManDfsNode( Hop_Man_t * p, Hop_Obj_t * pNode ); +extern int Hop_ManCountLevels( Hop_Man_t * p ); +extern void Hop_ManCreateRefs( Hop_Man_t * p ); +extern int Hop_DagSize( Hop_Obj_t * pObj ); +extern int Hop_ObjFanoutCount( Hop_Obj_t * pObj, Hop_Obj_t * pPivot ); +extern void Hop_ConeUnmark_rec( Hop_Obj_t * pObj ); +extern Hop_Obj_t * Hop_Transfer( Hop_Man_t * pSour, Hop_Man_t * pDest, Hop_Obj_t * pObj, int nVars ); +extern Hop_Obj_t * Hop_Compose( Hop_Man_t * p, Hop_Obj_t * pRoot, Hop_Obj_t * pFunc, int iVar ); +extern Hop_Obj_t * Hop_Complement( Hop_Man_t * p, Hop_Obj_t * pRoot, int iVar ); +extern Hop_Obj_t * Hop_Remap( Hop_Man_t * p, Hop_Obj_t * pRoot, unsigned uSupp, int nVars ); +extern Hop_Obj_t * Hop_Permute( Hop_Man_t * p, Hop_Obj_t * pRoot, int nRootVars, int * pPermute ); +/*=== hopMan.c ==========================================================*/ +extern Hop_Man_t * Hop_ManStart(); +extern Hop_Man_t * Hop_ManDup( Hop_Man_t * p ); +extern void Hop_ManStop( Hop_Man_t * p ); +extern int Hop_ManCleanup( Hop_Man_t * p ); +extern void Hop_ManPrintStats( Hop_Man_t * p ); +/*=== hopMem.c ==========================================================*/ +extern void Hop_ManStartMemory( Hop_Man_t * p ); +extern void Hop_ManStopMemory( Hop_Man_t * p ); +/*=== hopObj.c ==========================================================*/ +extern Hop_Obj_t * Hop_ObjCreatePi( Hop_Man_t * p ); +extern Hop_Obj_t * Hop_ObjCreatePo( Hop_Man_t * p, Hop_Obj_t * pDriver ); +extern Hop_Obj_t * Hop_ObjCreate( Hop_Man_t * p, Hop_Obj_t * pGhost ); +extern void Hop_ObjConnect( Hop_Man_t * p, Hop_Obj_t * pObj, Hop_Obj_t * pFan0, Hop_Obj_t * pFan1 ); +extern void Hop_ObjDisconnect( Hop_Man_t * p, Hop_Obj_t * pObj ); +extern void Hop_ObjDelete( Hop_Man_t * p, Hop_Obj_t * pObj ); +extern void Hop_ObjDelete_rec( Hop_Man_t * p, Hop_Obj_t * pObj ); +extern Hop_Obj_t * Hop_ObjRepr( Hop_Obj_t * pObj ); +extern void Hop_ObjCreateChoice( Hop_Obj_t * pOld, Hop_Obj_t * pNew ); +/*=== hopOper.c =========================================================*/ +extern Hop_Obj_t * Hop_IthVar( Hop_Man_t * p, int i ); +extern Hop_Obj_t * Hop_Oper( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Type_t Type ); +extern Hop_Obj_t * Hop_And( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ); +extern Hop_Obj_t * Hop_Or( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ); +extern Hop_Obj_t * Hop_Exor( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ); +extern Hop_Obj_t * Hop_Mux( Hop_Man_t * p, Hop_Obj_t * pC, Hop_Obj_t * p1, Hop_Obj_t * p0 ); +extern Hop_Obj_t * Hop_Maj( Hop_Man_t * p, Hop_Obj_t * pA, Hop_Obj_t * pB, Hop_Obj_t * pC ); +extern Hop_Obj_t * Hop_Miter( Hop_Man_t * p, Vec_Ptr_t * vPairs ); +extern Hop_Obj_t * Hop_CreateAnd( Hop_Man_t * p, int nVars ); +extern Hop_Obj_t * Hop_CreateOr( Hop_Man_t * p, int nVars ); +extern Hop_Obj_t * Hop_CreateExor( Hop_Man_t * p, int nVars ); +/*=== hopTable.c ========================================================*/ +extern Hop_Obj_t * Hop_TableLookup( Hop_Man_t * p, Hop_Obj_t * pGhost ); +extern void Hop_TableInsert( Hop_Man_t * p, Hop_Obj_t * pObj ); +extern void Hop_TableDelete( Hop_Man_t * p, Hop_Obj_t * pObj ); +extern int Hop_TableCountEntries( Hop_Man_t * p ); +extern void Hop_TableProfile( Hop_Man_t * p ); +/*=== hopTruth.c ========================================================*/ +extern unsigned * Hop_ManConvertAigToTruth( Hop_Man_t * p, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, int fMsbFirst ); +extern word Hop_ManComputeTruth6( Hop_Man_t * p, Hop_Obj_t * pObj, int nVars ); +/*=== hopUtil.c =========================================================*/ +extern void Hop_ManIncrementTravId( Hop_Man_t * p ); +extern void Hop_ManCleanData( Hop_Man_t * p ); +extern void Hop_ObjCleanData_rec( Hop_Obj_t * pObj ); +extern void Hop_ObjCollectMulti( Hop_Obj_t * pFunc, Vec_Ptr_t * vSuper ); +extern int Hop_ObjIsMuxType( Hop_Obj_t * pObj ); +extern int Hop_ObjRecognizeExor( Hop_Obj_t * pObj, Hop_Obj_t ** ppFan0, Hop_Obj_t ** ppFan1 ); +extern Hop_Obj_t * Hop_ObjRecognizeMux( Hop_Obj_t * pObj, Hop_Obj_t ** ppObjT, Hop_Obj_t ** ppObjE ); +extern void Hop_ObjPrintEqn( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ); +extern void Hop_ObjPrintVerilog( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int Level, int fOnlyAnds ); +extern void Hop_ObjPrintVerbose( Hop_Obj_t * pObj, int fHaig ); +extern void Hop_ManPrintVerbose( Hop_Man_t * p, int fHaig ); +extern void Hop_ManDumpBlif( Hop_Man_t * p, char * pFileName ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/yosys/abc/src/aig/hop/hopBalance.c b/yosys/abc/src/aig/hop/hopBalance.c new file mode 100644 index 00000000000..a3ce1c868c4 --- /dev/null +++ b/yosys/abc/src/aig/hop/hopBalance.c @@ -0,0 +1,401 @@ +/**CFile**************************************************************** + + FileName [hopBalance.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [Algebraic AIG balancing.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopBalance.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Hop_Obj_t * Hop_NodeBalance_rec( Hop_Man_t * pNew, Hop_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel ); +static Vec_Ptr_t * Hop_NodeBalanceCone( Hop_Obj_t * pObj, Vec_Vec_t * vStore, int Level ); +static int Hop_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ); +static void Hop_NodeBalancePermute( Hop_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ); +static void Hop_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Hop_Obj_t * pObj ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs algebraic balancing of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Man_t * Hop_ManBalance( Hop_Man_t * p, int fUpdateLevel ) +{ + Hop_Man_t * pNew; + Hop_Obj_t * pObj, * pObjNew; + Vec_Vec_t * vStore; + int i; + // create the new manager + pNew = Hop_ManStart(); + pNew->fRefCount = 0; + // map the PI nodes + Hop_ManCleanData( p ); + Hop_ManConst1(p)->pData = Hop_ManConst1(pNew); + Hop_ManForEachPi( p, pObj, i ) + pObj->pData = Hop_ObjCreatePi(pNew); + // balance the AIG + vStore = Vec_VecAlloc( 50 ); + Hop_ManForEachPo( p, pObj, i ) + { + pObjNew = Hop_NodeBalance_rec( pNew, Hop_ObjFanin0(pObj), vStore, 0, fUpdateLevel ); + Hop_ObjCreatePo( pNew, Hop_NotCond( pObjNew, Hop_ObjFaninC0(pObj) ) ); + } + Vec_VecFree( vStore ); + // remove dangling nodes +// Hop_ManCreateRefs( pNew ); +// if ( i = Hop_ManCleanup( pNew ) ) +// printf( "Cleanup after balancing removed %d dangling nodes.\n", i ); + // check the resulting AIG + if ( !Hop_ManCheck(pNew) ) + printf( "Hop_ManBalance(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Returns the new node constructed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_NodeBalance_rec( Hop_Man_t * pNew, Hop_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel ) +{ + Hop_Obj_t * pObjNew; + Vec_Ptr_t * vSuper; + int i; + assert( !Hop_IsComplement(pObjOld) ); + // return if the result is known + if ( pObjOld->pData ) + return (Hop_Obj_t *)pObjOld->pData; + assert( Hop_ObjIsNode(pObjOld) ); + // get the implication supergate + vSuper = Hop_NodeBalanceCone( pObjOld, vStore, Level ); + // check if supergate contains two nodes in the opposite polarity + if ( vSuper->nSize == 0 ) + return (Hop_Obj_t *)(pObjOld->pData = Hop_ManConst0(pNew)); + if ( Vec_PtrSize(vSuper) < 2 ) + printf( "BUG!\n" ); + // for each old node, derive the new well-balanced node + for ( i = 0; i < Vec_PtrSize(vSuper); i++ ) + { + pObjNew = Hop_NodeBalance_rec( pNew, Hop_Regular((Hop_Obj_t *)vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel ); + vSuper->pArray[i] = Hop_NotCond( pObjNew, Hop_IsComplement((Hop_Obj_t *)vSuper->pArray[i]) ); + } + // build the supergate + pObjNew = Hop_NodeBalanceBuildSuper( pNew, vSuper, Hop_ObjType(pObjOld), fUpdateLevel ); + // make sure the balanced node is not assigned +// assert( pObjOld->Level >= Hop_Regular(pObjNew)->Level ); + assert( pObjOld->pData == NULL ); + return (Hop_Obj_t *)(pObjOld->pData = pObjNew); +} + +/**Function************************************************************* + + Synopsis [Collects the nodes of the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_NodeBalanceCone_rec( Hop_Obj_t * pRoot, Hop_Obj_t * pObj, Vec_Ptr_t * vSuper ) +{ + int RetValue1, RetValue2, i; + // check if the node is visited + if ( Hop_Regular(pObj)->fMarkB ) + { + // check if the node occurs in the same polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == pObj ) + return 1; + // check if the node is present in the opposite polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == Hop_Not(pObj) ) + return -1; + assert( 0 ); + return 0; + } + // if the new node is complemented or a PI, another gate begins + if ( pObj != pRoot && (Hop_IsComplement(pObj) || Hop_ObjType(pObj) != Hop_ObjType(pRoot) || Hop_ObjRefs(pObj) > 1 || Vec_PtrSize(vSuper) > 10000) ) + { + Vec_PtrPush( vSuper, pObj ); + Hop_Regular(pObj)->fMarkB = 1; + return 0; + } + assert( !Hop_IsComplement(pObj) ); + assert( Hop_ObjIsNode(pObj) ); + // go through the branches + RetValue1 = Hop_NodeBalanceCone_rec( pRoot, Hop_ObjChild0(pObj), vSuper ); + RetValue2 = Hop_NodeBalanceCone_rec( pRoot, Hop_ObjChild1(pObj), vSuper ); + if ( RetValue1 == -1 || RetValue2 == -1 ) + return -1; + // return 1 if at least one branch has a duplicate + return RetValue1 || RetValue2; +} + +/**Function************************************************************* + + Synopsis [Collects the nodes of the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Hop_NodeBalanceCone( Hop_Obj_t * pObj, Vec_Vec_t * vStore, int Level ) +{ + Vec_Ptr_t * vNodes; + int RetValue, i; + assert( !Hop_IsComplement(pObj) ); + // extend the storage + if ( Vec_VecSize( vStore ) <= Level ) + Vec_VecPush( vStore, Level, 0 ); + // get the temporary array of nodes + vNodes = Vec_VecEntry( vStore, Level ); + Vec_PtrClear( vNodes ); + // collect the nodes in the implication supergate + RetValue = Hop_NodeBalanceCone_rec( pObj, pObj, vNodes ); + assert( vNodes->nSize > 1 ); + // unmark the visited nodes + Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i ) + Hop_Regular(pObj)->fMarkB = 0; + // if we found the node and its complement in the same implication supergate, + // return empty set of nodes (meaning that we should use constant-0 node) + if ( RetValue == -1 ) + vNodes->nSize = 0; + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_NodeCompareLevelsDecrease( Hop_Obj_t ** pp1, Hop_Obj_t ** pp2 ) +{ + int Diff = Hop_ObjLevel(Hop_Regular(*pp1)) - Hop_ObjLevel(Hop_Regular(*pp2)); + if ( Diff > 0 ) + return -1; + if ( Diff < 0 ) + return 1; + Diff = Hop_Regular(*pp1)->Id - Hop_Regular(*pp2)->Id; + if ( Diff > 0 ) + return -1; + if ( Diff < 0 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Builds implication supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_NodeBalanceBuildSuper( Hop_Man_t * p, Vec_Ptr_t * vSuper, Hop_Type_t Type, int fUpdateLevel ) +{ + Hop_Obj_t * pObj1, * pObj2; + int LeftBound; + assert( vSuper->nSize > 1 ); + // sort the new nodes by level in the decreasing order + Vec_PtrSort( vSuper, (int (*)(const void *, const void *))Hop_NodeCompareLevelsDecrease ); + // balance the nodes + while ( vSuper->nSize > 1 ) + { + // find the left bound on the node to be paired + LeftBound = (!fUpdateLevel)? 0 : Hop_NodeBalanceFindLeft( vSuper ); + // find the node that can be shared (if no such node, randomize choice) + Hop_NodeBalancePermute( p, vSuper, LeftBound, Type == AIG_EXOR ); + // pull out the last two nodes + pObj1 = (Hop_Obj_t *)Vec_PtrPop(vSuper); + pObj2 = (Hop_Obj_t *)Vec_PtrPop(vSuper); + Hop_NodeBalancePushUniqueOrderByLevel( vSuper, Hop_Oper(p, pObj1, pObj2, Type) ); + } + return (Hop_Obj_t *)Vec_PtrEntry(vSuper, 0); +} + +/**Function************************************************************* + + Synopsis [Finds the left bound on the next candidate to be paired.] + + Description [The nodes in the array are in the decreasing order of levels. + The last node in the array has the smallest level. By default it would be paired + with the next node on the left. However, it may be possible to pair it with some + other node on the left, in such a way that the new node is shared. This procedure + finds the index of the left-most node, which can be paired with the last node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ) +{ + Hop_Obj_t * pObjRight, * pObjLeft; + int Current; + // if two or less nodes, pair with the first + if ( Vec_PtrSize(vSuper) < 3 ) + return 0; + // set the pointer to the one before the last + Current = Vec_PtrSize(vSuper) - 2; + pObjRight = (Hop_Obj_t *)Vec_PtrEntry( vSuper, Current ); + // go through the nodes to the left of this one + for ( Current--; Current >= 0; Current-- ) + { + // get the next node on the left + pObjLeft = (Hop_Obj_t *)Vec_PtrEntry( vSuper, Current ); + // if the level of this node is different, quit the loop + if ( Hop_ObjLevel(Hop_Regular(pObjLeft)) != Hop_ObjLevel(Hop_Regular(pObjRight)) ) + break; + } + Current++; + // get the node, for which the equality holds + pObjLeft = (Hop_Obj_t *)Vec_PtrEntry( vSuper, Current ); + assert( Hop_ObjLevel(Hop_Regular(pObjLeft)) == Hop_ObjLevel(Hop_Regular(pObjRight)) ); + return Current; +} + +/**Function************************************************************* + + Synopsis [Moves closer to the end the node that is best for sharing.] + + Description [If there is no node with sharing, randomly chooses one of + the legal nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_NodeBalancePermute( Hop_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ) +{ + Hop_Obj_t * pObj1, * pObj2, * pObj3, * pGhost; + int RightBound, i; + // get the right bound + RightBound = Vec_PtrSize(vSuper) - 2; + assert( LeftBound <= RightBound ); + if ( LeftBound == RightBound ) + return; + // get the two last nodes + pObj1 = (Hop_Obj_t *)Vec_PtrEntry( vSuper, RightBound + 1 ); + pObj2 = (Hop_Obj_t *)Vec_PtrEntry( vSuper, RightBound ); + if ( Hop_Regular(pObj1) == p->pConst1 || Hop_Regular(pObj2) == p->pConst1 ) + return; + // find the first node that can be shared + for ( i = RightBound; i >= LeftBound; i-- ) + { + pObj3 = (Hop_Obj_t *)Vec_PtrEntry( vSuper, i ); + if ( Hop_Regular(pObj3) == p->pConst1 ) + { + Vec_PtrWriteEntry( vSuper, i, pObj2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); + return; + } + pGhost = Hop_ObjCreateGhost( p, pObj1, pObj3, fExor? AIG_EXOR : AIG_AND ); + if ( Hop_TableLookup( p, pGhost ) ) + { + if ( pObj3 == pObj2 ) + return; + Vec_PtrWriteEntry( vSuper, i, pObj2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); + return; + } + } +/* + // we did not find the node to share, randomize choice + { + int Choice = rand() % (RightBound - LeftBound + 1); + pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice ); + if ( pObj3 == pObj2 ) + return; + Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Inserts a new node in the order by levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Hop_Obj_t * pObj ) +{ + Hop_Obj_t * pObj1, * pObj2; + int i; + if ( Vec_PtrPushUnique(vStore, pObj) ) + return; + // find the p of the node + for ( i = vStore->nSize-1; i > 0; i-- ) + { + pObj1 = (Hop_Obj_t *)vStore->pArray[i ]; + pObj2 = (Hop_Obj_t *)vStore->pArray[i-1]; + if ( Hop_ObjLevel(Hop_Regular(pObj1)) <= Hop_ObjLevel(Hop_Regular(pObj2)) ) + break; + vStore->pArray[i ] = pObj2; + vStore->pArray[i-1] = pObj1; + } +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/hop/hopCheck.c b/yosys/abc/src/aig/hop/hopCheck.c new file mode 100644 index 00000000000..174c552389a --- /dev/null +++ b/yosys/abc/src/aig/hop/hopCheck.c @@ -0,0 +1,115 @@ +/**CFile**************************************************************** + + FileName [hopCheck.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [AIG checking procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopCheck.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks the consistency of the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_ManCheck( Hop_Man_t * p ) +{ + Hop_Obj_t * pObj, * pObj2; + int i; + // check primary inputs + Hop_ManForEachPi( p, pObj, i ) + { + if ( Hop_ObjFanin0(pObj) || Hop_ObjFanin1(pObj) ) + { + printf( "Hop_ManCheck: The PI node \"%p\" has fanins.\n", pObj ); + return 0; + } + } + // check primary outputs + Hop_ManForEachPo( p, pObj, i ) + { + if ( !Hop_ObjFanin0(pObj) ) + { + printf( "Hop_ManCheck: The PO node \"%p\" has NULL fanin.\n", pObj ); + return 0; + } + if ( Hop_ObjFanin1(pObj) ) + { + printf( "Hop_ManCheck: The PO node \"%p\" has second fanin.\n", pObj ); + return 0; + } + } + // check internal nodes + Hop_ManForEachNode( p, pObj, i ) + { + if ( !Hop_ObjFanin0(pObj) || !Hop_ObjFanin1(pObj) ) + { + printf( "Hop_ManCheck: The AIG has internal node \"%p\" with a NULL fanin.\n", pObj ); + return 0; + } + if ( Hop_ObjFanin0(pObj)->Id >= Hop_ObjFanin1(pObj)->Id ) + { + printf( "Hop_ManCheck: The AIG has node \"%p\" with a wrong ordering of fanins.\n", pObj ); + return 0; + } + pObj2 = Hop_TableLookup( p, pObj ); + if ( pObj2 != pObj ) + { + printf( "Hop_ManCheck: Node \"%p\" is not in the structural hashing table.\n", pObj ); + return 0; + } + } + // count the total number of nodes + if ( Hop_ManObjNum(p) != 1 + Hop_ManPiNum(p) + Hop_ManPoNum(p) + Hop_ManAndNum(p) + Hop_ManExorNum(p) ) + { + printf( "Hop_ManCheck: The number of created nodes is wrong.\n" ); + return 0; + } + // count the number of nodes in the table + if ( Hop_TableCountEntries(p) != Hop_ManAndNum(p) + Hop_ManExorNum(p) ) + { + printf( "Hop_ManCheck: The number of nodes in the structural hashing table is wrong.\n" ); + return 0; + } +// if ( !Hop_ManIsAcyclic(p) ) +// return 0; + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/hop/hopDfs.c b/yosys/abc/src/aig/hop/hopDfs.c new file mode 100644 index 00000000000..0706382f8f4 --- /dev/null +++ b/yosys/abc/src/aig/hop/hopDfs.c @@ -0,0 +1,591 @@ +/**CFile**************************************************************** + + FileName [hopDfs.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [DFS traversal procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopDfs.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManDfs_rec( Hop_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Hop_ManDfs_rec( Hop_ObjFanin0(pObj), vNodes ); + Hop_ManDfs_rec( Hop_ObjFanin1(pObj), vNodes ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA(pObj); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Hop_ManDfs( Hop_Man_t * p ) +{ + Vec_Ptr_t * vNodes; + Hop_Obj_t * pObj; + int i; + vNodes = Vec_PtrAlloc( Hop_ManNodeNum(p) ); + Hop_ManForEachNode( p, pObj, i ) + Hop_ManDfs_rec( pObj, vNodes ); + Hop_ManForEachNode( p, pObj, i ) + Hop_ObjClearMarkA(pObj); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Collects internal nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Hop_ManDfsNode( Hop_Man_t * p, Hop_Obj_t * pNode ) +{ + Vec_Ptr_t * vNodes; + Hop_Obj_t * pObj; + int i; + assert( !Hop_IsComplement(pNode) ); + vNodes = Vec_PtrAlloc( 16 ); + Hop_ManDfs_rec( pNode, vNodes ); + Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i ) + Hop_ObjClearMarkA(pObj); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Computes the max number of levels in the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_ManCountLevels( Hop_Man_t * p ) +{ + Vec_Ptr_t * vNodes; + Hop_Obj_t * pObj; + int i, LevelsMax, Level0, Level1; + // initialize the levels + Hop_ManConst1(p)->pData = NULL; + Hop_ManForEachPi( p, pObj, i ) + pObj->pData = NULL; + // compute levels in a DFS order + vNodes = Hop_ManDfs( p ); + Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i ) + { + Level0 = (int)(ABC_PTRUINT_T)Hop_ObjFanin0(pObj)->pData; + Level1 = (int)(ABC_PTRUINT_T)Hop_ObjFanin1(pObj)->pData; + pObj->pData = (void *)(ABC_PTRUINT_T)(1 + Hop_ObjIsExor(pObj) + Abc_MaxInt(Level0, Level1)); + } + Vec_PtrFree( vNodes ); + // get levels of the POs + LevelsMax = 0; + Hop_ManForEachPo( p, pObj, i ) + LevelsMax = Abc_MaxInt( LevelsMax, (int)(ABC_PTRUINT_T)Hop_ObjFanin0(pObj)->pData ); + return LevelsMax; +} + +/**Function************************************************************* + + Synopsis [Creates correct reference counters at each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManCreateRefs( Hop_Man_t * p ) +{ + Hop_Obj_t * pObj; + int i; + if ( p->fRefCount ) + return; + p->fRefCount = 1; + // clear refs + Hop_ObjClearRef( Hop_ManConst1(p) ); + Hop_ManForEachPi( p, pObj, i ) + Hop_ObjClearRef( pObj ); + Hop_ManForEachNode( p, pObj, i ) + Hop_ObjClearRef( pObj ); + Hop_ManForEachPo( p, pObj, i ) + Hop_ObjClearRef( pObj ); + // set refs + Hop_ManForEachNode( p, pObj, i ) + { + Hop_ObjRef( Hop_ObjFanin0(pObj) ); + Hop_ObjRef( Hop_ObjFanin1(pObj) ); + } + Hop_ManForEachPo( p, pObj, i ) + Hop_ObjRef( Hop_ObjFanin0(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ConeMark_rec( Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Hop_ConeMark_rec( Hop_ObjFanin0(pObj) ); + Hop_ConeMark_rec( Hop_ObjFanin1(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ConeCleanAndMark_rec( Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Hop_ConeCleanAndMark_rec( Hop_ObjFanin0(pObj) ); + Hop_ConeCleanAndMark_rec( Hop_ObjFanin1(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); + pObj->pData = NULL; +} + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_ConeCountAndMark_rec( Hop_Obj_t * pObj ) +{ + int Counter; + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return 0; + Counter = 1 + Hop_ConeCountAndMark_rec( Hop_ObjFanin0(pObj) ) + + Hop_ConeCountAndMark_rec( Hop_ObjFanin1(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ConeUnmark_rec( Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) ) + return; + Hop_ConeUnmark_rec( Hop_ObjFanin0(pObj) ); + Hop_ConeUnmark_rec( Hop_ObjFanin1(pObj) ); + assert( Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjClearMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Counts the number of AIG nodes rooted at this cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_DagSize( Hop_Obj_t * pObj ) +{ + int Counter; + Counter = Hop_ConeCountAndMark_rec( Hop_Regular(pObj) ); + Hop_ConeUnmark_rec( Hop_Regular(pObj) ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts how many fanout the given node has.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_ObjFanoutCount_rec( Hop_Obj_t * pObj, Hop_Obj_t * pPivot ) +{ + int Counter; + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return (int)(pObj == pPivot); + Counter = Hop_ObjFanoutCount_rec( Hop_ObjFanin0(pObj), pPivot ) + + Hop_ObjFanoutCount_rec( Hop_ObjFanin1(pObj), pPivot ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); + return Counter; +} +int Hop_ObjFanoutCount( Hop_Obj_t * pObj, Hop_Obj_t * pPivot ) +{ + int Counter; + assert( !Hop_IsComplement(pPivot) ); + Counter = Hop_ObjFanoutCount_rec( Hop_Regular(pObj), pPivot ); + Hop_ConeUnmark_rec( Hop_Regular(pObj) ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Transfers the AIG from one manager into another.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_Transfer_rec( Hop_Man_t * pDest, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Hop_Transfer_rec( pDest, Hop_ObjFanin0(pObj) ); + Hop_Transfer_rec( pDest, Hop_ObjFanin1(pObj) ); + pObj->pData = Hop_And( pDest, Hop_ObjChild0Copy(pObj), Hop_ObjChild1Copy(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Transfers the AIG from one manager into another.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Transfer( Hop_Man_t * pSour, Hop_Man_t * pDest, Hop_Obj_t * pRoot, int nVars ) +{ + Hop_Obj_t * pObj; + int i; + // solve simple cases + if ( pSour == pDest ) + return pRoot; + if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) + return Hop_NotCond( Hop_ManConst1(pDest), Hop_IsComplement(pRoot) ); + // set the PI mapping + Hop_ManForEachPi( pSour, pObj, i ) + { + if ( i == nVars ) + break; + pObj->pData = Hop_IthVar(pDest, i); + } + // transfer and set markings + Hop_Transfer_rec( pDest, Hop_Regular(pRoot) ); + // clear the markings + Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); + return Hop_NotCond( (Hop_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); +} + +/**Function************************************************************* + + Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_Compose_rec( Hop_Man_t * p, Hop_Obj_t * pObj, Hop_Obj_t * pFunc, Hop_Obj_t * pVar ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( Hop_ObjIsMarkA(pObj) ) + return; + if ( Hop_ObjIsConst1(pObj) || Hop_ObjIsPi(pObj) ) + { + pObj->pData = pObj == pVar ? pFunc : pObj; + return; + } + Hop_Compose_rec( p, Hop_ObjFanin0(pObj), pFunc, pVar ); + Hop_Compose_rec( p, Hop_ObjFanin1(pObj), pFunc, pVar ); + pObj->pData = Hop_And( p, Hop_ObjChild0Copy(pObj), Hop_ObjChild1Copy(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Composes the AIG (pRoot) with the function (pFunc) using PI var (iVar).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Compose( Hop_Man_t * p, Hop_Obj_t * pRoot, Hop_Obj_t * pFunc, int iVar ) +{ + // quit if the PI variable is not defined + if ( iVar >= Hop_ManPiNum(p) ) + { + printf( "Hop_Compose(): The PI variable %d is not defined.\n", iVar ); + return NULL; + } + // recursively perform composition + Hop_Compose_rec( p, Hop_Regular(pRoot), pFunc, Hop_ManPi(p, iVar) ); + // clear the markings + Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); + return Hop_NotCond( (Hop_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); +} + +/**Function************************************************************* + + Synopsis [Complements the AIG (pRoot) with the function (pFunc) using PI var (iVar).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_Complement_rec( Hop_Man_t * p, Hop_Obj_t * pObj, Hop_Obj_t * pVar ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( Hop_ObjIsMarkA(pObj) ) + return; + if ( Hop_ObjIsConst1(pObj) || Hop_ObjIsPi(pObj) ) + { + pObj->pData = pObj == pVar ? Hop_Not(pObj) : pObj; + return; + } + Hop_Complement_rec( p, Hop_ObjFanin0(pObj), pVar ); + Hop_Complement_rec( p, Hop_ObjFanin1(pObj), pVar ); + pObj->pData = Hop_And( p, Hop_ObjChild0Copy(pObj), Hop_ObjChild1Copy(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Complements the AIG (pRoot) with the function (pFunc) using PI var (iVar).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Complement( Hop_Man_t * p, Hop_Obj_t * pRoot, int iVar ) +{ + // quit if the PI variable is not defined + if ( iVar >= Hop_ManPiNum(p) ) + { + printf( "Hop_Complement(): The PI variable %d is not defined.\n", iVar ); + return NULL; + } + // recursively perform composition + Hop_Complement_rec( p, Hop_Regular(pRoot), Hop_ManPi(p, iVar) ); + // clear the markings + Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); + return Hop_NotCond( (Hop_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); +} + +/**Function************************************************************* + + Synopsis [Remaps the AIG (pRoot) to have the given support (uSupp).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_Remap_rec( Hop_Man_t * p, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Hop_Remap_rec( p, Hop_ObjFanin0(pObj) ); + Hop_Remap_rec( p, Hop_ObjFanin1(pObj) ); + pObj->pData = Hop_And( p, Hop_ObjChild0Copy(pObj), Hop_ObjChild1Copy(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Remaps the AIG (pRoot) to have the given support (uSupp).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Remap( Hop_Man_t * p, Hop_Obj_t * pRoot, unsigned uSupp, int nVars ) +{ + Hop_Obj_t * pObj; + int i, k; + // quit if the PI variable is not defined + if ( nVars > Hop_ManPiNum(p) ) + { + printf( "Hop_Remap(): The number of variables (%d) is more than the manager size (%d).\n", nVars, Hop_ManPiNum(p) ); + return NULL; + } + // return if constant + if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) + return pRoot; + if ( uSupp == 0 ) + return Hop_NotCond( Hop_ManConst0(p), Hop_ObjPhaseCompl(pRoot) ); + // set the PI mapping + k = 0; + Hop_ManForEachPi( p, pObj, i ) + { + if ( i == nVars ) + break; + if ( uSupp & (1 << i) ) + pObj->pData = Hop_IthVar(p, k++); + else + pObj->pData = Hop_ManConst0(p); + } + assert( k > 0 && k < nVars ); + // recursively perform composition + Hop_Remap_rec( p, Hop_Regular(pRoot) ); + // clear the markings + Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); + return Hop_NotCond( (Hop_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); +} + +/**Function************************************************************* + + Synopsis [Permute the AIG according to the given permutation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Permute( Hop_Man_t * p, Hop_Obj_t * pRoot, int nRootVars, int * pPermute ) +{ + Hop_Obj_t * pObj; + int i; + // return if constant + if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) + return pRoot; + // create mapping + Hop_ManForEachPi( p, pObj, i ) + { + if ( i == nRootVars ) + break; + assert( pPermute[i] >= 0 && pPermute[i] < Hop_ManPiNum(p) ); + pObj->pData = Hop_IthVar( p, pPermute[i] ); + } + // recursively perform composition + Hop_Remap_rec( p, Hop_Regular(pRoot) ); + // clear the markings + Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); + return Hop_NotCond( (Hop_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/hop/hopMan.c b/yosys/abc/src/aig/hop/hopMan.c new file mode 100644 index 00000000000..84d987bb7c9 --- /dev/null +++ b/yosys/abc/src/aig/hop/hopMan.c @@ -0,0 +1,169 @@ +/**CFile**************************************************************** + + FileName [hopMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [AIG manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopMan.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Man_t * Hop_ManStart() +{ + Hop_Man_t * p; + // start the manager + p = ABC_ALLOC( Hop_Man_t, 1 ); + memset( p, 0, sizeof(Hop_Man_t) ); + // perform initializations + p->nTravIds = 1; + p->fRefCount = 1; + p->fCatchExor = 0; + // allocate arrays for nodes + p->vPis = Vec_PtrAlloc( 100 ); + p->vPos = Vec_PtrAlloc( 100 ); + // prepare the internal memory manager + Hop_ManStartMemory( p ); + // create the constant node + p->pConst1 = Hop_ManFetchMemory( p ); + p->pConst1->Type = AIG_CONST1; + p->pConst1->fPhase = 1; + p->nCreated = 1; + // start the table +// p->nTableSize = 107; + p->nTableSize = 10007; + p->pTable = ABC_ALLOC( Hop_Obj_t *, p->nTableSize ); + memset( p->pTable, 0, sizeof(Hop_Obj_t *) * p->nTableSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManStop( Hop_Man_t * p ) +{ + Hop_Obj_t * pObj; + int i; + // make sure the nodes have clean marks + pObj = Hop_ManConst1(p); + assert( !pObj->fMarkA && !pObj->fMarkB ); + Hop_ManForEachPi( p, pObj, i ) + assert( !pObj->fMarkA && !pObj->fMarkB ); + Hop_ManForEachPo( p, pObj, i ) + assert( !pObj->fMarkA && !pObj->fMarkB ); + Hop_ManForEachNode( p, pObj, i ) + assert( !pObj->fMarkA && !pObj->fMarkB ); + // print time + if ( p->time1 ) { ABC_PRT( "time1", p->time1 ); } + if ( p->time2 ) { ABC_PRT( "time2", p->time2 ); } +// Hop_TableProfile( p ); + if ( p->vChunks ) Hop_ManStopMemory( p ); + if ( p->vPis ) Vec_PtrFree( p->vPis ); + if ( p->vPos ) Vec_PtrFree( p->vPos ); + if ( p->vObjs ) Vec_PtrFree( p->vObjs ); + ABC_FREE( p->pTable ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Returns the number of dangling nodes removed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_ManCleanup( Hop_Man_t * p ) +{ + Vec_Ptr_t * vObjs; + Hop_Obj_t * pNode; + int i, nNodesOld; + assert( p->fRefCount ); + nNodesOld = Hop_ManNodeNum(p); + // collect roots of dangling nodes + vObjs = Vec_PtrAlloc( 100 ); + Hop_ManForEachNode( p, pNode, i ) + if ( Hop_ObjRefs(pNode) == 0 ) + Vec_PtrPush( vObjs, pNode ); + // recursively remove dangling nodes + Vec_PtrForEachEntry( Hop_Obj_t *, vObjs, pNode, i ) + Hop_ObjDelete_rec( p, pNode ); + Vec_PtrFree( vObjs ); + return nNodesOld - Hop_ManNodeNum(p); +} + +/**Function************************************************************* + + Synopsis [Stops the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManPrintStats( Hop_Man_t * p ) +{ + printf( "PI/PO = %d/%d. ", Hop_ManPiNum(p), Hop_ManPoNum(p) ); + printf( "A = %7d. ", Hop_ManAndNum(p) ); + printf( "X = %5d. ", Hop_ManExorNum(p) ); + printf( "Cre = %7d. ", p->nCreated ); + printf( "Del = %7d. ", p->nDeleted ); + printf( "Lev = %3d. ", Hop_ManCountLevels(p) ); + printf( "\n" ); +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/hop/hopMem.c b/yosys/abc/src/aig/hop/hopMem.c new file mode 100644 index 00000000000..79de38048e7 --- /dev/null +++ b/yosys/abc/src/aig/hop/hopMem.c @@ -0,0 +1,120 @@ +/**CFile**************************************************************** + + FileName [hopMem.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [Memory management for the AIG nodes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopMem.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// memory management +#define IVY_PAGE_SIZE 12 // page size containing 2^IVY_PAGE_SIZE nodes +#define IVY_PAGE_MASK 4095 // page bitmask (2^IVY_PAGE_SIZE)-1 + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the internal memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManStartMemory( Hop_Man_t * p ) +{ + p->vChunks = Vec_PtrAlloc( 128 ); + p->vPages = Vec_PtrAlloc( 128 ); +} + +/**Function************************************************************* + + Synopsis [Stops the internal memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManStopMemory( Hop_Man_t * p ) +{ + void * pMemory; + int i; + Vec_PtrForEachEntry( void *, p->vChunks, pMemory, i ) + ABC_FREE( pMemory ); + Vec_PtrFree( p->vChunks ); + Vec_PtrFree( p->vPages ); + p->pListFree = NULL; +} + +/**Function************************************************************* + + Synopsis [Allocates additional memory for the nodes.] + + Description [Allocates IVY_PAGE_SIZE nodes. Aligns memory by 32 bytes. + Records the pointer to the AIG manager in the -1 entry.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManAddMemory( Hop_Man_t * p ) +{ + char * pMemory; + int i, nBytes; + assert( sizeof(Hop_Obj_t) <= 64 ); + assert( p->pListFree == NULL ); +// assert( (Hop_ManObjNum(p) & IVY_PAGE_MASK) == 0 ); + // allocate new memory page + nBytes = sizeof(Hop_Obj_t) * (1<vChunks, pMemory ); + // align memory at the 32-byte boundary + pMemory = pMemory + 64 - (((int)(ABC_PTRUINT_T)pMemory) & 63); + // remember the manager in the first entry + Vec_PtrPush( p->vPages, pMemory ); + // break the memory down into nodes + p->pListFree = (Hop_Obj_t *)pMemory; + for ( i = 1; i <= IVY_PAGE_MASK; i++ ) + { + *((char **)pMemory) = pMemory + sizeof(Hop_Obj_t); + pMemory += sizeof(Hop_Obj_t); + } + *((char **)pMemory) = NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/hop/hopObj.c b/yosys/abc/src/aig/hop/hopObj.c new file mode 100644 index 00000000000..4451b3faefc --- /dev/null +++ b/yosys/abc/src/aig/hop/hopObj.c @@ -0,0 +1,277 @@ +/**CFile**************************************************************** + + FileName [hopObj.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [Adding/removing objects.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopObj.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates primary input.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_ObjCreatePi( Hop_Man_t * p ) +{ + Hop_Obj_t * pObj; + pObj = Hop_ManFetchMemory( p ); + pObj->Type = AIG_PI; + pObj->PioNum = Vec_PtrSize( p->vPis ); + Vec_PtrPush( p->vPis, pObj ); + p->nObjs[AIG_PI]++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Creates primary output with the given driver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_ObjCreatePo( Hop_Man_t * p, Hop_Obj_t * pDriver ) +{ + Hop_Obj_t * pObj; + pObj = Hop_ManFetchMemory( p ); + pObj->Type = AIG_PO; + Vec_PtrPush( p->vPos, pObj ); + // add connections + pObj->pFanin0 = pDriver; + if ( p->fRefCount ) + Hop_ObjRef( Hop_Regular(pDriver) ); + else + pObj->nRefs = Hop_ObjLevel( Hop_Regular(pDriver) ); + // set the phase + pObj->fPhase = Hop_ObjPhaseCompl(pDriver); + // update node counters of the manager + p->nObjs[AIG_PO]++; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Create the new node assuming it does not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_ObjCreate( Hop_Man_t * p, Hop_Obj_t * pGhost ) +{ + Hop_Obj_t * pObj; + assert( !Hop_IsComplement(pGhost) ); + assert( Hop_ObjIsNode(pGhost) ); + assert( pGhost == &p->Ghost ); + // get memory for the new object + pObj = Hop_ManFetchMemory( p ); + pObj->Type = pGhost->Type; + // add connections + Hop_ObjConnect( p, pObj, pGhost->pFanin0, pGhost->pFanin1 ); + // update node counters of the manager + p->nObjs[Hop_ObjType(pObj)]++; + assert( pObj->pData == NULL ); + return pObj; +} + +/**Function************************************************************* + + Synopsis [Connect the object to the fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjConnect( Hop_Man_t * p, Hop_Obj_t * pObj, Hop_Obj_t * pFan0, Hop_Obj_t * pFan1 ) +{ + assert( !Hop_IsComplement(pObj) ); + assert( Hop_ObjIsNode(pObj) ); + // add the first fanin + pObj->pFanin0 = pFan0; + pObj->pFanin1 = pFan1; + // increment references of the fanins and add their fanouts + if ( p->fRefCount ) + { + if ( pFan0 != NULL ) + Hop_ObjRef( Hop_ObjFanin0(pObj) ); + if ( pFan1 != NULL ) + Hop_ObjRef( Hop_ObjFanin1(pObj) ); + } + else + pObj->nRefs = Hop_ObjLevelNew( pObj ); + // set the phase + pObj->fPhase = Hop_ObjPhaseCompl(pFan0) & Hop_ObjPhaseCompl(pFan1); + // add the node to the structural hash table + Hop_TableInsert( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Connect the object to the fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjDisconnect( Hop_Man_t * p, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + assert( Hop_ObjIsNode(pObj) ); + // remove connections + if ( pObj->pFanin0 != NULL ) + Hop_ObjDeref(Hop_ObjFanin0(pObj)); + if ( pObj->pFanin1 != NULL ) + Hop_ObjDeref(Hop_ObjFanin1(pObj)); + // remove the node from the structural hash table + Hop_TableDelete( p, pObj ); + // add the first fanin + pObj->pFanin0 = NULL; + pObj->pFanin1 = NULL; +} + +/**Function************************************************************* + + Synopsis [Deletes the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjDelete( Hop_Man_t * p, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + assert( !Hop_ObjIsTerm(pObj) ); + assert( Hop_ObjRefs(pObj) == 0 ); + // update node counters of the manager + p->nObjs[pObj->Type]--; + p->nDeleted++; + // remove connections + Hop_ObjDisconnect( p, pObj ); + // remove PIs/POs from the arrays + if ( Hop_ObjIsPi(pObj) ) + Vec_PtrRemove( p->vPis, pObj ); + // free the node + Hop_ManRecycleMemory( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Deletes the MFFC of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjDelete_rec( Hop_Man_t * p, Hop_Obj_t * pObj ) +{ + Hop_Obj_t * pFanin0, * pFanin1; + assert( !Hop_IsComplement(pObj) ); + if ( Hop_ObjIsConst1(pObj) || Hop_ObjIsPi(pObj) ) + return; + assert( Hop_ObjIsNode(pObj) ); + pFanin0 = Hop_ObjFanin0(pObj); + pFanin1 = Hop_ObjFanin1(pObj); + Hop_ObjDelete( p, pObj ); + if ( pFanin0 && !Hop_ObjIsNone(pFanin0) && Hop_ObjRefs(pFanin0) == 0 ) + Hop_ObjDelete_rec( p, pFanin0 ); + if ( pFanin1 && !Hop_ObjIsNone(pFanin1) && Hop_ObjRefs(pFanin1) == 0 ) + Hop_ObjDelete_rec( p, pFanin1 ); +} + +/**Function************************************************************* + + Synopsis [Returns the representative of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_ObjRepr( Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( pObj->pData == NULL || pObj->pData == pObj ) + return pObj; + return Hop_ObjRepr( (Hop_Obj_t *)pObj->pData ); +} + +/**Function************************************************************* + + Synopsis [Sets an equivalence relation between the nodes.] + + Description [Makes the representative of pNew point to the representaive of pOld.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjCreateChoice( Hop_Obj_t * pOld, Hop_Obj_t * pNew ) +{ + Hop_Obj_t * pOldRepr; + Hop_Obj_t * pNewRepr; + assert( pOld != NULL && pNew != NULL ); + pOldRepr = Hop_ObjRepr(pOld); + pNewRepr = Hop_ObjRepr(pNew); + if ( pNewRepr != pOldRepr ) + pNewRepr->pData = pOldRepr; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/hop/hopOper.c b/yosys/abc/src/aig/hop/hopOper.c new file mode 100644 index 00000000000..2f5e765064e --- /dev/null +++ b/yosys/abc/src/aig/hop/hopOper.c @@ -0,0 +1,378 @@ +/**CFile**************************************************************** + + FileName [hopOper.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [AIG operations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopOper.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// procedure to detect an EXOR gate +static inline int Hop_ObjIsExorType( Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Obj_t ** ppFan0, Hop_Obj_t ** ppFan1 ) +{ + if ( !Hop_IsComplement(p0) || !Hop_IsComplement(p1) ) + return 0; + p0 = Hop_Regular(p0); + p1 = Hop_Regular(p1); + if ( !Hop_ObjIsAnd(p0) || !Hop_ObjIsAnd(p1) ) + return 0; + if ( Hop_ObjFanin0(p0) != Hop_ObjFanin0(p1) || Hop_ObjFanin1(p0) != Hop_ObjFanin1(p1) ) + return 0; + if ( Hop_ObjFaninC0(p0) == Hop_ObjFaninC0(p1) || Hop_ObjFaninC1(p0) == Hop_ObjFaninC1(p1) ) + return 0; + *ppFan0 = Hop_ObjChild0(p0); + *ppFan1 = Hop_ObjChild1(p0); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns i-th elementary variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_IthVar( Hop_Man_t * p, int i ) +{ + int v; + for ( v = Hop_ManPiNum(p); v <= i; v++ ) + Hop_ObjCreatePi( p ); + assert( i < Vec_PtrSize(p->vPis) ); + return Hop_ManPi( p, i ); +} + +/**Function************************************************************* + + Synopsis [Perform one operation.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Oper( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1, Hop_Type_t Type ) +{ + if ( Type == AIG_AND ) + return Hop_And( p, p0, p1 ); + if ( Type == AIG_EXOR ) + return Hop_Exor( p, p0, p1 ); + assert( 0 ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_And( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ) +{ + Hop_Obj_t * pGhost, * pResult; +// Hop_Obj_t * pFan0, * pFan1; + // check trivial cases + if ( p0 == p1 ) + return p0; + if ( p0 == Hop_Not(p1) ) + return Hop_Not(p->pConst1); + if ( Hop_Regular(p0) == p->pConst1 ) + return p0 == p->pConst1 ? p1 : Hop_Not(p->pConst1); + if ( Hop_Regular(p1) == p->pConst1 ) + return p1 == p->pConst1 ? p0 : Hop_Not(p->pConst1); + // check if it can be an EXOR gate +// if ( Hop_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) ) +// return Hop_Exor( p, pFan0, pFan1 ); + // check the table + pGhost = Hop_ObjCreateGhost( p, p0, p1, AIG_AND ); + if ( (pResult = Hop_TableLookup( p, pGhost )) ) + return pResult; + return Hop_ObjCreate( p, pGhost ); +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Exor( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ) +{ +/* + Hop_Obj_t * pGhost, * pResult; + // check trivial cases + if ( p0 == p1 ) + return Hop_Not(p->pConst1); + if ( p0 == Hop_Not(p1) ) + return p->pConst1; + if ( Hop_Regular(p0) == p->pConst1 ) + return Hop_NotCond( p1, p0 == p->pConst1 ); + if ( Hop_Regular(p1) == p->pConst1 ) + return Hop_NotCond( p0, p1 == p->pConst1 ); + // check the table + pGhost = Hop_ObjCreateGhost( p, p0, p1, AIG_EXOR ); + if ( pResult = Hop_TableLookup( p, pGhost ) ) + return pResult; + return Hop_ObjCreate( p, pGhost ); +*/ + return Hop_Or( p, Hop_And(p, p0, Hop_Not(p1)), Hop_And(p, Hop_Not(p0), p1) ); +} + +/**Function************************************************************* + + Synopsis [Implements Boolean OR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Or( Hop_Man_t * p, Hop_Obj_t * p0, Hop_Obj_t * p1 ) +{ + return Hop_Not( Hop_And( p, Hop_Not(p0), Hop_Not(p1) ) ); +} + +/**Function************************************************************* + + Synopsis [Implements ITE operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Mux( Hop_Man_t * p, Hop_Obj_t * pC, Hop_Obj_t * p1, Hop_Obj_t * p0 ) +{ +/* + Hop_Obj_t * pTempA1, * pTempA2, * pTempB1, * pTempB2, * pTemp; + int Count0, Count1; + // consider trivial cases + if ( p0 == Hop_Not(p1) ) + return Hop_Exor( p, pC, p0 ); + // other cases can be added + // implement the first MUX (F = C * x1 + C' * x0) + + // check for constants here!!! + + pTempA1 = Hop_TableLookup( p, Hop_ObjCreateGhost(p, pC, p1, AIG_AND) ); + pTempA2 = Hop_TableLookup( p, Hop_ObjCreateGhost(p, Hop_Not(pC), p0, AIG_AND) ); + if ( pTempA1 && pTempA2 ) + { + pTemp = Hop_TableLookup( p, Hop_ObjCreateGhost(p, Hop_Not(pTempA1), Hop_Not(pTempA2), AIG_AND) ); + if ( pTemp ) return Hop_Not(pTemp); + } + Count0 = (pTempA1 != NULL) + (pTempA2 != NULL); + // implement the second MUX (F' = C * x1' + C' * x0') + pTempB1 = Hop_TableLookup( p, Hop_ObjCreateGhost(p, pC, Hop_Not(p1), AIG_AND) ); + pTempB2 = Hop_TableLookup( p, Hop_ObjCreateGhost(p, Hop_Not(pC), Hop_Not(p0), AIG_AND) ); + if ( pTempB1 && pTempB2 ) + { + pTemp = Hop_TableLookup( p, Hop_ObjCreateGhost(p, Hop_Not(pTempB1), Hop_Not(pTempB2), AIG_AND) ); + if ( pTemp ) return pTemp; + } + Count1 = (pTempB1 != NULL) + (pTempB2 != NULL); + // compare and decide which one to implement + if ( Count0 >= Count1 ) + { + pTempA1 = pTempA1? pTempA1 : Hop_And(p, pC, p1); + pTempA2 = pTempA2? pTempA2 : Hop_And(p, Hop_Not(pC), p0); + return Hop_Or( p, pTempA1, pTempA2 ); + } + pTempB1 = pTempB1? pTempB1 : Hop_And(p, pC, Hop_Not(p1)); + pTempB2 = pTempB2? pTempB2 : Hop_And(p, Hop_Not(pC), Hop_Not(p0)); + return Hop_Not( Hop_Or( p, pTempB1, pTempB2 ) ); +*/ + return Hop_Or( p, Hop_And(p, pC, p1), Hop_And(p, Hop_Not(pC), p0) ); +} + +/**Function************************************************************* + + Synopsis [Implements ITE operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Maj( Hop_Man_t * p, Hop_Obj_t * pA, Hop_Obj_t * pB, Hop_Obj_t * pC ) +{ + return Hop_Or( p, Hop_Or(p, Hop_And(p, pA, pB), Hop_And(p, pA, pC)), Hop_And(p, pB, pC) ); +} + +/**Function************************************************************* + + Synopsis [Constructs the well-balanced tree of gates.] + + Description [Disregards levels and possible logic sharing.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Multi_rec( Hop_Man_t * p, Hop_Obj_t ** ppObjs, int nObjs, Hop_Type_t Type ) +{ + Hop_Obj_t * pObj1, * pObj2; + if ( nObjs == 1 ) + return ppObjs[0]; + pObj1 = Hop_Multi_rec( p, ppObjs, nObjs/2, Type ); + pObj2 = Hop_Multi_rec( p, ppObjs + nObjs/2, nObjs - nObjs/2, Type ); + return Hop_Oper( p, pObj1, pObj2, Type ); +} + +/**Function************************************************************* + + Synopsis [Old code.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Multi( Hop_Man_t * p, Hop_Obj_t ** pArgs, int nArgs, Hop_Type_t Type ) +{ + assert( Type == AIG_AND || Type == AIG_EXOR ); + assert( nArgs > 0 ); + return Hop_Multi_rec( p, pArgs, nArgs, Type ); +} + +/**Function************************************************************* + + Synopsis [Implements the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_Miter( Hop_Man_t * p, Vec_Ptr_t * vPairs ) +{ + int i; + assert( vPairs->nSize > 0 ); + assert( vPairs->nSize % 2 == 0 ); + // go through the cubes of the node's SOP + for ( i = 0; i < vPairs->nSize; i += 2 ) + vPairs->pArray[i/2] = Hop_Not( Hop_Exor( p, (Hop_Obj_t *)vPairs->pArray[i], (Hop_Obj_t *)vPairs->pArray[i+1] ) ); + vPairs->nSize = vPairs->nSize/2; + return Hop_Not( Hop_Multi_rec( p, (Hop_Obj_t **)vPairs->pArray, vPairs->nSize, AIG_AND ) ); +} + +/**Function************************************************************* + + Synopsis [Creates AND function with nVars inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_CreateAnd( Hop_Man_t * p, int nVars ) +{ + Hop_Obj_t * pFunc; + int i; + pFunc = Hop_ManConst1( p ); + for ( i = 0; i < nVars; i++ ) + pFunc = Hop_And( p, pFunc, Hop_IthVar(p, i) ); + return pFunc; +} + +/**Function************************************************************* + + Synopsis [Creates AND function with nVars inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_CreateOr( Hop_Man_t * p, int nVars ) +{ + Hop_Obj_t * pFunc; + int i; + pFunc = Hop_ManConst0( p ); + for ( i = 0; i < nVars; i++ ) + pFunc = Hop_Or( p, pFunc, Hop_IthVar(p, i) ); + return pFunc; +} + +/**Function************************************************************* + + Synopsis [Creates AND function with nVars inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_CreateExor( Hop_Man_t * p, int nVars ) +{ + Hop_Obj_t * pFunc; + int i; + pFunc = Hop_ManConst0( p ); + for ( i = 0; i < nVars; i++ ) + pFunc = Hop_Exor( p, pFunc, Hop_IthVar(p, i) ); + return pFunc; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/hop/hopTable.c b/yosys/abc/src/aig/hop/hopTable.c new file mode 100644 index 00000000000..14e876993a3 --- /dev/null +++ b/yosys/abc/src/aig/hop/hopTable.c @@ -0,0 +1,232 @@ +/**CFile**************************************************************** + + FileName [hopTable.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [Structural hashing table.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006. ] + + Revision [$Id: hopTable.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// hashing the node +static unsigned long Hop_Hash( Hop_Obj_t * pObj, int TableSize ) +{ + unsigned long Key = Hop_ObjIsExor(pObj) * 1699; + Key ^= Hop_ObjFanin0(pObj)->Id * 7937; + Key ^= Hop_ObjFanin1(pObj)->Id * 2971; + Key ^= Hop_ObjFaninC0(pObj) * 911; + Key ^= Hop_ObjFaninC1(pObj) * 353; + return Key % TableSize; +} + +// returns the place where this node is stored (or should be stored) +static Hop_Obj_t ** Hop_TableFind( Hop_Man_t * p, Hop_Obj_t * pObj ) +{ + Hop_Obj_t ** ppEntry; + assert( Hop_ObjChild0(pObj) && Hop_ObjChild1(pObj) ); + assert( Hop_ObjFanin0(pObj)->Id < Hop_ObjFanin1(pObj)->Id ); + for ( ppEntry = p->pTable + Hop_Hash(pObj, p->nTableSize); *ppEntry; ppEntry = &(*ppEntry)->pNext ) + if ( *ppEntry == pObj ) + return ppEntry; + assert( *ppEntry == NULL ); + return ppEntry; +} + +static void Hop_TableResize( Hop_Man_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks if a node with the given attributes is in the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_TableLookup( Hop_Man_t * p, Hop_Obj_t * pGhost ) +{ + Hop_Obj_t * pEntry; + assert( !Hop_IsComplement(pGhost) ); + assert( Hop_ObjChild0(pGhost) && Hop_ObjChild1(pGhost) ); + assert( Hop_ObjFanin0(pGhost)->Id < Hop_ObjFanin1(pGhost)->Id ); + if ( p->fRefCount && (!Hop_ObjRefs(Hop_ObjFanin0(pGhost)) || !Hop_ObjRefs(Hop_ObjFanin1(pGhost))) ) + return NULL; + for ( pEntry = p->pTable[Hop_Hash(pGhost, p->nTableSize)]; pEntry; pEntry = pEntry->pNext ) + { + if ( Hop_ObjChild0(pEntry) == Hop_ObjChild0(pGhost) && + Hop_ObjChild1(pEntry) == Hop_ObjChild1(pGhost) && + Hop_ObjType(pEntry) == Hop_ObjType(pGhost) ) + return pEntry; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Adds the new node to the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_TableInsert( Hop_Man_t * p, Hop_Obj_t * pObj ) +{ + Hop_Obj_t ** ppPlace; + assert( !Hop_IsComplement(pObj) ); + assert( Hop_TableLookup(p, pObj) == NULL ); + if ( (pObj->Id & 0xFF) == 0 && 2 * p->nTableSize < Hop_ManNodeNum(p) ) + Hop_TableResize( p ); + ppPlace = Hop_TableFind( p, pObj ); + assert( *ppPlace == NULL ); + *ppPlace = pObj; +} + +/**Function************************************************************* + + Synopsis [Deletes the node from the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_TableDelete( Hop_Man_t * p, Hop_Obj_t * pObj ) +{ + Hop_Obj_t ** ppPlace; + assert( !Hop_IsComplement(pObj) ); + ppPlace = Hop_TableFind( p, pObj ); + assert( *ppPlace == pObj ); // node should be in the table + // remove the node + *ppPlace = pObj->pNext; + pObj->pNext = NULL; +} + +/**Function************************************************************* + + Synopsis [Count the number of nodes in the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_TableCountEntries( Hop_Man_t * p ) +{ + Hop_Obj_t * pEntry; + int i, Counter = 0; + for ( i = 0; i < p->nTableSize; i++ ) + for ( pEntry = p->pTable[i]; pEntry; pEntry = pEntry->pNext ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Resizes the table.] + + Description [Typically this procedure should not be called.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_TableResize( Hop_Man_t * p ) +{ + Hop_Obj_t * pEntry, * pNext; + Hop_Obj_t ** pTableOld, ** ppPlace; + int nTableSizeOld, Counter, nEntries, i; + abctime clk; +clk = Abc_Clock(); + // save the old table + pTableOld = p->pTable; + nTableSizeOld = p->nTableSize; + // get the new table + p->nTableSize = Abc_PrimeCudd( 2 * Hop_ManNodeNum(p) ); + p->pTable = ABC_ALLOC( Hop_Obj_t *, p->nTableSize ); + memset( p->pTable, 0, sizeof(Hop_Obj_t *) * p->nTableSize ); + // rehash the entries from the old table + Counter = 0; + for ( i = 0; i < nTableSizeOld; i++ ) + for ( pEntry = pTableOld[i], pNext = pEntry? pEntry->pNext : NULL; pEntry; pEntry = pNext, pNext = pEntry? pEntry->pNext : NULL ) + { + // get the place where this entry goes in the table + ppPlace = Hop_TableFind( p, pEntry ); + assert( *ppPlace == NULL ); // should not be there + // add the entry to the list + *ppPlace = pEntry; + pEntry->pNext = NULL; + Counter++; + } + nEntries = Hop_ManNodeNum(p); + assert( Counter == nEntries ); +// printf( "Increasing the structural table size from %6d to %6d. ", nTableSizeOld, p->nTableSize ); +// ABC_PRT( "Time", Abc_Clock() - clk ); + // replace the table and the parameters + ABC_FREE( pTableOld ); +} + +/**Function******************************************************************** + + Synopsis [Profiles the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Hop_TableProfile( Hop_Man_t * p ) +{ + Hop_Obj_t * pEntry; + int i, Counter; + for ( i = 0; i < p->nTableSize; i++ ) + { + Counter = 0; + for ( pEntry = p->pTable[i]; pEntry; pEntry = pEntry->pNext ) + Counter++; + if ( Counter ) + printf( "%d ", Counter ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/hop/hopTruth.c b/yosys/abc/src/aig/hop/hopTruth.c new file mode 100644 index 00000000000..bbb0e052199 --- /dev/null +++ b/yosys/abc/src/aig/hop/hopTruth.c @@ -0,0 +1,274 @@ +/**CFile**************************************************************** + + FileName [hopTruth.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopTruth.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Hop_ManTruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } + +static inline void Hop_ManTruthCopy( unsigned * pOut, unsigned * pIn, int nVars ) +{ + int w; + for ( w = Hop_ManTruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = pIn[w]; +} +static inline void Hop_ManTruthClear( unsigned * pOut, int nVars ) +{ + int w; + for ( w = Hop_ManTruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = 0; +} +static inline void Hop_ManTruthFill( unsigned * pOut, int nVars ) +{ + int w; + for ( w = Hop_ManTruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = ~(unsigned)0; +} +static inline void Hop_ManTruthNot( unsigned * pOut, unsigned * pIn, int nVars ) +{ + int w; + for ( w = Hop_ManTruthWordNum(nVars)-1; w >= 0; w-- ) + pOut[w] = ~pIn[w]; +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +/**Function************************************************************* + + Synopsis [Construct BDDs and mark AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_ManConvertAigToTruth_rec1( Hop_Obj_t * pObj ) +{ + int Counter = 0; + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return 0; + Counter += Hop_ManConvertAigToTruth_rec1( Hop_ObjFanin0(pObj) ); + Counter += Hop_ManConvertAigToTruth_rec1( Hop_ObjFanin1(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); + return Counter + 1; +} + +/**Function************************************************************* + + Synopsis [Computes truth table of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Hop_ManConvertAigToTruth_rec2( Hop_Obj_t * pObj, Vec_Int_t * vTruth, int nWords ) +{ + unsigned * pTruth, * pTruth0, * pTruth1; + int i; + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) ) + return (unsigned *)pObj->pData; + // compute the truth tables of the fanins + pTruth0 = Hop_ManConvertAigToTruth_rec2( Hop_ObjFanin0(pObj), vTruth, nWords ); + pTruth1 = Hop_ManConvertAigToTruth_rec2( Hop_ObjFanin1(pObj), vTruth, nWords ); + // creat the truth table of the node + pTruth = Vec_IntFetch( vTruth, nWords ); + if ( Hop_ObjIsExor(pObj) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] ^ pTruth1[i]; + else if ( !Hop_ObjFaninC0(pObj) && !Hop_ObjFaninC1(pObj) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] & pTruth1[i]; + else if ( !Hop_ObjFaninC0(pObj) && Hop_ObjFaninC1(pObj) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] & ~pTruth1[i]; + else if ( Hop_ObjFaninC0(pObj) && !Hop_ObjFaninC1(pObj) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ~pTruth0[i] & pTruth1[i]; + else // if ( Hop_ObjFaninC0(pObj) && Hop_ObjFaninC1(pObj) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ~pTruth0[i] & ~pTruth1[i]; + assert( Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjClearMarkA( pObj ); + pObj->pData = pTruth; + return pTruth; +} + +/**Function************************************************************* + + Synopsis [Computes truth table of the node.] + + Description [Assumes that the structural support is no more than 8 inputs. + Uses array vTruth to store temporary truth tables. The returned pointer should + be used immediately.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Hop_ManConvertAigToTruth( Hop_Man_t * p, Hop_Obj_t * pRoot, int nVars, Vec_Int_t * vTruth, int fMsbFirst ) +{ + static unsigned uTruths[8][8] = { // elementary truth tables + { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA }, + { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC }, + { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 }, + { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 }, + { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, + { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, + { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, + { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } + }; + Hop_Obj_t * pObj; + unsigned * pTruth, * pTruth2; + int i, nWords, nNodes; + Vec_Ptr_t * vTtElems; + + // if the number of variables is more than 8, allocate truth tables + if ( nVars > 8 ) + vTtElems = Vec_PtrAllocTruthTables( nVars ); + else + vTtElems = NULL; + + // clear the data fields and set marks + nNodes = Hop_ManConvertAigToTruth_rec1( Hop_Regular(pRoot) ); + // prepare memory + nWords = Hop_TruthWordNum( nVars ); + Vec_IntClear( vTruth ); + Vec_IntGrow( vTruth, nWords * (nNodes+1) ); + pTruth = Vec_IntFetch( vTruth, nWords ); + // check the case of a constant + if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) + { + assert( nNodes == 0 ); + if ( Hop_IsComplement(pRoot) ) + Hop_ManTruthClear( pTruth, nVars ); + else + Hop_ManTruthFill( pTruth, nVars ); + return pTruth; + } + // set elementary truth tables at the leaves + assert( nVars <= Hop_ManPiNum(p) ); +// assert( Hop_ManPiNum(p) <= 8 ); + if ( fMsbFirst ) + { +// Hop_ManForEachPi( p, pObj, i ) + for ( i = 0; i < nVars; i++ ) + { + pObj = Hop_ManPi( p, i ); + if ( vTtElems ) + pObj->pData = Vec_PtrEntry(vTtElems, nVars-1-i); + else + pObj->pData = (void *)uTruths[nVars-1-i]; + } + } + else + { +// Hop_ManForEachPi( p, pObj, i ) + for ( i = 0; i < nVars; i++ ) + { + pObj = Hop_ManPi( p, i ); + if ( vTtElems ) + pObj->pData = Vec_PtrEntry(vTtElems, i); + else + pObj->pData = (void *)uTruths[i]; + } + } + // clear the marks and compute the truth table + pTruth2 = Hop_ManConvertAigToTruth_rec2( Hop_Regular(pRoot), vTruth, nWords ); + // copy the result + Hop_ManTruthCopy( pTruth, pTruth2, nVars ); + if ( Hop_IsComplement(pRoot) ) + Hop_ManTruthNot( pTruth, pTruth, nVars ); + if ( vTtElems ) + Vec_PtrFree( vTtElems ); + return pTruth; +} + + +/**Function************************************************************* + + Synopsis [Compute truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static word Truth[8] = +{ + ABC_CONST(0xAAAAAAAAAAAAAAAA), + ABC_CONST(0xCCCCCCCCCCCCCCCC), + ABC_CONST(0xF0F0F0F0F0F0F0F0), + ABC_CONST(0xFF00FF00FF00FF00), + ABC_CONST(0xFFFF0000FFFF0000), + ABC_CONST(0xFFFFFFFF00000000), + ABC_CONST(0x0000000000000000), + ABC_CONST(0xFFFFFFFFFFFFFFFF) +}; +word Hop_ManComputeTruth6_rec( Hop_Man_t * p, Hop_Obj_t * pObj ) +{ + word Truth0, Truth1; + if ( Hop_ObjIsPi(pObj) ) + return Truth[pObj->iData]; + assert( Hop_ObjIsNode(pObj) ); + Truth0 = Hop_ManComputeTruth6_rec( p, Hop_ObjFanin0(pObj) ); + Truth1 = Hop_ManComputeTruth6_rec( p, Hop_ObjFanin1(pObj) ); + Truth0 = Hop_ObjFaninC0(pObj) ? ~Truth0 : Truth0; + Truth1 = Hop_ObjFaninC1(pObj) ? ~Truth1 : Truth1; + return Truth0 & Truth1; +} +word Hop_ManComputeTruth6( Hop_Man_t * p, Hop_Obj_t * pObj, int nVars ) +{ + word Truth; + int i; + if ( Hop_ObjIsConst1( Hop_Regular(pObj) ) ) + return Hop_IsComplement(pObj) ? 0 : ~(word)0; + for ( i = 0; i < nVars; i++ ) + Hop_ManPi( p, i )->iData = i; + Truth = Hop_ManComputeTruth6_rec( p, Hop_Regular(pObj) ); + return Hop_IsComplement(pObj) ? ~Truth : Truth; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/hop/hopUtil.c b/yosys/abc/src/aig/hop/hopUtil.c new file mode 100644 index 00000000000..02cb08e3aab --- /dev/null +++ b/yosys/abc/src/aig/hop/hopUtil.c @@ -0,0 +1,578 @@ +/**CFile**************************************************************** + + FileName [hopUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Various procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hopUtil.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Increments the current traversal ID of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManIncrementTravId( Hop_Man_t * p ) +{ + if ( p->nTravIds >= (1<<30)-1 ) + Hop_ManCleanData( p ); + p->nTravIds++; +} + +/**Function************************************************************* + + Synopsis [Cleans the data pointers for the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManCleanData( Hop_Man_t * p ) +{ + Hop_Obj_t * pObj; + int i; + p->nTravIds = 1; + Hop_ManConst1(p)->pData = NULL; + Hop_ManForEachPi( p, pObj, i ) + pObj->pData = NULL; + Hop_ManForEachPo( p, pObj, i ) + pObj->pData = NULL; + Hop_ManForEachNode( p, pObj, i ) + pObj->pData = NULL; +} + +/**Function************************************************************* + + Synopsis [Recursively cleans the data pointers in the cone of the node.] + + Description [Applicable to small AIGs only because no caching is performed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjCleanData_rec( Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + assert( !Hop_ObjIsPo(pObj) ); + if ( Hop_ObjIsAnd(pObj) ) + { + Hop_ObjCleanData_rec( Hop_ObjFanin0(pObj) ); + Hop_ObjCleanData_rec( Hop_ObjFanin1(pObj) ); + } + pObj->pData = NULL; +} + +/**Function************************************************************* + + Synopsis [Detects multi-input gate rooted at this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjCollectMulti_rec( Hop_Obj_t * pRoot, Hop_Obj_t * pObj, Vec_Ptr_t * vSuper ) +{ + if ( pRoot != pObj && (Hop_IsComplement(pObj) || Hop_ObjIsPi(pObj) || Hop_ObjType(pRoot) != Hop_ObjType(pObj)) ) + { + Vec_PtrPushUnique(vSuper, pObj); + return; + } + Hop_ObjCollectMulti_rec( pRoot, Hop_ObjChild0(pObj), vSuper ); + Hop_ObjCollectMulti_rec( pRoot, Hop_ObjChild1(pObj), vSuper ); +} + +/**Function************************************************************* + + Synopsis [Detects multi-input gate rooted at this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjCollectMulti( Hop_Obj_t * pRoot, Vec_Ptr_t * vSuper ) +{ + assert( !Hop_IsComplement(pRoot) ); + Vec_PtrClear( vSuper ); + Hop_ObjCollectMulti_rec( pRoot, pRoot, vSuper ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_ObjIsMuxType( Hop_Obj_t * pNode ) +{ + Hop_Obj_t * pNode0, * pNode1; + // check that the node is regular + assert( !Hop_IsComplement(pNode) ); + // if the node is not AND, this is not MUX + if ( !Hop_ObjIsAnd(pNode) ) + return 0; + // if the children are not complemented, this is not MUX + if ( !Hop_ObjFaninC0(pNode) || !Hop_ObjFaninC1(pNode) ) + return 0; + // get children + pNode0 = Hop_ObjFanin0(pNode); + pNode1 = Hop_ObjFanin1(pNode); + // if the children are not ANDs, this is not MUX + if ( !Hop_ObjIsAnd(pNode0) || !Hop_ObjIsAnd(pNode1) ) + return 0; + // otherwise the node is MUX iff it has a pair of equal grandchildren + return (Hop_ObjFanin0(pNode0) == Hop_ObjFanin0(pNode1) && (Hop_ObjFaninC0(pNode0) ^ Hop_ObjFaninC0(pNode1))) || + (Hop_ObjFanin0(pNode0) == Hop_ObjFanin1(pNode1) && (Hop_ObjFaninC0(pNode0) ^ Hop_ObjFaninC1(pNode1))) || + (Hop_ObjFanin1(pNode0) == Hop_ObjFanin0(pNode1) && (Hop_ObjFaninC1(pNode0) ^ Hop_ObjFaninC0(pNode1))) || + (Hop_ObjFanin1(pNode0) == Hop_ObjFanin1(pNode1) && (Hop_ObjFaninC1(pNode0) ^ Hop_ObjFaninC1(pNode1))); +} + + +/**Function************************************************************* + + Synopsis [Recognizes what nodes are inputs of the EXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Hop_ObjRecognizeExor( Hop_Obj_t * pObj, Hop_Obj_t ** ppFan0, Hop_Obj_t ** ppFan1 ) +{ + Hop_Obj_t * p0, * p1; + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) ) + return 0; + if ( Hop_ObjIsExor(pObj) ) + { + *ppFan0 = Hop_ObjChild0(pObj); + *ppFan1 = Hop_ObjChild1(pObj); + return 1; + } + assert( Hop_ObjIsAnd(pObj) ); + p0 = Hop_ObjChild0(pObj); + p1 = Hop_ObjChild1(pObj); + if ( !Hop_IsComplement(p0) || !Hop_IsComplement(p1) ) + return 0; + p0 = Hop_Regular(p0); + p1 = Hop_Regular(p1); + if ( !Hop_ObjIsAnd(p0) || !Hop_ObjIsAnd(p1) ) + return 0; + if ( Hop_ObjFanin0(p0) != Hop_ObjFanin0(p1) || Hop_ObjFanin1(p0) != Hop_ObjFanin1(p1) ) + return 0; + if ( Hop_ObjFaninC0(p0) == Hop_ObjFaninC0(p1) || Hop_ObjFaninC1(p0) == Hop_ObjFaninC1(p1) ) + return 0; + *ppFan0 = Hop_ObjChild0(p0); + *ppFan1 = Hop_ObjChild1(p0); + return 1; +} + +/**Function************************************************************* + + Synopsis [Recognizes what nodes are control and data inputs of a MUX.] + + Description [If the node is a MUX, returns the control variable C. + Assigns nodes T and E to be the then and else variables of the MUX. + Node C is never complemented. Nodes T and E can be complemented. + This function also recognizes EXOR/NEXOR gates as MUXes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Hop_ObjRecognizeMux( Hop_Obj_t * pNode, Hop_Obj_t ** ppNodeT, Hop_Obj_t ** ppNodeE ) +{ + Hop_Obj_t * pNode0, * pNode1; + assert( !Hop_IsComplement(pNode) ); + assert( Hop_ObjIsMuxType(pNode) ); + // get children + pNode0 = Hop_ObjFanin0(pNode); + pNode1 = Hop_ObjFanin1(pNode); + + // find the control variable + if ( Hop_ObjFanin1(pNode0) == Hop_ObjFanin1(pNode1) && (Hop_ObjFaninC1(pNode0) ^ Hop_ObjFaninC1(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p2) ) + if ( Hop_ObjFaninC1(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Hop_Not(Hop_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Hop_Not(Hop_ObjChild0(pNode0));//pNode1->p1); + return Hop_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Hop_Not(Hop_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Hop_Not(Hop_ObjChild0(pNode1));//pNode2->p1); + return Hop_ObjChild1(pNode0);//pNode1->p2; + } + } + else if ( Hop_ObjFanin0(pNode0) == Hop_ObjFanin0(pNode1) && (Hop_ObjFaninC0(pNode0) ^ Hop_ObjFaninC0(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p1) ) + if ( Hop_ObjFaninC0(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Hop_Not(Hop_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Hop_Not(Hop_ObjChild1(pNode0));//pNode1->p2); + return Hop_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Hop_Not(Hop_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Hop_Not(Hop_ObjChild1(pNode1));//pNode2->p2); + return Hop_ObjChild0(pNode0);//pNode1->p1; + } + } + else if ( Hop_ObjFanin0(pNode0) == Hop_ObjFanin1(pNode1) && (Hop_ObjFaninC0(pNode0) ^ Hop_ObjFaninC1(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p1) ) + if ( Hop_ObjFaninC0(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Hop_Not(Hop_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Hop_Not(Hop_ObjChild1(pNode0));//pNode1->p2); + return Hop_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Hop_Not(Hop_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Hop_Not(Hop_ObjChild0(pNode1));//pNode2->p1); + return Hop_ObjChild0(pNode0);//pNode1->p1; + } + } + else if ( Hop_ObjFanin1(pNode0) == Hop_ObjFanin0(pNode1) && (Hop_ObjFaninC1(pNode0) ^ Hop_ObjFaninC0(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p2) ) + if ( Hop_ObjFaninC1(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Hop_Not(Hop_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Hop_Not(Hop_ObjChild0(pNode0));//pNode1->p1); + return Hop_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Hop_Not(Hop_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Hop_Not(Hop_ObjChild1(pNode1));//pNode2->p2); + return Hop_ObjChild1(pNode0);//pNode1->p2; + } + } + assert( 0 ); // this is not MUX + return NULL; +} + + +/**Function************************************************************* + + Synopsis [Prints Eqn formula for the AIG rooted at this node.] + + Description [The formula is in terms of PIs, which should have + their names assigned in pObj->pData fields.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjPrintEqn( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int Level ) +{ + Vec_Ptr_t * vSuper; + Hop_Obj_t * pFanin; + int fCompl, i; + // store the complemented attribute + fCompl = Hop_IsComplement(pObj); + pObj = Hop_Regular(pObj); + // constant case + if ( Hop_ObjIsConst1(pObj) ) + { + fprintf( pFile, "%d", !fCompl ); + return; + } + // PI case + if ( Hop_ObjIsPi(pObj) ) + { + fprintf( pFile, "%s%s", fCompl? "!" : "", (char*)pObj->pData ); + return; + } + // AND case + Vec_VecExpand( vLevels, Level ); + vSuper = Vec_VecEntry(vLevels, Level); + Hop_ObjCollectMulti( pObj, vSuper ); + fprintf( pFile, "%s", (Level==0? "" : "(") ); + Vec_PtrForEachEntry( Hop_Obj_t *, vSuper, pFanin, i ) + { + Hop_ObjPrintEqn( pFile, Hop_NotCond(pFanin, fCompl), vLevels, Level+1 ); + if ( i < Vec_PtrSize(vSuper) - 1 ) + fprintf( pFile, " %s ", fCompl? "+" : "*" ); + } + fprintf( pFile, "%s", (Level==0? "" : ")") ); + return; +} + +/**Function************************************************************* + + Synopsis [Prints Verilog formula for the AIG rooted at this node.] + + Description [The formula is in terms of PIs, which should have + their names assigned in pObj->pData fields.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjPrintVerilog( FILE * pFile, Hop_Obj_t * pObj, Vec_Vec_t * vLevels, int Level, int fOnlyAnds ) +{ + Vec_Ptr_t * vSuper; + Hop_Obj_t * pFanin, * pFanin0, * pFanin1, * pFaninC; + int fCompl, i; + // store the complemented attribute + fCompl = Hop_IsComplement(pObj); + pObj = Hop_Regular(pObj); + // constant case + if ( Hop_ObjIsConst1(pObj) ) + { + fprintf( pFile, "1\'b%d", !fCompl ); + return; + } + // PI case + if ( Hop_ObjIsPi(pObj) ) + { + fprintf( pFile, "%s%s", fCompl? "~" : "", (char*)pObj->pData ); + return; + } + // EXOR case + if ( !fOnlyAnds && Hop_ObjIsExor(pObj) ) + { + Vec_VecExpand( vLevels, Level ); + vSuper = Vec_VecEntry( vLevels, Level ); + Hop_ObjCollectMulti( pObj, vSuper ); + fprintf( pFile, "%s", (Level==0? "" : "(") ); + Vec_PtrForEachEntry( Hop_Obj_t *, vSuper, pFanin, i ) + { + Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin, (fCompl && i==0)), vLevels, Level+1, fOnlyAnds ); + if ( i < Vec_PtrSize(vSuper) - 1 ) + fprintf( pFile, " ^ " ); + } + fprintf( pFile, "%s", (Level==0? "" : ")") ); + return; + } + // MUX case + if ( !fOnlyAnds && Hop_ObjIsMuxType(pObj) ) + { + if ( Hop_ObjRecognizeExor( pObj, &pFanin0, &pFanin1 ) ) + { + fprintf( pFile, "%s", (Level==0? "" : "(") ); + Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin0, fCompl), vLevels, Level+1, fOnlyAnds ); + fprintf( pFile, " ^ " ); + Hop_ObjPrintVerilog( pFile, pFanin1, vLevels, Level+1, fOnlyAnds ); + fprintf( pFile, "%s", (Level==0? "" : ")") ); + } + else + { + pFaninC = Hop_ObjRecognizeMux( pObj, &pFanin1, &pFanin0 ); + fprintf( pFile, "%s", (Level==0? "" : "(") ); + Hop_ObjPrintVerilog( pFile, pFaninC, vLevels, Level+1, fOnlyAnds ); + fprintf( pFile, " ? " ); + Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin1, fCompl), vLevels, Level+1, fOnlyAnds ); + fprintf( pFile, " : " ); + Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin0, fCompl), vLevels, Level+1, fOnlyAnds ); + fprintf( pFile, "%s", (Level==0? "" : ")") ); + } + return; + } + // AND case + Vec_VecExpand( vLevels, Level ); + vSuper = Vec_VecEntry(vLevels, Level); + Hop_ObjCollectMulti( pObj, vSuper ); + fprintf( pFile, "%s", (Level==0? "" : "(") ); + Vec_PtrForEachEntry( Hop_Obj_t *, vSuper, pFanin, i ) + { + Hop_ObjPrintVerilog( pFile, Hop_NotCond(pFanin, fCompl), vLevels, Level+1, fOnlyAnds ); + if ( i < Vec_PtrSize(vSuper) - 1 ) + fprintf( pFile, " %s ", fCompl? "|" : "&" ); + } + fprintf( pFile, "%s", (Level==0? "" : ")") ); + return; +} + + +/**Function************************************************************* + + Synopsis [Prints node in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ObjPrintVerbose( Hop_Obj_t * pObj, int fHaig ) +{ + assert( !Hop_IsComplement(pObj) ); + printf( "Node %p : ", pObj ); + if ( Hop_ObjIsConst1(pObj) ) + printf( "constant 1" ); + else if ( Hop_ObjIsPi(pObj) ) + printf( "PI" ); + else + printf( "AND( %p%s, %p%s )", + Hop_ObjFanin0(pObj), (Hop_ObjFaninC0(pObj)? "\'" : " "), + Hop_ObjFanin1(pObj), (Hop_ObjFaninC1(pObj)? "\'" : " ") ); + printf( " (refs = %3d)", Hop_ObjRefs(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Prints node in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManPrintVerbose( Hop_Man_t * p, int fHaig ) +{ + Vec_Ptr_t * vNodes; + Hop_Obj_t * pObj; + int i; + printf( "PIs: " ); + Hop_ManForEachPi( p, pObj, i ) + printf( " %p", pObj ); + printf( "\n" ); + vNodes = Hop_ManDfs( p ); + Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i ) + Hop_ObjPrintVerbose( pObj, fHaig ), printf( "\n" ); + printf( "\n" ); + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Writes the AIG into the BLIF file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Hop_ManDumpBlif( Hop_Man_t * p, char * pFileName ) +{ + FILE * pFile; + Vec_Ptr_t * vNodes; + Hop_Obj_t * pObj, * pConst1 = NULL; + int i, nDigits, Counter = 0; + if ( Hop_ManPoNum(p) == 0 ) + { + printf( "Hop_ManDumpBlif(): AIG manager does not have POs.\n" ); + return; + } + // collect nodes in the DFS order + vNodes = Hop_ManDfs( p ); + // assign IDs to objects + Hop_ManConst1(p)->pData = (void *)(ABC_PTRUINT_T)Counter++; + Hop_ManForEachPi( p, pObj, i ) + pObj->pData = (void *)(ABC_PTRUINT_T)Counter++; + Hop_ManForEachPo( p, pObj, i ) + pObj->pData = (void *)(ABC_PTRUINT_T)Counter++; + Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i ) + pObj->pData = (void *)(ABC_PTRUINT_T)Counter++; + nDigits = Hop_Base10Log( Counter ); + // write the file + pFile = fopen( pFileName, "w" ); + fprintf( pFile, "# BLIF file written by procedure Hop_ManDumpBlif() in ABC\n" ); + fprintf( pFile, "# http://www.eecs.berkeley.edu/~alanmi/abc/\n" ); + fprintf( pFile, ".model test\n" ); + // write PIs + fprintf( pFile, ".inputs" ); + Hop_ManForEachPi( p, pObj, i ) + fprintf( pFile, " n%0*d", nDigits, (int)(ABC_PTRUINT_T)pObj->pData ); + fprintf( pFile, "\n" ); + // write POs + fprintf( pFile, ".outputs" ); + Hop_ManForEachPo( p, pObj, i ) + fprintf( pFile, " n%0*d", nDigits, (int)(ABC_PTRUINT_T)pObj->pData ); + fprintf( pFile, "\n" ); + // write nodes + Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i ) + { + fprintf( pFile, ".names n%0*d n%0*d n%0*d\n", + nDigits, (int)(ABC_PTRUINT_T)Hop_ObjFanin0(pObj)->pData, + nDigits, (int)(ABC_PTRUINT_T)Hop_ObjFanin1(pObj)->pData, + nDigits, (int)(ABC_PTRUINT_T)pObj->pData ); + fprintf( pFile, "%d%d 1\n", !Hop_ObjFaninC0(pObj), !Hop_ObjFaninC1(pObj) ); + } + // write POs + Hop_ManForEachPo( p, pObj, i ) + { + fprintf( pFile, ".names n%0*d n%0*d\n", + nDigits, (int)(ABC_PTRUINT_T)Hop_ObjFanin0(pObj)->pData, + nDigits, (int)(ABC_PTRUINT_T)pObj->pData ); + fprintf( pFile, "%d 1\n", !Hop_ObjFaninC0(pObj) ); + if ( Hop_ObjIsConst1(Hop_ObjFanin0(pObj)) ) + pConst1 = Hop_ManConst1(p); + } + if ( pConst1 ) + fprintf( pFile, ".names n%0*d\n 1\n", nDigits, (int)(ABC_PTRUINT_T)pConst1->pData ); + fprintf( pFile, ".end\n\n" ); + fclose( pFile ); + Vec_PtrFree( vNodes ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/hop/hop_.c b/yosys/abc/src/aig/hop/hop_.c new file mode 100644 index 00000000000..b2bd8c22dee --- /dev/null +++ b/yosys/abc/src/aig/hop/hop_.c @@ -0,0 +1,53 @@ +/**CFile**************************************************************** + + FileName [hop_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic And-Inverter Graph package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: hop_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "hop.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/hop/module.make b/yosys/abc/src/aig/hop/module.make new file mode 100644 index 00000000000..e60ec4e8a51 --- /dev/null +++ b/yosys/abc/src/aig/hop/module.make @@ -0,0 +1,10 @@ +SRC += src/aig/hop/hopBalance.c \ + src/aig/hop/hopCheck.c \ + src/aig/hop/hopDfs.c \ + src/aig/hop/hopMan.c \ + src/aig/hop/hopMem.c \ + src/aig/hop/hopObj.c \ + src/aig/hop/hopOper.c \ + src/aig/hop/hopTable.c \ + src/aig/hop/hopTruth.c \ + src/aig/hop/hopUtil.c diff --git a/yosys/abc/src/aig/ioa/ioa.h b/yosys/abc/src/aig/ioa/ioa.h new file mode 100644 index 00000000000..c8aebd39cd1 --- /dev/null +++ b/yosys/abc/src/aig/ioa/ioa.h @@ -0,0 +1,87 @@ +/**CFile**************************************************************** + + FileName [ioa.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: ioa.h,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__ioa__ioa_h +#define ABC__aig__ioa__ioa_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#include "misc/vec/vec.h" +//#include "bar.h" +#include "aig/aig/aig.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== ioaReadAig.c ========================================================*/ +extern Aig_Man_t * Ioa_ReadAigerFromMemory( char * pContents, int nFileSize, int fCheck ); +extern Aig_Man_t * Ioa_ReadAiger( char * pFileName, int fCheck ); +/*=== ioaWriteAig.c =======================================================*/ +extern Vec_Str_t * Ioa_WriteAigerIntoMemoryStr( Aig_Man_t * pMan ); +extern char * Ioa_WriteAigerIntoMemory( Aig_Man_t * pMan, int * pnSize ); +extern void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact ); +/*=== ioaUtil.c =======================================================*/ +extern int Ioa_FileSize( char * pFileName ); +extern char * Ioa_FileNameGeneric( char * FileName ); +extern char * Ioa_FileNameGenericAppend( char * pBase, char * pSuffix ); +extern char * Ioa_TimeStamp(); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/yosys/abc/src/aig/ioa/ioaReadAig.c b/yosys/abc/src/aig/ioa/ioaReadAig.c new file mode 100644 index 00000000000..c1eceef01bc --- /dev/null +++ b/yosys/abc/src/aig/ioa/ioaReadAig.c @@ -0,0 +1,465 @@ +/**CFile**************************************************************** + + FileName [ioaReadAiger.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read binary AIGER format developed by + Armin Biere, Johannes Kepler University (http://fmv.jku.at/)] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - December 16, 2006.] + + Revision [$Id: ioaReadAiger.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ioa.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Extracts one unsigned AIG edge from the input buffer.] + + Description [This procedure is a slightly modified version of Armin Biere's + procedure "unsigned decode (FILE * file)". ] + + SideEffects [Updates the current reading position.] + + SeeAlso [] + +***********************************************************************/ +unsigned Ioa_ReadAigerDecode( char ** ppPos ) +{ + unsigned x = 0, i = 0; + unsigned char ch; + +// while ((ch = getnoneofch (file)) & 0x80) + while ((ch = *(*ppPos)++) & 0x80) + x |= (ch & 0x7f) << (7 * i++); + + return x | (ch << (7 * i)); +} + +/**Function************************************************************* + + Synopsis [Decodes the encoded array of literals.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Ioa_WriteDecodeLiterals( char ** ppPos, int nEntries ) +{ + Vec_Int_t * vLits; + int Lit, LitPrev, Diff, i; + vLits = Vec_IntAlloc( nEntries ); + LitPrev = Ioa_ReadAigerDecode( ppPos ); + Vec_IntPush( vLits, LitPrev ); + for ( i = 1; i < nEntries; i++ ) + { +// Diff = Lit - LitPrev; +// Diff = (Lit < LitPrev)? -Diff : Diff; +// Diff = ((2 * Diff) << 1) | (int)(Lit < LitPrev); + Diff = Ioa_ReadAigerDecode( ppPos ); + Diff = (Diff & 1)? -(Diff >> 1) : Diff >> 1; + Lit = Diff + LitPrev; + Vec_IntPush( vLits, Lit ); + LitPrev = Lit; + } + return vLits; +} + + +/**Function************************************************************* + + Synopsis [Reads the AIG in from the memory buffer.] + + Description [The buffer constains the AIG in AIGER format. The size gives + the number of bytes in the buffer. The buffer is allocated by the user + and not deallocated by this procedure.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Ioa_ReadAigerFromMemory( char * pContents, int nFileSize, int fCheck ) +{ + Vec_Int_t * vLits = NULL; + Vec_Ptr_t * vNodes, * vDrivers;//, * vTerms; + Aig_Obj_t * pObj, * pNode0, * pNode1; + Aig_Man_t * pNew; + int nTotal, nInputs, nOutputs, nLatches, nAnds, i;//, iTerm, nDigits; + int nBad = 0, nConstr = 0, nJust = 0, nFair = 0; + char * pDrivers, * pSymbols, * pCur;//, * pType; + unsigned uLit0, uLit1, uLit; + + // check if the input file format is correct + if ( strncmp(pContents, "aig", 3) != 0 || (pContents[3] != ' ' && pContents[3] != '2') ) + { + fprintf( stdout, "Wrong input file format.\n" ); + return NULL; + } + + // read the parameters (M I L O A + B C J F) + pCur = pContents; while ( *pCur != ' ' ) pCur++; pCur++; + // read the number of objects + nTotal = atoi( pCur ); while ( *pCur != ' ' ) pCur++; pCur++; + // read the number of inputs + nInputs = atoi( pCur ); while ( *pCur != ' ' ) pCur++; pCur++; + // read the number of latches + nLatches = atoi( pCur ); while ( *pCur != ' ' ) pCur++; pCur++; + // read the number of outputs + nOutputs = atoi( pCur ); while ( *pCur != ' ' ) pCur++; pCur++; + // read the number of nodes + nAnds = atoi( pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; + if ( *pCur == ' ' ) + { + assert( nOutputs == 0 ); + // read the number of properties + pCur++; + nBad = atoi( pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; + nOutputs += nBad; + } + if ( *pCur == ' ' ) + { + // read the number of properties + pCur++; + nConstr = atoi( pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; + nOutputs += nConstr; + } + if ( *pCur == ' ' ) + { + // read the number of properties + pCur++; + nJust = atoi( pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; + nOutputs += nJust; + } + if ( *pCur == ' ' ) + { + // read the number of properties + pCur++; + nFair = atoi( pCur ); while ( *pCur != ' ' && *pCur != '\n' ) pCur++; + nOutputs += nFair; + } + if ( *pCur != '\n' ) + { + fprintf( stdout, "The parameter line is in a wrong format.\n" ); + return NULL; + } + pCur++; + + // check the parameters + if ( nTotal != nInputs + nLatches + nAnds ) + { + fprintf( stdout, "The number of objects does not match.\n" ); + return NULL; + } + if ( nJust || nFair ) + { + fprintf( stdout, "Reading AIGER files with liveness properties are currently not supported.\n" ); + return NULL; + } + + if ( nConstr ) + { + if ( nConstr == 1 ) + fprintf( stdout, "Warning: The last output is interpreted as a constraint.\n" ); + else + fprintf( stdout, "Warning: The last %d outputs are interpreted as constraints.\n", nConstr ); + } + + // allocate the empty AIG + pNew = Aig_ManStart( nAnds ); + pNew->nConstrs = nConstr; + + // prepare the array of nodes + vNodes = Vec_PtrAlloc( 1 + nInputs + nLatches + nAnds ); + Vec_PtrPush( vNodes, Aig_ManConst0(pNew) ); + + // create the PIs + for ( i = 0; i < nInputs + nLatches; i++ ) + { + pObj = Aig_ObjCreateCi(pNew); + Vec_PtrPush( vNodes, pObj ); + } +/* + // create the POs + for ( i = 0; i < nOutputs + nLatches; i++ ) + { + pObj = Aig_ObjCreateCo(pNew); + } +*/ + // create the latches + pNew->nRegs = nLatches; +/* + nDigits = Ioa_Base10Log( nLatches ); + for ( i = 0; i < nLatches; i++ ) + { + pObj = Aig_ObjCreateLatch(pNew); + Aig_LatchSetInit0( pObj ); + pNode0 = Aig_ObjCreateBi(pNew); + pNode1 = Aig_ObjCreateBo(pNew); + Aig_ObjAddFanin( pObj, pNode0 ); + Aig_ObjAddFanin( pNode1, pObj ); + Vec_PtrPush( vNodes, pNode1 ); + // assign names to latch and its input +// Aig_ObjAssignName( pObj, Aig_ObjNameDummy("_L", i, nDigits), NULL ); +// printf( "Creating latch %s with input %d and output %d.\n", Aig_ObjName(pObj), pNode0->Id, pNode1->Id ); + } +*/ + + // remember the beginning of latch/PO literals + pDrivers = pCur; + if ( pContents[3] == ' ' ) // standard AIGER + { + // scroll to the beginning of the binary data + for ( i = 0; i < nLatches + nOutputs; ) + if ( *pCur++ == '\n' ) + i++; + } + else // modified AIGER + { + vLits = Ioa_WriteDecodeLiterals( &pCur, nLatches + nOutputs ); + } + + // create the AND gates +// pProgress = Bar_ProgressStart( stdout, nAnds ); + for ( i = 0; i < nAnds; i++ ) + { +// Bar_ProgressUpdate( pProgress, i, NULL ); + uLit = ((i + 1 + nInputs + nLatches) << 1); + uLit1 = uLit - Ioa_ReadAigerDecode( &pCur ); + uLit0 = uLit1 - Ioa_ReadAigerDecode( &pCur ); +// assert( uLit1 > uLit0 ); + pNode0 = Aig_NotCond( (Aig_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), uLit0 & 1 ); + pNode1 = Aig_NotCond( (Aig_Obj_t *)Vec_PtrEntry(vNodes, uLit1 >> 1), uLit1 & 1 ); + assert( Vec_PtrSize(vNodes) == i + 1 + nInputs + nLatches ); + Vec_PtrPush( vNodes, Aig_And(pNew, pNode0, pNode1) ); + } +// Bar_ProgressStop( pProgress ); + + // remember the place where symbols begin + pSymbols = pCur; + + // read the latch driver literals + vDrivers = Vec_PtrAlloc( nLatches + nOutputs ); + if ( pContents[3] == ' ' ) // standard AIGER + { + pCur = pDrivers; + for ( i = 0; i < nLatches; i++ ) + { + uLit0 = atoi( pCur ); while ( *pCur++ != '\n' ); + pNode0 = Aig_NotCond( (Aig_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); + Vec_PtrPush( vDrivers, pNode0 ); + } + // read the PO driver literals + for ( i = 0; i < nOutputs; i++ ) + { + uLit0 = atoi( pCur ); while ( *pCur++ != '\n' ); + pNode0 = Aig_NotCond( (Aig_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); + Vec_PtrPush( vDrivers, pNode0 ); + } + + } + else + { + // read the latch driver literals + for ( i = 0; i < nLatches; i++ ) + { + uLit0 = Vec_IntEntry( vLits, i ); + pNode0 = Aig_NotCond( (Aig_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); + Vec_PtrPush( vDrivers, pNode0 ); + } + // read the PO driver literals + for ( i = 0; i < nOutputs; i++ ) + { + uLit0 = Vec_IntEntry( vLits, i+nLatches ); + pNode0 = Aig_NotCond( (Aig_Obj_t *)Vec_PtrEntry(vNodes, uLit0 >> 1), (uLit0 & 1) );//^ (uLit0 < 2) ); + Vec_PtrPush( vDrivers, pNode0 ); + } + Vec_IntFree( vLits ); + } + + // create the POs + for ( i = 0; i < nOutputs; i++ ) + Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Vec_PtrEntry(vDrivers, nLatches + i) ); + for ( i = 0; i < nLatches; i++ ) + Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Vec_PtrEntry(vDrivers, i) ); + Vec_PtrFree( vDrivers ); + +/* + // read the names if present + pCur = pSymbols; + if ( *pCur != 'c' ) + { + int Counter = 0; + while ( pCur < pContents + nFileSize && *pCur != 'c' ) + { + // get the terminal type + pType = pCur; + if ( *pCur == 'i' ) + vTerms = pNew->vPis; + else if ( *pCur == 'l' ) + vTerms = pNew->vBoxes; + else if ( *pCur == 'o' ) + vTerms = pNew->vPos; + else + { + fprintf( stdout, "Wrong terminal type.\n" ); + return NULL; + } + // get the terminal number + iTerm = atoi( ++pCur ); while ( *pCur++ != ' ' ); + // get the node + if ( iTerm >= Vec_PtrSize(vTerms) ) + { + fprintf( stdout, "The number of terminal is out of bound.\n" ); + return NULL; + } + pObj = Vec_PtrEntry( vTerms, iTerm ); + if ( *pType == 'l' ) + pObj = Aig_ObjFanout0(pObj); + // assign the name + pName = pCur; while ( *pCur++ != '\n' ); + // assign this name + *(pCur-1) = 0; + Aig_ObjAssignName( pObj, pName, NULL ); + if ( *pType == 'l' ) + { + Aig_ObjAssignName( Aig_ObjFanin0(pObj), Aig_ObjName(pObj), "L" ); + Aig_ObjAssignName( Aig_ObjFanin0(Aig_ObjFanin0(pObj)), Aig_ObjName(pObj), "_in" ); + } + // mark the node as named + pObj->pCopy = (Aig_Obj_t *)Aig_ObjName(pObj); + } + + // assign the remaining names + Aig_ManForEachCi( pNew, pObj, i ) + { + if ( pObj->pCopy ) continue; + Aig_ObjAssignName( pObj, Aig_ObjName(pObj), NULL ); + Counter++; + } + Aig_ManForEachLatchOutput( pNew, pObj, i ) + { + if ( pObj->pCopy ) continue; + Aig_ObjAssignName( pObj, Aig_ObjName(pObj), NULL ); + Aig_ObjAssignName( Aig_ObjFanin0(pObj), Aig_ObjName(pObj), "L" ); + Aig_ObjAssignName( Aig_ObjFanin0(Aig_ObjFanin0(pObj)), Aig_ObjName(pObj), "_in" ); + Counter++; + } + Aig_ManForEachCo( pNew, pObj, i ) + { + if ( pObj->pCopy ) continue; + Aig_ObjAssignName( pObj, Aig_ObjName(pObj), NULL ); + Counter++; + } + if ( Counter ) + printf( "Ioa_ReadAiger(): Added %d default names for nameless I/O/register objects.\n", Counter ); + } + else + { +// printf( "Ioa_ReadAiger(): I/O/register names are not given. Generating short names.\n" ); + Aig_ManShortNames( pNew ); + } +*/ + pCur = pSymbols; + if ( pCur + 1 < pContents + nFileSize && *pCur == 'c' ) + { + pCur++; + if ( *pCur == 'n' ) + { + pCur++; + // read model name + ABC_FREE( pNew->pName ); + pNew->pName = Abc_UtilStrsav( pCur ); + } + } + + // skipping the comments + Vec_PtrFree( vNodes ); + + // remove the extra nodes + Aig_ManCleanup( pNew ); + Aig_ManSetRegNum( pNew, Aig_ManRegNum(pNew) ); + + // update polarity of the additional outputs + if ( nBad || nConstr || nJust || nFair ) + Aig_ManInvertConstraints( pNew ); + + // check the result + if ( fCheck && !Aig_ManCheck( pNew ) ) + { + printf( "Ioa_ReadAiger: The network check has failed.\n" ); + Aig_ManStop( pNew ); + return NULL; + } + return pNew; +} + +/**Function************************************************************* + + Synopsis [Reads the AIG in the binary AIGER format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Ioa_ReadAiger( char * pFileName, int fCheck ) +{ + FILE * pFile; + Aig_Man_t * pNew; + char * pName, * pContents; + int nFileSize, RetValue; + + // read the file into the buffer + nFileSize = Ioa_FileSize( pFileName ); + pFile = fopen( pFileName, "rb" ); + pContents = ABC_CALLOC( char, nFileSize+1 ); + RetValue = fread( pContents, nFileSize, 1, pFile ); + fclose( pFile ); + + pNew = Ioa_ReadAigerFromMemory( pContents, nFileSize, fCheck ); + ABC_FREE( pContents ); + if ( pNew ) + { + pName = Ioa_FileNameGeneric( pFileName ); + ABC_FREE( pNew->pName ); + pNew->pName = Abc_UtilStrsav( pName ); + pNew->pSpec = Abc_UtilStrsav( pFileName ); + ABC_FREE( pName ); + } + return pNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ioa/ioaUtil.c b/yosys/abc/src/aig/ioa/ioaUtil.c new file mode 100644 index 00000000000..a2748382931 --- /dev/null +++ b/yosys/abc/src/aig/ioa/ioaUtil.c @@ -0,0 +1,146 @@ +/**CFile**************************************************************** + + FileName [ioaUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to read binary AIGER format developed by + Armin Biere, Johannes Kepler University (http://fmv.jku.at/)] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - December 16, 2006.] + + Revision [$Id: ioaUtil.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ioa.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the file size.] + + Description [The file should be closed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ioa_FileSize( char * pFileName ) +{ + FILE * pFile; + int nFileSize; + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + printf( "Ioa_FileSize(): The file is unavailable (absent or open).\n" ); + return 0; + } + fseek( pFile, 0, SEEK_END ); + nFileSize = ftell( pFile ); + fclose( pFile ); + return nFileSize; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Ioa_FileNameGeneric( char * FileName ) +{ + char * pDot, * pRes; + pRes = Abc_UtilStrsav( FileName ); + if ( (pDot = strrchr( pRes, '.' )) ) + *pDot = 0; + return pRes; +} + +/**Function************************************************************* + + Synopsis [Returns the composite name of the file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Ioa_FileNameGenericAppend( char * pBase, char * pSuffix ) +{ + static char Buffer[1000]; + char * pDot; + if ( pBase == NULL ) + { + strcpy( Buffer, pSuffix ); + return Buffer; + } + strcpy( Buffer, pBase ); + if ( (pDot = strrchr( Buffer, '.' )) ) + *pDot = 0; + strcat( Buffer, pSuffix ); + // find the last occurrance of slash + for ( pDot = Buffer + strlen(Buffer) - 1; pDot >= Buffer; pDot-- ) + if (!((*pDot >= '0' && *pDot <= '9') || + (*pDot >= 'a' && *pDot <= 'z') || + (*pDot >= 'A' && *pDot <= 'Z') || + *pDot == '_' || *pDot == '.') ) + break; + return pDot + 1; +} + +/**Function************************************************************* + + Synopsis [Returns the time stamp.] + + Description [The file should be closed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Ioa_TimeStamp() +{ + static char Buffer[100]; + char * TimeStamp; + time_t ltime; + // get the current time + time( <ime ); + TimeStamp = asctime( localtime( <ime ) ); + TimeStamp[ strlen(TimeStamp) - 1 ] = 0; + strcpy( Buffer, TimeStamp ); + return Buffer; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ioa/ioaWriteAig.c b/yosys/abc/src/aig/ioa/ioaWriteAig.c new file mode 100644 index 00000000000..92e5b33585a --- /dev/null +++ b/yosys/abc/src/aig/ioa/ioaWriteAig.c @@ -0,0 +1,599 @@ +/**CFile**************************************************************** + + FileName [ioaWriteAiger.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Command processing package.] + + Synopsis [Procedures to write binary AIGER format developed by + Armin Biere, Johannes Kepler University (http://fmv.jku.at/)] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - December 16, 2006.] + + Revision [$Id: ioaWriteAiger.c,v 1.00 2006/12/16 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ioa.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/* + The following is taken from the AIGER format description, + which can be found at http://fmv.jku.at/aiger +*/ + + +/* + The AIGER And-Inverter Graph (AIG) Format Version 20061129 + ---------------------------------------------------------- + Armin Biere, Johannes Kepler University, 2006 + + This report describes the AIG file format as used by the AIGER library. + The purpose of this report is not only to motivate and document the + format, but also to allow independent implementations of writers and + readers by giving precise and unambiguous definitions. + + ... + +Introduction + + The name AIGER contains as one part the acronym AIG of And-Inverter + Graphs and also if pronounced in German sounds like the name of the + 'Eiger', a mountain in the Swiss alps. This choice should emphasize the + origin of this format. It was first openly discussed at the Alpine + Verification Meeting 2006 in Ascona as a way to provide a simple, compact + file format for a model checking competition affiliated to CAV 2007. + + ... + +Binary Format Definition + + The binary format is semantically a subset of the ASCII format with a + slightly different syntax. The binary format may need to reencode + literals, but translating a file in binary format into ASCII format and + then back in to binary format will result in the same file. + + The main differences of the binary format to the ASCII format are as + follows. After the header the list of input literals and all the + current state literals of a latch can be omitted. Furthermore the + definitions of the AND gates are binary encoded. However, the symbol + table and the comment section are as in the ASCII format. + + The header of an AIGER file in binary format has 'aig' as format + identifier, but otherwise is identical to the ASCII header. The standard + file extension for the binary format is therefore '.aig'. + + A header for the binary format is still in ASCII encoding: + + aig M I L O A + + Constants, variables and literals are handled in the same way as in the + ASCII format. The first simplifying restriction is on the variable + indices of inputs and latches. The variable indices of inputs come first, + followed by the pseudo-primary inputs of the latches and then the variable + indices of all LHS of AND gates: + + input variable indices 1, 2, ... , I + latch variable indices I+1, I+2, ... , (I+L) + AND variable indices I+L+1, I+L+2, ... , (I+L+A) == M + + The corresponding unsigned literals are + + input literals 2, 4, ... , 2*I + latch literals 2*I+2, 2*I+4, ... , 2*(I+L) + AND literals 2*(I+L)+2, 2*(I+L)+4, ... , 2*(I+L+A) == 2*M + + All literals have to be defined, and therefore 'M = I + L + A'. With this + restriction it becomes possible that the inputs and the current state + literals of the latches do not have to be listed explicitly. Therefore, + after the header only the list of 'L' next state literals follows, one per + latch on a single line, and then the 'O' outputs, again one per line. + + In the binary format we assume that the AND gates are ordered and respect + the child parent relation. AND gates with smaller literals on the LHS + come first. Therefore we can assume that the literals on the right-hand + side of a definition of an AND gate are smaller than the LHS literal. + Furthermore we can sort the literals on the RHS, such that the larger + literal comes first. A definition thus consists of three literals + + lhs rhs0 rhs1 + + with 'lhs' even and 'lhs > rhs0 >= rhs1'. Also the variable indices are + pairwise different to avoid combinational self loops. Since the LHS + indices of the definitions are all consecutive (as even integers), + the binary format does not have to keep 'lhs'. In addition, we can use + the order restriction and only write the differences 'delta0' and 'delta1' + instead of 'rhs0' and 'rhs1', with + + delta0 = lhs - rhs0, delta1 = rhs0 - rhs1 + + The differences will all be strictly positive, and in practice often very + small. We can take advantage of this fact by the simple little-endian + encoding of unsigned integers of the next section. After the binary delta + encoding of the RHSs of all AND gates, the optional symbol table and + optional comment section start in the same format as in the ASCII case. + + ... + +*/ + +static int Ioa_ObjMakeLit( int Var, int fCompl ) { return (Var << 1) | fCompl; } +static int Ioa_ObjAigerNum( Aig_Obj_t * pObj ) { return pObj->iData; } +static void Ioa_ObjSetAigerNum( Aig_Obj_t * pObj, unsigned Num ) { pObj->iData = Num; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Adds one unsigned AIG edge to the output buffer.] + + Description [This procedure is a slightly modified version of Armin Biere's + procedure "void encode (FILE * file, unsigned x)" ] + + SideEffects [Returns the current writing position.] + + SeeAlso [] + +***********************************************************************/ +int Ioa_WriteAigerEncode( unsigned char * pBuffer, int Pos, unsigned x ) +{ + unsigned char ch; + while (x & ~0x7f) + { + ch = (x & 0x7f) | 0x80; +// putc (ch, file); + pBuffer[Pos++] = ch; + x >>= 7; + } + ch = x; +// putc (ch, file); + pBuffer[Pos++] = ch; + return Pos; +} + +/**Function************************************************************* + + Synopsis [Adds one unsigned AIG edge to the output buffer.] + + Description [This procedure is a slightly modified version of Armin Biere's + procedure "void encode (FILE * file, unsigned x)" ] + + SideEffects [Returns the current writing position.] + + SeeAlso [] + +***********************************************************************/ +void Ioa_WriteAigerEncodeStr( Vec_Str_t * vStr, unsigned x ) +{ + unsigned char ch; + while (x & ~0x7f) + { + ch = (x & 0x7f) | 0x80; +// putc (ch, file); +// pBuffer[Pos++] = ch; + Vec_StrPush( vStr, ch ); + x >>= 7; + } + ch = x; +// putc (ch, file); +// pBuffer[Pos++] = ch; + Vec_StrPush( vStr, ch ); +} + +/**Function************************************************************* + + Synopsis [Create the array of literals to be written.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Ioa_WriteAigerLiterals( Aig_Man_t * pMan ) +{ + Vec_Int_t * vLits; + Aig_Obj_t * pObj, * pDriver; + int i; + vLits = Vec_IntAlloc( Aig_ManCoNum(pMan) ); + Aig_ManForEachLiSeq( pMan, pObj, i ) + { + pDriver = Aig_ObjFanin0(pObj); + Vec_IntPush( vLits, Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ) ); + } + Aig_ManForEachPoSeq( pMan, pObj, i ) + { + pDriver = Aig_ObjFanin0(pObj); + Vec_IntPush( vLits, Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ) ); + } + return vLits; +} + +/**Function************************************************************* + + Synopsis [Creates the binary encoded array of literals.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Str_t * Ioa_WriteEncodeLiterals( Vec_Int_t * vLits ) +{ + Vec_Str_t * vBinary; + int Pos = 0, Lit, LitPrev, Diff, i; + vBinary = Vec_StrAlloc( 2 * Vec_IntSize(vLits) ); + LitPrev = Vec_IntEntry( vLits, 0 ); + Pos = Ioa_WriteAigerEncode( (unsigned char *)Vec_StrArray(vBinary), Pos, LitPrev ); + Vec_IntForEachEntryStart( vLits, Lit, i, 1 ) + { + Diff = Lit - LitPrev; + Diff = (Lit < LitPrev)? -Diff : Diff; + Diff = (Diff << 1) | (int)(Lit < LitPrev); + Pos = Ioa_WriteAigerEncode( (unsigned char *)Vec_StrArray(vBinary), Pos, Diff ); + LitPrev = Lit; + if ( Pos + 10 > vBinary->nCap ) + Vec_StrGrow( vBinary, vBinary->nCap+1 ); + } + vBinary->nSize = Pos; +/* + // verify + { + extern Vec_Int_t * Ioa_WriteDecodeLiterals( char ** ppPos, int nEntries ); + char * pPos = Vec_StrArray( vBinary ); + Vec_Int_t * vTemp = Ioa_WriteDecodeLiterals( &pPos, Vec_IntSize(vLits) ); + for ( i = 0; i < Vec_IntSize(vLits); i++ ) + { + int Entry1 = Vec_IntEntry(vLits,i); + int Entry2 = Vec_IntEntry(vTemp,i); + assert( Entry1 == Entry2 ); + } + Vec_IntFree( vTemp ); + } +*/ + return vBinary; +} + +/**Function************************************************************* + + Synopsis [Writes the AIG in into the memory buffer.] + + Description [The resulting buffer constains the AIG in AIGER format. + The returned size (pnSize) gives the number of bytes in the buffer. + The resulting buffer should be deallocated by the user.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Str_t * Ioa_WriteAigerIntoMemoryStr( Aig_Man_t * pMan ) +{ + Vec_Str_t * vBuffer; + Aig_Obj_t * pObj, * pDriver; + int nNodes, i, uLit, uLit0, uLit1; + // set the node numbers to be used in the output file + nNodes = 0; + Ioa_ObjSetAigerNum( Aig_ManConst1(pMan), nNodes++ ); + Aig_ManForEachCi( pMan, pObj, i ) + Ioa_ObjSetAigerNum( pObj, nNodes++ ); + Aig_ManForEachNode( pMan, pObj, i ) + Ioa_ObjSetAigerNum( pObj, nNodes++ ); + + // write the header "M I L O A" where M = I + L + A +/* + fprintf( pFile, "aig%s %u %u %u %u %u\n", + fCompact? "2" : "", + Aig_ManCiNum(pMan) + Aig_ManNodeNum(pMan), + Aig_ManCiNum(pMan) - Aig_ManRegNum(pMan), + Aig_ManRegNum(pMan), + Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan), + Aig_ManNodeNum(pMan) ); +*/ + vBuffer = Vec_StrAlloc( 3*Aig_ManObjNum(pMan) ); + Vec_StrPrintStr( vBuffer, "aig " ); + Vec_StrPrintNum( vBuffer, Aig_ManCiNum(pMan) + Aig_ManNodeNum(pMan) ); + Vec_StrPrintStr( vBuffer, " " ); + Vec_StrPrintNum( vBuffer, Aig_ManCiNum(pMan) - Aig_ManRegNum(pMan) ); + Vec_StrPrintStr( vBuffer, " " ); + Vec_StrPrintNum( vBuffer, Aig_ManRegNum(pMan) ); + Vec_StrPrintStr( vBuffer, " " ); + Vec_StrPrintNum( vBuffer, Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan) ); + Vec_StrPrintStr( vBuffer, " " ); + Vec_StrPrintNum( vBuffer, Aig_ManNodeNum(pMan) ); + Vec_StrPrintStr( vBuffer, "\n" ); + + // write latch drivers + Aig_ManForEachLiSeq( pMan, pObj, i ) + { + pDriver = Aig_ObjFanin0(pObj); + uLit = Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ); +// fprintf( pFile, "%u\n", uLit ); + Vec_StrPrintNum( vBuffer, uLit ); + Vec_StrPrintStr( vBuffer, "\n" ); + } + + // write PO drivers + Aig_ManForEachPoSeq( pMan, pObj, i ) + { + pDriver = Aig_ObjFanin0(pObj); + uLit = Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ); +// fprintf( pFile, "%u\n", uLit ); + Vec_StrPrintNum( vBuffer, uLit ); + Vec_StrPrintStr( vBuffer, "\n" ); + } + // write the nodes into the buffer + Aig_ManForEachNode( pMan, pObj, i ) + { + uLit = Ioa_ObjMakeLit( Ioa_ObjAigerNum(pObj), 0 ); + uLit0 = Ioa_ObjMakeLit( Ioa_ObjAigerNum(Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj) ); + uLit1 = Ioa_ObjMakeLit( Ioa_ObjAigerNum(Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj) ); + assert( uLit0 != uLit1 ); + if ( uLit0 > uLit1 ) + { + int Temp = uLit0; + uLit0 = uLit1; + uLit1 = Temp; + } +// Pos = Ioa_WriteAigerEncode( pBuffer, Pos, uLit - uLit1 ); +// Pos = Ioa_WriteAigerEncode( pBuffer, Pos, uLit1 - uLit0 ); + Ioa_WriteAigerEncodeStr( vBuffer, uLit - uLit1 ); + Ioa_WriteAigerEncodeStr( vBuffer, uLit1 - uLit0 ); + } + Vec_StrPrintStr( vBuffer, "c" ); + return vBuffer; +} + +/**Function************************************************************* + + Synopsis [Writes the AIG in into the memory buffer.] + + Description [The resulting buffer constains the AIG in AIGER format. + The returned size (pnSize) gives the number of bytes in the buffer. + The resulting buffer should be deallocated by the user.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Ioa_WriteAigerIntoMemory( Aig_Man_t * pMan, int * pnSize ) +{ + char * pBuffer; + Vec_Str_t * vBuffer; + vBuffer = Ioa_WriteAigerIntoMemoryStr( pMan ); + if ( pMan->pName ) + { + Vec_StrPrintStr( vBuffer, "n" ); + Vec_StrPrintStr( vBuffer, pMan->pName ); + Vec_StrPush( vBuffer, 0 ); + } + // prepare the return values + *pnSize = Vec_StrSize( vBuffer ); + pBuffer = Vec_StrReleaseArray( vBuffer ); + Vec_StrFree( vBuffer ); + return pBuffer; +} + +/**Function************************************************************* + + Synopsis [This procedure is used to test the above procedure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ioa_WriteAigerBufferTest( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact ) +{ + FILE * pFile; + char * pBuffer; + int nSize; + if ( Aig_ManCoNum(pMan) == 0 ) + { + printf( "AIG cannot be written because it has no POs.\n" ); + return; + } + // start the output stream + pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Ioa_WriteAiger(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + // write the buffer + pBuffer = Ioa_WriteAigerIntoMemory( pMan, &nSize ); + fwrite( pBuffer, 1, nSize, pFile ); + ABC_FREE( pBuffer ); + // write the comment +// fprintf( pFile, "c" ); +// if ( pMan->pName ) +// fprintf( pFile, "n%s%c", pMan->pName, '\0' ); + fprintf( pFile, "\nThis file was produced by the IOA package in ABC on %s\n", Ioa_TimeStamp() ); + fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Writes the AIG in the binary AIGER format.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ioa_WriteAiger( Aig_Man_t * pMan, char * pFileName, int fWriteSymbols, int fCompact ) +{ +// Bar_Progress_t * pProgress; + FILE * pFile; + Aig_Obj_t * pObj, * pDriver; + int i, nNodes, nBufferSize, Pos; + unsigned char * pBuffer; + unsigned uLit0, uLit1, uLit; + + if ( Aig_ManCoNum(pMan) == 0 ) + { + printf( "AIG cannot be written because it has no POs.\n" ); + return; + } + +// assert( Aig_ManIsStrash(pMan) ); + // start the output stream + pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Ioa_WriteAiger(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } +/* + Aig_ManForEachLatch( pMan, pObj, i ) + if ( !Aig_LatchIsInit0(pObj) ) + { + fprintf( stdout, "Ioa_WriteAiger(): Cannot write AIGER format with non-0 latch init values. Run \"zero\".\n" ); + return; + } +*/ + // set the node numbers to be used in the output file + nNodes = 0; + Ioa_ObjSetAigerNum( Aig_ManConst1(pMan), nNodes++ ); + Aig_ManForEachCi( pMan, pObj, i ) + Ioa_ObjSetAigerNum( pObj, nNodes++ ); + Aig_ManForEachNode( pMan, pObj, i ) + Ioa_ObjSetAigerNum( pObj, nNodes++ ); + + // write the header "M I L O A" where M = I + L + A + fprintf( pFile, "aig%s %u %u %u %u %u", + fCompact? "2" : "", + Aig_ManCiNum(pMan) + Aig_ManNodeNum(pMan), + Aig_ManCiNum(pMan) - Aig_ManRegNum(pMan), + Aig_ManRegNum(pMan), + Aig_ManConstrNum(pMan) ? 0 : Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan), + Aig_ManNodeNum(pMan) ); + // write the extended header "B C J F" + if ( Aig_ManConstrNum(pMan) ) + fprintf( pFile, " %u %u", Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan) - Aig_ManConstrNum(pMan), Aig_ManConstrNum(pMan) ); + fprintf( pFile, "\n" ); + + // if the driver node is a constant, we need to complement the literal below + // because, in the AIGER format, literal 0/1 is represented as number 0/1 + // while, in ABC, constant 1 node has number 0 and so literal 0/1 will be 1/0 + + Aig_ManInvertConstraints( pMan ); + if ( !fCompact ) + { + // write latch drivers + Aig_ManForEachLiSeq( pMan, pObj, i ) + { + pDriver = Aig_ObjFanin0(pObj); + fprintf( pFile, "%u\n", Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ) ); + } + + // write PO drivers + Aig_ManForEachPoSeq( pMan, pObj, i ) + { + pDriver = Aig_ObjFanin0(pObj); + fprintf( pFile, "%u\n", Ioa_ObjMakeLit( Ioa_ObjAigerNum(pDriver), Aig_ObjFaninC0(pObj) ^ (Ioa_ObjAigerNum(pDriver) == 0) ) ); + } + } + else + { + Vec_Int_t * vLits = Ioa_WriteAigerLiterals( pMan ); + Vec_Str_t * vBinary = Ioa_WriteEncodeLiterals( vLits ); + fwrite( Vec_StrArray(vBinary), 1, Vec_StrSize(vBinary), pFile ); + Vec_StrFree( vBinary ); + Vec_IntFree( vLits ); + } + Aig_ManInvertConstraints( pMan ); + + // write the nodes into the buffer + Pos = 0; + nBufferSize = 6 * Aig_ManNodeNum(pMan) + 100; // skeptically assuming 3 chars per one AIG edge + pBuffer = ABC_ALLOC( unsigned char, nBufferSize ); +// pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(pMan) ); + Aig_ManForEachNode( pMan, pObj, i ) + { +// Bar_ProgressUpdate( pProgress, i, NULL ); + uLit = Ioa_ObjMakeLit( Ioa_ObjAigerNum(pObj), 0 ); + uLit0 = Ioa_ObjMakeLit( Ioa_ObjAigerNum(Aig_ObjFanin0(pObj)), Aig_ObjFaninC0(pObj) ); + uLit1 = Ioa_ObjMakeLit( Ioa_ObjAigerNum(Aig_ObjFanin1(pObj)), Aig_ObjFaninC1(pObj) ); + assert( uLit0 != uLit1 ); + if ( uLit0 > uLit1 ) + { + int Temp = uLit0; + uLit0 = uLit1; + uLit1 = Temp; + } + Pos = Ioa_WriteAigerEncode( pBuffer, Pos, uLit - uLit1 ); + Pos = Ioa_WriteAigerEncode( pBuffer, Pos, uLit1 - uLit0 ); + if ( Pos > nBufferSize - 10 ) + { + printf( "Ioa_WriteAiger(): AIGER generation has failed because the allocated buffer is too small.\n" ); + fclose( pFile ); + return; + } + } + assert( Pos < nBufferSize ); +// Bar_ProgressStop( pProgress ); + + // write the buffer + fwrite( pBuffer, 1, Pos, pFile ); + ABC_FREE( pBuffer ); +/* + // write the symbol table + if ( fWriteSymbols ) + { + int bads; + // write PIs + Aig_ManForEachPiSeq( pMan, pObj, i ) + fprintf( pFile, "i%d %s\n", i, Aig_ObjName(pObj) ); + // write latches + Aig_ManForEachLoSeq( pMan, pObj, i ) + fprintf( pFile, "l%d %s\n", i, Aig_ObjName(Aig_ObjFanout0(pObj)) ); + // write POs + bads = Aig_ManCoNum(pMan) - Aig_ManRegNum(pMan) - Aig_ManConstrNum(pMan); + Aig_ManForEachPoSeq( pMan, pObj, i ) + if ( !Aig_ManConstrNum(pMan) ) + fprintf( pFile, "o%d %s\n", i, Aig_ObjName(pObj) ); + else if ( i < bads ) + fprintf( pFile, "b%d %s\n", i, Aig_ObjName(pObj) ); + else + fprintf( pFile, "c%d %s\n", i - bads, Aig_ObjName(pObj) ); + } +*/ + // write the comment + fprintf( pFile, "c" ); + if ( pMan->pName ) + fprintf( pFile, "n%s%c", pMan->pName, '\0' ); + fprintf( pFile, "\nThis file was produced by the IOA package in ABC on %s\n", Ioa_TimeStamp() ); + fprintf( pFile, "For information about AIGER format, refer to %s\n", "http://fmv.jku.at/aiger" ); + fclose( pFile ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ioa/module.make b/yosys/abc/src/aig/ioa/module.make new file mode 100644 index 00000000000..66b4a0d5793 --- /dev/null +++ b/yosys/abc/src/aig/ioa/module.make @@ -0,0 +1,3 @@ +SRC += src/aig/ioa/ioaReadAig.c \ + src/aig/ioa/ioaWriteAig.c \ + src/aig/ioa/ioaUtil.c diff --git a/yosys/abc/src/aig/ivy/attr.h b/yosys/abc/src/aig/ivy/attr.h new file mode 100644 index 00000000000..07586832d7f --- /dev/null +++ b/yosys/abc/src/aig/ivy/attr.h @@ -0,0 +1,418 @@ +/**CFile**************************************************************** + + FileName [attr.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network attributes.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: attr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__ivy__attr_h +#define ABC__aig__ivy__attr_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "misc/extra/extra.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Attr_ManStruct_t_ Attr_Man_t; +struct Attr_ManStruct_t_ +{ + // attribute info + int nAttrSize; // the size of each attribute in bytes + Extra_MmFixed_t * pManMem; // memory manager for attributes + int nAttrs; // the number of attributes allocated + void ** pAttrs; // the array of attributes + int fUseInt; // uses integer attributes + // attribute specific info + void * pManAttr; // the manager for this attribute + void (*pFuncFreeMan) (void *); // the procedure to call to free attribute-specific manager + void (*pFuncFreeObj) (void *, void *); // the procedure to call to free attribute-specific data +}; + +// at any time, an attribute of the given ID can be +// - not available (p->nAttrs < Id) +// - available but not allocated (p->nAttrs >= Id && p->pAttrs[Id] == NULL) +// - available and allocated (p->nAttrs >= Id && p->pAttrs[Id] != NULL) + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the attribute manager.] + + Description [The manager is simple if it does not need memory manager.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Attr_Man_t * Attr_ManAlloc( int nAttrSize, int fManMem ) +{ + Attr_Man_t * p; + p = ALLOC( Attr_Man_t, 1 ); + memset( p, 0, sizeof(Attr_Man_t) ); + p->nAttrSize = nAttrSize; + if ( fManMem ) + p->pManMem = Extra_MmFixedStart( nAttrSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Start the attribute manager for integers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Attr_Man_t * Attr_ManStartInt( int nAttrs ) +{ + Attr_Man_t * p; + p = Attr_ManAlloc( sizeof(int), 0 ); + p->nAttrs = nAttrs; + p->pAttrs = (void **)ALLOC( int, nAttrs ); + memset( (int *)p->pAttrs, 0, sizeof(int) * nAttrs ); + p->fUseInt = 1; + return p; +} + +/**Function************************************************************* + + Synopsis [Start the attribute manager for pointers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Attr_Man_t * Attr_ManStartPtr( int nAttrs ) +{ + Attr_Man_t * p; + p = Attr_ManAlloc( sizeof(void *), 0 ); + p->nAttrs = nAttrs; + p->pAttrs = ALLOC( void *, nAttrs ); + memset( p->pAttrs, 0, sizeof(void *) * nAttrs ); + return p; +} + +/**Function************************************************************* + + Synopsis [Start the attribute manager for the fixed entry size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Attr_Man_t * Attr_ManStartPtrMem( int nAttrs, int nAttrSize ) +{ + Attr_Man_t * p; + int i; + p = Attr_ManAlloc( nAttrSize, 1 ); + p->nAttrs = nAttrs; + p->pAttrs = ALLOC( void *, nAttrs ); + for ( i = 0; i < p->nAttrs; i++ ) + { + p->pAttrs[i] = Extra_MmFixedEntryFetch( p->pManMem ); + memset( p->pAttrs[i], 0, nAttrSize ); + } + return p; +} + +/**Function************************************************************* + + Synopsis [Stop the attribute manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Attr_ManStop( Attr_Man_t * p ) +{ + // free the attributes of objects + if ( p->pFuncFreeObj ) + { + int i; + if ( p->fUseInt ) + { + for ( i = 0; i < p->nAttrs; i++ ) + if ( ((int *)p->pAttrs)[i] ) + p->pFuncFreeObj( p->pManAttr, (void *)((int *)p->pAttrs)[i] ); + } + else + { + for ( i = 0; i < p->nAttrs; i++ ) + if ( p->pAttrs[i] ) + p->pFuncFreeObj( p->pManAttr, p->pAttrs[i] ); + } + } + // free the attribute manager + if ( p->pManAttr && p->pFuncFreeMan ) + p->pFuncFreeMan( p->pManAttr ); + // free the memory manager + if ( p->pManMem ) + Extra_MmFixedStop( p->pManMem); + // free the attribute manager + FREE( p->pAttrs ); + free( p ); +} + +/**Function************************************************************* + + Synopsis [Reads the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Attr_ManReadAttrInt( Attr_Man_t * p, int Id ) +{ + assert( p->fUseInt ); + if ( Id >= p->nAttrs ) + return 0; + return ((int *)p->pAttrs)[Id]; +} + +/**Function************************************************************* + + Synopsis [Reads the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void * Attr_ManReadAttrPtr( Attr_Man_t * p, int Id ) +{ + assert( !p->fUseInt ); + if ( Id >= p->nAttrs ) + return NULL; + return p->pAttrs[Id]; +} + +/**Function************************************************************* + + Synopsis [Writes the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Attr_ManWriteAttrInt( Attr_Man_t * p, int Id, int Attr ) +{ + assert( p->fUseInt ); + ((int *)p->pAttrs)[Id] = Attr; +} + +/**Function************************************************************* + + Synopsis [Writes the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Attr_ManWriteAttrPtr( Attr_Man_t * p, int Id, void * pAttr ) +{ + assert( !p->fUseInt ); + assert( p->pManMem == NULL ); + p->pAttrs[Id] = pAttr; +} + +/**Function************************************************************* + + Synopsis [Returns or creates the pointer to the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int * Attr_ManFetchSpotInt( Attr_Man_t * p, int Id ) +{ + assert( p->fUseInt ); + if ( Id >= p->nAttrs ) + { + // save the old size + int i, nAttrsOld = p->nAttrs; + // get the new size + p->nAttrs = p->nAttrs? 2*p->nAttrs : 1024; + p->pAttrs = realloc( p->pAttrs, sizeof(int) * p->nAttrs ); + // fill in the empty spots + for ( i = nAttrsOld; i < p->nAttrs; i++ ) + ((int *)p->pAttrs)[Id] = 0; + } + return ((int *)p->pAttrs) + Id; +} + +/**Function************************************************************* + + Synopsis [Returns or creates the pointer to the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void ** Attr_ManFetchSpotPtr( Attr_Man_t * p, int Id ) +{ + assert( !p->fUseInt ); + if ( Id >= p->nAttrs ) + { + // save the old size + int i, nAttrsOld = p->nAttrs; + // get the new size + p->nAttrs = p->nAttrs? 2*p->nAttrs : 1024; + p->pAttrs = realloc( p->pAttrs, sizeof(void *) * p->nAttrs ); + // fill in the empty spots + for ( i = nAttrsOld; i < p->nAttrs; i++ ) + p->pAttrs[Id] = NULL; + } + // if memory manager is available but entry is not created, create it + if ( p->pManMem && p->pAttrs[Id] != NULL ) + { + p->pAttrs[Id] = Extra_MmFixedEntryFetch( p->pManMem ); + memset( p->pAttrs[Id], 0, p->nAttrSize ); + } + return p->pAttrs + Id; +} + + +/**Function************************************************************* + + Synopsis [Returns or creates the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Attr_ManFetchAttrInt( Attr_Man_t * p, int Id ) +{ + return *Attr_ManFetchSpotInt( p, Id ); +} + +/**Function************************************************************* + + Synopsis [Returns or creates the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void * Attr_ManFetchAttrPtr( Attr_Man_t * p, int Id ) +{ + return *Attr_ManFetchSpotPtr( p, Id ); +} + +/**Function************************************************************* + + Synopsis [Sets the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Attr_ManSetAttrInt( Attr_Man_t * p, int Id, int Attr ) +{ + *Attr_ManFetchSpotInt( p, Id ) = Attr; +} + +/**Function************************************************************* + + Synopsis [Sets the attribute of the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Attr_ManSetAttrPtr( Attr_Man_t * p, int Id, void * pAttr ) +{ + assert( p->pManMem == NULL ); + *Attr_ManFetchSpotPtr( p, Id ) = pAttr; +} + + + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/yosys/abc/src/aig/ivy/ivy.h b/yosys/abc/src/aig/ivy/ivy.h new file mode 100644 index 00000000000..c2bbd5abcd3 --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivy.h @@ -0,0 +1,562 @@ +/**CFile**************************************************************** + + FileName [ivy.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivy.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__ivy__ivy_h +#define ABC__aig__ivy__ivy_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include "misc/extra/extra.h" +#include "misc/vec/vec.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Ivy_Man_t_ Ivy_Man_t; +typedef struct Ivy_Obj_t_ Ivy_Obj_t; +typedef int Ivy_Edge_t; +typedef struct Ivy_FraigParams_t_ Ivy_FraigParams_t; + +// object types +typedef enum { + IVY_NONE, // 0: non-existent object + IVY_PI, // 1: primary input (and constant 1 node) + IVY_PO, // 2: primary output + IVY_ASSERT, // 3: assertion + IVY_LATCH, // 4: sequential element + IVY_AND, // 5: AND node + IVY_EXOR, // 6: EXOR node + IVY_BUF, // 7: buffer (temporary) + IVY_VOID // 8: unused object +} Ivy_Type_t; + +// latch initial values +typedef enum { + IVY_INIT_NONE, // 0: not a latch + IVY_INIT_0, // 1: zero + IVY_INIT_1, // 2: one + IVY_INIT_DC // 3: don't-care +} Ivy_Init_t; + +// the AIG node +struct Ivy_Obj_t_ // 24 bytes (32-bit) or 32 bytes (64-bit) // 10 words - 16 words +{ + int Id; // integer ID + int TravId; // traversal ID + unsigned Type : 4; // object type + unsigned fMarkA : 1; // multipurpose mask + unsigned fMarkB : 1; // multipurpose mask + unsigned fExFan : 1; // set to 1 if last fanout added is EXOR + unsigned fPhase : 1; // value under 000...0 pattern + unsigned fFailTfo : 1; // the TFO of the failed node + unsigned Init : 2; // latch initial value + unsigned Level : 21; // logic level + int nRefs; // reference counter + Ivy_Obj_t * pFanin0; // fanin + Ivy_Obj_t * pFanin1; // fanin + Ivy_Obj_t * pFanout; // fanout + Ivy_Obj_t * pNextFan0; // next fanout of the first fanin + Ivy_Obj_t * pNextFan1; // next fanout of the second fanin + Ivy_Obj_t * pPrevFan0; // prev fanout of the first fanin + Ivy_Obj_t * pPrevFan1; // prev fanout of the second fanin + Ivy_Obj_t * pEquiv; // equivalent node +}; + +// the AIG manager +struct Ivy_Man_t_ +{ + // AIG nodes + Vec_Ptr_t * vPis; // the array of PIs + Vec_Ptr_t * vPos; // the array of POs + Vec_Ptr_t * vBufs; // the array of buffers + Vec_Ptr_t * vObjs; // the array of objects + Ivy_Obj_t * pConst1; // the constant 1 node + Ivy_Obj_t Ghost; // the ghost node + // AIG node counters + int nObjs[IVY_VOID];// the number of objects by type + int nCreated; // the number of created objects + int nDeleted; // the number of deleted objects + // stuctural hash table + int * pTable; // structural hash table + int nTableSize; // structural hash table size + // various data members + int fCatchExor; // set to 1 to detect EXORs + int nTravIds; // the traversal ID + int nLevelMax; // the maximum level + Vec_Int_t * vRequired; // required times + int fFanout; // fanout is allocated + void * pData; // the temporary data + void * pCopy; // the temporary data + Ivy_Man_t * pHaig; // history AIG if present + int nClassesSkip; // the number of skipped classes + // memory management + Vec_Ptr_t * vChunks; // allocated memory pieces + Vec_Ptr_t * vPages; // memory pages used by nodes + Ivy_Obj_t * pListFree; // the list of free nodes + // timing statistics + abctime time1; + abctime time2; +}; + +struct Ivy_FraigParams_t_ +{ + int nSimWords; // the number of words in the simulation info + double dSimSatur; // the ratio of refined classes when saturation is reached + int fPatScores; // enables simulation pattern scoring + int MaxScore; // max score after which resimulation is used + double dActConeRatio; // the ratio of cone to be bumped + double dActConeBumpMax; // the largest bump in activity + int fProve; // prove the miter outputs + int fVerbose; // verbose output + int fDoSparse; // skip sparse functions + int nBTLimitNode; // conflict limit at a node + int nBTLimitMiter; // conflict limit at an output +// int nBTLimitGlobal; // conflict limit global +// int nInsLimitNode; // inspection limit at a node +// int nInsLimitMiter; // inspection limit at an output +// int nInsLimitGlobal; // inspection limit global +}; + + +#define IVY_CUT_LIMIT 256 +#define IVY_CUT_INPUT 6 + +typedef struct Ivy_Cut_t_ Ivy_Cut_t; +struct Ivy_Cut_t_ +{ + int nLatches; + short nSize; + short nSizeMax; + int pArray[IVY_CUT_INPUT]; + unsigned uHash; +}; + +typedef struct Ivy_Store_t_ Ivy_Store_t; +struct Ivy_Store_t_ +{ + int nCuts; + int nCutsM; + int nCutsMax; + int fSatur; + Ivy_Cut_t pCuts[IVY_CUT_LIMIT]; // storage for cuts +}; + +#define IVY_LEAF_MASK 255 +#define IVY_LEAF_BITS 8 + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define IVY_MIN(a,b) (((a) < (b))? (a) : (b)) +#define IVY_MAX(a,b) (((a) > (b))? (a) : (b)) + +extern void Ivy_ManAddMemory( Ivy_Man_t * p ); + +static inline int Ivy_BitWordNum( int nBits ) { return (nBits>>5) + ((nBits&31) > 0); } +static inline int Ivy_TruthWordNum( int nVars ) { return nVars <= 5 ? 1 : (1 << (nVars - 5)); } +static inline int Ivy_InfoHasBit( unsigned * p, int i ) { return (p[(i)>>5] & (1<<((i) & 31))) > 0; } +static inline void Ivy_InfoSetBit( unsigned * p, int i ) { p[(i)>>5] |= (1<<((i) & 31)); } +static inline void Ivy_InfoXorBit( unsigned * p, int i ) { p[(i)>>5] ^= (1<<((i) & 31)); } + +static inline Ivy_Obj_t * Ivy_Regular( Ivy_Obj_t * p ) { return (Ivy_Obj_t *)((ABC_PTRUINT_T)(p) & ~01); } +static inline Ivy_Obj_t * Ivy_Not( Ivy_Obj_t * p ) { return (Ivy_Obj_t *)((ABC_PTRUINT_T)(p) ^ 01); } +static inline Ivy_Obj_t * Ivy_NotCond( Ivy_Obj_t * p, int c ) { return (Ivy_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c)); } +static inline int Ivy_IsComplement( Ivy_Obj_t * p ) { return (int)((ABC_PTRUINT_T)(p) & 01); } + +static inline Ivy_Obj_t * Ivy_ManConst0( Ivy_Man_t * p ) { return Ivy_Not(p->pConst1); } +static inline Ivy_Obj_t * Ivy_ManConst1( Ivy_Man_t * p ) { return p->pConst1; } +static inline Ivy_Obj_t * Ivy_ManGhost( Ivy_Man_t * p ) { return &p->Ghost; } +static inline Ivy_Obj_t * Ivy_ManPi( Ivy_Man_t * p, int i ) { return (Ivy_Obj_t *)Vec_PtrEntry(p->vPis, i); } +static inline Ivy_Obj_t * Ivy_ManPo( Ivy_Man_t * p, int i ) { return (Ivy_Obj_t *)Vec_PtrEntry(p->vPos, i); } +static inline Ivy_Obj_t * Ivy_ManObj( Ivy_Man_t * p, int i ) { return (Ivy_Obj_t *)Vec_PtrEntry(p->vObjs, i); } + +static inline Ivy_Edge_t Ivy_EdgeCreate( int Id, int fCompl ) { return (Id << 1) | fCompl; } +static inline int Ivy_EdgeId( Ivy_Edge_t Edge ) { return Edge >> 1; } +static inline int Ivy_EdgeIsComplement( Ivy_Edge_t Edge ) { return Edge & 1; } +static inline Ivy_Edge_t Ivy_EdgeRegular( Ivy_Edge_t Edge ) { return (Edge >> 1) << 1; } +static inline Ivy_Edge_t Ivy_EdgeNot( Ivy_Edge_t Edge ) { return Edge ^ 1; } +static inline Ivy_Edge_t Ivy_EdgeNotCond( Ivy_Edge_t Edge, int fCond ) { return Edge ^ fCond; } +static inline Ivy_Edge_t Ivy_EdgeFromNode( Ivy_Obj_t * pNode ) { return Ivy_EdgeCreate( Ivy_Regular(pNode)->Id, Ivy_IsComplement(pNode) ); } +static inline Ivy_Obj_t * Ivy_EdgeToNode( Ivy_Man_t * p, Ivy_Edge_t Edge ){ return Ivy_NotCond( Ivy_ManObj(p, Ivy_EdgeId(Edge)), Ivy_EdgeIsComplement(Edge) ); } + +static inline int Ivy_LeafCreate( int Id, int Lat ) { return (Id << IVY_LEAF_BITS) | Lat; } +static inline int Ivy_LeafId( int Leaf ) { return Leaf >> IVY_LEAF_BITS; } +static inline int Ivy_LeafLat( int Leaf ) { return Leaf & IVY_LEAF_MASK; } + +static inline int Ivy_ManPiNum( Ivy_Man_t * p ) { return p->nObjs[IVY_PI]; } +static inline int Ivy_ManPoNum( Ivy_Man_t * p ) { return p->nObjs[IVY_PO]; } +static inline int Ivy_ManAssertNum( Ivy_Man_t * p ) { return p->nObjs[IVY_ASSERT]; } +static inline int Ivy_ManLatchNum( Ivy_Man_t * p ) { return p->nObjs[IVY_LATCH]; } +static inline int Ivy_ManAndNum( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]; } +static inline int Ivy_ManExorNum( Ivy_Man_t * p ) { return p->nObjs[IVY_EXOR]; } +static inline int Ivy_ManBufNum( Ivy_Man_t * p ) { return p->nObjs[IVY_BUF]; } +static inline int Ivy_ManObjNum( Ivy_Man_t * p ) { return p->nCreated - p->nDeleted; } +static inline int Ivy_ManObjIdMax( Ivy_Man_t * p ) { return Vec_PtrSize(p->vObjs)-1; } +static inline int Ivy_ManNodeNum( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]+p->nObjs[IVY_EXOR];} +static inline int Ivy_ManHashObjNum( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]+p->nObjs[IVY_EXOR]+p->nObjs[IVY_LATCH]; } +static inline int Ivy_ManGetCost( Ivy_Man_t * p ) { return p->nObjs[IVY_AND]+3*p->nObjs[IVY_EXOR]+8*p->nObjs[IVY_LATCH]; } + +static inline Ivy_Type_t Ivy_ObjType( Ivy_Obj_t * pObj ) { return (Ivy_Type_t)pObj->Type; } +static inline Ivy_Init_t Ivy_ObjInit( Ivy_Obj_t * pObj ) { return (Ivy_Init_t)pObj->Init; } +static inline int Ivy_ObjIsConst1( Ivy_Obj_t * pObj ) { return pObj->Id == 0; } +static inline int Ivy_ObjIsGhost( Ivy_Obj_t * pObj ) { return pObj->Id < 0; } +static inline int Ivy_ObjIsNone( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_NONE; } +static inline int Ivy_ObjIsPi( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PI; } +static inline int Ivy_ObjIsPo( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PO; } +static inline int Ivy_ObjIsCi( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PI || pObj->Type == IVY_LATCH; } +static inline int Ivy_ObjIsCo( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PO || pObj->Type == IVY_LATCH; } +static inline int Ivy_ObjIsAssert( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_ASSERT; } +static inline int Ivy_ObjIsLatch( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_LATCH; } +static inline int Ivy_ObjIsAnd( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_AND; } +static inline int Ivy_ObjIsExor( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_EXOR; } +static inline int Ivy_ObjIsBuf( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_BUF; } +static inline int Ivy_ObjIsNode( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_AND || pObj->Type == IVY_EXOR; } +static inline int Ivy_ObjIsTerm( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PI || pObj->Type == IVY_PO || pObj->Type == IVY_ASSERT; } +static inline int Ivy_ObjIsHash( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_AND || pObj->Type == IVY_EXOR || pObj->Type == IVY_LATCH; } +static inline int Ivy_ObjIsOneFanin( Ivy_Obj_t * pObj ) { return pObj->Type == IVY_PO || pObj->Type == IVY_ASSERT || pObj->Type == IVY_BUF || pObj->Type == IVY_LATCH; } + +static inline int Ivy_ObjIsMarkA( Ivy_Obj_t * pObj ) { return pObj->fMarkA; } +static inline void Ivy_ObjSetMarkA( Ivy_Obj_t * pObj ) { pObj->fMarkA = 1; } +static inline void Ivy_ObjClearMarkA( Ivy_Obj_t * pObj ) { pObj->fMarkA = 0; } + +static inline void Ivy_ObjSetTravId( Ivy_Obj_t * pObj, int TravId ) { pObj->TravId = TravId; } +static inline void Ivy_ObjSetTravIdCurrent( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { pObj->TravId = p->nTravIds; } +static inline void Ivy_ObjSetTravIdPrevious( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { pObj->TravId = p->nTravIds - 1; } +static inline int Ivy_ObjIsTravIdCurrent( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { return (int )((int)pObj->TravId == p->nTravIds); } +static inline int Ivy_ObjIsTravIdPrevious( Ivy_Man_t * p, Ivy_Obj_t * pObj ) { return (int )((int)pObj->TravId == p->nTravIds - 1); } + +static inline int Ivy_ObjId( Ivy_Obj_t * pObj ) { return pObj->Id; } +static inline int Ivy_ObjTravId( Ivy_Obj_t * pObj ) { return pObj->TravId; } +static inline int Ivy_ObjPhase( Ivy_Obj_t * pObj ) { return pObj->fPhase; } +static inline int Ivy_ObjExorFanout( Ivy_Obj_t * pObj ) { return pObj->fExFan; } +static inline int Ivy_ObjRefs( Ivy_Obj_t * pObj ) { return pObj->nRefs; } +static inline void Ivy_ObjRefsInc( Ivy_Obj_t * pObj ) { pObj->nRefs++; } +static inline void Ivy_ObjRefsDec( Ivy_Obj_t * pObj ) { assert( pObj->nRefs > 0 ); pObj->nRefs--; } +static inline int Ivy_ObjFaninId0( Ivy_Obj_t * pObj ) { return pObj->pFanin0? Ivy_ObjId(Ivy_Regular(pObj->pFanin0)) : 0; } +static inline int Ivy_ObjFaninId1( Ivy_Obj_t * pObj ) { return pObj->pFanin1? Ivy_ObjId(Ivy_Regular(pObj->pFanin1)) : 0; } +static inline int Ivy_ObjFaninC0( Ivy_Obj_t * pObj ) { return Ivy_IsComplement(pObj->pFanin0); } +static inline int Ivy_ObjFaninC1( Ivy_Obj_t * pObj ) { return Ivy_IsComplement(pObj->pFanin1); } +static inline Ivy_Obj_t * Ivy_ObjFanin0( Ivy_Obj_t * pObj ) { return Ivy_Regular(pObj->pFanin0); } +static inline Ivy_Obj_t * Ivy_ObjFanin1( Ivy_Obj_t * pObj ) { return Ivy_Regular(pObj->pFanin1); } +static inline Ivy_Obj_t * Ivy_ObjChild0( Ivy_Obj_t * pObj ) { return pObj->pFanin0; } +static inline Ivy_Obj_t * Ivy_ObjChild1( Ivy_Obj_t * pObj ) { return pObj->pFanin1; } +static inline Ivy_Obj_t * Ivy_ObjChild0Equiv( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return Ivy_ObjFanin0(pObj)? Ivy_NotCond(Ivy_ObjFanin0(pObj)->pEquiv, Ivy_ObjFaninC0(pObj)) : NULL; } +static inline Ivy_Obj_t * Ivy_ObjChild1Equiv( Ivy_Obj_t * pObj ) { assert( !Ivy_IsComplement(pObj) ); return Ivy_ObjFanin1(pObj)? Ivy_NotCond(Ivy_ObjFanin1(pObj)->pEquiv, Ivy_ObjFaninC1(pObj)) : NULL; } +static inline Ivy_Obj_t * Ivy_ObjEquiv( Ivy_Obj_t * pObj ) { return Ivy_Regular(pObj)->pEquiv? Ivy_NotCond(Ivy_Regular(pObj)->pEquiv, Ivy_IsComplement(pObj)) : NULL; } +static inline int Ivy_ObjLevel( Ivy_Obj_t * pObj ) { return pObj->Level; } +static inline int Ivy_ObjLevelNew( Ivy_Obj_t * pObj ) { return 1 + Ivy_ObjIsExor(pObj) + IVY_MAX(Ivy_ObjFanin0(pObj)->Level, Ivy_ObjFanin1(pObj)->Level); } +static inline int Ivy_ObjFaninPhase( Ivy_Obj_t * pObj ) { return Ivy_IsComplement(pObj)? !Ivy_Regular(pObj)->fPhase : pObj->fPhase; } + +static inline void Ivy_ObjClean( Ivy_Obj_t * pObj ) +{ + int IdSaved = pObj->Id; + memset( pObj, 0, sizeof(Ivy_Obj_t) ); + pObj->Id = IdSaved; +} +static inline void Ivy_ObjOverwrite( Ivy_Obj_t * pBase, Ivy_Obj_t * pData ) +{ + int IdSaved = pBase->Id; + memcpy( pBase, pData, sizeof(Ivy_Obj_t) ); + pBase->Id = IdSaved; +} +static inline int Ivy_ObjWhatFanin( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanin ) +{ + if ( Ivy_ObjFanin0(pObj) == pFanin ) return 0; + if ( Ivy_ObjFanin1(pObj) == pFanin ) return 1; + assert(0); return -1; +} +static inline int Ivy_ObjFanoutC( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) +{ + if ( Ivy_ObjFanin0(pFanout) == pObj ) return Ivy_ObjFaninC0(pObj); + if ( Ivy_ObjFanin1(pFanout) == pObj ) return Ivy_ObjFaninC1(pObj); + assert(0); return -1; +} + +// create the ghost of the new node +static inline Ivy_Obj_t * Ivy_ObjCreateGhost( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type, Ivy_Init_t Init ) +{ + Ivy_Obj_t * pGhost, * pTemp; + assert( Type != IVY_AND || !Ivy_ObjIsConst1(Ivy_Regular(p0)) ); + assert( p1 == NULL || !Ivy_ObjIsConst1(Ivy_Regular(p1)) ); + assert( Type == IVY_PI || Ivy_Regular(p0) != Ivy_Regular(p1) ); + assert( Type != IVY_LATCH || !Ivy_IsComplement(p0) ); +// assert( p1 == NULL || (!Ivy_ObjIsLatch(Ivy_Regular(p0)) || !Ivy_ObjIsLatch(Ivy_Regular(p1))) ); + pGhost = Ivy_ManGhost(p); + pGhost->Type = Type; + pGhost->Init = Init; + pGhost->pFanin0 = p0; + pGhost->pFanin1 = p1; + if ( p1 && Ivy_ObjFaninId0(pGhost) > Ivy_ObjFaninId1(pGhost) ) + pTemp = pGhost->pFanin0, pGhost->pFanin0 = pGhost->pFanin1, pGhost->pFanin1 = pTemp; + return pGhost; +} + +// get the complemented initial state +static Ivy_Init_t Ivy_InitNotCond( Ivy_Init_t Init, int fCompl ) +{ + assert( Init != IVY_INIT_NONE ); + if ( fCompl == 0 ) + return Init; + if ( Init == IVY_INIT_0 ) + return IVY_INIT_1; + if ( Init == IVY_INIT_1 ) + return IVY_INIT_0; + return IVY_INIT_DC; +} + +// get the initial state after forward retiming over AND gate +static Ivy_Init_t Ivy_InitAnd( Ivy_Init_t InitA, Ivy_Init_t InitB ) +{ + assert( InitA != IVY_INIT_NONE && InitB != IVY_INIT_NONE ); + if ( InitA == IVY_INIT_0 || InitB == IVY_INIT_0 ) + return IVY_INIT_0; + if ( InitA == IVY_INIT_DC || InitB == IVY_INIT_DC ) + return IVY_INIT_DC; + return IVY_INIT_1; +} + +// get the initial state after forward retiming over EXOR gate +static Ivy_Init_t Ivy_InitExor( Ivy_Init_t InitA, Ivy_Init_t InitB ) +{ + assert( InitA != IVY_INIT_NONE && InitB != IVY_INIT_NONE ); + if ( InitA == IVY_INIT_DC || InitB == IVY_INIT_DC ) + return IVY_INIT_DC; + if ( InitA == IVY_INIT_0 && InitB == IVY_INIT_1 ) + return IVY_INIT_1; + if ( InitA == IVY_INIT_1 && InitB == IVY_INIT_0 ) + return IVY_INIT_1; + return IVY_INIT_0; +} + +// internal memory manager +static inline Ivy_Obj_t * Ivy_ManFetchMemory( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pTemp; + if ( p->pListFree == NULL ) + Ivy_ManAddMemory( p ); + pTemp = p->pListFree; + p->pListFree = *((Ivy_Obj_t **)pTemp); + memset( pTemp, 0, sizeof(Ivy_Obj_t) ); + return pTemp; +} +static inline void Ivy_ManRecycleMemory( Ivy_Man_t * p, Ivy_Obj_t * pEntry ) +{ + pEntry->Type = IVY_NONE; // distinquishes dead node from live node + *((Ivy_Obj_t **)pEntry) = p->pListFree; + p->pListFree = pEntry; +} + + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +// iterator over the primary inputs +#define Ivy_ManForEachPi( p, pObj, i ) \ + Vec_PtrForEachEntry( Ivy_Obj_t *, p->vPis, pObj, i ) +// iterator over the primary outputs +#define Ivy_ManForEachPo( p, pObj, i ) \ + Vec_PtrForEachEntry( Ivy_Obj_t *, p->vPos, pObj, i ) +// iterator over all objects, including those currently not used +#define Ivy_ManForEachObj( p, pObj, i ) \ + Vec_PtrForEachEntry( Ivy_Obj_t *, p->vObjs, pObj, i ) if ( (pObj) == NULL ) {} else +// iterator over the combinational inputs +#define Ivy_ManForEachCi( p, pObj, i ) \ + Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsCi(pObj) ) {} else +// iterator over the combinational outputs +#define Ivy_ManForEachCo( p, pObj, i ) \ + Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsCo(pObj) ) {} else +// iterator over logic nodes (AND and EXOR gates) +#define Ivy_ManForEachNode( p, pObj, i ) \ + Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsNode(pObj) ) {} else +// iterator over logic latches +#define Ivy_ManForEachLatch( p, pObj, i ) \ + Ivy_ManForEachObj( p, pObj, i ) if ( !Ivy_ObjIsLatch(pObj) ) {} else +// iterator over the nodes whose IDs are stored in the array +#define Ivy_ManForEachNodeVec( p, vIds, pObj, i ) \ + for ( i = 0; i < Vec_IntSize(vIds) && ((pObj) = Ivy_ManObj(p, Vec_IntEntry(vIds,i))); i++ ) +// iterator over the fanouts of an object +#define Ivy_ObjForEachFanout( p, pObj, vArray, pFanout, i ) \ + for ( i = 0, Ivy_ObjCollectFanouts(p, pObj, vArray); \ + i < Vec_PtrSize(vArray) && ((pFanout) = (Ivy_Obj_t *)Vec_PtrEntry(vArray,i)); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== ivyBalance.c ========================================================*/ +extern Ivy_Man_t * Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel ); +extern Ivy_Obj_t * Ivy_NodeBalanceBuildSuper( Ivy_Man_t * p, Vec_Ptr_t * vSuper, Ivy_Type_t Type, int fUpdateLevel ); +/*=== ivyCanon.c ========================================================*/ +extern Ivy_Obj_t * Ivy_CanonAnd( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); +extern Ivy_Obj_t * Ivy_CanonExor( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); +extern Ivy_Obj_t * Ivy_CanonLatch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init ); +/*=== ivyCheck.c ========================================================*/ +extern int Ivy_ManCheck( Ivy_Man_t * p ); +extern int Ivy_ManCheckFanoutNums( Ivy_Man_t * p ); +extern int Ivy_ManCheckFanouts( Ivy_Man_t * p ); +extern int Ivy_ManCheckChoices( Ivy_Man_t * p ); +/*=== ivyCut.c ==========================================================*/ +extern void Ivy_ManSeqFindCut( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSize ); +extern Ivy_Store_t * Ivy_NodeFindCutsAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves ); +/*=== ivyDfs.c ==========================================================*/ +extern Vec_Int_t * Ivy_ManDfs( Ivy_Man_t * p ); +extern Vec_Int_t * Ivy_ManDfsSeq( Ivy_Man_t * p, Vec_Int_t ** pvLatches ); +extern void Ivy_ManCollectCone( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone ); +extern Vec_Vec_t * Ivy_ManLevelize( Ivy_Man_t * p ); +extern Vec_Int_t * Ivy_ManRequiredLevels( Ivy_Man_t * p ); +extern int Ivy_ManIsAcyclic( Ivy_Man_t * p ); +extern int Ivy_ManSetLevels( Ivy_Man_t * p, int fHaig ); +/*=== ivyDsd.c ==========================================================*/ +extern int Ivy_TruthDsd( unsigned uTruth, Vec_Int_t * vTree ); +extern void Ivy_TruthDsdPrint( FILE * pFile, Vec_Int_t * vTree ); +extern unsigned Ivy_TruthDsdCompute( Vec_Int_t * vTree ); +extern void Ivy_TruthDsdComputePrint( unsigned uTruth ); +extern Ivy_Obj_t * Ivy_ManDsdConstruct( Ivy_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vTree ); +/*=== ivyFanout.c ==========================================================*/ +extern void Ivy_ManStartFanout( Ivy_Man_t * p ); +extern void Ivy_ManStopFanout( Ivy_Man_t * p ); +extern void Ivy_ObjAddFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ); +extern void Ivy_ObjDeleteFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ); +extern void Ivy_ObjPatchFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFanoutOld, Ivy_Obj_t * pFanoutNew ); +extern void Ivy_ObjCollectFanouts( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vArray ); +extern Ivy_Obj_t * Ivy_ObjReadFirstFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern int Ivy_ObjFanoutNum( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +/*=== ivyFastMap.c =============================================================*/ +extern void Ivy_FastMapPerform( Ivy_Man_t * pAig, int nLimit, int fRecovery, int fVerbose ); +extern void Ivy_FastMapStop( Ivy_Man_t * pAig ); +extern void Ivy_FastMapReadSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Int_t * vLeaves ); +extern void Ivy_FastMapReverseLevel( Ivy_Man_t * pAig ); +/*=== ivyFraig.c ==========================================================*/ +extern int Ivy_FraigProve( Ivy_Man_t ** ppManAig, void * pPars ); +extern Ivy_Man_t * Ivy_FraigPerform( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); +extern Ivy_Man_t * Ivy_FraigMiter( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); +extern void Ivy_FraigParamsDefault( Ivy_FraigParams_t * pParams ); +/*=== ivyHaig.c ==========================================================*/ +extern void Ivy_ManHaigStart( Ivy_Man_t * p, int fVerbose ); +extern void Ivy_ManHaigTrasfer( Ivy_Man_t * p, Ivy_Man_t * pNew ); +extern void Ivy_ManHaigStop( Ivy_Man_t * p ); +extern void Ivy_ManHaigPostprocess( Ivy_Man_t * p, int fVerbose ); +extern void Ivy_ManHaigCreateObj( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern void Ivy_ManHaigCreateChoice( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew ); +extern void Ivy_ManHaigSimulate( Ivy_Man_t * p ); +/*=== ivyMan.c ==========================================================*/ +extern Ivy_Man_t * Ivy_ManStart(); +extern Ivy_Man_t * Ivy_ManStartFrom( Ivy_Man_t * p ); +extern Ivy_Man_t * Ivy_ManDup( Ivy_Man_t * p ); +extern Ivy_Man_t * Ivy_ManFrames( Ivy_Man_t * pMan, int nLatches, int nFrames, int fInit, Vec_Ptr_t ** pvMapping ); +extern void Ivy_ManStop( Ivy_Man_t * p ); +extern int Ivy_ManCleanup( Ivy_Man_t * p ); +extern int Ivy_ManPropagateBuffers( Ivy_Man_t * p, int fUpdateLevel ); +extern void Ivy_ManPrintStats( Ivy_Man_t * p ); +extern void Ivy_ManMakeSeq( Ivy_Man_t * p, int nLatches, int * pInits ); +/*=== ivyMem.c ==========================================================*/ +extern void Ivy_ManStartMemory( Ivy_Man_t * p ); +extern void Ivy_ManStopMemory( Ivy_Man_t * p ); +/*=== ivyMulti.c ==========================================================*/ +extern Ivy_Obj_t * Ivy_Multi( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); +extern Ivy_Obj_t * Ivy_Multi1( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); +extern Ivy_Obj_t * Ivy_Multi_rec( Ivy_Man_t * p, Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type ); +extern Ivy_Obj_t * Ivy_MultiBalance_rec( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); +extern int Ivy_MultiPlus( Ivy_Man_t * p, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Ivy_Type_t Type, int nLimit, Vec_Ptr_t * vSol ); +/*=== ivyObj.c ==========================================================*/ +extern Ivy_Obj_t * Ivy_ObjCreatePi( Ivy_Man_t * p ); +extern Ivy_Obj_t * Ivy_ObjCreatePo( Ivy_Man_t * p, Ivy_Obj_t * pDriver ); +extern Ivy_Obj_t * Ivy_ObjCreate( Ivy_Man_t * p, Ivy_Obj_t * pGhost ); +extern void Ivy_ObjConnect( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFan0, Ivy_Obj_t * pFan1 ); +extern void Ivy_ObjDisconnect( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern void Ivy_ObjPatchFanin0( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFaninNew ); +extern void Ivy_ObjDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ); +extern void Ivy_ObjDelete_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ); +extern void Ivy_ObjReplace( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew, int fDeleteOld, int fFreeTop, int fUpdateLevel ); +extern void Ivy_NodeFixBufferFanins( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel ); +/*=== ivyOper.c =========================================================*/ +extern Ivy_Obj_t * Ivy_Oper( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type ); +extern Ivy_Obj_t * Ivy_And( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); +extern Ivy_Obj_t * Ivy_Or( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); +extern Ivy_Obj_t * Ivy_Exor( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ); +extern Ivy_Obj_t * Ivy_Mux( Ivy_Man_t * p, Ivy_Obj_t * pC, Ivy_Obj_t * p1, Ivy_Obj_t * p0 ); +extern Ivy_Obj_t * Ivy_Maj( Ivy_Man_t * p, Ivy_Obj_t * pA, Ivy_Obj_t * pB, Ivy_Obj_t * pC ); +extern Ivy_Obj_t * Ivy_Miter( Ivy_Man_t * p, Vec_Ptr_t * vPairs ); +extern Ivy_Obj_t * Ivy_Latch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init ); +/*=== ivyResyn.c =========================================================*/ +extern Ivy_Man_t * Ivy_ManResyn0( Ivy_Man_t * p, int fUpdateLevel, int fVerbose ); +extern Ivy_Man_t * Ivy_ManResyn( Ivy_Man_t * p, int fUpdateLevel, int fVerbose ); +extern Ivy_Man_t * Ivy_ManRwsat( Ivy_Man_t * pMan, int fVerbose ); +/*=== ivyRewrite.c =========================================================*/ +extern int Ivy_ManSeqRewrite( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost ); +extern int Ivy_ManRewriteAlg( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost ); +extern int Ivy_ManRewritePre( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost, int fVerbose ); +/*=== ivySeq.c =========================================================*/ +extern int Ivy_ManRewriteSeq( Ivy_Man_t * p, int fUseZeroCost, int fVerbose ); +/*=== ivyShow.c =========================================================*/ +extern void Ivy_ManShow( Ivy_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ); +/*=== ivyTable.c ========================================================*/ +extern Ivy_Obj_t * Ivy_TableLookup( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern void Ivy_TableInsert( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern void Ivy_TableDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern void Ivy_TableUpdate( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ObjIdNew ); +extern int Ivy_TableCountEntries( Ivy_Man_t * p ); +extern void Ivy_TableProfile( Ivy_Man_t * p ); +/*=== ivyUtil.c =========================================================*/ +extern void Ivy_ManIncrementTravId( Ivy_Man_t * p ); +extern void Ivy_ManCleanTravId( Ivy_Man_t * p ); +extern unsigned * Ivy_ManCutTruth( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Int_t * vTruth ); +extern void Ivy_ManCollectCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ); +extern Vec_Int_t * Ivy_ManLatches( Ivy_Man_t * p ); +extern int Ivy_ManLevels( Ivy_Man_t * p ); +extern void Ivy_ManResetLevels( Ivy_Man_t * p ); +extern int Ivy_ObjMffcLabel( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern void Ivy_ObjUpdateLevel_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj ); +extern void Ivy_ObjUpdateLevelR_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ReqNew ); +extern int Ivy_ObjIsMuxType( Ivy_Obj_t * pObj ); +extern Ivy_Obj_t * Ivy_ObjRecognizeMux( Ivy_Obj_t * pObj, Ivy_Obj_t ** ppObjT, Ivy_Obj_t ** ppObjE ); +extern Ivy_Obj_t * Ivy_ObjReal( Ivy_Obj_t * pObj ); +extern void Ivy_ObjPrintVerbose( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fHaig ); +extern void Ivy_ManPrintVerbose( Ivy_Man_t * p, int fHaig ); +extern int Ivy_CutTruthPrint( Ivy_Man_t * p, Ivy_Cut_t * pCut, unsigned uTruth ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/yosys/abc/src/aig/ivy/ivyBalance.c b/yosys/abc/src/aig/ivy/ivyBalance.c new file mode 100644 index 00000000000..2bcc69eed27 --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivyBalance.c @@ -0,0 +1,414 @@ +/**CFile**************************************************************** + + FileName [ivyBalance.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Algebraic AIG balancing.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyBalance.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Ivy_NodeBalance_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level, int fUpdateLevel ); +static Vec_Ptr_t * Ivy_NodeBalanceCone( Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level ); +static int Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ); +static void Ivy_NodeBalancePermute( Ivy_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ); +static void Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Ivy_Obj_t * pObj ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs algebraic balancing of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManBalance( Ivy_Man_t * p, int fUpdateLevel ) +{ + Ivy_Man_t * pNew; + Ivy_Obj_t * pObj, * pDriver; + Vec_Vec_t * vStore; + int i, NewNodeId; + // clean the old manager + Ivy_ManCleanTravId( p ); + // create the new manager + pNew = Ivy_ManStart(); + // map the nodes + Ivy_ManConst1(p)->TravId = Ivy_EdgeFromNode( Ivy_ManConst1(pNew) ); + Ivy_ManForEachPi( p, pObj, i ) + pObj->TravId = Ivy_EdgeFromNode( Ivy_ObjCreatePi(pNew) ); + // if HAIG is defined, trasfer the pointers to the PIs/latches +// if ( p->pHaig ) +// Ivy_ManHaigTrasfer( p, pNew ); + // balance the AIG + vStore = Vec_VecAlloc( 50 ); + Ivy_ManForEachPo( p, pObj, i ) + { + pDriver = Ivy_ObjReal( Ivy_ObjChild0(pObj) ); + NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular(pDriver), vStore, 0, fUpdateLevel ); + NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement(pDriver) ); + Ivy_ObjCreatePo( pNew, Ivy_EdgeToNode(pNew, NewNodeId) ); + } + Vec_VecFree( vStore ); + if ( (i = Ivy_ManCleanup( pNew )) ) + { +// printf( "Cleanup after balancing removed %d dangling nodes.\n", i ); + } + // check the resulting AIG + if ( !Ivy_ManCheck(pNew) ) + printf( "Ivy_ManBalance(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeCompareLevelsDecrease( Ivy_Obj_t ** pp1, Ivy_Obj_t ** pp2 ) +{ + int Diff = Ivy_Regular(*pp1)->Level - Ivy_Regular(*pp2)->Level; + if ( Diff > 0 ) + return -1; + if ( Diff < 0 ) + return 1; + Diff = Ivy_Regular(*pp1)->Id - Ivy_Regular(*pp2)->Id; + if ( Diff > 0 ) + return -1; + if ( Diff < 0 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns the ID of new node constructed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeBalance_rec( Ivy_Man_t * pNew, Ivy_Obj_t * pObjOld, Vec_Vec_t * vStore, int Level, int fUpdateLevel ) +{ + Ivy_Obj_t * pObjNew; + Vec_Ptr_t * vSuper; + int i, NewNodeId; + assert( !Ivy_IsComplement(pObjOld) ); + assert( !Ivy_ObjIsBuf(pObjOld) ); + // return if the result is known + if ( Ivy_ObjIsConst1(pObjOld) ) + return pObjOld->TravId; + if ( pObjOld->TravId ) + return pObjOld->TravId; + assert( Ivy_ObjIsNode(pObjOld) ); + // get the implication supergate + vSuper = Ivy_NodeBalanceCone( pObjOld, vStore, Level ); + if ( vSuper->nSize == 0 ) + { // it means that the supergate contains two nodes in the opposite polarity + pObjOld->TravId = Ivy_EdgeFromNode( Ivy_ManConst0(pNew) ); + return pObjOld->TravId; + } + if ( vSuper->nSize < 2 ) + printf( "BUG!\n" ); + // for each old node, derive the new well-balanced node + for ( i = 0; i < vSuper->nSize; i++ ) + { + NewNodeId = Ivy_NodeBalance_rec( pNew, Ivy_Regular((Ivy_Obj_t *)vSuper->pArray[i]), vStore, Level + 1, fUpdateLevel ); + NewNodeId = Ivy_EdgeNotCond( NewNodeId, Ivy_IsComplement((Ivy_Obj_t *)vSuper->pArray[i]) ); + vSuper->pArray[i] = Ivy_EdgeToNode( pNew, NewNodeId ); + } + // build the supergate + pObjNew = Ivy_NodeBalanceBuildSuper( pNew, vSuper, Ivy_ObjType(pObjOld), fUpdateLevel ); + vSuper->nSize = 0; + // make sure the balanced node is not assigned + assert( pObjOld->TravId == 0 ); + pObjOld->TravId = Ivy_EdgeFromNode( pObjNew ); +// assert( pObjOld->Level >= Ivy_Regular(pObjNew)->Level ); + return pObjOld->TravId; +} + +/**Function************************************************************* + + Synopsis [Builds implication supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_NodeBalanceBuildSuper( Ivy_Man_t * p, Vec_Ptr_t * vSuper, Ivy_Type_t Type, int fUpdateLevel ) +{ + Ivy_Obj_t * pObj1, * pObj2; + int LeftBound; + assert( vSuper->nSize > 1 ); + // sort the new nodes by level in the decreasing order + Vec_PtrSort( vSuper, (int (*)(const void *, const void *))Ivy_NodeCompareLevelsDecrease ); + // balance the nodes + while ( vSuper->nSize > 1 ) + { + // find the left bound on the node to be paired + LeftBound = (!fUpdateLevel)? 0 : Ivy_NodeBalanceFindLeft( vSuper ); + // find the node that can be shared (if no such node, randomize choice) + Ivy_NodeBalancePermute( p, vSuper, LeftBound, Type == IVY_EXOR ); + // pull out the last two nodes + pObj1 = (Ivy_Obj_t *)Vec_PtrPop(vSuper); + pObj2 = (Ivy_Obj_t *)Vec_PtrPop(vSuper); + Ivy_NodeBalancePushUniqueOrderByLevel( vSuper, Ivy_Oper(p, pObj1, pObj2, Type) ); + } + return (Ivy_Obj_t *)Vec_PtrEntry(vSuper, 0); +} + +/**Function************************************************************* + + Synopsis [Collects the nodes of the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeBalanceCone_rec( Ivy_Obj_t * pRoot, Ivy_Obj_t * pObj, Vec_Ptr_t * vSuper ) +{ + int RetValue1, RetValue2, i; + // check if the node is visited + if ( Ivy_Regular(pObj)->fMarkB ) + { + // check if the node occurs in the same polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == pObj ) + return 1; + // check if the node is present in the opposite polarity + for ( i = 0; i < vSuper->nSize; i++ ) + if ( vSuper->pArray[i] == Ivy_Not(pObj) ) + return -1; + assert( 0 ); + return 0; + } + // if the new node is complemented or a PI, another gate begins + if ( pObj != pRoot && (Ivy_IsComplement(pObj) || Ivy_ObjType(pObj) != Ivy_ObjType(pRoot) || Ivy_ObjRefs(pObj) > 1 || Vec_PtrSize(vSuper) > 10000) ) + { + Vec_PtrPush( vSuper, pObj ); + Ivy_Regular(pObj)->fMarkB = 1; + return 0; + } + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjIsNode(pObj) ); + // go through the branches + RetValue1 = Ivy_NodeBalanceCone_rec( pRoot, Ivy_ObjReal( Ivy_ObjChild0(pObj) ), vSuper ); + RetValue2 = Ivy_NodeBalanceCone_rec( pRoot, Ivy_ObjReal( Ivy_ObjChild1(pObj) ), vSuper ); + if ( RetValue1 == -1 || RetValue2 == -1 ) + return -1; + // return 1 if at least one branch has a duplicate + return RetValue1 || RetValue2; +} + +/**Function************************************************************* + + Synopsis [Collects the nodes of the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Ivy_NodeBalanceCone( Ivy_Obj_t * pObj, Vec_Vec_t * vStore, int Level ) +{ + Vec_Ptr_t * vNodes; + int RetValue, i; + assert( !Ivy_IsComplement(pObj) ); + // extend the storage + if ( Vec_VecSize( vStore ) <= Level ) + Vec_VecPush( vStore, Level, 0 ); + // get the temporary array of nodes + vNodes = Vec_VecEntry( vStore, Level ); + Vec_PtrClear( vNodes ); + // collect the nodes in the implication supergate + RetValue = Ivy_NodeBalanceCone_rec( pObj, pObj, vNodes ); + assert( vNodes->nSize > 1 ); + // unmark the visited nodes + Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pObj, i ) + Ivy_Regular(pObj)->fMarkB = 0; + // if we found the node and its complement in the same implication supergate, + // return empty set of nodes (meaning that we should use constant-0 node) + if ( RetValue == -1 ) + vNodes->nSize = 0; + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Finds the left bound on the next candidate to be paired.] + + Description [The nodes in the array are in the decreasing order of levels. + The last node in the array has the smallest level. By default it would be paired + with the next node on the left. However, it may be possible to pair it with some + other node on the left, in such a way that the new node is shared. This procedure + finds the index of the left-most node, which can be paired with the last node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeBalanceFindLeft( Vec_Ptr_t * vSuper ) +{ + Ivy_Obj_t * pObjRight, * pObjLeft; + int Current; + // if two or less nodes, pair with the first + if ( Vec_PtrSize(vSuper) < 3 ) + return 0; + // set the pointer to the one before the last + Current = Vec_PtrSize(vSuper) - 2; + pObjRight = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, Current ); + // go through the nodes to the left of this one + for ( Current--; Current >= 0; Current-- ) + { + // get the next node on the left + pObjLeft = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, Current ); + // if the level of this node is different, quit the loop + if ( Ivy_Regular(pObjLeft)->Level != Ivy_Regular(pObjRight)->Level ) + break; + } + Current++; + // get the node, for which the equality holds + pObjLeft = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, Current ); + assert( Ivy_Regular(pObjLeft)->Level == Ivy_Regular(pObjRight)->Level ); + return Current; +} + +/**Function************************************************************* + + Synopsis [Moves closer to the end the node that is best for sharing.] + + Description [If there is no node with sharing, randomly chooses one of + the legal nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeBalancePermute( Ivy_Man_t * p, Vec_Ptr_t * vSuper, int LeftBound, int fExor ) +{ + Ivy_Obj_t * pObj1, * pObj2, * pObj3, * pGhost; + int RightBound, i; + // get the right bound + RightBound = Vec_PtrSize(vSuper) - 2; + assert( LeftBound <= RightBound ); + if ( LeftBound == RightBound ) + return; + // get the two last nodes + pObj1 = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, RightBound + 1 ); + pObj2 = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, RightBound ); + if ( Ivy_Regular(pObj1) == p->pConst1 || Ivy_Regular(pObj2) == p->pConst1 ) + return; + // find the first node that can be shared + for ( i = RightBound; i >= LeftBound; i-- ) + { + pObj3 = (Ivy_Obj_t *)Vec_PtrEntry( vSuper, i ); + if ( Ivy_Regular(pObj3) == p->pConst1 ) + { + Vec_PtrWriteEntry( vSuper, i, pObj2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); + return; + } + pGhost = Ivy_ObjCreateGhost( p, pObj1, pObj3, fExor? IVY_EXOR : IVY_AND, IVY_INIT_NONE ); + if ( Ivy_TableLookup( p, pGhost ) ) + { + if ( pObj3 == pObj2 ) + return; + Vec_PtrWriteEntry( vSuper, i, pObj2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); + return; + } + } +/* + // we did not find the node to share, randomize choice + { + int Choice = rand() % (RightBound - LeftBound + 1); + pObj3 = Vec_PtrEntry( vSuper, LeftBound + Choice ); + if ( pObj3 == pObj2 ) + return; + Vec_PtrWriteEntry( vSuper, LeftBound + Choice, pObj2 ); + Vec_PtrWriteEntry( vSuper, RightBound, pObj3 ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Inserts a new node in the order by levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeBalancePushUniqueOrderByLevel( Vec_Ptr_t * vStore, Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pObj1, * pObj2; + int i; + if ( Vec_PtrPushUnique(vStore, pObj) ) + return; + // find the p of the node + for ( i = vStore->nSize-1; i > 0; i-- ) + { + pObj1 = (Ivy_Obj_t *)vStore->pArray[i ]; + pObj2 = (Ivy_Obj_t *)vStore->pArray[i-1]; + if ( Ivy_Regular(pObj1)->Level <= Ivy_Regular(pObj2)->Level ) + break; + vStore->pArray[i ] = pObj2; + vStore->pArray[i-1] = pObj1; + } +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/ivyCanon.c b/yosys/abc/src/aig/ivy/ivyCanon.c new file mode 100644 index 00000000000..34ed781f297 --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivyCanon.c @@ -0,0 +1,149 @@ +/**CFile**************************************************************** + + FileName [ivyCanon.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Finding canonical form of objects.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyCanon.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static Ivy_Obj_t * Ivy_TableLookupPair_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1, int fCompl0, int fCompl1, Ivy_Type_t Type ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates the canonical form of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_CanonPair_rec( Ivy_Man_t * p, Ivy_Obj_t * pGhost ) +{ + Ivy_Obj_t * pResult, * pLat0, * pLat1; + Ivy_Init_t Init, Init0, Init1; + int fCompl0, fCompl1; + Ivy_Type_t Type; + assert( Ivy_ObjIsNode(pGhost) ); + assert( Ivy_ObjIsAnd(pGhost) || (!Ivy_ObjFaninC0(pGhost) && !Ivy_ObjFaninC1(pGhost)) ); + assert( Ivy_ObjFaninId0(pGhost) != 0 && Ivy_ObjFaninId1(pGhost) != 0 ); + // consider the case when the pair is canonical + if ( !Ivy_ObjIsLatch(Ivy_ObjFanin0(pGhost)) || !Ivy_ObjIsLatch(Ivy_ObjFanin1(pGhost)) ) + { + if ( (pResult = Ivy_TableLookup( p, pGhost )) ) + return pResult; + return Ivy_ObjCreate( p, pGhost ); + } + /// remember the latches + pLat0 = Ivy_ObjFanin0(pGhost); + pLat1 = Ivy_ObjFanin1(pGhost); + // remember type and compls + Type = Ivy_ObjType(pGhost); + fCompl0 = Ivy_ObjFaninC0(pGhost); + fCompl1 = Ivy_ObjFaninC1(pGhost); + // call recursively + pResult = Ivy_Oper( p, Ivy_NotCond(Ivy_ObjFanin0(pLat0), fCompl0), Ivy_NotCond(Ivy_ObjFanin0(pLat1), fCompl1), Type ); + // build latch on top of this + Init0 = Ivy_InitNotCond( Ivy_ObjInit(pLat0), fCompl0 ); + Init1 = Ivy_InitNotCond( Ivy_ObjInit(pLat1), fCompl1 ); + Init = (Type == IVY_AND)? Ivy_InitAnd(Init0, Init1) : Ivy_InitExor(Init0, Init1); + return Ivy_Latch( p, pResult, Init ); +} + +/**Function************************************************************* + + Synopsis [Creates the canonical form of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_CanonAnd( Ivy_Man_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ) +{ + Ivy_Obj_t * pGhost, * pResult; + pGhost = Ivy_ObjCreateGhost( p, pObj0, pObj1, IVY_AND, IVY_INIT_NONE ); + pResult = Ivy_CanonPair_rec( p, pGhost ); + return pResult; +} + +/**Function************************************************************* + + Synopsis [Creates the canonical form of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_CanonExor( Ivy_Man_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ) +{ + Ivy_Obj_t * pGhost, * pResult; + int fCompl = Ivy_IsComplement(pObj0) ^ Ivy_IsComplement(pObj1); + pObj0 = Ivy_Regular(pObj0); + pObj1 = Ivy_Regular(pObj1); + pGhost = Ivy_ObjCreateGhost( p, pObj0, pObj1, IVY_EXOR, IVY_INIT_NONE ); + pResult = Ivy_CanonPair_rec( p, pGhost ); + return Ivy_NotCond( pResult, fCompl ); +} + +/**Function************************************************************* + + Synopsis [Creates the canonical form of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_CanonLatch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init ) +{ + Ivy_Obj_t * pGhost, * pResult; + int fCompl = Ivy_IsComplement(pObj); + pObj = Ivy_Regular(pObj); + pGhost = Ivy_ObjCreateGhost( p, pObj, NULL, IVY_LATCH, Ivy_InitNotCond(Init, fCompl) ); + pResult = Ivy_TableLookup( p, pGhost ); + if ( pResult == NULL ) + pResult = Ivy_ObjCreate( p, pGhost ); + return Ivy_NotCond( pResult, fCompl ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/ivyCheck.c b/yosys/abc/src/aig/ivy/ivyCheck.c new file mode 100644 index 00000000000..d8ebb198fef --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivyCheck.c @@ -0,0 +1,278 @@ +/**CFile**************************************************************** + + FileName [ivyCheck.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [AIG checking procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyCheck.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks the consistency of the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManCheck( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj, * pObj2; + int i; + Ivy_ManForEachObj( p, pObj, i ) + { + // skip deleted nodes + if ( Ivy_ObjId(pObj) != i ) + { + printf( "Ivy_ManCheck: Node with ID %d is listed as number %d in the array of objects.\n", pObj->Id, i ); + return 0; + } + // consider the constant node and PIs + if ( i == 0 || Ivy_ObjIsPi(pObj) ) + { + if ( Ivy_ObjFaninId0(pObj) || Ivy_ObjFaninId1(pObj) || Ivy_ObjLevel(pObj) ) + { + printf( "Ivy_ManCheck: The AIG has non-standard constant or PI node with ID \"%d\".\n", pObj->Id ); + return 0; + } + continue; + } + if ( Ivy_ObjIsPo(pObj) ) + { + if ( Ivy_ObjFaninId1(pObj) ) + { + printf( "Ivy_ManCheck: The AIG has non-standard PO node with ID \"%d\".\n", pObj->Id ); + return 0; + } + continue; + } + if ( Ivy_ObjIsBuf(pObj) ) + { + if ( Ivy_ObjFanin1(pObj) ) + { + printf( "Ivy_ManCheck: The buffer with ID \"%d\" contains second fanin.\n", pObj->Id ); + return 0; + } + continue; + } + if ( Ivy_ObjIsLatch(pObj) ) + { + if ( Ivy_ObjFanin1(pObj) ) + { + printf( "Ivy_ManCheck: The latch with ID \"%d\" contains second fanin.\n", pObj->Id ); + return 0; + } + if ( Ivy_ObjInit(pObj) == IVY_INIT_NONE ) + { + printf( "Ivy_ManCheck: The latch with ID \"%d\" does not have initial state.\n", pObj->Id ); + return 0; + } + pObj2 = Ivy_TableLookup( p, pObj ); + if ( pObj2 != pObj ) + printf( "Ivy_ManCheck: Latch with ID \"%d\" is not in the structural hashing table.\n", pObj->Id ); + continue; + } + // consider the AND node + if ( !Ivy_ObjFanin0(pObj) || !Ivy_ObjFanin1(pObj) ) + { + printf( "Ivy_ManCheck: The AIG has internal node \"%d\" with a NULL fanin.\n", pObj->Id ); + return 0; + } + if ( Ivy_ObjFaninId0(pObj) >= Ivy_ObjFaninId1(pObj) ) + { + printf( "Ivy_ManCheck: The AIG has node \"%d\" with a wrong ordering of fanins.\n", pObj->Id ); + return 0; + } + if ( Ivy_ObjLevel(pObj) != Ivy_ObjLevelNew(pObj) ) + printf( "Ivy_ManCheck: Node with ID \"%d\" has level %d but should have level %d.\n", pObj->Id, Ivy_ObjLevel(pObj), Ivy_ObjLevelNew(pObj) ); + pObj2 = Ivy_TableLookup( p, pObj ); + if ( pObj2 != pObj ) + printf( "Ivy_ManCheck: Node with ID \"%d\" is not in the structural hashing table.\n", pObj->Id ); + if ( Ivy_ObjRefs(pObj) == 0 ) + printf( "Ivy_ManCheck: Node with ID \"%d\" has no fanouts.\n", pObj->Id ); + // check fanouts + if ( p->fFanout && Ivy_ObjRefs(pObj) != Ivy_ObjFanoutNum(p, pObj) ) + printf( "Ivy_ManCheck: Node with ID \"%d\" has mismatch between the number of fanouts and refs.\n", pObj->Id ); + } + // count the number of nodes in the table + if ( Ivy_TableCountEntries(p) != Ivy_ManAndNum(p) + Ivy_ManExorNum(p) + Ivy_ManLatchNum(p) ) + { + printf( "Ivy_ManCheck: The number of nodes in the structural hashing table is wrong.\n" ); + return 0; + } +// if ( !Ivy_ManCheckFanouts(p) ) +// return 0; + if ( !Ivy_ManIsAcyclic(p) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Verifies the fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManCheckFanoutNums( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i, Counter = 0; + Ivy_ManForEachObj( p, pObj, i ) + if ( Ivy_ObjIsNode(pObj) ) + Counter += (Ivy_ObjRefs(pObj) == 0); + if ( Counter ) + printf( "Sequential AIG has %d dangling nodes.\n", Counter ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Verifies the fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManCheckFanouts( Ivy_Man_t * p ) +{ + Vec_Ptr_t * vFanouts; + Ivy_Obj_t * pObj, * pFanout, * pFanin; + int i, k, RetValue = 1; + if ( !p->fFanout ) + return 1; + vFanouts = Vec_PtrAlloc( 100 ); + // make sure every fanin is a fanout + Ivy_ManForEachObj( p, pObj, i ) + { + pFanin = Ivy_ObjFanin0(pObj); + if ( pFanin == NULL ) + continue; + Ivy_ObjForEachFanout( p, pFanin, vFanouts, pFanout, k ) + if ( pFanout == pObj ) + break; + if ( k == Vec_PtrSize(vFanouts) ) + { + printf( "Node %d is a fanin of node %d but the fanout is not there.\n", pFanin->Id, pObj->Id ); + RetValue = 0; + } + + pFanin = Ivy_ObjFanin1(pObj); + if ( pFanin == NULL ) + continue; + Ivy_ObjForEachFanout( p, pFanin, vFanouts, pFanout, k ) + if ( pFanout == pObj ) + break; + if ( k == Vec_PtrSize(vFanouts) ) + { + printf( "Node %d is a fanin of node %d but the fanout is not there.\n", pFanin->Id, pObj->Id ); + RetValue = 0; + } + // check that the previous fanout has the same fanin + if ( pObj->pPrevFan0 ) + { + if ( Ivy_ObjFanin0(pObj->pPrevFan0) != Ivy_ObjFanin0(pObj) && + Ivy_ObjFanin0(pObj->pPrevFan0) != Ivy_ObjFanin1(pObj) && + Ivy_ObjFanin1(pObj->pPrevFan0) != Ivy_ObjFanin0(pObj) && + Ivy_ObjFanin1(pObj->pPrevFan0) != Ivy_ObjFanin1(pObj) ) + { + printf( "Node %d has prev %d without common fanin.\n", pObj->Id, pObj->pPrevFan0->Id ); + RetValue = 0; + } + } + // check that the previous fanout has the same fanin + if ( pObj->pPrevFan1 ) + { + if ( Ivy_ObjFanin0(pObj->pPrevFan1) != Ivy_ObjFanin0(pObj) && + Ivy_ObjFanin0(pObj->pPrevFan1) != Ivy_ObjFanin1(pObj) && + Ivy_ObjFanin1(pObj->pPrevFan1) != Ivy_ObjFanin0(pObj) && + Ivy_ObjFanin1(pObj->pPrevFan1) != Ivy_ObjFanin1(pObj) ) + { + printf( "Node %d has prev %d without common fanin.\n", pObj->Id, pObj->pPrevFan1->Id ); + RetValue = 0; + } + } + } + // make sure every fanout is a fanin + Ivy_ManForEachObj( p, pObj, i ) + { + Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, k ) + if ( Ivy_ObjFanin0(pFanout) != pObj && Ivy_ObjFanin1(pFanout) != pObj ) + { + printf( "Node %d is a fanout of node %d but the fanin is not there.\n", pFanout->Id, pObj->Id ); + RetValue = 0; + } + } + Vec_PtrFree( vFanouts ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Checks that each choice node has exactly one node with fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManCheckChoices( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj, * pTemp; + int i; + Ivy_ManForEachObj( p->pHaig, pObj, i ) + { + if ( Ivy_ObjRefs(pObj) == 0 ) + continue; + // count the number of nodes in the loop + assert( !Ivy_IsComplement(pObj->pEquiv) ); + for ( pTemp = pObj->pEquiv; pTemp && pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + if ( Ivy_ObjRefs(pTemp) > 1 ) + printf( "Node %d has member %d in its equiv class with %d fanouts.\n", pObj->Id, pTemp->Id, Ivy_ObjRefs(pTemp) ); + } + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/ivyCut.c b/yosys/abc/src/aig/ivy/ivyCut.c new file mode 100644 index 00000000000..5b5957edef3 --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivyCut.c @@ -0,0 +1,995 @@ +/**CFile**************************************************************** + + FileName [ivyCut.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Computes reconvergence driven sequential cut.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyCut.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Ivy_NodeCutHashValue( int NodeId ) { return 1 << (NodeId % 31); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Evaluate the cost of removing the node from the set of leaves.] + + Description [Returns the number of new leaves that will be brought in. + Returns large number if the node cannot be removed from the set of leaves.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_NodeGetLeafCostOne( Ivy_Man_t * p, int Leaf, Vec_Int_t * vInside ) +{ + Ivy_Obj_t * pNode; + int nLatches, FaninLeaf, Cost; + // make sure leaf is not a contant node + assert( Leaf > 0 ); + // get the node + pNode = Ivy_ManObj( p, Ivy_LeafId(Leaf) ); + // cannot expand over the PI node + if ( Ivy_ObjIsPi(pNode) || Ivy_ObjIsConst1(pNode) ) + return 999; + // get the number of latches + nLatches = Ivy_LeafLat(Leaf) + Ivy_ObjIsLatch(pNode); + if ( nLatches > 15 ) + return 999; + // get the first fanin + FaninLeaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pNode), nLatches ); + Cost = FaninLeaf && (Vec_IntFind(vInside, FaninLeaf) == -1); + // quit if this is the one fanin node + if ( Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) ) + return Cost; + assert( Ivy_ObjIsNode(pNode) ); + // get the second fanin + FaninLeaf = Ivy_LeafCreate( Ivy_ObjFaninId1(pNode), nLatches ); + Cost += FaninLeaf && (Vec_IntFind(vInside, FaninLeaf) == -1); + return Cost; +} + +/**Function************************************************************* + + Synopsis [Builds reconvergence-driven cut by changing one leaf at a time.] + + Description [This procedure looks at the current leaves and tries to change + one leaf at a time in such a way that the cut grows as little as possible. + In evaluating the fanins, this procedure looks only at their immediate + predecessors (this is why it is called a one-level construction procedure).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManSeqFindCut_int( Ivy_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSizeLimit ) +{ + Ivy_Obj_t * pNode; + int CostBest, CostCur, Leaf, LeafBest, Next, nLatches, i; + int LeavesBest[10]; + int Counter; + + // add random selection of the best fanin!!! + + // find the best fanin + CostBest = 99; + LeafBest = -1; + Counter = -1; +//printf( "Evaluating fanins of the cut:\n" ); + Vec_IntForEachEntry( vFront, Leaf, i ) + { + CostCur = Ivy_NodeGetLeafCostOne( p, Leaf, vInside ); +//printf( " Fanin %s has cost %d.\n", Ivy_ObjName(pNode), CostCur ); + if ( CostBest > CostCur ) + { + CostBest = CostCur; + LeafBest = Leaf; + LeavesBest[0] = Leaf; + Counter = 1; + } + else if ( CostBest == CostCur ) + LeavesBest[Counter++] = Leaf; + + if ( CostBest <= 1 ) // can be if ( CostBest <= 1 ) + break; + } + if ( CostBest == 99 ) + return 0; +// return Ivy_NodeBuildCutLevelTwo_int( vInside, vFront, nFaninLimit ); + + assert( CostBest < 3 ); + if ( Vec_IntSize(vFront) - 1 + CostBest > nSizeLimit ) + return 0; +// return Ivy_NodeBuildCutLevelTwo_int( vInside, vFront, nFaninLimit ); + + assert( Counter > 0 ); +printf( "%d", Counter ); + + LeafBest = LeavesBest[rand() % Counter]; + + // remove the node from the array + assert( LeafBest >= 0 ); + Vec_IntRemove( vFront, LeafBest ); +//printf( "Removing fanin %s.\n", Ivy_ObjName(pNode) ); + + // get the node and its latches + pNode = Ivy_ManObj( p, Ivy_LeafId(LeafBest) ); + nLatches = Ivy_LeafLat(LeafBest) + Ivy_ObjIsLatch(pNode); + assert( Ivy_ObjIsNode(pNode) || Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) ); + + // add the left child to the fanins + Next = Ivy_LeafCreate( Ivy_ObjFaninId0(pNode), nLatches ); + if ( Next && Vec_IntFind(vInside, Next) == -1 ) + { +//printf( "Adding fanin %s.\n", Ivy_ObjName(pNext) ); + Vec_IntPush( vFront, Next ); + Vec_IntPush( vInside, Next ); + } + + // quit if this is the one fanin node + if ( Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) ) + return 1; + assert( Ivy_ObjIsNode(pNode) ); + + // add the right child to the fanins + Next = Ivy_LeafCreate( Ivy_ObjFaninId1(pNode), nLatches ); + if ( Next && Vec_IntFind(vInside, Next) == -1 ) + { +//printf( "Adding fanin %s.\n", Ivy_ObjName(pNext) ); + Vec_IntPush( vFront, Next ); + Vec_IntPush( vInside, Next ); + } + assert( Vec_IntSize(vFront) <= nSizeLimit ); + // keep doing this + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes one sequential cut of the given size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManSeqFindCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vFront, Vec_Int_t * vInside, int nSize ) +{ + assert( !Ivy_IsComplement(pRoot) ); + assert( Ivy_ObjIsNode(pRoot) ); + assert( Ivy_ObjFaninId0(pRoot) ); + assert( Ivy_ObjFaninId1(pRoot) ); + + // start the cut + Vec_IntClear( vFront ); + Vec_IntPush( vFront, Ivy_LeafCreate(Ivy_ObjFaninId0(pRoot), 0) ); + Vec_IntPush( vFront, Ivy_LeafCreate(Ivy_ObjFaninId1(pRoot), 0) ); + + // start the visited nodes + Vec_IntClear( vInside ); + Vec_IntPush( vInside, Ivy_LeafCreate(pRoot->Id, 0) ); + Vec_IntPush( vInside, Ivy_LeafCreate(Ivy_ObjFaninId0(pRoot), 0) ); + Vec_IntPush( vInside, Ivy_LeafCreate(Ivy_ObjFaninId1(pRoot), 0) ); + + // compute the cut + while ( Ivy_ManSeqFindCut_int( p, vFront, vInside, nSize ) ); + assert( Vec_IntSize(vFront) <= nSize ); +} + + + + + +/**Function************************************************************* + + Synopsis [Computing Boolean cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManFindBoolCut_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vVolume, Ivy_Obj_t * pPivot ) +{ + int RetValue0, RetValue1; + if ( pObj == pPivot ) + { + Vec_PtrPushUnique( vLeaves, pObj ); + Vec_PtrPushUnique( vVolume, pObj ); + return 1; + } + if ( pObj->fMarkA ) + return 0; + +// assert( !Ivy_ObjIsCi(pObj) ); + if ( Ivy_ObjIsCi(pObj) ) + return 0; + + if ( Ivy_ObjIsBuf(pObj) ) + { + RetValue0 = Ivy_ManFindBoolCut_rec( p, Ivy_ObjFanin0(pObj), vLeaves, vVolume, pPivot ); + if ( !RetValue0 ) + return 0; + Vec_PtrPushUnique( vVolume, pObj ); + return 1; + } + assert( Ivy_ObjIsNode(pObj) ); + RetValue0 = Ivy_ManFindBoolCut_rec( p, Ivy_ObjFanin0(pObj), vLeaves, vVolume, pPivot ); + RetValue1 = Ivy_ManFindBoolCut_rec( p, Ivy_ObjFanin1(pObj), vLeaves, vVolume, pPivot ); + if ( !RetValue0 && !RetValue1 ) + return 0; + // add new leaves + if ( !RetValue0 ) + { + Vec_PtrPushUnique( vLeaves, Ivy_ObjFanin0(pObj) ); + Vec_PtrPushUnique( vVolume, Ivy_ObjFanin0(pObj) ); + } + if ( !RetValue1 ) + { + Vec_PtrPushUnique( vLeaves, Ivy_ObjFanin1(pObj) ); + Vec_PtrPushUnique( vVolume, Ivy_ObjFanin1(pObj) ); + } + Vec_PtrPushUnique( vVolume, pObj ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns the cost of one node (how many new nodes are added.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManFindBoolCutCost( Ivy_Obj_t * pObj ) +{ + int Cost; + // make sure the node is in the construction zone + assert( pObj->fMarkA == 1 ); + // cannot expand over the PI node + if ( Ivy_ObjIsCi(pObj) ) + return 999; + // always expand over the buffer + if ( Ivy_ObjIsBuf(pObj) ) + return !Ivy_ObjFanin0(pObj)->fMarkA; + // get the cost of the cone + Cost = (!Ivy_ObjFanin0(pObj)->fMarkA) + (!Ivy_ObjFanin1(pObj)->fMarkA); + // return the number of nodes to be added to the leaves if this node is removed + return Cost; +} + +/**Function************************************************************* + + Synopsis [Computing Boolean cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManFindBoolCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vVolume, Vec_Ptr_t * vLeaves ) +{ + Ivy_Obj_t * pObj = NULL; // Suppress "might be used uninitialized" + Ivy_Obj_t * pFaninC, * pFanin0, * pFanin1, * pPivot; + int RetValue, LevelLimit, Lev, k; + assert( !Ivy_IsComplement(pRoot) ); + // clear the frontier and collect the nodes + Vec_PtrClear( vFront ); + Vec_PtrClear( vVolume ); + if ( Ivy_ObjIsMuxType(pRoot) ) + pFaninC = Ivy_ObjRecognizeMux( pRoot, &pFanin0, &pFanin1 ); + else + { + pFaninC = NULL; + pFanin0 = Ivy_ObjFanin0(pRoot); + pFanin1 = Ivy_ObjFanin1(pRoot); + } + // start cone A + pFanin0->fMarkA = 1; + Vec_PtrPush( vFront, pFanin0 ); + Vec_PtrPush( vVolume, pFanin0 ); + // start cone B + pFanin1->fMarkB = 1; + Vec_PtrPush( vFront, pFanin1 ); + Vec_PtrPush( vVolume, pFanin1 ); + // iteratively expand until the common node (pPivot) is found or limit is reached + assert( Ivy_ObjLevel(pRoot) == Ivy_ObjLevelNew(pRoot) ); + pPivot = NULL; + LevelLimit = IVY_MAX( Ivy_ObjLevel(pRoot) - 10, 1 ); + for ( Lev = Ivy_ObjLevel(pRoot) - 1; Lev >= LevelLimit; Lev-- ) + { + while ( 1 ) + { + // find the next node to expand on this level + Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pObj, k ) + if ( (int)pObj->Level == Lev ) + break; + if ( k == Vec_PtrSize(vFront) ) + break; + assert( (int)pObj->Level <= Lev ); + assert( pObj->fMarkA ^ pObj->fMarkB ); + // remove the old node + Vec_PtrRemove( vFront, pObj ); + + // expand this node + pFanin0 = Ivy_ObjFanin0(pObj); + if ( !pFanin0->fMarkA && !pFanin0->fMarkB ) + { + Vec_PtrPush( vFront, pFanin0 ); + Vec_PtrPush( vVolume, pFanin0 ); + } + // mark the new nodes + if ( pObj->fMarkA ) + pFanin0->fMarkA = 1; + if ( pObj->fMarkB ) + pFanin0->fMarkB = 1; + + if ( Ivy_ObjIsBuf(pObj) ) + { + if ( pFanin0->fMarkA && pFanin0->fMarkB ) + { + pPivot = pFanin0; + break; + } + continue; + } + + // expand this node + pFanin1 = Ivy_ObjFanin1(pObj); + if ( !pFanin1->fMarkA && !pFanin1->fMarkB ) + { + Vec_PtrPush( vFront, pFanin1 ); + Vec_PtrPush( vVolume, pFanin1 ); + } + // mark the new nodes + if ( pObj->fMarkA ) + pFanin1->fMarkA = 1; + if ( pObj->fMarkB ) + pFanin1->fMarkB = 1; + + // consider if it is time to quit + if ( pFanin0->fMarkA && pFanin0->fMarkB ) + { + pPivot = pFanin0; + break; + } + if ( pFanin1->fMarkA && pFanin1->fMarkB ) + { + pPivot = pFanin1; + break; + } + } + if ( pPivot != NULL ) + break; + } + if ( pPivot == NULL ) + return 0; + // if the MUX control is defined, it should not be + if ( pFaninC && !pFaninC->fMarkA && !pFaninC->fMarkB ) + Vec_PtrPush( vFront, pFaninC ); + // clean the markings + Vec_PtrForEachEntry( Ivy_Obj_t *, vVolume, pObj, k ) + pObj->fMarkA = pObj->fMarkB = 0; + + // mark the nodes on the frontier (including the pivot) + Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pObj, k ) + pObj->fMarkA = 1; + // cut exists, collect all the nodes on the shortest path to the pivot + Vec_PtrClear( vLeaves ); + Vec_PtrClear( vVolume ); + RetValue = Ivy_ManFindBoolCut_rec( p, pRoot, vLeaves, vVolume, pPivot ); + assert( RetValue == 1 ); + // unmark the nodes on the frontier (including the pivot) + Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pObj, k ) + pObj->fMarkA = 0; + + // mark the nodes in the volume + Vec_PtrForEachEntry( Ivy_Obj_t *, vVolume, pObj, k ) + pObj->fMarkA = 1; + // expand the cut without increasing its size + while ( 1 ) + { + Vec_PtrForEachEntry( Ivy_Obj_t *, vLeaves, pObj, k ) + if ( Ivy_ManFindBoolCutCost(pObj) < 2 ) + break; + if ( k == Vec_PtrSize(vLeaves) ) + break; + // the node can be expanded + // remove the old node + Vec_PtrRemove( vLeaves, pObj ); + // expand this node + pFanin0 = Ivy_ObjFanin0(pObj); + if ( !pFanin0->fMarkA ) + { + pFanin0->fMarkA = 1; + Vec_PtrPush( vVolume, pFanin0 ); + Vec_PtrPush( vLeaves, pFanin0 ); + } + if ( Ivy_ObjIsBuf(pObj) ) + continue; + // expand this node + pFanin1 = Ivy_ObjFanin1(pObj); + if ( !pFanin1->fMarkA ) + { + pFanin1->fMarkA = 1; + Vec_PtrPush( vVolume, pFanin1 ); + Vec_PtrPush( vLeaves, pFanin1 ); + } + } + // unmark the nodes in the volume + Vec_PtrForEachEntry( Ivy_Obj_t *, vVolume, pObj, k ) + pObj->fMarkA = 0; + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManTestCutsBool( Ivy_Man_t * p ) +{ + Vec_Ptr_t * vFront, * vVolume, * vLeaves; + Ivy_Obj_t * pObj;//, * pTemp; + int i, RetValue;//, k; + vFront = Vec_PtrAlloc( 100 ); + vVolume = Vec_PtrAlloc( 100 ); + vLeaves = Vec_PtrAlloc( 100 ); + Ivy_ManForEachObj( p, pObj, i ) + { + if ( !Ivy_ObjIsNode(pObj) ) + continue; + if ( Ivy_ObjIsMuxType(pObj) ) + { + printf( "m" ); + continue; + } + if ( Ivy_ObjIsExor(pObj) ) + printf( "x" ); + RetValue = Ivy_ManFindBoolCut( p, pObj, vFront, vVolume, vLeaves ); + if ( RetValue == 0 ) + printf( "- " ); + else + printf( "%d ", Vec_PtrSize(vLeaves) ); +/* + printf( "( " ); + Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, k ) + printf( "%d ", Ivy_ObjRefs(Ivy_Regular(pTemp)) ); + printf( ")\n" ); +*/ + } + printf( "\n" ); + Vec_PtrFree( vFront ); + Vec_PtrFree( vVolume ); + Vec_PtrFree( vLeaves ); +} + + + +/**Function************************************************************* + + Synopsis [Find the hash value of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Ivy_NodeCutHash( Ivy_Cut_t * pCut ) +{ + int i; +// for ( i = 1; i < pCut->nSize; i++ ) +// assert( pCut->pArray[i-1] < pCut->pArray[i] ); + pCut->uHash = 0; + for ( i = 0; i < pCut->nSize; i++ ) + pCut->uHash |= (1 << (pCut->pArray[i] % 31)); + return pCut->uHash; +} + +/**Function************************************************************* + + Synopsis [Removes one node to the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Ivy_NodeCutShrink( Ivy_Cut_t * pCut, int iOld ) +{ + int i, k; + for ( i = k = 0; i < pCut->nSize; i++ ) + if ( pCut->pArray[i] != iOld ) + pCut->pArray[k++] = pCut->pArray[i]; + assert( k == pCut->nSize - 1 ); + pCut->nSize--; +} + +/**Function************************************************************* + + Synopsis [Adds one node to the cut.] + + Description [Returns 1 if the cuts is still okay.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_NodeCutExtend( Ivy_Cut_t * pCut, int iNew ) +{ + int i; + for ( i = 0; i < pCut->nSize; i++ ) + if ( pCut->pArray[i] == iNew ) + return 1; + // check if there is room + if ( pCut->nSize == pCut->nSizeMax ) + return 0; + // add the new one + for ( i = pCut->nSize - 1; i >= 0; i-- ) + if ( pCut->pArray[i] > iNew ) + pCut->pArray[i+1] = pCut->pArray[i]; + else + { + assert( pCut->pArray[i] < iNew ); + break; + } + pCut->pArray[i+1] = iNew; + pCut->nSize++; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the cut can be constructed; 0 otherwise.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_NodeCutPrescreen( Ivy_Cut_t * pCut, int Id0, int Id1 ) +{ + int i; + if ( pCut->nSize < pCut->nSizeMax ) + return 1; + for ( i = 0; i < pCut->nSize; i++ ) + if ( pCut->pArray[i] == Id0 || pCut->pArray[i] == Id1 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Derives new cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_NodeCutDeriveNew( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 ) +{ + unsigned uHash = 0; + int i, k; + assert( pCut->nSize > 0 ); + assert( IdNew0 < IdNew1 ); + for ( i = k = 0; i < pCut->nSize; i++ ) + { + if ( pCut->pArray[i] == IdOld ) + continue; + if ( IdNew0 <= pCut->pArray[i] ) + { + if ( IdNew0 < pCut->pArray[i] ) + { + pCutNew->pArray[ k++ ] = IdNew0; + uHash |= Ivy_NodeCutHashValue( IdNew0 ); + } + IdNew0 = 0x7FFFFFFF; + } + if ( IdNew1 <= pCut->pArray[i] ) + { + if ( IdNew1 < pCut->pArray[i] ) + { + pCutNew->pArray[ k++ ] = IdNew1; + uHash |= Ivy_NodeCutHashValue( IdNew1 ); + } + IdNew1 = 0x7FFFFFFF; + } + pCutNew->pArray[ k++ ] = pCut->pArray[i]; + uHash |= Ivy_NodeCutHashValue( pCut->pArray[i] ); + } + if ( IdNew0 < 0x7FFFFFFF ) + { + pCutNew->pArray[ k++ ] = IdNew0; + uHash |= Ivy_NodeCutHashValue( IdNew0 ); + } + if ( IdNew1 < 0x7FFFFFFF ) + { + pCutNew->pArray[ k++ ] = IdNew1; + uHash |= Ivy_NodeCutHashValue( IdNew1 ); + } + pCutNew->nSize = k; + pCutNew->uHash = uHash; + assert( pCutNew->nSize <= pCut->nSizeMax ); +// for ( i = 1; i < pCutNew->nSize; i++ ) +// assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Check if the cut exists.] + + Description [Returns 1 if the cut exists.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeCutFindOrAdd( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew ) +{ + Ivy_Cut_t * pCut; + int i, k; + assert( pCutNew->uHash ); + // try to find the cut + for ( i = 0; i < pCutStore->nCuts; i++ ) + { + pCut = pCutStore->pCuts + i; + if ( pCut->uHash == pCutNew->uHash && pCut->nSize == pCutNew->nSize ) + { + for ( k = 0; k < pCutNew->nSize; k++ ) + if ( pCut->pArray[k] != pCutNew->pArray[k] ) + break; + if ( k == pCutNew->nSize ) + return 1; + } + } + assert( pCutStore->nCuts < pCutStore->nCutsMax ); + // add the cut + pCut = pCutStore->pCuts + pCutStore->nCuts++; + *pCut = *pCutNew; + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pDom is contained in pCut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_CutCheckDominance( Ivy_Cut_t * pDom, Ivy_Cut_t * pCut ) +{ + int i, k; + for ( i = 0; i < pDom->nSize; i++ ) + { + for ( k = 0; k < pCut->nSize; k++ ) + if ( pDom->pArray[i] == pCut->pArray[k] ) + break; + if ( k == pCut->nSize ) // node i in pDom is not contained in pCut + return 0; + } + // every node in pDom is contained in pCut + return 1; +} + +/**Function************************************************************* + + Synopsis [Check if the cut exists.] + + Description [Returns 1 if the cut exists.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeCutFindOrAddFilter( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew ) +{ + Ivy_Cut_t * pCut; + int i, k; + assert( pCutNew->uHash ); + // try to find the cut + for ( i = 0; i < pCutStore->nCuts; i++ ) + { + pCut = pCutStore->pCuts + i; + if ( pCut->nSize == 0 ) + continue; + if ( pCut->nSize == pCutNew->nSize ) + { + if ( pCut->uHash == pCutNew->uHash ) + { + for ( k = 0; k < pCutNew->nSize; k++ ) + if ( pCut->pArray[k] != pCutNew->pArray[k] ) + break; + if ( k == pCutNew->nSize ) + return 1; + } + continue; + } + if ( pCut->nSize < pCutNew->nSize ) + { + // skip the non-contained cuts + if ( (pCut->uHash & pCutNew->uHash) != pCut->uHash ) + continue; + // check containment seriously + if ( Ivy_CutCheckDominance( pCut, pCutNew ) ) + return 1; + continue; + } + // check potential containment of other cut + + // skip the non-contained cuts + if ( (pCut->uHash & pCutNew->uHash) != pCutNew->uHash ) + continue; + // check containment seriously + if ( Ivy_CutCheckDominance( pCutNew, pCut ) ) + { + // remove the current cut +// --pCutStore->nCuts; +// for ( k = i; k < pCutStore->nCuts; k++ ) +// pCutStore->pCuts[k] = pCutStore->pCuts[k+1]; +// i--; + pCut->nSize = 0; + } + } + assert( pCutStore->nCuts < pCutStore->nCutsMax ); + // add the cut + pCut = pCutStore->pCuts + pCutStore->nCuts++; + *pCut = *pCutNew; + return 0; +} + +/**Function************************************************************* + + Synopsis [Print the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeCompactCuts( Ivy_Store_t * pCutStore ) +{ + Ivy_Cut_t * pCut; + int i, k; + for ( i = k = 0; i < pCutStore->nCuts; i++ ) + { + pCut = pCutStore->pCuts + i; + if ( pCut->nSize == 0 ) + continue; + pCutStore->pCuts[k++] = *pCut; + } + pCutStore->nCuts = k; +} + +/**Function************************************************************* + + Synopsis [Print the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodePrintCut( Ivy_Cut_t * pCut ) +{ + int i; + assert( pCut->nSize > 0 ); + printf( "%d : {", pCut->nSize ); + for ( i = 0; i < pCut->nSize; i++ ) + printf( " %d", pCut->pArray[i] ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodePrintCuts( Ivy_Store_t * pCutStore ) +{ + int i; + printf( "Node %d\n", pCutStore->pCuts[0].pArray[0] ); + for ( i = 0; i < pCutStore->nCuts; i++ ) + Ivy_NodePrintCut( pCutStore->pCuts + i ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Ivy_Obj_t * Ivy_ObjRealFanin( Ivy_Obj_t * pObj ) +{ + if ( !Ivy_ObjIsBuf(pObj) ) + return pObj; + return Ivy_ObjRealFanin( Ivy_ObjFanin0(pObj) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Store_t * Ivy_NodeFindCutsAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves ) +{ + static Ivy_Store_t CutStore, * pCutStore = &CutStore; + Ivy_Cut_t CutNew, * pCutNew = &CutNew, * pCut; + Ivy_Obj_t * pLeaf; + int i, k, iLeaf0, iLeaf1; + + assert( nLeaves <= IVY_CUT_INPUT ); + + // start the structure + pCutStore->nCuts = 0; + pCutStore->nCutsMax = IVY_CUT_LIMIT; + // start the trivial cut + pCutNew->uHash = 0; + pCutNew->nSize = 1; + pCutNew->nSizeMax = nLeaves; + pCutNew->pArray[0] = pObj->Id; + Ivy_NodeCutHash( pCutNew ); + // add the trivial cut + Ivy_NodeCutFindOrAdd( pCutStore, pCutNew ); + assert( pCutStore->nCuts == 1 ); + + // explore the cuts + for ( i = 0; i < pCutStore->nCuts; i++ ) + { + // expand this cut + pCut = pCutStore->pCuts + i; + if ( pCut->nSize == 0 ) + continue; + for ( k = 0; k < pCut->nSize; k++ ) + { + pLeaf = Ivy_ManObj( p, pCut->pArray[k] ); + if ( Ivy_ObjIsCi(pLeaf) ) + continue; +/* + *pCutNew = *pCut; + Ivy_NodeCutShrink( pCutNew, pLeaf->Id ); + if ( !Ivy_NodeCutExtend( pCutNew, Ivy_ObjFaninId0(pLeaf) ) ) + continue; + if ( Ivy_ObjIsNode(pLeaf) && !Ivy_NodeCutExtend( pCutNew, Ivy_ObjFaninId1(pLeaf) ) ) + continue; + Ivy_NodeCutHash( pCutNew ); +*/ + iLeaf0 = Ivy_ObjId( Ivy_ObjRealFanin(Ivy_ObjFanin0(pLeaf)) ); + iLeaf1 = Ivy_ObjId( Ivy_ObjRealFanin(Ivy_ObjFanin1(pLeaf)) ); +// if ( iLeaf0 == iLeaf1 ) // strange situation observed on Jan 18, 2007 +// continue; + if ( !Ivy_NodeCutPrescreen( pCut, iLeaf0, iLeaf1 ) ) + continue; + if ( iLeaf0 > iLeaf1 ) + Ivy_NodeCutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf1, iLeaf0 ); + else + Ivy_NodeCutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf0, iLeaf1 ); + Ivy_NodeCutFindOrAddFilter( pCutStore, pCutNew ); + if ( pCutStore->nCuts == IVY_CUT_LIMIT ) + break; + } + if ( pCutStore->nCuts == IVY_CUT_LIMIT ) + break; + } + Ivy_NodeCompactCuts( pCutStore ); +// Ivy_NodePrintCuts( pCutStore ); + return pCutStore; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManTestCutsAll( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i, nCutsCut, nCutsTotal, nNodeTotal, nNodeOver; + abctime clk = Abc_Clock(); + nNodeTotal = nNodeOver = 0; + nCutsTotal = -Ivy_ManNodeNum(p); + Ivy_ManForEachObj( p, pObj, i ) + { + if ( !Ivy_ObjIsNode(pObj) ) + continue; + nCutsCut = Ivy_NodeFindCutsAll( p, pObj, 5 )->nCuts; + nCutsTotal += nCutsCut; + nNodeOver += (nCutsCut == IVY_CUT_LIMIT); + nNodeTotal++; + } + printf( "Total cuts = %6d. Trivial = %6d. Nodes = %6d. Satur = %6d. ", + nCutsTotal, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver ); + ABC_PRT( "Time", Abc_Clock() - clk ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/ivyCutTrav.c b/yosys/abc/src/aig/ivy/ivyCutTrav.c new file mode 100644 index 00000000000..b1cdb4566b3 --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivyCutTrav.c @@ -0,0 +1,478 @@ +/**CFile**************************************************************** + + FileName [ivyCutTrav.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyCutTrav.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static unsigned * Ivy_NodeCutElementary( Vec_Int_t * vStore, int nWords, int NodeId ); +static void Ivy_NodeComputeVolume( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront ); +static void Ivy_NodeFindCutsMerge( Vec_Ptr_t * vCuts0, Vec_Ptr_t * vCuts1, Vec_Ptr_t * vCuts, int nLeaves, int nWords, Vec_Int_t * vStore ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes cuts for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Store_t * Ivy_NodeFindCutsTravAll( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves, int nNodeLimit, + Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront, Vec_Int_t * vStore, Vec_Vec_t * vBitCuts ) +{ + static Ivy_Store_t CutStore, * pCutStore = &CutStore; + Vec_Ptr_t * vCuts, * vCuts0, * vCuts1; + unsigned * pBitCut; + Ivy_Obj_t * pLeaf; + Ivy_Cut_t * pCut; + int i, k, nWords, nNodes; + + assert( nLeaves <= IVY_CUT_INPUT ); + + // find the given number of nodes in the TFI + Ivy_NodeComputeVolume( pObj, nNodeLimit - 1, vNodes, vFront ); + nNodes = Vec_PtrSize(vNodes); +// assert( nNodes <= nNodeLimit ); + + // make sure vBitCuts has enough room + Vec_VecExpand( vBitCuts, nNodes-1 ); + Vec_VecClear( vBitCuts ); + + // prepare the memory manager + Vec_IntClear( vStore ); + Vec_IntGrow( vStore, 64000 ); + + // set elementary cuts for the leaves + nWords = Extra_BitWordNum( nNodes ); + Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pLeaf, i ) + { + assert( Ivy_ObjTravId(pLeaf) < nNodes ); + // get the new bitcut + pBitCut = Ivy_NodeCutElementary( vStore, nWords, Ivy_ObjTravId(pLeaf) ); + // set it as the cut of this leaf + Vec_VecPush( vBitCuts, Ivy_ObjTravId(pLeaf), pBitCut ); + } + + // compute the cuts for each node + Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pLeaf, i ) + { + // skip the leaves + vCuts = Vec_VecEntry( vBitCuts, Ivy_ObjTravId(pLeaf) ); + if ( Vec_PtrSize(vCuts) > 0 ) + continue; + // add elementary cut + pBitCut = Ivy_NodeCutElementary( vStore, nWords, Ivy_ObjTravId(pLeaf) ); + // set it as the cut of this leaf + Vec_VecPush( vBitCuts, Ivy_ObjTravId(pLeaf), pBitCut ); + // get the fanin cuts + vCuts0 = Vec_VecEntry( vBitCuts, Ivy_ObjTravId( Ivy_ObjFanin0(pLeaf) ) ); + vCuts1 = Vec_VecEntry( vBitCuts, Ivy_ObjTravId( Ivy_ObjFanin1(pLeaf) ) ); + assert( Vec_PtrSize(vCuts0) > 0 ); + assert( Vec_PtrSize(vCuts1) > 0 ); + // merge the cuts + Ivy_NodeFindCutsMerge( vCuts0, vCuts1, vCuts, nLeaves, nWords, vStore ); + } + + // start the structure + pCutStore->nCuts = 0; + pCutStore->nCutsMax = IVY_CUT_LIMIT; + // collect the cuts of the root node + vCuts = Vec_VecEntry( vBitCuts, Ivy_ObjTravId(pObj) ); + Vec_PtrForEachEntry( unsigned *, vCuts, pBitCut, i ) + { + pCut = pCutStore->pCuts + pCutStore->nCuts++; + pCut->nSize = 0; + pCut->nSizeMax = nLeaves; + pCut->uHash = 0; + for ( k = 0; k < nNodes; k++ ) + if ( Extra_TruthHasBit(pBitCut, k) ) + pCut->pArray[ pCut->nSize++ ] = Ivy_ObjId( (Ivy_Obj_t *)Vec_PtrEntry(vNodes, k) ); + assert( pCut->nSize <= nLeaves ); + if ( pCutStore->nCuts == pCutStore->nCutsMax ) + break; + } + + // clean the travIds + Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pLeaf, i ) + pLeaf->TravId = 0; + return pCutStore; +} + +/**Function************************************************************* + + Synopsis [Creates elementary bit-cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Ivy_NodeCutElementary( Vec_Int_t * vStore, int nWords, int NodeId ) +{ + unsigned * pBitCut; + pBitCut = Vec_IntFetch( vStore, nWords ); + memset( pBitCut, 0, (size_t)(4 * nWords) ); + Extra_TruthSetBit( pBitCut, NodeId ); + return pBitCut; +} + +/**Function************************************************************* + + Synopsis [Compares the node by level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_CompareNodesByLevel( Ivy_Obj_t ** ppObj1, Ivy_Obj_t ** ppObj2 ) +{ + Ivy_Obj_t * pObj1 = *ppObj1; + Ivy_Obj_t * pObj2 = *ppObj2; + if ( pObj1->Level < pObj2->Level ) + return -1; + if ( pObj1->Level > pObj2->Level ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Mark all nodes up to the given depth.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeComputeVolumeTrav1_rec( Ivy_Obj_t * pObj, int Depth ) +{ + if ( Ivy_ObjIsCi(pObj) || Depth == 0 ) + return; + Ivy_NodeComputeVolumeTrav1_rec( Ivy_ObjFanin0(pObj), Depth - 1 ); + Ivy_NodeComputeVolumeTrav1_rec( Ivy_ObjFanin1(pObj), Depth - 1 ); + pObj->fMarkA = 1; +} + +/**Function************************************************************* + + Synopsis [Collect the marked nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeComputeVolumeTrav2_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + if ( !pObj->fMarkA ) + return; + Ivy_NodeComputeVolumeTrav2_rec( Ivy_ObjFanin0(pObj), vNodes ); + Ivy_NodeComputeVolumeTrav2_rec( Ivy_ObjFanin1(pObj), vNodes ); + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeComputeVolume( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront ) +{ + Ivy_Obj_t * pTemp, * pFanin; + int i, nNodes; + // mark nodes up to the given depth + Ivy_NodeComputeVolumeTrav1_rec( pObj, 6 ); + // collect the marked nodes + Vec_PtrClear( vFront ); + Ivy_NodeComputeVolumeTrav2_rec( pObj, vFront ); + // find the fanins that are not marked + Vec_PtrClear( vNodes ); + Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, i ) + { + pFanin = Ivy_ObjFanin0(pTemp); + if ( !pFanin->fMarkA ) + { + pFanin->fMarkA = 1; + Vec_PtrPush( vNodes, pFanin ); + } + pFanin = Ivy_ObjFanin1(pTemp); + if ( !pFanin->fMarkA ) + { + pFanin->fMarkA = 1; + Vec_PtrPush( vNodes, pFanin ); + } + } + // remember the number of nodes in the frontier + nNodes = Vec_PtrSize( vNodes ); + // add the remaining nodes + Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, i ) + Vec_PtrPush( vNodes, pTemp ); + // unmark the nodes + Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pTemp, i ) + { + pTemp->fMarkA = 0; + pTemp->TravId = i; + } + // collect the frontier nodes + Vec_PtrClear( vFront ); + Vec_PtrForEachEntryStop( Ivy_Obj_t *, vNodes, pTemp, i, nNodes ) + Vec_PtrPush( vFront, pTemp ); +// printf( "%d ", Vec_PtrSize(vNodes) ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeComputeVolume2( Ivy_Obj_t * pObj, int nNodeLimit, Vec_Ptr_t * vNodes, Vec_Ptr_t * vFront ) +{ + Ivy_Obj_t * pLeaf, * pPivot, * pFanin; + int LevelMax, i; + assert( Ivy_ObjIsNode(pObj) ); + // clear arrays + Vec_PtrClear( vNodes ); + Vec_PtrClear( vFront ); + // add the root + pObj->fMarkA = 1; + Vec_PtrPush( vNodes, pObj ); + Vec_PtrPush( vFront, pObj ); + // expand node with maximum level + LevelMax = pObj->Level; + do { + // get the node to expand + pPivot = NULL; + Vec_PtrForEachEntryReverse( Ivy_Obj_t *, vFront, pLeaf, i ) + { + if ( (int)pLeaf->Level == LevelMax ) + { + pPivot = pLeaf; + break; + } + } + // decrease level if we did not find the node + if ( pPivot == NULL ) + { + if ( --LevelMax == 0 ) + break; + continue; + } + // the node to expand is found + // remove it from frontier + Vec_PtrRemove( vFront, pPivot ); + // add fanins + pFanin = Ivy_ObjFanin0(pPivot); + if ( !pFanin->fMarkA ) + { + pFanin->fMarkA = 1; + Vec_PtrPush( vNodes, pFanin ); + Vec_PtrPush( vFront, pFanin ); + } + pFanin = Ivy_ObjFanin1(pPivot); + if ( pFanin && !pFanin->fMarkA ) + { + pFanin->fMarkA = 1; + Vec_PtrPush( vNodes, pFanin ); + Vec_PtrPush( vFront, pFanin ); + } + // quit if we collected enough nodes + } while ( Vec_PtrSize(vNodes) < nNodeLimit ); + + // sort nodes by level + Vec_PtrSort( vNodes, (int (*)(const void *, const void *))Ivy_CompareNodesByLevel ); + // make sure the nodes are ordered in the increasing number of levels + pFanin = (Ivy_Obj_t *)Vec_PtrEntry( vNodes, 0 ); + pPivot = (Ivy_Obj_t *)Vec_PtrEntryLast( vNodes ); + assert( pFanin->Level <= pPivot->Level ); + + // clean the marks and remember node numbers in the TravId + Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pFanin, i ) + { + pFanin->fMarkA = 0; + pFanin->TravId = i; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Extra_TruthOrWords( unsigned * pOut, unsigned * pIn0, unsigned * pIn1, int nWords ) +{ + int w; + for ( w = nWords-1; w >= 0; w-- ) + pOut[w] = pIn0[w] | pIn1[w]; +} +static inline int Extra_TruthIsImplyWords( unsigned * pIn1, unsigned * pIn2, int nWords ) +{ + int w; + for ( w = nWords-1; w >= 0; w-- ) + if ( pIn1[w] & ~pIn2[w] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Merges two sets of bit-cuts at a node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeFindCutsMerge( Vec_Ptr_t * vCuts0, Vec_Ptr_t * vCuts1, Vec_Ptr_t * vCuts, + int nLeaves, int nWords, Vec_Int_t * vStore ) +{ + unsigned * pBitCut, * pBitCut0, * pBitCut1, * pBitCutTest; + int i, k, c, w, Counter; + // iterate through the cut pairs + Vec_PtrForEachEntry( unsigned *, vCuts0, pBitCut0, i ) + Vec_PtrForEachEntry( unsigned *, vCuts1, pBitCut1, k ) + { + // skip infeasible cuts + Counter = 0; + for ( w = 0; w < nWords; w++ ) + { + Counter += Extra_WordCountOnes( pBitCut0[w] | pBitCut1[w] ); + if ( Counter > nLeaves ) + break; + } + if ( Counter > nLeaves ) + continue; + // the new cut is feasible - create it + pBitCutTest = Vec_IntFetch( vStore, nWords ); + Extra_TruthOrWords( pBitCutTest, pBitCut0, pBitCut1, nWords ); + // filter contained cuts; try to find containing cut + w = 0; + Vec_PtrForEachEntry( unsigned *, vCuts, pBitCut, c ) + { + if ( Extra_TruthIsImplyWords( pBitCut, pBitCutTest, nWords ) ) + break; + if ( Extra_TruthIsImplyWords( pBitCutTest, pBitCut, nWords ) ) + continue; + Vec_PtrWriteEntry( vCuts, w++, pBitCut ); + } + if ( c != Vec_PtrSize(vCuts) ) + continue; + Vec_PtrShrink( vCuts, w ); + // add the cut + Vec_PtrPush( vCuts, pBitCutTest ); + } +} + +/**Function************************************************************* + + Synopsis [Compute the set of all cuts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManTestCutsTravAll( Ivy_Man_t * p ) +{ + Ivy_Store_t * pStore; + Ivy_Obj_t * pObj; + Vec_Ptr_t * vNodes, * vFront; + Vec_Int_t * vStore; + Vec_Vec_t * vBitCuts; + int i, nCutsCut, nCutsTotal, nNodeTotal, nNodeOver; + abctime clk = Abc_Clock(); + + vNodes = Vec_PtrAlloc( 100 ); + vFront = Vec_PtrAlloc( 100 ); + vStore = Vec_IntAlloc( 100 ); + vBitCuts = Vec_VecAlloc( 100 ); + + nNodeTotal = nNodeOver = 0; + nCutsTotal = -Ivy_ManNodeNum(p); + Ivy_ManForEachObj( p, pObj, i ) + { + if ( !Ivy_ObjIsNode(pObj) ) + continue; + pStore = Ivy_NodeFindCutsTravAll( p, pObj, 4, 60, vNodes, vFront, vStore, vBitCuts ); + nCutsCut = pStore->nCuts; + nCutsTotal += nCutsCut; + nNodeOver += (nCutsCut == IVY_CUT_LIMIT); + nNodeTotal++; + } + printf( "Total cuts = %6d. Trivial = %6d. Nodes = %6d. Satur = %6d. ", + nCutsTotal, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver ); + ABC_PRT( "Time", Abc_Clock() - clk ); + + Vec_PtrFree( vNodes ); + Vec_PtrFree( vFront ); + Vec_IntFree( vStore ); + Vec_VecFree( vBitCuts ); + +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/ivyDfs.c b/yosys/abc/src/aig/ivy/ivyDfs.c new file mode 100644 index 00000000000..611dd854374 --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivyDfs.c @@ -0,0 +1,498 @@ +/**CFile**************************************************************** + + FileName [ivyDfs.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [DFS collection procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyDfs.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Collects nodes in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManDfs_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Int_t * vNodes ) +{ + if ( Ivy_ObjIsMarkA(pObj) ) + return; + Ivy_ObjSetMarkA(pObj); + if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) ) + { + if ( p->pHaig == NULL && pObj->pEquiv ) + Ivy_ManDfs_rec( p, Ivy_Regular(pObj->pEquiv), vNodes ); + return; + } +//printf( "visiting node %d\n", pObj->Id ); +/* + if ( pObj->Id == 87 || pObj->Id == 90 ) + { + int y = 0; + } +*/ + assert( Ivy_ObjIsBuf(pObj) || Ivy_ObjIsAnd(pObj) || Ivy_ObjIsExor(pObj) ); + Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes ); + if ( !Ivy_ObjIsBuf(pObj) ) + Ivy_ManDfs_rec( p, Ivy_ObjFanin1(pObj), vNodes ); + if ( p->pHaig == NULL && pObj->pEquiv ) + Ivy_ManDfs_rec( p, Ivy_Regular(pObj->pEquiv), vNodes ); + Vec_IntPush( vNodes, pObj->Id ); + +//printf( "adding node %d with fanins %d and %d and equiv %d (refs = %d)\n", +// pObj->Id, Ivy_ObjFanin0(pObj)->Id, Ivy_ObjFanin1(pObj)->Id, +// pObj->pEquiv? Ivy_Regular(pObj->pEquiv)->Id: -1, Ivy_ObjRefs(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Collects AND/EXOR nodes in the DFS order from CIs to COs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Ivy_ManDfs( Ivy_Man_t * p ) +{ + Vec_Int_t * vNodes; + Ivy_Obj_t * pObj; + int i; + assert( Ivy_ManLatchNum(p) == 0 ); + // make sure the nodes are not marked + Ivy_ManForEachObj( p, pObj, i ) + assert( !pObj->fMarkA && !pObj->fMarkB ); + // collect the nodes + vNodes = Vec_IntAlloc( Ivy_ManNodeNum(p) ); + Ivy_ManForEachPo( p, pObj, i ) + Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes ); + // unmark the collected nodes +// Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) +// Ivy_ObjClearMarkA(pObj); + Ivy_ManForEachObj( p, pObj, i ) + Ivy_ObjClearMarkA(pObj); + // make sure network does not have dangling nodes + assert( Vec_IntSize(vNodes) == Ivy_ManNodeNum(p) + Ivy_ManBufNum(p) ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Collects AND/EXOR nodes in the DFS order from CIs to COs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Ivy_ManDfsSeq( Ivy_Man_t * p, Vec_Int_t ** pvLatches ) +{ + Vec_Int_t * vNodes, * vLatches; + Ivy_Obj_t * pObj; + int i; +// assert( Ivy_ManLatchNum(p) > 0 ); + // make sure the nodes are not marked + Ivy_ManForEachObj( p, pObj, i ) + assert( !pObj->fMarkA && !pObj->fMarkB ); + // collect the latches + vLatches = Vec_IntAlloc( Ivy_ManLatchNum(p) ); + Ivy_ManForEachLatch( p, pObj, i ) + Vec_IntPush( vLatches, pObj->Id ); + // collect the nodes + vNodes = Vec_IntAlloc( Ivy_ManNodeNum(p) ); + Ivy_ManForEachPo( p, pObj, i ) + Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes ); + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + Ivy_ManDfs_rec( p, Ivy_ObjFanin0(pObj), vNodes ); + // unmark the collected nodes +// Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) +// Ivy_ObjClearMarkA(pObj); + Ivy_ManForEachObj( p, pObj, i ) + Ivy_ObjClearMarkA(pObj); + // make sure network does not have dangling nodes +// assert( Vec_IntSize(vNodes) == Ivy_ManNodeNum(p) + Ivy_ManBufNum(p) ); + +// temporary!!! + + if ( pvLatches == NULL ) + Vec_IntFree( vLatches ); + else + *pvLatches = vLatches; + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Collects nodes in the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManCollectCone_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vCone ) +{ + if ( pObj->fMarkA ) + return; + if ( Ivy_ObjIsBuf(pObj) ) + { + Ivy_ManCollectCone_rec( Ivy_ObjFanin0(pObj), vCone ); + Vec_PtrPush( vCone, pObj ); + return; + } + assert( Ivy_ObjIsNode(pObj) ); + Ivy_ManCollectCone_rec( Ivy_ObjFanin0(pObj), vCone ); + Ivy_ManCollectCone_rec( Ivy_ObjFanin1(pObj), vCone ); + Vec_PtrPushUnique( vCone, pObj ); +} + +/**Function************************************************************* + + Synopsis [Collects nodes in the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManCollectCone( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone ) +{ + Ivy_Obj_t * pTemp; + int i; + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjIsNode(pObj) ); + // mark the nodes + Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, i ) + Ivy_Regular(pTemp)->fMarkA = 1; + assert( pObj->fMarkA == 0 ); + // collect the cone + Vec_PtrClear( vCone ); + Ivy_ManCollectCone_rec( pObj, vCone ); + // unmark the nodes + Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, i ) + Ivy_Regular(pTemp)->fMarkA = 0; +} + +/**Function************************************************************* + + Synopsis [Returns the nodes by level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Vec_t * Ivy_ManLevelize( Ivy_Man_t * p ) +{ + Vec_Vec_t * vNodes; + Ivy_Obj_t * pObj; + int i; + vNodes = Vec_VecAlloc( 100 ); + Ivy_ManForEachObj( p, pObj, i ) + { + assert( !Ivy_ObjIsBuf(pObj) ); + if ( Ivy_ObjIsNode(pObj) ) + Vec_VecPush( vNodes, pObj->Level, pObj ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Computes required levels for each node.] + + Description [Assumes topological ordering of the nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Ivy_ManRequiredLevels( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + Vec_Int_t * vLevelsR; + Vec_Vec_t * vNodes; + int i, k, Level, LevelMax; + assert( p->vRequired == NULL ); + // start the required times + vLevelsR = Vec_IntStart( Ivy_ManObjIdMax(p) + 1 ); + // iterate through the nodes in the reverse order + vNodes = Ivy_ManLevelize( p ); + Vec_VecForEachEntryReverseReverse( Ivy_Obj_t *, vNodes, pObj, i, k ) + { + Level = Vec_IntEntry( vLevelsR, pObj->Id ) + 1 + Ivy_ObjIsExor(pObj); + if ( Vec_IntEntry( vLevelsR, Ivy_ObjFaninId0(pObj) ) < Level ) + Vec_IntWriteEntry( vLevelsR, Ivy_ObjFaninId0(pObj), Level ); + if ( Vec_IntEntry( vLevelsR, Ivy_ObjFaninId1(pObj) ) < Level ) + Vec_IntWriteEntry( vLevelsR, Ivy_ObjFaninId1(pObj), Level ); + } + Vec_VecFree( vNodes ); + // convert it into the required times + LevelMax = Ivy_ManLevels( p ); +//printf( "max %5d\n",LevelMax ); + Ivy_ManForEachObj( p, pObj, i ) + { + Level = Vec_IntEntry( vLevelsR, pObj->Id ); + Vec_IntWriteEntry( vLevelsR, pObj->Id, LevelMax - Level ); +//printf( "%5d : %5d %5d\n", pObj->Id, Level, LevelMax - Level ); + } + p->vRequired = vLevelsR; + return vLevelsR; +} + +/**Function************************************************************* + + Synopsis [Recursively detects combinational loops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManIsAcyclic_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + // skip the node if it is already visited + if ( Ivy_ObjIsTravIdPrevious(p, pObj) ) + return 1; + // check if the node is part of the combinational loop + if ( Ivy_ObjIsTravIdCurrent(p, pObj) ) + { + fprintf( stdout, "Manager contains combinational loop!\n" ); + fprintf( stdout, "Node \"%d\" is encountered twice on the following path:\n", Ivy_ObjId(pObj) ); + fprintf( stdout, " %d", Ivy_ObjId(pObj) ); + return 0; + } + // mark this node as a node on the current path + Ivy_ObjSetTravIdCurrent( p, pObj ); + // explore equivalent nodes if pObj is the main node + if ( p->pHaig == NULL && pObj->pEquiv && Ivy_ObjRefs(pObj) > 0 ) + { + Ivy_Obj_t * pTemp; + assert( !Ivy_IsComplement(pObj->pEquiv) ); + for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + { + // traverse the fanin's cone searching for the loop + if ( !Ivy_ManIsAcyclic_rec(p, pTemp) ) + { + // return as soon as the loop is detected + fprintf( stdout, " -> (%d", Ivy_ObjId(pObj) ); + for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + fprintf( stdout, " %d", Ivy_ObjId(pTemp) ); + fprintf( stdout, ")" ); + return 0; + } + } + } + // quite if it is a CI node + if ( Ivy_ObjIsCi(pObj) || Ivy_ObjIsConst1(pObj) ) + { + // mark this node as a visited node + Ivy_ObjSetTravIdPrevious( p, pObj ); + return 1; + } + assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); + // traverse the fanin's cone searching for the loop + if ( !Ivy_ManIsAcyclic_rec(p, Ivy_ObjFanin0(pObj)) ) + { + // return as soon as the loop is detected + fprintf( stdout, " -> %d", Ivy_ObjId(pObj) ); + return 0; + } + // traverse the fanin's cone searching for the loop + if ( Ivy_ObjIsNode(pObj) && !Ivy_ManIsAcyclic_rec(p, Ivy_ObjFanin1(pObj)) ) + { + // return as soon as the loop is detected + fprintf( stdout, " -> %d", Ivy_ObjId(pObj) ); + return 0; + } + // mark this node as a visited node + Ivy_ObjSetTravIdPrevious( p, pObj ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Detects combinational loops.] + + Description [This procedure is based on the idea suggested by Donald Chai. + As we traverse the network and visit the nodes, we need to distinquish + three types of nodes: (1) those that are visited for the first time, + (2) those that have been visited in this traversal but are currently not + on the traversal path, (3) those that have been visited and are currently + on the travesal path. When the node of type (3) is encountered, it means + that there is a combinational loop. To mark the three types of nodes, + two new values of the traversal IDs are used.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManIsAcyclic( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int fAcyclic, i; + // set the traversal ID for this DFS ordering + Ivy_ManIncrementTravId( p ); + Ivy_ManIncrementTravId( p ); + // pObj->TravId == pNet->nTravIds means "pObj is on the path" + // pObj->TravId == pNet->nTravIds - 1 means "pObj is visited but is not on the path" + // pObj->TravId < pNet->nTravIds - 1 means "pObj is not visited" + // traverse the network to detect cycles + fAcyclic = 1; + Ivy_ManForEachCo( p, pObj, i ) + { + // traverse the output logic cone + if ( (fAcyclic = Ivy_ManIsAcyclic_rec(p, Ivy_ObjFanin0(pObj))) ) + continue; + // stop as soon as the first loop is detected + fprintf( stdout, " (cone of %s \"%d\")\n", Ivy_ObjIsLatch(pObj)? "latch" : "PO", Ivy_ObjId(pObj) ); + break; + } + return fAcyclic; +} + +/**Function************************************************************* + + Synopsis [Sets the levels of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManSetLevels_rec( Ivy_Obj_t * pObj, int fHaig ) +{ + // quit if the node is visited + if ( Ivy_ObjIsMarkA(pObj) ) + return pObj->Level; + Ivy_ObjSetMarkA(pObj); + // quit if this is a CI + if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) ) + return 0; + assert( Ivy_ObjIsBuf(pObj) || Ivy_ObjIsAnd(pObj) || Ivy_ObjIsExor(pObj) ); + // get levels of the fanins + Ivy_ManSetLevels_rec( Ivy_ObjFanin0(pObj), fHaig ); + if ( !Ivy_ObjIsBuf(pObj) ) + Ivy_ManSetLevels_rec( Ivy_ObjFanin1(pObj), fHaig ); + // get level of the node + if ( Ivy_ObjIsBuf(pObj) ) + pObj->Level = 1 + Ivy_ObjFanin0(pObj)->Level; + else if ( Ivy_ObjIsNode(pObj) ) + pObj->Level = Ivy_ObjLevelNew( pObj ); + else assert( 0 ); + // get level of other choices + if ( fHaig && pObj->pEquiv && Ivy_ObjRefs(pObj) > 0 ) + { + Ivy_Obj_t * pTemp; + unsigned LevelMax = pObj->Level; + for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + { + Ivy_ManSetLevels_rec( pTemp, fHaig ); + LevelMax = IVY_MAX( LevelMax, pTemp->Level ); + } + // get this level + pObj->Level = LevelMax; + for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + pTemp->Level = LevelMax; + } + return pObj->Level; +} + +/**Function************************************************************* + + Synopsis [Sets the levels of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManSetLevels( Ivy_Man_t * p, int fHaig ) +{ + Ivy_Obj_t * pObj; + int i, LevelMax; + // check if CIs have choices + if ( fHaig ) + { + Ivy_ManForEachCi( p, pObj, i ) + if ( pObj->pEquiv ) + printf( "CI %d has a choice, which will not be visualized.\n", pObj->Id ); + } + // clean the levels + Ivy_ManForEachObj( p, pObj, i ) + pObj->Level = 0; + // compute the levels + LevelMax = 0; + Ivy_ManForEachCo( p, pObj, i ) + { + Ivy_ManSetLevels_rec( Ivy_ObjFanin0(pObj), fHaig ); + LevelMax = IVY_MAX( LevelMax, (int)Ivy_ObjFanin0(pObj)->Level ); + } + // compute levels of nodes without fanout + Ivy_ManForEachObj( p, pObj, i ) + if ( (Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj)) && Ivy_ObjRefs(pObj) == 0 ) + { + Ivy_ManSetLevels_rec( pObj, fHaig ); + LevelMax = IVY_MAX( LevelMax, (int)pObj->Level ); + } + // clean the marks + Ivy_ManForEachObj( p, pObj, i ) + Ivy_ObjClearMarkA(pObj); + return LevelMax; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/ivyDsd.c b/yosys/abc/src/aig/ivy/ivyDsd.c new file mode 100644 index 00000000000..78a935be4a5 --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivyDsd.c @@ -0,0 +1,831 @@ +/**CFile**************************************************************** + + FileName [ivyDsd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Disjoint-support decomposition.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyDsd.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// decomposition types +typedef enum { + IVY_DEC_PI, // 0: var + IVY_DEC_CONST1, // 1: CONST1 + IVY_DEC_BUF, // 2: BUF + IVY_DEC_AND, // 3: AND + IVY_DEC_EXOR, // 4: EXOR + IVY_DEC_MUX, // 5: MUX + IVY_DEC_MAJ, // 6: MAJ + IVY_DEC_PRIME // 7: undecomposable +} Ivy_DecType_t; + +typedef struct Ivy_Dec_t_ Ivy_Dec_t; +struct Ivy_Dec_t_ +{ + unsigned Type : 4; // the node type (PI, CONST1, AND, EXOR, MUX, PRIME) + unsigned fCompl : 1; // shows if node is complemented (root node only) + unsigned nFans : 3; // the number of fanins + unsigned Fan0 : 4; // fanin 0 + unsigned Fan1 : 4; // fanin 1 + unsigned Fan2 : 4; // fanin 2 + unsigned Fan3 : 4; // fanin 3 + unsigned Fan4 : 4; // fanin 4 + unsigned Fan5 : 4; // fanin 5 +}; + +static inline int Ivy_DecToInt( Ivy_Dec_t m ) { union { Ivy_Dec_t x; int y; } v; v.x = m; return v.y; } +static inline Ivy_Dec_t Ivy_IntToDec( int m ) { union { Ivy_Dec_t x; int y; } v; v.y = m; return v.x; } +static inline void Ivy_DecClear( Ivy_Dec_t * pNode ) { *pNode = Ivy_IntToDec(0); } + +//static inline int Ivy_DecToInt( Ivy_Dec_t Node ) { return *((int *)&Node); } +//static inline Ivy_Dec_t Ivy_IntToDec( int Node ) { return *((Ivy_Dec_t *)&Node); } +//static inline void Ivy_DecClear( Ivy_Dec_t * pNode ) { *((int *)pNode) = 0; } + + +static unsigned s_Masks[6][2] = { + { 0x55555555, 0xAAAAAAAA }, + { 0x33333333, 0xCCCCCCCC }, + { 0x0F0F0F0F, 0xF0F0F0F0 }, + { 0x00FF00FF, 0xFF00FF00 }, + { 0x0000FFFF, 0xFFFF0000 }, + { 0x00000000, 0xFFFFFFFF } +}; + +static inline int Ivy_TruthWordCountOnes( unsigned uWord ) +{ + uWord = (uWord & 0x55555555) + ((uWord>>1) & 0x55555555); + uWord = (uWord & 0x33333333) + ((uWord>>2) & 0x33333333); + uWord = (uWord & 0x0F0F0F0F) + ((uWord>>4) & 0x0F0F0F0F); + uWord = (uWord & 0x00FF00FF) + ((uWord>>8) & 0x00FF00FF); + return (uWord & 0x0000FFFF) + (uWord>>16); +} + +static inline int Ivy_TruthCofactorIsConst( unsigned uTruth, int Var, int Cof, int Const ) +{ + if ( Const == 0 ) + return (uTruth & s_Masks[Var][Cof]) == 0; + else + return (uTruth & s_Masks[Var][Cof]) == s_Masks[Var][Cof]; +} + +static inline int Ivy_TruthCofactorIsOne( unsigned uTruth, int Var ) +{ + return (uTruth & s_Masks[Var][0]) == 0; +} + +static inline unsigned Ivy_TruthCofactor( unsigned uTruth, int Var ) +{ + unsigned uCofactor = uTruth & s_Masks[Var >> 1][(Var & 1) == 0]; + int Shift = (1 << (Var >> 1)); + if ( Var & 1 ) + return uCofactor | (uCofactor << Shift); + return uCofactor | (uCofactor >> Shift); +} + +static inline unsigned Ivy_TruthCofactor2( unsigned uTruth, int Var0, int Var1 ) +{ + return Ivy_TruthCofactor( Ivy_TruthCofactor(uTruth, Var0), Var1 ); +} + +// returns 1 if the truth table depends on this var (var is regular interger var) +static inline int Ivy_TruthDepends( unsigned uTruth, int Var ) +{ + return Ivy_TruthCofactor(uTruth, Var << 1) != Ivy_TruthCofactor(uTruth, (Var << 1) | 1); +} + +static inline void Ivy_DecSetVar( Ivy_Dec_t * pNode, int iNum, unsigned Var ) +{ + assert( iNum >= 0 && iNum <= 5 ); + switch( iNum ) + { + case 0: pNode->Fan0 = Var; break; + case 1: pNode->Fan1 = Var; break; + case 2: pNode->Fan2 = Var; break; + case 3: pNode->Fan3 = Var; break; + case 4: pNode->Fan4 = Var; break; + case 5: pNode->Fan5 = Var; break; + } +} + +static inline unsigned Ivy_DecGetVar( Ivy_Dec_t * pNode, int iNum ) +{ + assert( iNum >= 0 && iNum <= 5 ); + switch( iNum ) + { + case 0: return pNode->Fan0; + case 1: return pNode->Fan1; + case 2: return pNode->Fan2; + case 3: return pNode->Fan3; + case 4: return pNode->Fan4; + case 5: return pNode->Fan5; + } + return ~0; +} + +static int Ivy_TruthDecompose_rec( unsigned uTruth, Vec_Int_t * vTree ); +static int Ivy_TruthRecognizeMuxMaj( unsigned uTruth, int * pSupp, int nSupp, Vec_Int_t * vTree ); + +//int nTruthDsd; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes DSD of truth table of 5 variables or less.] + + Description [Returns 1 if the function is a constant or is fully + DSD decomposable using AND/EXOR/MUX gates.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_TruthDsd( unsigned uTruth, Vec_Int_t * vTree ) +{ + Ivy_Dec_t Node; + int i, RetValue; + // set the PI variables + Vec_IntClear( vTree ); + for ( i = 0; i < 5; i++ ) + Vec_IntPush( vTree, 0 ); + // check if it is a constant + if ( uTruth == 0 || ~uTruth == 0 ) + { + Ivy_DecClear( &Node ); + Node.Type = IVY_DEC_CONST1; + Node.fCompl = (uTruth == 0); + Vec_IntPush( vTree, Ivy_DecToInt(Node) ); + return 1; + } + // perform the decomposition + RetValue = Ivy_TruthDecompose_rec( uTruth, vTree ); + if ( RetValue == -1 ) + return 0; + // get the topmost node + if ( (RetValue >> 1) < 5 ) + { // add buffer + Ivy_DecClear( &Node ); + Node.Type = IVY_DEC_BUF; + Node.fCompl = (RetValue & 1); + Node.Fan0 = ((RetValue >> 1) << 1); + Vec_IntPush( vTree, Ivy_DecToInt(Node) ); + } + else if ( RetValue & 1 ) + { // check if the topmost node has to be complemented + Node = Ivy_IntToDec( Vec_IntPop(vTree) ); + assert( Node.fCompl == 0 ); + Node.fCompl = (RetValue & 1); + Vec_IntPush( vTree, Ivy_DecToInt(Node) ); + } + if ( uTruth != Ivy_TruthDsdCompute(vTree) ) + printf( "Verification failed.\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes DSD of truth table.] + + Description [Returns the number of topmost decomposition node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_TruthDecompose_rec( unsigned uTruth, Vec_Int_t * vTree ) +{ + Ivy_Dec_t Node; + int Supp[5], Vars0[5], Vars1[5], Vars2[5], * pVars = NULL; + int nSupp, Count0, Count1, Count2, nVars = 0, RetValue, fCompl = 0, i; + unsigned uTruthCof, uCof0, uCof1; + + // get constant confactors + Count0 = Count1 = Count2 = nSupp = 0; + for ( i = 0; i < 5; i++ ) + { + if ( Ivy_TruthCofactorIsConst(uTruth, i, 0, 0) ) + Vars0[Count0++] = (i << 1) | 0; + else if ( Ivy_TruthCofactorIsConst(uTruth, i, 1, 0) ) + Vars0[Count0++] = (i << 1) | 1; + else if ( Ivy_TruthCofactorIsConst(uTruth, i, 0, 1) ) + Vars1[Count1++] = (i << 1) | 0; + else if ( Ivy_TruthCofactorIsConst(uTruth, i, 1, 1) ) + Vars1[Count1++] = (i << 1) | 1; + else + { + uCof0 = Ivy_TruthCofactor( uTruth, (i << 1) | 1 ); + uCof1 = Ivy_TruthCofactor( uTruth, (i << 1) | 0 ); + if ( uCof0 == ~uCof1 ) + Vars2[Count2++] = (i << 1) | 0; + else if ( uCof0 != uCof1 ) + Supp[nSupp++] = i; + } + } + assert( Count0 == 0 || Count1 == 0 ); + assert( Count0 == 0 || Count2 == 0 ); + assert( Count1 == 0 || Count2 == 0 ); + + // consider the case of a single variable + if ( Count0 == 1 && nSupp == 0 ) + return Vars0[0]; + + // consider more complex decompositions + if ( Count0 == 0 && Count1 == 0 && Count2 == 0 ) + return Ivy_TruthRecognizeMuxMaj( uTruth, Supp, nSupp, vTree ); + + // extract the nodes + Ivy_DecClear( &Node ); + if ( Count0 > 0 ) + nVars = Count0, pVars = Vars0, Node.Type = IVY_DEC_AND, fCompl = 0; + else if ( Count1 > 0 ) + nVars = Count1, pVars = Vars1, Node.Type = IVY_DEC_AND, fCompl = 1, uTruth = ~uTruth; + else if ( Count2 > 0 ) + nVars = Count2, pVars = Vars2, Node.Type = IVY_DEC_EXOR, fCompl = 0; + else + assert( 0 ); + Node.nFans = nVars+(nSupp>0); + + // compute cofactor + uTruthCof = uTruth; + for ( i = 0; i < nVars; i++ ) + { + uTruthCof = Ivy_TruthCofactor( uTruthCof, pVars[i] ); + Ivy_DecSetVar( &Node, i, pVars[i] ); + } + + if ( Node.Type == IVY_DEC_EXOR ) + fCompl ^= ((Node.nFans & 1) == 0); + + if ( nSupp > 0 ) + { + assert( uTruthCof != 0 && ~uTruthCof != 0 ); + // call recursively + RetValue = Ivy_TruthDecompose_rec( uTruthCof, vTree ); + // quit if non-decomposable + if ( RetValue == -1 ) + return -1; + // remove the complement from the child if the node is EXOR + if ( Node.Type == IVY_DEC_EXOR && (RetValue & 1) ) + { + fCompl ^= 1; + RetValue ^= 1; + } + // set the new decomposition + Ivy_DecSetVar( &Node, nVars, RetValue ); + } + else if ( Node.Type == IVY_DEC_EXOR ) + fCompl ^= (uTruthCof == 0); + + Vec_IntPush( vTree, Ivy_DecToInt(Node) ); + return ((Vec_IntSize(vTree)-1) << 1) | fCompl; +} + +/**Function************************************************************* + + Synopsis [Returns a non-negative number if the truth table is a MUX.] + + Description [If the truth table is a MUX, returns the variable as follows: + first, control variable; second, positive cofactor; third, negative cofactor.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_TruthRecognizeMuxMaj( unsigned uTruth, int * pSupp, int nSupp, Vec_Int_t * vTree ) +{ + Ivy_Dec_t Node; + int i, k, RetValue0, RetValue1; + unsigned uCof0, uCof1, Num; + char Count[3]; + assert( nSupp >= 3 ); + // start the node + Ivy_DecClear( &Node ); + Node.Type = IVY_DEC_MUX; + Node.nFans = 3; + // try each of the variables + for ( i = 0; i < nSupp; i++ ) + { + // get the cofactors with respect to these variables + uCof0 = Ivy_TruthCofactor( uTruth, (pSupp[i] << 1) | 1 ); + uCof1 = Ivy_TruthCofactor( uTruth, pSupp[i] << 1 ); + // go through all other variables and make sure + // each of them belongs to the support of one cofactor + for ( k = 0; k < nSupp; k++ ) + { + if ( k == i ) + continue; + if ( Ivy_TruthDepends(uCof0, pSupp[k]) && Ivy_TruthDepends(uCof1, pSupp[k]) ) + break; + } + if ( k < nSupp ) + continue; + // MUX decomposition exists + RetValue0 = Ivy_TruthDecompose_rec( uCof0, vTree ); + if ( RetValue0 == -1 ) + break; + RetValue1 = Ivy_TruthDecompose_rec( uCof1, vTree ); + if ( RetValue1 == -1 ) + break; + // both of them exist; create the node + Ivy_DecSetVar( &Node, 0, pSupp[i] << 1 ); + Ivy_DecSetVar( &Node, 1, RetValue1 ); + Ivy_DecSetVar( &Node, 2, RetValue0 ); + Vec_IntPush( vTree, Ivy_DecToInt(Node) ); + return ((Vec_IntSize(vTree)-1) << 1) | 0; + } + // check majority gate + if ( nSupp > 3 ) + return -1; + if ( Ivy_TruthWordCountOnes(uTruth) != 16 ) + return -1; + // this is a majority gate; determine polarity + Node.Type = IVY_DEC_MAJ; + Count[0] = Count[1] = Count[2] = 0; + for ( i = 0; i < 8; i++ ) + { + Num = 0; + for ( k = 0; k < 3; k++ ) + if ( i & (1 << k) ) + Num |= (1 << pSupp[k]); + assert( Num < 32 ); + if ( (uTruth & (1 << Num)) == 0 ) + continue; + for ( k = 0; k < 3; k++ ) + if ( i & (1 << k) ) + Count[k]++; + } + assert( Count[0] == 1 || Count[0] == 3 ); + assert( Count[1] == 1 || Count[1] == 3 ); + assert( Count[2] == 1 || Count[2] == 3 ); + Ivy_DecSetVar( &Node, 0, (pSupp[0] << 1)|(Count[0] == 1) ); + Ivy_DecSetVar( &Node, 1, (pSupp[1] << 1)|(Count[1] == 1) ); + Ivy_DecSetVar( &Node, 2, (pSupp[2] << 1)|(Count[2] == 1) ); + Vec_IntPush( vTree, Ivy_DecToInt(Node) ); + return ((Vec_IntSize(vTree)-1) << 1) | 0; +} + + +/**Function************************************************************* + + Synopsis [Computes truth table of decomposition tree for verification.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Ivy_TruthDsdCompute_rec( int iNode, Vec_Int_t * vTree ) +{ + unsigned uTruthChild, uTruthTotal; + int Var, i; + // get the node + Ivy_Dec_t Node = Ivy_IntToDec( Vec_IntEntry(vTree, iNode) ); + // compute the node function + if ( Node.Type == IVY_DEC_CONST1 ) + return s_Masks[5][ !Node.fCompl ]; + if ( Node.Type == IVY_DEC_PI ) + return s_Masks[iNode][ !Node.fCompl ]; + if ( Node.Type == IVY_DEC_BUF ) + { + uTruthTotal = Ivy_TruthDsdCompute_rec( Node.Fan0 >> 1, vTree ); + return Node.fCompl? ~uTruthTotal : uTruthTotal; + } + if ( Node.Type == IVY_DEC_AND ) + { + uTruthTotal = s_Masks[5][1]; + for ( i = 0; i < (int)Node.nFans; i++ ) + { + Var = Ivy_DecGetVar( &Node, i ); + uTruthChild = Ivy_TruthDsdCompute_rec( Var >> 1, vTree ); + uTruthTotal = (Var & 1)? uTruthTotal & ~uTruthChild : uTruthTotal & uTruthChild; + } + return Node.fCompl? ~uTruthTotal : uTruthTotal; + } + if ( Node.Type == IVY_DEC_EXOR ) + { + uTruthTotal = 0; + for ( i = 0; i < (int)Node.nFans; i++ ) + { + Var = Ivy_DecGetVar( &Node, i ); + uTruthTotal ^= Ivy_TruthDsdCompute_rec( Var >> 1, vTree ); + assert( (Var & 1) == 0 ); + } + return Node.fCompl? ~uTruthTotal : uTruthTotal; + } + assert( Node.fCompl == 0 ); + if ( Node.Type == IVY_DEC_MUX || Node.Type == IVY_DEC_MAJ ) + { + unsigned uTruthChildC, uTruthChild1, uTruthChild0; + int VarC, Var1, Var0; + VarC = Ivy_DecGetVar( &Node, 0 ); + Var1 = Ivy_DecGetVar( &Node, 1 ); + Var0 = Ivy_DecGetVar( &Node, 2 ); + uTruthChildC = Ivy_TruthDsdCompute_rec( VarC >> 1, vTree ); + uTruthChild1 = Ivy_TruthDsdCompute_rec( Var1 >> 1, vTree ); + uTruthChild0 = Ivy_TruthDsdCompute_rec( Var0 >> 1, vTree ); + assert( Node.Type == IVY_DEC_MAJ || (VarC & 1) == 0 ); + uTruthChildC = (VarC & 1)? ~uTruthChildC : uTruthChildC; + uTruthChild1 = (Var1 & 1)? ~uTruthChild1 : uTruthChild1; + uTruthChild0 = (Var0 & 1)? ~uTruthChild0 : uTruthChild0; + if ( Node.Type == IVY_DEC_MUX ) + return (uTruthChildC & uTruthChild1) | (~uTruthChildC & uTruthChild0); + else + return (uTruthChildC & uTruthChild1) | (uTruthChildC & uTruthChild0) | (uTruthChild1 & uTruthChild0); + } + assert( 0 ); + return 0; +} + + +/**Function************************************************************* + + Synopsis [Computes truth table of decomposition tree for verification.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Ivy_TruthDsdCompute( Vec_Int_t * vTree ) +{ + return Ivy_TruthDsdCompute_rec( Vec_IntSize(vTree)-1, vTree ); +} + +/**Function************************************************************* + + Synopsis [Prints the decomposition tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TruthDsdPrint_rec( FILE * pFile, int iNode, Vec_Int_t * vTree ) +{ + int Var, i; + // get the node + Ivy_Dec_t Node = Ivy_IntToDec( Vec_IntEntry(vTree, iNode) ); + // compute the node function + if ( Node.Type == IVY_DEC_CONST1 ) + fprintf( pFile, "Const1%s", (Node.fCompl? "\'" : "") ); + else if ( Node.Type == IVY_DEC_PI ) + fprintf( pFile, "%c%s", 'a' + iNode, (Node.fCompl? "\'" : "") ); + else if ( Node.Type == IVY_DEC_BUF ) + { + Ivy_TruthDsdPrint_rec( pFile, Node.Fan0 >> 1, vTree ); + fprintf( pFile, "%s", (Node.fCompl? "\'" : "") ); + } + else if ( Node.Type == IVY_DEC_AND ) + { + fprintf( pFile, "AND(" ); + for ( i = 0; i < (int)Node.nFans; i++ ) + { + Var = Ivy_DecGetVar( &Node, i ); + Ivy_TruthDsdPrint_rec( pFile, Var >> 1, vTree ); + fprintf( pFile, "%s", (Var & 1)? "\'" : "" ); + if ( i != (int)Node.nFans-1 ) + fprintf( pFile, "," ); + } + fprintf( pFile, ")%s", (Node.fCompl? "\'" : "") ); + } + else if ( Node.Type == IVY_DEC_EXOR ) + { + fprintf( pFile, "EXOR(" ); + for ( i = 0; i < (int)Node.nFans; i++ ) + { + Var = Ivy_DecGetVar( &Node, i ); + Ivy_TruthDsdPrint_rec( pFile, Var >> 1, vTree ); + if ( i != (int)Node.nFans-1 ) + fprintf( pFile, "," ); + assert( (Var & 1) == 0 ); + } + fprintf( pFile, ")%s", (Node.fCompl? "\'" : "") ); + } + else if ( Node.Type == IVY_DEC_MUX || Node.Type == IVY_DEC_MAJ ) + { + int VarC, Var1, Var0; + assert( Node.fCompl == 0 ); + VarC = Ivy_DecGetVar( &Node, 0 ); + Var1 = Ivy_DecGetVar( &Node, 1 ); + Var0 = Ivy_DecGetVar( &Node, 2 ); + fprintf( pFile, "%s", (Node.Type == IVY_DEC_MUX)? "MUX(" : "MAJ(" ); + Ivy_TruthDsdPrint_rec( pFile, VarC >> 1, vTree ); + fprintf( pFile, "%s", (VarC & 1)? "\'" : "" ); + fprintf( pFile, "," ); + Ivy_TruthDsdPrint_rec( pFile, Var1 >> 1, vTree ); + fprintf( pFile, "%s", (Var1 & 1)? "\'" : "" ); + fprintf( pFile, "," ); + Ivy_TruthDsdPrint_rec( pFile, Var0 >> 1, vTree ); + fprintf( pFile, "%s", (Var0 & 1)? "\'" : "" ); + fprintf( pFile, ")" ); + } + else assert( 0 ); +} + + +/**Function************************************************************* + + Synopsis [Prints the decomposition tree.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TruthDsdPrint( FILE * pFile, Vec_Int_t * vTree ) +{ + fprintf( pFile, "F = " ); + Ivy_TruthDsdPrint_rec( pFile, Vec_IntSize(vTree)-1, vTree ); + fprintf( pFile, "\n" ); +} + +/**Function************************************************************* + + Synopsis [Implement DSD in the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_ManDsdConstruct_rec( Ivy_Man_t * p, Vec_Int_t * vFront, int iNode, Vec_Int_t * vTree ) +{ + Ivy_Obj_t * pResult, * pChild, * pNodes[16]; + int Var, i; + // get the node + Ivy_Dec_t Node = Ivy_IntToDec( Vec_IntEntry(vTree, iNode) ); + // compute the node function + if ( Node.Type == IVY_DEC_CONST1 ) + return Ivy_NotCond( Ivy_ManConst1(p), Node.fCompl ); + if ( Node.Type == IVY_DEC_PI ) + { + pResult = Ivy_ManObj( p, Vec_IntEntry(vFront, iNode) ); + return Ivy_NotCond( pResult, Node.fCompl ); + } + if ( Node.Type == IVY_DEC_BUF ) + { + pResult = Ivy_ManDsdConstruct_rec( p, vFront, Node.Fan0 >> 1, vTree ); + return Ivy_NotCond( pResult, Node.fCompl ); + } + if ( Node.Type == IVY_DEC_AND || Node.Type == IVY_DEC_EXOR ) + { + for ( i = 0; i < (int)Node.nFans; i++ ) + { + Var = Ivy_DecGetVar( &Node, i ); + assert( Node.Type == IVY_DEC_AND || (Var & 1) == 0 ); + pChild = Ivy_ManDsdConstruct_rec( p, vFront, Var >> 1, vTree ); + pChild = Ivy_NotCond( pChild, (Var & 1) ); + pNodes[i] = pChild; + } + +// Ivy_MultiEval( pNodes, Node.nFans, Node.Type == IVY_DEC_AND ? IVY_AND : IVY_EXOR ); + + pResult = Ivy_Multi( p, pNodes, Node.nFans, Node.Type == IVY_DEC_AND ? IVY_AND : IVY_EXOR ); + return Ivy_NotCond( pResult, Node.fCompl ); + } + assert( Node.fCompl == 0 ); + if ( Node.Type == IVY_DEC_MUX || Node.Type == IVY_DEC_MAJ ) + { + int VarC, Var1, Var0; + VarC = Ivy_DecGetVar( &Node, 0 ); + Var1 = Ivy_DecGetVar( &Node, 1 ); + Var0 = Ivy_DecGetVar( &Node, 2 ); + pNodes[0] = Ivy_ManDsdConstruct_rec( p, vFront, VarC >> 1, vTree ); + pNodes[1] = Ivy_ManDsdConstruct_rec( p, vFront, Var1 >> 1, vTree ); + pNodes[2] = Ivy_ManDsdConstruct_rec( p, vFront, Var0 >> 1, vTree ); + assert( Node.Type == IVY_DEC_MAJ || (VarC & 1) == 0 ); + pNodes[0] = Ivy_NotCond( pNodes[0], (VarC & 1) ); + pNodes[1] = Ivy_NotCond( pNodes[1], (Var1 & 1) ); + pNodes[2] = Ivy_NotCond( pNodes[2], (Var0 & 1) ); + if ( Node.Type == IVY_DEC_MUX ) + return Ivy_Mux( p, pNodes[0], pNodes[1], pNodes[2] ); + else + return Ivy_Maj( p, pNodes[0], pNodes[1], pNodes[2] ); + } + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Implement DSD in the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_ManDsdConstruct( Ivy_Man_t * p, Vec_Int_t * vFront, Vec_Int_t * vTree ) +{ + int Entry, i; + // implement latches on the frontier (TEMPORARY!!!) + Vec_IntForEachEntry( vFront, Entry, i ) + Vec_IntWriteEntry( vFront, i, Ivy_LeafId(Entry) ); + // recursively construct the tree + return Ivy_ManDsdConstruct_rec( p, vFront, Vec_IntSize(vTree)-1, vTree ); +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TruthDsdComputePrint( unsigned uTruth ) +{ + static Vec_Int_t * vTree = NULL; + if ( vTree == NULL ) + vTree = Vec_IntAlloc( 12 ); + if ( Ivy_TruthDsd( uTruth, vTree ) ) + Ivy_TruthDsdPrint( stdout, vTree ); + else + printf( "Undecomposable\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TruthTestOne( unsigned uTruth ) +{ + static int Counter = 0; + static Vec_Int_t * vTree = NULL; + // decompose + if ( vTree == NULL ) + vTree = Vec_IntAlloc( 12 ); + + if ( !Ivy_TruthDsd( uTruth, vTree ) ) + { +// printf( "Undecomposable\n" ); + } + else + { +// nTruthDsd++; + printf( "%5d : ", Counter++ ); + Extra_PrintBinary( stdout, &uTruth, 32 ); + printf( " " ); + Ivy_TruthDsdPrint( stdout, vTree ); + if ( uTruth != Ivy_TruthDsdCompute(vTree) ) + printf( "Verification failed.\n" ); + } +// Vec_IntFree( vTree ); +} + +#if 0 + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TruthTest() +{ + FILE * pFile; + char Buffer[100]; + unsigned uTruth; + int i; + + pFile = fopen( "npn4.txt", "r" ); + for ( i = 0; i < 222; i++ ) +// pFile = fopen( "npn5.txt", "r" ); +// for ( i = 0; i < 616126; i++ ) + { + fscanf( pFile, "%s", Buffer ); + Extra_ReadHexadecimal( &uTruth, Buffer+2, 4 ); +// Extra_ReadHexadecimal( &uTruth, Buffer+2, 5 ); + uTruth |= (uTruth << 16); +// uTruth = ~uTruth; + Ivy_TruthTestOne( uTruth ); + } + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TruthTest3() +{ + FILE * pFile; + char Buffer[100]; + unsigned uTruth; + int i; + + pFile = fopen( "npn3.txt", "r" ); + for ( i = 0; i < 14; i++ ) + { + fscanf( pFile, "%s", Buffer ); + Extra_ReadHexadecimal( &uTruth, Buffer+2, 3 ); + uTruth = uTruth | (uTruth << 8) | (uTruth << 16) | (uTruth << 24); + Ivy_TruthTestOne( uTruth ); + } + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TruthTest5() +{ + FILE * pFile; + char Buffer[100]; + unsigned uTruth; + int i; + +// pFile = fopen( "npn4.txt", "r" ); +// for ( i = 0; i < 222; i++ ) + pFile = fopen( "npn5.txt", "r" ); + for ( i = 0; i < 616126; i++ ) + { + fscanf( pFile, "%s", Buffer ); +// Extra_ReadHexadecimal( &uTruth, Buffer+2, 4 ); + Extra_ReadHexadecimal( &uTruth, Buffer+2, 5 ); +// uTruth |= (uTruth << 16); +// uTruth = ~uTruth; + Ivy_TruthTestOne( uTruth ); + } + fclose( pFile ); +} + +#endif + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/ivyFanout.c b/yosys/abc/src/aig/ivy/ivyFanout.c new file mode 100644 index 00000000000..9ff4f4bc308 --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivyFanout.c @@ -0,0 +1,314 @@ +/**CFile**************************************************************** + + FileName [ivyFanout.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Representation of the fanouts.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyFanout.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// getting hold of the next fanout of the node +static inline Ivy_Obj_t * Ivy_ObjNextFanout( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) +{ + assert( !Ivy_IsComplement(pObj) ); + assert( !Ivy_IsComplement(pFanout) ); + if ( pFanout == NULL ) + return NULL; + if ( Ivy_ObjFanin0(pFanout) == pObj ) + return pFanout->pNextFan0; + assert( Ivy_ObjFanin1(pFanout) == pObj ); + return pFanout->pNextFan1; +} + +// getting hold of the previous fanout of the node +static inline Ivy_Obj_t * Ivy_ObjPrevFanout( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) +{ + assert( !Ivy_IsComplement(pObj) ); + assert( !Ivy_IsComplement(pFanout) ); + if ( pFanout == NULL ) + return NULL; + if ( Ivy_ObjFanin0(pFanout) == pObj ) + return pFanout->pPrevFan0; + assert( Ivy_ObjFanin1(pFanout) == pObj ); + return pFanout->pPrevFan1; +} + +// getting hold of the place where the next fanout will be attached +static inline Ivy_Obj_t ** Ivy_ObjNextFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) +{ + assert( !Ivy_IsComplement(pObj) ); + assert( !Ivy_IsComplement(pFanout) ); + if ( Ivy_ObjFanin0(pFanout) == pObj ) + return &pFanout->pNextFan0; + assert( Ivy_ObjFanin1(pFanout) == pObj ); + return &pFanout->pNextFan1; +} + +// getting hold of the place where the next fanout will be attached +static inline Ivy_Obj_t ** Ivy_ObjPrevFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) +{ + assert( !Ivy_IsComplement(pObj) ); + assert( !Ivy_IsComplement(pFanout) ); + if ( Ivy_ObjFanin0(pFanout) == pObj ) + return &pFanout->pPrevFan0; + assert( Ivy_ObjFanin1(pFanout) == pObj ); + return &pFanout->pPrevFan1; +} + +// getting hold of the place where the next fanout will be attached +static inline Ivy_Obj_t ** Ivy_ObjPrevNextFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) +{ + Ivy_Obj_t * pTemp; + assert( !Ivy_IsComplement(pObj) ); + assert( !Ivy_IsComplement(pFanout) ); + pTemp = Ivy_ObjPrevFanout(pObj, pFanout); + if ( pTemp == NULL ) + return &pObj->pFanout; + if ( Ivy_ObjFanin0(pTemp) == pObj ) + return &pTemp->pNextFan0; + assert( Ivy_ObjFanin1(pTemp) == pObj ); + return &pTemp->pNextFan1; +} + +// getting hold of the place where the next fanout will be attached +static inline Ivy_Obj_t ** Ivy_ObjNextPrevFanoutPlace( Ivy_Obj_t * pObj, Ivy_Obj_t * pFanout ) +{ + Ivy_Obj_t * pTemp; + assert( !Ivy_IsComplement(pObj) ); + assert( !Ivy_IsComplement(pFanout) ); + pTemp = Ivy_ObjNextFanout(pObj, pFanout); + if ( pTemp == NULL ) + return NULL; + if ( Ivy_ObjFanin0(pTemp) == pObj ) + return &pTemp->pPrevFan0; + assert( Ivy_ObjFanin1(pTemp) == pObj ); + return &pTemp->pPrevFan1; +} + +// iterator through the fanouts of the node +#define Ivy_ObjForEachFanoutInt( pObj, pFanout ) \ + for ( pFanout = (pObj)->pFanout; pFanout; \ + pFanout = Ivy_ObjNextFanout(pObj, pFanout) ) + +// safe iterator through the fanouts of the node +#define Ivy_ObjForEachFanoutIntSafe( pObj, pFanout, pFanout2 ) \ + for ( pFanout = (pObj)->pFanout, \ + pFanout2 = Ivy_ObjNextFanout(pObj, pFanout); \ + pFanout; \ + pFanout = pFanout2, \ + pFanout2 = Ivy_ObjNextFanout(pObj, pFanout) ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the fanout representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManStartFanout( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + assert( !p->fFanout ); + p->fFanout = 1; + Ivy_ManForEachObj( p, pObj, i ) + { + if ( Ivy_ObjFanin0(pObj) ) + Ivy_ObjAddFanout( p, Ivy_ObjFanin0(pObj), pObj ); + if ( Ivy_ObjFanin1(pObj) ) + Ivy_ObjAddFanout( p, Ivy_ObjFanin1(pObj), pObj ); + } +} + +/**Function************************************************************* + + Synopsis [Stops the fanout representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManStopFanout( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + assert( p->fFanout ); + p->fFanout = 0; + Ivy_ManForEachObj( p, pObj, i ) + pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL; +} + +/**Function************************************************************* + + Synopsis [Add the fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjAddFanout( Ivy_Man_t * p, Ivy_Obj_t * pFanin, Ivy_Obj_t * pFanout ) +{ + assert( p->fFanout ); + if ( pFanin->pFanout ) + { + *Ivy_ObjNextFanoutPlace(pFanin, pFanout) = pFanin->pFanout; + *Ivy_ObjPrevFanoutPlace(pFanin, pFanin->pFanout) = pFanout; + } + pFanin->pFanout = pFanout; +} + +/**Function************************************************************* + + Synopsis [Removes the fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjDeleteFanout( Ivy_Man_t * p, Ivy_Obj_t * pFanin, Ivy_Obj_t * pFanout ) +{ + Ivy_Obj_t ** ppPlace1, ** ppPlace2, ** ppPlaceN; + assert( pFanin->pFanout != NULL ); + + ppPlace1 = Ivy_ObjNextFanoutPlace(pFanin, pFanout); + ppPlaceN = Ivy_ObjPrevNextFanoutPlace(pFanin, pFanout); + assert( *ppPlaceN == pFanout ); + if ( ppPlaceN ) + *ppPlaceN = *ppPlace1; + + ppPlace2 = Ivy_ObjPrevFanoutPlace(pFanin, pFanout); + ppPlaceN = Ivy_ObjNextPrevFanoutPlace(pFanin, pFanout); + assert( ppPlaceN == NULL || *ppPlaceN == pFanout ); + if ( ppPlaceN ) + *ppPlaceN = *ppPlace2; + + *ppPlace1 = NULL; + *ppPlace2 = NULL; +} + +/**Function************************************************************* + + Synopsis [Replaces the fanout of pOld to be pFanoutNew.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjPatchFanout( Ivy_Man_t * p, Ivy_Obj_t * pFanin, Ivy_Obj_t * pFanoutOld, Ivy_Obj_t * pFanoutNew ) +{ + Ivy_Obj_t ** ppPlace; + ppPlace = Ivy_ObjPrevNextFanoutPlace(pFanin, pFanoutOld); + assert( *ppPlace == pFanoutOld ); + if ( ppPlace ) + *ppPlace = pFanoutNew; + ppPlace = Ivy_ObjNextPrevFanoutPlace(pFanin, pFanoutOld); + assert( ppPlace == NULL || *ppPlace == pFanoutOld ); + if ( ppPlace ) + *ppPlace = pFanoutNew; + // assuming that pFanoutNew already points to the next fanout +} + +/**Function************************************************************* + + Synopsis [Starts iteration through the fanouts.] + + Description [Copies the currently available fanouts into the array.] + + SideEffects [Can be used while the fanouts are being removed.] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjCollectFanouts( Ivy_Man_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vArray ) +{ + Ivy_Obj_t * pFanout; + assert( p->fFanout ); + assert( !Ivy_IsComplement(pObj) ); + Vec_PtrClear( vArray ); + Ivy_ObjForEachFanoutInt( pObj, pFanout ) + Vec_PtrPush( vArray, pFanout ); +} + +/**Function************************************************************* + + Synopsis [Reads one fanout.] + + Description [Returns fanout if there is only one fanout.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_ObjReadFirstFanout( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + return pObj->pFanout; +} + +/**Function************************************************************* + + Synopsis [Reads one fanout.] + + Description [Returns fanout if there is only one fanout.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ObjFanoutNum( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pFanout; + int Counter = 0; + Ivy_ObjForEachFanoutInt( pObj, pFanout ) + Counter++; + return Counter; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/ivyFastMap.c b/yosys/abc/src/aig/ivy/ivyFastMap.c new file mode 100644 index 00000000000..b8322b3fd19 --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivyFastMap.c @@ -0,0 +1,1569 @@ +/**CFile**************************************************************** + + FileName [ivyFastMap.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Fast FPGA mapping.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyFastMap.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define IVY_INFINITY 10000 + +typedef struct Ivy_SuppMan_t_ Ivy_SuppMan_t; +struct Ivy_SuppMan_t_ +{ + int nLimit; // the limit on the number of inputs + int nObjs; // the number of entries + int nSize; // size of each entry in bytes + char * pMem; // memory allocated + Vec_Vec_t * vLuts; // the array of nodes used in the mapping +}; + +typedef struct Ivy_Supp_t_ Ivy_Supp_t; +struct Ivy_Supp_t_ +{ + char nSize; // the number of support nodes + char fMark; // multipurpose mask + char fMark2; // multipurpose mask + char fMark3; // multipurpose mask + int nRefs; // the number of references + short Delay; // the delay of the node + short DelayR; // the reverse delay of the node + int pArray[0]; // the support nodes +}; + +static inline Ivy_Supp_t * Ivy_ObjSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + return (Ivy_Supp_t *)(((Ivy_SuppMan_t*)pAig->pData)->pMem + pObj->Id * ((Ivy_SuppMan_t*)pAig->pData)->nSize); +} +static inline Ivy_Supp_t * Ivy_ObjSuppStart( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + Ivy_Supp_t * pSupp; + pSupp = Ivy_ObjSupp( pAig, pObj ); + pSupp->fMark = 0; + pSupp->Delay = 0; + pSupp->nSize = 1; + pSupp->pArray[0] = pObj->Id; + return pSupp; +} + +static void Ivy_FastMapPrint( Ivy_Man_t * pAig, int Delay, int Area, abctime Time, char * pStr ); +static int Ivy_FastMapDelay( Ivy_Man_t * pAig ); +static int Ivy_FastMapArea( Ivy_Man_t * pAig ); +static void Ivy_FastMapNode( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ); +static void Ivy_FastMapNodeArea( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ); +static int Ivy_FastMapMerge( Ivy_Supp_t * pSupp0, Ivy_Supp_t * pSupp1, Ivy_Supp_t * pSupp, int nLimit ); +static void Ivy_FastMapRequired( Ivy_Man_t * pAig, int Delay, int fSetInter ); +static void Ivy_FastMapRecover( Ivy_Man_t * pAig, int nLimit ); +static int Ivy_FastMapNodeDelay( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); +static int Ivy_FastMapNodeAreaRefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); +static int Ivy_FastMapNodeAreaDerefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); +static void Ivy_FastMapNodeRecover( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ); +static int Ivy_FastMapNodeRef( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); +static int Ivy_FastMapNodeDeref( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ); + + +extern abctime s_MappingTime; +extern int s_MappingMem; + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs fast K-LUT mapping of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapPerform( Ivy_Man_t * pAig, int nLimit, int fRecovery, int fVerbose ) +{ + Ivy_SuppMan_t * pMan; + Ivy_Obj_t * pObj; + int i, Delay, Area; + abctime clk, clkTotal = Abc_Clock(); + // start the memory for supports + pMan = ABC_ALLOC( Ivy_SuppMan_t, 1 ); + memset( pMan, 0, sizeof(Ivy_SuppMan_t) ); + pMan->nLimit = nLimit; + pMan->nObjs = Ivy_ManObjIdMax(pAig) + 1; + pMan->nSize = sizeof(Ivy_Supp_t) + nLimit * sizeof(int); + pMan->pMem = (char *)ABC_ALLOC( char, pMan->nObjs * pMan->nSize ); + memset( pMan->pMem, 0, pMan->nObjs * pMan->nSize ); + pMan->vLuts = Vec_VecAlloc( 100 ); + pAig->pData = pMan; +clk = Abc_Clock(); + // set the PI mapping + Ivy_ObjSuppStart( pAig, Ivy_ManConst1(pAig) ); + Ivy_ManForEachPi( pAig, pObj, i ) + Ivy_ObjSuppStart( pAig, pObj ); + // iterate through all nodes in the topological order + Ivy_ManForEachNode( pAig, pObj, i ) + Ivy_FastMapNode( pAig, pObj, nLimit ); + // find the best arrival time and area + Delay = Ivy_FastMapDelay( pAig ); + Area = Ivy_FastMapArea(pAig); + if ( fVerbose ) + Ivy_FastMapPrint( pAig, Delay, Area, Abc_Clock() - clk, "Delay oriented mapping: " ); + +// 2-1-2 (doing 2-1-2-1-2 improves 0.5%) + + if ( fRecovery ) + { +clk = Abc_Clock(); + Ivy_FastMapRequired( pAig, Delay, 0 ); + // remap the nodes + Ivy_FastMapRecover( pAig, nLimit ); + Delay = Ivy_FastMapDelay( pAig ); + Area = Ivy_FastMapArea(pAig); + if ( fVerbose ) + Ivy_FastMapPrint( pAig, Delay, Area, Abc_Clock() - clk, "Area recovery 2 : " ); + +clk = Abc_Clock(); + Ivy_FastMapRequired( pAig, Delay, 0 ); + // iterate through all nodes in the topological order + Ivy_ManForEachNode( pAig, pObj, i ) + Ivy_FastMapNodeArea( pAig, pObj, nLimit ); + Delay = Ivy_FastMapDelay( pAig ); + Area = Ivy_FastMapArea(pAig); + if ( fVerbose ) + Ivy_FastMapPrint( pAig, Delay, Area, Abc_Clock() - clk, "Area recovery 1 : " ); + +clk = Abc_Clock(); + Ivy_FastMapRequired( pAig, Delay, 0 ); + // remap the nodes + Ivy_FastMapRecover( pAig, nLimit ); + Delay = Ivy_FastMapDelay( pAig ); + Area = Ivy_FastMapArea(pAig); + if ( fVerbose ) + Ivy_FastMapPrint( pAig, Delay, Area, Abc_Clock() - clk, "Area recovery 2 : " ); + } + + + s_MappingTime = Abc_Clock() - clkTotal; + s_MappingMem = pMan->nObjs * pMan->nSize; +/* + { + Vec_Ptr_t * vNodes; + vNodes = Vec_PtrAlloc( 100 ); + Vec_VecForEachEntry( Ivy_Obj_t *, pMan->vLuts, pObj, i, k ) + Vec_PtrPush( vNodes, pObj ); + Ivy_ManShow( pAig, 0, vNodes ); + Vec_PtrFree( vNodes ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Cleans memory used for decomposition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapStop( Ivy_Man_t * pAig ) +{ + Ivy_SuppMan_t * p = (Ivy_SuppMan_t *)pAig->pData; + Vec_VecFree( p->vLuts ); + ABC_FREE( p->pMem ); + ABC_FREE( p ); + pAig->pData = NULL; +} + +/**Function************************************************************* + + Synopsis [Prints statistics.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapPrint( Ivy_Man_t * pAig, int Delay, int Area, abctime Time, char * pStr ) +{ + printf( "%s : Delay = %3d. Area = %6d. ", pStr, Delay, Area ); + ABC_PRT( "Time", Time ); +} + +/**Function************************************************************* + + Synopsis [Computes delay after LUT mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapDelay( Ivy_Man_t * pAig ) +{ + Ivy_Supp_t * pSupp; + Ivy_Obj_t * pObj; + int i, DelayMax = 0; + Ivy_ManForEachPo( pAig, pObj, i ) + { + pObj = Ivy_ObjFanin0(pObj); + if ( !Ivy_ObjIsNode(pObj) ) + continue; + pSupp = Ivy_ObjSupp( pAig, pObj ); + if ( DelayMax < pSupp->Delay ) + DelayMax = pSupp->Delay; + } + return DelayMax; +} + +/**Function************************************************************* + + Synopsis [Computes area after mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapArea_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Vec_t * vLuts ) +{ + Ivy_Supp_t * pSupp; + int i, Counter; + pSupp = Ivy_ObjSupp( pAig, pObj ); + // skip visited nodes and PIs + if ( pSupp->fMark || pSupp->nSize == 1 ) + return 0; + pSupp->fMark = 1; + // compute the area of this node + Counter = 0; + for ( i = 0; i < pSupp->nSize; i++ ) + Counter += Ivy_FastMapArea_rec( pAig, Ivy_ManObj(pAig, pSupp->pArray[i]), vLuts ); + // add the node to the array of LUTs + Vec_VecPush( vLuts, pSupp->Delay, pObj ); + return 1 + Counter; +} + +/**Function************************************************************* + + Synopsis [Computes area after mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapArea( Ivy_Man_t * pAig ) +{ + Vec_Vec_t * vLuts; + Ivy_Obj_t * pObj; + int i, Counter = 0; + // get the array to store the nodes + vLuts = ((Ivy_SuppMan_t *)pAig->pData)->vLuts; + Vec_VecClear( vLuts ); + // explore starting from each node + Ivy_ManForEachPo( pAig, pObj, i ) + Counter += Ivy_FastMapArea_rec( pAig, Ivy_ObjFanin0(pObj), vLuts ); + // clean the marks + Ivy_ManForEachNode( pAig, pObj, i ) + Ivy_ObjSupp( pAig, pObj )->fMark = 0; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Performs fast mapping for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_ObjIsNodeInt1( Ivy_Obj_t * pObj ) +{ + return Ivy_ObjIsNode(pObj) && Ivy_ObjRefs(pObj) == 1; +} + +/**Function************************************************************* + + Synopsis [Performs fast mapping for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_ObjIsNodeInt2( Ivy_Obj_t * pObj ) +{ + return Ivy_ObjIsNode(pObj) && Ivy_ObjRefs(pObj) <= 2; +} + +/**Function************************************************************* + + Synopsis [Performs fast mapping for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Vec_IntRemoveDup( int * pArray, int nSize ) +{ + int i, k; + if ( nSize < 2 ) + return nSize; + for ( i = k = 1; i < nSize; i++ ) + if ( pArray[i] != pArray[i-1] ) + pArray[k++] = pArray[i]; + return k; +} + +/**Function************************************************************* + + Synopsis [Performs fast mapping for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodeArea2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ) +{ + static int Store[32], StoreSize; + static char Supp0[16], Supp1[16]; + static Ivy_Supp_t * pTemp0 = (Ivy_Supp_t *)Supp0; + static Ivy_Supp_t * pTemp1 = (Ivy_Supp_t *)Supp1; + Ivy_Obj_t * pFanin0, * pFanin1; + Ivy_Supp_t * pSupp0, * pSupp1, * pSupp; + int RetValue, DelayOld; + assert( nLimit <= 32 ); + assert( Ivy_ObjIsNode(pObj) ); + // get the fanins + pFanin0 = Ivy_ObjFanin0(pObj); + pFanin1 = Ivy_ObjFanin1(pObj); + // get the supports + pSupp0 = Ivy_ObjSupp( pAig, pFanin0 ); + pSupp1 = Ivy_ObjSupp( pAig, pFanin1 ); + pSupp = Ivy_ObjSupp( pAig, pObj ); + assert( pSupp->fMark == 0 ); + // get the old delay of the node + DelayOld = Ivy_FastMapNodeDelay(pAig, pObj); + assert( DelayOld <= pSupp->DelayR ); + // copy the current cut + memcpy( Store, pSupp->pArray, sizeof(int) * pSupp->nSize ); + StoreSize = pSupp->nSize; + // get the fanin support + if ( Ivy_ObjRefs(pFanin0) > 1 && pSupp0->Delay < pSupp->DelayR ) + { + pSupp0 = pTemp0; + pSupp0->nSize = 1; + pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj); + } + // get the fanin support + if ( Ivy_ObjRefs(pFanin1) > 1 && pSupp1->Delay < pSupp->DelayR ) + { + pSupp1 = pTemp1; + pSupp1->nSize = 1; + pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj); + } + // merge the cuts + if ( pSupp0->nSize < pSupp1->nSize ) + RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit ); + else + RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit ); + if ( !RetValue ) + { + pSupp->nSize = 2; + pSupp->pArray[0] = Ivy_ObjFaninId0(pObj); + pSupp->pArray[1] = Ivy_ObjFaninId1(pObj); + } + // check the resulting delay + pSupp->Delay = Ivy_FastMapNodeDelay(pAig, pObj); + if ( pSupp->Delay > pSupp->DelayR ) + { + pSupp->nSize = StoreSize; + memcpy( pSupp->pArray, Store, sizeof(int) * pSupp->nSize ); + pSupp->Delay = DelayOld; + } +} + +/**Function************************************************************* + + Synopsis [Performs fast mapping for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodeArea( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ) +{ + static int Store[32], StoreSize; + static char Supp0[16], Supp1[16]; + static Ivy_Supp_t * pTemp0 = (Ivy_Supp_t *)Supp0; + static Ivy_Supp_t * pTemp1 = (Ivy_Supp_t *)Supp1; + Ivy_Obj_t * pFanin0, * pFanin1; + Ivy_Supp_t * pSupp0, * pSupp1, * pSupp; + int RetValue, DelayOld, RefsOld; + int AreaBef, AreaAft; + assert( nLimit <= 32 ); + assert( Ivy_ObjIsNode(pObj) ); + // get the fanins + pFanin0 = Ivy_ObjFanin0(pObj); + pFanin1 = Ivy_ObjFanin1(pObj); + // get the supports + pSupp0 = Ivy_ObjSupp( pAig, pFanin0 ); + pSupp1 = Ivy_ObjSupp( pAig, pFanin1 ); + pSupp = Ivy_ObjSupp( pAig, pObj ); + assert( pSupp->fMark == 0 ); + + // get the area + if ( pSupp->nRefs == 0 ) + AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj ); + else + AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); +// if ( AreaBef == 1 ) +// return; + + // deref the cut if the node is refed + if ( pSupp->nRefs != 0 ) + Ivy_FastMapNodeDeref( pAig, pObj ); + + // get the old delay of the node + DelayOld = Ivy_FastMapNodeDelay(pAig, pObj); + assert( DelayOld <= pSupp->DelayR ); + // copy the current cut + memcpy( Store, pSupp->pArray, sizeof(int) * pSupp->nSize ); + StoreSize = pSupp->nSize; + // get the fanin support + if ( Ivy_ObjRefs(pFanin0) > 2 && pSupp0->Delay < pSupp->DelayR ) +// if ( pSupp0->nRefs > 0 && pSupp0->Delay < pSupp->DelayR ) // this leads to 2% worse results + { + pSupp0 = pTemp0; + pSupp0->nSize = 1; + pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj); + } + // get the fanin support + if ( Ivy_ObjRefs(pFanin1) > 2 && pSupp1->Delay < pSupp->DelayR ) +// if ( pSupp1->nRefs > 0 && pSupp1->Delay < pSupp->DelayR ) + { + pSupp1 = pTemp1; + pSupp1->nSize = 1; + pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj); + } + // merge the cuts + if ( pSupp0->nSize < pSupp1->nSize ) + RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit ); + else + RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit ); + if ( !RetValue ) + { + pSupp->nSize = 2; + pSupp->pArray[0] = Ivy_ObjFaninId0(pObj); + pSupp->pArray[1] = Ivy_ObjFaninId1(pObj); + } + + // check the resulting delay + pSupp->Delay = Ivy_FastMapNodeDelay(pAig, pObj); + + RefsOld = pSupp->nRefs; pSupp->nRefs = 0; + AreaAft = Ivy_FastMapNodeAreaDerefed( pAig, pObj ); + pSupp->nRefs = RefsOld; + + if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR ) +// if ( pSupp->Delay > pSupp->DelayR ) + { + pSupp->nSize = StoreSize; + memcpy( pSupp->pArray, Store, sizeof(int) * pSupp->nSize ); + pSupp->Delay = DelayOld; +// printf( "-" ); + } +// else +// printf( "+" ); + + if ( pSupp->nRefs != 0 ) + Ivy_FastMapNodeRef( pAig, pObj ); +} + +/**Function************************************************************* + + Synopsis [Performs fast mapping for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNode( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit ) +{ + Ivy_Supp_t * pSupp0, * pSupp1, * pSupp; + int fFaninParam = 2; + int RetValue; + assert( Ivy_ObjIsNode(pObj) ); + // get the supports + pSupp0 = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) ); + pSupp1 = Ivy_ObjSupp( pAig, Ivy_ObjFanin1(pObj) ); + pSupp = Ivy_ObjSupp( pAig, pObj ); + pSupp->fMark = 0; + // get the delays + if ( pSupp0->Delay == pSupp1->Delay ) + pSupp->Delay = (pSupp0->Delay == 0) ? pSupp0->Delay + 1: pSupp0->Delay; + else if ( pSupp0->Delay > pSupp1->Delay ) + { + pSupp->Delay = pSupp0->Delay; + pSupp1 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) ); + pSupp1->pArray[0] = Ivy_ObjFaninId1(pObj); + } + else // if ( pSupp0->Delay < pSupp1->Delay ) + { + pSupp->Delay = pSupp1->Delay; + pSupp0 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) ); + pSupp0->pArray[0] = Ivy_ObjFaninId0(pObj); + } + // merge the cuts + if ( pSupp0->nSize < pSupp1->nSize ) + RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit ); + else + RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit ); + if ( !RetValue ) + { + pSupp->Delay++; + if ( fFaninParam == 2 ) + { + pSupp->nSize = 2; + pSupp->pArray[0] = Ivy_ObjFaninId0(pObj); + pSupp->pArray[1] = Ivy_ObjFaninId1(pObj); + } + else if ( fFaninParam == 3 ) + { + Ivy_Obj_t * pFanin0, * pFanin1, * pFaninA, * pFaninB; + pFanin0 = Ivy_ObjFanin0(pObj); + pFanin1 = Ivy_ObjFanin1(pObj); + pSupp->nSize = 0; + // process the first fanin + if ( Ivy_ObjIsNodeInt1(pFanin0) ) + { + pFaninA = Ivy_ObjFanin0(pFanin0); + pFaninB = Ivy_ObjFanin1(pFanin0); + if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) ) + pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin0); + else + { + pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninA); + pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninB); + } + } + else + pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin0); + // process the second fanin + if ( Ivy_ObjIsNodeInt1(pFanin1) ) + { + pFaninA = Ivy_ObjFanin0(pFanin1); + pFaninB = Ivy_ObjFanin1(pFanin1); + if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) ) + pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin1); + else + { + pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninA); + pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninB); + } + } + else + pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin1); + // sort the fanins + Vec_IntSelectSort( pSupp->pArray, pSupp->nSize ); + pSupp->nSize = Vec_IntRemoveDup( pSupp->pArray, pSupp->nSize ); + assert( pSupp->pArray[0] < pSupp->pArray[1] ); + } + else if ( fFaninParam == 4 ) + { + Ivy_Obj_t * pFanin0, * pFanin1, * pFaninA, * pFaninB; + pFanin0 = Ivy_ObjFanin0(pObj); + pFanin1 = Ivy_ObjFanin1(pObj); + pSupp->nSize = 0; + // consider the case when exactly one of them is internal + if ( Ivy_ObjIsNodeInt1(pFanin0) ^ Ivy_ObjIsNodeInt1(pFanin1) ) + { + pSupp0 = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) ); + pSupp1 = Ivy_ObjSupp( pAig, Ivy_ObjFanin1(pObj) ); + if ( Ivy_ObjIsNodeInt1(pFanin0) && pSupp0->nSize < nLimit ) + { + pSupp->Delay = IVY_MAX( pSupp0->Delay, pSupp1->Delay + 1 ); + pSupp1 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) ); + pSupp1->pArray[0] = Ivy_ObjId(pFanin1); + // merge the cuts + RetValue = Ivy_FastMapMerge( pSupp0, pSupp1, pSupp, nLimit ); + assert( RetValue ); + assert( pSupp->nSize > 1 ); + return; + } + if ( Ivy_ObjIsNodeInt1(pFanin1) && pSupp1->nSize < nLimit ) + { + pSupp->Delay = IVY_MAX( pSupp1->Delay, pSupp0->Delay + 1 ); + pSupp0 = Ivy_ObjSupp( pAig, Ivy_ManConst1(pAig) ); + pSupp0->pArray[0] = Ivy_ObjId(pFanin0); + // merge the cuts + RetValue = Ivy_FastMapMerge( pSupp1, pSupp0, pSupp, nLimit ); + assert( RetValue ); + assert( pSupp->nSize > 1 ); + return; + } + } + // process the first fanin + if ( Ivy_ObjIsNodeInt1(pFanin0) ) + { + pFaninA = Ivy_ObjFanin0(pFanin0); + pFaninB = Ivy_ObjFanin1(pFanin0); + if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) ) + pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin0); + else + { + pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninA); + pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninB); + } + } + else + pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin0); + // process the second fanin + if ( Ivy_ObjIsNodeInt1(pFanin1) ) + { + pFaninA = Ivy_ObjFanin0(pFanin1); + pFaninB = Ivy_ObjFanin1(pFanin1); + if ( Ivy_ObjIsNodeInt1(pFaninA) && Ivy_ObjIsNodeInt1(pFaninB) ) + pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin1); + else + { + pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninA); + pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFaninB); + } + } + else + pSupp->pArray[(int)(pSupp->nSize++)] = Ivy_ObjId(pFanin1); + // sort the fanins + Vec_IntSelectSort( pSupp->pArray, pSupp->nSize ); + pSupp->nSize = Vec_IntRemoveDup( pSupp->pArray, pSupp->nSize ); + assert( pSupp->pArray[0] < pSupp->pArray[1] ); + assert( pSupp->nSize > 1 ); + } + } + assert( pSupp->Delay > 0 ); +} + +/**Function************************************************************* + + Synopsis [Merges two supports] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapMerge( Ivy_Supp_t * pSupp0, Ivy_Supp_t * pSupp1, Ivy_Supp_t * pSupp, int nLimit ) +{ + int i, k, c; + assert( pSupp0->nSize >= pSupp1->nSize ); + // the case of the largest cut sizes + if ( pSupp0->nSize == nLimit && pSupp1->nSize == nLimit ) + { + for ( i = 0; i < pSupp0->nSize; i++ ) + if ( pSupp0->pArray[i] != pSupp1->pArray[i] ) + return 0; + for ( i = 0; i < pSupp0->nSize; i++ ) + pSupp->pArray[i] = pSupp0->pArray[i]; + pSupp->nSize = pSupp0->nSize; + return 1; + } + // the case when one of the cuts is the largest + if ( pSupp0->nSize == nLimit ) + { + for ( i = 0; i < pSupp1->nSize; i++ ) + { + for ( k = pSupp0->nSize - 1; k >= 0; k-- ) + if ( pSupp0->pArray[k] == pSupp1->pArray[i] ) + break; + if ( k == -1 ) // did not find + return 0; + } + for ( i = 0; i < pSupp0->nSize; i++ ) + pSupp->pArray[i] = pSupp0->pArray[i]; + pSupp->nSize = pSupp0->nSize; + return 1; + } + + // compare two cuts with different numbers + i = k = 0; + for ( c = 0; c < nLimit; c++ ) + { + if ( k == pSupp1->nSize ) + { + if ( i == pSupp0->nSize ) + { + pSupp->nSize = c; + return 1; + } + pSupp->pArray[c] = pSupp0->pArray[i++]; + continue; + } + if ( i == pSupp0->nSize ) + { + if ( k == pSupp1->nSize ) + { + pSupp->nSize = c; + return 1; + } + pSupp->pArray[c] = pSupp1->pArray[k++]; + continue; + } + if ( pSupp0->pArray[i] < pSupp1->pArray[k] ) + { + pSupp->pArray[c] = pSupp0->pArray[i++]; + continue; + } + if ( pSupp0->pArray[i] > pSupp1->pArray[k] ) + { + pSupp->pArray[c] = pSupp1->pArray[k++]; + continue; + } + pSupp->pArray[c] = pSupp0->pArray[i++]; + k++; + } + if ( i < pSupp0->nSize || k < pSupp1->nSize ) + return 0; + pSupp->nSize = c; + return 1; +} + +/**Function************************************************************* + + Synopsis [Creates integer vector with the support of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapReadSupp( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Int_t * vLeaves ) +{ + Ivy_Supp_t * pSupp; + pSupp = Ivy_ObjSupp( pAig, pObj ); + vLeaves->nCap = 8; + vLeaves->nSize = pSupp->nSize; + vLeaves->pArray = pSupp->pArray; +} + +/**Function************************************************************* + + Synopsis [Sets the required times of the intermediate nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapRequired_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Ivy_Obj_t * pRoot, int DelayR ) +{ + Ivy_Supp_t * pSupp; + pSupp = Ivy_ObjSupp( pAig, pObj ); + if ( pObj != pRoot && (pSupp->nRefs > 0 || Ivy_ObjIsCi(pObj)) ) + return; + Ivy_FastMapRequired_rec( pAig, Ivy_ObjFanin0(pObj), pRoot, DelayR ); + Ivy_FastMapRequired_rec( pAig, Ivy_ObjFanin1(pObj), pRoot, DelayR ); +// assert( pObj == pRoot || pSupp->DelayR == IVY_INFINITY ); + pSupp->DelayR = DelayR; +} + +/**Function************************************************************* + + Synopsis [Computes the required times for each node.] + + Description [Sets reference counters for each node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapRequired( Ivy_Man_t * pAig, int Delay, int fSetInter ) +{ + Vec_Vec_t * vLuts; + Vec_Ptr_t * vNodes; + Ivy_Obj_t * pObj; + Ivy_Supp_t * pSupp, * pSuppF; + int i, k, c; + // clean the required times + Ivy_ManForEachPi( pAig, pObj, i ) + { + pSupp = Ivy_ObjSupp( pAig, pObj ); + pSupp->DelayR = IVY_INFINITY; + pSupp->nRefs = 0; + } + Ivy_ManForEachNode( pAig, pObj, i ) + { + pSupp = Ivy_ObjSupp( pAig, pObj ); + pSupp->DelayR = IVY_INFINITY; + pSupp->nRefs = 0; + } + // set the required times of the POs + Ivy_ManForEachPo( pAig, pObj, i ) + { + pSupp = Ivy_ObjSupp( pAig, Ivy_ObjFanin0(pObj) ); + pSupp->DelayR = Delay; + pSupp->nRefs++; + } + // get the levelized nodes used in the mapping + vLuts = ((Ivy_SuppMan_t *)pAig->pData)->vLuts; + // propagate the required times + Vec_VecForEachLevelReverse( vLuts, vNodes, i ) + Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pObj, k ) + { + pSupp = Ivy_ObjSupp( pAig, pObj ); + assert( pSupp->nRefs > 0 ); + for ( c = 0; c < pSupp->nSize; c++ ) + { + pSuppF = Ivy_ObjSupp( pAig, Ivy_ManObj(pAig, pSupp->pArray[c]) ); + pSuppF->DelayR = IVY_MIN( pSuppF->DelayR, pSupp->DelayR - 1 ); + pSuppF->nRefs++; + } + } +/* + // print out some of the required times + Ivy_ManForEachPi( pAig, pObj, i ) + { + pSupp = Ivy_ObjSupp( pAig, pObj ); + printf( "%d ", pSupp->DelayR ); + } + printf( "\n" ); +*/ + + if ( fSetInter ) + { + // set the required times of the intermediate nodes + Vec_VecForEachLevelReverse( vLuts, vNodes, i ) + Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pObj, k ) + { + pSupp = Ivy_ObjSupp( pAig, pObj ); + Ivy_FastMapRequired_rec( pAig, pObj, pObj, pSupp->DelayR ); + } + // make sure that all required times are assigned + Ivy_ManForEachNode( pAig, pObj, i ) + { + pSupp = Ivy_ObjSupp( pAig, pObj ); + assert( pSupp->DelayR < IVY_INFINITY ); + } + } +} + +/**Function************************************************************* + + Synopsis [Performs area recovery for each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapRecover( Ivy_Man_t * pAig, int nLimit ) +{ + Vec_Ptr_t * vFront, * vFrontOld; + Ivy_Obj_t * pObj; + int i; + vFront = Vec_PtrAlloc( nLimit ); + vFrontOld = Vec_PtrAlloc( nLimit ); + Ivy_ManCleanTravId( pAig ); + // iterate through all nodes in the topological order + Ivy_ManForEachNode( pAig, pObj, i ) + Ivy_FastMapNodeRecover( pAig, pObj, nLimit, vFront, vFrontOld ); + Vec_PtrFree( vFrontOld ); + Vec_PtrFree( vFront ); +} + +/**Function************************************************************* + + Synopsis [Computes the delay of the cut rooted at this node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapNodeDelay( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + Ivy_Supp_t * pSupp, * pSuppF; + int c, Delay = 0; + pSupp = Ivy_ObjSupp( pAig, pObj ); + for ( c = 0; c < pSupp->nSize; c++ ) + { + pSuppF = Ivy_ObjSupp( pAig, Ivy_ManObj(pAig, pSupp->pArray[c]) ); + Delay = IVY_MAX( Delay, pSuppF->Delay ); + } + return 1 + Delay; +} + + +/**function************************************************************* + + synopsis [References the cut.] + + description [This procedure is similar to the procedure NodeReclaim.] + + sideeffects [] + + seealso [] + +***********************************************************************/ +int Ivy_FastMapNodeRef( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + Ivy_Supp_t * pSupp, * pSuppF; + Ivy_Obj_t * pNodeChild; + int aArea, i; + // start the area of this cut + aArea = 1; + // go through the children + pSupp = Ivy_ObjSupp( pAig, pObj ); + assert( pSupp->nSize > 1 ); + for ( i = 0; i < pSupp->nSize; i++ ) + { + pNodeChild = Ivy_ManObj(pAig, pSupp->pArray[i]); + pSuppF = Ivy_ObjSupp( pAig, pNodeChild ); + assert( pSuppF->nRefs >= 0 ); + if ( pSuppF->nRefs++ > 0 ) + continue; + if ( pSuppF->nSize == 1 ) + continue; + aArea += Ivy_FastMapNodeRef( pAig, pNodeChild ); + } + return aArea; +} + +/**function************************************************************* + + synopsis [Dereferences the cut.] + + description [This procedure is similar to the procedure NodeRecusiveDeref.] + + sideeffects [] + + seealso [] + +***********************************************************************/ +int Ivy_FastMapNodeDeref( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + Ivy_Supp_t * pSupp, * pSuppF; + Ivy_Obj_t * pNodeChild; + int aArea, i; + // start the area of this cut + aArea = 1; + // go through the children + pSupp = Ivy_ObjSupp( pAig, pObj ); + assert( pSupp->nSize > 1 ); + for ( i = 0; i < pSupp->nSize; i++ ) + { + pNodeChild = Ivy_ManObj(pAig, pSupp->pArray[i]); + pSuppF = Ivy_ObjSupp( pAig, pNodeChild ); + assert( pSuppF->nRefs > 0 ); + if ( --pSuppF->nRefs > 0 ) + continue; + if ( pSuppF->nSize == 1 ) + continue; + aArea += Ivy_FastMapNodeDeref( pAig, pNodeChild ); + } + return aArea; +} + +/**function************************************************************* + + synopsis [Computes the exact area associated with the cut.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +int Ivy_FastMapNodeAreaRefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + Ivy_Supp_t * pSupp; + int aResult, aResult2; + if ( Ivy_ObjIsCi(pObj) ) + return 0; + assert( Ivy_ObjIsNode(pObj) ); + pSupp = Ivy_ObjSupp( pAig, pObj ); + assert( pSupp->nRefs > 0 ); + aResult = Ivy_FastMapNodeDeref( pAig, pObj ); + aResult2 = Ivy_FastMapNodeRef( pAig, pObj ); + assert( aResult == aResult2 ); + return aResult; +} + +/**function************************************************************* + + synopsis [Computes the exact area associated with the cut.] + + description [] + + sideeffects [] + + seealso [] + +***********************************************************************/ +int Ivy_FastMapNodeAreaDerefed( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + Ivy_Supp_t * pSupp; + int aResult, aResult2; + if ( Ivy_ObjIsCi(pObj) ) + return 0; + assert( Ivy_ObjIsNode(pObj) ); + pSupp = Ivy_ObjSupp( pAig, pObj ); + assert( pSupp->nRefs == 0 ); + aResult2 = Ivy_FastMapNodeRef( pAig, pObj ); + aResult = Ivy_FastMapNodeDeref( pAig, pObj ); + assert( aResult == aResult2 ); + return aResult; +} + + + + +/**Function************************************************************* + + Synopsis [Counts the number of nodes with no external fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapCutCost( Ivy_Man_t * pAig, Vec_Ptr_t * vFront ) +{ + Ivy_Supp_t * pSuppF; + Ivy_Obj_t * pFanin; + int i, Counter = 0; + Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pFanin, i ) + { + pSuppF = Ivy_ObjSupp( pAig, pFanin ); + if ( pSuppF->nRefs == 0 ) + Counter++; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Performs area recovery for each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapMark_rec( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + if ( Ivy_ObjIsTravIdCurrent(pAig, pObj) ) + return; + assert( Ivy_ObjIsNode(pObj) ); + Ivy_FastMapMark_rec( pAig, Ivy_ObjFanin0(pObj) ); + Ivy_FastMapMark_rec( pAig, Ivy_ObjFanin1(pObj) ); + Ivy_ObjSetTravIdCurrent(pAig, pObj); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the number of fanins will grow.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapNodeWillGrow( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pFanin0, * pFanin1; + assert( Ivy_ObjIsNode(pObj) ); + pFanin0 = Ivy_ObjFanin0(pObj); + pFanin1 = Ivy_ObjFanin1(pObj); + return !Ivy_ObjIsTravIdCurrent(pAig, pFanin0) && !Ivy_ObjIsTravIdCurrent(pAig, pFanin1); +} + +/**Function************************************************************* + + Synopsis [Returns the increase in the number of fanins with no external refs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapNodeFaninCost( Ivy_Man_t * pAig, Ivy_Obj_t * pObj ) +{ + Ivy_Supp_t * pSuppF; + Ivy_Obj_t * pFanin; + int Counter = 0; + assert( Ivy_ObjIsNode(pObj) ); + // check if the node has external refs + pSuppF = Ivy_ObjSupp( pAig, pObj ); + if ( pSuppF->nRefs == 0 ) + Counter--; + // increment the number of fanins without external refs + pFanin = Ivy_ObjFanin0(pObj); + pSuppF = Ivy_ObjSupp( pAig, pFanin ); + if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) && pSuppF->nRefs == 0 ) + Counter++; + // increment the number of fanins without external refs + pFanin = Ivy_ObjFanin1(pObj); + pSuppF = Ivy_ObjSupp( pAig, pFanin ); + if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) && pSuppF->nRefs == 0 ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Updates the frontier.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodeFaninUpdate( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Ptr_t * vFront ) +{ + Ivy_Obj_t * pFanin; + assert( Ivy_ObjIsNode(pObj) ); + Vec_PtrRemove( vFront, pObj ); + pFanin = Ivy_ObjFanin0(pObj); + if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) ) + { + Ivy_ObjSetTravIdCurrent(pAig, pFanin); + Vec_PtrPush( vFront, pFanin ); + } + pFanin = Ivy_ObjFanin1(pObj); + if ( !Ivy_ObjIsTravIdCurrent(pAig, pFanin) ) + { + Ivy_ObjSetTravIdCurrent(pAig, pFanin); + Vec_PtrPush( vFront, pFanin ); + } +} + +/**Function************************************************************* + + Synopsis [Compacts the number of external refs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapNodeFaninCompact0( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) +{ + Ivy_Obj_t * pFanin; + int i; + Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pFanin, i ) + { + if ( Ivy_ObjIsCi(pFanin) ) + continue; + if ( Ivy_FastMapNodeWillGrow(pAig, pFanin) ) + continue; + if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) <= 0 ) + { + Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront ); + return 1; + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Compacts the number of external refs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapNodeFaninCompact1( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) +{ + Ivy_Obj_t * pFanin; + int i; + Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pFanin, i ) + { + if ( Ivy_ObjIsCi(pFanin) ) + continue; + if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) < 0 ) + { + Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront ); + return 1; + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Compacts the number of external refs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapNodeFaninCompact2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) +{ + Ivy_Obj_t * pFanin; + int i; + Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pFanin, i ) + { + if ( Ivy_ObjIsCi(pFanin) ) + continue; + if ( Ivy_FastMapNodeFaninCost(pAig, pFanin) <= 0 ) + { + Ivy_FastMapNodeFaninUpdate( pAig, pFanin, vFront ); + return 1; + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Compacts the number of external refs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FastMapNodeFaninCompact_int( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) +{ + if ( Ivy_FastMapNodeFaninCompact0(pAig, pObj, nLimit, vFront) ) + return 1; + if ( Vec_PtrSize(vFront) < nLimit && Ivy_FastMapNodeFaninCompact1(pAig, pObj, nLimit, vFront) ) + return 1; + if ( Vec_PtrSize(vFront) < nLimit && Ivy_FastMapNodeFaninCompact2(pAig, pObj, nLimit, vFront) ) + return 1; + assert( Vec_PtrSize(vFront) <= nLimit ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Compacts the number of external refs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodeFaninCompact( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront ) +{ + while ( Ivy_FastMapNodeFaninCompact_int( pAig, pObj, nLimit, vFront ) ); +} + +/**Function************************************************************* + + Synopsis [Prepares node mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodePrepare( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ) +{ + Ivy_Supp_t * pSupp; + Ivy_Obj_t * pFanin; + int i; + pSupp = Ivy_ObjSupp( pAig, pObj ); + // expand the cut downwards from the given place + Vec_PtrClear( vFront ); + Vec_PtrClear( vFrontOld ); + Ivy_ManIncrementTravId( pAig ); + for ( i = 0; i < pSupp->nSize; i++ ) + { + pFanin = Ivy_ManObj(pAig, pSupp->pArray[i]); + Vec_PtrPush( vFront, pFanin ); + Vec_PtrPush( vFrontOld, pFanin ); + Ivy_ObjSetTravIdCurrent( pAig, pFanin ); + } + // mark the nodes in the cone + Ivy_FastMapMark_rec( pAig, pObj ); +} + +/**Function************************************************************* + + Synopsis [Updates the frontier.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodeUpdate( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, Vec_Ptr_t * vFront ) +{ + Ivy_Supp_t * pSupp; + Ivy_Obj_t * pFanin; + int i; + pSupp = Ivy_ObjSupp( pAig, pObj ); + // deref node's cut + Ivy_FastMapNodeDeref( pAig, pObj ); + // update the node's cut + pSupp->nSize = Vec_PtrSize(vFront); + Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pFanin, i ) + pSupp->pArray[i] = pFanin->Id; + // ref the new cut + Ivy_FastMapNodeRef( pAig, pObj ); +} + +/**Function************************************************************* + + Synopsis [Performs area recovery for each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodeRecover2( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ) +{ + Ivy_Supp_t * pSupp; + int CostBef, CostAft; + int AreaBef, AreaAft; + pSupp = Ivy_ObjSupp( pAig, pObj ); +// if ( pSupp->nRefs == 0 ) +// return; + if ( pSupp->nRefs == 0 ) + AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj ); + else + AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + // get the area + if ( AreaBef == 1 ) + return; + + if ( pSupp->nRefs == 0 ) + { + pSupp->nRefs = 1000000; + Ivy_FastMapNodeRef( pAig, pObj ); + } + // the cut is non-trivial + Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld ); + // iteratively modify the cut + CostBef = Ivy_FastMapCutCost( pAig, vFront ); + Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront ); + CostAft = Ivy_FastMapCutCost( pAig, vFront ); + assert( CostBef >= CostAft ); + // update the node + Ivy_FastMapNodeUpdate( pAig, pObj, vFront ); + // get the new area + AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + if ( AreaAft > AreaBef ) + { + Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld ); + AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + assert( AreaAft == AreaBef ); + } + if ( pSupp->nRefs == 1000000 ) + { + pSupp->nRefs = 0; + Ivy_FastMapNodeDeref( pAig, pObj ); + } +} + +/**Function************************************************************* + + Synopsis [Performs area recovery for each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodeRecover( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ) +{ + Ivy_Supp_t * pSupp; + int CostBef, CostAft; + int AreaBef, AreaAft; + int DelayOld; + pSupp = Ivy_ObjSupp( pAig, pObj ); + DelayOld = pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj ); + assert( pSupp->Delay <= pSupp->DelayR ); + if ( pSupp->nRefs == 0 ) + return; + // get the area + AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); +// if ( AreaBef == 1 ) +// return; + // the cut is non-trivial + Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld ); + // iteratively modify the cut + Ivy_FastMapNodeDeref( pAig, pObj ); + CostBef = Ivy_FastMapCutCost( pAig, vFront ); + Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront ); + CostAft = Ivy_FastMapCutCost( pAig, vFront ); + Ivy_FastMapNodeRef( pAig, pObj ); + assert( CostBef >= CostAft ); + // update the node + Ivy_FastMapNodeUpdate( pAig, pObj, vFront ); + pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj ); + // get the new area + AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR ) + { + Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld ); + AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + assert( AreaAft == AreaBef ); + pSupp->Delay = DelayOld; + } +} + +/**Function************************************************************* + + Synopsis [Performs area recovery for each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FastMapNodeRecover4( Ivy_Man_t * pAig, Ivy_Obj_t * pObj, int nLimit, Vec_Ptr_t * vFront, Vec_Ptr_t * vFrontOld ) +{ + Ivy_Supp_t * pSupp; + int CostBef, CostAft; + int AreaBef, AreaAft; + int DelayOld; + pSupp = Ivy_ObjSupp( pAig, pObj ); + DelayOld = pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj ); + assert( pSupp->Delay <= pSupp->DelayR ); +// if ( pSupp->nRefs == 0 ) +// return; +// AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + // get the area + if ( pSupp->nRefs == 0 ) + AreaBef = Ivy_FastMapNodeAreaDerefed( pAig, pObj ); + else + AreaBef = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + if ( AreaBef == 1 ) + return; + + if ( pSupp->nRefs == 0 ) + { + pSupp->nRefs = 1000000; + Ivy_FastMapNodeRef( pAig, pObj ); + } + // the cut is non-trivial + Ivy_FastMapNodePrepare( pAig, pObj, nLimit, vFront, vFrontOld ); + // iteratively modify the cut + CostBef = Ivy_FastMapCutCost( pAig, vFront ); + Ivy_FastMapNodeFaninCompact( pAig, pObj, nLimit, vFront ); + CostAft = Ivy_FastMapCutCost( pAig, vFront ); + assert( CostBef >= CostAft ); + // update the node + Ivy_FastMapNodeUpdate( pAig, pObj, vFront ); + pSupp->Delay = Ivy_FastMapNodeDelay( pAig, pObj ); + // get the new area + AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + if ( AreaAft > AreaBef || pSupp->Delay > pSupp->DelayR ) + { + Ivy_FastMapNodeUpdate( pAig, pObj, vFrontOld ); + AreaAft = Ivy_FastMapNodeAreaRefed( pAig, pObj ); + assert( AreaAft == AreaBef ); + pSupp->Delay = DelayOld; + } + if ( pSupp->nRefs == 1000000 ) + { + pSupp->nRefs = 0; + Ivy_FastMapNodeDeref( pAig, pObj ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/ivyFraig.c b/yosys/abc/src/aig/ivy/ivyFraig.c new file mode 100644 index 00000000000..0bf05ee8863 --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivyFraig.c @@ -0,0 +1,2972 @@ +/**CFile**************************************************************** + + FileName [ivyFraig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Functional reduction of AIGs] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyFraig.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include + +#include "sat/bsat/satSolver.h" +#include "misc/extra/extra.h" +#include "ivy.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Ivy_FraigMan_t_ Ivy_FraigMan_t; +typedef struct Ivy_FraigSim_t_ Ivy_FraigSim_t; +typedef struct Ivy_FraigList_t_ Ivy_FraigList_t; + +struct Ivy_FraigList_t_ +{ + Ivy_Obj_t * pHead; + Ivy_Obj_t * pTail; + int nItems; +}; + +struct Ivy_FraigSim_t_ +{ + int Type; + Ivy_FraigSim_t * pNext; + Ivy_FraigSim_t * pFanin0; + Ivy_FraigSim_t * pFanin1; + unsigned pData[0]; +}; + +struct Ivy_FraigMan_t_ +{ + // general info + Ivy_FraigParams_t * pParams; // various parameters + // temporary backtrack limits because "ABC_INT64_T" cannot be defined in Ivy_FraigParams_t ... + ABC_INT64_T nBTLimitGlobal; // global limit on the number of backtracks + ABC_INT64_T nInsLimitGlobal;// global limit on the number of clause inspects + // AIG manager + Ivy_Man_t * pManAig; // the starting AIG manager + Ivy_Man_t * pManFraig; // the final AIG manager + // simulation information + int nSimWords; // the number of words + char * pSimWords; // the simulation info + Ivy_FraigSim_t * pSimStart; // the list of simulation info for internal nodes + // counter example storage + int nPatWords; // the number of words in the counter example + unsigned * pPatWords; // the counter example + int * pPatScores; // the scores of each pattern + // equivalence classes + Ivy_FraigList_t lClasses; // equivalence classes + Ivy_FraigList_t lCand; // candidatates + int nPairs; // the number of pairs of nodes + // equivalence checking + sat_solver * pSat; // SAT solver + int nSatVars; // the number of variables currently used + Vec_Ptr_t * vPiVars; // the PIs of the cone used + // other + ProgressBar * pProgress; + // statistics + int nSimRounds; + int nNodesMiter; + int nClassesZero; + int nClassesBeg; + int nClassesEnd; + int nPairsBeg; + int nPairsEnd; + int nSatCalls; + int nSatCallsSat; + int nSatCallsUnsat; + int nSatProof; + int nSatFails; + int nSatFailsReal; + // runtime + abctime timeSim; + abctime timeTrav; + abctime timeSat; + abctime timeSatUnsat; + abctime timeSatSat; + abctime timeSatFail; + abctime timeRef; + abctime timeTotal; + abctime time1; + abctime time2; +}; + +typedef struct Prove_ParamsStruct_t_ Prove_Params_t; +struct Prove_ParamsStruct_t_ +{ + // general parameters + int fUseFraiging; // enables fraiging + int fUseRewriting; // enables rewriting + int fUseBdds; // enables BDD construction when other methods fail + int fVerbose; // prints verbose stats + // iterations + int nItersMax; // the number of iterations + // mitering + int nMiteringLimitStart; // starting mitering limit + float nMiteringLimitMulti; // multiplicative coefficient to increase the limit in each iteration + // rewriting + int nRewritingLimitStart; // the number of rewriting iterations + float nRewritingLimitMulti; // multiplicative coefficient to increase the limit in each iteration + // fraiging + int nFraigingLimitStart; // starting backtrack(conflict) limit + float nFraigingLimitMulti; // multiplicative coefficient to increase the limit in each iteration + // last-gasp BDD construction + int nBddSizeLimit; // the number of BDD nodes when construction is aborted + int fBddReorder; // enables dynamic BDD variable reordering + // last-gasp mitering + int nMiteringLimitLast; // final mitering limit + // global SAT solver limits + ABC_INT64_T nTotalBacktrackLimit; // global limit on the number of backtracks + ABC_INT64_T nTotalInspectLimit; // global limit on the number of clause inspects + // global resources applied + ABC_INT64_T nTotalBacktracksMade; // the total number of backtracks made + ABC_INT64_T nTotalInspectsMade; // the total number of inspects made +}; + +static inline Ivy_FraigSim_t * Ivy_ObjSim( Ivy_Obj_t * pObj ) { return (Ivy_FraigSim_t *)pObj->pFanout; } +static inline Ivy_Obj_t * Ivy_ObjClassNodeLast( Ivy_Obj_t * pObj ) { return pObj->pNextFan0; } +static inline Ivy_Obj_t * Ivy_ObjClassNodeRepr( Ivy_Obj_t * pObj ) { return pObj->pNextFan0; } +static inline Ivy_Obj_t * Ivy_ObjClassNodeNext( Ivy_Obj_t * pObj ) { return pObj->pNextFan1; } +static inline Ivy_Obj_t * Ivy_ObjNodeHashNext( Ivy_Obj_t * pObj ) { return pObj->pPrevFan0; } +static inline Ivy_Obj_t * Ivy_ObjEquivListNext( Ivy_Obj_t * pObj ) { return pObj->pPrevFan0; } +static inline Ivy_Obj_t * Ivy_ObjEquivListPrev( Ivy_Obj_t * pObj ) { return pObj->pPrevFan1; } +static inline Ivy_Obj_t * Ivy_ObjFraig( Ivy_Obj_t * pObj ) { return pObj->pEquiv; } +static inline int Ivy_ObjSatNum( Ivy_Obj_t * pObj ) { return (int)(ABC_PTRUINT_T)pObj->pNextFan0; } +static inline Vec_Ptr_t * Ivy_ObjFaninVec( Ivy_Obj_t * pObj ) { return (Vec_Ptr_t *)pObj->pNextFan1; } + +static inline void Ivy_ObjSetSim( Ivy_Obj_t * pObj, Ivy_FraigSim_t * pSim ) { pObj->pFanout = (Ivy_Obj_t *)pSim; } +static inline void Ivy_ObjSetClassNodeLast( Ivy_Obj_t * pObj, Ivy_Obj_t * pLast ) { pObj->pNextFan0 = pLast; } +static inline void Ivy_ObjSetClassNodeRepr( Ivy_Obj_t * pObj, Ivy_Obj_t * pRepr ) { pObj->pNextFan0 = pRepr; } +static inline void Ivy_ObjSetClassNodeNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pNextFan1 = pNext; } +static inline void Ivy_ObjSetNodeHashNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pPrevFan0 = pNext; } +static inline void Ivy_ObjSetEquivListNext( Ivy_Obj_t * pObj, Ivy_Obj_t * pNext ) { pObj->pPrevFan0 = pNext; } +static inline void Ivy_ObjSetEquivListPrev( Ivy_Obj_t * pObj, Ivy_Obj_t * pPrev ) { pObj->pPrevFan1 = pPrev; } +static inline void Ivy_ObjSetFraig( Ivy_Obj_t * pObj, Ivy_Obj_t * pNode ) { pObj->pEquiv = pNode; } +static inline void Ivy_ObjSetSatNum( Ivy_Obj_t * pObj, int Num ) { pObj->pNextFan0 = (Ivy_Obj_t *)(ABC_PTRUINT_T)Num; } +static inline void Ivy_ObjSetFaninVec( Ivy_Obj_t * pObj, Vec_Ptr_t * vFanins ) { pObj->pNextFan1 = (Ivy_Obj_t *)vFanins; } + +static inline unsigned Ivy_ObjRandomSim() { return (rand() << 24) ^ (rand() << 12) ^ rand(); } + +// iterate through equivalence classes +#define Ivy_FraigForEachEquivClass( pList, pEnt ) \ + for ( pEnt = pList; \ + pEnt; \ + pEnt = Ivy_ObjEquivListNext(pEnt) ) +#define Ivy_FraigForEachEquivClassSafe( pList, pEnt, pEnt2 ) \ + for ( pEnt = pList, \ + pEnt2 = pEnt? Ivy_ObjEquivListNext(pEnt): NULL; \ + pEnt; \ + pEnt = pEnt2, \ + pEnt2 = pEnt? Ivy_ObjEquivListNext(pEnt): NULL ) +// iterate through nodes in one class +#define Ivy_FraigForEachClassNode( pClass, pEnt ) \ + for ( pEnt = pClass; \ + pEnt; \ + pEnt = Ivy_ObjClassNodeNext(pEnt) ) +// iterate through nodes in the hash table +#define Ivy_FraigForEachBinNode( pBin, pEnt ) \ + for ( pEnt = pBin; \ + pEnt; \ + pEnt = Ivy_ObjNodeHashNext(pEnt) ) + +static Ivy_FraigMan_t * Ivy_FraigStart( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); +static Ivy_FraigMan_t * Ivy_FraigStartSimple( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ); +static Ivy_Man_t * Ivy_FraigPerform_int( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams, ABC_INT64_T nBTLimitGlobal, ABC_INT64_T nInsLimitGlobal, ABC_INT64_T * pnSatConfs, ABC_INT64_T * pnSatInspects ); +static void Ivy_FraigPrint( Ivy_FraigMan_t * p ); +static void Ivy_FraigStop( Ivy_FraigMan_t * p ); +static void Ivy_FraigSimulate( Ivy_FraigMan_t * p ); +static void Ivy_FraigSweep( Ivy_FraigMan_t * p ); +static Ivy_Obj_t * Ivy_FraigAnd( Ivy_FraigMan_t * p, Ivy_Obj_t * pObjOld ); +static int Ivy_FraigNodesAreEquiv( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ); +static int Ivy_FraigNodeIsConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ); +static void Ivy_FraigNodeAddToSolver( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ); +static int Ivy_FraigSetActivityFactors( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ); +static void Ivy_FraigAddToPatScores( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass, Ivy_Obj_t * pClassNew ); +static int Ivy_FraigMiterStatus( Ivy_Man_t * pMan ); +static void Ivy_FraigMiterProve( Ivy_FraigMan_t * p ); +static void Ivy_FraigMiterPrint( Ivy_Man_t * pNtk, char * pString, abctime clk, int fVerbose ); +static int * Ivy_FraigCreateModel( Ivy_FraigMan_t * p ); + +static int Ivy_FraigNodesAreEquivBdd( Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2 ); +static int Ivy_FraigCheckCone( Ivy_FraigMan_t * pGlo, Ivy_Man_t * p, Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2, int nConfLimit ); + +static ABC_INT64_T s_nBTLimitGlobal = 0; +static ABC_INT64_T s_nInsLimitGlobal = 0; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Sets the default solving parameters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigParamsDefault( Ivy_FraigParams_t * pParams ) +{ + memset( pParams, 0, sizeof(Ivy_FraigParams_t) ); + pParams->nSimWords = 32; // the number of words in the simulation info + pParams->dSimSatur = 0.005; // the ratio of refined classes when saturation is reached + pParams->fPatScores = 0; // enables simulation pattern scoring + pParams->MaxScore = 25; // max score after which resimulation is used + pParams->fDoSparse = 1; // skips sparse functions +// pParams->dActConeRatio = 0.05; // the ratio of cone to be bumped +// pParams->dActConeBumpMax = 5.0; // the largest bump of activity + pParams->dActConeRatio = 0.3; // the ratio of cone to be bumped + pParams->dActConeBumpMax = 10.0; // the largest bump of activity + + pParams->nBTLimitNode = 100; // conflict limit at a node + pParams->nBTLimitMiter = 500000; // conflict limit at an output +// pParams->nBTLimitGlobal = 0; // conflict limit global +// pParams->nInsLimitGlobal = 0; // inspection limit global +} + +/**Function************************************************************* + + Synopsis [Performs combinational equivalence checking for the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigProve( Ivy_Man_t ** ppManAig, void * pPars ) +{ + Prove_Params_t * pParams = (Prove_Params_t *)pPars; + Ivy_FraigParams_t Params, * pIvyParams = &Params; + Ivy_Man_t * pManAig, * pManTemp; + int RetValue, nIter; + abctime clk;//, Counter; + ABC_INT64_T nSatConfs = 0, nSatInspects = 0; + + // start the network and parameters + pManAig = *ppManAig; + Ivy_FraigParamsDefault( pIvyParams ); + pIvyParams->fVerbose = pParams->fVerbose; + pIvyParams->fProve = 1; + + if ( pParams->fVerbose ) + { + printf( "RESOURCE LIMITS: Iterations = %d. Rewriting = %s. Fraiging = %s.\n", + pParams->nItersMax, pParams->fUseRewriting? "yes":"no", pParams->fUseFraiging? "yes":"no" ); + printf( "Miter = %d (%3.1f). Rwr = %d (%3.1f). Fraig = %d (%3.1f). Last = %d.\n", + pParams->nMiteringLimitStart, pParams->nMiteringLimitMulti, + pParams->nRewritingLimitStart, pParams->nRewritingLimitMulti, + pParams->nFraigingLimitStart, pParams->nFraigingLimitMulti, pParams->nMiteringLimitLast ); + } + + // if SAT only, solve without iteration + if ( !pParams->fUseRewriting && !pParams->fUseFraiging ) + { + clk = Abc_Clock(); + pIvyParams->nBTLimitMiter = pParams->nMiteringLimitLast / Ivy_ManPoNum(pManAig); + pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams ); Ivy_ManStop( pManTemp ); + RetValue = Ivy_FraigMiterStatus( pManAig ); + Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose ); + *ppManAig = pManAig; + return RetValue; + } + + if ( Ivy_ManNodeNum(pManAig) < 500 ) + { + // run the first mitering + clk = Abc_Clock(); + pIvyParams->nBTLimitMiter = pParams->nMiteringLimitStart / Ivy_ManPoNum(pManAig); + pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams ); Ivy_ManStop( pManTemp ); + RetValue = Ivy_FraigMiterStatus( pManAig ); + Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose ); + if ( RetValue >= 0 ) + { + *ppManAig = pManAig; + return RetValue; + } + } + + // check the current resource limits + RetValue = -1; + for ( nIter = 0; nIter < pParams->nItersMax; nIter++ ) + { + if ( pParams->fVerbose ) + { + printf( "ITERATION %2d : Confs = %6d. FraigBTL = %3d. \n", nIter+1, + (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), + (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)) ); + fflush( stdout ); + } + + // try rewriting + if ( pParams->fUseRewriting ) + { // bug in Ivy_NodeFindCutsAll() when leaves are identical! +/* + clk = Abc_Clock(); + Counter = (int)(pParams->nRewritingLimitStart * pow(pParams->nRewritingLimitMulti,nIter)); + pManAig = Ivy_ManRwsat( pManAig, 0 ); + RetValue = Ivy_FraigMiterStatus( pManAig ); + Ivy_FraigMiterPrint( pManAig, "Rewriting ", clk, pParams->fVerbose ); +*/ + } + if ( RetValue >= 0 ) + break; + + // catch the situation when ref pattern detects the bug + RetValue = Ivy_FraigMiterStatus( pManAig ); + if ( RetValue >= 0 ) + break; + + // try fraiging followed by mitering + if ( pParams->fUseFraiging ) + { + clk = Abc_Clock(); + pIvyParams->nBTLimitNode = (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)); + pIvyParams->nBTLimitMiter = 1 + (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)) / Ivy_ManPoNum(pManAig); + pManAig = Ivy_FraigPerform_int( pManTemp = pManAig, pIvyParams, pParams->nTotalBacktrackLimit, pParams->nTotalInspectLimit, &nSatConfs, &nSatInspects ); Ivy_ManStop( pManTemp ); + RetValue = Ivy_FraigMiterStatus( pManAig ); + Ivy_FraigMiterPrint( pManAig, "Fraiging ", clk, pParams->fVerbose ); + } + if ( RetValue >= 0 ) + break; + + // add to the number of backtracks and inspects + pParams->nTotalBacktracksMade += nSatConfs; + pParams->nTotalInspectsMade += nSatInspects; + // check if global resource limit is reached + if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) || + (pParams->nTotalInspectLimit && pParams->nTotalInspectsMade >= pParams->nTotalInspectLimit) ) + { + printf( "Reached global limit on conflicts/inspects. Quitting.\n" ); + *ppManAig = pManAig; + return -1; + } + } +/* + if ( RetValue < 0 ) + { + if ( pParams->fVerbose ) + { + printf( "Attempting SAT with conflict limit %d ...\n", pParams->nMiteringLimitLast ); + fflush( stdout ); + } + clk = Abc_Clock(); + pIvyParams->nBTLimitMiter = pParams->nMiteringLimitLast / Ivy_ManPoNum(pManAig); + if ( pParams->nTotalBacktrackLimit ) + s_nBTLimitGlobal = pParams->nTotalBacktrackLimit - pParams->nTotalBacktracksMade; + if ( pParams->nTotalInspectLimit ) + s_nInsLimitGlobal = pParams->nTotalInspectLimit - pParams->nTotalInspectsMade; + pManAig = Ivy_FraigMiter( pManTemp = pManAig, pIvyParams ); Ivy_ManStop( pManTemp ); + s_nBTLimitGlobal = 0; + s_nInsLimitGlobal = 0; + RetValue = Ivy_FraigMiterStatus( pManAig ); + Ivy_FraigMiterPrint( pManAig, "SAT solving", clk, pParams->fVerbose ); + // make sure that the sover never returns "undecided" when infinite resource limits are set + if( RetValue == -1 && pParams->nTotalInspectLimit == 0 && + pParams->nTotalBacktrackLimit == 0 ) + { + extern void Prove_ParamsPrint( Prove_Params_t * pParams ); + Prove_ParamsPrint( pParams ); + printf("ERROR: ABC has returned \"undecided\" in spite of no limits...\n"); + exit(1); + } + } +*/ + // assign the model if it was proved by rewriting (const 1 miter) + if ( RetValue == 0 && pManAig->pData == NULL ) + { + pManAig->pData = ABC_ALLOC( int, Ivy_ManPiNum(pManAig) ); + memset( pManAig->pData, 0, sizeof(int) * Ivy_ManPiNum(pManAig) ); + } + *ppManAig = pManAig; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Performs fraiging of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_FraigPerform_int( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams, ABC_INT64_T nBTLimitGlobal, ABC_INT64_T nInsLimitGlobal, ABC_INT64_T * pnSatConfs, ABC_INT64_T * pnSatInspects ) +{ + Ivy_FraigMan_t * p; + Ivy_Man_t * pManAigNew; + abctime clk; + if ( Ivy_ManNodeNum(pManAig) == 0 ) + return Ivy_ManDup(pManAig); +clk = Abc_Clock(); + assert( Ivy_ManLatchNum(pManAig) == 0 ); + p = Ivy_FraigStart( pManAig, pParams ); + // set global limits + p->nBTLimitGlobal = nBTLimitGlobal; + p->nInsLimitGlobal = nInsLimitGlobal; + + Ivy_FraigSimulate( p ); + Ivy_FraigSweep( p ); + pManAigNew = p->pManFraig; +p->timeTotal = Abc_Clock() - clk; + if ( pnSatConfs ) + *pnSatConfs = p->pSat? p->pSat->stats.conflicts : 0; + if ( pnSatInspects ) + *pnSatInspects = p->pSat? p->pSat->stats.inspects : 0; + Ivy_FraigStop( p ); + return pManAigNew; +} + +/**Function************************************************************* + + Synopsis [Performs fraiging of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_FraigPerform( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) +{ + Ivy_FraigMan_t * p; + Ivy_Man_t * pManAigNew; + abctime clk; + if ( Ivy_ManNodeNum(pManAig) == 0 ) + return Ivy_ManDup(pManAig); +clk = Abc_Clock(); + assert( Ivy_ManLatchNum(pManAig) == 0 ); + p = Ivy_FraigStart( pManAig, pParams ); + Ivy_FraigSimulate( p ); + Ivy_FraigSweep( p ); + pManAigNew = p->pManFraig; +p->timeTotal = Abc_Clock() - clk; + Ivy_FraigStop( p ); + return pManAigNew; +} + +/**Function************************************************************* + + Synopsis [Applies brute-force SAT to the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_FraigMiter( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) +{ + Ivy_FraigMan_t * p; + Ivy_Man_t * pManAigNew; + Ivy_Obj_t * pObj; + int i; + abctime clk; +clk = Abc_Clock(); + assert( Ivy_ManLatchNum(pManAig) == 0 ); + p = Ivy_FraigStartSimple( pManAig, pParams ); + // set global limits + p->nBTLimitGlobal = s_nBTLimitGlobal; + p->nInsLimitGlobal = s_nInsLimitGlobal; + // duplicate internal nodes + Ivy_ManForEachNode( p->pManAig, pObj, i ) + pObj->pEquiv = Ivy_And( p->pManFraig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); + // try to prove each output of the miter + Ivy_FraigMiterProve( p ); + // add the POs + Ivy_ManForEachPo( p->pManAig, pObj, i ) + Ivy_ObjCreatePo( p->pManFraig, Ivy_ObjChild0Equiv(pObj) ); + // clean the new manager + Ivy_ManForEachObj( p->pManFraig, pObj, i ) + { + if ( Ivy_ObjFaninVec(pObj) ) + Vec_PtrFree( Ivy_ObjFaninVec(pObj) ); + pObj->pNextFan0 = pObj->pNextFan1 = NULL; + } + // remove dangling nodes + Ivy_ManCleanup( p->pManFraig ); + pManAigNew = p->pManFraig; +p->timeTotal = Abc_Clock() - clk; + +//printf( "Final nodes = %6d. ", Ivy_ManNodeNum(pManAigNew) ); +//ABC_PRT( "Time", p->timeTotal ); + Ivy_FraigStop( p ); + return pManAigNew; +} + +/**Function************************************************************* + + Synopsis [Starts the fraiging manager without simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_FraigMan_t * Ivy_FraigStartSimple( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) +{ + Ivy_FraigMan_t * p; + // allocat the fraiging manager + p = ABC_ALLOC( Ivy_FraigMan_t, 1 ); + memset( p, 0, sizeof(Ivy_FraigMan_t) ); + p->pParams = pParams; + p->pManAig = pManAig; + p->pManFraig = Ivy_ManStartFrom( pManAig ); + p->vPiVars = Vec_PtrAlloc( 100 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Starts the fraiging manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_FraigMan_t * Ivy_FraigStart( Ivy_Man_t * pManAig, Ivy_FraigParams_t * pParams ) +{ + Ivy_FraigMan_t * p; + Ivy_FraigSim_t * pSims; + Ivy_Obj_t * pObj; + int i, k, EntrySize; + // clean the fanout representation + Ivy_ManForEachObj( pManAig, pObj, i ) +// pObj->pEquiv = pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL; + assert( !pObj->pEquiv && !pObj->pFanout ); + // allocat the fraiging manager + p = ABC_ALLOC( Ivy_FraigMan_t, 1 ); + memset( p, 0, sizeof(Ivy_FraigMan_t) ); + p->pParams = pParams; + p->pManAig = pManAig; + p->pManFraig = Ivy_ManStartFrom( pManAig ); + // allocate simulation info + p->nSimWords = pParams->nSimWords; +// p->pSimWords = ABC_ALLOC( unsigned, Ivy_ManObjNum(pManAig) * p->nSimWords ); + EntrySize = sizeof(Ivy_FraigSim_t) + sizeof(unsigned) * p->nSimWords; + p->pSimWords = (char *)ABC_ALLOC( char, Ivy_ManObjNum(pManAig) * EntrySize ); + memset( p->pSimWords, 0, (size_t)EntrySize ); + k = 0; + Ivy_ManForEachObj( pManAig, pObj, i ) + { + pSims = (Ivy_FraigSim_t *)(p->pSimWords + EntrySize * k++); + pSims->pNext = NULL; + if ( Ivy_ObjIsNode(pObj) ) + { + if ( p->pSimStart == NULL ) + p->pSimStart = pSims; + else + ((Ivy_FraigSim_t *)(p->pSimWords + EntrySize * (k-2)))->pNext = pSims; + pSims->pFanin0 = Ivy_ObjSim( Ivy_ObjFanin0(pObj) ); + pSims->pFanin1 = Ivy_ObjSim( Ivy_ObjFanin1(pObj) ); + pSims->Type = (Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) << 2) | (Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj)) << 1) | pObj->fPhase; + } + else + { + pSims->pFanin0 = NULL; + pSims->pFanin1 = NULL; + pSims->Type = 0; + } + Ivy_ObjSetSim( pObj, pSims ); + } + assert( k == Ivy_ManObjNum(pManAig) ); + // allocate storage for sim pattern + p->nPatWords = Ivy_BitWordNum( Ivy_ManPiNum(pManAig) ); + p->pPatWords = ABC_ALLOC( unsigned, p->nPatWords ); + p->pPatScores = ABC_ALLOC( int, 32 * p->nSimWords ); + p->vPiVars = Vec_PtrAlloc( 100 ); + // set random number generator + srand( 0xABCABC ); + return p; +} + +/**Function************************************************************* + + Synopsis [Stops the fraiging manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigStop( Ivy_FraigMan_t * p ) +{ + if ( p->pParams->fVerbose ) + Ivy_FraigPrint( p ); + if ( p->vPiVars ) Vec_PtrFree( p->vPiVars ); + if ( p->pSat ) sat_solver_delete( p->pSat ); + ABC_FREE( p->pPatScores ); + ABC_FREE( p->pPatWords ); + ABC_FREE( p->pSimWords ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Prints stats for the fraiging manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigPrint( Ivy_FraigMan_t * p ) +{ + double nMemory; + nMemory = (double)Ivy_ManObjNum(p->pManAig)*p->nSimWords*sizeof(unsigned)/(1<<20); + printf( "SimWords = %d. Rounds = %d. Mem = %0.2f MB. ", p->nSimWords, p->nSimRounds, nMemory ); + printf( "Classes: Beg = %d. End = %d.\n", p->nClassesBeg, p->nClassesEnd ); +// printf( "Limits: BTNode = %d. BTMiter = %d.\n", p->pParams->nBTLimitNode, p->pParams->nBTLimitMiter ); + printf( "Proof = %d. Counter-example = %d. Fail = %d. FailReal = %d. Zero = %d.\n", + p->nSatProof, p->nSatCallsSat, p->nSatFails, p->nSatFailsReal, p->nClassesZero ); + printf( "Final = %d. Miter = %d. Total = %d. Mux = %d. (Exor = %d.) SatVars = %d.\n", + Ivy_ManNodeNum(p->pManFraig), p->nNodesMiter, Ivy_ManNodeNum(p->pManAig), 0, 0, p->nSatVars ); + if ( p->pSat ) Sat_SolverPrintStats( stdout, p->pSat ); + ABC_PRT( "AIG simulation ", p->timeSim ); + ABC_PRT( "AIG traversal ", p->timeTrav ); + ABC_PRT( "SAT solving ", p->timeSat ); + ABC_PRT( " Unsat ", p->timeSatUnsat ); + ABC_PRT( " Sat ", p->timeSatSat ); + ABC_PRT( " Fail ", p->timeSatFail ); + ABC_PRT( "Class refining ", p->timeRef ); + ABC_PRT( "TOTAL RUNTIME ", p->timeTotal ); + if ( p->time1 ) { ABC_PRT( "time1 ", p->time1 ); } +} + + + +/**Function************************************************************* + + Synopsis [Assigns random patterns to the PI node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeAssignRandom( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_FraigSim_t * pSims; + int i; + assert( Ivy_ObjIsPi(pObj) ); + pSims = Ivy_ObjSim(pObj); + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = Ivy_ObjRandomSim(); +} + +/**Function************************************************************* + + Synopsis [Assigns constant patterns to the PI node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeAssignConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, int fConst1 ) +{ + Ivy_FraigSim_t * pSims; + int i; + assert( Ivy_ObjIsPi(pObj) ); + pSims = Ivy_ObjSim(pObj); + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = fConst1? ~(unsigned)0 : 0; +} + +/**Function************************************************************* + + Synopsis [Assings random simulation info for the PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigAssignRandom( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + Ivy_ManForEachPi( p->pManAig, pObj, i ) + Ivy_NodeAssignRandom( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Assings distance-1 simulation info for the PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigAssignDist1( Ivy_FraigMan_t * p, unsigned * pPat ) +{ + Ivy_Obj_t * pObj; + int i, Limit; + Ivy_ManForEachPi( p->pManAig, pObj, i ) + { + Ivy_NodeAssignConst( p, pObj, Ivy_InfoHasBit(pPat, i) ); +// printf( "%d", Ivy_InfoHasBit(pPat, i) ); + } +// printf( "\n" ); + + Limit = IVY_MIN( Ivy_ManPiNum(p->pManAig), p->nSimWords * 32 - 1 ); + for ( i = 0; i < Limit; i++ ) + Ivy_InfoXorBit( Ivy_ObjSim( Ivy_ManPi(p->pManAig,i) )->pData, i+1 ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation info is composed of all zeros.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeHasZeroSim( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_FraigSim_t * pSims; + int i; + pSims = Ivy_ObjSim(pObj); + for ( i = 0; i < p->nSimWords; i++ ) + if ( pSims->pData[i] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation info is composed of all zeros.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeComplementSim( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_FraigSim_t * pSims; + int i; + pSims = Ivy_ObjSim(pObj); + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = ~pSims->pData[i]; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation infos are equal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeCompareSims( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj0, Ivy_Obj_t * pObj1 ) +{ + Ivy_FraigSim_t * pSims0, * pSims1; + int i; + pSims0 = Ivy_ObjSim(pObj0); + pSims1 = Ivy_ObjSim(pObj1); + for ( i = 0; i < p->nSimWords; i++ ) + if ( pSims0->pData[i] != pSims1->pData[i] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeSimulateSim( Ivy_FraigMan_t * p, Ivy_FraigSim_t * pSims ) +{ + unsigned * pData, * pData0, * pData1; + int i; + pData = pSims->pData; + pData0 = pSims->pFanin0->pData; + pData1 = pSims->pFanin1->pData; + switch( pSims->Type ) + { + case 0: + for ( i = 0; i < p->nSimWords; i++ ) + pData[i] = (pData0[i] & pData1[i]); + break; + case 1: + for ( i = 0; i < p->nSimWords; i++ ) + pData[i] = ~(pData0[i] & pData1[i]); + break; + case 2: + for ( i = 0; i < p->nSimWords; i++ ) + pData[i] = (pData0[i] & ~pData1[i]); + break; + case 3: + for ( i = 0; i < p->nSimWords; i++ ) + pData[i] = (~pData0[i] | pData1[i]); + break; + case 4: + for ( i = 0; i < p->nSimWords; i++ ) + pData[i] = (~pData0[i] & pData1[i]); + break; + case 5: + for ( i = 0; i < p->nSimWords; i++ ) + pData[i] = (pData0[i] | ~pData1[i]); + break; + case 6: + for ( i = 0; i < p->nSimWords; i++ ) + pData[i] = ~(pData0[i] | pData1[i]); + break; + case 7: + for ( i = 0; i < p->nSimWords; i++ ) + pData[i] = (pData0[i] | pData1[i]); + break; + } +} + +/**Function************************************************************* + + Synopsis [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeSimulate( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_FraigSim_t * pSims, * pSims0, * pSims1; + int fCompl, fCompl0, fCompl1, i; + assert( !Ivy_IsComplement(pObj) ); + // get hold of the simulation information + pSims = Ivy_ObjSim(pObj); + pSims0 = Ivy_ObjSim(Ivy_ObjFanin0(pObj)); + pSims1 = Ivy_ObjSim(Ivy_ObjFanin1(pObj)); + // get complemented attributes of the children using their random info + fCompl = pObj->fPhase; + fCompl0 = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)); + fCompl1 = Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj)); + // simulate + if ( fCompl0 && fCompl1 ) + { + if ( fCompl ) + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = (pSims0->pData[i] | pSims1->pData[i]); + else + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = ~(pSims0->pData[i] | pSims1->pData[i]); + } + else if ( fCompl0 && !fCompl1 ) + { + if ( fCompl ) + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = (pSims0->pData[i] | ~pSims1->pData[i]); + else + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = (~pSims0->pData[i] & pSims1->pData[i]); + } + else if ( !fCompl0 && fCompl1 ) + { + if ( fCompl ) + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = (~pSims0->pData[i] | pSims1->pData[i]); + else + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = (pSims0->pData[i] & ~pSims1->pData[i]); + } + else // if ( !fCompl0 && !fCompl1 ) + { + if ( fCompl ) + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = ~(pSims0->pData[i] & pSims1->pData[i]); + else + for ( i = 0; i < p->nSimWords; i++ ) + pSims->pData[i] = (pSims0->pData[i] & pSims1->pData[i]); + } +} + +/**Function************************************************************* + + Synopsis [Computes hash value using simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Ivy_NodeHash( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) +{ + static int s_FPrimes[128] = { + 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, + 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, + 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, + 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, + 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, + 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, + 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, + 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, + 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, + 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, + 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, + 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, + 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 + }; + Ivy_FraigSim_t * pSims; + unsigned uHash; + int i; + assert( p->nSimWords <= 128 ); + uHash = 0; + pSims = Ivy_ObjSim(pObj); + for ( i = 0; i < p->nSimWords; i++ ) + uHash ^= pSims->pData[i] * s_FPrimes[i]; + return uHash; +} + +/**Function************************************************************* + + Synopsis [Simulates AIG manager.] + + Description [Assumes that the PI simulation info is attached.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSimulateOne( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + abctime clk; +clk = Abc_Clock(); + Ivy_ManForEachNode( p->pManAig, pObj, i ) + { + Ivy_NodeSimulate( p, pObj ); +/* + if ( Ivy_ObjFraig(pObj) == NULL ) + printf( "%3d --- -- %d : ", pObj->Id, pObj->fPhase ); + else + printf( "%3d %3d %2d %d : ", pObj->Id, Ivy_Regular(Ivy_ObjFraig(pObj))->Id, Ivy_ObjSatNum(Ivy_Regular(Ivy_ObjFraig(pObj))), pObj->fPhase ); + Extra_PrintBinary( stdout, Ivy_ObjSim(pObj), 30 ); + printf( "\n" ); +*/ + } +p->timeSim += Abc_Clock() - clk; +p->nSimRounds++; +} + +/**Function************************************************************* + + Synopsis [Simulates AIG manager.] + + Description [Assumes that the PI simulation info is attached.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSimulateOneSim( Ivy_FraigMan_t * p ) +{ + Ivy_FraigSim_t * pSims; + abctime clk; +clk = Abc_Clock(); + for ( pSims = p->pSimStart; pSims; pSims = pSims->pNext ) + Ivy_NodeSimulateSim( p, pSims ); +p->timeSim += Abc_Clock() - clk; +p->nSimRounds++; +} + +/**Function************************************************************* + + Synopsis [Adds one node to the equivalence class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeAddToClass( Ivy_Obj_t * pClass, Ivy_Obj_t * pObj ) +{ + if ( Ivy_ObjClassNodeNext(pClass) == NULL ) + Ivy_ObjSetClassNodeNext( pClass, pObj ); + else + Ivy_ObjSetClassNodeNext( Ivy_ObjClassNodeLast(pClass), pObj ); + Ivy_ObjSetClassNodeLast( pClass, pObj ); + Ivy_ObjSetClassNodeRepr( pObj, pClass ); + Ivy_ObjSetClassNodeNext( pObj, NULL ); +} + +/**Function************************************************************* + + Synopsis [Adds equivalence class to the list of classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigAddClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pClass ) +{ + if ( pList->pHead == NULL ) + { + pList->pHead = pClass; + pList->pTail = pClass; + Ivy_ObjSetEquivListPrev( pClass, NULL ); + Ivy_ObjSetEquivListNext( pClass, NULL ); + } + else + { + Ivy_ObjSetEquivListNext( pList->pTail, pClass ); + Ivy_ObjSetEquivListPrev( pClass, pList->pTail ); + Ivy_ObjSetEquivListNext( pClass, NULL ); + pList->pTail = pClass; + } + pList->nItems++; +} + +/**Function************************************************************* + + Synopsis [Updates the list of classes after base class has split.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigInsertClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pBase, Ivy_Obj_t * pClass ) +{ + Ivy_ObjSetEquivListPrev( pClass, pBase ); + Ivy_ObjSetEquivListNext( pClass, Ivy_ObjEquivListNext(pBase) ); + if ( Ivy_ObjEquivListNext(pBase) ) + Ivy_ObjSetEquivListPrev( Ivy_ObjEquivListNext(pBase), pClass ); + Ivy_ObjSetEquivListNext( pBase, pClass ); + if ( pList->pTail == pBase ) + pList->pTail = pClass; + pList->nItems++; +} + +/**Function************************************************************* + + Synopsis [Removes equivalence class from the list of classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigRemoveClass( Ivy_FraigList_t * pList, Ivy_Obj_t * pClass ) +{ + if ( pList->pHead == pClass ) + pList->pHead = Ivy_ObjEquivListNext(pClass); + if ( pList->pTail == pClass ) + pList->pTail = Ivy_ObjEquivListPrev(pClass); + if ( Ivy_ObjEquivListPrev(pClass) ) + Ivy_ObjSetEquivListNext( Ivy_ObjEquivListPrev(pClass), Ivy_ObjEquivListNext(pClass) ); + if ( Ivy_ObjEquivListNext(pClass) ) + Ivy_ObjSetEquivListPrev( Ivy_ObjEquivListNext(pClass), Ivy_ObjEquivListPrev(pClass) ); + Ivy_ObjSetEquivListNext( pClass, NULL ); + Ivy_ObjSetEquivListPrev( pClass, NULL ); + pClass->fMarkA = 0; + pList->nItems--; +} + +/**Function************************************************************* + + Synopsis [Count the number of pairs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigCountPairsClasses( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pClass, * pNode; + int nPairs = 0, nNodes; + return nPairs; + + Ivy_FraigForEachEquivClass( p->lClasses.pHead, pClass ) + { + nNodes = 0; + Ivy_FraigForEachClassNode( pClass, pNode ) + nNodes++; + nPairs += nNodes * (nNodes - 1) / 2; + } + return nPairs; +} + +/**Function************************************************************* + + Synopsis [Creates initial simulation classes.] + + Description [Assumes that simulation info is assigned.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigCreateClasses( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t ** pTable; + Ivy_Obj_t * pObj, * pConst1, * pBin, * pEntry; + int i, nTableSize; + unsigned Hash; + pConst1 = Ivy_ManConst1(p->pManAig); + // allocate the table + nTableSize = Ivy_ManObjNum(p->pManAig) / 2 + 13; + pTable = ABC_ALLOC( Ivy_Obj_t *, nTableSize ); + memset( pTable, 0, sizeof(Ivy_Obj_t *) * nTableSize ); + // collect nodes into the table + Ivy_ManForEachObj( p->pManAig, pObj, i ) + { + if ( !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsNode(pObj) ) + continue; + Hash = Ivy_NodeHash( p, pObj ); + if ( Hash == 0 && Ivy_NodeHasZeroSim( p, pObj ) ) + { + Ivy_NodeAddToClass( pConst1, pObj ); + continue; + } + // add the node to the table + pBin = pTable[Hash % nTableSize]; + Ivy_FraigForEachBinNode( pBin, pEntry ) + if ( Ivy_NodeCompareSims( p, pEntry, pObj ) ) + { + Ivy_NodeAddToClass( pEntry, pObj ); + break; + } + // check if the entry was added + if ( pEntry ) + continue; + Ivy_ObjSetNodeHashNext( pObj, pBin ); + pTable[Hash % nTableSize] = pObj; + } + // collect non-trivial classes + assert( p->lClasses.pHead == NULL ); + Ivy_ManForEachObj( p->pManAig, pObj, i ) + { + if ( !Ivy_ObjIsConst1(pObj) && !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsNode(pObj) ) + continue; + Ivy_ObjSetNodeHashNext( pObj, NULL ); + if ( Ivy_ObjClassNodeRepr(pObj) == NULL ) + { + assert( Ivy_ObjClassNodeNext(pObj) == NULL ); + continue; + } + // recognize the head of the class + if ( Ivy_ObjClassNodeNext( Ivy_ObjClassNodeRepr(pObj) ) != NULL ) + continue; + // clean the class representative and add it to the list + Ivy_ObjSetClassNodeRepr( pObj, NULL ); + Ivy_FraigAddClass( &p->lClasses, pObj ); + } + // free the table + ABC_FREE( pTable ); +} + +/**Function************************************************************* + + Synopsis [Recursively refines the class after simulation.] + + Description [Returns 1 if the class has changed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigRefineClass_rec( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass ) +{ + Ivy_Obj_t * pClassNew, * pListOld, * pListNew, * pNode; + int RetValue = 0; + // check if there is refinement + pListOld = pClass; + Ivy_FraigForEachClassNode( Ivy_ObjClassNodeNext(pClass), pClassNew ) + { + if ( !Ivy_NodeCompareSims(p, pClass, pClassNew) ) + { + if ( p->pParams->fPatScores ) + Ivy_FraigAddToPatScores( p, pClass, pClassNew ); + break; + } + pListOld = pClassNew; + } + if ( pClassNew == NULL ) + return 0; + // set representative of the new class + Ivy_ObjSetClassNodeRepr( pClassNew, NULL ); + // start the new list + pListNew = pClassNew; + // go through the remaining nodes and sort them into two groups: + // (1) matches of the old node; (2) non-matches of the old node + Ivy_FraigForEachClassNode( Ivy_ObjClassNodeNext(pClassNew), pNode ) + if ( Ivy_NodeCompareSims( p, pClass, pNode ) ) + { + Ivy_ObjSetClassNodeNext( pListOld, pNode ); + pListOld = pNode; + } + else + { + Ivy_ObjSetClassNodeNext( pListNew, pNode ); + Ivy_ObjSetClassNodeRepr( pNode, pClassNew ); + pListNew = pNode; + } + // finish both lists + Ivy_ObjSetClassNodeNext( pListNew, NULL ); + Ivy_ObjSetClassNodeNext( pListOld, NULL ); + // update the list of classes + Ivy_FraigInsertClass( &p->lClasses, pClass, pClassNew ); + // if the old class is trivial, remove it + if ( Ivy_ObjClassNodeNext(pClass) == NULL ) + Ivy_FraigRemoveClass( &p->lClasses, pClass ); + // if the new class is trivial, remove it; otherwise, try to refine it + if ( Ivy_ObjClassNodeNext(pClassNew) == NULL ) + Ivy_FraigRemoveClass( &p->lClasses, pClassNew ); + else + RetValue = Ivy_FraigRefineClass_rec( p, pClassNew ); + return RetValue + 1; +} + +/**Function************************************************************* + + Synopsis [Creates the counter-example from the successful pattern.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigCheckOutputSimsSavePattern( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_FraigSim_t * pSims; + int i, k, BestPat, * pModel; + // find the word of the pattern + pSims = Ivy_ObjSim(pObj); + for ( i = 0; i < p->nSimWords; i++ ) + if ( pSims->pData[i] ) + break; + assert( i < p->nSimWords ); + // find the bit of the pattern + for ( k = 0; k < 32; k++ ) + if ( pSims->pData[i] & (1 << k) ) + break; + assert( k < 32 ); + // determine the best pattern + BestPat = i * 32 + k; + // fill in the counter-example data + pModel = ABC_ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); + Ivy_ManForEachPi( p->pManAig, pObj, i ) + { + pModel[i] = Ivy_InfoHasBit(Ivy_ObjSim(pObj)->pData, BestPat); +// printf( "%d", pModel[i] ); + } +// printf( "\n" ); + // set the model + assert( p->pManFraig->pData == NULL ); + p->pManFraig->pData = pModel; + return; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the one of the output is already non-constant 0.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigCheckOutputSims( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + // make sure the reference simulation pattern does not detect the bug +// pObj = Ivy_ManPo( p->pManAig, 0 ); + Ivy_ManForEachPo( p->pManAig, pObj, i ) + { + //assert( Ivy_ObjFanin0(pObj)->fPhase == (unsigned)Ivy_ObjFaninC0(pObj) ); // Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) == 0 + // complement simulation info +// if ( Ivy_ObjFanin0(pObj)->fPhase ^ Ivy_ObjFaninC0(pObj) ) // Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) +// Ivy_NodeComplementSim( p, Ivy_ObjFanin0(pObj) ); + // check + if ( !Ivy_NodeHasZeroSim( p, Ivy_ObjFanin0(pObj) ) ) + { + // create the counter-example from this pattern + Ivy_FraigCheckOutputSimsSavePattern( p, Ivy_ObjFanin0(pObj) ); + return 1; + } + // complement simulation info +// if ( Ivy_ObjFanin0(pObj)->fPhase ^ Ivy_ObjFaninC0(pObj) ) +// Ivy_NodeComplementSim( p, Ivy_ObjFanin0(pObj) ); + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Refines the classes after simulation.] + + Description [Assumes that simulation info is assigned. Returns the + number of classes refined.] + + SideEffects [Large equivalence class of constant 0 may cause problems.] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigRefineClasses( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pClass, * pClass2; + int RetValue, Counter = 0; + abctime clk; + // check if some outputs already became non-constant + // this is a special case when computation can be stopped!!! + if ( p->pParams->fProve ) + Ivy_FraigCheckOutputSims( p ); + if ( p->pManFraig->pData ) + return 0; + // refine the classed +clk = Abc_Clock(); + Ivy_FraigForEachEquivClassSafe( p->lClasses.pHead, pClass, pClass2 ) + { + if ( pClass->fMarkA ) + continue; + RetValue = Ivy_FraigRefineClass_rec( p, pClass ); + Counter += ( RetValue > 0 ); +//if ( Ivy_ObjIsConst1(pClass) ) +//printf( "%d ", RetValue ); +//if ( Ivy_ObjIsConst1(pClass) ) +// p->time1 += Abc_Clock() - clk; + } +p->timeRef += Abc_Clock() - clk; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Print the class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigPrintClass( Ivy_Obj_t * pClass ) +{ + Ivy_Obj_t * pObj; + printf( "Class {" ); + Ivy_FraigForEachClassNode( pClass, pObj ) + printf( " %d(%d)%c", pObj->Id, pObj->Level, pObj->fPhase? '+' : '-' ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [Count the number of elements in the class.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigCountClassNodes( Ivy_Obj_t * pClass ) +{ + Ivy_Obj_t * pObj; + int Counter = 0; + Ivy_FraigForEachClassNode( pClass, pObj ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Prints simulation classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigPrintSimClasses( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pClass; + Ivy_FraigForEachEquivClass( p->lClasses.pHead, pClass ) + { +// Ivy_FraigPrintClass( pClass ); + printf( "%d ", Ivy_FraigCountClassNodes( pClass ) ); + } +// printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Generated const 0 pattern.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSavePattern0( Ivy_FraigMan_t * p ) +{ + memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); +} + +/**Function************************************************************* + + Synopsis [[Generated const 1 pattern.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSavePattern1( Ivy_FraigMan_t * p ) +{ + memset( p->pPatWords, 0xff, sizeof(unsigned) * p->nPatWords ); +} + +/**Function************************************************************* + + Synopsis [Generates the counter-example satisfying the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Ivy_FraigCreateModel( Ivy_FraigMan_t * p ) +{ + int * pModel; + Ivy_Obj_t * pObj; + int i; + pModel = ABC_ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); + Ivy_ManForEachPi( p->pManFraig, pObj, i ) +// pModel[i] = ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True ); + pModel[i] = ( p->pSat->model[Ivy_ObjSatNum(pObj)] == l_True ); + return pModel; +} + +/**Function************************************************************* + + Synopsis [Copy pattern from the solver into the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSavePattern( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); + Ivy_ManForEachPi( p->pManFraig, pObj, i ) +// Vec_PtrForEachEntry( Ivy_Obj_t *, p->vPiVars, pObj, i ) +// if ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True ) + if ( p->pSat->model[Ivy_ObjSatNum(pObj)] == l_True ) + Ivy_InfoSetBit( p->pPatWords, i ); +// Ivy_InfoSetBit( p->pPatWords, pObj->Id - 1 ); +} + +/**Function************************************************************* + + Synopsis [Copy pattern from the solver into the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSavePattern2( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); +// Ivy_ManForEachPi( p->pManFraig, pObj, i ) + Vec_PtrForEachEntry( Ivy_Obj_t *, p->vPiVars, pObj, i ) +// if ( p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True ) + if ( p->pSat->model[Ivy_ObjSatNum(pObj)] == l_True ) +// Ivy_InfoSetBit( p->pPatWords, i ); + Ivy_InfoSetBit( p->pPatWords, pObj->Id - 1 ); +} + +/**Function************************************************************* + + Synopsis [Copy pattern from the solver into the internal storage.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSavePattern3( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + for ( i = 0; i < p->nPatWords; i++ ) + p->pPatWords[i] = Ivy_ObjRandomSim(); + Vec_PtrForEachEntry( Ivy_Obj_t *, p->vPiVars, pObj, i ) +// if ( Ivy_InfoHasBit( p->pPatWords, pObj->Id - 1 ) ^ (p->pSat->model.ptr[Ivy_ObjSatNum(pObj)] == l_True) ) + if ( Ivy_InfoHasBit( p->pPatWords, pObj->Id - 1 ) ^ sat_solver_var_value(p->pSat, Ivy_ObjSatNum(pObj)) ) + Ivy_InfoXorBit( p->pPatWords, pObj->Id - 1 ); +} + + +/**Function************************************************************* + + Synopsis [Performs simulation of the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSimulate( Ivy_FraigMan_t * p ) +{ + int nChanges, nClasses; + // start the classes + Ivy_FraigAssignRandom( p ); + Ivy_FraigSimulateOne( p ); + Ivy_FraigCreateClasses( p ); +//printf( "Starting classes = %5d. Pairs = %6d.\n", p->lClasses.nItems, Ivy_FraigCountPairsClasses(p) ); + // refine classes by walking 0/1 patterns + Ivy_FraigSavePattern0( p ); + Ivy_FraigAssignDist1( p, p->pPatWords ); + Ivy_FraigSimulateOne( p ); + nChanges = Ivy_FraigRefineClasses( p ); + if ( p->pManFraig->pData ) + return; +//printf( "Refined classes = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); + Ivy_FraigSavePattern1( p ); + Ivy_FraigAssignDist1( p, p->pPatWords ); + Ivy_FraigSimulateOne( p ); + nChanges = Ivy_FraigRefineClasses( p ); + if ( p->pManFraig->pData ) + return; +//printf( "Refined classes = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); + // refine classes by random simulation + do { + Ivy_FraigAssignRandom( p ); + Ivy_FraigSimulateOne( p ); + nClasses = p->lClasses.nItems; + nChanges = Ivy_FraigRefineClasses( p ); + if ( p->pManFraig->pData ) + return; +//printf( "Refined classes = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); + } while ( (double)nChanges / nClasses > p->pParams->dSimSatur ); +// Ivy_FraigPrintSimClasses( p ); +} + + + +/**Function************************************************************* + + Synopsis [Cleans pattern scores.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigCleanPatScores( Ivy_FraigMan_t * p ) +{ + int i, nLimit = p->nSimWords * 32; + for ( i = 0; i < nLimit; i++ ) + p->pPatScores[i] = 0; +} + +/**Function************************************************************* + + Synopsis [Adds to pattern scores.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigAddToPatScores( Ivy_FraigMan_t * p, Ivy_Obj_t * pClass, Ivy_Obj_t * pClassNew ) +{ + Ivy_FraigSim_t * pSims0, * pSims1; + unsigned uDiff; + int i, w; + // get hold of the simulation information + pSims0 = Ivy_ObjSim(pClass); + pSims1 = Ivy_ObjSim(pClassNew); + // iterate through the differences and record the score + for ( w = 0; w < p->nSimWords; w++ ) + { + uDiff = pSims0->pData[w] ^ pSims1->pData[w]; + if ( uDiff == 0 ) + continue; + for ( i = 0; i < 32; i++ ) + if ( uDiff & ( 1 << i ) ) + p->pPatScores[w*32+i]++; + } +} + +/**Function************************************************************* + + Synopsis [Selects the best pattern.] + + Description [Returns 1 if such pattern is found.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigSelectBestPat( Ivy_FraigMan_t * p ) +{ + Ivy_FraigSim_t * pSims; + Ivy_Obj_t * pObj; + int i, nLimit = p->nSimWords * 32, MaxScore = 0, BestPat = -1; + for ( i = 1; i < nLimit; i++ ) + { + if ( MaxScore < p->pPatScores[i] ) + { + MaxScore = p->pPatScores[i]; + BestPat = i; + } + } + if ( MaxScore == 0 ) + return 0; +// if ( MaxScore > p->pParams->MaxScore ) +// printf( "Max score is %3d. ", MaxScore ); + // copy the best pattern into the selected pattern + memset( p->pPatWords, 0, sizeof(unsigned) * p->nPatWords ); + Ivy_ManForEachPi( p->pManAig, pObj, i ) + { + pSims = Ivy_ObjSim(pObj); + if ( Ivy_InfoHasBit(pSims->pData, BestPat) ) + Ivy_InfoSetBit(p->pPatWords, i); + } + return MaxScore; +} + +/**Function************************************************************* + + Synopsis [Resimulates fraiging manager after finding a counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigResimulate( Ivy_FraigMan_t * p ) +{ + int nChanges; + Ivy_FraigAssignDist1( p, p->pPatWords ); + Ivy_FraigSimulateOne( p ); + if ( p->pParams->fPatScores ) + Ivy_FraigCleanPatScores( p ); + nChanges = Ivy_FraigRefineClasses( p ); + if ( p->pManFraig->pData ) + return; + if ( nChanges < 1 ) + printf( "Error: A counter-example did not refine classes!\n" ); + assert( nChanges >= 1 ); +//printf( "Refined classes! = %5d. Changes = %4d.\n", p->lClasses.nItems, nChanges ); + if ( !p->pParams->fPatScores ) + return; + + // perform additional simulation using dist1 patterns derived from successful patterns + while ( Ivy_FraigSelectBestPat(p) > p->pParams->MaxScore ) + { + Ivy_FraigAssignDist1( p, p->pPatWords ); + Ivy_FraigSimulateOne( p ); + Ivy_FraigCleanPatScores( p ); + nChanges = Ivy_FraigRefineClasses( p ); + if ( p->pManFraig->pData ) + return; +//printf( "Refined class!!! = %5d. Changes = %4d. Pairs = %6d.\n", p->lClasses.nItems, nChanges, Ivy_FraigCountPairsClasses(p) ); + if ( nChanges == 0 ) + break; + } +} + + +/**Function************************************************************* + + Synopsis [Prints the status of the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigMiterPrint( Ivy_Man_t * pNtk, char * pString, abctime clk, int fVerbose ) +{ + if ( !fVerbose ) + return; + printf( "Nodes = %7d. Levels = %4d. ", Ivy_ManNodeNum(pNtk), Ivy_ManLevels(pNtk) ); + ABC_PRT( pString, Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [Reports the status of the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigMiterStatus( Ivy_Man_t * pMan ) +{ + Ivy_Obj_t * pObj, * pObjNew; + int i, CountConst0 = 0, CountNonConst0 = 0, CountUndecided = 0; + if ( pMan->pData ) + return 0; + Ivy_ManForEachPo( pMan, pObj, i ) + { + pObjNew = Ivy_ObjChild0(pObj); + // check if the output is constant 1 + if ( pObjNew == pMan->pConst1 ) + { + CountNonConst0++; + continue; + } + // check if the output is constant 0 + if ( pObjNew == Ivy_Not(pMan->pConst1) ) + { + CountConst0++; + continue; + } +/* + // check if the output is a primary input + if ( Ivy_ObjIsPi(Ivy_Regular(pObjNew)) ) + { + CountNonConst0++; + continue; + } +*/ + // check if the output can be constant 0 + if ( Ivy_Regular(pObjNew)->fPhase != (unsigned)Ivy_IsComplement(pObjNew) ) + { + CountNonConst0++; + continue; + } + CountUndecided++; + } +/* + if ( p->pParams->fVerbose ) + { + printf( "Miter has %d outputs. ", Ivy_ManPoNum(p->pManAig) ); + printf( "Const0 = %d. ", CountConst0 ); + printf( "NonConst0 = %d. ", CountNonConst0 ); + printf( "Undecided = %d. ", CountUndecided ); + printf( "\n" ); + } +*/ + if ( CountNonConst0 ) + return 0; + if ( CountUndecided ) + return -1; + return 1; +} + +/**Function************************************************************* + + Synopsis [Tries to prove each output of the miter until encountering a sat output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigMiterProve( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pObj, * pObjNew; + int i, RetValue; + abctime clk = Abc_Clock(); + int fVerbose = 0; + Ivy_ManForEachPo( p->pManAig, pObj, i ) + { + if ( i && fVerbose ) + { + ABC_PRT( "Time", Abc_Clock() -clk ); + } + pObjNew = Ivy_ObjChild0Equiv(pObj); + // check if the output is constant 1 + if ( pObjNew == p->pManFraig->pConst1 ) + { + if ( fVerbose ) + printf( "Output %2d (out of %2d) is constant 1. ", i, Ivy_ManPoNum(p->pManAig) ); + // assing constant 0 model + p->pManFraig->pData = ABC_ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); + memset( p->pManFraig->pData, 0, sizeof(int) * Ivy_ManPiNum(p->pManFraig) ); + break; + } + // check if the output is constant 0 + if ( pObjNew == Ivy_Not(p->pManFraig->pConst1) ) + { + if ( fVerbose ) + printf( "Output %2d (out of %2d) is already constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); + continue; + } + // check if the output can be constant 0 + if ( Ivy_Regular(pObjNew)->fPhase != (unsigned)Ivy_IsComplement(pObjNew) ) + { + if ( fVerbose ) + printf( "Output %2d (out of %2d) cannot be constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); + // assing constant 0 model + p->pManFraig->pData = ABC_ALLOC( int, Ivy_ManPiNum(p->pManFraig) ); + memset( p->pManFraig->pData, 0, sizeof(int) * Ivy_ManPiNum(p->pManFraig) ); + break; + } +/* + // check the representative of this node + pRepr = Ivy_ObjClassNodeRepr(Ivy_ObjFanin0(pObj)); + if ( Ivy_Regular(pRepr) != p->pManAig->pConst1 ) + printf( "Representative is not constant 1.\n" ); + else + printf( "Representative is constant 1.\n" ); +*/ + // try to prove the output constant 0 + RetValue = Ivy_FraigNodeIsConst( p, Ivy_Regular(pObjNew) ); + if ( RetValue == 1 ) // proved equivalent + { + if ( fVerbose ) + printf( "Output %2d (out of %2d) was proved constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); + // set the constant miter + Ivy_ObjFanin0(pObj)->pEquiv = Ivy_NotCond( p->pManFraig->pConst1, !Ivy_ObjFaninC0(pObj) ); + continue; + } + if ( RetValue == -1 ) // failed + { + if ( fVerbose ) + printf( "Output %2d (out of %2d) has timed out at %d backtracks. ", i, Ivy_ManPoNum(p->pManAig), p->pParams->nBTLimitMiter ); + continue; + } + // proved satisfiable + if ( fVerbose ) + printf( "Output %2d (out of %2d) was proved NOT a constant 0. ", i, Ivy_ManPoNum(p->pManAig) ); + // create the model + p->pManFraig->pData = Ivy_FraigCreateModel(p); + break; + } + if ( fVerbose ) + { + ABC_PRT( "Time", Abc_Clock() -clk ); + } +} + +/**Function************************************************************* + + Synopsis [Performs fraiging for the internal nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigSweep( Ivy_FraigMan_t * p ) +{ + Ivy_Obj_t * pObj;//, * pTemp; + int i, k = 0; +p->nClassesZero = p->lClasses.pHead? (Ivy_ObjIsConst1(p->lClasses.pHead) ? Ivy_FraigCountClassNodes(p->lClasses.pHead) : 0) : 0; +p->nClassesBeg = p->lClasses.nItems; + // duplicate internal nodes + p->pProgress = Extra_ProgressBarStart( stdout, Ivy_ManNodeNum(p->pManAig) ); + Ivy_ManForEachNode( p->pManAig, pObj, i ) + { + Extra_ProgressBarUpdate( p->pProgress, k++, NULL ); + // default to simple strashing if simulation detected a counter-example for a PO + if ( p->pManFraig->pData ) + pObj->pEquiv = Ivy_And( p->pManFraig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); + else + pObj->pEquiv = Ivy_FraigAnd( p, pObj ); + assert( pObj->pEquiv != NULL ); +// pTemp = Ivy_Regular(pObj->pEquiv); +// assert( Ivy_Regular(pObj->pEquiv)->Type ); + } + Extra_ProgressBarStop( p->pProgress ); +p->nClassesEnd = p->lClasses.nItems; + // try to prove the outputs of the miter + p->nNodesMiter = Ivy_ManNodeNum(p->pManFraig); +// Ivy_FraigMiterStatus( p->pManFraig ); + if ( p->pParams->fProve && p->pManFraig->pData == NULL ) + Ivy_FraigMiterProve( p ); + // add the POs + Ivy_ManForEachPo( p->pManAig, pObj, i ) + Ivy_ObjCreatePo( p->pManFraig, Ivy_ObjChild0Equiv(pObj) ); + // clean the old manager + Ivy_ManForEachObj( p->pManAig, pObj, i ) + pObj->pFanout = pObj->pNextFan0 = pObj->pNextFan1 = pObj->pPrevFan0 = pObj->pPrevFan1 = NULL; + // clean the new manager + Ivy_ManForEachObj( p->pManFraig, pObj, i ) + { + if ( Ivy_ObjFaninVec(pObj) ) + Vec_PtrFree( Ivy_ObjFaninVec(pObj) ); + pObj->pNextFan0 = pObj->pNextFan1 = NULL; + pObj->pEquiv = NULL; + } + // remove dangling nodes + Ivy_ManCleanup( p->pManFraig ); + // clean up the class marks + Ivy_FraigForEachEquivClass( p->lClasses.pHead, pObj ) + pObj->fMarkA = 0; +} + +/**Function************************************************************* + + Synopsis [Performs fraiging for one node.] + + Description [Returns the fraiged node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_FraigAnd( Ivy_FraigMan_t * p, Ivy_Obj_t * pObjOld ) +{ + Ivy_Obj_t * pObjNew, * pFanin0New, * pFanin1New, * pObjReprNew; + int RetValue; + // get the fraiged fanins + pFanin0New = Ivy_ObjChild0Equiv(pObjOld); + pFanin1New = Ivy_ObjChild1Equiv(pObjOld); + // get the candidate fraig node + pObjNew = Ivy_And( p->pManFraig, pFanin0New, pFanin1New ); + // get representative of this class + if ( Ivy_ObjClassNodeRepr(pObjOld) == NULL || // this is a unique node + (!p->pParams->fDoSparse && Ivy_ObjClassNodeRepr(pObjOld) == p->pManAig->pConst1) ) // this is a sparse node + { +// assert( Ivy_Regular(pFanin0New) != Ivy_Regular(pFanin1New) ); +// assert( pObjNew != Ivy_Regular(pFanin0New) ); +// assert( pObjNew != Ivy_Regular(pFanin1New) ); + return pObjNew; + } + // get the fraiged representative + pObjReprNew = Ivy_ObjFraig(Ivy_ObjClassNodeRepr(pObjOld)); + // if the fraiged nodes are the same return + if ( Ivy_Regular(pObjNew) == Ivy_Regular(pObjReprNew) ) + return pObjNew; + assert( Ivy_Regular(pObjNew) != Ivy_ManConst1(p->pManFraig) ); +// printf( "Node = %d. Repr = %d.\n", pObjOld->Id, Ivy_ObjClassNodeRepr(pObjOld)->Id ); + + // they are different (the counter-example is in p->pPatWords) + RetValue = Ivy_FraigNodesAreEquiv( p, Ivy_Regular(pObjReprNew), Ivy_Regular(pObjNew) ); + if ( RetValue == 1 ) // proved equivalent + { + // mark the class as proved + if ( Ivy_ObjClassNodeNext(pObjOld) == NULL ) + Ivy_ObjClassNodeRepr(pObjOld)->fMarkA = 1; + return Ivy_NotCond( pObjReprNew, pObjOld->fPhase ^ Ivy_ObjClassNodeRepr(pObjOld)->fPhase ); + } + if ( RetValue == -1 ) // failed + return pObjNew; + // simulate the counter-example and return the new node + Ivy_FraigResimulate( p ); + return pObjNew; +} + +/**Function************************************************************* + + Synopsis [Prints variable activity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigPrintActivity( Ivy_FraigMan_t * p ) +{ + int i; + for ( i = 0; i < p->nSatVars; i++ ) + printf( "%d %d ", i, (int)p->pSat->activity[i] ); + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Runs equivalence test for the two nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigNodesAreEquiv( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ) +{ + int pLits[4], RetValue, RetValue1, nBTLimit; + abctime clk; //, clk2 = Abc_Clock(); + + // make sure the nodes are not complemented + assert( !Ivy_IsComplement(pNew) ); + assert( !Ivy_IsComplement(pOld) ); + assert( pNew != pOld ); + + // if at least one of the nodes is a failed node, perform adjustments: + // if the backtrack limit is small, simply skip this node + // if the backtrack limit is > 10, take the quare root of the limit + nBTLimit = p->pParams->nBTLimitNode; + if ( nBTLimit > 0 && (pOld->fFailTfo || pNew->fFailTfo) ) + { + p->nSatFails++; + // fail immediately +// return -1; + if ( nBTLimit <= 10 ) + return -1; + nBTLimit = (int)pow(nBTLimit, 0.7); + } + p->nSatCalls++; + + // make sure the solver is allocated and has enough variables + if ( p->pSat == NULL ) + { + p->pSat = sat_solver_new(); + sat_solver_setnvars( p->pSat, 1000 ); + p->pSat->factors = ABC_CALLOC( double, p->pSat->cap ); + p->nSatVars = 1; + // var 0 is reserved for const1 node - add the clause +// pLits[0] = toLit( 0 ); +// sat_solver_addclause( p->pSat, pLits, pLits + 1 ); + } + + // if the nodes do not have SAT variables, allocate them + Ivy_FraigNodeAddToSolver( p, pOld, pNew ); + + // prepare variable activity + Ivy_FraigSetActivityFactors( p, pOld, pNew ); + + // solve under assumptions + // A = 1; B = 0 OR A = 1; B = 1 +clk = Abc_Clock(); + pLits[0] = toLitCond( Ivy_ObjSatNum(pOld), 0 ); + pLits[1] = toLitCond( Ivy_ObjSatNum(pNew), pOld->fPhase == pNew->fPhase ); +//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 ); + RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, + (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, + p->nBTLimitGlobal, p->nInsLimitGlobal ); +p->timeSat += Abc_Clock() - clk; + if ( RetValue1 == l_False ) + { +p->timeSatUnsat += Abc_Clock() - clk; + pLits[0] = lit_neg( pLits[0] ); + pLits[1] = lit_neg( pLits[1] ); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( RetValue ); + // continue solving the other implication + p->nSatCallsUnsat++; + } + else if ( RetValue1 == l_True ) + { +p->timeSatSat += Abc_Clock() - clk; + Ivy_FraigSavePattern( p ); + p->nSatCallsSat++; + return 0; + } + else // if ( RetValue1 == l_Undef ) + { +p->timeSatFail += Abc_Clock() - clk; +/* + if ( nBTLimit > 1000 ) + { + RetValue = Ivy_FraigCheckCone( p, p->pManFraig, pOld, pNew, nBTLimit ); + if ( RetValue != -1 ) + return RetValue; + } +*/ + // mark the node as the failed node + if ( pOld != p->pManFraig->pConst1 ) + pOld->fFailTfo = 1; + pNew->fFailTfo = 1; + p->nSatFailsReal++; + return -1; + } + + // if the old node was constant 0, we already know the answer + if ( pOld == p->pManFraig->pConst1 ) + { + p->nSatProof++; + return 1; + } + + // solve under assumptions + // A = 0; B = 1 OR A = 0; B = 0 +clk = Abc_Clock(); + pLits[0] = toLitCond( Ivy_ObjSatNum(pOld), 1 ); + pLits[1] = toLitCond( Ivy_ObjSatNum(pNew), pOld->fPhase ^ pNew->fPhase ); + RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, + (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, + p->nBTLimitGlobal, p->nInsLimitGlobal ); +p->timeSat += Abc_Clock() - clk; + if ( RetValue1 == l_False ) + { +p->timeSatUnsat += Abc_Clock() - clk; + pLits[0] = lit_neg( pLits[0] ); + pLits[1] = lit_neg( pLits[1] ); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( RetValue ); + p->nSatCallsUnsat++; + } + else if ( RetValue1 == l_True ) + { +p->timeSatSat += Abc_Clock() - clk; + Ivy_FraigSavePattern( p ); + p->nSatCallsSat++; + return 0; + } + else // if ( RetValue1 == l_Undef ) + { +p->timeSatFail += Abc_Clock() - clk; +/* + if ( nBTLimit > 1000 ) + { + RetValue = Ivy_FraigCheckCone( p, p->pManFraig, pOld, pNew, nBTLimit ); + if ( RetValue != -1 ) + return RetValue; + } +*/ + // mark the node as the failed node + pOld->fFailTfo = 1; + pNew->fFailTfo = 1; + p->nSatFailsReal++; + return -1; + } +/* + // check BDD proof + { + int RetVal; + ABC_PRT( "Sat", Abc_Clock() - clk2 ); + clk2 = Abc_Clock(); + RetVal = Ivy_FraigNodesAreEquivBdd( pOld, pNew ); +// printf( "%d ", RetVal ); + assert( RetVal ); + ABC_PRT( "Bdd", Abc_Clock() - clk2 ); + printf( "\n" ); + } +*/ + // return SAT proof + p->nSatProof++; + return 1; +} + +/**Function************************************************************* + + Synopsis [Runs equivalence test for one node.] + + Description [Returns the fraiged node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigNodeIsConst( Ivy_FraigMan_t * p, Ivy_Obj_t * pNew ) +{ + int pLits[2], RetValue1; + abctime clk; + int RetValue; + + // make sure the nodes are not complemented + assert( !Ivy_IsComplement(pNew) ); + assert( pNew != p->pManFraig->pConst1 ); + p->nSatCalls++; + + // make sure the solver is allocated and has enough variables + if ( p->pSat == NULL ) + { + p->pSat = sat_solver_new(); + sat_solver_setnvars( p->pSat, 1000 ); + p->pSat->factors = ABC_CALLOC( double, p->pSat->cap ); + p->nSatVars = 1; + // var 0 is reserved for const1 node - add the clause +// pLits[0] = toLit( 0 ); +// sat_solver_addclause( p->pSat, pLits, pLits + 1 ); + } + + // if the nodes do not have SAT variables, allocate them + Ivy_FraigNodeAddToSolver( p, NULL, pNew ); + + // prepare variable activity + Ivy_FraigSetActivityFactors( p, NULL, pNew ); + + // solve under assumptions +clk = Abc_Clock(); + pLits[0] = toLitCond( Ivy_ObjSatNum(pNew), pNew->fPhase ); + RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 1, + (ABC_INT64_T)p->pParams->nBTLimitMiter, (ABC_INT64_T)0, + p->nBTLimitGlobal, p->nInsLimitGlobal ); +p->timeSat += Abc_Clock() - clk; + if ( RetValue1 == l_False ) + { +p->timeSatUnsat += Abc_Clock() - clk; + pLits[0] = lit_neg( pLits[0] ); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 1 ); + assert( RetValue ); + // continue solving the other implication + p->nSatCallsUnsat++; + } + else if ( RetValue1 == l_True ) + { +p->timeSatSat += Abc_Clock() - clk; + if ( p->pPatWords ) + Ivy_FraigSavePattern( p ); + p->nSatCallsSat++; + return 0; + } + else // if ( RetValue1 == l_Undef ) + { +p->timeSatFail += Abc_Clock() - clk; +/* + if ( p->pParams->nBTLimitMiter > 1000 ) + { + RetValue = Ivy_FraigCheckCone( p, p->pManFraig, p->pManFraig->pConst1, pNew, p->pParams->nBTLimitMiter ); + if ( RetValue != -1 ) + return RetValue; + } +*/ + // mark the node as the failed node + pNew->fFailTfo = 1; + p->nSatFailsReal++; + return -1; + } + + // return SAT proof + p->nSatProof++; + return 1; +} + +/**Function************************************************************* + + Synopsis [Addes clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigAddClausesMux( Ivy_FraigMan_t * p, Ivy_Obj_t * pNode ) +{ + Ivy_Obj_t * pNodeI, * pNodeT, * pNodeE; + int pLits[4], RetValue, VarF, VarI, VarT, VarE, fCompT, fCompE; + + assert( !Ivy_IsComplement( pNode ) ); + assert( Ivy_ObjIsMuxType( pNode ) ); + // get nodes (I = if, T = then, E = else) + pNodeI = Ivy_ObjRecognizeMux( pNode, &pNodeT, &pNodeE ); + // get the variable numbers + VarF = Ivy_ObjSatNum(pNode); + VarI = Ivy_ObjSatNum(pNodeI); + VarT = Ivy_ObjSatNum(Ivy_Regular(pNodeT)); + VarE = Ivy_ObjSatNum(Ivy_Regular(pNodeE)); + // get the complementation flags + fCompT = Ivy_IsComplement(pNodeT); + fCompE = Ivy_IsComplement(pNodeE); + + // f = ITE(i, t, e) + + // i' + t' + f + // i' + t + f' + // i + e' + f + // i + e + f' + + // create four clauses + pLits[0] = toLitCond(VarI, 1); + pLits[1] = toLitCond(VarT, 1^fCompT); + pLits[2] = toLitCond(VarF, 0); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + pLits[0] = toLitCond(VarI, 1); + pLits[1] = toLitCond(VarT, 0^fCompT); + pLits[2] = toLitCond(VarF, 1); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + pLits[0] = toLitCond(VarI, 0); + pLits[1] = toLitCond(VarE, 1^fCompE); + pLits[2] = toLitCond(VarF, 0); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + pLits[0] = toLitCond(VarI, 0); + pLits[1] = toLitCond(VarE, 0^fCompE); + pLits[2] = toLitCond(VarF, 1); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + + // two additional clauses + // t' & e' -> f' + // t & e -> f + + // t + e + f' + // t' + e' + f + + if ( VarT == VarE ) + { +// assert( fCompT == !fCompE ); + return; + } + + pLits[0] = toLitCond(VarT, 0^fCompT); + pLits[1] = toLitCond(VarE, 0^fCompE); + pLits[2] = toLitCond(VarF, 1); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); + pLits[0] = toLitCond(VarT, 1^fCompT); + pLits[1] = toLitCond(VarE, 1^fCompE); + pLits[2] = toLitCond(VarF, 0); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 3 ); + assert( RetValue ); +} + +/**Function************************************************************* + + Synopsis [Addes clauses to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigAddClausesSuper( Ivy_FraigMan_t * p, Ivy_Obj_t * pNode, Vec_Ptr_t * vSuper ) +{ + Ivy_Obj_t * pFanin; + int * pLits, nLits, RetValue, i; + assert( !Ivy_IsComplement(pNode) ); + assert( Ivy_ObjIsNode( pNode ) ); + // create storage for literals + nLits = Vec_PtrSize(vSuper) + 1; + pLits = ABC_ALLOC( int, nLits ); + // suppose AND-gate is A & B = C + // add !A => !C or A + !C + Vec_PtrForEachEntry( Ivy_Obj_t *, vSuper, pFanin, i ) + { + pLits[0] = toLitCond(Ivy_ObjSatNum(Ivy_Regular(pFanin)), Ivy_IsComplement(pFanin)); + pLits[1] = toLitCond(Ivy_ObjSatNum(pNode), 1); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 ); + assert( RetValue ); + } + // add A & B => C or !A + !B + C + Vec_PtrForEachEntry( Ivy_Obj_t *, vSuper, pFanin, i ) + pLits[i] = toLitCond(Ivy_ObjSatNum(Ivy_Regular(pFanin)), !Ivy_IsComplement(pFanin)); + pLits[nLits-1] = toLitCond(Ivy_ObjSatNum(pNode), 0); + RetValue = sat_solver_addclause( p->pSat, pLits, pLits + nLits ); + assert( RetValue ); + ABC_FREE( pLits ); +} + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigCollectSuper_rec( Ivy_Obj_t * pObj, Vec_Ptr_t * vSuper, int fFirst, int fUseMuxes ) +{ + // if the new node is complemented or a PI, another gate begins + if ( Ivy_IsComplement(pObj) || Ivy_ObjIsPi(pObj) || (!fFirst && Ivy_ObjRefs(pObj) > 1) || + (fUseMuxes && Ivy_ObjIsMuxType(pObj)) ) + { + Vec_PtrPushUnique( vSuper, pObj ); + return; + } + // go through the branches + Ivy_FraigCollectSuper_rec( Ivy_ObjChild0(pObj), vSuper, 0, fUseMuxes ); + Ivy_FraigCollectSuper_rec( Ivy_ObjChild1(pObj), vSuper, 0, fUseMuxes ); +} + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Ivy_FraigCollectSuper( Ivy_Obj_t * pObj, int fUseMuxes ) +{ + Vec_Ptr_t * vSuper; + assert( !Ivy_IsComplement(pObj) ); + assert( !Ivy_ObjIsPi(pObj) ); + vSuper = Vec_PtrAlloc( 4 ); + Ivy_FraigCollectSuper_rec( pObj, vSuper, 1, fUseMuxes ); + return vSuper; +} + +/**Function************************************************************* + + Synopsis [Updates the solver clause database.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigObjAddToFrontier( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, Vec_Ptr_t * vFrontier ) +{ + assert( !Ivy_IsComplement(pObj) ); + if ( Ivy_ObjSatNum(pObj) ) + return; + assert( Ivy_ObjSatNum(pObj) == 0 ); + assert( Ivy_ObjFaninVec(pObj) == NULL ); + if ( Ivy_ObjIsConst1(pObj) ) + return; +//printf( "Assigning node %d number %d\n", pObj->Id, p->nSatVars ); + Ivy_ObjSetSatNum( pObj, p->nSatVars++ ); + if ( Ivy_ObjIsNode(pObj) ) + Vec_PtrPush( vFrontier, pObj ); +} + +/**Function************************************************************* + + Synopsis [Updates the solver clause database.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigNodeAddToSolver( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ) +{ + Vec_Ptr_t * vFrontier, * vFanins; + Ivy_Obj_t * pNode, * pFanin; + int i, k, fUseMuxes = 1; + assert( pOld || pNew ); + // quit if CNF is ready + if ( (!pOld || Ivy_ObjFaninVec(pOld)) && (!pNew || Ivy_ObjFaninVec(pNew)) ) + return; + // start the frontier + vFrontier = Vec_PtrAlloc( 100 ); + if ( pOld ) Ivy_FraigObjAddToFrontier( p, pOld, vFrontier ); + if ( pNew ) Ivy_FraigObjAddToFrontier( p, pNew, vFrontier ); + // explore nodes in the frontier + Vec_PtrForEachEntry( Ivy_Obj_t *, vFrontier, pNode, i ) + { + // create the supergate + assert( Ivy_ObjSatNum(pNode) ); + assert( Ivy_ObjFaninVec(pNode) == NULL ); + if ( fUseMuxes && Ivy_ObjIsMuxType(pNode) ) + { + vFanins = Vec_PtrAlloc( 4 ); + Vec_PtrPushUnique( vFanins, Ivy_ObjFanin0( Ivy_ObjFanin0(pNode) ) ); + Vec_PtrPushUnique( vFanins, Ivy_ObjFanin0( Ivy_ObjFanin1(pNode) ) ); + Vec_PtrPushUnique( vFanins, Ivy_ObjFanin1( Ivy_ObjFanin0(pNode) ) ); + Vec_PtrPushUnique( vFanins, Ivy_ObjFanin1( Ivy_ObjFanin1(pNode) ) ); + Vec_PtrForEachEntry( Ivy_Obj_t *, vFanins, pFanin, k ) + Ivy_FraigObjAddToFrontier( p, Ivy_Regular(pFanin), vFrontier ); + Ivy_FraigAddClausesMux( p, pNode ); + } + else + { + vFanins = Ivy_FraigCollectSuper( pNode, fUseMuxes ); + Vec_PtrForEachEntry( Ivy_Obj_t *, vFanins, pFanin, k ) + Ivy_FraigObjAddToFrontier( p, Ivy_Regular(pFanin), vFrontier ); + Ivy_FraigAddClausesSuper( p, pNode, vFanins ); + } + assert( Vec_PtrSize(vFanins) > 1 ); + Ivy_ObjSetFaninVec( pNode, vFanins ); + } + Vec_PtrFree( vFrontier ); + sat_solver_simplify( p->pSat ); +} + +/**Function************************************************************* + + Synopsis [Sets variable activities in the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigSetActivityFactors_rec( Ivy_FraigMan_t * p, Ivy_Obj_t * pObj, int LevelMin, int LevelMax ) +{ + Vec_Ptr_t * vFanins; + Ivy_Obj_t * pFanin; + int i, Counter = 0; + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjSatNum(pObj) ); + // skip visited variables + if ( Ivy_ObjIsTravIdCurrent(p->pManFraig, pObj) ) + return 0; + Ivy_ObjSetTravIdCurrent(p->pManFraig, pObj); + // add the PI to the list + if ( pObj->Level <= (unsigned)LevelMin || Ivy_ObjIsPi(pObj) ) + return 0; + // set the factor of this variable + // (LevelMax-LevelMin) / (pObj->Level-LevelMin) = p->pParams->dActConeBumpMax / ThisBump + p->pSat->factors[Ivy_ObjSatNum(pObj)] = p->pParams->dActConeBumpMax * (pObj->Level - LevelMin)/(LevelMax - LevelMin); + veci_push(&p->pSat->act_vars, Ivy_ObjSatNum(pObj)); + // explore the fanins + vFanins = Ivy_ObjFaninVec( pObj ); + Vec_PtrForEachEntry( Ivy_Obj_t *, vFanins, pFanin, i ) + Counter += Ivy_FraigSetActivityFactors_rec( p, Ivy_Regular(pFanin), LevelMin, LevelMax ); + return 1 + Counter; +} + +/**Function************************************************************* + + Synopsis [Sets variable activities in the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigSetActivityFactors( Ivy_FraigMan_t * p, Ivy_Obj_t * pOld, Ivy_Obj_t * pNew ) +{ + int LevelMin, LevelMax; + abctime clk; + assert( pOld || pNew ); +clk = Abc_Clock(); + // reset the active variables + veci_resize(&p->pSat->act_vars, 0); + // prepare for traversal + Ivy_ManIncrementTravId( p->pManFraig ); + // determine the min and max level to visit + assert( p->pParams->dActConeRatio > 0 && p->pParams->dActConeRatio < 1 ); + LevelMax = IVY_MAX( (pNew ? pNew->Level : 0), (pOld ? pOld->Level : 0) ); + LevelMin = (int)(LevelMax * (1.0 - p->pParams->dActConeRatio)); + // traverse + if ( pOld && !Ivy_ObjIsConst1(pOld) ) + Ivy_FraigSetActivityFactors_rec( p, pOld, LevelMin, LevelMax ); + if ( pNew && !Ivy_ObjIsConst1(pNew) ) + Ivy_FraigSetActivityFactors_rec( p, pNew, LevelMin, LevelMax ); +//Ivy_FraigPrintActivity( p ); +p->timeTrav += Abc_Clock() - clk; + return 1; +} + +ABC_NAMESPACE_IMPL_END + +#ifdef ABC_USE_CUDD +#include "bdd/cudd/cuddInt.h" +#endif + +ABC_NAMESPACE_IMPL_START + +#ifdef ABC_USE_CUDD + +/**Function************************************************************* + + Synopsis [Checks equivalence using BDDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Ivy_FraigNodesAreEquivBdd_int( DdManager * dd, DdNode * bFunc, Vec_Ptr_t * vFront, int Level ) +{ + DdNode ** pFuncs; + DdNode * bFuncNew; + Vec_Ptr_t * vTemp; + Ivy_Obj_t * pObj, * pFanin; + int i, NewSize; + // create new frontier + vTemp = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pObj, i ) + { + if ( (int)pObj->Level != Level ) + { + pObj->fMarkB = 1; + pObj->TravId = Vec_PtrSize(vTemp); + Vec_PtrPush( vTemp, pObj ); + continue; + } + + pFanin = Ivy_ObjFanin0(pObj); + if ( pFanin->fMarkB == 0 ) + { + pFanin->fMarkB = 1; + pFanin->TravId = Vec_PtrSize(vTemp); + Vec_PtrPush( vTemp, pFanin ); + } + + pFanin = Ivy_ObjFanin1(pObj); + if ( pFanin->fMarkB == 0 ) + { + pFanin->fMarkB = 1; + pFanin->TravId = Vec_PtrSize(vTemp); + Vec_PtrPush( vTemp, pFanin ); + } + } + // collect the permutation + NewSize = IVY_MAX(dd->size, Vec_PtrSize(vTemp)); + pFuncs = ABC_ALLOC( DdNode *, NewSize ); + Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pObj, i ) + { + if ( (int)pObj->Level != Level ) + pFuncs[i] = Cudd_bddIthVar( dd, pObj->TravId ); + else + pFuncs[i] = Cudd_bddAnd( dd, + Cudd_NotCond( Cudd_bddIthVar(dd, Ivy_ObjFanin0(pObj)->TravId), Ivy_ObjFaninC0(pObj) ), + Cudd_NotCond( Cudd_bddIthVar(dd, Ivy_ObjFanin1(pObj)->TravId), Ivy_ObjFaninC1(pObj) ) ); + Cudd_Ref( pFuncs[i] ); + } + // add the remaining vars + assert( NewSize == dd->size ); + for ( i = Vec_PtrSize(vFront); i < dd->size; i++ ) + { + pFuncs[i] = Cudd_bddIthVar( dd, i ); + Cudd_Ref( pFuncs[i] ); + } + + // create new + bFuncNew = Cudd_bddVectorCompose( dd, bFunc, pFuncs ); Cudd_Ref( bFuncNew ); + // clean trav Id + Vec_PtrForEachEntry( Ivy_Obj_t *, vTemp, pObj, i ) + { + pObj->fMarkB = 0; + pObj->TravId = 0; + } + // deref + for ( i = 0; i < dd->size; i++ ) + Cudd_RecursiveDeref( dd, pFuncs[i] ); + ABC_FREE( pFuncs ); + + ABC_FREE( vFront->pArray ); + *vFront = *vTemp; + + vTemp->nCap = vTemp->nSize = 0; + vTemp->pArray = NULL; + Vec_PtrFree( vTemp ); + + Cudd_Deref( bFuncNew ); + return bFuncNew; +} + +/**Function************************************************************* + + Synopsis [Checks equivalence using BDDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigNodesAreEquivBdd( Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2 ) +{ + static DdManager * dd = NULL; + DdNode * bFunc, * bTemp; + Vec_Ptr_t * vFront; + Ivy_Obj_t * pObj; + int i, RetValue, Iter, Level; + // start the manager + if ( dd == NULL ) + dd = Cudd_Init( 50, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + // create front + vFront = Vec_PtrAlloc( 100 ); + Vec_PtrPush( vFront, pObj1 ); + Vec_PtrPush( vFront, pObj2 ); + // get the function + bFunc = Cudd_bddXor( dd, Cudd_bddIthVar(dd,0), Cudd_bddIthVar(dd,1) ); Cudd_Ref( bFunc ); + bFunc = Cudd_NotCond( bFunc, pObj1->fPhase != pObj2->fPhase ); + // try running BDDs + for ( Iter = 0; ; Iter++ ) + { + // find max level + Level = 0; + Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pObj, i ) + if ( Level < (int)pObj->Level ) + Level = (int)pObj->Level; + if ( Level == 0 ) + break; + bFunc = Ivy_FraigNodesAreEquivBdd_int( dd, bTemp = bFunc, vFront, Level ); Cudd_Ref( bFunc ); + Cudd_RecursiveDeref( dd, bTemp ); + if ( bFunc == Cudd_ReadLogicZero(dd) ) // proved + {printf( "%d", Iter ); break;} + if ( Cudd_DagSize(bFunc) > 1000 ) + {printf( "b" ); break;} + if ( dd->size > 120 ) + {printf( "s" ); break;} + if ( Iter > 50 ) + {printf( "i" ); break;} + } + if ( bFunc == Cudd_ReadLogicZero(dd) ) // unsat + RetValue = 1; + else if ( Level == 0 ) // sat + RetValue = 0; + else + RetValue = -1; // spaceout/timeout + Cudd_RecursiveDeref( dd, bFunc ); + Vec_PtrFree( vFront ); + return RetValue; +} +#endif + +ABC_NAMESPACE_IMPL_END + +#include "aig/aig/aig.h" + +ABC_NAMESPACE_IMPL_START + + +/**Function************************************************************* + + Synopsis [Computes truth table of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_FraigExtractCone_rec( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ) +{ + if ( pNode->fMarkB ) + return; + pNode->fMarkB = 1; + if ( Ivy_ObjIsPi(pNode) ) + { + Vec_IntPush( vLeaves, pNode->Id ); + return; + } + assert( Ivy_ObjIsAnd(pNode) ); + Ivy_FraigExtractCone_rec( p, Ivy_ObjFanin0(pNode), vLeaves, vNodes ); + Ivy_FraigExtractCone_rec( p, Ivy_ObjFanin1(pNode), vLeaves, vNodes ); + Vec_IntPush( vNodes, pNode->Id ); +} + +/**Function************************************************************* + + Synopsis [Checks equivalence using BDDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Ivy_FraigExtractCone( Ivy_Man_t * p, Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2, Vec_Int_t * vLeaves ) +{ + Aig_Man_t * pMan; + Aig_Obj_t * pMiter; + Vec_Int_t * vNodes; + Ivy_Obj_t * pObjIvy; + int i; + // collect nodes + vNodes = Vec_IntAlloc( 100 ); + Ivy_ManConst1(p)->fMarkB = 1; + Ivy_FraigExtractCone_rec( p, pObj1, vLeaves, vNodes ); + Ivy_FraigExtractCone_rec( p, pObj2, vLeaves, vNodes ); + Ivy_ManConst1(p)->fMarkB = 0; + // create new manager + pMan = Aig_ManStart( 1000 ); + Ivy_ManConst1(p)->pEquiv = (Ivy_Obj_t *)Aig_ManConst1(pMan); + Ivy_ManForEachNodeVec( p, vLeaves, pObjIvy, i ) + { + pObjIvy->pEquiv = (Ivy_Obj_t *)Aig_ObjCreateCi( pMan ); + pObjIvy->fMarkB = 0; + } + // duplicate internal nodes + Ivy_ManForEachNodeVec( p, vNodes, pObjIvy, i ) + { + + pObjIvy->pEquiv = (Ivy_Obj_t *)Aig_And( pMan, (Aig_Obj_t *)Ivy_ObjChild0Equiv(pObjIvy), (Aig_Obj_t *)Ivy_ObjChild1Equiv(pObjIvy) ); + pObjIvy->fMarkB = 0; + + pMiter = (Aig_Obj_t *)pObjIvy->pEquiv; + assert( pMiter->fPhase == pObjIvy->fPhase ); + } + // create the PO + pMiter = Aig_Exor( pMan, (Aig_Obj_t *)pObj1->pEquiv, (Aig_Obj_t *)pObj2->pEquiv ); + pMiter = Aig_NotCond( pMiter, Aig_Regular(pMiter)->fPhase ^ Aig_IsComplement(pMiter) ); + +/* +printf( "Polarity = %d\n", pMiter->fPhase ); + if ( Ivy_ObjIsConst1(pObj1) || Ivy_ObjIsConst1(pObj2) ) + { + pMiter = Aig_NotCond( pMiter, 1 ); +printf( "***************\n" ); + } +*/ + pMiter = Aig_ObjCreateCo( pMan, pMiter ); +//printf( "Polarity = %d\n", pMiter->fPhase ); + Aig_ManCleanup( pMan ); + Vec_IntFree( vNodes ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [Checks equivalence using BDDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_FraigCheckCone( Ivy_FraigMan_t * pGlo, Ivy_Man_t * p, Ivy_Obj_t * pObj1, Ivy_Obj_t * pObj2, int nConfLimit ) +{ + extern int Fra_FraigSat( Aig_Man_t * pMan, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int nLearnedStart, int nLearnedDelta, int nLearnedPerce, int fFlipBits, int fAndOuts, int fNewSolver, int fVerbose ); + Vec_Int_t * vLeaves; + Aig_Man_t * pMan; + Aig_Obj_t * pObj; + int i, RetValue; + vLeaves = Vec_IntAlloc( 100 ); + pMan = Ivy_FraigExtractCone( p, pObj1, pObj2, vLeaves ); + RetValue = Fra_FraigSat( pMan, nConfLimit, 0, 0, 0, 0, 0, 0, 0, 1 ); + if ( RetValue == 0 ) + { + int Counter = 0; + memset( pGlo->pPatWords, 0, sizeof(unsigned) * pGlo->nPatWords ); + Aig_ManForEachCi( pMan, pObj, i ) + if ( ((int *)pMan->pData)[i] ) + { + int iObjIvy = Vec_IntEntry( vLeaves, i ); + assert( iObjIvy > 0 && iObjIvy <= Ivy_ManPiNum(p) ); + Ivy_InfoSetBit( pGlo->pPatWords, iObjIvy-1 ); +//printf( "%d ", iObjIvy ); +Counter++; + } + assert( Counter > 0 ); + } + Vec_IntFree( vLeaves ); + if ( RetValue == 1 ) + printf( "UNSAT\n" ); + else if ( RetValue == 0 ) + printf( "SAT\n" ); + else if ( RetValue == -1 ) + printf( "UNDEC\n" ); + +// p->pModel = (int *)pMan->pData, pMan2->pData = NULL; + Aig_ManStop( pMan ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/ivyHaig.c b/yosys/abc/src/aig/ivy/ivyHaig.c new file mode 100644 index 00000000000..a4fda7d80a6 --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivyHaig.c @@ -0,0 +1,535 @@ +/**CFile**************************************************************** + + FileName [ivyHaig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [HAIG management procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyHaig.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/* + HAIGing rules in working AIG: + - Each node in the working AIG has a pointer to the corresponding node in HAIG + (this node is not necessarily the representative of the equivalence class of HAIG nodes) + - This pointer is complemented if the AIG node and its corresponding HAIG node have different phase + + Choice node rules in HAIG: + - Equivalent nodes are linked into a ring + - Exactly one node in the ring has fanouts (this node is called the representative) + - The pointer going from a node to the next node in the ring is complemented + if the first node is complemented, compared to the representative node of the equivalence class + - (consequence of the above) The representative node always has non-complemented pointer to the next node + - New nodes are inserted into the ring immediately after the representative node +*/ + +// returns the representative node of the given HAIG node +static inline Ivy_Obj_t * Ivy_HaigObjRepr( Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pTemp; + assert( !Ivy_IsComplement(pObj) ); + // if the node has no equivalent node or has fanout, it is representative + if ( pObj->pEquiv == NULL || Ivy_ObjRefs(pObj) > 0 ) + return pObj; + // the node belongs to a class and is not a representative + // complemented edge (pObj->pEquiv) tells if it is complemented w.r.t. the repr + for ( pTemp = Ivy_Regular(pObj->pEquiv); pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + if ( Ivy_ObjRefs(pTemp) > 0 ) + break; + // return the representative node + assert( Ivy_ObjRefs(pTemp) > 0 ); + return Ivy_NotCond( pTemp, Ivy_IsComplement(pObj->pEquiv) ); +} + +// counts the number of nodes in the equivalence class +static inline int Ivy_HaigObjCountClass( Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pTemp; + int Counter; + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjRefs(pObj) > 0 ); + if ( pObj->pEquiv == NULL ) + return 1; + assert( !Ivy_IsComplement(pObj->pEquiv) ); + Counter = 1; + for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + Counter++; + return Counter; +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts HAIG for the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigStart( Ivy_Man_t * p, int fVerbose ) +{ + Vec_Int_t * vLatches; + Ivy_Obj_t * pObj; + int i; + assert( p->pHaig == NULL ); + p->pHaig = Ivy_ManDup( p ); + + if ( fVerbose ) + { + printf( "Starting : " ); + Ivy_ManPrintStats( p->pHaig ); + } + + // collect latches of design D and set their values to be DC + vLatches = Vec_IntAlloc( 100 ); + Ivy_ManForEachLatch( p->pHaig, pObj, i ) + { + pObj->Init = IVY_INIT_DC; + Vec_IntPush( vLatches, pObj->Id ); + } + p->pHaig->pData = vLatches; +/* + { + int x; + Ivy_ManShow( p, 0, NULL ); + Ivy_ManShow( p->pHaig, 1, NULL ); + x = 0; + } +*/ +} + +/**Function************************************************************* + + Synopsis [Transfers the HAIG to the newly created manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigTrasfer( Ivy_Man_t * p, Ivy_Man_t * pNew ) +{ + Ivy_Obj_t * pObj; + int i; + assert( p->pHaig != NULL ); + Ivy_ManConst1(pNew)->pEquiv = Ivy_ManConst1(p)->pEquiv; + Ivy_ManForEachPi( pNew, pObj, i ) + pObj->pEquiv = Ivy_ManPi( p, i )->pEquiv; + pNew->pHaig = p->pHaig; +} + +/**Function************************************************************* + + Synopsis [Stops HAIG for the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigStop( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + assert( p->pHaig != NULL ); + Vec_IntFree( (Vec_Int_t *)p->pHaig->pData ); + Ivy_ManStop( p->pHaig ); + p->pHaig = NULL; + // remove dangling pointers to the HAIG objects + Ivy_ManForEachObj( p, pObj, i ) + pObj->pEquiv = NULL; +} + +/**Function************************************************************* + + Synopsis [Creates a new node in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigCreateObj( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pEquiv0, * pEquiv1; + assert( p->pHaig != NULL ); + assert( !Ivy_IsComplement(pObj) ); + if ( Ivy_ObjType(pObj) == IVY_BUF ) + pObj->pEquiv = Ivy_ObjChild0Equiv(pObj); + else if ( Ivy_ObjType(pObj) == IVY_LATCH ) + { +// pObj->pEquiv = Ivy_Latch( p->pHaig, Ivy_ObjChild0Equiv(pObj), pObj->Init ); + pEquiv0 = Ivy_ObjChild0Equiv(pObj); + pEquiv0 = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pEquiv0)), Ivy_IsComplement(pEquiv0) ); + pObj->pEquiv = Ivy_Latch( p->pHaig, pEquiv0, (Ivy_Init_t)pObj->Init ); + } + else if ( Ivy_ObjType(pObj) == IVY_AND ) + { +// pObj->pEquiv = Ivy_And( p->pHaig, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); + pEquiv0 = Ivy_ObjChild0Equiv(pObj); + pEquiv0 = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pEquiv0)), Ivy_IsComplement(pEquiv0) ); + pEquiv1 = Ivy_ObjChild1Equiv(pObj); + pEquiv1 = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pEquiv1)), Ivy_IsComplement(pEquiv1) ); + pObj->pEquiv = Ivy_And( p->pHaig, pEquiv0, pEquiv1 ); + } + else assert( 0 ); + // make sure the node points to the representative +// pObj->pEquiv = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObj->pEquiv)), Ivy_IsComplement(pObj->pEquiv) ); +} + +/**Function************************************************************* + + Synopsis [Checks if the old node is in the TFI of the new node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ObjIsInTfi_rec( Ivy_Obj_t * pObjNew, Ivy_Obj_t * pObjOld, int Levels ) +{ + if ( pObjNew == pObjOld ) + return 1; + if ( Levels == 0 || Ivy_ObjIsCi(pObjNew) || Ivy_ObjIsConst1(pObjNew) ) + return 0; + if ( Ivy_ObjIsInTfi_rec( Ivy_ObjFanin0(pObjNew), pObjOld, Levels - 1 ) ) + return 1; + if ( Ivy_ObjIsNode(pObjNew) && Ivy_ObjIsInTfi_rec( Ivy_ObjFanin1(pObjNew), pObjOld, Levels - 1 ) ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Sets the pair of equivalent nodes in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigCreateChoice( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew ) +{ + Ivy_Obj_t * pObjOldHaig, * pObjNewHaig; + Ivy_Obj_t * pObjOldHaigR, * pObjNewHaigR; + int fCompl; +//printf( "\nCreating choice for %d and %d in AIG\n", pObjOld->Id, Ivy_Regular(pObjNew)->Id ); + + assert( p->pHaig != NULL ); + assert( !Ivy_IsComplement(pObjOld) ); + // get pointers to the representatives of pObjOld and pObjNew + pObjOldHaig = pObjOld->pEquiv; + pObjNewHaig = Ivy_NotCond( Ivy_Regular(pObjNew)->pEquiv, Ivy_IsComplement(pObjNew) ); + // get the classes + pObjOldHaig = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObjOldHaig)), Ivy_IsComplement(pObjOldHaig) ); + pObjNewHaig = Ivy_NotCond( Ivy_HaigObjRepr(Ivy_Regular(pObjNewHaig)), Ivy_IsComplement(pObjNewHaig) ); + // get regular pointers + pObjOldHaigR = Ivy_Regular(pObjOldHaig); + pObjNewHaigR = Ivy_Regular(pObjNewHaig); + // check if there is phase difference between them + fCompl = (Ivy_IsComplement(pObjOldHaig) != Ivy_IsComplement(pObjNewHaig)); + // if the class is the same, nothing to do + if ( pObjOldHaigR == pObjNewHaigR ) + return; + // if the second node belongs to a class, do not merge classes (for the time being) + if ( Ivy_ObjRefs(pObjOldHaigR) == 0 || pObjNewHaigR->pEquiv != NULL || + Ivy_ObjRefs(pObjNewHaigR) > 0 ) //|| Ivy_ObjIsInTfi_rec(pObjNewHaigR, pObjOldHaigR, 10) ) + { +/* + if ( pObjNewHaigR->pEquiv != NULL ) + printf( "c" ); + if ( Ivy_ObjRefs(pObjNewHaigR) > 0 ) + printf( "f" ); + printf( " " ); +*/ + p->pHaig->nClassesSkip++; + return; + } + + // add this node to the class of pObjOldHaig + assert( Ivy_ObjRefs(pObjOldHaigR) > 0 ); + assert( !Ivy_IsComplement(pObjOldHaigR->pEquiv) ); + if ( pObjOldHaigR->pEquiv == NULL ) + pObjNewHaigR->pEquiv = Ivy_NotCond( pObjOldHaigR, fCompl ); + else + pObjNewHaigR->pEquiv = Ivy_NotCond( pObjOldHaigR->pEquiv, fCompl ); + pObjOldHaigR->pEquiv = pObjNewHaigR; +//printf( "Setting choice node %d -> %d.\n", pObjOldHaigR->Id, pObjNewHaigR->Id ); + // update the class of the new node +// Ivy_Regular(pObjNew)->pEquiv = Ivy_NotCond( pObjOldHaigR, fCompl ^ Ivy_IsComplement(pObjNew) ); +//printf( "Creating choice for %d and %d in HAIG\n", pObjOldHaigR->Id, pObjNewHaigR->Id ); + +// if ( pObjOldHaigR->Id == 13 ) +// { +// Ivy_ManShow( p, 0 ); +// Ivy_ManShow( p->pHaig, 1 ); +// } +// if ( !Ivy_ManIsAcyclic( p->pHaig ) ) +// printf( "HAIG contains a cycle\n" ); +} + +/**Function************************************************************* + + Synopsis [Count the number of choices and choice nodes in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManHaigCountChoices( Ivy_Man_t * p, int * pnChoices ) +{ + Ivy_Obj_t * pObj; + int nChoices, nChoiceNodes, Counter, i; + assert( p->pHaig != NULL ); + nChoices = nChoiceNodes = 0; + Ivy_ManForEachObj( p->pHaig, pObj, i ) + { + if ( Ivy_ObjIsTerm(pObj) || i == 0 ) + continue; + if ( Ivy_ObjRefs(pObj) == 0 ) + continue; + Counter = Ivy_HaigObjCountClass( pObj ); + nChoiceNodes += (int)(Counter > 1); + nChoices += Counter - 1; +// if ( Counter > 1 ) +// printf( "Choice node %d %s\n", pObj->Id, Ivy_ObjIsLatch(pObj)? "(latch)": "" ); + } + *pnChoices = nChoices; + return nChoiceNodes; +} + +/**Function************************************************************* + + Synopsis [Prints statistics of the HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigPostprocess( Ivy_Man_t * p, int fVerbose ) +{ + int nChoices, nChoiceNodes; + + assert( p->pHaig != NULL ); + + if ( fVerbose ) + { + printf( "Final : " ); + Ivy_ManPrintStats( p ); + printf( "HAIG : " ); + Ivy_ManPrintStats( p->pHaig ); + + // print choice node stats + nChoiceNodes = Ivy_ManHaigCountChoices( p, &nChoices ); + printf( "Total choice nodes = %d. Total choices = %d. Skipped classes = %d.\n", + nChoiceNodes, nChoices, p->pHaig->nClassesSkip ); + } + + if ( Ivy_ManIsAcyclic( p->pHaig ) ) + { + if ( fVerbose ) + printf( "HAIG is acyclic\n" ); + } + else + printf( "HAIG contains a cycle\n" ); + +// if ( fVerbose ) +// Ivy_ManHaigSimulate( p ); +} + + +/**Function************************************************************* + + Synopsis [Applies the simulation rules.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Ivy_Init_t Ivy_ManHaigSimulateAnd( Ivy_Init_t In0, Ivy_Init_t In1 ) +{ + assert( In0 != IVY_INIT_NONE && In1 != IVY_INIT_NONE ); + if ( In0 == IVY_INIT_DC || In1 == IVY_INIT_DC ) + return IVY_INIT_DC; + if ( In0 == IVY_INIT_1 && In1 == IVY_INIT_1 ) + return IVY_INIT_1; + return IVY_INIT_0; +} + +/**Function************************************************************* + + Synopsis [Applies the simulation rules.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Ivy_Init_t Ivy_ManHaigSimulateChoice( Ivy_Init_t In0, Ivy_Init_t In1 ) +{ + assert( In0 != IVY_INIT_NONE && In1 != IVY_INIT_NONE ); + if ( (In0 == IVY_INIT_0 && In1 == IVY_INIT_1) || (In0 == IVY_INIT_1 && In1 == IVY_INIT_0) ) + { + printf( "Compatibility fails.\n" ); + return IVY_INIT_0; + } + if ( In0 == IVY_INIT_DC && In1 == IVY_INIT_DC ) + return IVY_INIT_DC; + if ( In0 != IVY_INIT_DC ) + return In0; + return In1; +} + +/**Function************************************************************* + + Synopsis [Simulate HAIG using modified 3-valued simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManHaigSimulate( Ivy_Man_t * p ) +{ + Vec_Int_t * vNodes, * vLatches, * vLatchesD; + Ivy_Obj_t * pObj, * pTemp; + Ivy_Init_t In0, In1; + int i, k, Counter; + int fVerbose = 0; + + // check choices + Ivy_ManCheckChoices( p ); + + // switch to HAIG + assert( p->pHaig != NULL ); + p = p->pHaig; + +if ( fVerbose ) +Ivy_ManForEachPi( p, pObj, i ) +printf( "Setting PI %d\n", pObj->Id ); + + // collect latches and nodes in the DFS order + vNodes = Ivy_ManDfsSeq( p, &vLatches ); + +if ( fVerbose ) +Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) +printf( "Collected node %d with fanins %d and %d\n", pObj->Id, Ivy_ObjFanin0(pObj)->Id, Ivy_ObjFanin1(pObj)->Id ); + + // set the PI values + Ivy_ManConst1(p)->Init = IVY_INIT_1; + Ivy_ManForEachPi( p, pObj, i ) + pObj->Init = IVY_INIT_0; + + // set the latch values + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + pObj->Init = IVY_INIT_DC; + // set the latches of D to be determinate + vLatchesD = (Vec_Int_t *)p->pData; + Ivy_ManForEachNodeVec( p, vLatchesD, pObj, i ) + pObj->Init = IVY_INIT_0; + + // perform several rounds of simulation + for ( k = 0; k < 10; k++ ) + { + // count the number of non-determinate values + Counter = 0; + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + Counter += ( pObj->Init == IVY_INIT_DC ); + printf( "Iter %d : Non-determinate = %d\n", k, Counter ); + + // simulate the internal nodes + Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) + { +if ( fVerbose ) +printf( "Processing node %d with fanins %d and %d\n", pObj->Id, Ivy_ObjFanin0(pObj)->Id, Ivy_ObjFanin1(pObj)->Id ); + In0 = Ivy_InitNotCond( (Ivy_Init_t)Ivy_ObjFanin0(pObj)->Init, Ivy_ObjFaninC0(pObj) ); + In1 = Ivy_InitNotCond( (Ivy_Init_t)Ivy_ObjFanin1(pObj)->Init, Ivy_ObjFaninC1(pObj) ); + pObj->Init = Ivy_ManHaigSimulateAnd( In0, In1 ); + // simulate the equivalence class if the node is a representative + if ( pObj->pEquiv && Ivy_ObjRefs(pObj) > 0 ) + { +if ( fVerbose ) +printf( "Processing choice node %d\n", pObj->Id ); + In0 = (Ivy_Init_t)pObj->Init; + assert( !Ivy_IsComplement(pObj->pEquiv) ); + for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + { +if ( fVerbose ) +printf( "Processing secondary node %d\n", pTemp->Id ); + In1 = Ivy_InitNotCond( (Ivy_Init_t)pTemp->Init, Ivy_IsComplement(pTemp->pEquiv) ); + In0 = Ivy_ManHaigSimulateChoice( In0, In1 ); + } + pObj->Init = In0; + } + } + + // simulate the latches + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + { + pObj->Level = Ivy_ObjFanin0(pObj)->Init; +if ( fVerbose ) +printf( "Using latch %d with fanin %d\n", pObj->Id, Ivy_ObjFanin0(pObj)->Id ); + } + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + pObj->Init = pObj->Level, pObj->Level = 0; + } + // free arrays + Vec_IntFree( vNodes ); + Vec_IntFree( vLatches ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/ivyMan.c b/yosys/abc/src/aig/ivy/ivyMan.c new file mode 100644 index 00000000000..6fa34144c92 --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivyMan.c @@ -0,0 +1,552 @@ +/**CFile**************************************************************** + + FileName [ivyMan.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [AIG manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivy_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManStart() +{ + Ivy_Man_t * p; + // start the manager + p = ABC_ALLOC( Ivy_Man_t, 1 ); + memset( p, 0, sizeof(Ivy_Man_t) ); + // perform initializations + p->Ghost.Id = -1; + p->nTravIds = 1; + p->fCatchExor = 1; + // allocate arrays for nodes + p->vPis = Vec_PtrAlloc( 100 ); + p->vPos = Vec_PtrAlloc( 100 ); + p->vBufs = Vec_PtrAlloc( 100 ); + p->vObjs = Vec_PtrAlloc( 100 ); + // prepare the internal memory manager + Ivy_ManStartMemory( p ); + // create the constant node + p->pConst1 = Ivy_ManFetchMemory( p ); + p->pConst1->fPhase = 1; + Vec_PtrPush( p->vObjs, p->pConst1 ); + p->nCreated = 1; + // start the table + p->nTableSize = 10007; + p->pTable = ABC_ALLOC( int, p->nTableSize ); + memset( p->pTable, 0, sizeof(int) * p->nTableSize ); + return p; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManStartFrom( Ivy_Man_t * p ) +{ + Ivy_Man_t * pNew; + Ivy_Obj_t * pObj; + int i; + // create the new manager + pNew = Ivy_ManStart(); + // create the PIs + Ivy_ManConst1(p)->pEquiv = Ivy_ManConst1(pNew); + Ivy_ManForEachPi( p, pObj, i ) + pObj->pEquiv = Ivy_ObjCreatePi(pNew); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManDup( Ivy_Man_t * p ) +{ + Vec_Int_t * vNodes, * vLatches; + Ivy_Man_t * pNew; + Ivy_Obj_t * pObj; + int i; + // collect latches and nodes in the DFS order + vNodes = Ivy_ManDfsSeq( p, &vLatches ); + // create the new manager + pNew = Ivy_ManStart(); + // create the PIs + Ivy_ManConst1(p)->pEquiv = Ivy_ManConst1(pNew); + Ivy_ManForEachPi( p, pObj, i ) + pObj->pEquiv = Ivy_ObjCreatePi(pNew); + // create the fake PIs for latches + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + pObj->pEquiv = Ivy_ObjCreatePi(pNew); + // duplicate internal nodes + Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) + if ( Ivy_ObjIsBuf(pObj) ) + pObj->pEquiv = Ivy_ObjChild0Equiv(pObj); + else + pObj->pEquiv = Ivy_And( pNew, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); + // add the POs + Ivy_ManForEachPo( p, pObj, i ) + Ivy_ObjCreatePo( pNew, Ivy_ObjChild0Equiv(pObj) ); + // transform additional PI nodes into latches and connect them + Ivy_ManForEachNodeVec( p, vLatches, pObj, i ) + { + assert( !Ivy_ObjFaninC0(pObj) ); + pObj->pEquiv->Type = IVY_LATCH; + pObj->pEquiv->Init = pObj->Init; + Ivy_ObjConnect( pNew, pObj->pEquiv, Ivy_ObjChild0Equiv(pObj), NULL ); + } + // shrink the arrays + Vec_PtrShrink( pNew->vPis, Ivy_ManPiNum(p) ); + // update the counters of different objects + pNew->nObjs[IVY_PI] -= Ivy_ManLatchNum(p); + pNew->nObjs[IVY_LATCH] += Ivy_ManLatchNum(p); + // free arrays + Vec_IntFree( vNodes ); + Vec_IntFree( vLatches ); + // make sure structural hashing did not change anything + assert( Ivy_ManNodeNum(p) == Ivy_ManNodeNum(pNew) ); + assert( Ivy_ManLatchNum(p) == Ivy_ManLatchNum(pNew) ); + // check the resulting network + if ( !Ivy_ManCheck(pNew) ) + printf( "Ivy_ManMakeSeq(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Stops the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManFrames( Ivy_Man_t * pMan, int nLatches, int nFrames, int fInit, Vec_Ptr_t ** pvMapping ) +{ + Vec_Ptr_t * vMapping; + Ivy_Man_t * pNew; + Ivy_Obj_t * pObj; + int i, f, nPis, nPos, nIdMax; + assert( Ivy_ManLatchNum(pMan) == 0 ); + assert( nFrames > 0 ); + // prepare the mapping + nPis = Ivy_ManPiNum(pMan) - nLatches; + nPos = Ivy_ManPoNum(pMan) - nLatches; + nIdMax = Ivy_ManObjIdMax(pMan); + // create the new manager + pNew = Ivy_ManStart(); + // set the starting values of latch inputs + for ( i = 0; i < nLatches; i++ ) + Ivy_ManPo(pMan, nPos+i)->pEquiv = fInit? Ivy_Not(Ivy_ManConst1(pNew)) : Ivy_ObjCreatePi(pNew); + // add timeframes + vMapping = Vec_PtrStart( nIdMax * nFrames + 1 ); + for ( f = 0; f < nFrames; f++ ) + { + // create PIs + Ivy_ManConst1(pMan)->pEquiv = Ivy_ManConst1(pNew); + for ( i = 0; i < nPis; i++ ) + Ivy_ManPi(pMan, i)->pEquiv = Ivy_ObjCreatePi(pNew); + // transfer values to latch outputs + for ( i = 0; i < nLatches; i++ ) + Ivy_ManPi(pMan, nPis+i)->pEquiv = Ivy_ManPo(pMan, nPos+i)->pEquiv; + // perform strashing + Ivy_ManForEachNode( pMan, pObj, i ) + pObj->pEquiv = Ivy_And( pNew, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) ); + // create POs + for ( i = 0; i < nPos; i++ ) + Ivy_ManPo(pMan, i)->pEquiv = Ivy_ObjCreatePo( pNew, Ivy_ObjChild0Equiv(Ivy_ManPo(pMan, i)) ); + // set the results of latch inputs + for ( i = 0; i < nLatches; i++ ) + Ivy_ManPo(pMan, nPos+i)->pEquiv = Ivy_ObjChild0Equiv(Ivy_ManPo(pMan, nPos+i)); + // save the pointers in this frame + Ivy_ManForEachObj( pMan, pObj, i ) + Vec_PtrWriteEntry( vMapping, f * nIdMax + i, pObj->pEquiv ); + } + // connect latches + if ( !fInit ) + for ( i = 0; i < nLatches; i++ ) + Ivy_ObjCreatePo( pNew, Ivy_ManPo(pMan, nPos+i)->pEquiv ); + // remove dangling nodes + Ivy_ManCleanup(pNew); + *pvMapping = vMapping; + // check the resulting network + if ( !Ivy_ManCheck(pNew) ) + printf( "Ivy_ManFrames(): The check has failed.\n" ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Stops the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManStop( Ivy_Man_t * p ) +{ + if ( p->time1 ) { ABC_PRT( "Update lev ", p->time1 ); } + if ( p->time2 ) { ABC_PRT( "Update levR ", p->time2 ); } +// Ivy_TableProfile( p ); +// if ( p->vFanouts ) Ivy_ManStopFanout( p ); + if ( p->vChunks ) Ivy_ManStopMemory( p ); + if ( p->vRequired ) Vec_IntFree( p->vRequired ); + if ( p->vPis ) Vec_PtrFree( p->vPis ); + if ( p->vPos ) Vec_PtrFree( p->vPos ); + if ( p->vBufs ) Vec_PtrFree( p->vBufs ); + if ( p->vObjs ) Vec_PtrFree( p->vObjs ); + ABC_FREE( p->pTable ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Removes nodes without fanout.] + + Description [Returns the number of dangling nodes removed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManCleanup( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pNode; + int i, nNodesOld; + nNodesOld = Ivy_ManNodeNum(p); + Ivy_ManForEachObj( p, pNode, i ) + if ( Ivy_ObjIsNode(pNode) || Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) ) + if ( Ivy_ObjRefs(pNode) == 0 ) + Ivy_ObjDelete_rec( p, pNode, 1 ); +//printf( "Cleanup removed %d nodes.\n", nNodesOld - Ivy_ManNodeNum(p) ); + return nNodesOld - Ivy_ManNodeNum(p); +} + +/**Function************************************************************* + + Synopsis [Marks nodes reachable from the given one.] + + Description [Returns the number of dangling nodes removed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManCleanupSeq_rec( Ivy_Obj_t * pObj ) +{ + if ( Ivy_ObjIsMarkA(pObj) ) + return; + Ivy_ObjSetMarkA(pObj); + if ( pObj->pFanin0 != NULL ) + Ivy_ManCleanupSeq_rec( Ivy_ObjFanin0(pObj) ); + if ( pObj->pFanin1 != NULL ) + Ivy_ManCleanupSeq_rec( Ivy_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Removes logic that does not feed into POs.] + + Description [Returns the number of dangling nodes removed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManCleanupSeq( Ivy_Man_t * p ) +{ + Vec_Ptr_t * vNodes; + Ivy_Obj_t * pObj; + int i, RetValue; + // mark the constant and PIs + Ivy_ObjSetMarkA( Ivy_ManConst1(p) ); + Ivy_ManForEachPi( p, pObj, i ) + Ivy_ObjSetMarkA( pObj ); + // mark nodes visited from POs + Ivy_ManForEachPo( p, pObj, i ) + Ivy_ManCleanupSeq_rec( pObj ); + // collect unmarked nodes + vNodes = Vec_PtrAlloc( 100 ); + Ivy_ManForEachObj( p, pObj, i ) + { + if ( Ivy_ObjIsMarkA(pObj) ) + Ivy_ObjClearMarkA(pObj); + else + Vec_PtrPush( vNodes, pObj ); + } + if ( Vec_PtrSize(vNodes) == 0 ) + { + Vec_PtrFree( vNodes ); +//printf( "Sequential sweep cleaned out %d nodes.\n", 0 ); + return 0; + } + // disconnect the marked objects + Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pObj, i ) + Ivy_ObjDisconnect( p, pObj ); + // remove the dangling objects + Vec_PtrForEachEntry( Ivy_Obj_t *, vNodes, pObj, i ) + { + assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsLatch(pObj) || Ivy_ObjIsBuf(pObj) ); + assert( Ivy_ObjRefs(pObj) == 0 ); + // update node counters of the manager + p->nObjs[pObj->Type]--; + p->nDeleted++; + // delete buffer from the array of buffers + if ( p->fFanout && Ivy_ObjIsBuf(pObj) ) + Vec_PtrRemove( p->vBufs, pObj ); + // free the node + Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); + Ivy_ManRecycleMemory( p, pObj ); + } + // return the number of nodes freed + RetValue = Vec_PtrSize(vNodes); + Vec_PtrFree( vNodes ); +//printf( "Sequential sweep cleaned out %d nodes.\n", RetValue ); + return RetValue; +} + + +/**Function************************************************************* + + Synopsis [Checks if latches form self-loop.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManLatchIsSelfFeed_rec( Ivy_Obj_t * pLatch, Ivy_Obj_t * pLatchRoot ) +{ + if ( !Ivy_ObjIsLatch(pLatch) && !Ivy_ObjIsBuf(pLatch) ) + return 0; + if ( pLatch == pLatchRoot ) + return 1; + return Ivy_ManLatchIsSelfFeed_rec( Ivy_ObjFanin0(pLatch), pLatchRoot ); +} + +/**Function************************************************************* + + Synopsis [Checks if latches form self-loop.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManLatchIsSelfFeed( Ivy_Obj_t * pLatch ) +{ + if ( !Ivy_ObjIsLatch(pLatch) ) + return 0; + return Ivy_ManLatchIsSelfFeed_rec( Ivy_ObjFanin0(pLatch), pLatch ); +} + + +/**Function************************************************************* + + Synopsis [Returns the number of dangling nodes removed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManPropagateBuffers( Ivy_Man_t * p, int fUpdateLevel ) +{ + Ivy_Obj_t * pNode; + int LimitFactor = 100; + int NodeBeg = Ivy_ManNodeNum(p); + int nSteps; + for ( nSteps = 0; Vec_PtrSize(p->vBufs) > 0; nSteps++ ) + { + pNode = (Ivy_Obj_t *)Vec_PtrEntryLast(p->vBufs); + while ( Ivy_ObjIsBuf(pNode) ) + pNode = Ivy_ObjReadFirstFanout( p, pNode ); + // check if this buffer should remain + if ( Ivy_ManLatchIsSelfFeed(pNode) ) + { + Vec_PtrPop(p->vBufs); + continue; + } +//printf( "Propagating buffer %d with input %d and output %d\n", Ivy_ObjFaninId0(pNode), Ivy_ObjFaninId0(Ivy_ObjFanin0(pNode)), pNode->Id ); +//printf( "Latch num %d\n", Ivy_ManLatchNum(p) ); + Ivy_NodeFixBufferFanins( p, pNode, fUpdateLevel ); + if ( nSteps > NodeBeg * LimitFactor ) + { + printf( "Structural hashing is not finished after %d forward latch moves.\n", NodeBeg * LimitFactor ); + printf( "This circuit cannot be forward-retimed completely. Quitting.\n" ); + break; + } + } +// printf( "Number of steps = %d. Nodes beg = %d. Nodes end = %d.\n", nSteps, NodeBeg, Ivy_ManNodeNum(p) ); + return nSteps; +} + +/**Function************************************************************* + + Synopsis [Stops the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManPrintStats( Ivy_Man_t * p ) +{ + printf( "PI/PO = %d/%d ", Ivy_ManPiNum(p), Ivy_ManPoNum(p) ); + printf( "A = %7d. ", Ivy_ManAndNum(p) ); + printf( "L = %5d. ", Ivy_ManLatchNum(p) ); +// printf( "X = %d. ", Ivy_ManExorNum(p) ); +// printf( "B = %3d. ", Ivy_ManBufNum(p) ); + printf( "MaxID = %7d. ", Ivy_ManObjIdMax(p) ); +// printf( "Cre = %d. ", p->nCreated ); +// printf( "Del = %d. ", p->nDeleted ); + printf( "Lev = %3d. ", Ivy_ManLatchNum(p)? -1 : Ivy_ManLevels(p) ); + printf( "\n" ); + fflush( stdout ); +} + +/**Function************************************************************* + + Synopsis [Converts a combinational AIG manager into a sequential one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManMakeSeq( Ivy_Man_t * p, int nLatches, int * pInits ) +{ + Ivy_Obj_t * pObj, * pLatch; + Ivy_Init_t Init; + int i; + if ( nLatches == 0 ) + return; + assert( nLatches < Ivy_ManPiNum(p) && nLatches < Ivy_ManPoNum(p) ); + assert( Ivy_ManPiNum(p) == Vec_PtrSize(p->vPis) ); + assert( Ivy_ManPoNum(p) == Vec_PtrSize(p->vPos) ); + assert( Vec_PtrSize( p->vBufs ) == 0 ); + // create fanouts + if ( p->fFanout == 0 ) + Ivy_ManStartFanout( p ); + // collect the POs to be converted into latches + for ( i = 0; i < nLatches; i++ ) + { + // get the latch value + Init = pInits? (Ivy_Init_t)pInits[i] : IVY_INIT_0; + // create latch + pObj = Ivy_ManPo( p, Ivy_ManPoNum(p) - nLatches + i ); + pLatch = Ivy_Latch( p, Ivy_ObjChild0(pObj), Init ); + Ivy_ObjDisconnect( p, pObj ); + // recycle the old PO object + Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); + Ivy_ManRecycleMemory( p, pObj ); + // convert the corresponding PI to a buffer and connect it to the latch + pObj = Ivy_ManPi( p, Ivy_ManPiNum(p) - nLatches + i ); + pObj->Type = IVY_BUF; + Ivy_ObjConnect( p, pObj, pLatch, NULL ); + // save the buffer + Vec_PtrPush( p->vBufs, pObj ); + } + // shrink the arrays + Vec_PtrShrink( p->vPis, Ivy_ManPiNum(p) - nLatches ); + Vec_PtrShrink( p->vPos, Ivy_ManPoNum(p) - nLatches ); + // update the counters of different objects + p->nObjs[IVY_PI] -= nLatches; + p->nObjs[IVY_PO] -= nLatches; + p->nObjs[IVY_BUF] += nLatches; + p->nDeleted -= 2 * nLatches; + // remove dangling nodes + Ivy_ManCleanup(p); + Ivy_ManCleanupSeq(p); +/* + // check for dangling nodes + Ivy_ManForEachObj( p, pObj, i ) + if ( !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsPo(pObj) && !Ivy_ObjIsConst1(pObj) ) + { + assert( Ivy_ObjRefs(pObj) > 0 ); + assert( Ivy_ObjRefs(pObj) == Ivy_ObjFanoutNum(p, pObj) ); + } +*/ + // perform hashing by propagating the buffers + Ivy_ManPropagateBuffers( p, 0 ); + if ( Ivy_ManBufNum(p) ) + printf( "The number of remaining buffers is %d.\n", Ivy_ManBufNum(p) ); + // fix the levels + Ivy_ManResetLevels( p ); + // check the resulting network + if ( !Ivy_ManCheck(p) ) + printf( "Ivy_ManMakeSeq(): The check has failed.\n" ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/ivyMem.c b/yosys/abc/src/aig/ivy/ivyMem.c new file mode 100644 index 00000000000..d5e6e545bb4 --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivyMem.c @@ -0,0 +1,121 @@ +/**CFile**************************************************************** + + FileName [ivyMem.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Memory management for the AIG nodes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyMem.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// memory management +#define IVY_PAGE_SIZE 12 // page size containing 2^IVY_PAGE_SIZE nodes +#define IVY_PAGE_MASK 4095 // page bitmask (2^IVY_PAGE_SIZE)-1 + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the internal memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManStartMemory( Ivy_Man_t * p ) +{ + p->vChunks = Vec_PtrAlloc( 128 ); + p->vPages = Vec_PtrAlloc( 128 ); +} + +/**Function************************************************************* + + Synopsis [Stops the internal memory manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManStopMemory( Ivy_Man_t * p ) +{ + void * pMemory; + int i; + Vec_PtrForEachEntry( void *, p->vChunks, pMemory, i ) + ABC_FREE( pMemory ); + Vec_PtrFree( p->vChunks ); + Vec_PtrFree( p->vPages ); + p->pListFree = NULL; +} + +/**Function************************************************************* + + Synopsis [Allocates additional memory for the nodes.] + + Description [Allocates IVY_PAGE_SIZE nodes. Aligns memory by 32 bytes. + Records the pointer to the AIG manager in the -1 entry.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManAddMemory( Ivy_Man_t * p ) +{ + char * pMemory; + int i, nBytes; + int EntrySizeMax = 128; + assert( sizeof(Ivy_Obj_t) <= EntrySizeMax ); + assert( p->pListFree == NULL ); +// assert( (Ivy_ManObjNum(p) & IVY_PAGE_MASK) == 0 ); + // allocate new memory page + nBytes = sizeof(Ivy_Obj_t) * (1<vChunks, pMemory ); + // align memory at the 32-byte boundary + pMemory = pMemory + EntrySizeMax - (((int)(ABC_PTRUINT_T)pMemory) & (EntrySizeMax-1)); + // remember the manager in the first entry + Vec_PtrPush( p->vPages, pMemory ); + // break the memory down into nodes + p->pListFree = (Ivy_Obj_t *)pMemory; + for ( i = 1; i <= IVY_PAGE_MASK; i++ ) + { + *((char **)pMemory) = pMemory + sizeof(Ivy_Obj_t); + pMemory += sizeof(Ivy_Obj_t); + } + *((char **)pMemory) = NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/ivyMulti.c b/yosys/abc/src/aig/ivy/ivyMulti.c new file mode 100644 index 00000000000..c137a65902d --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivyMulti.c @@ -0,0 +1,312 @@ +/**CFile**************************************************************** + + FileName [ivyMulti.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Constructing multi-input AND/EXOR gates.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyMulti.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define IVY_EVAL_LIMIT 128 + +typedef struct Ivy_Eva_t_ Ivy_Eva_t; +struct Ivy_Eva_t_ +{ + Ivy_Obj_t * pArg; // the argument node + unsigned Mask; // the mask of covered nodes + int Weight; // the number of covered nodes +}; + +static void Ivy_MultiPrint( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals ); +static int Ivy_MultiCover( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals, int nLimit, Vec_Ptr_t * vSols ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Constructs a balanced tree while taking sharing into account.] + + Description [Returns 1 if the implementation exists.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_MultiPlus( Ivy_Man_t * p, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Ivy_Type_t Type, int nLimit, Vec_Ptr_t * vSols ) +{ + static Ivy_Eva_t pEvals[IVY_EVAL_LIMIT]; + Ivy_Eva_t * pEval, * pFan0, * pFan1; + Ivy_Obj_t * pObj = NULL; // Suppress "might be used uninitialized" + Ivy_Obj_t * pTemp; + int nEvals, nEvalsOld, i, k, x, nLeaves; + unsigned uMaskAll; + + // consider special cases + nLeaves = Vec_PtrSize(vLeaves); + assert( nLeaves > 2 ); + if ( nLeaves > 32 || nLeaves + Vec_PtrSize(vCone) > IVY_EVAL_LIMIT ) + return 0; +// if ( nLeaves == 1 ) +// return Vec_PtrEntry( vLeaves, 0 ); +// if ( nLeaves == 2 ) +// return Ivy_Oper( Vec_PtrEntry(vLeaves, 0), Vec_PtrEntry(vLeaves, 1), Type ); + + // set the leaf entries + uMaskAll = ((1 << nLeaves) - 1); + nEvals = 0; + Vec_PtrForEachEntry( Ivy_Obj_t *, vLeaves, pObj, i ) + { + pEval = pEvals + nEvals; + pEval->pArg = pObj; + pEval->Mask = (1 << nEvals); + pEval->Weight = 1; + // mark the leaf + Ivy_Regular(pObj)->TravId = nEvals; + nEvals++; + } + + // propagate masks through the cone + Vec_PtrForEachEntry( Ivy_Obj_t *, vCone, pObj, i ) + { + pObj->TravId = nEvals + i; + if ( Ivy_ObjIsBuf(pObj) ) + pEvals[pObj->TravId].Mask = pEvals[Ivy_ObjFanin0(pObj)->TravId].Mask; + else + pEvals[pObj->TravId].Mask = pEvals[Ivy_ObjFanin0(pObj)->TravId].Mask | pEvals[Ivy_ObjFanin1(pObj)->TravId].Mask; + } + + // set the internal entries + Vec_PtrForEachEntry( Ivy_Obj_t *, vCone, pObj, i ) + { + if ( i == Vec_PtrSize(vCone) - 1 ) + break; + // skip buffers + if ( Ivy_ObjIsBuf(pObj) ) + continue; + // skip nodes without external fanout + if ( Ivy_ObjRefs(pObj) == 0 ) + continue; + assert( !Ivy_IsComplement(pObj) ); + pEval = pEvals + nEvals; + pEval->pArg = pObj; + pEval->Mask = pEvals[pObj->TravId].Mask; + pEval->Weight = Extra_WordCountOnes(pEval->Mask); + // mark the node + pObj->TravId = nEvals; + nEvals++; + } + + // find the available nodes + nEvalsOld = nEvals; + for ( i = 1; i < nEvals; i++ ) + for ( k = 0; k < i; k++ ) + { + pFan0 = pEvals + i; + pFan1 = pEvals + k; + pTemp = Ivy_TableLookup(p, Ivy_ObjCreateGhost(p, pFan0->pArg, pFan1->pArg, Type, IVY_INIT_NONE)); + // skip nodes in the cone + if ( pTemp == NULL || pTemp->fMarkB ) + continue; + // skip the leaves + for ( x = 0; x < nLeaves; x++ ) + if ( pTemp == Ivy_Regular((Ivy_Obj_t *)vLeaves->pArray[x]) ) + break; + if ( x < nLeaves ) + continue; + pEval = pEvals + nEvals; + pEval->pArg = pTemp; + pEval->Mask = pFan0->Mask | pFan1->Mask; + pEval->Weight = (pFan0->Mask & pFan1->Mask) ? Extra_WordCountOnes(pEval->Mask) : pFan0->Weight + pFan1->Weight; + // save the argument + pObj->TravId = nEvals; + nEvals++; + // quit if the number of entries exceeded the limit + if ( nEvals == IVY_EVAL_LIMIT ) + goto Outside; + // quit if we found an acceptable implementation + if ( pEval->Mask == uMaskAll ) + goto Outside; + } +Outside: + +// Ivy_MultiPrint( pEvals, nLeaves, nEvals ); + if ( !Ivy_MultiCover( p, pEvals, nLeaves, nEvals, nLimit, vSols ) ) + return 0; + assert( Vec_PtrSize( vSols ) > 0 ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes how many uncovered ones this one covers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_MultiPrint( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals ) +{ + Ivy_Eva_t * pEval; + int i, k; + for ( i = nLeaves; i < nEvals; i++ ) + { + pEval = pEvals + i; + printf( "%2d (id = %5d) : |", i-nLeaves, Ivy_ObjId(pEval->pArg) ); + for ( k = 0; k < nLeaves; k++ ) + { + if ( pEval->Mask & (1 << k) ) + printf( "+" ); + else + printf( " " ); + } + printf( "| Lev = %d.\n", Ivy_ObjLevel(pEval->pArg) ); + } +} + +/**Function************************************************************* + + Synopsis [Computes how many uncovered ones this one covers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_MultiWeight( unsigned uMask, int nMaskOnes, unsigned uFound ) +{ + assert( uMask & ~uFound ); + if ( (uMask & uFound) == 0 ) + return nMaskOnes; + return Extra_WordCountOnes( uMask & ~uFound ); +} + +/**Function************************************************************* + + Synopsis [Finds the cover.] + + Description [Returns 1 if the cover is found.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_MultiCover( Ivy_Man_t * p, Ivy_Eva_t * pEvals, int nLeaves, int nEvals, int nLimit, Vec_Ptr_t * vSols ) +{ + int fVerbose = 0; + Ivy_Eva_t * pEval; + Ivy_Eva_t * pEvalBest = NULL; // Suppress "might be used uninitialized" + unsigned uMaskAll, uFound, uTemp; + int i, k, BestK; + int WeightBest = -1; // Suppress "might be used uninitialized" + int WeightCur; + int LevelBest = -1; // Suppress "might be used uninitialized" + int LevelCur; + uMaskAll = (nLeaves == 32)? (~(unsigned)0) : ((1 << nLeaves) - 1); + uFound = 0; + // solve the covering problem + if ( fVerbose ) + printf( "Solution: " ); + Vec_PtrClear( vSols ); + for ( i = 0; i < nLimit; i++ ) + { + BestK = -1; + for ( k = nEvals - 1; k >= 0; k-- ) + { + pEval = pEvals + k; + if ( (pEval->Mask & ~uFound) == 0 ) + continue; + if ( BestK == -1 ) + { + BestK = k; + pEvalBest = pEval; + WeightBest = Ivy_MultiWeight( pEvalBest->Mask, pEvalBest->Weight, uFound ); + LevelBest = Ivy_ObjLevel( Ivy_Regular(pEvalBest->pArg) ); + continue; + } + // compare BestK and the new one (k) + WeightCur = Ivy_MultiWeight( pEval->Mask, pEval->Weight, uFound ); + LevelCur = Ivy_ObjLevel( Ivy_Regular(pEval->pArg) ); + if ( WeightBest < WeightCur || + (WeightBest == WeightCur && LevelBest > LevelCur) ) + { + BestK = k; + pEvalBest = pEval; + WeightBest = WeightCur; + LevelBest = LevelCur; + } + } + assert( BestK != -1 ); + // if the cost is only 1, take the leaf + if ( WeightBest == 1 && BestK >= nLeaves ) + { + uTemp = (pEvalBest->Mask & ~uFound); + for ( k = 0; k < nLeaves; k++ ) + if ( uTemp & (1 << k) ) + break; + assert( k < nLeaves ); + BestK = k; + pEvalBest = pEvals + BestK; + } + if ( fVerbose ) + { + if ( BestK < nLeaves ) + printf( "L(%d) ", BestK ); + else + printf( "%d ", BestK - nLeaves ); + } + // update the found set + Vec_PtrPush( vSols, pEvalBest->pArg ); + uFound |= pEvalBest->Mask; + if ( uFound == uMaskAll ) + break; + } + if ( uFound == uMaskAll ) + { + if ( fVerbose ) + printf( " Found \n\n" ); + return 1; + } + else + { + if ( fVerbose ) + printf( " Not found \n\n" ); + return 0; + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/ivyMulti8.c b/yosys/abc/src/aig/ivy/ivyMulti8.c new file mode 100644 index 00000000000..23af0e387aa --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivyMulti8.c @@ -0,0 +1,432 @@ +/**CFile**************************************************************** + + FileName [ivyMulti.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Constructing multi-input AND/EXOR gates.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyMulti.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Ivy_Eval_t_ Ivy_Eval_t; +struct Ivy_Eval_t_ +{ + unsigned Mask : 5; // the mask of covered nodes + unsigned Weight : 3; // the number of covered nodes + unsigned Cost : 4; // the number of overlapping nodes + unsigned Level : 12; // the level of this node + unsigned Fan0 : 4; // the first fanin + unsigned Fan1 : 4; // the second fanin +}; + +static Ivy_Obj_t * Ivy_MultiBuild_rec( Ivy_Eval_t * pEvals, int iNum, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); +static void Ivy_MultiSort( Ivy_Obj_t ** pArgs, int nArgs ); +static int Ivy_MultiPushUniqueOrderByLevel( Ivy_Obj_t ** pArray, int nArgs, Ivy_Obj_t * pNode ); +static Ivy_Obj_t * Ivy_MultiEval( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ); + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Constructs the well-balanced tree of gates.] + + Description [Disregards levels and possible logic sharing.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Multi_rec( Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type ) +{ + Ivy_Obj_t * pObj1, * pObj2; + if ( nObjs == 1 ) + return ppObjs[0]; + pObj1 = Ivy_Multi_rec( ppObjs, nObjs/2, Type ); + pObj2 = Ivy_Multi_rec( ppObjs + nObjs/2, nObjs - nObjs/2, Type ); + return Ivy_Oper( pObj1, pObj2, Type ); +} + +/**Function************************************************************* + + Synopsis [Constructs a balanced tree while taking sharing into account.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Multi( Ivy_Obj_t ** pArgsInit, int nArgs, Ivy_Type_t Type ) +{ + static char NumBits[32] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5}; + static Ivy_Eval_t pEvals[15+15*14/2]; + static Ivy_Obj_t * pArgs[16]; + Ivy_Eval_t * pEva, * pEvaBest; + int nArgsNew, nEvals, i, k; + Ivy_Obj_t * pTemp; + + // consider the case of one argument + assert( nArgs > 0 ); + if ( nArgs == 1 ) + return pArgsInit[0]; + // consider the case of two arguments + if ( nArgs == 2 ) + return Ivy_Oper( pArgsInit[0], pArgsInit[1], Type ); + +//Ivy_MultiEval( pArgsInit, nArgs, Type ); printf( "\n" ); + + // set the initial ones + for ( i = 0; i < nArgs; i++ ) + { + pArgs[i] = pArgsInit[i]; + pEva = pEvals + i; + pEva->Mask = (1 << i); + pEva->Weight = 1; + pEva->Cost = 0; + pEva->Level = Ivy_Regular(pArgs[i])->Level; + pEva->Fan0 = 0; + pEva->Fan1 = 0; + } + + // find the available nodes + pEvaBest = pEvals; + nArgsNew = nArgs; + for ( i = 1; i < nArgsNew; i++ ) + for ( k = 0; k < i; k++ ) + if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgs[k], pArgs[i], Type, IVY_INIT_NONE)) ) + { + pEva = pEvals + nArgsNew; + pEva->Mask = pEvals[k].Mask | pEvals[i].Mask; + pEva->Weight = NumBits[pEva->Mask]; + pEva->Cost = pEvals[k].Cost + pEvals[i].Cost + NumBits[pEvals[k].Mask & pEvals[i].Mask]; + pEva->Level = 1 + IVY_MAX(pEvals[k].Level, pEvals[i].Level); + pEva->Fan0 = k; + pEva->Fan1 = i; +// assert( pEva->Level == (unsigned)Ivy_ObjLevel(pTemp) ); + // compare + if ( pEvaBest->Weight < pEva->Weight || + pEvaBest->Weight == pEva->Weight && pEvaBest->Cost > pEva->Cost || + pEvaBest->Weight == pEva->Weight && pEvaBest->Cost == pEva->Cost && pEvaBest->Level > pEva->Level ) + pEvaBest = pEva; + // save the argument + pArgs[nArgsNew++] = pTemp; + if ( nArgsNew == 15 ) + goto Outside; + } +Outside: + +// printf( "Best = %d.\n", pEvaBest - pEvals ); + + // the case of no common nodes + if ( nArgsNew == nArgs ) + { + Ivy_MultiSort( pArgs, nArgs ); + return Ivy_MultiBalance_rec( pArgs, nArgs, Type ); + } + // the case of one common node + if ( nArgsNew == nArgs + 1 ) + { + assert( pEvaBest - pEvals == nArgs ); + k = 0; + for ( i = 0; i < nArgs; i++ ) + if ( i != (int)pEvaBest->Fan0 && i != (int)pEvaBest->Fan1 ) + pArgs[k++] = pArgs[i]; + pArgs[k++] = pArgs[nArgs]; + assert( k == nArgs - 1 ); + nArgs = k; + Ivy_MultiSort( pArgs, nArgs ); + return Ivy_MultiBalance_rec( pArgs, nArgs, Type ); + } + // the case when there is a node that covers everything + if ( (int)pEvaBest->Mask == ((1 << nArgs) - 1) ) + return Ivy_MultiBuild_rec( pEvals, pEvaBest - pEvals, pArgs, nArgsNew, Type ); + + // evaluate node pairs + nEvals = nArgsNew; + for ( i = 1; i < nArgsNew; i++ ) + for ( k = 0; k < i; k++ ) + { + pEva = pEvals + nEvals; + pEva->Mask = pEvals[k].Mask | pEvals[i].Mask; + pEva->Weight = NumBits[pEva->Mask]; + pEva->Cost = pEvals[k].Cost + pEvals[i].Cost + NumBits[pEvals[k].Mask & pEvals[i].Mask]; + pEva->Level = 1 + IVY_MAX(pEvals[k].Level, pEvals[i].Level); + pEva->Fan0 = k; + pEva->Fan1 = i; + // compare + if ( pEvaBest->Weight < pEva->Weight || + pEvaBest->Weight == pEva->Weight && pEvaBest->Cost > pEva->Cost || + pEvaBest->Weight == pEva->Weight && pEvaBest->Cost == pEva->Cost && pEvaBest->Level > pEva->Level ) + pEvaBest = pEva; + // save the argument + nEvals++; + } + assert( pEvaBest - pEvals >= nArgsNew ); + +// printf( "Used (%d, %d).\n", pEvaBest->Fan0, pEvaBest->Fan1 ); + + // get the best implementation + pTemp = Ivy_MultiBuild_rec( pEvals, pEvaBest - pEvals, pArgs, nArgsNew, Type ); + + // collect those not covered by EvaBest + k = 0; + for ( i = 0; i < nArgs; i++ ) + if ( (pEvaBest->Mask & (1 << i)) == 0 ) + pArgs[k++] = pArgs[i]; + pArgs[k++] = pTemp; + assert( k == nArgs - (int)pEvaBest->Weight + 1 ); + nArgs = k; + Ivy_MultiSort( pArgs, nArgs ); + return Ivy_MultiBalance_rec( pArgs, nArgs, Type ); +} + +/**Function************************************************************* + + Synopsis [Implements multi-input AND/EXOR operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_MultiBuild_rec( Ivy_Eval_t * pEvals, int iNum, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) +{ + Ivy_Obj_t * pNode0, * pNode1; + if ( iNum < nArgs ) + return pArgs[iNum]; + pNode0 = Ivy_MultiBuild_rec( pEvals, pEvals[iNum].Fan0, pArgs, nArgs, Type ); + pNode1 = Ivy_MultiBuild_rec( pEvals, pEvals[iNum].Fan1, pArgs, nArgs, Type ); + return Ivy_Oper( pNode0, pNode1, Type ); +} + +/**Function************************************************************* + + Synopsis [Selection-sorts the nodes in the decreasing over of level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_MultiSort( Ivy_Obj_t ** pArgs, int nArgs ) +{ + Ivy_Obj_t * pTemp; + int i, j, iBest; + + for ( i = 0; i < nArgs-1; i++ ) + { + iBest = i; + for ( j = i+1; j < nArgs; j++ ) + if ( Ivy_Regular(pArgs[j])->Level > Ivy_Regular(pArgs[iBest])->Level ) + iBest = j; + pTemp = pArgs[i]; + pArgs[i] = pArgs[iBest]; + pArgs[iBest] = pTemp; + } +} + +/**Function************************************************************* + + Synopsis [Inserts a new node in the order by levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_MultiPushUniqueOrderByLevel( Ivy_Obj_t ** pArray, int nArgs, Ivy_Obj_t * pNode ) +{ + Ivy_Obj_t * pNode1, * pNode2; + int i; + // try to find the node in the array + for ( i = 0; i < nArgs; i++ ) + if ( pArray[i] == pNode ) + return nArgs; + // put the node last + pArray[nArgs++] = pNode; + // find the place to put the new node + for ( i = nArgs-1; i > 0; i-- ) + { + pNode1 = pArray[i ]; + pNode2 = pArray[i-1]; + if ( Ivy_Regular(pNode1)->Level <= Ivy_Regular(pNode2)->Level ) + break; + pArray[i ] = pNode2; + pArray[i-1] = pNode1; + } + return nArgs; +} + +/**Function************************************************************* + + Synopsis [Balances the array recursively.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_MultiBalance_rec( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) +{ + Ivy_Obj_t * pNodeNew; + // consider the case of one argument + assert( nArgs > 0 ); + if ( nArgs == 1 ) + return pArgs[0]; + // consider the case of two arguments + if ( nArgs == 2 ) + return Ivy_Oper( pArgs[0], pArgs[1], Type ); + // get the last two nodes + pNodeNew = Ivy_Oper( pArgs[nArgs-1], pArgs[nArgs-2], Type ); + // add the new node + nArgs = Ivy_MultiPushUniqueOrderByLevel( pArgs, nArgs - 2, pNodeNew ); + return Ivy_MultiBalance_rec( pArgs, nArgs, Type ); +} + +/**Function************************************************************* + + Synopsis [Implements multi-input AND/EXOR operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_MultiEval( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) +{ + Ivy_Obj_t * pTemp; + int i, k; + int nArgsOld = nArgs; + for ( i = 0; i < nArgs; i++ ) + printf( "%d[%d] ", i, Ivy_Regular(pArgs[i])->Level ); + for ( i = 1; i < nArgs; i++ ) + for ( k = 0; k < i; k++ ) + { + pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgs[k], pArgs[i], Type, IVY_INIT_NONE)); + if ( pTemp != NULL ) + { + printf( "%d[%d]=(%d,%d) ", nArgs, Ivy_Regular(pTemp)->Level, k, i ); + pArgs[nArgs++] = pTemp; + } + } + printf( " ((%d/%d)) ", nArgsOld, nArgs-nArgsOld ); + return NULL; +} + + + +/**Function************************************************************* + + Synopsis [Old code.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Multi1( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) +{ + Ivy_Obj_t * pArgsRef[5], * pTemp; + int i, k, m, nArgsNew, Counter = 0; + + +//Ivy_MultiEval( pArgs, nArgs, Type ); printf( "\n" ); + + + assert( Type == IVY_AND || Type == IVY_EXOR ); + assert( nArgs > 0 ); + if ( nArgs == 1 ) + return pArgs[0]; + + // find the nodes with more than one fanout + nArgsNew = 0; + for ( i = 0; i < nArgs; i++ ) + if ( Ivy_ObjRefs( Ivy_Regular(pArgs[i]) ) > 0 ) + pArgsRef[nArgsNew++] = pArgs[i]; + + // go through pairs + if ( nArgsNew >= 2 ) + for ( i = 0; i < nArgsNew; i++ ) + for ( k = i + 1; k < nArgsNew; k++ ) + if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgsRef[i], pArgsRef[k], Type, IVY_INIT_NONE)) ) + Counter++; +// printf( "%d", Counter ); + + // go through pairs + if ( nArgsNew >= 2 ) + for ( i = 0; i < nArgsNew; i++ ) + for ( k = i + 1; k < nArgsNew; k++ ) + if ( pTemp = Ivy_TableLookup(Ivy_ObjCreateGhost(pArgsRef[i], pArgsRef[k], Type, IVY_INIT_NONE)) ) + { + nArgsNew = 0; + for ( m = 0; m < nArgs; m++ ) + if ( pArgs[m] != pArgsRef[i] && pArgs[m] != pArgsRef[k] ) + pArgs[nArgsNew++] = pArgs[m]; + pArgs[nArgsNew++] = pTemp; + assert( nArgsNew == nArgs - 1 ); + return Ivy_Multi1( pArgs, nArgsNew, Type ); + } + return Ivy_Multi_rec( pArgs, nArgs, Type ); +} + +/**Function************************************************************* + + Synopsis [Old code.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Multi2( Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) +{ + assert( Type == IVY_AND || Type == IVY_EXOR ); + assert( nArgs > 0 ); + return Ivy_Multi_rec( pArgs, nArgs, Type ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/ivyObj.c b/yosys/abc/src/aig/ivy/ivyObj.c new file mode 100644 index 00000000000..527f4daff9a --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivyObj.c @@ -0,0 +1,481 @@ +/**CFile**************************************************************** + + FileName [ivyObj.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Adding/removing objects.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyObj.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Create the new node assuming it does not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_ObjCreatePi( Ivy_Man_t * p ) +{ + return Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, NULL, NULL, IVY_PI, IVY_INIT_NONE) ); +} + +/**Function************************************************************* + + Synopsis [Create the new node assuming it does not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_ObjCreatePo( Ivy_Man_t * p, Ivy_Obj_t * pDriver ) +{ + return Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, pDriver, NULL, IVY_PO, IVY_INIT_NONE) ); +} + +/**Function************************************************************* + + Synopsis [Create the new node assuming it does not exist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_ObjCreate( Ivy_Man_t * p, Ivy_Obj_t * pGhost ) +{ + Ivy_Obj_t * pObj; + assert( !Ivy_IsComplement(pGhost) ); + assert( Ivy_ObjIsGhost(pGhost) ); + assert( Ivy_TableLookup(p, pGhost) == NULL ); + // get memory for the new object + pObj = Ivy_ManFetchMemory( p ); + assert( Ivy_ObjIsNone(pObj) ); + pObj->Id = Vec_PtrSize(p->vObjs); + Vec_PtrPush( p->vObjs, pObj ); + // add basic info (fanins, compls, type, init) + pObj->Type = pGhost->Type; + pObj->Init = pGhost->Init; + // add connections + Ivy_ObjConnect( p, pObj, pGhost->pFanin0, pGhost->pFanin1 ); + // compute level + if ( Ivy_ObjIsNode(pObj) ) + pObj->Level = Ivy_ObjLevelNew(pObj); + else if ( Ivy_ObjIsLatch(pObj) ) + pObj->Level = 0; + else if ( Ivy_ObjIsOneFanin(pObj) ) + pObj->Level = Ivy_ObjFanin0(pObj)->Level; + else if ( !Ivy_ObjIsPi(pObj) ) + assert( 0 ); + // create phase + if ( Ivy_ObjIsNode(pObj) ) + pObj->fPhase = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)) & Ivy_ObjFaninPhase(Ivy_ObjChild1(pObj)); + else if ( Ivy_ObjIsOneFanin(pObj) ) + pObj->fPhase = Ivy_ObjFaninPhase(Ivy_ObjChild0(pObj)); + // set the fail TFO flag + if ( Ivy_ObjIsNode(pObj) ) + pObj->fFailTfo = Ivy_ObjFanin0(pObj)->fFailTfo | Ivy_ObjFanin1(pObj)->fFailTfo; + // mark the fanins in a special way if the node is EXOR + if ( Ivy_ObjIsExor(pObj) ) + { + Ivy_ObjFanin0(pObj)->fExFan = 1; + Ivy_ObjFanin1(pObj)->fExFan = 1; + } + // add PIs/POs to the arrays + if ( Ivy_ObjIsPi(pObj) ) + Vec_PtrPush( p->vPis, pObj ); + else if ( Ivy_ObjIsPo(pObj) ) + Vec_PtrPush( p->vPos, pObj ); +// else if ( Ivy_ObjIsBuf(pObj) ) +// Vec_PtrPush( p->vBufs, pObj ); + if ( p->vRequired && Vec_IntSize(p->vRequired) <= pObj->Id ) + Vec_IntFillExtra( p->vRequired, 2 * Vec_IntSize(p->vRequired), 1000000 ); + // update node counters of the manager + p->nObjs[Ivy_ObjType(pObj)]++; + p->nCreated++; + +// printf( "Adding %sAIG node: ", p->pHaig==NULL? "H":" " ); +// Ivy_ObjPrintVerbose( p, pObj, p->pHaig==NULL ); +// printf( "\n" ); + + // if HAIG is defined, create a corresponding node + if ( p->pHaig ) + Ivy_ManHaigCreateObj( p, pObj ); + return pObj; +} + +/**Function************************************************************* + + Synopsis [Connect the object to the fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjConnect( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFan0, Ivy_Obj_t * pFan1 ) +{ + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjIsPi(pObj) || Ivy_ObjIsOneFanin(pObj) || pFan1 != NULL ); + // add the first fanin + pObj->pFanin0 = pFan0; + pObj->pFanin1 = pFan1; + // increment references of the fanins and add their fanouts + if ( Ivy_ObjFanin0(pObj) != NULL ) + { + Ivy_ObjRefsInc( Ivy_ObjFanin0(pObj) ); + if ( p->fFanout ) + Ivy_ObjAddFanout( p, Ivy_ObjFanin0(pObj), pObj ); + } + if ( Ivy_ObjFanin1(pObj) != NULL ) + { + Ivy_ObjRefsInc( Ivy_ObjFanin1(pObj) ); + if ( p->fFanout ) + Ivy_ObjAddFanout( p, Ivy_ObjFanin1(pObj), pObj ); + } + // add the node to the structural hash table + Ivy_TableInsert( p, pObj ); +} + +/**Function************************************************************* + + Synopsis [Connect the object to the fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjDisconnect( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjIsPi(pObj) || Ivy_ObjIsOneFanin(pObj) || Ivy_ObjFanin1(pObj) != NULL ); + // remove connections + if ( pObj->pFanin0 != NULL ) + { + Ivy_ObjRefsDec(Ivy_ObjFanin0(pObj)); + if ( p->fFanout ) + Ivy_ObjDeleteFanout( p, Ivy_ObjFanin0(pObj), pObj ); + } + if ( pObj->pFanin1 != NULL ) + { + Ivy_ObjRefsDec(Ivy_ObjFanin1(pObj)); + if ( p->fFanout ) + Ivy_ObjDeleteFanout( p, Ivy_ObjFanin1(pObj), pObj ); + } + assert( pObj->pNextFan0 == NULL ); + assert( pObj->pNextFan1 == NULL ); + assert( pObj->pPrevFan0 == NULL ); + assert( pObj->pPrevFan1 == NULL ); + // remove the node from the structural hash table + Ivy_TableDelete( p, pObj ); + // add the first fanin + pObj->pFanin0 = NULL; + pObj->pFanin1 = NULL; +} + +/**Function************************************************************* + + Synopsis [Replaces the first fanin of the node by the new fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjPatchFanin0( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Obj_t * pFaninNew ) +{ + Ivy_Obj_t * pFaninOld; + assert( !Ivy_IsComplement(pObj) ); + pFaninOld = Ivy_ObjFanin0(pObj); + // decrement ref and remove fanout + Ivy_ObjRefsDec( pFaninOld ); + if ( p->fFanout ) + Ivy_ObjDeleteFanout( p, pFaninOld, pObj ); + // update the fanin + pObj->pFanin0 = pFaninNew; + // increment ref and add fanout + Ivy_ObjRefsInc( Ivy_Regular(pFaninNew) ); + if ( p->fFanout ) + Ivy_ObjAddFanout( p, Ivy_Regular(pFaninNew), pObj ); + // get rid of old fanin + if ( !Ivy_ObjIsPi(pFaninOld) && !Ivy_ObjIsConst1(pFaninOld) && Ivy_ObjRefs(pFaninOld) == 0 ) + Ivy_ObjDelete_rec( p, pFaninOld, 1 ); +} + +/**Function************************************************************* + + Synopsis [Deletes the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ) +{ + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjRefs(pObj) == 0 || !fFreeTop ); + // update node counters of the manager + p->nObjs[pObj->Type]--; + p->nDeleted++; + // remove connections + Ivy_ObjDisconnect( p, pObj ); + // remove PIs/POs from the arrays + if ( Ivy_ObjIsPi(pObj) ) + Vec_PtrRemove( p->vPis, pObj ); + else if ( Ivy_ObjIsPo(pObj) ) + Vec_PtrRemove( p->vPos, pObj ); + else if ( p->fFanout && Ivy_ObjIsBuf(pObj) ) + Vec_PtrRemove( p->vBufs, pObj ); + // clean and recycle the entry + if ( fFreeTop ) + { + // free the node + Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL ); + Ivy_ManRecycleMemory( p, pObj ); + } + else + { + int nRefsOld = pObj->nRefs; + Ivy_Obj_t * pFanout = pObj->pFanout; + Ivy_ObjClean( pObj ); + pObj->pFanout = pFanout; + pObj->nRefs = nRefsOld; + } +} + +/**Function************************************************************* + + Synopsis [Deletes the MFFC of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjDelete_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fFreeTop ) +{ + Ivy_Obj_t * pFanin0, * pFanin1; + assert( !Ivy_IsComplement(pObj) ); + assert( !Ivy_ObjIsNone(pObj) ); + if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsPi(pObj) ) + return; + pFanin0 = Ivy_ObjFanin0(pObj); + pFanin1 = Ivy_ObjFanin1(pObj); + Ivy_ObjDelete( p, pObj, fFreeTop ); + if ( pFanin0 && !Ivy_ObjIsNone(pFanin0) && Ivy_ObjRefs(pFanin0) == 0 ) + Ivy_ObjDelete_rec( p, pFanin0, 1 ); + if ( pFanin1 && !Ivy_ObjIsNone(pFanin1) && Ivy_ObjRefs(pFanin1) == 0 ) + Ivy_ObjDelete_rec( p, pFanin1, 1 ); +} + +/**Function************************************************************* + + Synopsis [Replaces one object by another.] + + Description [Both objects are currently in the manager. The new object + (pObjNew) should be used instead of the old object (pObjOld). If the + new object is complemented or used, the buffer is added.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjReplace( Ivy_Man_t * p, Ivy_Obj_t * pObjOld, Ivy_Obj_t * pObjNew, int fDeleteOld, int fFreeTop, int fUpdateLevel ) +{ + int nRefsOld;//, clk; + // the object to be replaced cannot be complemented + assert( !Ivy_IsComplement(pObjOld) ); + // the object to be replaced cannot be a terminal + assert( Ivy_ObjIsNone(pObjOld) || !Ivy_ObjIsPi(pObjOld) ); + // the object to be used cannot be a PO or assert + assert( !Ivy_ObjIsBuf(Ivy_Regular(pObjNew)) ); + // the object cannot be the same + assert( pObjOld != Ivy_Regular(pObjNew) ); +//printf( "Replacing %d by %d.\n", Ivy_Regular(pObjOld)->Id, Ivy_Regular(pObjNew)->Id ); + + // if HAIG is defined, create the choice node + if ( p->pHaig ) + { +// if ( pObjOld->Id == 31 ) +// { +// Ivy_ManShow( p, 0 ); +// Ivy_ManShow( p->pHaig, 1 ); +// } + Ivy_ManHaigCreateChoice( p, pObjOld, pObjNew ); + } + // if the new object is complemented or already used, add the buffer + if ( Ivy_IsComplement(pObjNew) || Ivy_ObjIsLatch(pObjNew) || Ivy_ObjRefs(pObjNew) > 0 || Ivy_ObjIsPi(pObjNew) || Ivy_ObjIsConst1(pObjNew) ) + pObjNew = Ivy_ObjCreate( p, Ivy_ObjCreateGhost(p, pObjNew, NULL, IVY_BUF, IVY_INIT_NONE) ); + assert( !Ivy_IsComplement(pObjNew) ); + if ( fUpdateLevel ) + { +//clk = Abc_Clock(); + // if the new node's arrival time is different, recursively update arrival time of the fanouts + if ( p->fFanout && !Ivy_ObjIsBuf(pObjNew) && pObjOld->Level != pObjNew->Level ) + { + assert( Ivy_ObjIsNode(pObjOld) ); + pObjOld->Level = pObjNew->Level; + Ivy_ObjUpdateLevel_rec( p, pObjOld ); + } +//p->time1 += Abc_Clock() - clk; + // if the new node's required time has changed, recursively update required time of the fanins +//clk = Abc_Clock(); + if ( p->vRequired ) + { + int ReqNew = Vec_IntEntry(p->vRequired, pObjOld->Id); + if ( ReqNew < Vec_IntEntry(p->vRequired, pObjNew->Id) ) + { + Vec_IntWriteEntry( p->vRequired, pObjNew->Id, ReqNew ); + Ivy_ObjUpdateLevelR_rec( p, pObjNew, ReqNew ); + } + } +//p->time2 += Abc_Clock() - clk; + } + // delete the old object + if ( fDeleteOld ) + Ivy_ObjDelete_rec( p, pObjOld, fFreeTop ); + // make sure object is not pointing to itself + assert( Ivy_ObjFanin0(pObjNew) == NULL || pObjOld != Ivy_ObjFanin0(pObjNew) ); + assert( Ivy_ObjFanin1(pObjNew) == NULL || pObjOld != Ivy_ObjFanin1(pObjNew) ); + // make sure the old node has no fanin fanout pointers + if ( p->fFanout ) + { + assert( pObjOld->pFanout != NULL ); + assert( pObjNew->pFanout == NULL ); + pObjNew->pFanout = pObjOld->pFanout; + } + // transfer the old object + assert( Ivy_ObjRefs(pObjNew) == 0 ); + nRefsOld = pObjOld->nRefs; + Ivy_ObjOverwrite( pObjOld, pObjNew ); + pObjOld->nRefs = nRefsOld; + // patch the fanout of the fanins + if ( p->fFanout ) + { + Ivy_ObjPatchFanout( p, Ivy_ObjFanin0(pObjOld), pObjNew, pObjOld ); + if ( Ivy_ObjFanin1(pObjOld) ) + Ivy_ObjPatchFanout( p, Ivy_ObjFanin1(pObjOld), pObjNew, pObjOld ); + } + // update the hash table + Ivy_TableUpdate( p, pObjNew, pObjOld->Id ); + // recycle the object that was taken over by pObjOld + Vec_PtrWriteEntry( p->vObjs, pObjNew->Id, NULL ); + Ivy_ManRecycleMemory( p, pObjNew ); + // if the new node is the buffer propagate it + if ( p->fFanout && Ivy_ObjIsBuf(pObjOld) ) + Vec_PtrPush( p->vBufs, pObjOld ); +// Ivy_ManCheckFanouts( p ); +// printf( "\n" ); +/* + if ( p->pHaig ) + { + int x; + Ivy_ManShow( p, 0, NULL ); + Ivy_ManShow( p->pHaig, 1, NULL ); + x = 0; + } +*/ +// if ( Ivy_ManCheckFanoutNums(p) ) +// { +// int x = 0; +// } +} + +/**Function************************************************************* + + Synopsis [Fixes buffer fanins.] + + Description [This situation happens because NodeReplace is a lazy + procedure, which does not propagate the change to the fanouts but + instead records the change in the form of a buf/inv node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_NodeFixBufferFanins( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel ) +{ + Ivy_Obj_t * pFanReal0, * pFanReal1, * pResult = NULL; + if ( Ivy_ObjIsPo(pNode) ) + { + if ( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) ) + return; + pFanReal0 = Ivy_ObjReal( Ivy_ObjChild0(pNode) ); + Ivy_ObjPatchFanin0( p, pNode, pFanReal0 ); +// Ivy_ManCheckFanouts( p ); + return; + } + if ( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) && !Ivy_ObjIsBuf(Ivy_ObjFanin1(pNode)) ) + return; + // get the real fanins + pFanReal0 = Ivy_ObjReal( Ivy_ObjChild0(pNode) ); + pFanReal1 = Ivy_ObjReal( Ivy_ObjChild1(pNode) ); + // get the new node + if ( Ivy_ObjIsNode(pNode) ) + pResult = Ivy_Oper( p, pFanReal0, pFanReal1, Ivy_ObjType(pNode) ); + else if ( Ivy_ObjIsLatch(pNode) ) + pResult = Ivy_Latch( p, pFanReal0, Ivy_ObjInit(pNode) ); + else + assert( 0 ); + +//printf( "===== Replacing %d by %d.\n", pNode->Id, pResult->Id ); +//Ivy_ObjPrintVerbose( p, pNode, 0 ); printf( "\n" ); +//Ivy_ObjPrintVerbose( p, pResult, 0 ); printf( "\n" ); + + // perform the replacement + Ivy_ObjReplace( p, pNode, pResult, 1, 0, fUpdateLevel ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/ivyOper.c b/yosys/abc/src/aig/ivy/ivyOper.c new file mode 100644 index 00000000000..ea61924d266 --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivyOper.c @@ -0,0 +1,298 @@ +/**CFile**************************************************************** + + FileName [ivyOper.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [AIG operations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyOper.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// procedure to detect an EXOR gate +static inline int Ivy_ObjIsExorType( Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Obj_t ** ppFan0, Ivy_Obj_t ** ppFan1 ) +{ + if ( !Ivy_IsComplement(p0) || !Ivy_IsComplement(p1) ) + return 0; + p0 = Ivy_Regular(p0); + p1 = Ivy_Regular(p1); + if ( !Ivy_ObjIsAnd(p0) || !Ivy_ObjIsAnd(p1) ) + return 0; + if ( Ivy_ObjFanin0(p0) != Ivy_ObjFanin0(p1) || Ivy_ObjFanin1(p0) != Ivy_ObjFanin1(p1) ) + return 0; + if ( Ivy_ObjFaninC0(p0) == Ivy_ObjFaninC0(p1) || Ivy_ObjFaninC1(p0) == Ivy_ObjFaninC1(p1) ) + return 0; + *ppFan0 = Ivy_ObjChild0(p0); + *ppFan1 = Ivy_ObjChild1(p0); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Perform one operation.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Oper( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1, Ivy_Type_t Type ) +{ + if ( Type == IVY_AND ) + return Ivy_And( p, p0, p1 ); + if ( Type == IVY_EXOR ) + return Ivy_Exor( p, p0, p1 ); + assert( 0 ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_And( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ) +{ +// Ivy_Obj_t * pFan0, * pFan1; + // check trivial cases + if ( p0 == p1 ) + return p0; + if ( p0 == Ivy_Not(p1) ) + return Ivy_Not(p->pConst1); + if ( Ivy_Regular(p0) == p->pConst1 ) + return p0 == p->pConst1 ? p1 : Ivy_Not(p->pConst1); + if ( Ivy_Regular(p1) == p->pConst1 ) + return p1 == p->pConst1 ? p0 : Ivy_Not(p->pConst1); + // check if it can be an EXOR gate +// if ( Ivy_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) ) +// return Ivy_CanonExor( pFan0, pFan1 ); + return Ivy_CanonAnd( p, p0, p1 ); +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Exor( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ) +{ +/* + // check trivial cases + if ( p0 == p1 ) + return Ivy_Not(p->pConst1); + if ( p0 == Ivy_Not(p1) ) + return p->pConst1; + if ( Ivy_Regular(p0) == p->pConst1 ) + return Ivy_NotCond( p1, p0 == p->pConst1 ); + if ( Ivy_Regular(p1) == p->pConst1 ) + return Ivy_NotCond( p0, p1 == p->pConst1 ); + // check the table + return Ivy_CanonExor( p, p0, p1 ); +*/ + return Ivy_Or( p, Ivy_And(p, p0, Ivy_Not(p1)), Ivy_And(p, Ivy_Not(p0), p1) ); +} + +/**Function************************************************************* + + Synopsis [Implements Boolean OR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Or( Ivy_Man_t * p, Ivy_Obj_t * p0, Ivy_Obj_t * p1 ) +{ + return Ivy_Not( Ivy_And( p, Ivy_Not(p0), Ivy_Not(p1) ) ); +} + +/**Function************************************************************* + + Synopsis [Implements ITE operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Mux( Ivy_Man_t * p, Ivy_Obj_t * pC, Ivy_Obj_t * p1, Ivy_Obj_t * p0 ) +{ + Ivy_Obj_t * pTempA1, * pTempA2, * pTempB1, * pTempB2, * pTemp; + int Count0, Count1; + // consider trivial cases + if ( p0 == Ivy_Not(p1) ) + return Ivy_Exor( p, pC, p0 ); + // other cases can be added + // implement the first MUX (F = C * x1 + C' * x0) + pTempA1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pC, p1, IVY_AND, IVY_INIT_NONE) ); + pTempA2 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pC), p0, IVY_AND, IVY_INIT_NONE) ); + if ( pTempA1 && pTempA2 ) + { + pTemp = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pTempA1), Ivy_Not(pTempA2), IVY_AND, IVY_INIT_NONE) ); + if ( pTemp ) return Ivy_Not(pTemp); + } + Count0 = (pTempA1 != NULL) + (pTempA2 != NULL); + // implement the second MUX (F' = C * x1' + C' * x0') + pTempB1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pC, Ivy_Not(p1), IVY_AND, IVY_INIT_NONE) ); + pTempB2 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pC), Ivy_Not(p0), IVY_AND, IVY_INIT_NONE) ); + if ( pTempB1 && pTempB2 ) + { + pTemp = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Not(pTempB1), Ivy_Not(pTempB2), IVY_AND, IVY_INIT_NONE) ); + if ( pTemp ) return pTemp; + } + Count1 = (pTempB1 != NULL) + (pTempB2 != NULL); + // compare and decide which one to implement + if ( Count0 >= Count1 ) + { + pTempA1 = pTempA1? pTempA1 : Ivy_And(p, pC, p1); + pTempA2 = pTempA2? pTempA2 : Ivy_And(p, Ivy_Not(pC), p0); + return Ivy_Or( p, pTempA1, pTempA2 ); + } + pTempB1 = pTempB1? pTempB1 : Ivy_And(p, pC, Ivy_Not(p1)); + pTempB2 = pTempB2? pTempB2 : Ivy_And(p, Ivy_Not(pC), Ivy_Not(p0)); + return Ivy_Not( Ivy_Or( p, pTempB1, pTempB2 ) ); + +// return Ivy_Or( Ivy_And(pC, p1), Ivy_And(Ivy_Not(pC), p0) ); +} + +/**Function************************************************************* + + Synopsis [Implements ITE operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Maj( Ivy_Man_t * p, Ivy_Obj_t * pA, Ivy_Obj_t * pB, Ivy_Obj_t * pC ) +{ + return Ivy_Or( p, Ivy_Or(p, Ivy_And(p, pA, pB), Ivy_And(p, pA, pC)), Ivy_And(p, pB, pC) ); +} + +/**Function************************************************************* + + Synopsis [Constructs the well-balanced tree of gates.] + + Description [Disregards levels and possible logic sharing.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Multi_rec( Ivy_Man_t * p, Ivy_Obj_t ** ppObjs, int nObjs, Ivy_Type_t Type ) +{ + Ivy_Obj_t * pObj1, * pObj2; + if ( nObjs == 1 ) + return ppObjs[0]; + pObj1 = Ivy_Multi_rec( p, ppObjs, nObjs/2, Type ); + pObj2 = Ivy_Multi_rec( p, ppObjs + nObjs/2, nObjs - nObjs/2, Type ); + return Ivy_Oper( p, pObj1, pObj2, Type ); +} + +/**Function************************************************************* + + Synopsis [Old code.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Multi( Ivy_Man_t * p, Ivy_Obj_t ** pArgs, int nArgs, Ivy_Type_t Type ) +{ + assert( Type == IVY_AND || Type == IVY_EXOR ); + assert( nArgs > 0 ); + return Ivy_Multi_rec( p, pArgs, nArgs, Type ); +} + +/**Function************************************************************* + + Synopsis [Implements the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Miter( Ivy_Man_t * p, Vec_Ptr_t * vPairs ) +{ + int i; + assert( vPairs->nSize > 0 ); + assert( vPairs->nSize % 2 == 0 ); + // go through the cubes of the node's SOP + for ( i = 0; i < vPairs->nSize; i += 2 ) + vPairs->pArray[i/2] = Ivy_Not( Ivy_Exor( p, (Ivy_Obj_t *)vPairs->pArray[i], (Ivy_Obj_t *)vPairs->pArray[i+1] ) ); + vPairs->nSize = vPairs->nSize/2; + return Ivy_Not( Ivy_Multi_rec( p, (Ivy_Obj_t **)vPairs->pArray, vPairs->nSize, IVY_AND ) ); +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_Latch( Ivy_Man_t * p, Ivy_Obj_t * pObj, Ivy_Init_t Init ) +{ + return Ivy_CanonLatch( p, pObj, Init ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/ivyResyn.c b/yosys/abc/src/aig/ivy/ivyResyn.c new file mode 100644 index 00000000000..1eacbe5e1e5 --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivyResyn.c @@ -0,0 +1,201 @@ +/**CFile**************************************************************** + + FileName [ivyResyn.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [AIG rewriting script.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyResyn.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs several passes of rewriting on the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManResyn0( Ivy_Man_t * pMan, int fUpdateLevel, int fVerbose ) +{ + abctime clk; + Ivy_Man_t * pTemp; + +if ( fVerbose ) { printf( "Original:\n" ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = Abc_Clock(); + pMan = Ivy_ManBalance( pMan, fUpdateLevel ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { ABC_PRT( "Balance", Abc_Clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 0 ); +clk = Abc_Clock(); + Ivy_ManRewritePre( pMan, fUpdateLevel, 0, 0 ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { ABC_PRT( "Rewrite", Abc_Clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = Abc_Clock(); + pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel ); + Ivy_ManStop( pTemp ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { ABC_PRT( "Balance", Abc_Clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [Performs several passes of rewriting on the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManResyn( Ivy_Man_t * pMan, int fUpdateLevel, int fVerbose ) +{ + abctime clk; + Ivy_Man_t * pTemp; + +if ( fVerbose ) { printf( "Original:\n" ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = Abc_Clock(); + pMan = Ivy_ManBalance( pMan, fUpdateLevel ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { ABC_PRT( "Balance", Abc_Clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 0 ); +clk = Abc_Clock(); + Ivy_ManRewritePre( pMan, fUpdateLevel, 0, 0 ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { ABC_PRT( "Rewrite", Abc_Clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = Abc_Clock(); + pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel ); + Ivy_ManStop( pTemp ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { ABC_PRT( "Balance", Abc_Clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 1 ); +clk = Abc_Clock(); + Ivy_ManRewritePre( pMan, fUpdateLevel, 1, 0 ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { ABC_PRT( "Rewrite", Abc_Clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = Abc_Clock(); + pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel ); + Ivy_ManStop( pTemp ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { ABC_PRT( "Balance", Abc_Clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +// Ivy_ManRewriteAlg( pMan, fUpdateLevel, 1 ); +clk = Abc_Clock(); + Ivy_ManRewritePre( pMan, fUpdateLevel, 1, 0 ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { ABC_PRT( "Rewrite", Abc_Clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = Abc_Clock(); + pMan = Ivy_ManBalance( pTemp = pMan, fUpdateLevel ); + Ivy_ManStop( pTemp ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { ABC_PRT( "Balance", Abc_Clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + return pMan; +} + +/**Function************************************************************* + + Synopsis [Performs several passes of rewriting on the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Man_t * Ivy_ManRwsat( Ivy_Man_t * pMan, int fVerbose ) +{ + abctime clk; + Ivy_Man_t * pTemp; + +if ( fVerbose ) { printf( "Original:\n" ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = Abc_Clock(); + Ivy_ManRewritePre( pMan, 0, 0, 0 ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { ABC_PRT( "Rewrite", Abc_Clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = Abc_Clock(); + pMan = Ivy_ManBalance( pTemp = pMan, 0 ); +// pMan = Ivy_ManDup( pTemp = pMan ); + Ivy_ManStop( pTemp ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { ABC_PRT( "Balance", Abc_Clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +/* +clk = Abc_Clock(); + Ivy_ManRewritePre( pMan, 0, 0, 0 ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { ABC_PRT( "Rewrite", Abc_Clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); + +clk = Abc_Clock(); + pMan = Ivy_ManBalance( pTemp = pMan, 0 ); + Ivy_ManStop( pTemp ); +if ( fVerbose ) { printf( "\n" ); } +if ( fVerbose ) { ABC_PRT( "Balance", Abc_Clock() - clk ); } +if ( fVerbose ) Ivy_ManPrintStats( pMan ); +*/ + return pMan; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/ivyRwr.c b/yosys/abc/src/aig/ivy/ivyRwr.c new file mode 100644 index 00000000000..30bff58f089 --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivyRwr.c @@ -0,0 +1,618 @@ +/**CFile**************************************************************** + + FileName [ivyRwt.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Rewriting based on precomputation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyRwt.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" +#include "bool/deco/deco.h" +#include "opt/rwt/rwt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static unsigned Ivy_NodeGetTruth( Ivy_Obj_t * pObj, int * pNums, int nNums ); +static int Ivy_NodeRewrite( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel, int fUseZeroCost ); +static Dec_Graph_t * Rwt_CutEvaluate( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, + Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, unsigned uTruth ); + +static int Ivy_GraphToNetworkCount( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax ); +static void Ivy_GraphUpdateNetwork( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs incremental rewriting of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManRewritePre( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost, int fVerbose ) +{ + Rwt_Man_t * pManRwt; + Ivy_Obj_t * pNode; + int i, nNodes, nGain; + abctime clk, clkStart = Abc_Clock(); + // start the rewriting manager + pManRwt = Rwt_ManStart( 0 ); + p->pData = pManRwt; + if ( pManRwt == NULL ) + return 0; + // create fanouts + if ( fUpdateLevel && p->fFanout == 0 ) + Ivy_ManStartFanout( p ); + // compute the reverse levels if level update is requested + if ( fUpdateLevel ) + Ivy_ManRequiredLevels( p ); + // set the number of levels +// p->nLevelMax = Ivy_ManLevels( p ); + // resynthesize each node once + nNodes = Ivy_ManObjIdMax(p); + Ivy_ManForEachNode( p, pNode, i ) + { + // fix the fanin buffer problem + Ivy_NodeFixBufferFanins( p, pNode, 1 ); + if ( Ivy_ObjIsBuf(pNode) ) + continue; + // stop if all nodes have been tried once + if ( i > nNodes ) + break; + // for each cut, try to resynthesize it + nGain = Ivy_NodeRewrite( p, pManRwt, pNode, fUpdateLevel, fUseZeroCost ); + if ( nGain > 0 || (nGain == 0 && fUseZeroCost) ) + { + Dec_Graph_t * pGraph = (Dec_Graph_t *)Rwt_ManReadDecs(pManRwt); + int fCompl = Rwt_ManReadCompl(pManRwt); +/* + { + Ivy_Obj_t * pObj; + int i; + printf( "USING: (" ); + Vec_PtrForEachEntry( Ivy_Obj_t *, Rwt_ManReadLeaves(pManRwt), pObj, i ) + printf( "%d ", Ivy_ObjFanoutNum(Ivy_Regular(pObj)) ); + printf( ") Gain = %d.\n", nGain ); + } + if ( nGain > 0 ) + { // print stats on the MFFC + extern void Ivy_NodeMffcConeSuppPrint( Ivy_Obj_t * pNode ); + printf( "Node %6d : Gain = %4d ", pNode->Id, nGain ); + Ivy_NodeMffcConeSuppPrint( pNode ); + } +*/ + // complement the FF if needed +clk = Abc_Clock(); + if ( fCompl ) Dec_GraphComplement( pGraph ); + Ivy_GraphUpdateNetwork( p, pNode, pGraph, fUpdateLevel, nGain ); + if ( fCompl ) Dec_GraphComplement( pGraph ); +Rwt_ManAddTimeUpdate( pManRwt, Abc_Clock() - clk ); + } + } +Rwt_ManAddTimeTotal( pManRwt, Abc_Clock() - clkStart ); + // print stats + if ( fVerbose ) + Rwt_ManPrintStats( pManRwt ); + // delete the managers + Rwt_ManStop( pManRwt ); + p->pData = NULL; + // fix the levels + if ( fUpdateLevel ) + Vec_IntFree( p->vRequired ), p->vRequired = NULL; + else + Ivy_ManResetLevels( p ); + // check + if ( (i = Ivy_ManCleanup(p)) ) + printf( "Cleanup after rewriting removed %d dangling nodes.\n", i ); + if ( !Ivy_ManCheck(p) ) + printf( "Ivy_ManRewritePre(): The check has failed.\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Performs rewriting for one node.] + + Description [This procedure considers all the cuts computed for the node + and tries to rewrite each of them using the "forest" of different AIG + structures precomputed and stored in the RWR manager. + Determines the best rewriting and computes the gain in the number of AIG + nodes in the final network. In the end, p->vFanins contains information + about the best cut that can be used for rewriting, while p->pGraph gives + the decomposition dag (represented using decomposition graph data structure). + Returns gain in the number of nodes or -1 if node cannot be rewritten.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeRewrite( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUpdateLevel, int fUseZeroCost ) +{ + int fVeryVerbose = 0; + Dec_Graph_t * pGraph; + Ivy_Store_t * pStore; + Ivy_Cut_t * pCut; + Ivy_Obj_t * pFanin; + unsigned uPhase; + unsigned uTruthBest = 0; // Suppress "might be used uninitialized" + unsigned uTruth; + char * pPerm; + int Required, nNodesSaved; + int nNodesSaveCur = -1; // Suppress "might be used uninitialized" + int i, c, GainCur = -1, GainBest = -1; + abctime clk, clk2; + + p->nNodesConsidered++; + // get the required times + Required = fUpdateLevel? Vec_IntEntry( pMan->vRequired, pNode->Id ) : 1000000; + // get the node's cuts +clk = Abc_Clock(); + pStore = Ivy_NodeFindCutsAll( pMan, pNode, 5 ); +p->timeCut += Abc_Clock() - clk; + + // go through the cuts +clk = Abc_Clock(); + for ( c = 1; c < pStore->nCuts; c++ ) + { + pCut = pStore->pCuts + c; + // consider only 4-input cuts + if ( pCut->nSize != 4 ) + continue; + // skip the cuts with buffers + for ( i = 0; i < (int)pCut->nSize; i++ ) + if ( Ivy_ObjIsBuf( Ivy_ManObj(pMan, pCut->pArray[i]) ) ) + break; + if ( i != pCut->nSize ) + { + p->nCutsBad++; + continue; + } + p->nCutsGood++; + // get the fanin permutation +clk2 = Abc_Clock(); + uTruth = 0xFFFF & Ivy_NodeGetTruth( pNode, pCut->pArray, pCut->nSize ); // truth table +p->timeTruth += Abc_Clock() - clk2; + pPerm = p->pPerms4[ (int) p->pPerms[uTruth] ]; + uPhase = p->pPhases[uTruth]; + // collect fanins with the corresponding permutation/phase + Vec_PtrClear( p->vFaninsCur ); + Vec_PtrFill( p->vFaninsCur, (int)pCut->nSize, 0 ); + for ( i = 0; i < (int)pCut->nSize; i++ ) + { + pFanin = Ivy_ManObj( pMan, pCut->pArray[(int)pPerm[i]] ); + assert( Ivy_ObjIsNode(pFanin) || Ivy_ObjIsCi(pFanin) ); + pFanin = Ivy_NotCond(pFanin, ((uPhase & (1< 0) ); + Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin ); + } +clk2 = Abc_Clock(); +/* + printf( "Considering: (" ); + Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFaninsCur, pFanin, i ) + printf( "%d ", Ivy_ObjFanoutNum(Ivy_Regular(pFanin)) ); + printf( ")\n" ); +*/ + // mark the fanin boundary + Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFaninsCur, pFanin, i ) + Ivy_ObjRefsInc( Ivy_Regular(pFanin) ); + // label MFFC with current ID + Ivy_ManIncrementTravId( pMan ); + nNodesSaved = Ivy_ObjMffcLabel( pMan, pNode ); + // unmark the fanin boundary + Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFaninsCur, pFanin, i ) + Ivy_ObjRefsDec( Ivy_Regular(pFanin) ); +p->timeMffc += Abc_Clock() - clk2; + + // evaluate the cut +clk2 = Abc_Clock(); + pGraph = Rwt_CutEvaluate( pMan, p, pNode, p->vFaninsCur, nNodesSaved, Required, &GainCur, uTruth ); +p->timeEval += Abc_Clock() - clk2; + + // check if the cut is better than the current best one + if ( pGraph != NULL && GainBest < GainCur ) + { + // save this form + nNodesSaveCur = nNodesSaved; + GainBest = GainCur; + p->pGraph = pGraph; + p->fCompl = ((uPhase & (1<<4)) > 0); + uTruthBest = uTruth; + // collect fanins in the + Vec_PtrClear( p->vFanins ); + Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFaninsCur, pFanin, i ) + Vec_PtrPush( p->vFanins, pFanin ); + } + } +p->timeRes += Abc_Clock() - clk; + + if ( GainBest == -1 ) + return -1; + +// printf( "%d", nNodesSaveCur - GainBest ); +/* + if ( GainBest > 0 ) + { + if ( Rwt_CutIsintean( pNode, p->vFanins ) ) + printf( "b" ); + else + { + printf( "Node %d : ", pNode->Id ); + Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFanins, pFanin, i ) + printf( "%d ", Ivy_Regular(pFanin)->Id ); + printf( "a" ); + } + } +*/ +/* + if ( GainBest > 0 ) + if ( p->fCompl ) + printf( "c" ); + else + printf( "." ); +*/ + + // copy the leaves + Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFanins, pFanin, i ) + Dec_GraphNode((Dec_Graph_t *)p->pGraph, i)->pFunc = pFanin; + + p->nScores[p->pMap[uTruthBest]]++; + p->nNodesGained += GainBest; + if ( fUseZeroCost || GainBest > 0 ) + p->nNodesRewritten++; + + // report the progress + if ( fVeryVerbose && GainBest > 0 ) + { + printf( "Node %6d : ", Ivy_ObjId(pNode) ); + printf( "Fanins = %d. ", p->vFanins->nSize ); + printf( "Save = %d. ", nNodesSaveCur ); + printf( "Add = %d. ", nNodesSaveCur-GainBest ); + printf( "GAIN = %d. ", GainBest ); + printf( "Cone = %d. ", p->pGraph? Dec_GraphNodeNum((Dec_Graph_t *)p->pGraph) : 0 ); + printf( "Class = %d. ", p->pMap[uTruthBest] ); + printf( "\n" ); + } + return GainBest; +} + +/**Function************************************************************* + + Synopsis [Computes the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Ivy_NodeGetTruth_rec( Ivy_Obj_t * pObj, int * pNums, int nNums ) +{ + static unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; + unsigned uTruth0, uTruth1; + int i; + for ( i = 0; i < nNums; i++ ) + if ( pObj->Id == pNums[i] ) + return uMasks[i]; + assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); + uTruth0 = Ivy_NodeGetTruth_rec( Ivy_ObjFanin0(pObj), pNums, nNums ); + if ( Ivy_ObjFaninC0(pObj) ) + uTruth0 = ~uTruth0; + if ( Ivy_ObjIsBuf(pObj) ) + return uTruth0; + uTruth1 = Ivy_NodeGetTruth_rec( Ivy_ObjFanin1(pObj), pNums, nNums ); + if ( Ivy_ObjFaninC1(pObj) ) + uTruth1 = ~uTruth1; + return uTruth0 & uTruth1; +} + + +/**Function************************************************************* + + Synopsis [Computes the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Ivy_NodeGetTruth( Ivy_Obj_t * pObj, int * pNums, int nNums ) +{ + assert( nNums < 6 ); + return Ivy_NodeGetTruth_rec( pObj, pNums, nNums ); +} + +/**Function************************************************************* + + Synopsis [Evaluates the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Rwt_CutEvaluate( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int LevelMax, int * pGainBest, unsigned uTruth ) +{ + Vec_Ptr_t * vSubgraphs; + Dec_Graph_t * pGraphBest = NULL; // Suppress "might be used uninitialized" + Dec_Graph_t * pGraphCur; + Rwt_Node_t * pNode, * pFanin; + int nNodesAdded, GainBest, i, k; + // find the matching class of subgraphs + vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] ); + p->nSubgraphs += vSubgraphs->nSize; + // determine the best subgraph + GainBest = -1; + Vec_PtrForEachEntry( Rwt_Node_t *, vSubgraphs, pNode, i ) + { + // get the current graph + pGraphCur = (Dec_Graph_t *)pNode->pNext; + // copy the leaves + Vec_PtrForEachEntry( Rwt_Node_t *, vFaninsCur, pFanin, k ) + Dec_GraphNode(pGraphCur, k)->pFunc = pFanin; + // detect how many unlabeled nodes will be reused + nNodesAdded = Ivy_GraphToNetworkCount( pMan, pRoot, pGraphCur, nNodesSaved, LevelMax ); + if ( nNodesAdded == -1 ) + continue; + assert( nNodesSaved >= nNodesAdded ); + // count the gain at this node + if ( GainBest < nNodesSaved - nNodesAdded ) + { + GainBest = nNodesSaved - nNodesAdded; + pGraphBest = pGraphCur; + } + } + if ( GainBest == -1 ) + return NULL; + *pGainBest = GainBest; + return pGraphBest; +} + + +/**Function************************************************************* + + Synopsis [Counts the number of new nodes added when using this graph.] + + Description [AIG nodes for the fanins should be assigned to pNode->pFunc + of the leaves of the graph before calling this procedure. + Returns -1 if the number of nodes and levels exceeded the given limit or + the number of levels exceeded the maximum allowed level.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_GraphToNetworkCount( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax ) +{ + Dec_Node_t * pNode, * pNode0, * pNode1; + Ivy_Obj_t * pAnd, * pAnd0, * pAnd1; + int i, Counter, LevelNew, LevelOld; + // check for constant function or a literal + if ( Dec_GraphIsConst(pGraph) || Dec_GraphIsVar(pGraph) ) + return 0; + // set the levels of the leaves + Dec_GraphForEachLeaf( pGraph, pNode, i ) + pNode->Level = Ivy_Regular((Ivy_Obj_t *)pNode->pFunc)->Level; + // compute the AIG size after adding the internal nodes + Counter = 0; + Dec_GraphForEachNode( pGraph, pNode, i ) + { + // get the children of this node + pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node ); + pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node ); + // get the AIG nodes corresponding to the children + pAnd0 = (Ivy_Obj_t *)pNode0->pFunc; + pAnd1 = (Ivy_Obj_t *)pNode1->pFunc; + if ( pAnd0 && pAnd1 ) + { + // if they are both present, find the resulting node + pAnd0 = Ivy_NotCond( pAnd0, pNode->eEdge0.fCompl ); + pAnd1 = Ivy_NotCond( pAnd1, pNode->eEdge1.fCompl ); + pAnd = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pAnd0, pAnd1, IVY_AND, IVY_INIT_NONE) ); + // return -1 if the node is the same as the original root + if ( Ivy_Regular(pAnd) == pRoot ) + return -1; + } + else + pAnd = NULL; + // count the number of added nodes + if ( pAnd == NULL || Ivy_ObjIsTravIdCurrent(p, Ivy_Regular(pAnd)) ) + { + if ( ++Counter > NodeMax ) + return -1; + } + // count the number of new levels + LevelNew = 1 + RWT_MAX( pNode0->Level, pNode1->Level ); + if ( pAnd ) + { + if ( Ivy_Regular(pAnd) == p->pConst1 ) + LevelNew = 0; + else if ( Ivy_Regular(pAnd) == Ivy_Regular(pAnd0) ) + LevelNew = (int)Ivy_Regular(pAnd0)->Level; + else if ( Ivy_Regular(pAnd) == Ivy_Regular(pAnd1) ) + LevelNew = (int)Ivy_Regular(pAnd1)->Level; + LevelOld = (int)Ivy_Regular(pAnd)->Level; +// assert( LevelNew == LevelOld ); + } + if ( LevelNew > LevelMax ) + return -1; + pNode->pFunc = pAnd; + pNode->Level = LevelNew; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Transforms the decomposition graph into the AIG.] + + Description [AIG nodes for the fanins should be assigned to pNode->pFunc + of the leaves of the graph before calling this procedure.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_GraphToNetwork( Ivy_Man_t * p, Dec_Graph_t * pGraph ) +{ + Ivy_Obj_t * pAnd0, * pAnd1; + Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized" + int i; + // check for constant function + if ( Dec_GraphIsConst(pGraph) ) + return Ivy_NotCond( Ivy_ManConst1(p), Dec_GraphIsComplement(pGraph) ); + // check for a literal + if ( Dec_GraphIsVar(pGraph) ) + return Ivy_NotCond( (Ivy_Obj_t *)Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) ); + // build the AIG nodes corresponding to the AND gates of the graph + Dec_GraphForEachNode( pGraph, pNode, i ) + { + pAnd0 = Ivy_NotCond( (Ivy_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + pAnd1 = Ivy_NotCond( (Ivy_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); + pNode->pFunc = Ivy_And( p, pAnd0, pAnd1 ); + } + // complement the result if necessary + return Ivy_NotCond( (Ivy_Obj_t *)pNode->pFunc, Dec_GraphIsComplement(pGraph) ); +} + +/**Function************************************************************* + + Synopsis [Replaces MFFC of the node by the new factored form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_GraphUpdateNetwork( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ) +{ + Ivy_Obj_t * pRootNew; + int nNodesNew, nNodesOld, Required; + Required = fUpdateLevel? Vec_IntEntry( p->vRequired, pRoot->Id ) : 1000000; + nNodesOld = Ivy_ManNodeNum(p); + // create the new structure of nodes + pRootNew = Ivy_GraphToNetwork( p, pGraph ); + assert( (int)Ivy_Regular(pRootNew)->Level <= Required ); +// if ( Ivy_Regular(pRootNew)->Level == Required ) +// printf( "Difference %d.\n", Ivy_Regular(pRootNew)->Level - Required ); + // remove the old nodes +// Ivy_AigReplace( pMan->pManFunc, pRoot, pRootNew, fUpdateLevel ); +/* + if ( Ivy_IsComplement(pRootNew) ) + printf( "c" ); + else + printf( "d" ); + if ( Ivy_ObjRefs(Ivy_Regular(pRootNew)) > 0 ) + printf( "%d", Ivy_ObjRefs(Ivy_Regular(pRootNew)) ); + printf( " " ); +*/ + Ivy_ObjReplace( p, pRoot, pRootNew, 1, 0, 1 ); + // compare the gains + nNodesNew = Ivy_ManNodeNum(p); + assert( nGain <= nNodesOld - nNodesNew ); + // propagate the buffer + Ivy_ManPropagateBuffers( p, 1 ); +} + +/**Function************************************************************* + + Synopsis [Replaces MFFC of the node by the new factored form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_GraphUpdateNetwork3( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ) +{ + Ivy_Obj_t * pRootNew, * pFanin; + int nNodesNew, nNodesOld, i, nRefsOld; + nNodesOld = Ivy_ManNodeNum(p); + +//printf( "Before = %d. ", Ivy_ManNodeNum(p) ); + // mark the cut + Vec_PtrForEachEntry( Ivy_Obj_t *, ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i ) + Ivy_ObjRefsInc( Ivy_Regular(pFanin) ); + // deref the old cone + nRefsOld = pRoot->nRefs; + pRoot->nRefs = 0; + Ivy_ObjDelete_rec( p, pRoot, 0 ); + pRoot->nRefs = nRefsOld; + // unmark the cut + Vec_PtrForEachEntry( Ivy_Obj_t *, ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i ) + Ivy_ObjRefsDec( Ivy_Regular(pFanin) ); +//printf( "Deref = %d. ", Ivy_ManNodeNum(p) ); + + // create the new structure of nodes + pRootNew = Ivy_GraphToNetwork( p, pGraph ); +//printf( "Create = %d. ", Ivy_ManNodeNum(p) ); + // remove the old nodes +// Ivy_AigReplace( pMan->pManFunc, pRoot, pRootNew, fUpdateLevel ); +/* + if ( Ivy_IsComplement(pRootNew) ) + printf( "c" ); + else + printf( "d" ); + if ( Ivy_ObjRefs(Ivy_Regular(pRootNew)) > 0 ) + printf( "%d", Ivy_ObjRefs(Ivy_Regular(pRootNew)) ); + printf( " " ); +*/ + Ivy_ObjReplace( p, pRoot, pRootNew, 0, 0, 1 ); +//printf( "Replace = %d. ", Ivy_ManNodeNum(p) ); + + // delete remaining dangling nodes + Vec_PtrForEachEntry( Ivy_Obj_t *, ((Rwt_Man_t *)p->pData)->vFanins, pFanin, i ) + { + pFanin = Ivy_Regular(pFanin); + if ( !Ivy_ObjIsNone(pFanin) && Ivy_ObjRefs(pFanin) == 0 ) + Ivy_ObjDelete_rec( p, pFanin, 1 ); + } +//printf( "Deref = %d. ", Ivy_ManNodeNum(p) ); +//printf( "\n" ); + + // compare the gains + nNodesNew = Ivy_ManNodeNum(p); + assert( nGain <= nNodesOld - nNodesNew ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/ivyRwrAlg.c b/yosys/abc/src/aig/ivy/ivyRwrAlg.c new file mode 100644 index 00000000000..53fe58177d2 --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivyRwrAlg.c @@ -0,0 +1,413 @@ +/**CFile**************************************************************** + + FileName [ivyRwrAlg.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Algebraic AIG rewriting.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyRwrAlg.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Ivy_ManFindAlgCut( Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone ); +static Ivy_Obj_t * Ivy_NodeRewriteAlg( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vSols, int LevelR, int fUseZeroCost ); +static int Ivy_NodeCountMffc( Ivy_Obj_t * pNode ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Algebraic AIG rewriting.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManRewriteAlg( Ivy_Man_t * p, int fUpdateLevel, int fUseZeroCost ) +{ + Vec_Int_t * vRequired; + Vec_Ptr_t * vFront, * vLeaves, * vCone, * vSol; + Ivy_Obj_t * pObj, * pResult; + int i, RetValue, LevelR, nNodesOld; + int CountUsed, CountUndo; + vRequired = fUpdateLevel? Ivy_ManRequiredLevels( p ) : NULL; + vFront = Vec_PtrAlloc( 100 ); + vLeaves = Vec_PtrAlloc( 100 ); + vCone = Vec_PtrAlloc( 100 ); + vSol = Vec_PtrAlloc( 100 ); + // go through the nodes in the topological order + CountUsed = CountUndo = 0; + nNodesOld = Ivy_ManObjIdNext(p); + Ivy_ManForEachObj( p, pObj, i ) + { + assert( !Ivy_ObjIsBuf(pObj) ); + if ( i >= nNodesOld ) + break; + // skip no-nodes and MUX roots + if ( !Ivy_ObjIsNode(pObj) || Ivy_ObjIsExor(pObj) || Ivy_ObjIsMuxType(pObj) ) + continue; +// if ( pObj->Id > 297 ) // 296 --- 297 +// break; + if ( pObj->Id == 297 ) + { + int x = 0; + } + // get the largest algebraic cut + RetValue = Ivy_ManFindAlgCut( pObj, vFront, vLeaves, vCone ); + // the case of a trivial tree cut + if ( RetValue == 1 ) + continue; + // the case of constant 0 cone + if ( RetValue == -1 ) + { + Ivy_ObjReplace( pObj, Ivy_ManConst0(p), 1, 0, 1 ); + continue; + } + assert( Vec_PtrSize(vLeaves) > 2 ); + // get the required level for this node + LevelR = vRequired? Vec_IntEntry(vRequired, pObj->Id) : 1000000; + // create a new cone + pResult = Ivy_NodeRewriteAlg( pObj, vFront, vLeaves, vCone, vSol, LevelR, fUseZeroCost ); + if ( pResult == NULL || pResult == pObj ) + continue; + assert( Vec_PtrSize(vSol) == 1 || !Ivy_IsComplement(pResult) ); + if ( Ivy_ObjLevel(Ivy_Regular(pResult)) > LevelR && Ivy_ObjRefs(Ivy_Regular(pResult)) == 0 ) + Ivy_ObjDelete_rec(Ivy_Regular(pResult), 1), CountUndo++; + else + Ivy_ObjReplace( pObj, pResult, 1, 0, 1 ), CountUsed++; + } + printf( "Used = %d. Undo = %d.\n", CountUsed, CountUndo ); + Vec_PtrFree( vFront ); + Vec_PtrFree( vCone ); + Vec_PtrFree( vSol ); + if ( vRequired ) Vec_IntFree( vRequired ); + if ( i = Ivy_ManCleanup(p) ) + printf( "Cleanup after rewriting removed %d dangling nodes.\n", i ); + if ( !Ivy_ManCheck(p) ) + printf( "Ivy_ManRewriteAlg(): The check has failed.\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Analizes one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_NodeRewriteAlg( Ivy_Obj_t * pObj, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone, Vec_Ptr_t * vSols, int LevelR, int fUseZeroCost ) +{ + int fVerbose = 0; + Ivy_Obj_t * pTemp; + int k, Counter, nMffc, RetValue; + + if ( fVerbose ) + { + if ( Ivy_ObjIsExor(pObj) ) + printf( "x " ); + else + printf( " " ); + } + +/* + printf( "%d ", Vec_PtrSize(vFront) ); + printf( "( " ); + Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, k ) + printf( "%d ", Ivy_ObjRefs(Ivy_Regular(pTemp)) ); + printf( ")\n" ); +*/ + // collect nodes in the cone + if ( Ivy_ObjIsExor(pObj) ) + Ivy_ManCollectCone( pObj, vFront, vCone ); + else + Ivy_ManCollectCone( pObj, vLeaves, vCone ); + + // deref nodes in the cone + Vec_PtrForEachEntry( Ivy_Obj_t *, vCone, pTemp, k ) + { + Ivy_ObjRefsDec( Ivy_ObjFanin0(pTemp) ); + Ivy_ObjRefsDec( Ivy_ObjFanin1(pTemp) ); + pTemp->fMarkB = 1; + } + + // count the MFFC size + Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, k ) + Ivy_Regular(pTemp)->fMarkA = 1; + nMffc = Ivy_NodeCountMffc( pObj ); + Vec_PtrForEachEntry( Ivy_Obj_t *, vFront, pTemp, k ) + Ivy_Regular(pTemp)->fMarkA = 0; + + if ( fVerbose ) + { + Counter = 0; + Vec_PtrForEachEntry( Ivy_Obj_t *, vCone, pTemp, k ) + Counter += (Ivy_ObjRefs(pTemp) > 0); + printf( "%5d : Leaves = %2d. Cone = %2d. ConeRef = %2d. Mffc = %d. Lev = %d. LevR = %d.\n", + pObj->Id, Vec_PtrSize(vFront), Vec_PtrSize(vCone), Counter-1, nMffc, Ivy_ObjLevel(pObj), LevelR ); + } +/* + printf( "Leaves:" ); + Vec_PtrForEachEntry( Ivy_Obj_t *, vLeaves, pTemp, k ) + printf( " %d%s", Ivy_Regular(pTemp)->Id, Ivy_IsComplement(pTemp)? "\'" : "" ); + printf( "\n" ); + printf( "Cone:\n" ); + Vec_PtrForEachEntry( Ivy_Obj_t *, vCone, pTemp, k ) + printf( " %5d = %d%s %d%s\n", pTemp->Id, + Ivy_ObjFaninId0(pTemp), Ivy_ObjFaninC0(pTemp)? "\'" : "", + Ivy_ObjFaninId1(pTemp), Ivy_ObjFaninC1(pTemp)? "\'" : "" ); +*/ + + RetValue = Ivy_MultiPlus( vLeaves, vCone, Ivy_ObjType(pObj), nMffc + fUseZeroCost, vSols ); + + // ref nodes in the cone + Vec_PtrForEachEntry( Ivy_Obj_t *, vCone, pTemp, k ) + { + Ivy_ObjRefsInc( Ivy_ObjFanin0(pTemp) ); + Ivy_ObjRefsInc( Ivy_ObjFanin1(pTemp) ); + pTemp->fMarkA = 0; + pTemp->fMarkB = 0; + } + + if ( !RetValue ) + return NULL; + + if ( Vec_PtrSize( vSols ) == 1 ) + return Vec_PtrEntry( vSols, 0 ); + return Ivy_NodeBalanceBuildSuper( vSols, Ivy_ObjType(pObj), 1 ); +} + +/**Function************************************************************* + + Synopsis [Comparison for node pointers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeCountMffc_rec( Ivy_Obj_t * pNode ) +{ + if ( Ivy_ObjRefs(pNode) > 0 || Ivy_ObjIsCi(pNode) || pNode->fMarkA ) + return 0; + assert( pNode->fMarkB ); + pNode->fMarkA = 1; +// printf( "%d ", pNode->Id ); + if ( Ivy_ObjIsBuf(pNode) ) + return Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) ); + return 1 + Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) ) + Ivy_NodeCountMffc_rec( Ivy_ObjFanin1(pNode) ); +} + +/**Function************************************************************* + + Synopsis [Comparison for node pointers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeCountMffc( Ivy_Obj_t * pNode ) +{ + assert( pNode->fMarkB ); + return 1 + Ivy_NodeCountMffc_rec( Ivy_ObjFanin0(pNode) ) + Ivy_NodeCountMffc_rec( Ivy_ObjFanin1(pNode) ); +} + +/**Function************************************************************* + + Synopsis [Comparison for node pointers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManFindAlgCutCompare( Ivy_Obj_t ** pp1, Ivy_Obj_t ** pp2 ) +{ + if ( *pp1 < *pp2 ) + return -1; + if ( *pp1 > *pp2 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Computing one algebraic cut.] + + Description [Returns 1 if the tree-leaves of this node where traversed + and found to have no external references (and have not been collected). + Returns 0 if the tree-leaves have external references and are collected.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManFindAlgCut_rec( Ivy_Obj_t * pObj, Ivy_Type_t Type, Vec_Ptr_t * vFront, Vec_Ptr_t * vCone ) +{ + int RetValue0, RetValue1; + Ivy_Obj_t * pObjR = Ivy_Regular(pObj); + assert( !Ivy_ObjIsBuf(pObjR) ); + assert( Type != IVY_EXOR || !Ivy_IsComplement(pObj) ); + + // make sure the node is not visited twice in different polarities + if ( Ivy_IsComplement(pObj) ) + { // if complemented, mark B + if ( pObjR->fMarkA ) + return -1; + pObjR->fMarkB = 1; + } + else + { // if non-complicated, mark A + if ( pObjR->fMarkB ) + return -1; + pObjR->fMarkA = 1; + } + Vec_PtrPush( vCone, pObjR ); + + // if the node is the end of the tree, return + if ( Ivy_IsComplement(pObj) || Ivy_ObjType(pObj) != Type ) + { + if ( Ivy_ObjRefs(pObjR) == 1 ) + return 1; + assert( Ivy_ObjRefs(pObjR) > 1 ); + Vec_PtrPush( vFront, pObj ); + return 0; + } + + // branch on the node + assert( !Ivy_IsComplement(pObj) ); + assert( Ivy_ObjIsNode(pObj) ); + // what if buffer has more than one fanout??? + RetValue0 = Ivy_ManFindAlgCut_rec( Ivy_ObjReal( Ivy_ObjChild0(pObj) ), Type, vFront, vCone ); + RetValue1 = Ivy_ManFindAlgCut_rec( Ivy_ObjReal( Ivy_ObjChild1(pObj) ), Type, vFront, vCone ); + if ( RetValue0 == -1 || RetValue1 == -1 ) + return -1; + + // the case when both have no external references + if ( RetValue0 && RetValue1 ) + { + if ( Ivy_ObjRefs(pObj) == 1 ) + return 1; + assert( Ivy_ObjRefs(pObj) > 1 ); + Vec_PtrPush( vFront, pObj ); + return 0; + } + // the case when one of them has external references + if ( RetValue0 ) + Vec_PtrPush( vFront, Ivy_ObjReal( Ivy_ObjChild0(pObj) ) ); + if ( RetValue1 ) + Vec_PtrPush( vFront, Ivy_ObjReal( Ivy_ObjChild1(pObj) ) ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Computing one algebraic cut.] + + Description [Algebraic cut stops when we hit (a) CI, (b) complemented edge, + (c) boundary of different gates. Returns 1 if this is a pure tree. + Returns -1 if the contant 0 is detected. Return 0 if the array can be used.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManFindAlgCut( Ivy_Obj_t * pRoot, Vec_Ptr_t * vFront, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vCone ) +{ + Ivy_Obj_t * pObj, * pPrev; + int RetValue, i; + assert( !Ivy_IsComplement(pRoot) ); + assert( Ivy_ObjIsNode(pRoot) ); + // clear the frontier and collect the nodes + Vec_PtrClear( vCone ); + Vec_PtrClear( vFront ); + Vec_PtrClear( vLeaves ); + RetValue = Ivy_ManFindAlgCut_rec( pRoot, Ivy_ObjType(pRoot), vFront, vCone ); + // clean the marks + Vec_PtrForEachEntry( Ivy_Obj_t *, vCone, pObj, i ) + pObj->fMarkA = pObj->fMarkB = 0; + // quit if the same node is found in both polarities + if ( RetValue == -1 ) + return -1; + // return if the node is the root of a tree + if ( RetValue == 1 ) + return 1; + // return if the cut is composed of two nodes + if ( Vec_PtrSize(vFront) <= 2 ) + return 1; + // sort the entries in increasing order + Vec_PtrSort( vFront, (int (*)(const void *, const void *))Ivy_ManFindAlgCutCompare ); + // remove duplicates from vFront and save the nodes in vLeaves + pPrev = Vec_PtrEntry(vFront, 0); + Vec_PtrPush( vLeaves, pPrev ); + Vec_PtrForEachEntryStart( Ivy_Obj_t *, vFront, pObj, i, 1 ) + { + // compare current entry and the previous entry + if ( pObj == pPrev ) + { + if ( Ivy_ObjIsExor(pRoot) ) // A <+> A = 0 + { + // vLeaves are no longer structural support of pRoot!!! + Vec_PtrPop(vLeaves); + pPrev = Vec_PtrSize(vLeaves) == 0 ? NULL : Vec_PtrEntryLast(vLeaves); + } + continue; + } + if ( pObj == Ivy_Not(pPrev) ) + { + assert( Ivy_ObjIsAnd(pRoot) ); + return -1; + } + pPrev = pObj; + Vec_PtrPush( vLeaves, pObj ); + } + if ( Vec_PtrSize(vLeaves) == 0 ) + return -1; + if ( Vec_PtrSize(vLeaves) <= 2 ) + return 1; + return 0; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/ivySeq.c b/yosys/abc/src/aig/ivy/ivySeq.c new file mode 100644 index 00000000000..0ffe2d15cb3 --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivySeq.c @@ -0,0 +1,1142 @@ +/**CFile**************************************************************** + + FileName [ivySeq.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivySeq.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" +#include "bool/deco/deco.h" +#include "opt/rwt/rwt.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Ivy_NodeRewriteSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUseZeroCost ); +static void Ivy_GraphPrepare( Dec_Graph_t * pGraph, Ivy_Cut_t * pCut, Vec_Ptr_t * vFanins, char * pPerm ); +static unsigned Ivy_CutGetTruth( Ivy_Man_t * p, Ivy_Obj_t * pObj, int * pNums, int nNums ); +static Dec_Graph_t * Rwt_CutEvaluateSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Ivy_Cut_t * pCut, char * pPerm, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int * pGainBest, unsigned uTruth ); +static int Ivy_GraphToNetworkSeqCountSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax ); +static Ivy_Obj_t * Ivy_GraphToNetworkSeq( Ivy_Man_t * p, Dec_Graph_t * pGraph ); +static void Ivy_GraphUpdateNetworkSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int nGain ); +static Ivy_Store_t * Ivy_CutComputeForNode( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves ); + +static inline int Ivy_CutHashValue( int NodeId ) { return 1 << (NodeId % 31); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//int nMoves; +//int nMovesS; +//int nClauses; +//int timeInv; + +/**Function************************************************************* + + Synopsis [Performs incremental rewriting of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManRewriteSeq( Ivy_Man_t * p, int fUseZeroCost, int fVerbose ) +{ + Rwt_Man_t * pManRwt; + Ivy_Obj_t * pNode; + int i, nNodes, nGain; + abctime clk, clkStart = Abc_Clock(); + + // set the DC latch values + Ivy_ManForEachLatch( p, pNode, i ) + pNode->Init = IVY_INIT_DC; + // start the rewriting manager + pManRwt = Rwt_ManStart( 0 ); + p->pData = pManRwt; + if ( pManRwt == NULL ) + return 0; + // create fanouts + if ( p->fFanout == 0 ) + Ivy_ManStartFanout( p ); + // resynthesize each node once + nNodes = Ivy_ManObjIdMax(p); + Ivy_ManForEachNode( p, pNode, i ) + { + assert( !Ivy_ObjIsBuf(pNode) ); + assert( !Ivy_ObjIsBuf(Ivy_ObjFanin0(pNode)) ); + assert( !Ivy_ObjIsBuf(Ivy_ObjFanin1(pNode)) ); + // fix the fanin buffer problem +// Ivy_NodeFixBufferFanins( p, pNode ); +// if ( Ivy_ObjIsBuf(pNode) ) +// continue; + // stop if all nodes have been tried once + if ( i > nNodes ) + break; + // for each cut, try to resynthesize it + nGain = Ivy_NodeRewriteSeq( p, pManRwt, pNode, fUseZeroCost ); + if ( nGain > 0 || (nGain == 0 && fUseZeroCost) ) + { + Dec_Graph_t * pGraph = (Dec_Graph_t *)Rwt_ManReadDecs(pManRwt); + int fCompl = Rwt_ManReadCompl(pManRwt); + // complement the FF if needed +clk = Abc_Clock(); + if ( fCompl ) Dec_GraphComplement( pGraph ); + Ivy_GraphUpdateNetworkSeq( p, pNode, pGraph, nGain ); + if ( fCompl ) Dec_GraphComplement( pGraph ); +Rwt_ManAddTimeUpdate( pManRwt, Abc_Clock() - clk ); + } + } +Rwt_ManAddTimeTotal( pManRwt, Abc_Clock() - clkStart ); + // print stats + if ( fVerbose ) + Rwt_ManPrintStats( pManRwt ); + // delete the managers + Rwt_ManStop( pManRwt ); + p->pData = NULL; + // fix the levels + Ivy_ManResetLevels( p ); +// if ( Ivy_ManCheckFanoutNums(p) ) +// printf( "Ivy_ManRewritePre(): The check has failed.\n" ); + // check + if ( !Ivy_ManCheck(p) ) + printf( "Ivy_ManRewritePre(): The check has failed.\n" ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Performs rewriting for one node.] + + Description [This procedure considers all the cuts computed for the node + and tries to rewrite each of them using the "forest" of different AIG + structures precomputed and stored in the RWR manager. + Determines the best rewriting and computes the gain in the number of AIG + nodes in the final network. In the end, p->vFanins contains information + about the best cut that can be used for rewriting, while p->pGraph gives + the decomposition dag (represented using decomposition graph data structure). + Returns gain in the number of nodes or -1 if node cannot be rewritten.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_NodeRewriteSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pNode, int fUseZeroCost ) +{ + int fVeryVerbose = 0; + Dec_Graph_t * pGraph; + Ivy_Store_t * pStore; + Ivy_Cut_t * pCut; + Ivy_Obj_t * pFanin;//, * pFanout; + Vec_Ptr_t * vFanout; + unsigned uPhase; + unsigned uTruthBest = 0; // Suppress "might be used uninitialized" + unsigned uTruth;//, nNewClauses; + char * pPerm; + int nNodesSaved; + int nNodesSaveCur = -1; // Suppress "might be used uninitialized" + int i, c, GainCur = -1, GainBest = -1; + abctime clk, clk2;//, clk3; + + p->nNodesConsidered++; + // get the node's cuts +clk = Abc_Clock(); + pStore = Ivy_CutComputeForNode( pMan, pNode, 5 ); +p->timeCut += Abc_Clock() - clk; + + // go through the cuts +clk = Abc_Clock(); + vFanout = Vec_PtrAlloc( 100 ); + for ( c = 1; c < pStore->nCuts; c++ ) + { + pCut = pStore->pCuts + c; + // consider only 4-input cuts + if ( pCut->nSize != 4 ) + continue; + // skip the cuts with buffers + for ( i = 0; i < (int)pCut->nSize; i++ ) + if ( Ivy_ObjIsBuf( Ivy_ManObj(pMan, Ivy_LeafId(pCut->pArray[i])) ) ) + break; + if ( i != pCut->nSize ) + { + p->nCutsBad++; + continue; + } + p->nCutsGood++; + // get the fanin permutation +clk2 = Abc_Clock(); + uTruth = 0xFFFF & Ivy_CutGetTruth( pMan, pNode, pCut->pArray, pCut->nSize ); // truth table +p->timeTruth += Abc_Clock() - clk2; + pPerm = p->pPerms4[ (int)p->pPerms[uTruth] ]; + uPhase = p->pPhases[uTruth]; + // collect fanins with the corresponding permutation/phase + Vec_PtrClear( p->vFaninsCur ); + Vec_PtrFill( p->vFaninsCur, (int)pCut->nSize, 0 ); + for ( i = 0; i < (int)pCut->nSize; i++ ) + { + pFanin = Ivy_ManObj( pMan, Ivy_LeafId( pCut->pArray[(int)pPerm[i]] ) ); + assert( Ivy_ObjIsNode(pFanin) || Ivy_ObjIsCi(pFanin) || Ivy_ObjIsConst1(pFanin) ); + pFanin = Ivy_NotCond(pFanin, ((uPhase & (1< 0) ); + Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin ); + } +clk2 = Abc_Clock(); + // mark the fanin boundary + Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFaninsCur, pFanin, i ) + Ivy_ObjRefsInc( Ivy_Regular(pFanin) ); + // label MFFC with current ID + Ivy_ManIncrementTravId( pMan ); + nNodesSaved = Ivy_ObjMffcLabel( pMan, pNode ); + // label fanouts with the current ID +// Ivy_ObjForEachFanout( pMan, pNode, vFanout, pFanout, i ) +// Ivy_ObjSetTravIdCurrent( pMan, pFanout ); + // unmark the fanin boundary + Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFaninsCur, pFanin, i ) + Ivy_ObjRefsDec( Ivy_Regular(pFanin) ); +p->timeMffc += Abc_Clock() - clk2; + + // evaluate the cut +clk2 = Abc_Clock(); + pGraph = Rwt_CutEvaluateSeq( pMan, p, pNode, pCut, pPerm, p->vFaninsCur, nNodesSaved, &GainCur, uTruth ); +p->timeEval += Abc_Clock() - clk2; + + + // check if the cut is better than the current best one + if ( pGraph != NULL && GainBest < GainCur ) + { + // save this form + nNodesSaveCur = nNodesSaved; + GainBest = GainCur; + p->pGraph = pGraph; + p->pCut = pCut; + p->pPerm = pPerm; + p->fCompl = ((uPhase & (1<<4)) > 0); + uTruthBest = uTruth; + // collect fanins in the + Vec_PtrClear( p->vFanins ); + Vec_PtrForEachEntry( Ivy_Obj_t *, p->vFaninsCur, pFanin, i ) + Vec_PtrPush( p->vFanins, pFanin ); + } + } + Vec_PtrFree( vFanout ); +p->timeRes += Abc_Clock() - clk; + + if ( GainBest == -1 ) + return -1; +/* + { + Ivy_Cut_t * pCut = p->pCut; + printf( "Node %5d. Using cut : {", Ivy_ObjId(pNode) ); + for ( i = 0; i < pCut->nSize; i++ ) + printf( " %d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) ); + printf( " }\n" ); + } +*/ + +//clk3 = Abc_Clock(); +//nNewClauses = Ivy_CutTruthPrint( pMan, p->pCut, uTruth ); +//timeInv += Abc_Clock() - clk; + +// nClauses += nNewClauses; +// nMoves++; +// if ( nNewClauses > 0 ) +// nMovesS++; + + // copy the leaves + Ivy_GraphPrepare( (Dec_Graph_t *)p->pGraph, (Ivy_Cut_t *)p->pCut, p->vFanins, p->pPerm ); + + p->nScores[p->pMap[uTruthBest]]++; + p->nNodesGained += GainBest; + if ( fUseZeroCost || GainBest > 0 ) + p->nNodesRewritten++; + +/* + if ( GainBest > 0 ) + { + Ivy_Cut_t * pCut = p->pCut; + printf( "Node %5d. Using cut : {", Ivy_ObjId(pNode) ); + for ( i = 0; i < pCut->nSize; i++ ) + printf( " %5d(%2d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) ); + printf( " }\n" ); + } +*/ + + // report the progress + if ( fVeryVerbose && GainBest > 0 ) + { + printf( "Node %6d : ", Ivy_ObjId(pNode) ); + printf( "Fanins = %d. ", p->vFanins->nSize ); + printf( "Save = %d. ", nNodesSaveCur ); + printf( "Add = %d. ", nNodesSaveCur-GainBest ); + printf( "GAIN = %d. ", GainBest ); + printf( "Cone = %d. ", p->pGraph? Dec_GraphNodeNum((Dec_Graph_t *)p->pGraph) : 0 ); + printf( "Class = %d. ", p->pMap[uTruthBest] ); + printf( "\n" ); + } + return GainBest; +} + + +/**Function************************************************************* + + Synopsis [Evaluates the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Dec_Graph_t * Rwt_CutEvaluateSeq( Ivy_Man_t * pMan, Rwt_Man_t * p, Ivy_Obj_t * pRoot, Ivy_Cut_t * pCut, char * pPerm, Vec_Ptr_t * vFaninsCur, int nNodesSaved, int * pGainBest, unsigned uTruth ) +{ + Vec_Ptr_t * vSubgraphs; + Dec_Graph_t * pGraphBest = NULL; // Suppress "might be used uninitialized" + Dec_Graph_t * pGraphCur; + Rwt_Node_t * pNode; + int nNodesAdded, GainBest, i; + // find the matching class of subgraphs + vSubgraphs = Vec_VecEntry( p->vClasses, p->pMap[uTruth] ); + p->nSubgraphs += vSubgraphs->nSize; + // determine the best subgraph + GainBest = -1; + Vec_PtrForEachEntry( Rwt_Node_t *, vSubgraphs, pNode, i ) + { + // get the current graph + pGraphCur = (Dec_Graph_t *)pNode->pNext; + +// if ( pRoot->Id == 8648 ) +// Dec_GraphPrint( stdout, pGraphCur, NULL, NULL ); + // copy the leaves +// Vec_PtrForEachEntry( Ivy_Obj_t *, vFaninsCur, pFanin, k ) +// Dec_GraphNode(pGraphCur, k)->pFunc = pFanin; + Ivy_GraphPrepare( pGraphCur, pCut, vFaninsCur, pPerm ); + + // detect how many unlabeled nodes will be reused + nNodesAdded = Ivy_GraphToNetworkSeqCountSeq( pMan, pRoot, pGraphCur, nNodesSaved ); + if ( nNodesAdded == -1 ) + continue; + assert( nNodesSaved >= nNodesAdded ); + // count the gain at this node + if ( GainBest < nNodesSaved - nNodesAdded ) + { + GainBest = nNodesSaved - nNodesAdded; + pGraphBest = pGraphCur; + } + } + if ( GainBest == -1 ) + return NULL; + *pGainBest = GainBest; + return pGraphBest; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_GraphPrepare( Dec_Graph_t * pGraph, Ivy_Cut_t * pCut, Vec_Ptr_t * vFanins, char * pPerm ) +{ + Dec_Node_t * pNode, * pNode0, * pNode1; + int i; + assert( Dec_GraphLeaveNum(pGraph) == pCut->nSize ); + assert( Vec_PtrSize(vFanins) == pCut->nSize ); + // label the leaves with latch numbers + Dec_GraphForEachLeaf( pGraph, pNode, i ) + { + pNode->pFunc = Vec_PtrEntry( vFanins, i ); + pNode->nLat2 = Ivy_LeafLat( pCut->pArray[(int)pPerm[i]] ); + } + // propagate latches through the nodes + Dec_GraphForEachNode( pGraph, pNode, i ) + { + // get the children of this node + pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node ); + pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node ); + // distribute the latches + pNode->nLat2 = IVY_MIN( pNode0->nLat2, pNode1->nLat2 ); + pNode->nLat0 = pNode0->nLat2 - pNode->nLat2; + pNode->nLat1 = pNode1->nLat2 - pNode->nLat2; + } +} + +/**Function************************************************************* + + Synopsis [Counts the number of new nodes added when using this graph.] + + Description [AIG nodes for the fanins should be assigned to pNode->pFunc + of the leaves of the graph before calling this procedure. + Returns -1 if the number of nodes and levels exceeded the given limit or + the number of levels exceeded the maximum allowed level.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_GraphToNetworkSeqCountSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax ) +{ + Dec_Node_t * pNode, * pNode0, * pNode1; + Ivy_Obj_t * pAnd, * pAnd0, * pAnd1; + int i, k, Counter, fCompl; + // check for constant function or a literal + if ( Dec_GraphIsConst(pGraph) || Dec_GraphIsVar(pGraph) ) + return 0; + // compute the AIG size after adding the internal nodes + Counter = 0; + Dec_GraphForEachNode( pGraph, pNode, i ) + { + // get the children of this node + pNode0 = Dec_GraphNode( pGraph, pNode->eEdge0.Node ); + pNode1 = Dec_GraphNode( pGraph, pNode->eEdge1.Node ); + // get the AIG nodes corresponding to the children + pAnd0 = (Ivy_Obj_t *)pNode0->pFunc; + pAnd1 = (Ivy_Obj_t *)pNode1->pFunc; + // skip the latches + for ( k = 0; pAnd0 && k < (int)pNode->nLat0; k++ ) + { + fCompl = Ivy_IsComplement(pAnd0); + pAnd0 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Regular(pAnd0), NULL, IVY_LATCH, IVY_INIT_DC) ); + if ( pAnd0 ) + pAnd0 = Ivy_NotCond( pAnd0, fCompl ); + } + for ( k = 0; pAnd1 && k < (int)pNode->nLat1; k++ ) + { + fCompl = Ivy_IsComplement(pAnd1); + pAnd1 = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, Ivy_Regular(pAnd1), NULL, IVY_LATCH, IVY_INIT_DC) ); + if ( pAnd1 ) + pAnd1 = Ivy_NotCond( pAnd1, fCompl ); + } + // get the new node + if ( pAnd0 && pAnd1 ) + { + // if they are both present, find the resulting node + pAnd0 = Ivy_NotCond( pAnd0, pNode->eEdge0.fCompl ); + pAnd1 = Ivy_NotCond( pAnd1, pNode->eEdge1.fCompl ); + assert( !Ivy_ObjIsLatch(Ivy_Regular(pAnd0)) || !Ivy_ObjIsLatch(Ivy_Regular(pAnd1)) ); + if ( Ivy_Regular(pAnd0) == Ivy_Regular(pAnd1) || Ivy_ObjIsConst1(Ivy_Regular(pAnd0)) || Ivy_ObjIsConst1(Ivy_Regular(pAnd1)) ) + pAnd = Ivy_And( p, pAnd0, pAnd1 ); + else + pAnd = Ivy_TableLookup( p, Ivy_ObjCreateGhost(p, pAnd0, pAnd1, IVY_AND, IVY_INIT_NONE) ); + // return -1 if the node is the same as the original root + if ( Ivy_Regular(pAnd) == pRoot ) + return -1; + } + else + pAnd = NULL; + // count the number of added nodes + if ( pAnd == NULL || Ivy_ObjIsTravIdCurrent(p, Ivy_Regular(pAnd)) ) + { + if ( ++Counter > NodeMax ) + return -1; + } + pNode->pFunc = pAnd; + } + return Counter; +} + + +/**Function************************************************************* + + Synopsis [Transforms the decomposition graph into the AIG.] + + Description [AIG nodes for the fanins should be assigned to pNode->pFunc + of the leaves of the graph before calling this procedure.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_GraphToNetworkSeq( Ivy_Man_t * p, Dec_Graph_t * pGraph ) +{ + Ivy_Obj_t * pAnd0, * pAnd1; + Dec_Node_t * pNode = NULL; // Suppress "might be used uninitialized" + int i, k; + // check for constant function + if ( Dec_GraphIsConst(pGraph) ) + return Ivy_NotCond( Ivy_ManConst1(p), Dec_GraphIsComplement(pGraph) ); + // check for a literal + if ( Dec_GraphIsVar(pGraph) ) + { + // get the variable node + pNode = Dec_GraphVar(pGraph); + // add the remaining latches + for ( k = 0; k < (int)pNode->nLat2; k++ ) + pNode->pFunc = Ivy_Latch( p, (Ivy_Obj_t *)pNode->pFunc, IVY_INIT_DC ); + return Ivy_NotCond( (Ivy_Obj_t *)pNode->pFunc, Dec_GraphIsComplement(pGraph) ); + } + // build the AIG nodes corresponding to the AND gates of the graph + Dec_GraphForEachNode( pGraph, pNode, i ) + { + pAnd0 = Ivy_NotCond( (Ivy_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl ); + pAnd1 = Ivy_NotCond( (Ivy_Obj_t *)Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl ); + // add the latches + for ( k = 0; k < (int)pNode->nLat0; k++ ) + pAnd0 = Ivy_Latch( p, pAnd0, IVY_INIT_DC ); + for ( k = 0; k < (int)pNode->nLat1; k++ ) + pAnd1 = Ivy_Latch( p, pAnd1, IVY_INIT_DC ); + // create the node + pNode->pFunc = Ivy_And( p, pAnd0, pAnd1 ); + } + // add the remaining latches + for ( k = 0; k < (int)pNode->nLat2; k++ ) + pNode->pFunc = Ivy_Latch( p, (Ivy_Obj_t *)pNode->pFunc, IVY_INIT_DC ); + // complement the result if necessary + return Ivy_NotCond( (Ivy_Obj_t *)pNode->pFunc, Dec_GraphIsComplement(pGraph) ); +} + +/**Function************************************************************* + + Synopsis [Replaces MFFC of the node by the new factored form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_GraphUpdateNetworkSeq( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Dec_Graph_t * pGraph, int nGain ) +{ + Ivy_Obj_t * pRootNew; + int nNodesNew, nNodesOld; + nNodesOld = Ivy_ManNodeNum(p); + // create the new structure of nodes + pRootNew = Ivy_GraphToNetworkSeq( p, pGraph ); + Ivy_ObjReplace( p, pRoot, pRootNew, 1, 0, 0 ); + // compare the gains + nNodesNew = Ivy_ManNodeNum(p); + assert( nGain <= nNodesOld - nNodesNew ); + // propagate the buffer + Ivy_ManPropagateBuffers( p, 0 ); +} + + + + + + + + + +/**Function************************************************************* + + Synopsis [Computes the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Ivy_CutGetTruth_rec( Ivy_Man_t * p, int Leaf, int * pNums, int nNums ) +{ + static unsigned uMasks[5] = { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000 }; + unsigned uTruth0, uTruth1; + Ivy_Obj_t * pObj; + int i; + for ( i = 0; i < nNums; i++ ) + if ( Leaf == pNums[i] ) + return uMasks[i]; + pObj = Ivy_ManObj( p, Ivy_LeafId(Leaf) ); + if ( Ivy_ObjIsLatch(pObj) ) + { + assert( !Ivy_ObjFaninC0(pObj) ); + Leaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pObj), Ivy_LeafLat(Leaf) + 1 ); + return Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums ); + } + assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); + Leaf = Ivy_LeafCreate( Ivy_ObjFaninId0(pObj), Ivy_LeafLat(Leaf) ); + uTruth0 = Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums ); + if ( Ivy_ObjFaninC0(pObj) ) + uTruth0 = ~uTruth0; + if ( Ivy_ObjIsBuf(pObj) ) + return uTruth0; + Leaf = Ivy_LeafCreate( Ivy_ObjFaninId1(pObj), Ivy_LeafLat(Leaf) ); + uTruth1 = Ivy_CutGetTruth_rec( p, Leaf, pNums, nNums ); + if ( Ivy_ObjFaninC1(pObj) ) + uTruth1 = ~uTruth1; + return uTruth0 & uTruth1; +} + + +/**Function************************************************************* + + Synopsis [Computes the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Ivy_CutGetTruth( Ivy_Man_t * p, Ivy_Obj_t * pObj, int * pNums, int nNums ) +{ + assert( Ivy_ObjIsNode(pObj) ); + assert( nNums < 6 ); + return Ivy_CutGetTruth_rec( p, Ivy_LeafCreate(pObj->Id, 0), pNums, nNums ); +} + + + + + +/**Function************************************************************* + + Synopsis [Returns 1 if the cut can be constructed; 0 otherwise.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_CutPrescreen( Ivy_Cut_t * pCut, int Id0, int Id1 ) +{ + int i; + if ( pCut->nSize < pCut->nSizeMax ) + return 1; + for ( i = 0; i < pCut->nSize; i++ ) + if ( pCut->pArray[i] == Id0 || pCut->pArray[i] == Id1 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Derives new cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_CutDeriveNew2( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 ) +{ + unsigned uHash = 0; + int i, k; + assert( pCut->nSize > 0 ); + assert( IdNew0 < IdNew1 ); + for ( i = k = 0; i < pCut->nSize; i++ ) + { + if ( pCut->pArray[i] == IdOld ) + continue; + if ( IdNew0 >= 0 ) + { + if ( IdNew0 <= pCut->pArray[i] ) + { + if ( IdNew0 < pCut->pArray[i] ) + { + if ( k == pCut->nSizeMax ) + return 0; + pCutNew->pArray[ k++ ] = IdNew0; + uHash |= Ivy_CutHashValue( IdNew0 ); + } + IdNew0 = -1; + } + } + if ( IdNew1 >= 0 ) + { + if ( IdNew1 <= pCut->pArray[i] ) + { + if ( IdNew1 < pCut->pArray[i] ) + { + if ( k == pCut->nSizeMax ) + return 0; + pCutNew->pArray[ k++ ] = IdNew1; + uHash |= Ivy_CutHashValue( IdNew1 ); + } + IdNew1 = -1; + } + } + if ( k == pCut->nSizeMax ) + return 0; + pCutNew->pArray[ k++ ] = pCut->pArray[i]; + uHash |= Ivy_CutHashValue( pCut->pArray[i] ); + } + if ( IdNew0 >= 0 ) + { + if ( k == pCut->nSizeMax ) + return 0; + pCutNew->pArray[ k++ ] = IdNew0; + uHash |= Ivy_CutHashValue( IdNew0 ); + } + if ( IdNew1 >= 0 ) + { + if ( k == pCut->nSizeMax ) + return 0; + pCutNew->pArray[ k++ ] = IdNew1; + uHash |= Ivy_CutHashValue( IdNew1 ); + } + pCutNew->nSize = k; + pCutNew->uHash = uHash; + assert( pCutNew->nSize <= pCut->nSizeMax ); + for ( i = 1; i < pCutNew->nSize; i++ ) + assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Derives new cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_CutDeriveNew( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 ) +{ + unsigned uHash = 0; + int i, k; + assert( pCut->nSize > 0 ); + assert( IdNew0 < IdNew1 ); + for ( i = k = 0; i < pCut->nSize; i++ ) + { + if ( pCut->pArray[i] == IdOld ) + continue; + if ( IdNew0 <= pCut->pArray[i] ) + { + if ( IdNew0 < pCut->pArray[i] ) + { + pCutNew->pArray[ k++ ] = IdNew0; + uHash |= Ivy_CutHashValue( IdNew0 ); + } + IdNew0 = 0x7FFFFFFF; + } + if ( IdNew1 <= pCut->pArray[i] ) + { + if ( IdNew1 < pCut->pArray[i] ) + { + pCutNew->pArray[ k++ ] = IdNew1; + uHash |= Ivy_CutHashValue( IdNew1 ); + } + IdNew1 = 0x7FFFFFFF; + } + pCutNew->pArray[ k++ ] = pCut->pArray[i]; + uHash |= Ivy_CutHashValue( pCut->pArray[i] ); + } + if ( IdNew0 < 0x7FFFFFFF ) + { + pCutNew->pArray[ k++ ] = IdNew0; + uHash |= Ivy_CutHashValue( IdNew0 ); + } + if ( IdNew1 < 0x7FFFFFFF ) + { + pCutNew->pArray[ k++ ] = IdNew1; + uHash |= Ivy_CutHashValue( IdNew1 ); + } + pCutNew->nSize = k; + pCutNew->uHash = uHash; + assert( pCutNew->nSize <= pCut->nSizeMax ); +// for ( i = 1; i < pCutNew->nSize; i++ ) +// assert( pCutNew->pArray[i-1] < pCutNew->pArray[i] ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Find the hash value of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Ivy_NodeCutHash( Ivy_Cut_t * pCut ) +{ + int i; + pCut->uHash = 0; + for ( i = 0; i < pCut->nSize; i++ ) + pCut->uHash |= (1 << (pCut->pArray[i] % 31)); + return pCut->uHash; +} + +/**Function************************************************************* + + Synopsis [Derives new cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_CutDeriveNew3( Ivy_Cut_t * pCut, Ivy_Cut_t * pCutNew, int IdOld, int IdNew0, int IdNew1 ) +{ + int i, k; + assert( pCut->nSize > 0 ); + assert( IdNew0 < IdNew1 ); + for ( i = k = 0; i < pCut->nSize; i++ ) + { + if ( pCut->pArray[i] == IdOld ) + continue; + if ( IdNew0 <= pCut->pArray[i] ) + { + if ( IdNew0 < pCut->pArray[i] ) + pCutNew->pArray[ k++ ] = IdNew0; + IdNew0 = 0x7FFFFFFF; + } + if ( IdNew1 <= pCut->pArray[i] ) + { + if ( IdNew1 < pCut->pArray[i] ) + pCutNew->pArray[ k++ ] = IdNew1; + IdNew1 = 0x7FFFFFFF; + } + pCutNew->pArray[ k++ ] = pCut->pArray[i]; + } + if ( IdNew0 < 0x7FFFFFFF ) + pCutNew->pArray[ k++ ] = IdNew0; + if ( IdNew1 < 0x7FFFFFFF ) + pCutNew->pArray[ k++ ] = IdNew1; + pCutNew->nSize = k; + assert( pCutNew->nSize <= pCut->nSizeMax ); + Ivy_NodeCutHash( pCutNew ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if pDom is contained in pCut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_CutCheckDominance( Ivy_Cut_t * pDom, Ivy_Cut_t * pCut ) +{ + int i, k; + for ( i = 0; i < pDom->nSize; i++ ) + { + assert( i==0 || pDom->pArray[i-1] < pDom->pArray[i] ); + for ( k = 0; k < pCut->nSize; k++ ) + if ( pDom->pArray[i] == pCut->pArray[k] ) + break; + if ( k == pCut->nSize ) // node i in pDom is not contained in pCut + return 0; + } + // every node in pDom is contained in pCut + return 1; +} + +/**Function************************************************************* + + Synopsis [Check if the cut exists.] + + Description [Returns 1 if the cut exists.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_CutFindOrAddFilter( Ivy_Store_t * pCutStore, Ivy_Cut_t * pCutNew ) +{ + Ivy_Cut_t * pCut; + int i, k; + assert( pCutNew->uHash ); + // try to find the cut + for ( i = 0; i < pCutStore->nCuts; i++ ) + { + pCut = pCutStore->pCuts + i; + if ( pCut->nSize == 0 ) + continue; + if ( pCut->nSize == pCutNew->nSize ) + { + if ( pCut->uHash == pCutNew->uHash ) + { + for ( k = 0; k < pCutNew->nSize; k++ ) + if ( pCut->pArray[k] != pCutNew->pArray[k] ) + break; + if ( k == pCutNew->nSize ) + return 1; + } + continue; + } + if ( pCut->nSize < pCutNew->nSize ) + { + // skip the non-contained cuts + if ( (pCut->uHash & pCutNew->uHash) != pCut->uHash ) + continue; + // check containment seriously + if ( Ivy_CutCheckDominance( pCut, pCutNew ) ) + return 1; + continue; + } + // check potential containment of other cut + + // skip the non-contained cuts + if ( (pCut->uHash & pCutNew->uHash) != pCutNew->uHash ) + continue; + // check containment seriously + if ( Ivy_CutCheckDominance( pCutNew, pCut ) ) + { + // remove the current cut + pCut->nSize = 0; + } + } + assert( pCutStore->nCuts < pCutStore->nCutsMax ); + // add the cut + pCut = pCutStore->pCuts + pCutStore->nCuts++; + *pCut = *pCutNew; + return 0; +} + +/**Function************************************************************* + + Synopsis [Compresses the cut representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_CutCompactAll( Ivy_Store_t * pCutStore ) +{ + Ivy_Cut_t * pCut; + int i, k; + pCutStore->nCutsM = 0; + for ( i = k = 0; i < pCutStore->nCuts; i++ ) + { + pCut = pCutStore->pCuts + i; + if ( pCut->nSize == 0 ) + continue; + if ( pCut->nSize < pCut->nSizeMax ) + pCutStore->nCutsM++; + pCutStore->pCuts[k++] = *pCut; + } + pCutStore->nCuts = k; +} + +/**Function************************************************************* + + Synopsis [Print the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_CutPrintForNode( Ivy_Cut_t * pCut ) +{ + int i; + assert( pCut->nSize > 0 ); + printf( "%d : {", pCut->nSize ); + for ( i = 0; i < pCut->nSize; i++ ) + printf( " %d", pCut->pArray[i] ); + printf( " }\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_CutPrintForNodes( Ivy_Store_t * pCutStore ) +{ + int i; + printf( "Node %d\n", pCutStore->pCuts[0].pArray[0] ); + for ( i = 0; i < pCutStore->nCuts; i++ ) + Ivy_CutPrintForNode( pCutStore->pCuts + i ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Ivy_CutReadLeaf( Ivy_Obj_t * pFanin ) +{ + int nLats, iLeaf; + assert( !Ivy_IsComplement(pFanin) ); + if ( !Ivy_ObjIsLatch(pFanin) ) + return Ivy_LeafCreate( pFanin->Id, 0 ); + iLeaf = Ivy_CutReadLeaf(Ivy_ObjFanin0(pFanin)); + nLats = Ivy_LeafLat(iLeaf); + assert( nLats < IVY_LEAF_MASK ); + return 1 + iLeaf; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Store_t * Ivy_CutComputeForNode( Ivy_Man_t * p, Ivy_Obj_t * pObj, int nLeaves ) +{ + static Ivy_Store_t CutStore, * pCutStore = &CutStore; + Ivy_Cut_t CutNew, * pCutNew = &CutNew, * pCut; + Ivy_Obj_t * pLeaf; + int i, k, Temp, nLats, iLeaf0, iLeaf1; + + assert( nLeaves <= IVY_CUT_INPUT ); + + // start the structure + pCutStore->nCuts = 0; + pCutStore->nCutsMax = IVY_CUT_LIMIT; + // start the trivial cut + pCutNew->uHash = 0; + pCutNew->nSize = 1; + pCutNew->nSizeMax = nLeaves; + pCutNew->pArray[0] = Ivy_LeafCreate( pObj->Id, 0 ); + pCutNew->uHash = Ivy_CutHashValue( pCutNew->pArray[0] ); + // add the trivial cut + pCutStore->pCuts[pCutStore->nCuts++] = *pCutNew; + assert( pCutStore->nCuts == 1 ); + + // explore the cuts + for ( i = 0; i < pCutStore->nCuts; i++ ) + { + // expand this cut + pCut = pCutStore->pCuts + i; + if ( pCut->nSize == 0 ) + continue; + for ( k = 0; k < pCut->nSize; k++ ) + { + pLeaf = Ivy_ManObj( p, Ivy_LeafId(pCut->pArray[k]) ); + if ( Ivy_ObjIsCi(pLeaf) || Ivy_ObjIsConst1(pLeaf) ) + continue; + assert( Ivy_ObjIsNode(pLeaf) ); + nLats = Ivy_LeafLat(pCut->pArray[k]); + + // get the fanins fanins + iLeaf0 = Ivy_CutReadLeaf( Ivy_ObjFanin0(pLeaf) ); + iLeaf1 = Ivy_CutReadLeaf( Ivy_ObjFanin1(pLeaf) ); + assert( nLats + Ivy_LeafLat(iLeaf0) < IVY_LEAF_MASK && nLats + Ivy_LeafLat(iLeaf1) < IVY_LEAF_MASK ); + iLeaf0 = nLats + iLeaf0; + iLeaf1 = nLats + iLeaf1; + if ( !Ivy_CutPrescreen( pCut, iLeaf0, iLeaf1 ) ) + continue; + // the given cut exist + if ( iLeaf0 > iLeaf1 ) + Temp = iLeaf0, iLeaf0 = iLeaf1, iLeaf1 = Temp; + // create the new cut + if ( !Ivy_CutDeriveNew( pCut, pCutNew, pCut->pArray[k], iLeaf0, iLeaf1 ) ) + continue; + // add the cut + Ivy_CutFindOrAddFilter( pCutStore, pCutNew ); + if ( pCutStore->nCuts == IVY_CUT_LIMIT ) + break; + } + if ( pCutStore->nCuts == IVY_CUT_LIMIT ) + break; + } + if ( pCutStore->nCuts == IVY_CUT_LIMIT ) + pCutStore->fSatur = 1; + else + pCutStore->fSatur = 0; +// printf( "%d ", pCutStore->nCuts ); + Ivy_CutCompactAll( pCutStore ); +// printf( "%d \n", pCutStore->nCuts ); +// Ivy_CutPrintForNodes( pCutStore ); + return pCutStore; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_CutComputeAll( Ivy_Man_t * p, int nInputs ) +{ + Ivy_Store_t * pStore; + Ivy_Obj_t * pObj; + int i, nCutsTotal, nCutsTotalM, nNodeTotal, nNodeOver; + abctime clk = Abc_Clock(); + if ( nInputs > IVY_CUT_INPUT ) + { + printf( "Cannot compute cuts for more than %d inputs.\n", IVY_CUT_INPUT ); + return; + } + nNodeTotal = nNodeOver = 0; + nCutsTotal = nCutsTotalM = -Ivy_ManNodeNum(p); + Ivy_ManForEachObj( p, pObj, i ) + { + if ( !Ivy_ObjIsNode(pObj) ) + continue; + pStore = Ivy_CutComputeForNode( p, pObj, nInputs ); + nCutsTotal += pStore->nCuts; + nCutsTotalM += pStore->nCutsM; + nNodeOver += pStore->fSatur; + nNodeTotal++; + } + printf( "All = %6d. Minus = %6d. Triv = %6d. Node = %6d. Satur = %6d. ", + nCutsTotal, nCutsTotalM, Ivy_ManPiNum(p) + Ivy_ManNodeNum(p), nNodeTotal, nNodeOver ); + ABC_PRT( "Time", Abc_Clock() - clk ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/ivyShow.c b/yosys/abc/src/aig/ivy/ivyShow.c new file mode 100644 index 00000000000..3b8c7cc0a74 --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivyShow.c @@ -0,0 +1,343 @@ +/**CFile**************************************************************** + + FileName [ivyShow.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Visualization of HAIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyShow.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Ivy_WriteDotAig( Ivy_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManShow( Ivy_Man_t * pMan, int fHaig, Vec_Ptr_t * vBold ) +{ + extern void Abc_ShowFile( char * FileNameDot, int fKeepDot ); + static int Counter = 0; + char FileNameDot[200]; + FILE * pFile; + // create the file name +// Ivy_ShowGetFileName( pMan->pName, FileNameDot ); + sprintf( FileNameDot, "temp%02d.dot", Counter++ ); + // check that the file can be opened + if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); + return; + } + fclose( pFile ); + // generate the file + Ivy_WriteDotAig( pMan, FileNameDot, fHaig, vBold ); + // visualize the file + Abc_ShowFile( FileNameDot, 0 ); +} + +/**Function************************************************************* + + Synopsis [Writes the graph structure of AIG for DOT.] + + Description [Useful for graph visualization using tools such as GraphViz: + http://www.graphviz.org/] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_WriteDotAig( Ivy_Man_t * pMan, char * pFileName, int fHaig, Vec_Ptr_t * vBold ) +{ + FILE * pFile; + Ivy_Obj_t * pNode, * pTemp, * pPrev; + int LevelMax, Level, i; + + if ( Ivy_ManNodeNum(pMan) > 200 ) + { + fprintf( stdout, "Cannot visualize AIG with more than 200 nodes.\n" ); + return; + } + if ( (pFile = fopen( pFileName, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); + return; + } + + // mark the nodes + if ( vBold ) + Vec_PtrForEachEntry( Ivy_Obj_t *, vBold, pNode, i ) + pNode->fMarkB = 1; + + // compute levels + LevelMax = 1 + Ivy_ManSetLevels( pMan, fHaig ); + + // write the DOT header + fprintf( pFile, "# %s\n", "AIG structure generated by IVY package" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "digraph AIG {\n" ); + fprintf( pFile, "size = \"7.5,10\";\n" ); +// fprintf( pFile, "ranksep = 0.5;\n" ); +// fprintf( pFile, "nodesep = 0.5;\n" ); + fprintf( pFile, "center = true;\n" ); +// fprintf( pFile, "orientation = landscape;\n" ); +// fprintf( pFile, "edge [fontsize = 10];\n" ); +// fprintf( pFile, "edge [dir = none];\n" ); + fprintf( pFile, "edge [dir = back];\n" ); + fprintf( pFile, "\n" ); + + // labels on the left of the picture + fprintf( pFile, "{\n" ); + fprintf( pFile, " node [shape = plaintext];\n" ); + fprintf( pFile, " edge [style = invis];\n" ); + fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); + fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); + // generate node names with labels + for ( Level = LevelMax; Level >= 0; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + fprintf( pFile, " [label = " ); + // label name + fprintf( pFile, "\"" ); + fprintf( pFile, "\"" ); + fprintf( pFile, "];\n" ); + } + + // genetate the sequence of visible/invisible nodes to mark levels + fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); + for ( Level = LevelMax; Level >= 0; Level-- ) + { + // the visible node name + fprintf( pFile, " Level%d", Level ); + // the connector + if ( Level != 0 ) + fprintf( pFile, " ->" ); + else + fprintf( pFile, ";" ); + } + fprintf( pFile, "\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate title box on top + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle1;\n" ); + fprintf( pFile, " title1 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=20,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + fprintf( pFile, "%s", "AIG structure visualized by ABC" ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "Benchmark \\\"%s\\\". ", "aig" ); + fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate statistics box + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + fprintf( pFile, " LevelTitle2;\n" ); + fprintf( pFile, " title2 [shape=plaintext,\n" ); + fprintf( pFile, " fontsize=18,\n" ); + fprintf( pFile, " fontname = \"Times-Roman\",\n" ); + fprintf( pFile, " label=\"" ); + fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Ivy_ManNodeNum(pMan), LevelMax ); + fprintf( pFile, "\\n" ); + fprintf( pFile, "\"\n" ); + fprintf( pFile, " ];\n" ); + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate the COs + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", LevelMax ); + // generate the CO nodes + Ivy_ManForEachCo( pMan, pNode, i ) + { + if ( fHaig || pNode->pEquiv == NULL ) + fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id, + (Ivy_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") ); + else + fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, + (Ivy_ObjIsLatch(pNode)? "_in":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":""), + Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" ); + fprintf( pFile, ", shape = %s", (Ivy_ObjIsLatch(pNode)? "box":"invtriangle") ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate nodes of each rank + for ( Level = LevelMax - 1; Level > 0; Level-- ) + { + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", Level ); + Ivy_ManForEachObj( pMan, pNode, i ) + { + if ( (int)pNode->Level != Level ) + continue; + if ( fHaig || pNode->pEquiv == NULL ) + fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); + else + fprintf( pFile, " Node%d [label = \"%d(%d%s)\"", pNode->Id, pNode->Id, + Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" ); + fprintf( pFile, ", shape = ellipse" ); + if ( vBold && pNode->fMarkB ) + fprintf( pFile, ", style = filled" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + } + + // generate the CI nodes + fprintf( pFile, "{\n" ); + fprintf( pFile, " rank = same;\n" ); + // the labeling node of this level + fprintf( pFile, " Level%d;\n", 0 ); + // generate constant node + if ( Ivy_ObjRefs(Ivy_ManConst1(pMan)) > 0 ) + { + pNode = Ivy_ManConst1(pMan); + // check if the costant node is present + fprintf( pFile, " Node%d [label = \"Const1\"", pNode->Id ); + fprintf( pFile, ", shape = ellipse" ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + // generate the CI nodes + Ivy_ManForEachCi( pMan, pNode, i ) + { + if ( fHaig || pNode->pEquiv == NULL ) + fprintf( pFile, " Node%d%s [label = \"%d%s\"", pNode->Id, + (Ivy_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_out":"") ); + else + fprintf( pFile, " Node%d%s [label = \"%d%s(%d%s)\"", pNode->Id, + (Ivy_ObjIsLatch(pNode)? "_out":""), pNode->Id, (Ivy_ObjIsLatch(pNode)? "_out":""), + Ivy_Regular(pNode->pEquiv)->Id, Ivy_IsComplement(pNode->pEquiv)? "\'":"" ); + fprintf( pFile, ", shape = %s", (Ivy_ObjIsLatch(pNode)? "box":"triangle") ); + fprintf( pFile, ", color = coral, fillcolor = coral" ); + fprintf( pFile, "];\n" ); + } + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + + // generate invisible edges from the square down + fprintf( pFile, "title1 -> title2 [style = invis];\n" ); + Ivy_ManForEachCo( pMan, pNode, i ) + fprintf( pFile, "title2 -> Node%d%s [style = invis];\n", pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") ); + + // generate edges + Ivy_ManForEachObj( pMan, pNode, i ) + { + if ( !Ivy_ObjIsNode(pNode) && !Ivy_ObjIsCo(pNode) && !Ivy_ObjIsBuf(pNode) ) + continue; + // generate the edge from this node to the next + fprintf( pFile, "Node%d%s", pNode->Id, (Ivy_ObjIsLatch(pNode)? "_in":"") ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d%s", Ivy_ObjFaninId0(pNode), (Ivy_ObjIsLatch(Ivy_ObjFanin0(pNode))? "_out":"") ); + fprintf( pFile, " [" ); + fprintf( pFile, "style = %s", Ivy_ObjFaninC0(pNode)? "dotted" : "bold" ); +// if ( Ivy_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL0(pNode) > 0 ) +// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,0) ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + if ( !Ivy_ObjIsNode(pNode) ) + continue; + // generate the edge from this node to the next + fprintf( pFile, "Node%d", pNode->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d%s", Ivy_ObjFaninId1(pNode), (Ivy_ObjIsLatch(Ivy_ObjFanin1(pNode))? "_out":"") ); + fprintf( pFile, " [" ); + fprintf( pFile, "style = %s", Ivy_ObjFaninC1(pNode)? "dotted" : "bold" ); +// if ( Ivy_NtkIsSeq(pNode->pMan) && Seq_ObjFaninL1(pNode) > 0 ) +// fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,1) ); + fprintf( pFile, "]" ); + fprintf( pFile, ";\n" ); + // generate the edges between the equivalent nodes + if ( fHaig && pNode->pEquiv && Ivy_ObjRefs(pNode) > 0 ) + { + pPrev = pNode; + for ( pTemp = pNode->pEquiv; pTemp != pNode; pTemp = Ivy_Regular(pTemp->pEquiv) ) + { + fprintf( pFile, "Node%d", pPrev->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", pTemp->Id ); + fprintf( pFile, " [style = %s]", Ivy_IsComplement(pTemp->pEquiv)? "dotted" : "bold" ); + fprintf( pFile, ";\n" ); + pPrev = pTemp; + } + // connect the last node with the first + fprintf( pFile, "Node%d", pPrev->Id ); + fprintf( pFile, " -> " ); + fprintf( pFile, "Node%d", pNode->Id ); + fprintf( pFile, " [style = %s]", Ivy_IsComplement(pPrev->pEquiv)? "dotted" : "bold" ); + fprintf( pFile, ";\n" ); + } + } + + fprintf( pFile, "}" ); + fprintf( pFile, "\n" ); + fprintf( pFile, "\n" ); + fclose( pFile ); + + // unmark nodes + if ( vBold ) + Vec_PtrForEachEntry( Ivy_Obj_t *, vBold, pNode, i ) + pNode->fMarkB = 0; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/ivyTable.c b/yosys/abc/src/aig/ivy/ivyTable.c new file mode 100644 index 00000000000..7d8590d86d8 --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivyTable.c @@ -0,0 +1,272 @@ +/**CFile**************************************************************** + + FileName [ivyTable.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Structural hashing table.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006. ] + + Revision [$Id: ivyTable.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// hashing the node +static unsigned Ivy_Hash( Ivy_Obj_t * pObj, int TableSize ) +{ + unsigned Key = Ivy_ObjIsExor(pObj) * 1699; + Key ^= Ivy_ObjFaninId0(pObj) * 7937; + Key ^= Ivy_ObjFaninId1(pObj) * 2971; + Key ^= Ivy_ObjFaninC0(pObj) * 911; + Key ^= Ivy_ObjFaninC1(pObj) * 353; + Key ^= Ivy_ObjInit(pObj) * 911; + return Key % TableSize; +} + +// returns the place where this node is stored (or should be stored) +static int * Ivy_TableFind( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + int i; + assert( Ivy_ObjIsHash(pObj) ); + for ( i = Ivy_Hash(pObj, p->nTableSize); p->pTable[i]; i = (i+1) % p->nTableSize ) + if ( p->pTable[i] == pObj->Id ) + break; + return p->pTable + i; +} + +static void Ivy_TableResize( Ivy_Man_t * p ); +static unsigned int Cudd_PrimeAig( unsigned int p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks if node with the given attributes is in the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_TableLookup( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pEntry; + int i; + assert( !Ivy_IsComplement(pObj) ); + if ( !Ivy_ObjIsHash(pObj) ) + return NULL; + assert( Ivy_ObjIsLatch(pObj) || Ivy_ObjFaninId0(pObj) > 0 ); + assert( Ivy_ObjFaninId1(pObj) == 0 || Ivy_ObjFaninId0(pObj) < Ivy_ObjFaninId1(pObj) ); + if ( Ivy_ObjFanin0(pObj)->nRefs == 0 || (Ivy_ObjChild1(pObj) && Ivy_ObjFanin1(pObj)->nRefs == 0) ) + return NULL; + for ( i = Ivy_Hash(pObj, p->nTableSize); p->pTable[i]; i = (i+1) % p->nTableSize ) + { + pEntry = Ivy_ManObj( p, p->pTable[i] ); + if ( Ivy_ObjChild0(pEntry) == Ivy_ObjChild0(pObj) && + Ivy_ObjChild1(pEntry) == Ivy_ObjChild1(pObj) && + Ivy_ObjInit(pEntry) == Ivy_ObjInit(pObj) && + Ivy_ObjType(pEntry) == Ivy_ObjType(pObj) ) + return pEntry; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Adds the node to the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TableInsert( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + int * pPlace; + assert( !Ivy_IsComplement(pObj) ); + if ( !Ivy_ObjIsHash(pObj) ) + return; + if ( (pObj->Id & 63) == 0 ) + { + if ( p->nTableSize < 2 * Ivy_ManHashObjNum(p) ) + Ivy_TableResize( p ); + } + pPlace = Ivy_TableFind( p, pObj ); + assert( *pPlace == 0 ); + *pPlace = pObj->Id; +} + +/**Function************************************************************* + + Synopsis [Deletes the node from the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TableDelete( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pEntry; + int i, * pPlace; + assert( !Ivy_IsComplement(pObj) ); + if ( !Ivy_ObjIsHash(pObj) ) + return; + pPlace = Ivy_TableFind( p, pObj ); + assert( *pPlace == pObj->Id ); // node should be in the table + *pPlace = 0; + // rehash the adjacent entries + i = pPlace - p->pTable; + for ( i = (i+1) % p->nTableSize; p->pTable[i]; i = (i+1) % p->nTableSize ) + { + pEntry = Ivy_ManObj( p, p->pTable[i] ); + p->pTable[i] = 0; + Ivy_TableInsert( p, pEntry ); + } +} + +/**Function************************************************************* + + Synopsis [Updates the table to point to the new node.] + + Description [If the old node (pObj) is in the table, updates the table + to point to an object with different ID (ObjIdNew). The table should + not contain an object with ObjIdNew (this is currently not checked).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TableUpdate( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ObjIdNew ) +{ + int * pPlace; + assert( !Ivy_IsComplement(pObj) ); + if ( !Ivy_ObjIsHash(pObj) ) + return; + pPlace = Ivy_TableFind( p, pObj ); + assert( *pPlace == pObj->Id ); // node should be in the table + *pPlace = ObjIdNew; +} + +/**Function************************************************************* + + Synopsis [Count the number of nodes in the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_TableCountEntries( Ivy_Man_t * p ) +{ + int i, Counter = 0; + for ( i = 0; i < p->nTableSize; i++ ) + Counter += (p->pTable[i] != 0); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Resizes the table.] + + Description [Typically this procedure should not be called.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_TableResize( Ivy_Man_t * p ) +{ + int * pTableOld, * pPlace; + int nTableSizeOld, Counter, nEntries, e; + abctime clk; +clk = Abc_Clock(); + // save the old table + pTableOld = p->pTable; + nTableSizeOld = p->nTableSize; + // get the new table + p->nTableSize = Abc_PrimeCudd( 5 * Ivy_ManHashObjNum(p) ); + p->pTable = ABC_ALLOC( int, p->nTableSize ); + memset( p->pTable, 0, sizeof(int) * p->nTableSize ); + // rehash the entries from the old table + Counter = 0; + for ( e = 0; e < nTableSizeOld; e++ ) + { + if ( pTableOld[e] == 0 ) + continue; + Counter++; + // get the place where this entry goes in the table table + pPlace = Ivy_TableFind( p, Ivy_ManObj(p, pTableOld[e]) ); + assert( *pPlace == 0 ); // should not be in the table + *pPlace = pTableOld[e]; + } + nEntries = Ivy_ManHashObjNum(p); +// assert( Counter == nEntries ); +// printf( "Increasing the structural table size from %6d to %6d. ", nTableSizeOld, p->nTableSize ); +// ABC_PRT( "Time", Abc_Clock() - clk ); + // replace the table and the parameters + ABC_FREE( pTableOld ); +} + +/**Function******************************************************************** + + Synopsis [Profiles the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +******************************************************************************/ +void Ivy_TableProfile( Ivy_Man_t * p ) +{ + int i, Counter = 0; + for ( i = 0; i < p->nTableSize; i++ ) + { + if ( p->pTable[i] ) + Counter++; + else if ( Counter ) + { + printf( "%d ", Counter ); + Counter = 0; + } + } +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/ivyUtil.c b/yosys/abc/src/aig/ivy/ivyUtil.c new file mode 100644 index 00000000000..c8d4003a41e --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivyUtil.c @@ -0,0 +1,824 @@ +/**CFile**************************************************************** + + FileName [ivyUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [Various procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivyUtil.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Increments the current traversal ID of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManIncrementTravId( Ivy_Man_t * p ) +{ + if ( p->nTravIds >= (1<<30)-1 - 1000 ) + Ivy_ManCleanTravId( p ); + p->nTravIds++; +} + +/**Function************************************************************* + + Synopsis [Sets the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManCleanTravId( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + p->nTravIds = 1; + Ivy_ManForEachObj( p, pObj, i ) + pObj->TravId = 0; +} + +/**Function************************************************************* + + Synopsis [Computes truth table of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManCollectCut_rec( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vNodes ) +{ + if ( pNode->fMarkA ) + return; + pNode->fMarkA = 1; + assert( Ivy_ObjIsAnd(pNode) || Ivy_ObjIsExor(pNode) ); + Ivy_ManCollectCut_rec( p, Ivy_ObjFanin0(pNode), vNodes ); + Ivy_ManCollectCut_rec( p, Ivy_ObjFanin1(pNode), vNodes ); + Vec_IntPush( vNodes, pNode->Id ); +} + +/**Function************************************************************* + + Synopsis [Computes truth table of the cut.] + + Description [Does not modify the array of leaves. Uses array vTruth to store + temporary truth tables. The returned pointer should be used immediately.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManCollectCut( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes ) +{ + int i, Leaf; + // collect and mark the leaves + Vec_IntClear( vNodes ); + Vec_IntForEachEntry( vLeaves, Leaf, i ) + { + Vec_IntPush( vNodes, Leaf ); + Ivy_ManObj(p, Leaf)->fMarkA = 1; + } + // collect and mark the nodes + Ivy_ManCollectCut_rec( p, pRoot, vNodes ); + // clean the nodes + Vec_IntForEachEntry( vNodes, Leaf, i ) + Ivy_ManObj(p, Leaf)->fMarkA = 0; +} + +/**Function************************************************************* + + Synopsis [Returns the pointer to the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Ivy_ObjGetTruthStore( int ObjNum, Vec_Int_t * vTruth ) +{ + return ((unsigned *)Vec_IntArray(vTruth)) + 8 * ObjNum; +} + +/**Function************************************************************* + + Synopsis [Computes truth table of the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManCutTruthOne( Ivy_Man_t * p, Ivy_Obj_t * pNode, Vec_Int_t * vTruth, int nWords ) +{ + unsigned * pTruth, * pTruth0, * pTruth1; + int i; + pTruth = Ivy_ObjGetTruthStore( pNode->TravId, vTruth ); + pTruth0 = Ivy_ObjGetTruthStore( Ivy_ObjFanin0(pNode)->TravId, vTruth ); + pTruth1 = Ivy_ObjGetTruthStore( Ivy_ObjFanin1(pNode)->TravId, vTruth ); + if ( Ivy_ObjIsExor(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] ^ pTruth1[i]; + else if ( !Ivy_ObjFaninC0(pNode) && !Ivy_ObjFaninC1(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] & pTruth1[i]; + else if ( !Ivy_ObjFaninC0(pNode) && Ivy_ObjFaninC1(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = pTruth0[i] & ~pTruth1[i]; + else if ( Ivy_ObjFaninC0(pNode) && !Ivy_ObjFaninC1(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ~pTruth0[i] & pTruth1[i]; + else // if ( Ivy_ObjFaninC0(pNode) && Ivy_ObjFaninC1(pNode) ) + for ( i = 0; i < nWords; i++ ) + pTruth[i] = ~pTruth0[i] & ~pTruth1[i]; +} + +/**Function************************************************************* + + Synopsis [Computes truth table of the cut.] + + Description [Does not modify the array of leaves. Uses array vTruth to store + temporary truth tables. The returned pointer should be used immediately.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Ivy_ManCutTruth( Ivy_Man_t * p, Ivy_Obj_t * pRoot, Vec_Int_t * vLeaves, Vec_Int_t * vNodes, Vec_Int_t * vTruth ) +{ + static unsigned uTruths[8][8] = { // elementary truth tables + { 0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA,0xAAAAAAAA }, + { 0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC,0xCCCCCCCC }, + { 0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0,0xF0F0F0F0 }, + { 0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00,0xFF00FF00 }, + { 0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000,0xFFFF0000 }, + { 0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF,0x00000000,0xFFFFFFFF }, + { 0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF }, + { 0x00000000,0x00000000,0x00000000,0x00000000,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF } + }; + int i, Leaf; + // collect the cut + Ivy_ManCollectCut( p, pRoot, vLeaves, vNodes ); + // set the node numbers + Vec_IntForEachEntry( vNodes, Leaf, i ) + Ivy_ManObj(p, Leaf)->TravId = i; + // alloc enough memory + Vec_IntClear( vTruth ); + Vec_IntGrow( vTruth, 8 * Vec_IntSize(vNodes) ); + // set the elementary truth tables + Vec_IntForEachEntry( vLeaves, Leaf, i ) + memcpy( Ivy_ObjGetTruthStore(i, vTruth), uTruths[i], 8 * sizeof(unsigned) ); + // compute truths for other nodes + Vec_IntForEachEntryStart( vNodes, Leaf, i, Vec_IntSize(vLeaves) ) + Ivy_ManCutTruthOne( p, Ivy_ManObj(p, Leaf), vTruth, 8 ); + return Ivy_ObjGetTruthStore( pRoot->TravId, vTruth ); +} + +/**Function************************************************************* + + Synopsis [Collect the latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Ivy_ManLatches( Ivy_Man_t * p ) +{ + Vec_Int_t * vLatches; + Ivy_Obj_t * pObj; + int i; + vLatches = Vec_IntAlloc( Ivy_ManLatchNum(p) ); + Ivy_ManForEachLatch( p, pObj, i ) + Vec_IntPush( vLatches, pObj->Id ); + return vLatches; +} + +/**Function************************************************************* + + Synopsis [Collect the latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManLevels( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i, LevelMax = 0; + Ivy_ManForEachPo( p, pObj, i ) + LevelMax = IVY_MAX( LevelMax, (int)Ivy_ObjFanin0(pObj)->Level ); + return LevelMax; +} + +/**Function************************************************************* + + Synopsis [Collect the latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ManResetLevels_rec( Ivy_Obj_t * pObj ) +{ + if ( pObj->Level || Ivy_ObjIsCi(pObj) || Ivy_ObjIsConst1(pObj) ) + return pObj->Level; + if ( Ivy_ObjIsBuf(pObj) ) + return pObj->Level = Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) ); + assert( Ivy_ObjIsNode(pObj) ); + Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) ); + Ivy_ManResetLevels_rec( Ivy_ObjFanin1(pObj) ); + return pObj->Level = Ivy_ObjLevelNew( pObj ); +} + +/**Function************************************************************* + + Synopsis [Collect the latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManResetLevels( Ivy_Man_t * p ) +{ + Ivy_Obj_t * pObj; + int i; + Ivy_ManForEachObj( p, pObj, i ) + pObj->Level = 0; + Ivy_ManForEachCo( p, pObj, i ) + Ivy_ManResetLevels_rec( Ivy_ObjFanin0(pObj) ); +} + +/**Function************************************************************* + + Synopsis [References/references the node and returns MFFC size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ObjRefDeref( Ivy_Man_t * p, Ivy_Obj_t * pNode, int fReference, int fLabel ) +{ + Ivy_Obj_t * pNode0, * pNode1; + int Counter; + // label visited nodes + if ( fLabel ) + Ivy_ObjSetTravIdCurrent( p, pNode ); + // skip the CI + if ( Ivy_ObjIsPi(pNode) ) + return 0; + assert( Ivy_ObjIsNode(pNode) || Ivy_ObjIsBuf(pNode) || Ivy_ObjIsLatch(pNode) ); + // process the internal node + pNode0 = Ivy_ObjFanin0(pNode); + pNode1 = Ivy_ObjFanin1(pNode); + Counter = Ivy_ObjIsNode(pNode); + if ( fReference ) + { + if ( pNode0->nRefs++ == 0 ) + Counter += Ivy_ObjRefDeref( p, pNode0, fReference, fLabel ); + if ( pNode1 && pNode1->nRefs++ == 0 ) + Counter += Ivy_ObjRefDeref( p, pNode1, fReference, fLabel ); + } + else + { + assert( pNode0->nRefs > 0 ); + assert( pNode1 == NULL || pNode1->nRefs > 0 ); + if ( --pNode0->nRefs == 0 ) + Counter += Ivy_ObjRefDeref( p, pNode0, fReference, fLabel ); + if ( pNode1 && --pNode1->nRefs == 0 ) + Counter += Ivy_ObjRefDeref( p, pNode1, fReference, fLabel ); + } + return Counter; +} + + +/**Function************************************************************* + + Synopsis [Labels MFFC with the current label.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ObjMffcLabel( Ivy_Man_t * p, Ivy_Obj_t * pNode ) +{ + int nConeSize1, nConeSize2; + assert( !Ivy_IsComplement( pNode ) ); + assert( Ivy_ObjIsNode( pNode ) ); + nConeSize1 = Ivy_ObjRefDeref( p, pNode, 0, 1 ); // dereference + nConeSize2 = Ivy_ObjRefDeref( p, pNode, 1, 0 ); // reference + assert( nConeSize1 == nConeSize2 ); + assert( nConeSize1 > 0 ); + return nConeSize1; +} + +/**Function************************************************************* + + Synopsis [Recursively updates fanout levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjUpdateLevel_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pFanout; + Vec_Ptr_t * vFanouts; + int i, LevelNew; + assert( p->fFanout ); + assert( Ivy_ObjIsNode(pObj) ); + vFanouts = Vec_PtrAlloc( 10 ); + Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i ) + { + if ( Ivy_ObjIsCo(pFanout) ) + { +// assert( (int)Ivy_ObjFanin0(pFanout)->Level <= p->nLevelMax ); + continue; + } + LevelNew = Ivy_ObjLevelNew( pFanout ); + if ( (int)pFanout->Level == LevelNew ) + continue; + pFanout->Level = LevelNew; + Ivy_ObjUpdateLevel_rec( p, pFanout ); + } + Vec_PtrFree( vFanouts ); +} + +/**Function************************************************************* + + Synopsis [Compute the new required level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ObjLevelRNew( Ivy_Man_t * p, Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pFanout; + Vec_Ptr_t * vFanouts; + int i, Required, LevelNew = 1000000; + assert( p->fFanout && p->vRequired ); + vFanouts = Vec_PtrAlloc( 10 ); + Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i ) + { + Required = Vec_IntEntry(p->vRequired, pFanout->Id); + LevelNew = IVY_MIN( LevelNew, Required ); + } + Vec_PtrFree( vFanouts ); + return LevelNew - 1; +} + +/**Function************************************************************* + + Synopsis [Recursively updates fanout levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjUpdateLevelR_rec( Ivy_Man_t * p, Ivy_Obj_t * pObj, int ReqNew ) +{ + Ivy_Obj_t * pFanin; + if ( Ivy_ObjIsConst1(pObj) || Ivy_ObjIsCi(pObj) ) + return; + assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsBuf(pObj) ); + // process the first fanin + pFanin = Ivy_ObjFanin0(pObj); + if ( Vec_IntEntry(p->vRequired, pFanin->Id) > ReqNew - 1 ) + { + Vec_IntWriteEntry( p->vRequired, pFanin->Id, ReqNew - 1 ); + Ivy_ObjUpdateLevelR_rec( p, pFanin, ReqNew - 1 ); + } + if ( Ivy_ObjIsBuf(pObj) ) + return; + // process the second fanin + pFanin = Ivy_ObjFanin1(pObj); + if ( Vec_IntEntry(p->vRequired, pFanin->Id) > ReqNew - 1 ) + { + Vec_IntWriteEntry( p->vRequired, pFanin->Id, ReqNew - 1 ); + Ivy_ObjUpdateLevelR_rec( p, pFanin, ReqNew - 1 ); + } +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_ObjIsMuxType( Ivy_Obj_t * pNode ) +{ + Ivy_Obj_t * pNode0, * pNode1; + // check that the node is regular + assert( !Ivy_IsComplement(pNode) ); + // if the node is not AND, this is not MUX + if ( !Ivy_ObjIsAnd(pNode) ) + return 0; + // if the children are not complemented, this is not MUX + if ( !Ivy_ObjFaninC0(pNode) || !Ivy_ObjFaninC1(pNode) ) + return 0; + // get children + pNode0 = Ivy_ObjFanin0(pNode); + pNode1 = Ivy_ObjFanin1(pNode); + // if the children are not ANDs, this is not MUX + if ( !Ivy_ObjIsAnd(pNode0) || !Ivy_ObjIsAnd(pNode1) ) + return 0; + // otherwise the node is MUX iff it has a pair of equal grandchildren + return (Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC0(pNode1))) || + (Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC1(pNode1))) || + (Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC0(pNode1))) || + (Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC1(pNode1))); +} + +/**Function************************************************************* + + Synopsis [Recognizes what nodes are control and data inputs of a MUX.] + + Description [If the node is a MUX, returns the control variable C. + Assigns nodes T and E to be the then and else variables of the MUX. + Node C is never complemented. Nodes T and E can be complemented. + This function also recognizes EXOR/NEXOR gates as MUXes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_ObjRecognizeMux( Ivy_Obj_t * pNode, Ivy_Obj_t ** ppNodeT, Ivy_Obj_t ** ppNodeE ) +{ + Ivy_Obj_t * pNode0, * pNode1; + assert( !Ivy_IsComplement(pNode) ); + assert( Ivy_ObjIsMuxType(pNode) ); + // get children + pNode0 = Ivy_ObjFanin0(pNode); + pNode1 = Ivy_ObjFanin1(pNode); + // find the control variable +// if ( pNode1->p1 == Fraig_Not(pNode2->p1) ) + if ( Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC0(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p1) ) + if ( Ivy_ObjFaninC0(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); + return Ivy_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); + return Ivy_ObjChild0(pNode0);//pNode1->p1; + } + } +// else if ( pNode1->p1 == Fraig_Not(pNode2->p2) ) + else if ( Ivy_ObjFaninId0(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC0(pNode0) ^ Ivy_ObjFaninC1(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p1) ) + if ( Ivy_ObjFaninC0(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); + return Ivy_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); + return Ivy_ObjChild0(pNode0);//pNode1->p1; + } + } +// else if ( pNode1->p2 == Fraig_Not(pNode2->p1) ) + else if ( Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId0(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC0(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p2) ) + if ( Ivy_ObjFaninC1(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); + return Ivy_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Ivy_Not(Ivy_ObjChild1(pNode1));//pNode2->p2); + return Ivy_ObjChild1(pNode0);//pNode1->p2; + } + } +// else if ( pNode1->p2 == Fraig_Not(pNode2->p2) ) + else if ( Ivy_ObjFaninId1(pNode0) == Ivy_ObjFaninId1(pNode1) && (Ivy_ObjFaninC1(pNode0) ^ Ivy_ObjFaninC1(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p2) ) + if ( Ivy_ObjFaninC1(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); + return Ivy_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Ivy_Not(Ivy_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Ivy_Not(Ivy_ObjChild0(pNode1));//pNode2->p1); + return Ivy_ObjChild1(pNode0);//pNode1->p2; + } + } + assert( 0 ); // this is not MUX + return NULL; +} + +/**Function************************************************************* + + Synopsis [Returns the real fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Ivy_Obj_t * Ivy_ObjReal( Ivy_Obj_t * pObj ) +{ + Ivy_Obj_t * pFanin; + if ( pObj == NULL || !Ivy_ObjIsBuf( Ivy_Regular(pObj) ) ) + return pObj; + pFanin = Ivy_ObjReal( Ivy_ObjChild0(Ivy_Regular(pObj)) ); + return Ivy_NotCond( pFanin, Ivy_IsComplement(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Prints node in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ObjPrintVerbose( Ivy_Man_t * p, Ivy_Obj_t * pObj, int fHaig ) +{ + Ivy_Obj_t * pTemp; + int fShowFanouts = 0; + assert( !Ivy_IsComplement(pObj) ); + printf( "Node %5d : ", Ivy_ObjId(pObj) ); + if ( Ivy_ObjIsConst1(pObj) ) + printf( "constant 1" ); + else if ( Ivy_ObjIsPi(pObj) ) + printf( "PI" ); + else if ( Ivy_ObjIsPo(pObj) ) + printf( "PO" ); + else if ( Ivy_ObjIsLatch(pObj) ) + printf( "latch (%d%s)", Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") ); + else if ( Ivy_ObjIsBuf(pObj) ) + printf( "buffer (%d%s)", Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") ); + else + printf( "AND( %5d%s, %5d%s )", + Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " "), + Ivy_ObjFanin1(pObj)->Id, (Ivy_ObjFaninC1(pObj)? "\'" : " ") ); + printf( " (refs = %3d)", Ivy_ObjRefs(pObj) ); + if ( fShowFanouts ) + { + Vec_Ptr_t * vFanouts; + Ivy_Obj_t * pFanout; + int i; + vFanouts = Vec_PtrAlloc( 10 ); + printf( "\nFanouts:\n" ); + Ivy_ObjForEachFanout( p, pObj, vFanouts, pFanout, i ) + { + printf( " " ); + printf( "Node %5d : ", Ivy_ObjId(pFanout) ); + if ( Ivy_ObjIsPo(pFanout) ) + printf( "PO" ); + else if ( Ivy_ObjIsLatch(pFanout) ) + printf( "latch (%d%s)", Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " ") ); + else if ( Ivy_ObjIsBuf(pFanout) ) + printf( "buffer (%d%s)", Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " ") ); + else + printf( "AND( %5d%s, %5d%s )", + Ivy_ObjFanin0(pFanout)->Id, (Ivy_ObjFaninC0(pFanout)? "\'" : " "), + Ivy_ObjFanin1(pFanout)->Id, (Ivy_ObjFaninC1(pFanout)? "\'" : " ") ); + printf( "\n" ); + } + Vec_PtrFree( vFanouts ); + return; + } + if ( !fHaig ) + { + if ( pObj->pEquiv == NULL ) + printf( " HAIG node not given" ); + else + printf( " HAIG node = %d%s", Ivy_Regular(pObj->pEquiv)->Id, (Ivy_IsComplement(pObj->pEquiv)? "\'" : " ") ); + return; + } + if ( pObj->pEquiv == NULL ) + return; + // there are choices + if ( Ivy_ObjRefs(pObj) > 0 ) + { + // print equivalence class + printf( " { %5d ", pObj->Id ); + assert( !Ivy_IsComplement(pObj->pEquiv) ); + for ( pTemp = pObj->pEquiv; pTemp != pObj; pTemp = Ivy_Regular(pTemp->pEquiv) ) + printf( " %5d%s", pTemp->Id, (Ivy_IsComplement(pTemp->pEquiv)? "\'" : " ") ); + printf( " }" ); + return; + } + // this is a secondary node + for ( pTemp = Ivy_Regular(pObj->pEquiv); Ivy_ObjRefs(pTemp) == 0; pTemp = Ivy_Regular(pTemp->pEquiv) ); + assert( Ivy_ObjRefs(pTemp) > 0 ); + printf( " class of %d", pTemp->Id ); +} + +/**Function************************************************************* + + Synopsis [Prints node in HAIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ivy_ManPrintVerbose( Ivy_Man_t * p, int fHaig ) +{ + Vec_Int_t * vNodes; + Ivy_Obj_t * pObj; + int i; + printf( "PIs: " ); + Ivy_ManForEachPi( p, pObj, i ) + printf( " %d", pObj->Id ); + printf( "\n" ); + printf( "POs: " ); + Ivy_ManForEachPo( p, pObj, i ) + printf( " %d", pObj->Id ); + printf( "\n" ); + printf( "Latches: " ); + Ivy_ManForEachLatch( p, pObj, i ) + printf( " %d=%d%s", pObj->Id, Ivy_ObjFanin0(pObj)->Id, (Ivy_ObjFaninC0(pObj)? "\'" : " ") ); + printf( "\n" ); + vNodes = Ivy_ManDfsSeq( p, NULL ); + Ivy_ManForEachNodeVec( p, vNodes, pObj, i ) + Ivy_ObjPrintVerbose( p, pObj, fHaig ), printf( "\n" ); + printf( "\n" ); + Vec_IntFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Performs incremental rewriting of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_CutTruthPrint2( Ivy_Man_t * p, Ivy_Cut_t * pCut, unsigned uTruth ) +{ + int i; + printf( "Trying cut : {" ); + for ( i = 0; i < pCut->nSize; i++ ) + printf( " %6d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) ); + printf( " } " ); + Extra_PrintBinary( stdout, &uTruth, 16 ); printf( "\n" ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Performs incremental rewriting of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ivy_CutTruthPrint( Ivy_Man_t * p, Ivy_Cut_t * pCut, unsigned uTruth ) +{ + Vec_Ptr_t * vArray; + Ivy_Obj_t * pObj, * pFanout; + int nLatches = 0; + int nPresent = 0; + int i, k; + int fVerbose = 0; + + if ( fVerbose ) + printf( "Trying cut : {" ); + for ( i = 0; i < pCut->nSize; i++ ) + { + if ( fVerbose ) + printf( " %6d(%d)", Ivy_LeafId(pCut->pArray[i]), Ivy_LeafLat(pCut->pArray[i]) ); + nLatches += Ivy_LeafLat(pCut->pArray[i]); + } + if ( fVerbose ) + printf( " } " ); + if ( fVerbose ) + printf( "Latches = %d. ", nLatches ); + + // check if there are latches on the fanout edges + vArray = Vec_PtrAlloc( 100 ); + for ( i = 0; i < pCut->nSize; i++ ) + { + pObj = Ivy_ManObj( p, Ivy_LeafId(pCut->pArray[i]) ); + Ivy_ObjForEachFanout( p, pObj, vArray, pFanout, k ) + { + if ( Ivy_ObjIsLatch(pFanout) ) + { + nPresent++; + break; + } + } + } + Vec_PtrSize( vArray ); + if ( fVerbose ) + { + printf( "Present = %d. ", nPresent ); + if ( nLatches > nPresent ) + printf( "Clauses = %d. ", 2*(nLatches - nPresent) ); + printf( "\n" ); + } + return ( nLatches > nPresent ) ? 2*(nLatches - nPresent) : 0; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/ivy_.c b/yosys/abc/src/aig/ivy/ivy_.c new file mode 100644 index 00000000000..ccad8a46ae2 --- /dev/null +++ b/yosys/abc/src/aig/ivy/ivy_.c @@ -0,0 +1,53 @@ +/**CFile**************************************************************** + + FileName [ivy_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [And-Inverter Graph package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - May 11, 2006.] + + Revision [$Id: ivy_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "ivy.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/ivy/module.make b/yosys/abc/src/aig/ivy/module.make new file mode 100644 index 00000000000..daef43dfbe2 --- /dev/null +++ b/yosys/abc/src/aig/ivy/module.make @@ -0,0 +1,22 @@ +SRC += src/aig/ivy/ivyBalance.c \ + src/aig/ivy/ivyCanon.c \ + src/aig/ivy/ivyCheck.c \ + src/aig/ivy/ivyCut.c \ + src/aig/ivy/ivyCutTrav.c \ + src/aig/ivy/ivyDfs.c \ + src/aig/ivy/ivyDsd.c \ + src/aig/ivy/ivyFanout.c \ + src/aig/ivy/ivyFastMap.c \ + src/aig/ivy/ivyFraig.c \ + src/aig/ivy/ivyHaig.c \ + src/aig/ivy/ivyMan.c \ + src/aig/ivy/ivyMem.c \ + src/aig/ivy/ivyMulti.c \ + src/aig/ivy/ivyObj.c \ + src/aig/ivy/ivyOper.c \ + src/aig/ivy/ivyResyn.c \ + src/aig/ivy/ivyRwr.c \ + src/aig/ivy/ivySeq.c \ + src/aig/ivy/ivyShow.c \ + src/aig/ivy/ivyTable.c \ + src/aig/ivy/ivyUtil.c diff --git a/yosys/abc/src/aig/miniaig/abcOper.h b/yosys/abc/src/aig/miniaig/abcOper.h new file mode 100644 index 00000000000..cbe2a0f3a72 --- /dev/null +++ b/yosys/abc/src/aig/miniaig/abcOper.h @@ -0,0 +1,282 @@ +/**CFile**************************************************************** + + FileName [acbTypes.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Hierarchical word-level netlist.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - July 21, 2015.] + + Revision [$Id: acbTypes.h,v 1.00 2014/11/29 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__base__acb__acb__types_h +#define ABC__base__acb__acb__types_h + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +#ifndef _YOSYS_ +ABC_NAMESPACE_HEADER_START +#endif + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +// network objects +typedef enum { + ABC_OPER_NONE = 0, // 00 unused + ABC_OPER_PI, // 01 input + ABC_OPER_PO, // 02 output + ABC_OPER_CI, // 03 combinational input + ABC_OPER_CO, // 04 combinational output + ABC_OPER_FON, // 05 output placeholder + ABC_OPER_BOX, // 06 box + + ABC_OPER_CONST_F, // 07 + ABC_OPER_CONST_T, // 08 + ABC_OPER_CONST_X, // 09 + ABC_OPER_CONST_Z, // 10 + + ABC_OPER_BIT_BUF, // 11 + ABC_OPER_BIT_INV, // 12 + ABC_OPER_BIT_AND, // 13 + ABC_OPER_BIT_NAND, // 14 + ABC_OPER_BIT_OR, // 15 + ABC_OPER_BIT_NOR, // 16 + ABC_OPER_BIT_XOR, // 17 + ABC_OPER_BIT_NXOR, // 18 + ABC_OPER_BIT_SHARP, // 19 + ABC_OPER_BIT_SHARPL, // 20 + ABC_OPER_BIT_MUX, // 21 fanins are: {Ctrl, Data1, Data0} + ABC_OPER_BIT_MAJ, // 22 + + ABC_OPER_ABC, // 23 + ABC_OPER_BA, // 24 + ABC_OPER_BO, // 25 + ABC_OPER_BX, // 26 + ABC_OPER_BN, // 27 + ABC_OPER_BAO, // 28 + ABC_OPER_BOA, // 29 + + ABC_OPER_RED_AND, // 30 + ABC_OPER_RED_NAND, // 31 + ABC_OPER_RED_OR, // 32 + ABC_OPER_RED_NOR, // 33 + ABC_OPER_RED_XOR, // 34 + ABC_OPER_RED_NXOR, // 35 + + ABC_OPER_LOGIC_NOT, // 36 + ABC_OPER_LOGIC_AND, // 37 + ABC_OPER_LOGIC_NAND, // 38 + ABC_OPER_LOGIC_OR, // 39 + ABC_OPER_LOGIC_NOR, // 40 + ABC_OPER_LOGIC_XOR, // 41 + ABC_OPER_LOGIC_XNOR, // 42 + + ABC_OPER_SEL_NMUX, // 43 fanins are: {Ctrl, Data0, Data1, Data2, ...} + ABC_OPER_SEL_SEL, // 44 + ABC_OPER_SEL_PSEL, // 45 + ABC_OPER_SEL_ENC, // 46 + ABC_OPER_SEL_PENC, // 47 + ABC_OPER_SEL_DEC, // 48 + ABC_OPER_SEL_EDEC, // 49 + + ABC_OPER_ARI_ADD, // 50 + ABC_OPER_ARI_SUB, // 51 + ABC_OPER_ARI_MUL, // 52 + ABC_OPER_ARI_SMUL, // 53 + ABC_OPER_ARI_DIV, // 54 + ABC_OPER_ARI_MOD, // 55 + ABC_OPER_ARI_REM, // 56 + ABC_OPER_ARI_POW, // 57 + ABC_OPER_ARI_MIN, // 58 + ABC_OPER_ARI_SQRT, // 59 + ABC_OPER_ARI_ABS, // 60 + + ABC_OPER_COMP_SLESS, // 61 + ABC_OPER_COMP_LESS, // 62 + ABC_OPER_COMP_LESSEQU, // 63 + ABC_OPER_COMP_MOREEQU, // 64 + ABC_OPER_COMP_MORE, // 65 + ABC_OPER_COMP_EQU, // 66 + ABC_OPER_COMP_NOTEQU, // 67 + + ABC_OPER_SHIFT_L, // 68 + ABC_OPER_SHIFT_R, // 69 + ABC_OPER_SHIFT_LA, // 70 + ABC_OPER_SHIFT_RA, // 71 + ABC_OPER_SHIFT_ROTL, // 72 + ABC_OPER_SHIFT_ROTR, // 73 + + ABC_OPER_NODE, // 74 + ABC_OPER_LUT, // 75 + ABC_OPER_GATE, // 76 + ABC_OPER_TABLE, // 77 + + ABC_OPER_TRI, // 78 + ABC_OPER_RAM, // 79 + ABC_OPER_RAMR, // 80 + ABC_OPER_RAMW, // 81 + ABC_OPER_RAMWC, // 82 + ABC_OPER_RAML, // 83 + ABC_OPER_RAMS, // 84 + ABC_OPER_RAMBOX, // 85 + + ABC_OPER_LATCH, // 86 + ABC_OPER_LATCHRS, // 87 + ABC_OPER_DFF, // 88 + ABC_OPER_DFFRSE, // 89 + ABC_OPER_DFFLAST, // 90 + + ABC_OPER_SLICE, // 91 + ABC_OPER_CONCAT, // 92 + ABC_OPER_ZEROPAD, // 93 + ABC_OPER_SIGNEXT, // 94 + + ABC_OPER_LOGIC_IMPL, // 95 + ABC_OPER_ARI_SQUARE, // 96 + ABC_OPER_CONST, // 97 + + ABC_OPER_ARI_ADDSUB, // 98 + + ABC_OPER_LAST // 99 +} Acb_ObjType_t; + + +// printing operator types +static inline const char * Abc_OperName( int Type ) +{ + if ( Type == ABC_OPER_NONE ) return NULL; + if ( Type == ABC_OPER_PI ) return "pi"; + if ( Type == ABC_OPER_PO ) return "po"; + if ( Type == ABC_OPER_CI ) return "ci"; + if ( Type == ABC_OPER_CO ) return "co"; + if ( Type == ABC_OPER_FON ) return "fon"; + if ( Type == ABC_OPER_BOX ) return "box"; + + if ( Type == ABC_OPER_BIT_BUF ) return "buf"; + if ( Type == ABC_OPER_BIT_INV ) return "~"; + if ( Type == ABC_OPER_BIT_MUX ) return "mux"; + if ( Type == ABC_OPER_BIT_MAJ ) return "maj"; + if ( Type == ABC_OPER_BIT_AND ) return "&"; + if ( Type == ABC_OPER_BIT_OR ) return "|"; + if ( Type == ABC_OPER_BIT_XOR ) return "^"; + if ( Type == ABC_OPER_BIT_NAND ) return "~&"; + if ( Type == ABC_OPER_BIT_NOR ) return "~|"; + if ( Type == ABC_OPER_BIT_NXOR ) return "~^"; + + if ( Type == ABC_OPER_RED_AND ) return "&"; + if ( Type == ABC_OPER_RED_OR ) return "|"; + if ( Type == ABC_OPER_RED_XOR ) return "^"; + if ( Type == ABC_OPER_RED_NAND ) return "~&"; + if ( Type == ABC_OPER_RED_NOR ) return "~|"; + if ( Type == ABC_OPER_RED_NXOR ) return "~^"; + + if ( Type == ABC_OPER_LOGIC_NOT ) return "!"; + if ( Type == ABC_OPER_LOGIC_IMPL ) return "=>"; + if ( Type == ABC_OPER_LOGIC_AND ) return "&&"; + if ( Type == ABC_OPER_LOGIC_OR ) return "||"; + if ( Type == ABC_OPER_LOGIC_XOR ) return "^^"; + + if ( Type == ABC_OPER_ARI_ADD ) return "+"; + if ( Type == ABC_OPER_ARI_SUB ) return "-"; + if ( Type == ABC_OPER_ARI_MUL ) return "*"; + if ( Type == ABC_OPER_ARI_SMUL ) return "*"; + if ( Type == ABC_OPER_ARI_DIV ) return "/"; + if ( Type == ABC_OPER_ARI_REM ) return "%"; + if ( Type == ABC_OPER_ARI_MOD ) return "mod"; + if ( Type == ABC_OPER_ARI_POW ) return "**"; + if ( Type == ABC_OPER_ARI_MIN ) return "-"; + if ( Type == ABC_OPER_ARI_SQRT ) return "sqrt"; + if ( Type == ABC_OPER_ARI_SQUARE ) return "squar"; + + if ( Type == ABC_OPER_COMP_EQU ) return "=="; + if ( Type == ABC_OPER_COMP_NOTEQU ) return "!="; + if ( Type == ABC_OPER_COMP_LESS ) return "<"; + if ( Type == ABC_OPER_COMP_MORE ) return ">"; + if ( Type == ABC_OPER_COMP_LESSEQU ) return "<="; + if ( Type == ABC_OPER_COMP_MOREEQU ) return ">="; + + if ( Type == ABC_OPER_SHIFT_L ) return "<<"; + if ( Type == ABC_OPER_SHIFT_R ) return ">>"; + if ( Type == ABC_OPER_SHIFT_LA ) return "<<<"; + if ( Type == ABC_OPER_SHIFT_RA ) return ">>>"; + if ( Type == ABC_OPER_SHIFT_ROTL ) return "rotL"; + if ( Type == ABC_OPER_SHIFT_ROTR ) return "rotR"; + + if ( Type == ABC_OPER_DFFRSE ) return "DFFRSE"; + + if ( Type == ABC_OPER_SLICE ) return "[:]"; + if ( Type == ABC_OPER_CONCAT ) return "{}"; + if ( Type == ABC_OPER_ZEROPAD ) return "zPad"; + if ( Type == ABC_OPER_SIGNEXT ) return "sExt"; + + if ( Type == ABC_OPER_BIT_MUX ) return "mux"; + if ( Type == ABC_OPER_SEL_NMUX ) return "nmux"; + if ( Type == ABC_OPER_SEL_SEL ) return "pmux"; + + if ( Type == ABC_OPER_CONST ) return "const"; + if ( Type == ABC_OPER_TABLE ) return "table"; + if ( Type == ABC_OPER_LUT ) return "lut"; + if ( Type == ABC_OPER_LAST ) return NULL; + assert( 0 ); + return NULL; +} + +// printing operator types +static inline const char * Abc_OperNameSimple( int Type ) +{ + if ( Type == ABC_OPER_NONE ) return NULL; + if ( Type == ABC_OPER_CONST_F ) return "buf"; + if ( Type == ABC_OPER_CONST_T ) return "buf"; + if ( Type == ABC_OPER_CONST_X ) return "buf"; + if ( Type == ABC_OPER_CONST_Z ) return "buf"; + if ( Type == ABC_OPER_BIT_BUF ) return "buf"; + if ( Type == ABC_OPER_BIT_INV ) return "not"; + if ( Type == ABC_OPER_BIT_AND ) return "and"; + if ( Type == ABC_OPER_BIT_OR ) return "or"; + if ( Type == ABC_OPER_BIT_XOR ) return "xor"; + if ( Type == ABC_OPER_BIT_NAND ) return "nand"; + if ( Type == ABC_OPER_BIT_NOR ) return "nor"; + if ( Type == ABC_OPER_BIT_NXOR ) return "xnor"; + assert( 0 ); + return NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#ifndef _YOSYS_ +ABC_NAMESPACE_HEADER_END +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/yosys/abc/src/aig/miniaig/miniaig.h b/yosys/abc/src/aig/miniaig/miniaig.h new file mode 100644 index 00000000000..c7ce14e96b2 --- /dev/null +++ b/yosys/abc/src/aig/miniaig/miniaig.h @@ -0,0 +1,850 @@ +/**CFile**************************************************************** + + FileName [miniaig.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic AIG package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 29, 2012.] + + Revision [$Id: miniaig.h,v 1.00 2012/09/29 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef MINI_AIG__mini_aig_h +#define MINI_AIG__mini_aig_h + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#ifndef _VERIFIC_DATABASE_H_ +ABC_NAMESPACE_HEADER_START +#endif + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +#define MINI_AIG_NULL (0x7FFFFFFF) +#define MINI_AIG_START_SIZE (0x000000FF) + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Mini_Aig_t_ Mini_Aig_t; +struct Mini_Aig_t_ +{ + int nCap; + int nSize; + int nRegs; + int * pArray; +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// memory management +#define MINI_AIG_ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) +#define MINI_AIG_CALLOC(type, num) ((type *) calloc((num), sizeof(type))) +#define MINI_AIG_FALLOC(type, num) ((type *) memset(malloc(sizeof(type) * (num)), 0xff, sizeof(type) * (num))) +#define MINI_AIG_FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) +#define MINI_AIG_REALLOC(type, obj, num) \ + ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ + ((type *) malloc(sizeof(type) * (num)))) + +// internal procedures +static void Mini_AigGrow( Mini_Aig_t * p, int nCapMin ) +{ + if ( p->nCap >= nCapMin ) + return; + p->pArray = MINI_AIG_REALLOC( int, p->pArray, nCapMin ); + assert( p->pArray ); + p->nCap = nCapMin; +} +static void Mini_AigPush( Mini_Aig_t * p, int Lit0, int Lit1 ) +{ + if ( p->nSize + 2 > p->nCap ) + { + assert( p->nSize < MINI_AIG_NULL/4 ); + if ( p->nCap < MINI_AIG_START_SIZE ) + Mini_AigGrow( p, MINI_AIG_START_SIZE ); + else + Mini_AigGrow( p, 2 * p->nCap ); + } + p->pArray[p->nSize++] = Lit0; + p->pArray[p->nSize++] = Lit1; +} + +// accessing fanins +static int Mini_AigNodeFanin0( Mini_Aig_t * p, int Id ) +{ + assert( Id >= 0 && 2*Id < p->nSize ); + assert( p->pArray[2*Id] == MINI_AIG_NULL || p->pArray[2*Id] < 2*Id ); + return p->pArray[2*Id]; +} +static int Mini_AigNodeFanin1( Mini_Aig_t * p, int Id ) +{ + assert( Id >= 0 && 2*Id < p->nSize ); + assert( p->pArray[2*Id+1] == MINI_AIG_NULL || p->pArray[2*Id+1] < 2*Id ); + return p->pArray[2*Id+1]; +} +static void Mini_AigFlipLastPo( Mini_Aig_t * p ) +{ + assert( p->pArray[p->nSize-1] == MINI_AIG_NULL ); + assert( p->pArray[p->nSize-2] != MINI_AIG_NULL ); + p->pArray[p->nSize-2] ^= 1; +} + +// working with variables and literals +static int Mini_AigVar2Lit( int Var, int fCompl ) { return Var + Var + fCompl; } +static int Mini_AigLit2Var( int Lit ) { return Lit >> 1; } +static int Mini_AigLitIsCompl( int Lit ) { return Lit & 1; } +static int Mini_AigLitNot( int Lit ) { return Lit ^ 1; } +static int Mini_AigLitNotCond( int Lit, int c ) { return Lit ^ (int)(c > 0); } +static int Mini_AigLitRegular( int Lit ) { return Lit & ~01; } + +static int Mini_AigLitConst0() { return 0; } +static int Mini_AigLitConst1() { return 1; } +static int Mini_AigLitIsConst0( int Lit ) { return Lit == 0; } +static int Mini_AigLitIsConst1( int Lit ) { return Lit == 1; } +static int Mini_AigLitIsConst( int Lit ) { return Lit == 0 || Lit == 1; } + +static int Mini_AigNodeNum( Mini_Aig_t * p ) { return p->nSize/2; } +static int Mini_AigNodeIsConst( Mini_Aig_t * p, int Id ) { assert( Id >= 0 ); return Id == 0; } +static int Mini_AigNodeIsPi( Mini_Aig_t * p, int Id ) { assert( Id >= 0 ); return Id > 0 && Mini_AigNodeFanin0( p, Id ) == MINI_AIG_NULL; } +static int Mini_AigNodeIsPo( Mini_Aig_t * p, int Id ) { assert( Id >= 0 ); return Id > 0 && Mini_AigNodeFanin0( p, Id ) != MINI_AIG_NULL && Mini_AigNodeFanin1( p, Id ) == MINI_AIG_NULL; } +static int Mini_AigNodeIsAnd( Mini_Aig_t * p, int Id ) { assert( Id >= 0 ); return Id > 0 && Mini_AigNodeFanin0( p, Id ) != MINI_AIG_NULL && Mini_AigNodeFanin1( p, Id ) != MINI_AIG_NULL; } + +// working with sequential AIGs +static int Mini_AigRegNum( Mini_Aig_t * p ) { return p->nRegs; } +static void Mini_AigSetRegNum( Mini_Aig_t * p, int n ) { p->nRegs = n; } + +// iterators through objects +#define Mini_AigForEachPi( p, i ) for (i = 1; i < Mini_AigNodeNum(p); i++) if ( !Mini_AigNodeIsPi(p, i) ) {} else +#define Mini_AigForEachPo( p, i ) for (i = 1; i < Mini_AigNodeNum(p); i++) if ( !Mini_AigNodeIsPo(p, i) ) {} else +#define Mini_AigForEachAnd( p, i ) for (i = 1; i < Mini_AigNodeNum(p); i++) if ( !Mini_AigNodeIsAnd(p, i) ) {} else + + +// constructor/destructor +static Mini_Aig_t * Mini_AigStart() +{ + Mini_Aig_t * p; + p = MINI_AIG_CALLOC( Mini_Aig_t, 1 ); + p->nCap = MINI_AIG_START_SIZE; + p->pArray = MINI_AIG_ALLOC( int, p->nCap ); + Mini_AigPush( p, MINI_AIG_NULL, MINI_AIG_NULL ); + return p; +} +static Mini_Aig_t * Mini_AigStartSupport( int nIns, int nObjsAlloc ) +{ + Mini_Aig_t * p; int i; + assert( 1+nIns < nObjsAlloc ); + p = MINI_AIG_CALLOC( Mini_Aig_t, 1 ); + p->nCap = 2*nObjsAlloc; + p->nSize = 2*(1+nIns); + p->pArray = MINI_AIG_ALLOC( int, p->nCap ); + for ( i = 0; i < p->nSize; i++ ) + p->pArray[i] = MINI_AIG_NULL; + return p; +} +static Mini_Aig_t * Mini_AigStartArray( int nIns, int n0InAnds, int * p0InAnds, int nOuts, int * pOuts ) +{ + Mini_Aig_t * p; int i; + assert( 1+nIns <= n0InAnds ); + p = MINI_AIG_CALLOC( Mini_Aig_t, 1 ); + p->nCap = 2*(n0InAnds + nOuts); + p->nSize = 2*(n0InAnds + nOuts); + p->pArray = MINI_AIG_ALLOC( int, p->nCap ); + for ( i = 0; i < 2*(1 + nIns); i++ ) + p->pArray[i] = MINI_AIG_NULL; + memcpy( p->pArray + 2*(1 + nIns), p0InAnds + 2*(1 + nIns), 2*(n0InAnds - 1 - nIns)*sizeof(int) ); + for ( i = 0; i < nOuts; i++ ) + { + p->pArray[2*(n0InAnds + i)+0] = pOuts[i]; + p->pArray[2*(n0InAnds + i)+1] = MINI_AIG_NULL; + } + return p; +} +static Mini_Aig_t * Mini_AigDup( Mini_Aig_t * p ) +{ + Mini_Aig_t * pNew; + pNew = MINI_AIG_CALLOC( Mini_Aig_t, 1 ); + pNew->nCap = p->nCap; + pNew->nSize = p->nSize; + pNew->pArray = MINI_AIG_ALLOC( int, p->nSize ); + memcpy( pNew->pArray, p->pArray, p->nSize * sizeof(int) ); + return pNew; +} +static void Mini_AigStop( Mini_Aig_t * p ) +{ + MINI_AIG_FREE( p->pArray ); + MINI_AIG_FREE( p ); +} +static int Mini_AigPiNum( Mini_Aig_t * p ) +{ + int i, nPis = 0; + Mini_AigForEachPi( p, i ) + nPis++; + return nPis; +} +static int Mini_AigPoNum( Mini_Aig_t * p ) +{ + int i, nPos = 0; + Mini_AigForEachPo( p, i ) + nPos++; + return nPos; +} +static int Mini_AigAndNum( Mini_Aig_t * p ) +{ + int i, nNodes = 0; + Mini_AigForEachAnd( p, i ) + nNodes++; + return nNodes; +} +static int Mini_AigXorNum( Mini_Aig_t * p ) +{ + int i, nNodes = 0; + Mini_AigForEachAnd( p, i ) + nNodes += p->pArray[2*i] > p->pArray[2*i+1]; + return nNodes; +} +static int Mini_AigLevelNum( Mini_Aig_t * p ) +{ + int i, Level = 0; + int * pLevels = MINI_AIG_CALLOC( int, Mini_AigNodeNum(p) ); + Mini_AigForEachAnd( p, i ) + { + int Lel0 = pLevels[Mini_AigLit2Var(Mini_AigNodeFanin0(p, i))]; + int Lel1 = pLevels[Mini_AigLit2Var(Mini_AigNodeFanin1(p, i))]; + pLevels[i] = 1 + (Lel0 > Lel1 ? Lel0 : Lel1); + } + Mini_AigForEachPo( p, i ) + { + int Lel0 = pLevels[Mini_AigLit2Var(Mini_AigNodeFanin0(p, i))]; + Level = Level > Lel0 ? Level : Lel0; + } + MINI_AIG_FREE( pLevels ); + return Level; +} +static void Mini_AigPrintStats( Mini_Aig_t * p ) +{ + printf( "MiniAIG stats: PI = %d PO = %d FF = %d AND = %d\n", Mini_AigPiNum(p), Mini_AigPoNum(p), Mini_AigRegNum(p), Mini_AigAndNum(p) ); +} + +// serialization +static void Mini_AigDump( Mini_Aig_t * p, char * pFileName ) +{ + FILE * pFile; + int RetValue; + pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file for writing \"%s\".\n", pFileName ); + return; + } + RetValue = (int)fwrite( &p->nSize, sizeof(int), 1, pFile ); + RetValue = (int)fwrite( &p->nRegs, sizeof(int), 1, pFile ); + RetValue = (int)fwrite( p->pArray, sizeof(int), p->nSize, pFile ); + fclose( pFile ); +} +static Mini_Aig_t * Mini_AigLoad( char * pFileName ) +{ + Mini_Aig_t * p; + FILE * pFile; + int RetValue, nSize; + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file for reading \"%s\".\n", pFileName ); + return NULL; + } + RetValue = (int)fread( &nSize, sizeof(int), 1, pFile ); + p = MINI_AIG_CALLOC( Mini_Aig_t, 1 ); + p->nSize = p->nCap = nSize; + p->pArray = MINI_AIG_ALLOC( int, p->nCap ); + RetValue = (int)fread( &p->nRegs, sizeof(int), 1, pFile ); + RetValue = (int)fread( p->pArray, sizeof(int), p->nSize, pFile ); + fclose( pFile ); + return p; +} + + +// creating nodes +// (constant node is created when AIG manager is created) +static int Mini_AigCreatePi( Mini_Aig_t * p ) +{ + int Lit = p->nSize; + Mini_AigPush( p, MINI_AIG_NULL, MINI_AIG_NULL ); + return Lit; +} +static int Mini_AigCreatePo( Mini_Aig_t * p, int Lit0 ) +{ + int Lit = p->nSize; + assert( Lit0 >= 0 && Lit0 < Lit ); + Mini_AigPush( p, Lit0, MINI_AIG_NULL ); + return Lit; +} + +// boolean operations +static int Mini_AigAnd( Mini_Aig_t * p, int Lit0, int Lit1 ) +{ + int Lit = p->nSize; + assert( Lit0 >= 0 && Lit0 < Lit ); + assert( Lit1 >= 0 && Lit1 < Lit ); + if ( Lit0 < Lit1 ) + Mini_AigPush( p, Lit0, Lit1 ); + else + Mini_AigPush( p, Lit1, Lit0 ); + return Lit; +} +static int Mini_AigOr( Mini_Aig_t * p, int Lit0, int Lit1 ) +{ + return Mini_AigLitNot( Mini_AigAnd( p, Mini_AigLitNot(Lit0), Mini_AigLitNot(Lit1) ) ); +} +static int Mini_AigMux( Mini_Aig_t * p, int LitC, int Lit1, int Lit0 ) +{ + int Res0 = Mini_AigAnd( p, LitC, Lit1 ); + int Res1 = Mini_AigAnd( p, Mini_AigLitNot(LitC), Lit0 ); + return Mini_AigOr( p, Res0, Res1 ); +} +static int Mini_AigXor( Mini_Aig_t * p, int Lit0, int Lit1 ) +{ + return Mini_AigMux( p, Lit0, Mini_AigLitNot(Lit1), Lit1 ); +} +static int Mini_AigXorSpecial( Mini_Aig_t * p, int Lit0, int Lit1 ) +{ + int Lit = p->nSize; + assert( Lit0 >= 0 && Lit0 < Lit ); + assert( Lit1 >= 0 && Lit1 < Lit ); + if ( Lit0 > Lit1 ) + Mini_AigPush( p, Lit0, Lit1 ); + else + Mini_AigPush( p, Lit1, Lit0 ); + return Lit; +} +static int Mini_AigAndMulti( Mini_Aig_t * p, int * pLits, int nLits ) +{ + int i; + assert( nLits > 0 ); + while ( nLits > 1 ) + { + for ( i = 0; i < nLits/2; i++ ) + pLits[i] = Mini_AigAnd(p, pLits[2*i], pLits[2*i+1]); + if ( nLits & 1 ) + pLits[i++] = pLits[nLits-1]; + nLits = i; + } + return pLits[0]; +} +static int Mini_AigMuxMulti( Mini_Aig_t * p, int * pCtrl, int nCtrl, int * pData, int nData ) +{ + int i, c; + assert( nData > 0 ); + if ( nCtrl == 0 ) + return pData[0]; + assert( nData <= (1 << nCtrl) ); + for ( c = 0; c < nCtrl; c++ ) + { + for ( i = 0; i < nData/2; i++ ) + pData[i] = Mini_AigMux( p, pCtrl[c], pData[2*i+1], pData[2*i] ); + if ( nData & 1 ) + pData[i++] = Mini_AigMux( p, pCtrl[c], 0, pData[nData-1] ); + nData = i; + } + assert( nData == 1 ); + return pData[0]; +} +static int Mini_AigMuxMulti_rec( Mini_Aig_t * p, int * pCtrl, int * pData, int nData ) +{ + int Res0, Res1; + assert( nData > 0 ); + if ( nData == 1 ) + return pData[0]; + assert( nData % 2 == 0 ); + Res0 = Mini_AigMuxMulti_rec( p, pCtrl+1, pData, nData/2 ); + Res1 = Mini_AigMuxMulti_rec( p, pCtrl+1, pData+nData/2, nData/2 ); + return Mini_AigMux( p, pCtrl[0], Res1, Res0 ); +} +static Mini_Aig_t * Mini_AigTransformXor( Mini_Aig_t * p ) +{ + Mini_Aig_t * pNew = Mini_AigStart(); + int i, * pCopy = MINI_AIG_ALLOC( int, Mini_AigNodeNum(p) ); + Mini_AigForEachPi( p, i ) + pCopy[i] = Mini_AigCreatePi(pNew); + Mini_AigForEachAnd( p, i ) + { + int iLit0 = Mini_AigNodeFanin0(p, i); + int iLit1 = Mini_AigNodeFanin1(p, i); + iLit0 = Mini_AigLitNotCond( pCopy[Mini_AigLit2Var(iLit0)], Mini_AigLitIsCompl(iLit0) ); + iLit1 = Mini_AigLitNotCond( pCopy[Mini_AigLit2Var(iLit1)], Mini_AigLitIsCompl(iLit1) ); + if ( iLit0 <= iLit1 ) + pCopy[i] = Mini_AigAnd( pNew, iLit0, iLit1 ); + else + pCopy[i] = Mini_AigXor( pNew, iLit0, iLit1 ); + } + Mini_AigForEachPo( p, i ) + { + int iLit0 = Mini_AigNodeFanin0( p, i ); + iLit0 = Mini_AigLitNotCond( pCopy[Mini_AigLit2Var(iLit0)], Mini_AigLitIsCompl(iLit0) ); + pCopy[i] = Mini_AigCreatePo( pNew, iLit0 ); + } + MINI_AIG_FREE( pCopy ); + return pNew; +} + + +static unsigned s_MiniTruths5[5] = { + 0xAAAAAAAA, + 0xCCCCCCCC, + 0xF0F0F0F0, + 0xFF00FF00, + 0xFFFF0000, +}; +static inline int Mini_AigTt5HasVar( unsigned t, int iVar ) +{ + return ((t << (1<= 0 && iVar < 6 ); + return (t & ~s_MiniTruths5[iVar]) | ((t & ~s_MiniTruths5[iVar]) << (1<= 0 && iVar < 6 ); + return (t & s_MiniTruths5[iVar]) | ((t & s_MiniTruths5[iVar]) >> (1< 0 ); + // find the topmost var + for ( Var = nVars-1; Var >= 0; Var-- ) + if ( Mini_AigTt5HasVar( Truth, Var ) ) + break; + assert( Var >= 0 ); + // cofactor + Lit0 = Mini_AigTruth( p, pVarLits, Var, Mini_AigTt5Cofactor0(Truth, Var) ); + Lit1 = Mini_AigTruth( p, pVarLits, Var, Mini_AigTt5Cofactor1(Truth, Var) ); + return Mini_AigMuxProp( p, pVarLits[Var], Lit1, Lit0 ); +} +static char * Mini_AigPhase( Mini_Aig_t * p ) +{ + char * pRes = MINI_AIG_CALLOC( char, Mini_AigNodeNum(p) ); + int i; + Mini_AigForEachAnd( p, i ) + { + int iFaninLit0 = Mini_AigNodeFanin0( p, i ); + int iFaninLit1 = Mini_AigNodeFanin1( p, i ); + int Phase0 = pRes[Mini_AigLit2Var(iFaninLit0)] ^ Mini_AigLitIsCompl(iFaninLit0); + int Phase1 = pRes[Mini_AigLit2Var(iFaninLit1)] ^ Mini_AigLitIsCompl(iFaninLit1); + pRes[i] = Phase0 & Phase1; + } + return pRes; +} + +// procedure to check the topological order during AIG construction +static int Mini_AigCheck( Mini_Aig_t * p ) +{ + int status = 1; + int i, iFaninLit0, iFaninLit1; + Mini_AigForEachAnd( p, i ) + { + // get the fanin literals of this AND node + iFaninLit0 = Mini_AigNodeFanin0( p, i ); + iFaninLit1 = Mini_AigNodeFanin1( p, i ); + // compare the fanin literals with the literal of the current node (2 * i) + if ( iFaninLit0 >= 2 * i ) + printf( "Fanin0 of AND node %d is not in a topological order.\n", i ), status = 0; + if ( iFaninLit1 >= 2 * i ) + printf( "Fanin0 of AND node %d is not in a topological order.\n", i ), status = 0; + } + Mini_AigForEachPo( p, i ) + { + // get the fanin literal of this PO node + iFaninLit0 = Mini_AigNodeFanin0( p, i ); + // compare the fanin literal with the literal of the current node (2 * i) + if ( iFaninLit0 >= 2 * i ) + printf( "Fanin0 of PO node %d is not in a topological order.\n", i ), status = 0; + } + return status; +} + +// procedure to dump MiniAIG into a Verilog file +static void Mini_AigDumpVerilog( char * pFileName, char * pModuleName, Mini_Aig_t * p ) +{ + int i, k, iFaninLit0, iFaninLit1, Length = strlen(pModuleName), nPos = Mini_AigPoNum(p); + char * pObjIsPi = MINI_AIG_CALLOC( char, Mini_AigNodeNum(p) ); + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) { printf( "Cannot open output file %s\n", pFileName ); MINI_AIG_FREE( pObjIsPi ); return; } + // write interface + //fprintf( pFile, "// This MiniAIG dump was produced by ABC on %s\n\n", Extra_TimeStamp() ); + fprintf( pFile, "module %s (\n", pModuleName ); + if ( Mini_AigPiNum(p) > 0 ) + { + fprintf( pFile, "%*sinput wire", Length+10, "" ); + k = 0; + Mini_AigForEachPi( p, i ) + { + if ( k++ % 12 == 0 ) fprintf( pFile, "\n%*s", Length+10, "" ); + fprintf( pFile, "i%d, ", i ); + pObjIsPi[i] = 1; + } + } + fprintf( pFile, "\n%*soutput wire", Length+10, "" ); + k = 0; + Mini_AigForEachPo( p, i ) + { + if ( k++ % 12 == 0 ) fprintf( pFile, "\n%*s", Length+10, "" ); + fprintf( pFile, "o%d%s", i, k==nPos ? "":", " ); + } + fprintf( pFile, "\n%*s);\n\n", Length+8, "" ); + // write LUTs + Mini_AigForEachAnd( p, i ) + { + iFaninLit0 = Mini_AigNodeFanin0( p, i ); + iFaninLit1 = Mini_AigNodeFanin1( p, i ); + fprintf( pFile, " assign n%d = ", i ); + fprintf( pFile, "%s%c%d", (iFaninLit0 & 1) ? "~":"", pObjIsPi[iFaninLit0 >> 1] ? 'i':'n', iFaninLit0 >> 1 ); + fprintf( pFile, " & " ); + fprintf( pFile, "%s%c%d", (iFaninLit1 & 1) ? "~":"", pObjIsPi[iFaninLit1 >> 1] ? 'i':'n', iFaninLit1 >> 1 ); + fprintf( pFile, ";\n" ); + } + // write assigns + fprintf( pFile, "\n" ); + Mini_AigForEachPo( p, i ) + { + iFaninLit0 = Mini_AigNodeFanin0( p, i ); + fprintf( pFile, " assign o%d = ", i ); + fprintf( pFile, "%s%c%d", (iFaninLit0 & 1) ? "~":"", pObjIsPi[iFaninLit0 >> 1] ? 'i':'n', iFaninLit0 >> 1 ); + fprintf( pFile, ";\n" ); + } + fprintf( pFile, "\nendmodule // %s \n\n\n", pModuleName ); + MINI_AIG_FREE( pObjIsPi ); + fclose( pFile ); +} + +// procedure to dump MiniAIG into a BLIF file +static void Mini_AigDumpBlif( char * pFileName, char * pModuleName, Mini_Aig_t * p, int fVerbose ) +{ + int i, k, iFaninLit0, iFaninLit1; + char * pObjIsPi = MINI_AIG_FALLOC( char, Mini_AigNodeNum(p) ); + FILE * pFile = fopen( pFileName, "wb" ); + assert( Mini_AigPiNum(p) <= 26 ); + if ( pFile == NULL ) { printf( "Cannot open output file %s\n", pFileName ); MINI_AIG_FREE( pObjIsPi ); return; } + // write interface + //fprintf( pFile, "// This MiniAIG dump was produced by ABC on %s\n\n", Extra_TimeStamp() ); + fprintf( pFile, ".model %s\n", pModuleName ); + if ( Mini_AigPiNum(p) ) + { + k = 0; + fprintf( pFile, ".inputs" ); + Mini_AigForEachPi( p, i ) + { + pObjIsPi[i] = k; + fprintf( pFile, " %c", (char)('a'+k++) ); + } + } + k = 0; + fprintf( pFile, "\n.outputs" ); + Mini_AigForEachPo( p, i ) + fprintf( pFile, " o%d", k++ ); + fprintf( pFile, "\n\n" ); + // write LUTs + Mini_AigForEachAnd( p, i ) + { + iFaninLit0 = Mini_AigNodeFanin0( p, i ); + iFaninLit1 = Mini_AigNodeFanin1( p, i ); + fprintf( pFile, ".names" ); + if ( pObjIsPi[iFaninLit0 >> 1] >= 0 ) + fprintf( pFile, " %c", (char)('a'+pObjIsPi[iFaninLit0 >> 1]) ); + else + fprintf( pFile, " n%d", iFaninLit0 >> 1 ); + if ( pObjIsPi[iFaninLit1 >> 1] >= 0 ) + fprintf( pFile, " %c", (char)('a'+pObjIsPi[iFaninLit1 >> 1]) ); + else + fprintf( pFile, " n%d", iFaninLit1 >> 1 ); + fprintf( pFile, " n%d\n", i ); + if ( iFaninLit0 < iFaninLit1 ) + fprintf( pFile, "%d%d 1\n", !(iFaninLit0 & 1), !(iFaninLit1 & 1) ); + else if ( !(iFaninLit0 & 1) == !(iFaninLit1 & 1) ) + fprintf( pFile, "10 1\n01 1\n" ); + else + fprintf( pFile, "00 1\n11 1\n" ); + } + // write assigns + fprintf( pFile, "\n" ); + k = 0; + Mini_AigForEachPo( p, i ) + { + iFaninLit0 = Mini_AigNodeFanin0( p, i ); + fprintf( pFile, ".names" ); + if ( pObjIsPi[iFaninLit0 >> 1] >= 0 ) + fprintf( pFile, " %c", (char)('a'+pObjIsPi[iFaninLit0 >> 1]) ); + else + fprintf( pFile, " n%d", iFaninLit0 >> 1 ); + fprintf( pFile, " o%d\n", k++ ); + fprintf( pFile, "%d 1\n", !(iFaninLit0 & 1) ); + } + fprintf( pFile, ".end\n\n" ); + MINI_AIG_FREE( pObjIsPi ); + fclose( pFile ); + if ( fVerbose ) + printf( "Written MiniAIG into the BLIF file \"%s\".\n", pFileName ); +} + + +// checks if MiniAIG is normalized (first inputs, then internal nodes, then outputs) +static int Mini_AigIsNormalized( Mini_Aig_t * p ) +{ + int nCiNum = Mini_AigPiNum(p); + int nCoNum = Mini_AigPoNum(p); + int i, nOffset = 1; + for ( i = 0; i < nCiNum; i++ ) + if ( !Mini_AigNodeIsPi( p, nOffset+i ) ) + return 0; + nOffset = Mini_AigNodeNum(p) - nCoNum; + for ( i = 0; i < nCoNum; i++ ) + if ( !Mini_AigNodeIsPo( p, nOffset+i ) ) + return 0; + return 1; +} + + +//////////////////////////////////////////////////////////////////////// +/// MiniAIG reading from / write into AIGER /// +//////////////////////////////////////////////////////////////////////// + +static unsigned Mini_AigerReadUnsigned( FILE * pFile ) +{ + unsigned x = 0, i = 0; + unsigned char ch; + while ((ch = fgetc(pFile)) & 0x80) + x |= (ch & 0x7f) << (7 * i++); + return x | (ch << (7 * i)); +} +static void Mini_AigerWriteUnsigned( FILE * pFile, unsigned x ) +{ + unsigned char ch; + while (x & ~0x7f) + { + ch = (x & 0x7f) | 0x80; + fputc( ch, pFile ); + x >>= 7; + } + ch = x; + fputc( ch, pFile ); +} +static int * Mini_AigerReadInt( char * pFileName, int * pnObjs, int * pnIns, int * pnLatches, int * pnOuts, int * pnAnds ) +{ + int i, Temp, nTotal, nObjs, nIns, nLatches, nOuts, nAnds, * pObjs; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + fprintf( stdout, "Mini_AigerRead(): Cannot open the output file \"%s\".\n", pFileName ); + return NULL; + } + if ( fgetc(pFile) != 'a' || fgetc(pFile) != 'i' || fgetc(pFile) != 'g' ) + { + fprintf( stdout, "Mini_AigerRead(): Can only read binary AIGER.\n" ); + fclose( pFile ); + return NULL; + } + if ( fscanf(pFile, "%d %d %d %d %d", &nTotal, &nIns, &nLatches, &nOuts, &nAnds) != 5 ) + { + fprintf( stdout, "Mini_AigerRead(): Cannot read the header line.\n" ); + fclose( pFile ); + return NULL; + } + if ( nTotal != nIns + nLatches + nAnds ) + { + fprintf( stdout, "The number of objects does not match.\n" ); + fclose( pFile ); + return NULL; + } + nObjs = 1 + nIns + 2*nLatches + nOuts + nAnds; + pObjs = MINI_AIG_CALLOC( int, nObjs * 2 ); + for ( i = 0; i <= nIns + nLatches; i++ ) + pObjs[2*i] = pObjs[2*i+1] = MINI_AIG_NULL; + // read flop input literals + for ( i = 0; i < nLatches; i++ ) + { + while ( fgetc(pFile) != '\n' ); + fscanf( pFile, "%d", &Temp ); + pObjs[2*(nObjs-nLatches+i)+0] = Temp; + pObjs[2*(nObjs-nLatches+i)+1] = MINI_AIG_NULL; + } + // read output literals + for ( i = 0; i < nOuts; i++ ) + { + while ( fgetc(pFile) != '\n' ); + fscanf( pFile, "%d", &Temp ); + pObjs[2*(nObjs-nOuts-nLatches+i)+0] = Temp; + pObjs[2*(nObjs-nOuts-nLatches+i)+1] = MINI_AIG_NULL; + } + // read the binary part + while ( fgetc(pFile) != '\n' ); + for ( i = 0; i < nAnds; i++ ) + { + int uLit = 2*(1+nIns+nLatches+i); + int uLit1 = uLit - Mini_AigerReadUnsigned( pFile ); + int uLit0 = uLit1 - Mini_AigerReadUnsigned( pFile ); + pObjs[uLit+0] = uLit0; + pObjs[uLit+1] = uLit1; + } + fclose( pFile ); + if ( pnObjs ) *pnObjs = nObjs; + if ( pnIns ) *pnIns = nIns; + if ( pnLatches ) *pnLatches = nLatches; + if ( pnOuts ) *pnOuts = nOuts; + if ( pnAnds ) *pnAnds = nAnds; + return pObjs; +} +static Mini_Aig_t * Mini_AigerRead( char * pFileName, int fVerbose ) +{ + Mini_Aig_t * p; + int nObjs, nIns, nLatches, nOuts, nAnds, * pObjs = Mini_AigerReadInt( pFileName, &nObjs, &nIns, &nLatches, &nOuts, &nAnds ); + if ( pObjs == NULL ) + return NULL; + p = MINI_AIG_CALLOC( Mini_Aig_t, 1 ); + p->nCap = 2*nObjs; + p->nSize = 2*nObjs; + p->nRegs = nLatches; + p->pArray = pObjs; + if ( fVerbose ) + printf( "Loaded MiniAIG from the AIGER file \"%s\".\n", pFileName ); + return p; +} + +static void Mini_AigerWriteInt( char * pFileName, int * pObjs, int nObjs, int nIns, int nLatches, int nOuts, int nAnds ) +{ + FILE * pFile = fopen( pFileName, "wb" ); int i; + if ( pFile == NULL ) + { + fprintf( stdout, "Mini_AigerWrite(): Cannot open the output file \"%s\".\n", pFileName ); + return; + } + fprintf( pFile, "aig %d %d %d %d %d\n", nIns + nLatches + nAnds, nIns, nLatches, nOuts, nAnds ); + for ( i = 0; i < nLatches; i++ ) + fprintf( pFile, "%d\n", pObjs[2*(nObjs-nLatches+i)+0] ); + for ( i = 0; i < nOuts; i++ ) + fprintf( pFile, "%d\n", pObjs[2*(nObjs-nOuts-nLatches+i)+0] ); + for ( i = 0; i < nAnds; i++ ) + { + int uLit = 2*(1+nIns+nLatches+i); + int uLit0 = pObjs[uLit+0]; + int uLit1 = pObjs[uLit+1]; + Mini_AigerWriteUnsigned( pFile, uLit - uLit1 ); + Mini_AigerWriteUnsigned( pFile, uLit1 - uLit0 ); + } + fprintf( pFile, "c\n" ); + fclose( pFile ); +} +static void Mini_AigerWrite( char * pFileName, Mini_Aig_t * p, int fVerbose ) +{ + int i, nIns = 0, nOuts = 0, nAnds = 0; + assert( Mini_AigIsNormalized(p) ); + for ( i = 1; i < Mini_AigNodeNum(p); i++ ) + { + if ( Mini_AigNodeIsPi(p, i) ) + nIns++; + else if ( Mini_AigNodeIsPo(p, i) ) + nOuts++; + else + nAnds++; + } + Mini_AigerWriteInt( pFileName, p->pArray, p->nSize/2, nIns - p->nRegs, p->nRegs, nOuts - p->nRegs, nAnds ); + if ( fVerbose ) + printf( "Written MiniAIG into the AIGER file \"%s\".\n", pFileName ); +} +static void Mini_AigerTest( char * pFileNameIn, char * pFileNameOut ) +{ + Mini_Aig_t * p = Mini_AigerRead( pFileNameIn, 1 ); + if ( p == NULL ) + return; + printf( "Finished reading input file \"%s\".\n", pFileNameIn ); + Mini_AigerWrite( pFileNameOut, p, 1 ); + printf( "Finished writing output file \"%s\".\n", pFileNameOut ); + Mini_AigStop( p ); +} + +/* +int main( int argc, char ** argv ) +{ + if ( argc != 3 ) + return 0; + Mini_AigerTest( argv[1], argv[2] ); + return 1; +} +*/ + +/* +#include "aig/miniaig/miniaig.h" + +// this procedure creates a MiniAIG for function F = a*b + ~c and writes it into a file "test.aig" +void Mini_AigTest() +{ + Mini_Aig_t * p = Mini_AigStart(); // create empty AIG manager (contains only const0 node) + int litApos = Mini_AigCreatePi( p ); // create input A (returns pos lit of A) + int litBpos = Mini_AigCreatePi( p ); // create input B (returns pos lit of B) + int litCpos = Mini_AigCreatePi( p ); // create input C (returns pos lit of C) + int litCneg = Mini_AigLitNot( litCpos ); // neg lit of C + int litAnd = Mini_AigAnd( p, litApos, litBpos ); // lit for a*b + int litOr = Mini_AigOr( p, litAnd, litCneg ); // lit for a*b + ~c + Mini_AigCreatePo( p, litOr ); // create primary output + Mini_AigerWrite( "test.aig", p, 1 ); // write the result into a file + Mini_AigStop( p ); // deallocate MiniAIG +} +*/ + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#ifndef _VERIFIC_DATABASE_H_ +ABC_NAMESPACE_HEADER_END +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/yosys/abc/src/aig/miniaig/minilut.h b/yosys/abc/src/aig/miniaig/minilut.h new file mode 100644 index 00000000000..2a27ccadbe6 --- /dev/null +++ b/yosys/abc/src/aig/miniaig/minilut.h @@ -0,0 +1,320 @@ +/**CFile**************************************************************** + + FileName [minilut.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Minimalistic representation of LUT mapped network.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - September 29, 2012.] + + Revision [$Id: minilut.h,v 1.00 2012/09/29 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef MINI_LUT__mini_lut_h +#define MINI_LUT__mini_lut_h + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +ABC_NAMESPACE_HEADER_START + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +#define MINI_LUT_NULL (0x7FFFFFFF) +#define MINI_LUT_NULL2 (0x7FFFFFFE) +#define MINI_LUT_START_SIZE (0x000000FF) + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Mini_Lut_t_ Mini_Lut_t; +struct Mini_Lut_t_ +{ + int nCap; + int nSize; + int nRegs; + int LutSize; + int * pArray; + unsigned * pTruths; +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// memory management +#define MINI_LUT_ALLOC(type, num) ((type *) malloc(sizeof(type) * (num))) +#define MINI_LUT_CALLOC(type, num) ((type *) calloc((num), sizeof(type))) +#define MINI_LUT_FALLOC(type, num) ((type *) memset(malloc(sizeof(type) * (num)), 0xff, sizeof(type) * (num))) +#define MINI_LUT_FREE(obj) ((obj) ? (free((char *) (obj)), (obj) = 0) : 0) +#define MINI_LUT_REALLOC(type, obj, num) \ + ((obj) ? ((type *) realloc((char *)(obj), sizeof(type) * (num))) : \ + ((type *) malloc(sizeof(type) * (num)))) + +// compute truth table size measured in unsigned's +static int Mini_LutWordNum( int LutSize ) +{ + return LutSize > 5 ? 1 << (LutSize-5) : 1; +} + +// internal procedures +static void Mini_LutGrow( Mini_Lut_t * p, int nCapMin ) +{ + if ( p->nCap >= nCapMin ) + return; + p->pArray = MINI_LUT_REALLOC( int, p->pArray, nCapMin * p->LutSize ); + p->pTruths = MINI_LUT_REALLOC( unsigned, p->pTruths, nCapMin * Mini_LutWordNum(p->LutSize) ); + p->nCap = nCapMin; + assert( p->pArray ); + assert( p->pTruths ); +} +static void Mini_LutPush( Mini_Lut_t * p, int nVars, int * pVars, unsigned * pTruth ) +{ + int i, nWords = Mini_LutWordNum(p->LutSize); + if ( p->nSize == p->nCap ) + { + assert( p->LutSize*p->nSize < MINI_LUT_NULL/2 ); + if ( p->nCap < MINI_LUT_START_SIZE ) + Mini_LutGrow( p, MINI_LUT_START_SIZE ); + else + Mini_LutGrow( p, 2 * p->nCap ); + } + for ( i = 0; i < nVars; i++ ) + assert( pVars[i] >= 0 && pVars[i] < p->nSize ); + for ( i = 0; i < nVars; i++ ) + p->pArray[p->LutSize * p->nSize + i] = pVars[i]; + for ( ; i < p->LutSize; i++ ) + p->pArray[p->LutSize * p->nSize + i] = MINI_LUT_NULL; + for ( i = 0; i < nWords; i++ ) + p->pTruths[nWords * p->nSize + i] = pTruth? pTruth[i] : 0; + p->nSize++; +} + +// accessing fanins +static int Mini_LutNodeFanin( Mini_Lut_t * p, int Id, int k ) +{ + assert( Id >= 0 && Id < p->nSize ); + return p->pArray[p->LutSize*Id+k]; +} +static unsigned * Mini_LutNodeTruth( Mini_Lut_t * p, int Id ) +{ + assert( Id >= 0 && Id < p->nSize ); + return p->pTruths + Id * Mini_LutWordNum(p->LutSize); +} + +// working with LUTs +static int Mini_LutNodeConst0() { return 0; } +static int Mini_LutNodeConst1() { return 1; } + +static int Mini_LutNodeNum( Mini_Lut_t * p ) { return p->nSize; } +static int Mini_LutNodeIsConst( Mini_Lut_t * p, int Id ) { assert( Id >= 0 ); return Id == 0 || Id == 1; } +static int Mini_LutNodeIsPi( Mini_Lut_t * p, int Id ) { assert( Id >= 0 ); return Id > 1 && Mini_LutNodeFanin( p, Id, 0 ) == MINI_LUT_NULL; } +static int Mini_LutNodeIsPo( Mini_Lut_t * p, int Id ) { assert( Id >= 0 ); return Id > 1 && Mini_LutNodeFanin( p, Id, 0 ) != MINI_LUT_NULL && Mini_LutNodeFanin( p, Id, 1 ) == MINI_LUT_NULL2; } +static int Mini_LutNodeIsNode( Mini_Lut_t * p, int Id ) { assert( Id >= 0 ); return Id > 1 && Mini_LutNodeFanin( p, Id, 0 ) != MINI_LUT_NULL && Mini_LutNodeFanin( p, Id, 1 ) != MINI_LUT_NULL2; } + +static int Mini_LutSize( Mini_Lut_t * p ) { return p->LutSize; } + +// working with sequential AIGs +static int Mini_LutRegNum( Mini_Lut_t * p ) { return p->nRegs; } +static void Mini_LutSetRegNum( Mini_Lut_t * p, int n ) { p->nRegs = n; } + +// iterators through objects +#define Mini_LutForEachPi( p, i ) for (i = 2; i < Mini_LutNodeNum(p); i++) if ( !Mini_LutNodeIsPi(p, i) ) {} else +#define Mini_LutForEachPo( p, i ) for (i = 2; i < Mini_LutNodeNum(p); i++) if ( !Mini_LutNodeIsPo(p, i) ) {} else +#define Mini_LutForEachNode( p, i ) for (i = 2; i < Mini_LutNodeNum(p); i++) if ( !Mini_LutNodeIsNode(p, i) ) {} else + +// iterator through fanins +#define Mini_LutForEachFanin( p, i, Fan, k ) for (k = 0; (k < p->LutSize) && (Fan = Mini_LutNodeFanin(p, i, k)) < MINI_LUT_NULL2; k++) + +// constructor/destructor +static Mini_Lut_t * Mini_LutStart( int LutSize ) +{ + Mini_Lut_t * p; int i; + assert( LutSize >= 2 && LutSize <= 16 ); + p = MINI_LUT_CALLOC( Mini_Lut_t, 1 ); + p->LutSize = LutSize; + p->nCap = MINI_LUT_START_SIZE; + p->pArray = MINI_LUT_ALLOC( int, p->nCap * p->LutSize ); + p->pTruths = MINI_LUT_ALLOC( unsigned, p->nCap * Mini_LutWordNum(p->LutSize) ); + Mini_LutPush( p, 0, NULL, NULL ); // const0 + Mini_LutPush( p, 0, NULL, NULL ); // const1 + for ( i = 0; i < Mini_LutWordNum(p->LutSize); i++ ) + p->pTruths[i] = 0; + for ( i = 0; i < Mini_LutWordNum(p->LutSize); i++ ) + p->pTruths[Mini_LutWordNum(p->LutSize) + i] = ~0; + return p; +} +static void Mini_LutStop( Mini_Lut_t * p ) +{ + MINI_LUT_FREE( p->pArray ); + MINI_LUT_FREE( p->pTruths ); + MINI_LUT_FREE( p ); +} +static void Mini_LutPrintStats( Mini_Lut_t * p ) +{ + int i, nPis, nPos, nNodes; + nPis = 0; + Mini_LutForEachPi( p, i ) + nPis++; + nPos = 0; + Mini_LutForEachPo( p, i ) + nPos++; + nNodes = 0; + Mini_LutForEachNode( p, i ) + nNodes++; + printf( "PI = %d. PO = %d. LUT = %d. FF = %d.\n", nPis, nPos, nNodes, p->nRegs ); +} +static void Mini_LutPrint( Mini_Lut_t * p ) +{ + int i, k, Fan; + printf( "MiniLUT statistics: " ); + Mini_LutPrintStats( p ); + printf( "Printout of nodes:\n" ); + for ( i = 0; i < p->nSize; i++ ) + { + printf( "%6d : ", i ); + if ( Mini_LutNodeIsConst(p, i) ) + printf( "Const%d", i ); + else if ( Mini_LutNodeIsPi(p, i) ) + printf( "PI" ); + else if ( Mini_LutNodeIsPo(p, i) ) + printf( "PO" ); + else if ( Mini_LutNodeIsNode(p, i) ) + { + printf( "LUT%d Fanins:", p->LutSize ); + Mini_LutForEachFanin( p, i, Fan, k ) + printf( " %6d", Fan ); + while ( k++ < p->LutSize ) + printf( " " ); + printf( " Function: " ); + for ( k = 31; k >= 0; k-- ) + printf( "%c", '0' + ((p->pTruths[i] >> k) & 1) ); + } + printf( "\n" ); + } + printf( "End of printout.\n" ); +} + +// serialization +static void Mini_LutDump( Mini_Lut_t * p, char * pFileName ) +{ + FILE * pFile; + int RetValue; + pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file for writing \"%s\".\n", pFileName ); + return; + } + RetValue = (int)fwrite( &p->nSize, sizeof(int), 1, pFile ); + RetValue = (int)fwrite( &p->nRegs, sizeof(int), 1, pFile ); + RetValue = (int)fwrite( &p->LutSize, sizeof(int), 1, pFile ); + RetValue = (int)fwrite( p->pArray, sizeof(int), p->nSize * p->LutSize, pFile ); + RetValue = (int)fwrite( p->pTruths, sizeof(int), p->nSize * Mini_LutWordNum(p->LutSize), pFile ); + fclose( pFile ); +} +static Mini_Lut_t * Mini_LutLoad( char * pFileName ) +{ + Mini_Lut_t * p; + FILE * pFile; + int RetValue, nSize; + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file for reading \"%s\".\n", pFileName ); + return NULL; + } + RetValue = (int)fread( &nSize, sizeof(int), 1, pFile ); + p = MINI_LUT_CALLOC( Mini_Lut_t, 1 ); + p->nSize = p->nCap = nSize; + RetValue = (int)fread( &p->nRegs, sizeof(int), 1, pFile ); + RetValue = (int)fread( &p->LutSize, sizeof(int), 1, pFile ); + p->pArray = MINI_LUT_ALLOC( int, p->nCap * p->LutSize ); + p->pTruths = MINI_LUT_ALLOC( unsigned, p->nCap * Mini_LutWordNum(p->LutSize) ); + RetValue = (int)fread( p->pArray, sizeof(int), p->nCap * p->LutSize, pFile ); + RetValue = (int)fread( p->pTruths, sizeof(int), p->nCap * Mini_LutWordNum(p->LutSize), pFile ); + fclose( pFile ); + return p; +} + + +// creating nodes +// (constant nodes are created when LUT manager is created) +static int Mini_LutCreatePi( Mini_Lut_t * p ) +{ + Mini_LutPush( p, 0, NULL, NULL ); + return p->nSize - 1; +} +static int Mini_LutCreatePo( Mini_Lut_t * p, int Var0 ) +{ + assert( Var0 >= 0 && Var0 < p->nSize ); + Mini_LutPush( p, 1, &Var0, NULL ); + // mark PO by setting its 2nd fanin to the special number + p->pArray[p->LutSize*(p->nSize - 1)+1] = MINI_LUT_NULL2; + return p->nSize - 1; +} + +// create LUT +static int Mini_LutCreateNode( Mini_Lut_t * p, int nVars, int * pVars, unsigned * pTruth ) +{ + assert( nVars >= 0 && nVars <= p->LutSize ); + Mini_LutPush( p, nVars, pVars, pTruth ); + return p->nSize - 1; +} + +// procedure to check the topological order during AIG construction +static int Mini_LutCheck( Mini_Lut_t * p ) +{ + int status = 1; + int i, k, iFaninVar; + Mini_LutForEachNode( p, i ) + { + for ( k = 0; k < p->LutSize; k++ ) + { + iFaninVar = Mini_LutNodeFanin( p, i, k ); + if ( iFaninVar == MINI_LUT_NULL ) + continue; + if ( iFaninVar >= p->LutSize * i ) + printf( "Fanin %d of LUT node %d is not in a topological order.\n", k, i ), status = 0; + } + } + Mini_LutForEachPo( p, i ) + { + iFaninVar = Mini_LutNodeFanin( p, i, 0 ); + if ( iFaninVar >= p->LutSize * i ) + printf( "Fanin %d of PO node %d is not in a topological order.\n", k, i ), status = 0; + } + return status; +} + + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_HEADER_END + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/yosys/abc/src/aig/miniaig/module.make b/yosys/abc/src/aig/miniaig/module.make new file mode 100644 index 00000000000..d6d908e733b --- /dev/null +++ b/yosys/abc/src/aig/miniaig/module.make @@ -0,0 +1 @@ +SRC += diff --git a/yosys/abc/src/aig/miniaig/ndr.h b/yosys/abc/src/aig/miniaig/ndr.h new file mode 100644 index 00000000000..1d2211f9636 --- /dev/null +++ b/yosys/abc/src/aig/miniaig/ndr.h @@ -0,0 +1,1169 @@ +/**CFile**************************************************************** + + FileName [ndr.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Format for word-level design representation.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - August 22, 2014.] + + Revision [$Id: ndr.h,v 1.00 2014/09/12 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__base__ndr__ndr_h +#define ABC__base__ndr__ndr_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#include "abcOper.h" + +#ifndef _YOSYS_ +ABC_NAMESPACE_HEADER_START +#endif + +#ifdef _WIN32 +#define inline __inline +#endif + +/* + For the lack of a better name, this format is called New Data Representation (NDR). + + NDR is designed as an interchange format to pass hierarchical word-level designs between the tools. + It is relatively simple, uses little memory, and can be easily converted into other ABC data-structures. + + This tutorial discusses how to construct the NDR representation of a hierarchical word-level design. + + First, all names used in the design (including the design name, module names, port names, net names, + instance names, etc) are hashed into 1-based integers called "name IDs". Nets are not explicitly represented. + The connectivity of a design object is established by specifying name IDs of the nets connected to the object. + Object inputs are name IDs of the driving nets; object outputs are name IDs of the driven nets. + + The design is initialized using procedure Ndr_Create(), which takes the design name as an argument. + A module in the design is initialized using procedure Ndr_AddModule(), which takes the design and + the module name as arguments. Objects are added to a module in any order using procedure Ndr_AddObject(). + + Primary input and primary output objects should be explicitly created, as shown in the examples below. + + Instances of known operators listed in file "abcOper.h" are assumed to have one output. The only known + issue due to this restriction concerns the adder, which produces the sum and the carry-out. To make sure the + adder instance has only one output, the carry-out has to be concatenated with the sum before the adder + instance is created in the NDR format. + + Instances of hierarchical modules defined by the user can have multiple outputs. + + Bit-slice and concatenation operators should be represented as separate objects. + + If the ordering of inputs/outputs/flops of a module is not provided as a separate record in NDR format, + their ordering is determined by the order of their appearance in the NDR description of the module. + + If left limit and right limit of a bit-range are equal, it is assumed that the range contains one bit + + Word-level constants are represented as char-strings given in the same way as they would appear in a Verilog + file. For example, the 16-bit constant 10 is represented as a string "4'b1010" and is given as an argument + (char * pFunction) to the procedure Ndr_AddObject(). + + Currently two types of flops are supported: a simple flop with implicit clock and two fanins (data and init) + and a complex flop with 8 fanins (clock, data, reset, set, enable, async, sre, init), as shown in the examples below. + + The initial value of a flop is represented by input "init", which can be driven by a constant or by a primary + input of the module. If it is a primary input, is it assumed that the flop is not initialized. If the input + "init" is not driven, it is assumed that the flop is initialized to 0. + + Memory read and write ports are supported, as shown in the example below. + + (to be continued) +*/ + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +// record types +typedef enum { + NDR_NONE = 0, // 0: unused + NDR_DESIGN, // 1: design (or library of modules) + NDR_MODULE, // 2: one module + NDR_OBJECT, // 3: object + NDR_INPUT, // 4: input + NDR_OUTPUT, // 5: output + NDR_OPERTYPE, // 6: operator type (buffer, shifter, adder, etc) + NDR_NAME, // 7: name + NDR_RANGE, // 8: bit range + NDR_FUNCTION, // 9: specified for some operators (PLAs, etc) + NDR_TARGET, // 10: target + NDR_UNKNOWN // 11: unknown +} Ndr_RecordType_t; + + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +// this is an internal procedure, which is not seen by the user +typedef struct Ndr_Data_t_ Ndr_Data_t; +struct Ndr_Data_t_ +{ + int nSize; + int nCap; + unsigned char * pHead; + unsigned int * pBody; +}; + +static inline int Ndr_DataType( Ndr_Data_t * p, int i ) { assert( p->pHead[i] ); return (int)p->pHead[i]; } +static inline int Ndr_DataSize( Ndr_Data_t * p, int i ) { return Ndr_DataType(p, i) > NDR_OBJECT ? 1 : p->pBody[i]; } +static inline int Ndr_DataEntry( Ndr_Data_t * p, int i ) { return (int)p->pBody[i]; } +static inline int * Ndr_DataEntryP( Ndr_Data_t * p, int i ) { return (int *)p->pBody + i; } +static inline int Ndr_DataEnd( Ndr_Data_t * p, int i ) { return i + p->pBody[i]; } +static inline void Ndr_DataAddTo( Ndr_Data_t * p, int i, int Add ) { assert(Ndr_DataType(p, i) <= NDR_OBJECT); p->pBody[i] += Add; } +static inline void Ndr_DataPush( Ndr_Data_t * p, int Type, int Entry ) { p->pHead[p->nSize] = Type; p->pBody[p->nSize++] = Entry; } + +#define NDR_ALLOC(type, num) ((type *) malloc(sizeof(type) * (size_t)(num))) + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +// iterates over modules in the design +#define Ndr_DesForEachMod( p, Mod ) \ + for ( Mod = 1; Mod < Ndr_DataEntry(p, 0); Mod += Ndr_DataSize(p, Mod) ) if (Ndr_DataType(p, Mod) != NDR_MODULE) {} else + +// iterates over objects in a module +#define Ndr_ModForEachObj( p, Mod, Obj ) \ + for ( Obj = Mod + 1; Obj < Ndr_DataEnd(p, Mod); Obj += Ndr_DataSize(p, Obj) ) if (Ndr_DataType(p, Obj) != NDR_OBJECT) {} else + +// iterates over records in an object +#define Ndr_ObjForEachEntry( p, Obj, Ent ) \ + for ( Ent = Obj + 1; Ent < Ndr_DataEnd(p, Obj); Ent += Ndr_DataSize(p, Ent) ) + +// iterates over primary inputs of a module +#define Ndr_ModForEachPi( p, Mod, Obj ) \ + Ndr_ModForEachObj( p, Mod, Obj ) if ( !Ndr_ObjIsType(p, Obj, ABC_OPER_CI) ) {} else + +// iteraots over primary outputs of a module +#define Ndr_ModForEachPo( p, Mod, Obj ) \ + Ndr_ModForEachObj( p, Mod, Obj ) if ( !Ndr_ObjIsType(p, Obj, ABC_OPER_CO) ) {} else + +// iterates over internal nodes of a module +#define Ndr_ModForEachNode( p, Mod, Obj ) \ + Ndr_ModForEachObj( p, Mod, Obj ) if ( Ndr_ObjIsType(p, Obj, ABC_OPER_CI) || Ndr_ObjIsType(p, Obj, ABC_OPER_CO) ) {} else + +// iterates over target signals of a module +#define Ndr_ModForEachTarget( p, Mod, Obj ) \ + for ( Obj = Mod + 1; Obj < Ndr_DataEnd(p, Mod); Obj += Ndr_DataSize(p, Obj) ) if (Ndr_DataType(p, Obj) != NDR_TARGET) {} else + +//////////////////////////////////////////////////////////////////////// +/// INTERNAL PROCEDURES /// +//////////////////////////////////////////////////////////////////////// + + +static inline void Ndr_DataResize( Ndr_Data_t * p, int Add ) +{ + if ( p->nSize + Add <= p->nCap ) + return; + p->nCap = 2 * p->nCap > p->nSize + Add ? 2 * p->nCap : p->nSize + Add; + p->pHead = (unsigned char*)realloc( p->pHead, p->nCap ); + p->pBody = (unsigned int *)realloc( p->pBody, 4*p->nCap ); +} +static inline void Ndr_DataPushRange( Ndr_Data_t * p, int RangeLeft, int RangeRight, int fSignedness ) +{ + if ( fSignedness ) + { + Ndr_DataPush( p, NDR_RANGE, RangeLeft ); + Ndr_DataPush( p, NDR_RANGE, RangeRight ); + Ndr_DataPush( p, NDR_RANGE, fSignedness ); + return; + } + if ( !RangeLeft && !RangeRight ) + return; + if ( RangeLeft == RangeRight ) + Ndr_DataPush( p, NDR_RANGE, RangeLeft ); + else + { + Ndr_DataPush( p, NDR_RANGE, RangeLeft ); + Ndr_DataPush( p, NDR_RANGE, RangeRight ); + } +} +static inline void Ndr_DataPushArray( Ndr_Data_t * p, int Type, int nArray, int * pArray ) +{ + if ( !nArray ) + return; + assert( nArray > 0 ); + Ndr_DataResize( p, nArray ); + memset( p->pHead + p->nSize, Type, (size_t)nArray ); + memcpy( p->pBody + p->nSize, pArray, (size_t)4*nArray ); + p->nSize += nArray; +} +static inline void Ndr_DataPushString( Ndr_Data_t * p, int ObjType, int Type, char * pFunc ) +{ + int nBuffInts; + int * pBuff; + if ( !pFunc ) + return; + if ( ObjType == ABC_OPER_LUT ) + { + //word Truth = (word)pFunc; + //Ndr_DataPushArray( p, Type, 2, (int *)&Truth ); + int nInts = (strlen(pFunc) + 1 + sizeof(int) - 1) / sizeof(int); + Ndr_DataPushArray( p, Type, nInts, (int *)&pFunc ); + } + else + { + nBuffInts = ((int)strlen(pFunc) + 4) / 4; + pBuff = (int *)calloc( 1, 4*nBuffInts ); + memcpy( pBuff, pFunc, strlen(pFunc) ); + Ndr_DataPushArray( p, Type, nBuffInts, pBuff ); + free( pBuff ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// VERILOG WRITING /// +//////////////////////////////////////////////////////////////////////// + +static inline int Ndr_ObjReadEntry( Ndr_Data_t * p, int Obj, int Type ) +{ + int Ent; + Ndr_ObjForEachEntry( p, Obj, Ent ) + if ( Ndr_DataType(p, Ent) == Type ) + return Ndr_DataEntry(p, Ent); + return -1; +} +static inline int Ndr_ObjReadArray( Ndr_Data_t * p, int Obj, int Type, int ** ppStart ) +{ + int Ent, Counter = 0; *ppStart = NULL; + Ndr_ObjForEachEntry( p, Obj, Ent ) + if ( Ndr_DataType(p, Ent) == Type ) + { + Counter++; + if ( *ppStart == NULL ) + *ppStart = (int *)p->pBody + Ent; + } + else if ( *ppStart ) + return Counter; + return Counter; +} +static inline int Ndr_ObjIsType( Ndr_Data_t * p, int Obj, int Type ) +{ + int Ent; + Ndr_ObjForEachEntry( p, Obj, Ent ) + if ( Ndr_DataType(p, Ent) == NDR_OPERTYPE ) + return (int)(Ndr_DataEntry(p, Ent) == Type); + return -1; +} +static inline int Ndr_ObjReadBody( Ndr_Data_t * p, int Obj, int Type ) +{ + int Ent; + Ndr_ObjForEachEntry( p, Obj, Ent ) + if ( Ndr_DataType(p, Ent) == Type ) + return Ndr_DataEntry(p, Ent); + return -1; +} +static inline int * Ndr_ObjReadBodyP( Ndr_Data_t * p, int Obj, int Type ) +{ + int Ent; + Ndr_ObjForEachEntry( p, Obj, Ent ) + if ( Ndr_DataType(p, Ent) == Type ) + return Ndr_DataEntryP(p, Ent); + return NULL; +} +static inline void Ndr_ObjWriteRange( Ndr_Data_t * p, int Obj, FILE * pFile, int fSkipBin ) +{ + int * pArray, nArray = Ndr_ObjReadArray( p, Obj, NDR_RANGE, &pArray ); + if ( (nArray == 0 || nArray == 1) && fSkipBin ) + return; + if ( nArray == 3 && fSkipBin ) + fprintf( pFile, "signed " ); + else if ( nArray == 1 ) + { + if ( fSkipBin ) + fprintf( pFile, "[%d:%d]", pArray[0], pArray[0] ); + else + fprintf( pFile, "[%d]", pArray[0] ); + } + else if ( nArray == 0 ) + { + if ( fSkipBin ) + fprintf( pFile, "[%d:%d]", 0, 0 ); + else + fprintf( pFile, "[%d]", 0 ); + } + else + fprintf( pFile, "[%d:%d]", pArray[0], pArray[1] ); +} +static inline char * Ndr_ObjReadOutName( Ndr_Data_t * p, int Obj, char ** pNames ) +{ + return pNames[Ndr_ObjReadBody(p, Obj, NDR_OUTPUT)]; +} +static inline char * Ndr_ObjReadInName( Ndr_Data_t * p, int Obj, char ** pNames ) +{ + return pNames[Ndr_ObjReadBody(p, Obj, NDR_INPUT)]; +} + +static inline int Ndr_DataCiNum( Ndr_Data_t * p, int Mod ) +{ + int Obj, Count = 0; + Ndr_ModForEachPi( p, Mod, Obj ) + Count++; + return Count; +} +static inline int Ndr_DataCoNum( Ndr_Data_t * p, int Mod ) +{ + int Obj, Count = 0; + Ndr_ModForEachPo( p, Mod, Obj ) + Count++; + return Count; +} +static inline int Ndr_DataObjNum( Ndr_Data_t * p, int Mod ) +{ + int Obj, Count = 0; + Ndr_ModForEachObj( p, Mod, Obj ) + Count++; + return Count; +} + +// to write signal names, this procedure takes a mapping of name IDs into actual char-strings (pNames) +static inline void Ndr_WriteVerilogModule( FILE * pFile, void * pDesign, int Mod, char ** pNames, int fSimple ) +{ + Ndr_Data_t * p = (Ndr_Data_t *)pDesign; + int * pOuts = NDR_ALLOC( int, Ndr_DataCoNum(p, Mod) ); + int i, k, Obj, nArray, * pArray, fFirst = 1; + + fprintf( pFile, "\nmodule %s (\n ", pNames[Ndr_ObjReadEntry(p, Mod, NDR_NAME)] ); + + Ndr_ModForEachPi( p, Mod, Obj ) + fprintf( pFile, "%s, ", Ndr_ObjReadOutName(p, Obj, pNames) ); + + fprintf( pFile, "\n " ); + + Ndr_ModForEachPo( p, Mod, Obj ) + fprintf( pFile, "%s%s", fFirst ? "":", ", Ndr_ObjReadInName(p, Obj, pNames) ), fFirst = 0; + + fprintf( pFile, "\n);\n\n" ); + + Ndr_ModForEachPi( p, Mod, Obj ) + { + fprintf( pFile, " input " ); + Ndr_ObjWriteRange( p, Obj, pFile, 1 ); + fprintf( pFile, " %s;\n", Ndr_ObjReadOutName(p, Obj, pNames) ); + } + + i = 0; + Ndr_ModForEachPo( p, Mod, Obj ) + { + fprintf( pFile, " output " ); + Ndr_ObjWriteRange( p, Obj, pFile, 1 ); + fprintf( pFile, " %s;\n", Ndr_ObjReadInName(p, Obj, pNames) ); + pOuts[i++] = Ndr_ObjReadBody(p, Obj, NDR_INPUT); + } + + fprintf( pFile, "\n" ); + + Ndr_ModForEachNode( p, Mod, Obj ) + { + for ( k = 0; k < i; k++ ) + if ( pOuts[k] == Ndr_ObjReadBody(p, Obj, NDR_OUTPUT) ) + break; + if ( k < i ) + continue; + if ( Ndr_ObjReadOutName(p, Obj, pNames)[0] == '1' ) + continue; + fprintf( pFile, " wire " ); + Ndr_ObjWriteRange( p, Obj, pFile, 1 ); + fprintf( pFile, " %s;\n", Ndr_ObjReadOutName(p, Obj, pNames) ); + } + free( pOuts ); + + fprintf( pFile, "\n" ); + + Ndr_ModForEachNode( p, Mod, Obj ) + { + int i, Type = Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE); + if ( Type >= 256 ) + { + fprintf( pFile, " %s ", pNames[Ndr_ObjReadEntry(p, Type-256, NDR_NAME)] ); + if ( Ndr_ObjReadBody(p, Obj, NDR_NAME) > 0 ) + fprintf( pFile, "%s ", pNames[Ndr_ObjReadBody(p, Obj, NDR_NAME)] ); + fprintf( pFile, "( " ); + nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); + for ( i = 0; i < nArray; i++ ) + fprintf( pFile, "%s%s ", pNames[pArray[i]], i==nArray-1 ? "":"," ); + fprintf( pFile, ");\n" ); + continue; + } + if ( Type == ABC_OPER_DFF ) + { + fprintf( pFile, " %s ", "ABC_DFF" ); + if ( Ndr_ObjReadBody(p, Obj, NDR_NAME) > 0 ) + fprintf( pFile, "%s ", pNames[Ndr_ObjReadBody(p, Obj, NDR_NAME)] ); + fprintf( pFile, "( " ); + nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); + fprintf( pFile, ".q(%s), ", Ndr_ObjReadOutName(p, Obj, pNames) ); + fprintf( pFile, ".d(%s), ", pNames[pArray[0]] ); + fprintf( pFile, ".init(%s) ", pNames[pArray[1]] ); + fprintf( pFile, ");\n" ); + continue; + } + if ( Type == ABC_OPER_DFFRSE ) + { + fprintf( pFile, " %s ", "ABC_DFFRSE" ); + if ( Ndr_ObjReadBody(p, Obj, NDR_NAME) > 0 ) + fprintf( pFile, "%s ", pNames[Ndr_ObjReadBody(p, Obj, NDR_NAME)] ); + fprintf( pFile, "( " ); + nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); + fprintf( pFile, ".q(%s), ", Ndr_ObjReadOutName(p, Obj, pNames) ); + fprintf( pFile, ".d(%s), ", pNames[pArray[0]] ); + fprintf( pFile, ".clk(%s), ", pNames[pArray[1]] ); + fprintf( pFile, ".reset(%s), ", pNames[pArray[2]] ); + fprintf( pFile, ".set(%s), ", pNames[pArray[3]] ); + fprintf( pFile, ".enable(%s), ", pNames[pArray[4]] ); + fprintf( pFile, ".async(%s), ", pNames[pArray[5]] ); + fprintf( pFile, ".sre(%s), ", pNames[pArray[6]] ); + fprintf( pFile, ".init(%s) ", pNames[pArray[7]] ); + fprintf( pFile, ");\n" ); + continue; + } + if ( Type == ABC_OPER_RAMR ) + { + fprintf( pFile, " %s ", "ABC_READ" ); + if ( Ndr_ObjReadBody(p, Obj, NDR_NAME) > 0 ) + fprintf( pFile, "%s ", pNames[Ndr_ObjReadBody(p, Obj, NDR_NAME)] ); + fprintf( pFile, "( " ); + nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); + fprintf( pFile, ".data(%s), ", Ndr_ObjReadOutName(p, Obj, pNames) ); + fprintf( pFile, ".mem_in(%s), ", pNames[pArray[0]] ); + fprintf( pFile, ".addr(%s) ", pNames[pArray[1]] ); + fprintf( pFile, ");\n" ); + continue; + } + if ( Type == ABC_OPER_RAMW ) + { + fprintf( pFile, " %s ", "ABC_WRITE" ); + if ( Ndr_ObjReadBody(p, Obj, NDR_NAME) > 0 ) + fprintf( pFile, "%s ", pNames[Ndr_ObjReadBody(p, Obj, NDR_NAME)] ); + fprintf( pFile, "( " ); + nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); + fprintf( pFile, ".mem_out(%s), ", Ndr_ObjReadOutName(p, Obj, pNames) ); + fprintf( pFile, ".mem_in(%s), ", pNames[pArray[0]] ); + fprintf( pFile, ".addr(%s), ", pNames[pArray[1]] ); + fprintf( pFile, ".data(%s) ", pNames[pArray[2]] ); + fprintf( pFile, ");\n" ); + continue; + } + if ( fSimple ) + { + if ( Ndr_ObjReadOutName(p, Obj, pNames)[0] == '1' ) + continue; + nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); + fprintf( pFile, " %s ( %s", Abc_OperNameSimple(Type), Ndr_ObjReadOutName(p, Obj, pNames) ); + if ( nArray == 0 ) + fprintf( pFile, ", %s );\n", (char *)Ndr_ObjReadBodyP(p, Obj, NDR_FUNCTION) ); + else if ( nArray == 1 && Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE) == ABC_OPER_BIT_BUF ) + fprintf( pFile, ", %s );\n", pNames[pArray[0]] ); + else + { + for ( i = 0; i < nArray; i++ ) + fprintf( pFile, ", %s", pNames[pArray[i]] ); + fprintf( pFile, " );\n" ); + } + continue; + } + fprintf( pFile, " assign %s = ", Ndr_ObjReadOutName(p, Obj, pNames) ); + nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray ); + if ( nArray == 0 ) + fprintf( pFile, "%s;\n", (char *)Ndr_ObjReadBodyP(p, Obj, NDR_FUNCTION) ); + else if ( nArray == 1 && Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE) == ABC_OPER_BIT_BUF ) + fprintf( pFile, "%s;\n", pNames[pArray[0]] ); + else if ( Type == ABC_OPER_SLICE ) + fprintf( pFile, "%s", pNames[pArray[0]] ), + Ndr_ObjWriteRange( p, Obj, pFile, 0 ), + fprintf( pFile, ";\n" ); + else if ( Type == ABC_OPER_CONCAT ) + { + fprintf( pFile, "{" ); + for ( i = 0; i < nArray; i++ ) + fprintf( pFile, "%s%s", pNames[pArray[i]], i==nArray-1 ? "":", " ); + fprintf( pFile, "};\n" ); + } + else if ( nArray == 1 ) + fprintf( pFile, "%s %s;\n", Abc_OperName(Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE)), pNames[pArray[0]] ); + else if ( nArray == 2 ) + fprintf( pFile, "%s %s %s;\n", pNames[pArray[0]], Abc_OperName(Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE)), pNames[pArray[1]] ); + else if ( nArray == 3 && Type == ABC_OPER_ARI_ADD ) + fprintf( pFile, "%s + %s + %s;\n", pNames[pArray[0]], pNames[pArray[1]], pNames[pArray[2]] ); + else if ( Type == ABC_OPER_BIT_MUX ) + fprintf( pFile, "%s ? %s : %s;\n", pNames[pArray[0]], pNames[pArray[2]], pNames[pArray[1]] ); + else + fprintf( pFile, ";\n", Abc_OperName(Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE)) ); + } + + fprintf( pFile, "\nendmodule\n\n" ); +} + +// to write signal names, this procedure takes a mapping of name IDs into actual char-strings (pNames) +static inline void Ndr_WriteVerilog( char * pFileName, void * pDesign, char ** pNames, int fSimple ) +{ + Ndr_Data_t * p = (Ndr_Data_t *)pDesign; int Mod; + + FILE * pFile = pFileName ? fopen( pFileName, "wb" ) : stdout; + if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ? pFileName : "stdout" ); return; } + + Ndr_DesForEachMod( p, Mod ) + Ndr_WriteVerilogModule( pFile, p, Mod, pNames, fSimple ); + + if ( pFileName ) fclose( pFile ); +} + + +//////////////////////////////////////////////////////////////////////// +/// EXTERNAL PROCEDURES /// +//////////////////////////////////////////////////////////////////////// + +// creating a new module (returns pointer to the memory buffer storing the module info) +static inline void * Ndr_Create( int Name ) +{ + Ndr_Data_t * p = NDR_ALLOC( Ndr_Data_t, 1 ); + p->nSize = 0; + p->nCap = 16; + p->pHead = NDR_ALLOC( unsigned char, p->nCap ); + p->pBody = NDR_ALLOC( unsigned int, p->nCap * 4 ); + Ndr_DataPush( p, NDR_DESIGN, 0 ); + Ndr_DataPush( p, NDR_NAME, Name ); + Ndr_DataAddTo( p, 0, p->nSize ); + assert( p->nSize == 2 ); + assert( Name ); + return p; +} + +// creating a new module in an already started design +// returns module ID to be used when adding objects to the module +static inline int Ndr_AddModule( void * pDesign, int Name ) +{ + Ndr_Data_t * p = (Ndr_Data_t *)pDesign; + int Mod = p->nSize; + Ndr_DataResize( p, 6 ); + Ndr_DataPush( p, NDR_MODULE, 0 ); + Ndr_DataPush( p, NDR_NAME, Name ); + Ndr_DataAddTo( p, Mod, p->nSize - Mod ); + Ndr_DataAddTo( p, 0, p->nSize - Mod ); + assert( (int)p->pBody[0] == p->nSize ); + return Mod + 256; +} + +// adding a new object (input/output/flop/intenal node) to an already started module +// this procedure takes the design, the module ID, and the parameters of the boject +// (please note that all objects should be added to a given module before starting a new module) +static inline void Ndr_AddObject( void * pDesign, int ModuleId, + int ObjType, int InstName, + int RangeLeft, int RangeRight, int fSignedness, + int nInputs, int * pInputs, + int nOutputs, int * pOutputs, + char * pFunction ) +{ + Ndr_Data_t * p = (Ndr_Data_t *)pDesign; + int Mod = ModuleId - 256; + int Obj = p->nSize; assert( ObjType != 0 ); + Ndr_DataResize( p, 6 ); + Ndr_DataPush( p, NDR_OBJECT, 0 ); + Ndr_DataPush( p, NDR_OPERTYPE, ObjType ); + Ndr_DataPushRange( p, RangeLeft, RangeRight, fSignedness ); + if ( InstName ) + Ndr_DataPush( p, NDR_NAME, InstName ); + Ndr_DataPushArray( p, NDR_INPUT, nInputs, pInputs ); + Ndr_DataPushArray( p, NDR_OUTPUT, nOutputs, pOutputs ); + Ndr_DataPushString( p, ObjType, NDR_FUNCTION, pFunction ); + Ndr_DataAddTo( p, Obj, p->nSize - Obj ); + Ndr_DataAddTo( p, Mod, p->nSize - Obj ); + Ndr_DataAddTo( p, 0, p->nSize - Obj ); + assert( (int)p->pBody[0] == p->nSize ); +} + +// deallocate the memory buffer +static inline void Ndr_Delete( void * pDesign ) +{ + Ndr_Data_t * p = (Ndr_Data_t *)pDesign; + if ( !p ) return; + free( p->pHead ); + free( p->pBody ); + free( p ); +} + + +//////////////////////////////////////////////////////////////////////// +/// FILE READING AND WRITING /// +//////////////////////////////////////////////////////////////////////// + +// file reading/writing +static inline void * Ndr_Read( char * pFileName ) +{ + Ndr_Data_t * p; int nFileSize, RetValue; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for reading.\n", pFileName ); return NULL; } + // check file size + fseek( pFile, 0, SEEK_END ); + nFileSize = ftell( pFile ); + if ( nFileSize % 5 != 0 ) + return NULL; + assert( nFileSize % 5 == 0 ); + rewind( pFile ); + // create structure + p = NDR_ALLOC( Ndr_Data_t, 1 ); + p->nSize = p->nCap = nFileSize / 5; + p->pHead = NDR_ALLOC( unsigned char, p->nCap ); + p->pBody = NDR_ALLOC( unsigned int, p->nCap * 4 ); + RetValue = (int)fread( p->pBody, 4, p->nCap, pFile ); + RetValue = (int)fread( p->pHead, 1, p->nCap, pFile ); + assert( p->nSize == (int)p->pBody[0] ); + fclose( pFile ); + //printf( "Read the design from file \"%s\".\n", pFileName ); + return p; +} +static inline void Ndr_Write( char * pFileName, void * pDesign ) +{ + Ndr_Data_t * p = (Ndr_Data_t *)pDesign; int RetValue; + FILE * pFile = fopen( pFileName, "wb" ); + if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ? pFileName : "stdout" ); return; } + RetValue = (int)fwrite( p->pBody, 4, p->pBody[0], pFile ); + RetValue = (int)fwrite( p->pHead, 1, p->pBody[0], pFile ); + fclose( pFile ); + //printf( "Dumped the design into file \"%s\".\n", pFileName ); +} + + +//////////////////////////////////////////////////////////////////////// +/// TESTING PROCEDURE /// +//////////////////////////////////////////////////////////////////////// + +// This testing procedure creates and writes into a Verilog file +// the following design composed of one module + +// module add10 ( input [3:0] a, output [3:0] s ); +// wire [3:0] const10 = 4'b1010; +// assign s = a + const10; +// endmodule + +static inline void Ndr_ModuleTest() +{ + // name IDs + int NameIdA = 2; + int NameIdS = 3; + int NameIdC = 4; + // array of fanins of node s + int Fanins[2] = { NameIdA, NameIdC }; + // map name IDs into char strings + //char * ppNames[5] = { NULL, "add10", "a", "s", "const10" }; + + // create a new module + void * pDesign = Ndr_Create( 1 ); + + int ModuleID = Ndr_AddModule( pDesign, 1 ); + + // add objects to the modele + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 3, 0, 0, 0, NULL, 1, &NameIdA, NULL ); // no fanins + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CONST, 0, 3, 0, 0, 0, NULL, 1, &NameIdC, (char*)"4'b1010" ); // no fanins + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_ARI_ADD, 0, 3, 0, 0, 2, Fanins, 1, &NameIdS, NULL ); // fanins are a and const10 + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 3, 0, 0, 1, &NameIdS, 0, NULL, NULL ); // fanin is a + + // write Verilog for verification + //Ndr_WriteVerilog( NULL, pDesign, ppNames, 0 ); + Ndr_Write( (char*)"add4.ndr", pDesign ); + Ndr_Delete( pDesign ); +} + + + +// This testing procedure creates and writes into a Verilog file +// the following design composed of one adder divided into two + +// module add8 ( input [7:0] a, input [7:0] b, output [7:0] s, output co ); +// wire [3:0] a0 = a[3:0]; +// wire [3:0] b0 = b[3:0]; + +// wire [7:4] a1 = a[7:4]; +// wire [7:4] b1 = b[7:4]; + +// wire [4:0] r0 = a0 + b0; +// wire [3:0] s0 = r0[3:0]; +// wire rco = r0[4]; + +// wire [4:0] r1 = a1 + b1 + rco; +// wire [3:0] s1 = r1[3:0]; +// assign co = r1[4]; + +// assign s = {s1, s0}; +// endmodule + +static inline void Ndr_ModuleTestAdder() +{ +/* + // map name IDs into char strings + char * ppNames[20] = { NULL, + "a", "b", "s", "co", // 1, 2, 3, 4 + "a0", "a1", "b0", "b1", // 5, 6, 7, 8 + "r0", "s0", "rco", // 9, 10, 11 + "r1", "s1", "add8" // 12, 13, 14 + }; +*/ + // fanins + int FaninA = 1; + int FaninB = 2; + int FaninS = 3; + int FaninCO = 4; + + int FaninA0 = 5; + int FaninA1 = 6; + int FaninB0 = 7; + int FaninB1 = 8; + + int FaninR0 = 9; + int FaninS0 = 10; + int FaninRCO = 11; + + int FaninR1 = 12; + int FaninS1 = 13; + + int Fanins1[2] = { FaninA0, FaninB0 }; + int Fanins2[3] = { FaninA1, FaninB1, FaninRCO }; + int Fanins3[4] = { FaninS1, FaninS0 }; + + // create a new module + void * pDesign = Ndr_Create( 14 ); + + int ModuleID = Ndr_AddModule( pDesign, 14 ); + + // add objects to the modele + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 7, 0, 0, 0, NULL, 1, &FaninA, NULL ); // no fanins + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 7, 0, 0, 0, NULL, 1, &FaninB, NULL ); // no fanins + + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SLICE, 0, 3, 0, 0, 1, &FaninA, 1, &FaninA0, NULL ); // wire [3:0] a0 = a[3:0]; + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SLICE, 0, 3, 0, 0, 1, &FaninB, 1, &FaninB0, NULL ); // wire [3:0] b0 = a[3:0]; + + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SLICE, 0, 7, 4, 0, 1, &FaninA, 1, &FaninA1, NULL ); // wire [7:4] a1 = a[7:4]; + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SLICE, 0, 7, 4, 0, 1, &FaninB, 1, &FaninB1, NULL ); // wire [7:4] b1 = b[7:4]; + + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_ARI_ADD, 0, 4, 0, 0, 2, Fanins1, 1, &FaninR0, NULL ); // wire [4:0] r0 = a0 + b0; + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SLICE, 0, 3, 0, 0, 1, &FaninR0, 1, &FaninS0, NULL ); // wire [3:0] s0 = r0[3:0]; + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SLICE, 0, 4, 4, 0, 1, &FaninR0, 1, &FaninRCO, NULL ); // wire rco = r0[4]; + + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_ARI_ADD, 0, 4, 0, 0, 3, Fanins2, 1, &FaninR1, NULL ); // wire [4:0] r1 = a1 + b1 + rco; + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SLICE, 0, 3, 0, 0, 1, &FaninR1, 1, &FaninS1, NULL ); // wire [3:0] s1 = r1[3:0]; + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SLICE, 0, 4, 4, 0, 1, &FaninR1, 1, &FaninCO, NULL ); // assign co = r1[4]; + + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CONCAT, 0, 7, 0, 0, 2, Fanins3, 1, &FaninS, NULL ); // s = {s1, s0}; + + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 7, 0, 0, 1, &FaninS, 0, NULL, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 0, 0, 0, 1, &FaninCO, 0, NULL, NULL ); + + // write Verilog for verification + //Ndr_WriteVerilog( NULL, pDesign, ppNames, 0 ); + Ndr_Write( (char*)"add8.ndr", pDesign ); + Ndr_Delete( pDesign ); + +} + +// This testing procedure creates and writes into a Verilog file +// the following hierarchical design composed of two modules + +// module mux21w ( input sel, input [3:0] d1, input [3:0] d0, output [3:0] out ); +// assign out = sel ? d1 : d0; +// endmodule + +// module mux41w ( input [1:0] sel, input [15:0] d, output [3:0] out ); +// wire [3:0] t0, t1; +// wire [3:0] d0 = d[3:0]; +// wire [3:0] d1 = d[7:4]; +// wire [3:0] d2 = d[11:8]; +// wire [3:0] d3 = d[15:12]; +// wire sel0 = sel[0]; +// wire sel1 = sel[1]; +// mux21w i0 ( sel0, d1, d0, t0 ); +// mux21w i1 ( sel0, d3, d2, t1 ); +// mux21w i2 ( sel1, t1, t0, out ); +// endmodule + +static inline void Ndr_ModuleTestHierarchy() +{ +/* + // map name IDs into char strings + char * ppNames[20] = { NULL, + "mux21w", "mux41w", // 1, 2 + "sel", "d", "out", // 3, 4, 5 + "d0", "d1", "d2", "d3", // 6, 7, 8, 9 + "sel0", "sel1", // 10, 11, + "t0", "t1", // 12, 13 + "i0", "i1", "i2" // 14, 15, 16 + }; +*/ + // fanins + int FaninSel = 3; + int FaninSel0 = 10; + int FaninSel1 = 11; + int FaninD = 4; + int FaninD0 = 6; + int FaninD1 = 7; + int FaninD2 = 8; + int FaninD3 = 9; + int FaninT0 = 12; + int FaninT1 = 13; + int FaninOut = 5; + int Fanins1[3] = { FaninSel, FaninD1, FaninD0 }; + int Fanins3[3][3] = { {FaninSel0, FaninD1, FaninD0 }, + {FaninSel0, FaninD3, FaninD2 }, + {FaninSel1, FaninT1, FaninT0 } }; + + // create a new module + void * pDesign = Ndr_Create( 2 ); + + int Module21, Module41; + + Module21 = Ndr_AddModule( pDesign, 1 ); + + Ndr_AddObject( pDesign, Module21, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &FaninSel, NULL ); + Ndr_AddObject( pDesign, Module21, ABC_OPER_CI, 0, 3, 0, 0, 0, NULL, 1, &FaninD1, NULL ); + Ndr_AddObject( pDesign, Module21, ABC_OPER_CI, 0, 3, 0, 0, 0, NULL, 1, &FaninD0, NULL ); + Ndr_AddObject( pDesign, Module21, ABC_OPER_BIT_MUX, 0, 3, 0, 0, 3, Fanins1, 1, &FaninOut, NULL ); + Ndr_AddObject( pDesign, Module21, ABC_OPER_CO, 0, 3, 0, 0, 1, &FaninOut, 0, NULL, NULL ); + + Module41 = Ndr_AddModule( pDesign, 2 ); + + Ndr_AddObject( pDesign, Module41, ABC_OPER_CI, 0, 1, 0, 0, 0, NULL, 1, &FaninSel, NULL ); + Ndr_AddObject( pDesign, Module41, ABC_OPER_CI, 0, 15,0, 0, 0, NULL, 1, &FaninD, NULL ); + + Ndr_AddObject( pDesign, Module41, ABC_OPER_SLICE, 0, 3, 0, 0, 1, &FaninD, 1, &FaninD0, NULL ); + Ndr_AddObject( pDesign, Module41, ABC_OPER_SLICE, 0, 7, 4, 0, 1, &FaninD, 1, &FaninD1, NULL ); + Ndr_AddObject( pDesign, Module41, ABC_OPER_SLICE, 0, 11,8, 0, 1, &FaninD, 1, &FaninD2, NULL ); + Ndr_AddObject( pDesign, Module41, ABC_OPER_SLICE, 0, 15,12,0, 1, &FaninD, 1, &FaninD3, NULL ); + + Ndr_AddObject( pDesign, Module41, ABC_OPER_SLICE, 0, 0, 0, 0, 1, &FaninSel, 1, &FaninSel0, NULL ); + Ndr_AddObject( pDesign, Module41, ABC_OPER_SLICE, 0, 1, 1, 0, 1, &FaninSel, 1, &FaninSel1, NULL ); + + Ndr_AddObject( pDesign, Module41, Module21, 14, 3, 0, 0, 3, Fanins3[0], 1, &FaninT0, NULL ); + Ndr_AddObject( pDesign, Module41, Module21, 15, 3, 0, 0, 3, Fanins3[1], 1, &FaninT1, NULL ); + Ndr_AddObject( pDesign, Module41, Module21, 16, 3, 0, 0, 3, Fanins3[2], 1, &FaninOut, NULL ); + Ndr_AddObject( pDesign, Module41, ABC_OPER_CO, 0, 3, 0, 0, 1, &FaninOut, 0, NULL, NULL ); + + // write Verilog for verification + //Ndr_WriteVerilog( NULL, pDesign, ppNames, 0 ); + Ndr_Write( (char*)"mux41w.ndr", pDesign ); + Ndr_Delete( pDesign ); +} + + +// This testing procedure creates and writes into a Verilog file +// the following design with read/write memory ports + +// module test ( input clk, input [8:0] raddr, input [8:0] waddr, input [31:0] data, input [16383:0] mem_init, output out ); +// +// wire [31:0] read1, read2; +// +// wire [16383:0] mem_fo1, mem_fo2, mem_fi1, mem_fi2; +// +// ABC_FF i_reg1 ( .q(mem_fo1), .d(mem_fi1), .init(mem_init) ); +// ABC_FF i_reg2 ( .q(mem_fo2), .d(mem_fi2), .init(mem_init) ); +// +// ABC_WRITE i_write1 ( .mem_out(mem_fi1), .mem_in(mem_fo1), .addr(waddr), .data(data) ); +// ABC_WRITE i_write2 ( .mem_out(mem_fi2), .mem_in(mem_fo2), .addr(waddr), .data(data) ); +// +// ABC_READ i_read1 ( .data(read1), .mem_in(mem_fi1), .addr(raddr) ); +// ABC_READ i_read2 ( .data(read2), .mem_in(mem_fi2), .addr(raddr) ); +// +// assign out = read1 != read2; +//endmodule + +static inline void Ndr_ModuleTestMemory() +{ +/* + // map name IDs into char strings + char * ppNames[20] = { NULL, + "clk", "raddr", "waddr", "data", "mem_init", "out", // 1, 2, 3, 4, 5, 6 + "read1", "read2", // 7. 8 + "mem_fo1", "mem_fo2", "mem_fi1", "mem_fi2", // 9, 10, 11, 12 + "i_reg1", "i_reg2", // 13, 14 + "i_read1", "i_read2", // 15, 16 + "i_write1", "i_write2", "memtest" // 17, 18, 19 + }; +*/ + // inputs + int NameIdClk = 1; + int NameIdRaddr = 2; + int NameIdWaddr = 3; + int NameIdData = 4; + int NameIdMemInit = 5; + // flops + int NameIdFF1 = 9; + int NameIdFF2 = 10; + int FaninsFF1[2] = { 11, 5 }; + int FaninsFF2[2] = { 12, 5 }; + // writes + int NameIdWrite1 = 11; + int NameIdWrite2 = 12; + int FaninsWrite1[3] = { 9, 3, 4 }; + int FaninsWrite2[3] = { 10, 3, 4 }; + // reads + int NameIdRead1 = 7; + int NameIdRead2 = 8; + int FaninsRead1[2] = { 11, 2 }; + int FaninsRead2[2] = { 12, 2 }; + // compare + int NameIdComp = 6; + int FaninsComp[2] = { 7, 8 }; + + // create a new module + void * pDesign = Ndr_Create( 19 ); // create design named "memtest" + + int ModuleID = Ndr_AddModule( pDesign, 19 ); // create module named "memtest" + + // add objects to the module + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &NameIdClk, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 8, 0, 0, 0, NULL, 1, &NameIdRaddr, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 8, 0, 0, 0, NULL, 1, &NameIdWaddr, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 31, 0, 0, 0, NULL, 1, &NameIdData, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 16383, 0, 0, 0, NULL, 1, &NameIdMemInit, NULL ); + + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 0, 0, 0, 1, &NameIdComp, 0, NULL, NULL ); + + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_DFF, 13, 16383, 0, 0, 2, FaninsFF1, 1, &NameIdFF1, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_DFF, 14, 16383, 0, 0, 2, FaninsFF2, 1, &NameIdFF2, NULL ); + + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_RAMW, 17, 16383, 0, 0, 3, FaninsWrite1, 1, &NameIdWrite1, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_RAMW, 18, 16383, 0, 0, 3, FaninsWrite2, 1, &NameIdWrite2, NULL ); + + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_RAMR, 15, 31, 0, 0, 2, FaninsRead1, 1, &NameIdRead1, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_RAMR, 16, 31, 0, 0, 2, FaninsRead2, 1, &NameIdRead2, NULL ); + + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_COMP_NOTEQU, 0, 0, 0, 0, 2, FaninsComp, 1, &NameIdComp, NULL ); + + // write Verilog for verification + //Ndr_WriteVerilog( NULL, pDesign, ppNames, 0 ); + Ndr_Write( (char*)"memtest.ndr", pDesign ); + Ndr_Delete( pDesign ); +} + +// This testing procedure creates and writes into a Verilog file +// the following design composed of one word-level flop + +// module flop ( input [3:0] data, input clk, input reset, input set, input enable, input async, input sre, input [3:0] init, output [3:0] q ); +// ABC_DFFRSE reg1 ( .d(data), .clk(clk), .reset(reset), .set(set), .enable(enable), .async(async), .sre(sre), .init(init), .q(q) ) ; +// endmodule + +static inline void Ndr_ModuleTestFlop() +{ + // map name IDs into char strings + //char * ppNames[12] = { NULL, "flop", "data", "clk", "reset", "set", "enable", "async", "sre", "init", "q" }; + // name IDs + int NameIdData = 2; + int NameIdClk = 3; + int NameIdReset = 4; + int NameIdSet = 5; + int NameIdEnable = 6; + int NameIdAsync = 7; + int NameIdSre = 8; + int NameIdInit = 9; + int NameIdQ = 10; + // array of fanins of node s + int Fanins[8] = { NameIdData, NameIdClk, NameIdReset, NameIdSet, NameIdEnable, NameIdAsync, NameIdSre, NameIdInit }; + + // create a new module + void * pDesign = Ndr_Create( 1 ); + + int ModuleID = Ndr_AddModule( pDesign, 1 ); + + // add objects to the modele + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 3, 0, 0, 0, NULL, 1, &NameIdData, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &NameIdClk, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &NameIdReset, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &NameIdSet, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &NameIdEnable, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &NameIdAsync, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &NameIdSre, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 3, 0, 0, 0, NULL, 1, &NameIdInit, NULL ); + + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_DFFRSE, 0, 3, 0, 0, 8, Fanins, 1, &NameIdQ, NULL ); + + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 3, 0, 0, 1, &NameIdQ, 0, NULL, NULL ); + + // write Verilog for verification + //Ndr_WriteVerilog( NULL, pDesign, ppNames, 0 ); + Ndr_Write( (char*)"flop.ndr", pDesign ); + Ndr_Delete( pDesign ); +} + + +// This testing procedure creates and writes into a Verilog file +// the following design composed of one selector + +// module sel ( input [3:0] c, input [2:0] d0, input [2:0] d1, input [2:0] d2, input [2:0] d3, input [2:0] out ); +// wire [2:0] s7 ; +// always @( c or d0 or d1 or d2 or d3 ) +// begin +// case ( c ) +// 4'b0001 : s7 = d0 ; +// 4'b0010 : s7 = d1 ; +// 4'b0100 : s7 = d2 ; +// 4'b1000 : s7 = d3 ; +// endcase +// end +// assign out = s7 ; +// endmodule + +static inline void Ndr_ModuleTestSelSel() +{ + // map name IDs into char strings + //char * ppNames[12] = { NULL, "sel", "c", "d0", "d1", "d2", "d3", "out" }; + // name IDs + int NameIdC = 2; + int NameIdD0 = 3; + int NameIdD1 = 4; + int NameIdD2 = 5; + int NameIdD3 = 6; + int NameIdOut = 7; + // array of fanins of node s + int Fanins[8] = { NameIdC, NameIdD0, NameIdD1, NameIdD2, NameIdD3 }; + + // create a new module + void * pDesign = Ndr_Create( 1 ); + + int ModuleID = Ndr_AddModule( pDesign, 1 ); + + // add objects to the modele + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 3, 0, 0, 0, NULL, 1, &NameIdC, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 2, 0, 0, 0, NULL, 1, &NameIdD0, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 2, 0, 0, 0, NULL, 1, &NameIdD1, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 2, 0, 0, 0, NULL, 1, &NameIdD2, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 2, 0, 0, 0, NULL, 1, &NameIdD3, NULL ); + + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SEL_SEL, 0, 2, 0, 0, 5, Fanins, 1, &NameIdOut, NULL ); + + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 2, 0, 0, 1, &NameIdOut,0, NULL, NULL ); + + // write Verilog for verification + //Ndr_WriteVerilog( NULL, pDesign, ppNames, 0 ); + Ndr_Write( (char*)"sel.ndr", pDesign ); + Ndr_Delete( pDesign ); +} + +// This testing procedure creates and writes into a Verilog file +// the following design composed of one decoder + +// module dec ( input [1:0] in, output [3:0] out ); +// wire out0 = ~in[1] & ~in[0] ; +// wire out1 = ~in[1] & in[0] ; +// wire out2 = in[1] & ~in[0] ; +// wire out3 = in[1] & in[0] ; +// assign out = { out3, out2, out1, out0 } ; +// endmodule + +static inline void Ndr_ModuleTestDec() +{ + // map name IDs into char strings + //char * ppNames[12] = { NULL, "dec", "in", "out" }; + // name IDs + int NameIdIn = 2; + int NameIdOut = 3; + + // create a new module + void * pDesign = Ndr_Create( 1 ); + + int ModuleID = Ndr_AddModule( pDesign, 1 ); + + // add objects to the modele + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 1, 0, 0, 0, NULL, 1, &NameIdIn, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SEL_DEC, 0, 3, 0, 0, 1, &NameIdIn, 1, &NameIdOut, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 3, 0, 0, 1, &NameIdOut, 0, NULL, NULL ); + + Ndr_Write( (char*)"dec.ndr", pDesign ); + Ndr_Delete( pDesign ); +} + +// This testing procedure creates and writes into a Verilog file +// the following design composed of one adder/subtractor + +// module addsub ( input mode, input cin, input [2:0] a, input [2:0] b, output [3:0] out ); +// assign out = mode ? a+b+cin : a-b-cin ; +// endmodule + +static inline void Ndr_ModuleTestAddSub() +{ + // map name IDs into char strings + //char * ppNames[12] = { NULL, "addsub", "mode", "cin", "a", "b", "out" }; + // name IDs + int NameIdInMode = 2; + int NameIdInCin = 3; + int NameIdInA = 4; + int NameIdInB = 5; + int NameIdOut = 6; + int Fanins[8] = { 2, 3, 4, 5 }; + + // create a new module + void * pDesign = Ndr_Create( 1 ); + + int ModuleID = Ndr_AddModule( pDesign, 1 ); + + // add objects to the modele + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &NameIdInMode, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 0, 0, 0, 0, NULL, 1, &NameIdInCin, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 2, 0, 0, 0, NULL, 1, &NameIdInA, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 2, 0, 0, 0, NULL, 1, &NameIdInB, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_ARI_ADDSUB, 0, 3, 0, 0, 4, Fanins, 1, &NameIdOut, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 3, 0, 0, 1, &NameIdOut, 0, NULL, NULL ); + + Ndr_Write( (char*)"addsub.ndr", pDesign ); + Ndr_Delete( pDesign ); +} + +// This testing procedure creates and writes into a Verilog file +// the following design composed of one lookup table with function of AND2 + +// module lut_test ( input [1:0] in, output out ); +// assign out = LUT #(TT=4'h8) lut_inst { in[0], in[1], out } ; +// endmodule + +static inline void Ndr_ModuleTestLut() +{ + // map name IDs into char strings + //char * ppNames[12] = { NULL, "lut_test", "in", "out" }; + // name IDs + int NameIdIn = 2; + int NameIdOut = 3; + + // create a new module + void * pDesign = Ndr_Create( 1 ); + + int ModuleID = Ndr_AddModule( pDesign, 1 ); + + unsigned pTruth[2] = { 0x88888888, 0x88888888 }; + + // add objects to the modele + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI, 0, 1, 0, 0, 0, NULL, 1, &NameIdIn, NULL ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_LUT, 0, 0, 0, 0, 1, &NameIdIn, 1, &NameIdOut, (char *)pTruth ); + Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO, 0, 0, 0, 0, 1, &NameIdOut, 0, NULL, NULL ); + + Ndr_Write( (char*)"lut_test.ndr", pDesign ); + Ndr_Delete( pDesign ); +} + +#ifndef _YOSYS_ +ABC_NAMESPACE_HEADER_END +#endif + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/yosys/abc/src/aig/saig/module.make b/yosys/abc/src/aig/saig/module.make new file mode 100644 index 00000000000..4048043e3e6 --- /dev/null +++ b/yosys/abc/src/aig/saig/module.make @@ -0,0 +1,26 @@ +SRC += src/aig/saig/saigCone.c \ + src/aig/saig/saigConstr.c \ + src/aig/saig/saigConstr2.c \ + src/aig/saig/saigDual.c \ + src/aig/saig/saigDup.c \ + src/aig/saig/saigInd.c \ + src/aig/saig/saigIoa.c \ + src/aig/saig/saigIso.c \ + src/aig/saig/saigIsoFast.c \ + src/aig/saig/saigIsoSlow.c \ + src/aig/saig/saigMiter.c \ + src/aig/saig/saigOutDec.c \ + src/aig/saig/saigPhase.c \ + src/aig/saig/saigRetFwd.c \ + src/aig/saig/saigRetMin.c \ + src/aig/saig/saigRetStep.c \ + src/aig/saig/saigScl.c \ + src/aig/saig/saigSimFast.c \ + src/aig/saig/saigSimMv.c \ + src/aig/saig/saigSimSeq.c \ + src/aig/saig/saigStrSim.c \ + src/aig/saig/saigSwitch.c \ + src/aig/saig/saigSynch.c \ + src/aig/saig/saigTempor.c \ + src/aig/saig/saigTrans.c \ + src/aig/saig/saigWnd.c diff --git a/yosys/abc/src/aig/saig/saig.h b/yosys/abc/src/aig/saig/saig.h new file mode 100644 index 00000000000..4744b8f86db --- /dev/null +++ b/yosys/abc/src/aig/saig/saig.h @@ -0,0 +1,200 @@ +/**CFile**************************************************************** + + FileName [saig.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saig.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__aig__saig__saig_h +#define ABC__aig__saig__saig_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include "aig/aig/aig.h" + +ABC_NAMESPACE_HEADER_START + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Sec_MtrStatus_t_ Sec_MtrStatus_t; +struct Sec_MtrStatus_t_ +{ + int nInputs; // the total number of inputs + int nNodes; // the total number of nodes + int nOutputs; // the total number of outputs + int nUnsat; // the number of UNSAT outputs + int nSat; // the number of SAT outputs + int nUndec; // the number of undecided outputs + int iOut; // the satisfied output +}; + +typedef struct Saig_ParBbr_t_ Saig_ParBbr_t; +struct Saig_ParBbr_t_ +{ + int TimeLimit; + int nBddMax; + int nIterMax; + int fPartition; + int fReorder; + int fReorderImage; + int fVerbose; + int fSilent; + int fSkipOutCheck;// skip output checking + int iFrame; // explored up to this frame +}; + + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline int Saig_ManPiNum( Aig_Man_t * p ) { return p->nTruePis; } +static inline int Saig_ManPoNum( Aig_Man_t * p ) { return p->nTruePos; } +static inline int Saig_ManCiNum( Aig_Man_t * p ) { return p->nTruePis + p->nRegs; } +static inline int Saig_ManCoNum( Aig_Man_t * p ) { return p->nTruePos + p->nRegs; } +static inline int Saig_ManRegNum( Aig_Man_t * p ) { return p->nRegs; } +static inline int Saig_ManConstrNum( Aig_Man_t * p ) { return p->nConstrs; } +static inline Aig_Obj_t * Saig_ManLo( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vCis, Saig_ManPiNum(p)+i); } +static inline Aig_Obj_t * Saig_ManLi( Aig_Man_t * p, int i ) { return (Aig_Obj_t *)Vec_PtrEntry(p->vCos, Saig_ManPoNum(p)+i); } + +static inline int Saig_ObjIsPi( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjIsCi(pObj) && Aig_ObjCioId(pObj) < Saig_ManPiNum(p); } +static inline int Saig_ObjIsPo( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjIsCo(pObj) && Aig_ObjCioId(pObj) < Saig_ManPoNum(p); } +static inline int Saig_ObjIsLo( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjIsCi(pObj) && Aig_ObjCioId(pObj) >= Saig_ManPiNum(p); } +static inline int Saig_ObjIsLi( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjIsCo(pObj) && Aig_ObjCioId(pObj) >= Saig_ManPoNum(p); } +static inline Aig_Obj_t * Saig_ObjLoToLi( Aig_Man_t * p, Aig_Obj_t * pObj ) { assert(Saig_ObjIsLo(p, pObj)); return (Aig_Obj_t *)Vec_PtrEntry(p->vCos, Saig_ManPoNum(p)+Aig_ObjCioId(pObj)-Saig_ManPiNum(p)); } +static inline Aig_Obj_t * Saig_ObjLiToLo( Aig_Man_t * p, Aig_Obj_t * pObj ) { assert(Saig_ObjIsLi(p, pObj)); return (Aig_Obj_t *)Vec_PtrEntry(p->vCis, Saig_ManPiNum(p)+Aig_ObjCioId(pObj)-Saig_ManPoNum(p)); } +static inline int Saig_ObjRegId( Aig_Man_t * p, Aig_Obj_t * pObj ) { if ( Saig_ObjIsLo(p, pObj) ) return Aig_ObjCioId(pObj)-Saig_ManPiNum(p); if ( Saig_ObjIsLi(p, pObj) ) return Aig_ObjCioId(pObj)-Saig_ManPoNum(p); else assert(0); return -1; } + +// iterator over the primary inputs/outputs +#define Saig_ManForEachPi( p, pObj, i ) \ + Vec_PtrForEachEntryStop( Aig_Obj_t *, p->vCis, pObj, i, Saig_ManPiNum(p) ) +#define Saig_ManForEachPo( p, pObj, i ) \ + Vec_PtrForEachEntryStop( Aig_Obj_t *, p->vCos, pObj, i, Saig_ManPoNum(p) ) +// iterator over the latch inputs/outputs +#define Saig_ManForEachLo( p, pObj, i ) \ + for ( i = 0; (i < Saig_ManRegNum(p)) && (((pObj) = (Aig_Obj_t *)Vec_PtrEntry(p->vCis, i+Saig_ManPiNum(p))), 1); i++ ) +#define Saig_ManForEachLi( p, pObj, i ) \ + for ( i = 0; (i < Saig_ManRegNum(p)) && (((pObj) = (Aig_Obj_t *)Vec_PtrEntry(p->vCos, i+Saig_ManPoNum(p))), 1); i++ ) +// iterator over the latch input and outputs +#define Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) \ + for ( i = 0; (i < Saig_ManRegNum(p)) && (((pObjLi) = Saig_ManLi(p, i)), 1) \ + && (((pObjLo)=Saig_ManLo(p, i)), 1); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== saigCone.c ==========================================================*/ +extern void Saig_ManPrintCones( Aig_Man_t * p ); +/*=== saigConstr.c ==========================================================*/ +extern Aig_Man_t * Saig_ManDupUnfoldConstrs( Aig_Man_t * pAig ); +extern Aig_Man_t * Saig_ManDupFoldConstrs( Aig_Man_t * pAig, Vec_Int_t * vConstrs ); +extern int Saig_ManDetectConstrTest( Aig_Man_t * p ); +extern void Saig_ManDetectConstrFuncTest( Aig_Man_t * p, int nFrames, int nConfs, int nProps, int fOldAlgo, int fVerbose ); +/*=== saigConstr2.c ==========================================================*/ +extern Aig_Man_t * Saig_ManDupFoldConstrsFunc( Aig_Man_t * pAig, int fCompl, int fVerbose, int fSeqCleanup ); +extern Aig_Man_t * Saig_ManDupUnfoldConstrsFunc( Aig_Man_t * pAig, int nFrames, int nConfs, int nProps, int fOldAlgo, int fVerbose ); +// -- jlong -- begin +extern Aig_Man_t * Saig_ManDupFoldConstrsFunc2( Aig_Man_t * pAig, int fCompl, int fVerbose, int typeII_cnt ); +extern Aig_Man_t * Saig_ManDupUnfoldConstrsFunc2( Aig_Man_t * pAig, int nFrames, int nConfs, int nProps, int fOldAlgo, int fVerbose , int * typeII_cnt); +// --jlong -- end + +/*=== saigDual.c ==========================================================*/ +extern Aig_Man_t * Saig_ManDupDual( Aig_Man_t * pAig, Vec_Int_t * vDcFlops, int nDualPis, int fDualFfs, int fMiterFfs, int fComplPo, int fCheckZero, int fCheckOne ); +extern void Saig_ManBlockPo( Aig_Man_t * pAig, int nCycles ); +/*=== saigDup.c ==========================================================*/ +extern Aig_Man_t * Saig_ManDupOrpos( Aig_Man_t * p ); +extern Aig_Man_t * Saig_ManCreateEquivMiter( Aig_Man_t * pAig, Vec_Int_t * vPairs, int fAddOuts ); +extern Aig_Man_t * Saig_ManDupAbstraction( Aig_Man_t * pAig, Vec_Int_t * vFlops ); +extern int Saig_ManVerifyCex( Aig_Man_t * pAig, Abc_Cex_t * p ); +extern Abc_Cex_t * Saig_ManExtendCex( Aig_Man_t * pAig, Abc_Cex_t * p ); +extern int Saig_ManFindFailedPoCex( Aig_Man_t * pAig, Abc_Cex_t * p ); +extern Aig_Man_t * Saig_ManDupWithPhase( Aig_Man_t * pAig, Vec_Int_t * vInit ); +extern Aig_Man_t * Saig_ManDupCones( Aig_Man_t * pAig, int * pPos, int nPos ); +/*=== saigHaig.c ==========================================================*/ +extern Aig_Man_t * Saig_ManHaigRecord( Aig_Man_t * p, int nIters, int nSteps, int fRetimingOnly, int fAddBugs, int fUseCnf, int fVerbose ); +/*=== saigInd.c ==========================================================*/ +extern int Saig_ManInduction( Aig_Man_t * p, int nTimeOut, int nFramesMax, int nConfMax, int fUnique, int fUniqueAll, int fGetCex, int fVerbose, int fVeryVerbose ); +/*=== saigIoa.c ==========================================================*/ +extern void Saig_ManDumpBlif( Aig_Man_t * p, char * pFileName ); +extern Aig_Man_t * Saig_ManReadBlif( char * pFileName ); +/*=== saigIso.c ==========================================================*/ +extern Vec_Int_t * Saig_ManFindIsoPerm( Aig_Man_t * pAig, int fVerbose ); +extern Aig_Man_t * Saig_ManDupIsoCanonical( Aig_Man_t * pAig, int fVerbose ); +extern Aig_Man_t * Saig_ManIsoReduce( Aig_Man_t * pAig, Vec_Ptr_t ** pvCosEquivs, int fVerbose ); +/*=== saigIsoFast.c ==========================================================*/ +extern Vec_Vec_t * Saig_IsoDetectFast( Aig_Man_t * pAig ); +/*=== saigMiter.c ==========================================================*/ +extern Sec_MtrStatus_t Sec_MiterStatus( Aig_Man_t * p ); +extern Aig_Man_t * Saig_ManCreateMiter( Aig_Man_t * p1, Aig_Man_t * p2, int Oper ); +extern Aig_Man_t * Saig_ManCreateMiterComb( Aig_Man_t * p1, Aig_Man_t * p2, int Oper ); +extern Aig_Man_t * Saig_ManDualRail( Aig_Man_t * p, int fMiter ); +extern Aig_Man_t * Saig_ManCreateMiterTwo( Aig_Man_t * pOld, Aig_Man_t * pNew, int nFrames ); +extern int Saig_ManDemiterSimple( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 ); +extern int Saig_ManDemiterSimpleDiff( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 ); +extern int Saig_ManDemiterDual( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 ); +extern int Ssw_SecSpecialMiter( Aig_Man_t * p0, Aig_Man_t * p1, int nFrames, int fVerbose ); +extern int Saig_ManDemiterNew( Aig_Man_t * pMan ); +/*=== saigOutdec.c ==========================================================*/ +extern Aig_Man_t * Saig_ManDecPropertyOutput( Aig_Man_t * pAig, int nLits, int fVerbose ); +/*=== saigPhase.c ==========================================================*/ +extern Aig_Man_t * Saig_ManPhaseAbstract( Aig_Man_t * p, Vec_Int_t * vInits, int nFrames, int nPref, int fIgnore, int fPrint, int fVerbose ); +/*=== saigRetFwd.c ==========================================================*/ +extern void Saig_ManMarkAutonomous( Aig_Man_t * p ); +extern Aig_Man_t * Saig_ManRetimeForward( Aig_Man_t * p, int nMaxIters, int fVerbose ); +/*=== saigRetMin.c ==========================================================*/ +extern Aig_Man_t * Saig_ManRetimeDupForward( Aig_Man_t * p, Vec_Ptr_t * vCut ); +extern Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose ); +/*=== saigRetStep.c ==========================================================*/ +extern int Saig_ManRetimeSteps( Aig_Man_t * p, int nSteps, int fForward, int fAddBugs ); +/*=== saigScl.c ==========================================================*/ +extern void Saig_ManReportUselessRegisters( Aig_Man_t * pAig ); +/*=== saigSimMv.c ==========================================================*/ +extern Vec_Ptr_t * Saig_MvManSimulate( Aig_Man_t * pAig, int nFramesSymb, int nFramesSatur, int fVerbose, int fVeryVerbose ); +/*=== saigStrSim.c ==========================================================*/ +extern Vec_Int_t * Saig_StrSimPerformMatching( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose, Aig_Man_t ** ppMiter ); +/*=== saigSwitch.c ==========================================================*/ +extern Vec_Int_t * Saig_ManComputeSwitchProb2s( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ); +/*=== saigSynch.c ==========================================================*/ +extern Aig_Man_t * Saig_ManDupInitZero( Aig_Man_t * p ); +/*=== saigTrans.c ==========================================================*/ +extern Aig_Man_t * Saig_ManTimeframeSimplify( Aig_Man_t * pAig, int nFrames, int nFramesMax, int fInit, int fVerbose ); +/*=== saigWnd.c ==========================================================*/ +extern Aig_Man_t * Saig_ManWindowExtract( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist ); +extern Aig_Man_t * Saig_ManWindowInsert( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist, Aig_Man_t * pWnd ); +extern Aig_Obj_t * Saig_ManFindPivot( Aig_Man_t * p ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + diff --git a/yosys/abc/src/aig/saig/saigCone.c b/yosys/abc/src/aig/saig/saigCone.c new file mode 100644 index 00000000000..f81a2cbcf9d --- /dev/null +++ b/yosys/abc/src/aig/saig/saigCone.c @@ -0,0 +1,181 @@ +/**CFile**************************************************************** + + FileName [saigCone.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Cone of influence computation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigCone.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Counts the support size of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManSupport_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vSupp ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Aig_ObjIsConst1(pObj) ) + return; + if ( Aig_ObjIsCi(pObj) ) + { + if ( Saig_ObjIsLo(p,pObj) ) + { + pObj = Saig_ManLi( p, Aig_ObjCioId(pObj)-Saig_ManPiNum(p) ); + Vec_PtrPush( vSupp, pObj ); + } + return; + } + assert( Aig_ObjIsNode(pObj) ); + Saig_ManSupport_rec( p, Aig_ObjFanin0(pObj), vSupp ); + Saig_ManSupport_rec( p, Aig_ObjFanin1(pObj), vSupp ); +} + +/**Function************************************************************* + + Synopsis [Counts the support size of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Saig_ManSupport( Aig_Man_t * p, Vec_Ptr_t * vNodes ) +{ + Vec_Ptr_t * vSupp; + Aig_Obj_t * pObj; + int i; + vSupp = Vec_PtrAlloc( 100 ); + Aig_ManIncrementTravId( p ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + assert( Aig_ObjIsCo(pObj) ); + Saig_ManSupport_rec( p, Aig_ObjFanin0(pObj), vSupp ); + } + return vSupp; +} + +/**Function************************************************************* + + Synopsis [Prints information about cones of influence of the POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManPrintConeOne( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Vec_Ptr_t * vPrev, * vCur, * vTotal; + int s, i, nCurNew, nCurPrev, nCurOld; + assert( Saig_ObjIsPo(p, pObj) ); + // start the array + vPrev = Vec_PtrAlloc( 100 ); + Vec_PtrPush( vPrev, pObj ); + // get the current support + vCur = Saig_ManSupport( p, vPrev ); + Vec_PtrClear( vPrev ); + printf( " PO %3d ", Aig_ObjCioId(pObj) ); + // continue computing supports as long as there are now nodes + vTotal = Vec_PtrAlloc( 100 ); + for ( s = 0; ; s++ ) + { + // classify current into those new, prev, and older + nCurNew = nCurPrev = nCurOld = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, vCur, pObj, i ) + { + if ( Vec_PtrFind(vTotal, pObj) == -1 ) + { + Vec_PtrPush( vTotal, pObj ); + nCurNew++; + } + else if ( Vec_PtrFind(vPrev, pObj) >= 0 ) + nCurPrev++; + else + nCurOld++; + } + assert( nCurNew + nCurPrev + nCurOld == Vec_PtrSize(vCur) ); + // print the result + printf( "%d:%d %d=%d+%d+%d ", s, Vec_PtrSize(vTotal), Vec_PtrSize(vCur), nCurNew, nCurPrev, nCurOld ); + if ( nCurNew == 0 ) + break; + // compute one more step + Vec_PtrFree( vPrev ); + vCur = Saig_ManSupport( p, vPrev = vCur ); + } + printf( "\n" ); + Vec_PtrFree( vPrev ); + Vec_PtrFree( vCur ); + Vec_PtrFree( vTotal ); +} + +/**Function************************************************************* + + Synopsis [Prints information about cones of influence of the POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManPrintCones( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + printf( "The format of this print-out: For each PO, x:a b=c+d+e, where \n" ); + printf( "- x is the time-frame counting back from the PO\n" ); + printf( "- a is the total number of registers in the COI of the PO so far\n" ); + printf( "- b is the number of registers in the COI of the PO in this time-frame\n" ); + printf( "- c is the number of registers in b that are new (appear for the first time)\n" ); + printf( "- d is the number of registers in b in common with the previous time-frame\n" ); + printf( "- e is the number of registers in b in common with other time-frames\n" ); + Aig_ManSetCioIds( p ); + Saig_ManForEachPo( p, pObj, i ) + Saig_ManPrintConeOne( p, pObj ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigConstr.c b/yosys/abc/src/aig/saig/saigConstr.c new file mode 100644 index 00000000000..90e828166d2 --- /dev/null +++ b/yosys/abc/src/aig/saig/saigConstr.c @@ -0,0 +1,484 @@ +/**CFile**************************************************************** + + FileName [saigConstr.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Structural constraint detection.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigConstr.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" +#include "sat/cnf/cnf.h" +#include "sat/bsat/satSolver.h" +#include "bool/kit/kit.h" +#include "aig/ioa/ioa.h" + +ABC_NAMESPACE_IMPL_START + +/* + Property holds iff it is const 0. + Constraint holds iff it is const 0. + + The following structure is used for folding constraints: + - the output of OR gate is 0 as long as all constraints hold + - as soon as one constraint fail, the property output becomes 0 forever + because the flop becomes 1 and it stays 1 forever + + + property output + + | + |-----| + | and | + |-----| + | | + | / \ + | /inv\ + | ----- + ____| |_________________________ + | | | + / \ ----------- | + / \ | or | | + / \ ----------- | + / logic \ | | | | + / cone \ | | | | + /___________\ | | | | + | | ------ | + | | |flop| (init=0) | + | | ------ | + | | | | + | | |______________| + | | + c1 c2 +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_DetectConstrCollectSuper_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper ) +{ + // if the new node is complemented or a PI, another gate begins + if ( Aig_IsComplement(pObj) || !Aig_ObjIsNode(pObj) )//|| (Aig_ObjRefs(pObj) > 1) ) + { + Vec_PtrPushUnique( vSuper, Aig_Not(pObj) ); + return; + } + // go through the branches + Saig_DetectConstrCollectSuper_rec( Aig_ObjChild0(pObj), vSuper ); + Saig_DetectConstrCollectSuper_rec( Aig_ObjChild1(pObj), vSuper ); +} + +/**Function************************************************************* + + Synopsis [Collects the supergate.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Saig_DetectConstrCollectSuper( Aig_Obj_t * pObj ) +{ + Vec_Ptr_t * vSuper; + assert( !Aig_IsComplement(pObj) ); + assert( Aig_ObjIsAnd(pObj) ); + vSuper = Vec_PtrAlloc( 4 ); + Saig_DetectConstrCollectSuper_rec( Aig_ObjChild0(pObj), vSuper ); + Saig_DetectConstrCollectSuper_rec( Aig_ObjChild1(pObj), vSuper ); + return vSuper; +} + +/**Function************************************************************* + + Synopsis [Returns NULL if not contained, or array with unique entries.] + + Description [Returns NULL if vSuper2 is not contained in vSuper. Otherwise + returns the array of entries in vSuper that are not found in vSuper2.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Saig_ManDetectConstrCheckCont( Vec_Ptr_t * vSuper, Vec_Ptr_t * vSuper2 ) +{ + Vec_Ptr_t * vUnique; + Aig_Obj_t * pObj, * pObj2; + int i; + Vec_PtrForEachEntry( Aig_Obj_t *, vSuper2, pObj2, i ) + if ( Vec_PtrFind( vSuper, pObj2 ) == -1 ) + return 0; + vUnique = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pObj, i ) + if ( Vec_PtrFind( vSuper2, pObj ) == -1 ) + Vec_PtrPush( vUnique, pObj ); + return vUnique; +} + +/**Function************************************************************* + + Synopsis [Detects constraints using structural methods.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManDetectConstr( Aig_Man_t * p, int iOut, Vec_Ptr_t ** pvOuts, Vec_Ptr_t ** pvCons ) +{ + Vec_Ptr_t * vSuper, * vSuper2 = NULL, * vUnique; + Aig_Obj_t * pObj, * pObj2, * pFlop; + int i, nFlops, RetValue; + assert( iOut >= 0 && iOut < Saig_ManPoNum(p) ); + *pvOuts = NULL; + *pvCons = NULL; + pObj = Aig_ObjChild0( Aig_ManCo(p, iOut) ); + if ( pObj == Aig_ManConst0(p) ) + { + vUnique = Vec_PtrStart( 1 ); + Vec_PtrWriteEntry( vUnique, 0, Aig_ManConst1(p) ); + *pvOuts = vUnique; + *pvCons = Vec_PtrAlloc( 0 ); + return -1; + } + if ( Aig_IsComplement(pObj) || !Aig_ObjIsNode(pObj) ) + { + printf( "The output is not an AND.\n" ); + return 0; + } + vSuper = Saig_DetectConstrCollectSuper( pObj ); + assert( Vec_PtrSize(vSuper) >= 2 ); + nFlops = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pObj, i ) + nFlops += Saig_ObjIsLo( p, Aig_Regular(pObj) ); + if ( nFlops == 0 ) + { + printf( "There is no flop outputs.\n" ); + Vec_PtrFree( vSuper ); + return 0; + } + // try flops + vUnique = NULL; + Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pObj, i ) + { + pFlop = Aig_Regular( pObj ); + if ( !Saig_ObjIsLo(p, pFlop) ) + continue; + pFlop = Saig_ObjLoToLi( p, pFlop ); + pObj2 = Aig_ObjChild0( pFlop ); + if ( !Aig_IsComplement(pObj2) || !Aig_ObjIsNode(Aig_Regular(pObj2)) ) + continue; + vSuper2 = Saig_DetectConstrCollectSuper( Aig_Regular(pObj2) ); + // every node in vSuper2 should appear in vSuper + vUnique = Saig_ManDetectConstrCheckCont( vSuper, vSuper2 ); + if ( vUnique != NULL ) + { +/// assert( !Aig_IsComplement(pObj) ); + // assert( Vec_PtrFind( vSuper2, pObj ) >= 0 ); + if ( Aig_IsComplement(pObj) ) + { + printf( "Special flop input is complemented.\n" ); + Vec_PtrFreeP( &vUnique ); + Vec_PtrFree( vSuper2 ); + break; + } + if ( Vec_PtrFind( vSuper2, pObj ) == -1 ) + { + printf( "Cannot find special flop about the inputs of OR gate.\n" ); + Vec_PtrFreeP( &vUnique ); + Vec_PtrFree( vSuper2 ); + break; + } + // remove the flop output + Vec_PtrRemove( vSuper2, pObj ); + break; + } + Vec_PtrFree( vSuper2 ); + } + Vec_PtrFree( vSuper ); + if ( vUnique == NULL ) + { + printf( "There is no structural constraints.\n" ); + return 0; + } + // vUnique contains unique entries + // vSuper2 contains the supergate + printf( "Output %d : Structural analysis found %d original properties and %d constraints.\n", + iOut, Vec_PtrSize(vUnique), Vec_PtrSize(vSuper2) ); + // remember the number of constraints + RetValue = Vec_PtrSize(vSuper2); + // make the AND of properties +// Vec_PtrFree( vUnique ); +// Vec_PtrFree( vSuper2 ); + *pvOuts = vUnique; + *pvCons = vSuper2; + return RetValue; +} + + +/**Function************************************************************* + + Synopsis [Procedure used for sorting nodes by ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManDupCompare( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 ) +{ + int Diff = Aig_ObjToLit(*pp1) - Aig_ObjToLit(*pp2); + if ( Diff < 0 ) + return -1; + if ( Diff > 0 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG while unfolding constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManDupUnfoldConstrs( Aig_Man_t * pAig ) +{ + Vec_Ptr_t * vOutsAll, * vConsAll; + Vec_Ptr_t * vOuts, * vCons, * vCons0; + Aig_Man_t * pAigNew; + Aig_Obj_t * pMiter, * pObj; + int i, k, RetValue; + // detect constraints for each output + vOutsAll = Vec_PtrAlloc( Saig_ManPoNum(pAig) ); + vConsAll = Vec_PtrAlloc( Saig_ManPoNum(pAig) ); + Saig_ManForEachPo( pAig, pObj, i ) + { + RetValue = Saig_ManDetectConstr( pAig, i, &vOuts, &vCons ); + if ( RetValue == 0 ) + { + Vec_PtrFreeP( &vOuts ); + Vec_PtrFreeP( &vCons ); + Vec_VecFree( (Vec_Vec_t *)vOutsAll ); + Vec_VecFree( (Vec_Vec_t *)vConsAll ); + return Aig_ManDupDfs( pAig ); + } + Vec_PtrSort( vOuts, (int (*)(const void *, const void *))Saig_ManDupCompare ); + Vec_PtrSort( vCons, (int (*)(const void *, const void *))Saig_ManDupCompare ); + Vec_PtrPush( vOutsAll, vOuts ); + Vec_PtrPush( vConsAll, vCons ); + } + // check if constraints are compatible + vCons0 = (Vec_Ptr_t *)Vec_PtrEntry( vConsAll, 0 ); + Vec_PtrForEachEntry( Vec_Ptr_t *, vConsAll, vCons, i ) + if ( Vec_PtrSize(vCons) ) + vCons0 = vCons; + Vec_PtrForEachEntry( Vec_Ptr_t *, vConsAll, vCons, i ) + { + // Constant 0 outputs are always compatible (vOuts stores the negation) + vOuts = (Vec_Ptr_t *)Vec_PtrEntry( vOutsAll, i ); + if ( Vec_PtrSize(vOuts) == 1 && (Aig_Obj_t *)Vec_PtrEntry( vOuts, 0 ) == Aig_ManConst1(pAig) ) + continue; + if ( !Vec_PtrEqual(vCons0, vCons) ) + break; + } + if ( i < Vec_PtrSize(vConsAll) ) + { + printf( "Collected constraints are not compatible.\n" ); + Vec_VecFree( (Vec_Vec_t *)vOutsAll ); + Vec_VecFree( (Vec_Vec_t *)vConsAll ); + return Aig_ManDupDfs( pAig ); + } + + // start the new manager + pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); + pAigNew->pName = Abc_UtilStrsav( pAig->pName ); + // map the constant node + Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); + // create variables for PIs + Aig_ManForEachCi( pAig, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pAigNew ); + // add internal nodes of this frame + Aig_ManForEachNode( pAig, pObj, i ) + pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // transform each output + Vec_PtrForEachEntry( Vec_Ptr_t *, vOutsAll, vOuts, i ) + { + // AND the outputs + pMiter = Aig_ManConst1( pAigNew ); + Vec_PtrForEachEntry( Aig_Obj_t *, vOuts, pObj, k ) + pMiter = Aig_And( pAigNew, pMiter, Aig_Not(Aig_ObjRealCopy(pObj)) ); + Aig_ObjCreateCo( pAigNew, pMiter ); + } + // add constraints + pAigNew->nConstrs = Vec_PtrSize(vCons0); + Vec_PtrForEachEntry( Aig_Obj_t *, vCons0, pObj, i ) + Aig_ObjCreateCo( pAigNew, Aig_ObjRealCopy(pObj) ); + // transfer to register outputs + Saig_ManForEachLi( pAig, pObj, i ) + Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); +// Vec_PtrFreeP( &vOuts ); +// Vec_PtrFreeP( &vCons ); + Vec_VecFree( (Vec_Vec_t *)vOutsAll ); + Vec_VecFree( (Vec_Vec_t *)vConsAll ); + + Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig) ); + Aig_ManCleanup( pAigNew ); + Aig_ManSeqCleanup( pAigNew ); + return pAigNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG while folding in the constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManDupFoldConstrs( Aig_Man_t * pAig, Vec_Int_t * vConstrs ) +{ + Aig_Man_t * pAigNew; + Aig_Obj_t * pMiter, * pFlopOut, * pFlopIn, * pObj; + int Entry, i; + assert( Saig_ManRegNum(pAig) > 0 ); + // start the new manager + pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); + pAigNew->pName = Abc_UtilStrsav( pAig->pName ); + // map the constant node + Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); + // create variables for PIs + Aig_ManForEachCi( pAig, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pAigNew ); + // add internal nodes of this frame + Aig_ManForEachNode( pAig, pObj, i ) + pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + + // OR the constraint outputs + pMiter = Aig_ManConst0( pAigNew ); + Vec_IntForEachEntry( vConstrs, Entry, i ) + { + assert( Entry > 0 && Entry < Saig_ManPoNum(pAig) ); + pObj = Aig_ManCo( pAig, Entry ); + pMiter = Aig_Or( pAigNew, pMiter, Aig_ObjChild0Copy(pObj) ); + } + // create additional flop + pFlopOut = Aig_ObjCreateCi( pAigNew ); + pFlopIn = Aig_Or( pAigNew, pMiter, pFlopOut ); + + // create primary output + Saig_ManForEachPo( pAig, pObj, i ) + { + pMiter = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_Not(pFlopIn) ); + Aig_ObjCreateCo( pAigNew, pMiter ); + } + + // transfer to register outputs + Saig_ManForEachLi( pAig, pObj, i ) + Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); + // create additional flop + Aig_ObjCreateCo( pAigNew, pFlopIn ); + + Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig)+1 ); + Aig_ManCleanup( pAigNew ); + Aig_ManSeqCleanup( pAigNew ); + return pAigNew; +} + + +/**Function************************************************************* + + Synopsis [Tests the above two procedures.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManFoldConstrTest( Aig_Man_t * pAig ) +{ + Aig_Man_t * pAig1, * pAig2; + Vec_Int_t * vConstrs; + // unfold constraints + pAig1 = Saig_ManDupUnfoldConstrs( pAig ); + // create the constraint list + vConstrs = Vec_IntStartNatural( Saig_ManPoNum(pAig1) ); + Vec_IntRemove( vConstrs, 0 ); + // fold constraints back + pAig2 = Saig_ManDupFoldConstrs( pAig1, vConstrs ); + Vec_IntFree( vConstrs ); + // compare the two AIGs + Ioa_WriteAiger( pAig2, "test.aig", 0, 0 ); + Aig_ManStop( pAig1 ); + Aig_ManStop( pAig2 ); +} + +/**Function************************************************************* + + Synopsis [Experiment with the above procedure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManDetectConstrTest( Aig_Man_t * p ) +{ + Vec_Ptr_t * vOuts, * vCons; + int RetValue = Saig_ManDetectConstr( p, 0, &vOuts, &vCons ); + Vec_PtrFreeP( &vOuts ); + Vec_PtrFreeP( &vCons ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigConstr2.c b/yosys/abc/src/aig/saig/saigConstr2.c new file mode 100644 index 00000000000..79f557616eb --- /dev/null +++ b/yosys/abc/src/aig/saig/saigConstr2.c @@ -0,0 +1,1014 @@ +/**CFile**************************************************************** + + FileName [saigConstr2.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Functional constraint detection.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigConstr2.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" +#include "sat/cnf/cnf.h" +#include "sat/bsat/satSolver.h" +#include "bool/kit/kit.h" +#include "misc/bar/bar.h" + +ABC_NAMESPACE_IMPL_START + + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline Aig_Obj_t * Aig_ObjFrames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return pObjMap[nFs*pObj->Id + i]; } +static inline void Aig_ObjSetFrames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { pObjMap[nFs*pObj->Id + i] = pNode; } + +static inline Aig_Obj_t * Aig_ObjChild0Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin0(pObj)? Aig_NotCond(Aig_ObjFrames(pObjMap,nFs,Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL; } +static inline Aig_Obj_t * Aig_ObjChild1Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin1(pObj)? Aig_NotCond(Aig_ObjFrames(pObjMap,nFs,Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the probability of POs being 1 under rand seq sim.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_ManProfileConstraints( Aig_Man_t * p, int nWords, int nFrames, int fVerbose ) +{ + Vec_Ptr_t * vInfo; + Vec_Int_t * vProbs, * vProbs2; + Aig_Obj_t * pObj, * pObjLi; + unsigned * pInfo, * pInfo0, * pInfo1, * pInfoMask, * pInfoMask2; + int i, w, f, RetValue = 1; + abctime clk = Abc_Clock(); + if ( fVerbose ) + printf( "Simulating %d nodes and %d flops for %d frames with %d words... ", + Aig_ManNodeNum(p), Aig_ManRegNum(p), nFrames, nWords ); + Aig_ManRandom( 1 ); + vInfo = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p)+2, nWords ); + Vec_PtrCleanSimInfo( vInfo, 0, nWords ); + vProbs = Vec_IntStart( Saig_ManPoNum(p) ); + vProbs2 = Vec_IntStart( Saig_ManPoNum(p) ); + // start the constant + pInfo = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(Aig_ManConst1(p)) ); + for ( w = 0; w < nWords; w++ ) + pInfo[w] = ~0; + // start the flop inputs + Saig_ManForEachLi( p, pObj, i ) + { + pInfo = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObj) ); + for ( w = 0; w < nWords; w++ ) + pInfo[w] = 0; + } + // get the info mask + pInfoMask = (unsigned *)Vec_PtrEntry( vInfo, Aig_ManObjNumMax(p) ); // PO failed + pInfoMask2 = (unsigned *)Vec_PtrEntry( vInfo, Aig_ManObjNumMax(p)+1 ); // constr failed + for ( f = 0; f < nFrames; f++ ) + { + // assign primary inputs + Saig_ManForEachPi( p, pObj, i ) + { + pInfo = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObj) ); + for ( w = 0; w < nWords; w++ ) + pInfo[w] = Aig_ManRandom( 0 ); + } + // move the flop values + Saig_ManForEachLiLo( p, pObjLi, pObj, i ) + { + pInfo = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObj) ); + pInfo0 = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObjLi) ); + for ( w = 0; w < nWords; w++ ) + pInfo[w] = pInfo0[w]; + } + // simulate the nodes + Aig_ManForEachNode( p, pObj, i ) + { + pInfo = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObj) ); + pInfo0 = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjFaninId0(pObj) ); + pInfo1 = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjFaninId1(pObj) ); + if ( Aig_ObjFaninC0(pObj) ) + { + if ( Aig_ObjFaninC1(pObj) ) + for ( w = 0; w < nWords; w++ ) + pInfo[w] = ~(pInfo0[w] | pInfo1[w]); + else + for ( w = 0; w < nWords; w++ ) + pInfo[w] = ~pInfo0[w] & pInfo1[w]; + } + else + { + if ( Aig_ObjFaninC1(pObj) ) + for ( w = 0; w < nWords; w++ ) + pInfo[w] = pInfo0[w] & ~pInfo1[w]; + else + for ( w = 0; w < nWords; w++ ) + pInfo[w] = pInfo0[w] & pInfo1[w]; + } + } + // clean the mask + for ( w = 0; w < nWords; w++ ) + pInfoMask[w] = pInfoMask2[w] = 0; + // simulate the primary outputs + Aig_ManForEachCo( p, pObj, i ) + { + pInfo = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObj) ); + pInfo0 = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjFaninId0(pObj) ); + if ( i < Saig_ManPoNum(p)-Saig_ManConstrNum(p) || i >= Saig_ManPoNum(p) ) + { + if ( Aig_ObjFaninC0(pObj) ) + { + for ( w = 0; w < nWords; w++ ) + pInfo[w] = ~pInfo0[w]; + } + else + { + for ( w = 0; w < nWords; w++ ) + pInfo[w] = pInfo0[w]; + } + } + else + { + if ( Aig_ObjFaninC0(pObj) ) + { + for ( w = 0; w < nWords; w++ ) + pInfo[w] |= ~pInfo0[w]; + } + else + { + for ( w = 0; w < nWords; w++ ) + pInfo[w] |= pInfo0[w]; + } + } + // collect patterns when one of the outputs fails + if ( i < Saig_ManPoNum(p)-Saig_ManConstrNum(p) ) + { + for ( w = 0; w < nWords; w++ ) + pInfoMask[w] |= pInfo[w]; + } + else if ( i < Saig_ManPoNum(p) ) + { + for ( w = 0; w < nWords; w++ ) + pInfoMask2[w] |= pInfo[w]; + } + } + // compare the PO values (mask=1 => out=0) or UNSAT(mask=1 & out=1) + Saig_ManForEachPo( p, pObj, i ) + { + pInfo = (unsigned *)Vec_PtrEntry( vInfo, Aig_ObjId(pObj) ); + for ( w = 0; w < nWords; w++ ) + Vec_IntAddToEntry( vProbs, i, Aig_WordCountOnes(pInfo[w]) ); + if ( i < Saig_ManPoNum(p)-Saig_ManConstrNum(p) ) + { + // chek the output + for ( w = 0; w < nWords; w++ ) + if ( pInfo[w] & ~pInfoMask2[w] ) + break; + if ( w == nWords ) + continue; + printf( "Primary output %d fails on some input patterns.\n", i ); + } + else + { + // collect patterns that block the POs + for ( w = 0; w < nWords; w++ ) + Vec_IntAddToEntry( vProbs2, i, Aig_WordCountOnes(pInfo[w] & pInfoMask[w]) ); + } + } + } + if ( fVerbose ) + Abc_PrintTime( 1, "T", Abc_Clock() - clk ); + // print the state + if ( fVerbose ) + { + Saig_ManForEachPo( p, pObj, i ) + { + if ( i < Saig_ManPoNum(p) - Saig_ManConstrNum(p) ) + printf( "Primary output : " ); + else + printf( "Constraint %3d : ", i-(Saig_ManPoNum(p) - Saig_ManConstrNum(p)) ); + printf( "ProbOne = %f ", (float)Vec_IntEntry(vProbs, i)/(32*nWords*nFrames) ); + printf( "ProbOneC = %f ", (float)Vec_IntEntry(vProbs2, i)/(32*nWords*nFrames) ); + printf( "AllZeroValue = %d ", Aig_ObjPhase(pObj) ); + printf( "\n" ); + } + } + + // print the states + Vec_PtrFree( vInfo ); + Vec_IntFree( vProbs ); + Vec_IntFree( vProbs2 ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Creates COI of the property output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManCreateIndMiter( Aig_Man_t * pAig, Vec_Vec_t * vCands ) +{ + int nFrames = 2; + Vec_Ptr_t * vNodes; + Aig_Man_t * pFrames; + Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew; + Aig_Obj_t ** pObjMap; + int i, f, k; + + // create mapping for the frames nodes + pObjMap = ABC_CALLOC( Aig_Obj_t *, nFrames * Aig_ManObjNumMax(pAig) ); + + // start the fraig package + pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFrames ); + pFrames->pName = Abc_UtilStrsav( pAig->pName ); + pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); + // map constant nodes + for ( f = 0; f < nFrames; f++ ) + Aig_ObjSetFrames( pObjMap, nFrames, Aig_ManConst1(pAig), f, Aig_ManConst1(pFrames) ); + // create PI nodes for the frames + for ( f = 0; f < nFrames; f++ ) + Aig_ManForEachPiSeq( pAig, pObj, i ) + Aig_ObjSetFrames( pObjMap, nFrames, pObj, f, Aig_ObjCreateCi(pFrames) ); + // set initial state for the latches + Aig_ManForEachLoSeq( pAig, pObj, i ) + Aig_ObjSetFrames( pObjMap, nFrames, pObj, 0, Aig_ObjCreateCi(pFrames) ); + + // add timeframes + for ( f = 0; f < nFrames; f++ ) + { + // add internal nodes of this frame + Aig_ManForEachNode( pAig, pObj, i ) + { + pObjNew = Aig_And( pFrames, Aig_ObjChild0Frames(pObjMap,nFrames,pObj,f), Aig_ObjChild1Frames(pObjMap,nFrames,pObj,f) ); + Aig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew ); + } + // set the latch inputs and copy them into the latch outputs of the next frame + Aig_ManForEachLiLoSeq( pAig, pObjLi, pObjLo, i ) + { + pObjNew = Aig_ObjChild0Frames(pObjMap,nFrames,pObjLi,f); + if ( f < nFrames - 1 ) + Aig_ObjSetFrames( pObjMap, nFrames, pObjLo, f+1, pObjNew ); + } + } + + // go through the candidates + Vec_VecForEachLevel( vCands, vNodes, i ) + { + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, k ) + { + Aig_Obj_t * pObjR = Aig_Regular(pObj); + Aig_Obj_t * pNode0 = pObjMap[nFrames*Aig_ObjId(pObjR)+0]; + Aig_Obj_t * pNode1 = pObjMap[nFrames*Aig_ObjId(pObjR)+1]; + Aig_Obj_t * pFan0 = Aig_NotCond( pNode0, Aig_IsComplement(pObj) ); + Aig_Obj_t * pFan1 = Aig_NotCond( pNode1, !Aig_IsComplement(pObj) ); + Aig_Obj_t * pMiter = Aig_And( pFrames, pFan0, pFan1 ); + Aig_ObjCreateCo( pFrames, pMiter ); + } + } + Aig_ManCleanup( pFrames ); + ABC_FREE( pObjMap ); + +//Aig_ManShow( pAig, 0, NULL ); +//Aig_ManShow( pFrames, 0, NULL ); + return pFrames; +} + +/**Function************************************************************* + + Synopsis [Performs inductive check for one of the constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManFilterUsingIndOne_new( Aig_Man_t * p, Aig_Man_t * pFrame, sat_solver * pSat, Cnf_Dat_t * pCnf, int nConfs, int nProps, int Counter ) +{ + Aig_Obj_t * pObj; + int Lit, status; + pObj = Aig_ManCo( pFrame, Counter ); + Lit = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ); + status = sat_solver_solve( pSat, &Lit, &Lit + 1, (ABC_INT64_T)nConfs, 0, 0, 0 ); + if ( status == l_False ) + return 1; + if ( status == l_Undef ) + { +// printf( "Solver returned undecided.\n" ); + return 0; + } + assert( status == l_True ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Detects constraints functionally.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManFilterUsingInd( Aig_Man_t * p, Vec_Vec_t * vCands, int nConfs, int nProps, int fVerbose ) +{ + Vec_Ptr_t * vNodes; + Aig_Man_t * pFrames; + sat_solver * pSat; + Cnf_Dat_t * pCnf; + Aig_Obj_t * pObj; + int i, k, k2, Counter; +/* + Vec_VecForEachLevel( vCands, vNodes, i ) + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, k ) + printf( "%d ", Aig_ObjId(Aig_Regular(pObj)) ); + printf( "\n" ); +*/ + // create timeframes +// pFrames = Saig_ManUnrollInd( p ); + pFrames = Saig_ManCreateIndMiter( p, vCands ); + assert( Aig_ManCoNum(pFrames) == Vec_VecSizeSize(vCands) ); + // start the SAT solver + pCnf = Cnf_DeriveSimple( pFrames, Aig_ManCoNum(pFrames) ); + pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + // check candidates + if ( fVerbose ) + printf( "Filtered cands: " ); + Counter = 0; + Vec_VecForEachLevel( vCands, vNodes, i ) + { + k2 = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, k ) + { + if ( Saig_ManFilterUsingIndOne_new( p, pFrames, pSat, pCnf, nConfs, nProps, Counter++ ) ) +// if ( Saig_ManFilterUsingIndOne_old( p, pSat, pCnf, nConfs, pObj ) ) + { + Vec_PtrWriteEntry( vNodes, k2++, pObj ); + if ( fVerbose ) + printf( "%d:%s%d ", i, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); + } + } + Vec_PtrShrink( vNodes, k2 ); + } + if ( fVerbose ) + printf( "\n" ); + // clean up + Cnf_DataFree( pCnf ); + sat_solver_delete( pSat ); + if ( fVerbose ) + Aig_ManPrintStats( pFrames ); + Aig_ManStop( pFrames ); +} + + + + +/**Function************************************************************* + + Synopsis [Creates COI of the property output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManUnrollCOI_( Aig_Man_t * p, int nFrames ) +{ + Aig_Man_t * pFrames; + Aig_Obj_t ** pObjMap; + int i; +//Aig_Man_t * Aig_ManFrames( Aig_Man_t * pAig, int nFrames, int fInit, int fOuts, int fRegs, int fEnlarge, Aig_Obj_t *** ppObjMap ) + pFrames = Aig_ManFrames( p, nFrames, 0, 1, 1, 0, &pObjMap ); + for ( i = 0; i < nFrames * Aig_ManObjNumMax(p); i++ ) + if ( pObjMap[i] && Aig_ObjIsNone( Aig_Regular(pObjMap[i]) ) ) + pObjMap[i] = NULL; + assert( p->pObjCopies == NULL ); + p->pObjCopies = pObjMap; + return pFrames; +} + +/**Function************************************************************* + + Synopsis [Creates COI of the property output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManUnrollCOI( Aig_Man_t * pAig, int nFrames ) +{ + Aig_Man_t * pFrames; + Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew; + Aig_Obj_t ** pObjMap; + int i, f; + // create mapping for the frames nodes + pObjMap = ABC_CALLOC( Aig_Obj_t *, nFrames * Aig_ManObjNumMax(pAig) ); + // start the fraig package + pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFrames ); + pFrames->pName = Abc_UtilStrsav( pAig->pName ); + pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); + // map constant nodes + for ( f = 0; f < nFrames; f++ ) + Aig_ObjSetFrames( pObjMap, nFrames, Aig_ManConst1(pAig), f, Aig_ManConst1(pFrames) ); + // create PI nodes for the frames + for ( f = 0; f < nFrames; f++ ) + Aig_ManForEachPiSeq( pAig, pObj, i ) + Aig_ObjSetFrames( pObjMap, nFrames, pObj, f, Aig_ObjCreateCi(pFrames) ); + // set initial state for the latches + Aig_ManForEachLoSeq( pAig, pObj, i ) + Aig_ObjSetFrames( pObjMap, nFrames, pObj, 0, Aig_ObjCreateCi(pFrames) ); + // add timeframes + for ( f = 0; f < nFrames; f++ ) + { + Aig_ManForEachNode( pAig, pObj, i ) + { + pObjNew = Aig_And( pFrames, Aig_ObjChild0Frames(pObjMap,nFrames,pObj,f), Aig_ObjChild1Frames(pObjMap,nFrames,pObj,f) ); + Aig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew ); + } + // set the latch inputs and copy them into the latch outputs of the next frame + Aig_ManForEachLiLoSeq( pAig, pObjLi, pObjLo, i ) + { + pObjNew = Aig_ObjChild0Frames(pObjMap,nFrames,pObjLi,f); + if ( f < nFrames - 1 ) + Aig_ObjSetFrames( pObjMap, nFrames, pObjLo, f+1, pObjNew ); + } + } + // create the only output + for ( f = nFrames-1; f < nFrames; f++ ) + { + Aig_ManForEachPoSeq( pAig, pObj, i ) + { + pObjNew = Aig_ObjCreateCo( pFrames, Aig_ObjChild0Frames(pObjMap,nFrames,pObj,f) ); + Aig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew ); + } + } + // created lots of dangling nodes - no sweeping! + //Aig_ManCleanup( pFrames ); + assert( pAig->pObjCopies == NULL ); + pAig->pObjCopies = pObjMap; + return pFrames; +} + + +/**Function************************************************************* + + Synopsis [Collects and saves values of the SAT variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_CollectSatValues( sat_solver * pSat, Cnf_Dat_t * pCnf, Vec_Ptr_t * vInfo, int * piPat ) +{ + Aig_Obj_t * pObj; + unsigned * pInfo; + int i; + Aig_ManForEachObj( pCnf->pMan, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) ) + continue; + assert( pCnf->pVarNums[i] > 0 ); + pInfo = (unsigned *)Vec_PtrEntry( vInfo, i ); + if ( Abc_InfoHasBit(pInfo, *piPat) != sat_solver_var_value(pSat, pCnf->pVarNums[i]) ) + Abc_InfoXorBit(pInfo, *piPat); + } +} + +/**Function************************************************************* + + Synopsis [Runs the SAT test for the node in one polarity.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_DetectTryPolarity( sat_solver * pSat, int nConfs, int nProps, Cnf_Dat_t * pCnf, Aig_Obj_t * pObj, int iPol, Vec_Ptr_t * vInfo, int * piPat, int fVerbose ) +{ + Aig_Obj_t * pOut = Aig_ManCo( pCnf->pMan, 0 ); + int status, Lits[2]; +// ABC_INT64_T nOldConfs = pSat->stats.conflicts; +// ABC_INT64_T nOldImps = pSat->stats.propagations; + Lits[0] = toLitCond( pCnf->pVarNums[Aig_ObjId(pOut)], 0 ); + Lits[1] = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !iPol ); + status = sat_solver_solve( pSat, Lits, Lits + 2, (ABC_INT64_T)nConfs, (ABC_INT64_T)nProps, 0, 0 ); + if ( status == l_False ) + { +// printf( "u%d(%d) ", (int)(pSat->stats.conflicts-nOldConfs), (int)(pSat->stats.propagations-nOldImps) ); + return 1; + } + if ( status == l_Undef ) + { +// printf( "Solver returned undecided.\n" ); + return 0; + } +// printf( "s%d(%d) ", (int)(pSat->stats.conflicts-nOldConfs), (int)(pSat->stats.propagations-nOldImps) ); + assert( status == l_True ); + Saig_CollectSatValues( pSat, pCnf, vInfo, piPat ); + (*piPat)++; + if ( *piPat == Vec_PtrReadWordsSimInfo(vInfo) * 32 ) + { + if ( fVerbose ) + printf( "Warning: Reached the limit on the number of patterns.\n" ); + *piPat = 0; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns the number of variables implied by the output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Vec_t * Ssw_ManFindDirectImplications( Aig_Man_t * p, int nFrames, int nConfs, int nProps, int fVerbose ) +{ + Vec_Vec_t * vCands = NULL; + Vec_Ptr_t * vNodes; + Cnf_Dat_t * pCnf; + sat_solver * pSat; + Aig_Man_t * pFrames; + Aig_Obj_t * pObj, * pRepr, * pReprR; + int i, f, k, value; + vCands = Vec_VecAlloc( nFrames ); + + // perform unrolling + pFrames = Saig_ManUnrollCOI( p, nFrames ); + assert( Aig_ManCoNum(pFrames) == 1 ); + // start the SAT solver + pCnf = Cnf_DeriveSimple( pFrames, 0 ); + pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + if ( pSat != NULL ) + { + Aig_ManIncrementTravId( p ); + for ( f = 0; f < nFrames; f++ ) + { + Aig_ManForEachObj( p, pObj, i ) + { + if ( !Aig_ObjIsCand(pObj) ) + continue; + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + continue; + // get the node from timeframes + pRepr = p->pObjCopies[nFrames*i + nFrames-1-f]; + pReprR = Aig_Regular(pRepr); + if ( pCnf->pVarNums[Aig_ObjId(pReprR)] < 0 ) + continue; +// value = pSat->assigns[ pCnf->pVarNums[Aig_ObjId(pReprR)] ]; + value = sat_solver_get_var_value( pSat, pCnf->pVarNums[Aig_ObjId(pReprR)] ); + if ( value == l_Undef ) + continue; + // label this node as taken + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Saig_ObjIsLo(p, pObj) ) + Aig_ObjSetTravIdCurrent( p, Aig_ObjFanin0(Saig_ObjLoToLi(p, pObj)) ); + // remember the node + Vec_VecPush( vCands, f, Aig_NotCond( pObj, (value == l_True) ^ Aig_IsComplement(pRepr) ) ); + // printf( "%s%d ", (value == l_False)? "":"!", i ); + } + } + // printf( "\n" ); + sat_solver_delete( pSat ); + } + Aig_ManStop( pFrames ); + Cnf_DataFree( pCnf ); + + if ( fVerbose ) + { + printf( "Found %3d candidates.\n", Vec_VecSizeSize(vCands) ); + Vec_VecForEachLevel( vCands, vNodes, k ) + { + printf( "Level %d. Cands =%d ", k, Vec_PtrSize(vNodes) ); +// Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) +// printf( "%d:%s%d ", k, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); + printf( "\n" ); + } + } + + ABC_FREE( p->pObjCopies ); + Saig_ManFilterUsingInd( p, vCands, nConfs, nProps, fVerbose ); + if ( Vec_VecSizeSize(vCands) ) + printf( "Found %3d constraints after filtering.\n", Vec_VecSizeSize(vCands) ); + if ( fVerbose ) + { + Vec_VecForEachLevel( vCands, vNodes, k ) + { + printf( "Level %d. Constr =%d ", k, Vec_PtrSize(vNodes) ); +// Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) +// printf( "%d:%s%d ", k, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); + printf( "\n" ); + } + } + + return vCands; +} + + +/**Function************************************************************* + + Synopsis [Detects constraints functionally.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Vec_t * Saig_ManDetectConstrFunc( Aig_Man_t * p, int nFrames, int nConfs, int nProps, int fVerbose ) +{ + int iPat = 0, nWordsAlloc = 16; + Bar_Progress_t * pProgress = NULL; + Vec_Vec_t * vCands = NULL; + Vec_Ptr_t * vInfo, * vNodes; + Aig_Obj_t * pObj, * pRepr, * pObjNew; + Aig_Man_t * pFrames; + sat_solver * pSat; + Cnf_Dat_t * pCnf; + unsigned * pInfo; + int i, j, k, Lit, status, nCands = 0; + assert( Saig_ManPoNum(p) == 1 ); + if ( Saig_ManPoNum(p) != 1 ) + { + printf( "The number of outputs is different from 1.\n" ); + return NULL; + } +//printf( "Implications = %d.\n", Ssw_ManCountImplications(p, nFrames) ); + + // perform unrolling + pFrames = Saig_ManUnrollCOI( p, nFrames ); + assert( Aig_ManCoNum(pFrames) == 1 ); + if ( fVerbose ) + { + printf( "Detecting constraints with %d frames, %d conflicts, and %d propagations.\n", nFrames, nConfs, nProps ); + printf( "Frames: " ); + Aig_ManPrintStats( pFrames ); + } +// Aig_ManShow( pFrames, 0, NULL ); + + // start the SAT solver + pCnf = Cnf_DeriveSimple( pFrames, Aig_ManCoNum(pFrames) ); + pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); +//printf( "Implications = %d.\n", pSat->qhead ); + + // solve the original problem + Lit = toLitCond( pCnf->pVarNums[Aig_ObjId(Aig_ManCo(pFrames,0))], 0 ); + status = sat_solver_solve( pSat, &Lit, &Lit + 1, (ABC_INT64_T)nConfs, 0, 0, 0 ); + if ( status == l_False ) + { + printf( "The problem is trivially UNSAT (inductive with k=%d).\n", nFrames-1 ); + Cnf_DataFree( pCnf ); + sat_solver_delete( pSat ); + Aig_ManStop( pFrames ); + return NULL; + } + if ( status == l_Undef ) + { + printf( "Solver could not solve the original problem.\n" ); + Cnf_DataFree( pCnf ); + sat_solver_delete( pSat ); + Aig_ManStop( pFrames ); + return NULL; + } + assert( status == l_True ); + + // create simulation info + vInfo = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(pFrames), nWordsAlloc ); + Vec_PtrCleanSimInfo( vInfo, 0, nWordsAlloc ); + Saig_CollectSatValues( pSat, pCnf, vInfo, &iPat ); + Aig_ManForEachObj( pFrames, pObj, i ) + { + pInfo = (unsigned *)Vec_PtrEntry( vInfo, i ); + if ( pInfo[0] & 1 ) + memset( (char*)pInfo, 0xff, 4*nWordsAlloc ); + } +// Aig_ManShow( pFrames, 0, NULL ); +// Aig_ManShow( p, 0, NULL ); + + // consider the nodes for ci=>!Out and label when it holds + pProgress = Bar_ProgressStart( stdout, Aig_ManObjNumMax(pFrames) ); + Aig_ManCleanMarkAB( pFrames ); + Aig_ManForEachObj( pFrames, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) ) + continue; + Bar_ProgressUpdate( pProgress, i, NULL ); + // check if the node is available in both polarities + pInfo = (unsigned *)Vec_PtrEntry( vInfo, i ); + for ( k = 0; k < nWordsAlloc; k++ ) + if ( pInfo[k] != ~0 ) + break; + if ( k == nWordsAlloc ) + { + if ( Saig_DetectTryPolarity(pSat, nConfs, nProps, pCnf, pObj, 0, vInfo, &iPat, fVerbose) ) // !pObj is a constr + { + pObj->fMarkA = 1, nCands++; +// printf( "!%d ", Aig_ObjId(pObj) ); + } + continue; + } + for ( k = 0; k < nWordsAlloc; k++ ) + if ( pInfo[k] != 0 ) + break; + if ( k == nWordsAlloc ) + { + if ( Saig_DetectTryPolarity(pSat, nConfs, nProps, pCnf, pObj, 1, vInfo, &iPat, fVerbose) ) // pObj is a constr + { + pObj->fMarkB = 1, nCands++; +// printf( "%d ", Aig_ObjId(pObj) ); + } + continue; + } + } + Bar_ProgressStop( pProgress ); + if ( nCands ) + { + +// printf( "\n" ); + if ( fVerbose ) + printf( "Found %3d classes of candidates.\n", nCands ); + vCands = Vec_VecAlloc( nFrames ); + for ( k = 0; k < nFrames; k++ ) + { + Aig_ManForEachObj( p, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) ) + continue; + pRepr = p->pObjCopies[nFrames*i + nFrames-1-k]; +// pRepr = p->pObjCopies[nFrames*i + k]; + if ( pRepr == NULL ) + continue; + if ( Aig_Regular(pRepr)->fMarkA ) // !pObj is a constr + { + pObjNew = Aig_NotCond(pObj, !Aig_IsComplement(pRepr)); + + for ( j = 0; j < k; j++ ) + if ( Vec_PtrFind( Vec_VecEntry(vCands, j), pObjNew ) >= 0 ) + break; + if ( j == k ) + Vec_VecPush( vCands, k, pObjNew ); +// printf( "%d->!%d ", Aig_ObjId(Aig_Regular(pRepr)), Aig_ObjId(pObj) ); + } + else if ( Aig_Regular(pRepr)->fMarkB ) // pObj is a constr + { + pObjNew = Aig_NotCond(pObj, Aig_IsComplement(pRepr)); + + for ( j = 0; j < k; j++ ) + if ( Vec_PtrFind( Vec_VecEntry(vCands, j), pObjNew ) >= 0 ) + break; + if ( j == k ) + Vec_VecPush( vCands, k, pObjNew ); +// printf( "%d->%d ", Aig_ObjId(Aig_Regular(pRepr)), Aig_ObjId(pObj) ); + } + } + } + +// printf( "\n" ); + if ( fVerbose ) + { + printf( "Found %3d candidates.\n", Vec_VecSizeSize(vCands) ); + Vec_VecForEachLevel( vCands, vNodes, k ) + { + printf( "Level %d. Cands =%d ", k, Vec_PtrSize(vNodes) ); +// Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) +// printf( "%d:%s%d ", k, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); + printf( "\n" ); + } + } + + ABC_FREE( p->pObjCopies ); + Saig_ManFilterUsingInd( p, vCands, nConfs, nProps, fVerbose ); + if ( Vec_VecSizeSize(vCands) ) + printf( "Found %3d constraints after filtering.\n", Vec_VecSizeSize(vCands) ); + if ( fVerbose ) + { + Vec_VecForEachLevel( vCands, vNodes, k ) + { + printf( "Level %d. Constr =%d ", k, Vec_PtrSize(vNodes) ); +// Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) +// printf( "%d:%s%d ", k, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); + printf( "\n" ); + } + } + } + Vec_PtrFree( vInfo ); + Cnf_DataFree( pCnf ); + sat_solver_delete( pSat ); + Aig_ManCleanMarkAB( pFrames ); + Aig_ManStop( pFrames ); + return vCands; +} + +/**Function************************************************************* + + Synopsis [Experimental procedure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManDetectConstrFuncTest( Aig_Man_t * p, int nFrames, int nConfs, int nProps, int fOldAlgo, int fVerbose ) +{ + Vec_Vec_t * vCands; + if ( fOldAlgo ) + vCands = Saig_ManDetectConstrFunc( p, nFrames, nConfs, nProps, fVerbose ); + else + vCands = Ssw_ManFindDirectImplications( p, nFrames, nConfs, nProps, fVerbose ); + Vec_VecFreeP( &vCands ); +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG while unfolding constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManDupUnfoldConstrsFunc( Aig_Man_t * pAig, int nFrames, int nConfs, int nProps, int fOldAlgo, int fVerbose ) +{ + Aig_Man_t * pNew; + Vec_Vec_t * vCands; + Vec_Ptr_t * vNodes, * vNewFlops; + Aig_Obj_t * pObj; + int i, j, k, nNewFlops; + if ( fOldAlgo ) + vCands = Saig_ManDetectConstrFunc( pAig, nFrames, nConfs, nProps, fVerbose ); + else + vCands = Ssw_ManFindDirectImplications( pAig, nFrames, nConfs, nProps, fVerbose ); + if ( vCands == NULL || Vec_VecSizeSize(vCands) == 0 ) + { + Vec_VecFreeP( &vCands ); + return Aig_ManDupDfs( pAig ); + } + // create new manager + pNew = Aig_ManDupWithoutPos( pAig ); + pNew->nConstrs = pAig->nConstrs + Vec_VecSizeSize(vCands); + // add normal POs + Saig_ManForEachPo( pAig, pObj, i ) + Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + // create constraint outputs + vNewFlops = Vec_PtrAlloc( 100 ); + Vec_VecForEachLevel( vCands, vNodes, i ) + { + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, k ) + { + Vec_PtrPush( vNewFlops, Aig_ObjRealCopy(pObj) ); + for ( j = 0; j < i; j++ ) + Vec_PtrPush( vNewFlops, Aig_ObjCreateCi(pNew) ); + Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Vec_PtrPop(vNewFlops) ); + } + } + // add latch outputs + Saig_ManForEachLi( pAig, pObj, i ) + Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + // add new latch outputs + nNewFlops = 0; + Vec_VecForEachLevel( vCands, vNodes, i ) + { + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, k ) + { + for ( j = 0; j < i; j++ ) + Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Vec_PtrEntry(vNewFlops, nNewFlops++) ); + } + } + assert( nNewFlops == Vec_PtrSize(vNewFlops) ); + Aig_ManSetRegNum( pNew, Aig_ManRegNum(pAig) + nNewFlops ); + Vec_VecFreeP( &vCands ); + Vec_PtrFree( vNewFlops ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG while unfolding constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManDupFoldConstrsFunc( Aig_Man_t * pAig, int fCompl, int fVerbose, int fSeqCleanup ) +{ + Aig_Man_t * pAigNew; + Aig_Obj_t * pMiter, * pFlopOut, * pFlopIn, * pObj; + int i; + if ( Aig_ManConstrNum(pAig) == 0 ) + return Aig_ManDupDfs( pAig ); + assert( Aig_ManConstrNum(pAig) < Saig_ManPoNum(pAig) ); + // start the new manager + pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); + pAigNew->pName = Abc_UtilStrsav( pAig->pName ); + pAigNew->pSpec = Abc_UtilStrsav( pAig->pSpec ); + // map the constant node + Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); + // create variables for PIs + Aig_ManForEachCi( pAig, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pAigNew ); + // add internal nodes of this frame + Aig_ManForEachNode( pAig, pObj, i ) + pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + + // OR the constraint outputs + pMiter = Aig_ManConst0( pAigNew ); + Saig_ManForEachPo( pAig, pObj, i ) + { + if ( i < Saig_ManPoNum(pAig)-Aig_ManConstrNum(pAig) ) + continue; + pMiter = Aig_Or( pAigNew, pMiter, Aig_NotCond( Aig_ObjChild0Copy(pObj), fCompl ) ); + } + + // create additional flop + if ( Saig_ManRegNum(pAig) > 0 ) + { + pFlopOut = Aig_ObjCreateCi( pAigNew ); + pFlopIn = Aig_Or( pAigNew, pMiter, pFlopOut ); + } + else + pFlopIn = pMiter; + + // create primary output + Saig_ManForEachPo( pAig, pObj, i ) + { + if ( i >= Saig_ManPoNum(pAig)-Aig_ManConstrNum(pAig) ) + continue; + pMiter = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_Not(pFlopIn) ); + Aig_ObjCreateCo( pAigNew, pMiter ); + } + + // transfer to register outputs + Saig_ManForEachLi( pAig, pObj, i ) + Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); + + // create additional flop + if ( Saig_ManRegNum(pAig) > 0 ) + { + Aig_ObjCreateCo( pAigNew, pFlopIn ); + Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig)+1 ); + } + + // perform cleanup + Aig_ManCleanup( pAigNew ); + if ( fSeqCleanup ) + Aig_ManSeqCleanup( pAigNew ); + return pAigNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +#include "saigUnfold2.c" +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigDual.c b/yosys/abc/src/aig/saig/saigDual.c new file mode 100644 index 00000000000..16fae8d1aff --- /dev/null +++ b/yosys/abc/src/aig/saig/saigDual.c @@ -0,0 +1,240 @@ +/**CFile**************************************************************** + + FileName [saigDual.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Various duplication procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigDual.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline void Saig_ObjSetDual( Vec_Ptr_t * vCopies, int Id, int fPos, Aig_Obj_t * pItem ) { Vec_PtrWriteEntry( vCopies, 2*Id+fPos, pItem ); } +static inline Aig_Obj_t * Saig_ObjDual( Vec_Ptr_t * vCopies, int Id, int fPos ) { return (Aig_Obj_t *)Vec_PtrEntry( vCopies, 2*Id+fPos ); } + +static inline void Saig_ObjDualFanin( Aig_Man_t * pAigNew, Vec_Ptr_t * vCopies, Aig_Obj_t * pObj, int iFanin, Aig_Obj_t ** ppRes0, Aig_Obj_t ** ppRes1 ) { + + Aig_Obj_t * pTemp0, * pTemp1, * pCare; + int fCompl; + assert( iFanin == 0 || iFanin == 1 ); + if ( iFanin == 0 ) + { + pTemp0 = Saig_ObjDual( vCopies, Aig_ObjFaninId0(pObj), 0 ); + pTemp1 = Saig_ObjDual( vCopies, Aig_ObjFaninId0(pObj), 1 ); + fCompl = Aig_ObjFaninC0( pObj ); + } + else + { + pTemp0 = Saig_ObjDual( vCopies, Aig_ObjFaninId1(pObj), 0 ); + pTemp1 = Saig_ObjDual( vCopies, Aig_ObjFaninId1(pObj), 1 ); + fCompl = Aig_ObjFaninC1( pObj ); + } + if ( fCompl ) + { + pCare = Aig_Or( pAigNew, pTemp0, pTemp1 ); + *ppRes0 = Aig_And( pAigNew, pTemp1, pCare ); + *ppRes1 = Aig_And( pAigNew, pTemp0, pCare ); + } + else + { + *ppRes0 = pTemp0; + *ppRes1 = pTemp1; + } +} + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Transforms sequential AIG into dual-rail miter.] + + Description [Transforms sequential AIG into a miter encoding ternary + problem formulated as follows "none of the POs has a ternary value". + Interprets the first nDualPis as having ternary value. Sets flops + to have ternary intial value when fDualFfs is set to 1.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManDupDual( Aig_Man_t * pAig, Vec_Int_t * vDcFlops, int nDualPis, int fDualFfs, int fMiterFfs, int fComplPo, int fCheckZero, int fCheckOne ) +{ + Vec_Ptr_t * vCopies; + Aig_Man_t * pAigNew; + Aig_Obj_t * pObj, * pTemp0, * pTemp1, * pTemp2, * pTemp3, * pCare, * pMiter; + int i; + assert( Saig_ManPoNum(pAig) > 0 ); + assert( nDualPis >= 0 && nDualPis <= Saig_ManPiNum(pAig) ); + assert( vDcFlops == NULL || Vec_IntSize(vDcFlops) == Aig_ManRegNum(pAig) ); + vCopies = Vec_PtrStart( 2*Aig_ManObjNum(pAig) ); + // start the new manager + pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); + pAigNew->pName = Abc_UtilStrsav( pAig->pName ); + // map the constant node + Saig_ObjSetDual( vCopies, 0, 0, Aig_ManConst0(pAigNew) ); + Saig_ObjSetDual( vCopies, 0, 1, Aig_ManConst1(pAigNew) ); + // create variables for PIs + Aig_ManForEachCi( pAig, pObj, i ) + { + if ( i < nDualPis ) + { + pTemp0 = Aig_ObjCreateCi( pAigNew ); + pTemp1 = Aig_ObjCreateCi( pAigNew ); + } + else if ( i < Saig_ManPiNum(pAig) ) + { + pTemp1 = Aig_ObjCreateCi( pAigNew ); + pTemp0 = Aig_Not( pTemp1 ); + } + else + { + pTemp0 = Aig_ObjCreateCi( pAigNew ); + pTemp1 = Aig_ObjCreateCi( pAigNew ); + if ( vDcFlops ) + pTemp0 = Aig_NotCond( pTemp0, !Vec_IntEntry(vDcFlops, i-Saig_ManPiNum(pAig)) ); + else + pTemp0 = Aig_NotCond( pTemp0, !fDualFfs ); + } + Saig_ObjSetDual( vCopies, Aig_ObjId(pObj), 0, Aig_And(pAigNew, pTemp0, Aig_Not(pTemp1)) ); + Saig_ObjSetDual( vCopies, Aig_ObjId(pObj), 1, Aig_And(pAigNew, pTemp1, Aig_Not(pTemp0)) ); + } + // create internal nodes + Aig_ManForEachNode( pAig, pObj, i ) + { + Saig_ObjDualFanin( pAigNew, vCopies, pObj, 0, &pTemp0, &pTemp1 ); + Saig_ObjDualFanin( pAigNew, vCopies, pObj, 1, &pTemp2, &pTemp3 ); + Saig_ObjSetDual( vCopies, Aig_ObjId(pObj), 0, Aig_Or (pAigNew, pTemp0, pTemp2) ); + Saig_ObjSetDual( vCopies, Aig_ObjId(pObj), 1, Aig_And(pAigNew, pTemp1, pTemp3) ); + } + // create miter and flops + pMiter = Aig_ManConst0(pAigNew); + if ( fMiterFfs ) + { + Saig_ManForEachLi( pAig, pObj, i ) + { + Saig_ObjDualFanin( pAigNew, vCopies, pObj, 0, &pTemp0, &pTemp1 ); + if ( fCheckZero ) + { + pCare = Aig_And( pAigNew, pTemp0, Aig_Not(pTemp1) ); + pMiter = Aig_Or( pAigNew, pMiter, pCare ); + } + else if ( fCheckOne ) + { + pCare = Aig_And( pAigNew, Aig_Not(pTemp0), pTemp1 ); + pMiter = Aig_Or( pAigNew, pMiter, pCare ); + } + else // check X + { + pCare = Aig_And( pAigNew, Aig_Not(pTemp0), Aig_Not(pTemp1) ); + pMiter = Aig_Or( pAigNew, pMiter, pCare ); + } + } + } + else + { + Saig_ManForEachPo( pAig, pObj, i ) + { + Saig_ObjDualFanin( pAigNew, vCopies, pObj, 0, &pTemp0, &pTemp1 ); + if ( fCheckZero ) + { + pCare = Aig_And( pAigNew, pTemp0, Aig_Not(pTemp1) ); + pMiter = Aig_Or( pAigNew, pMiter, pCare ); + } + else if ( fCheckOne ) + { + pCare = Aig_And( pAigNew, Aig_Not(pTemp0), pTemp1 ); + pMiter = Aig_Or( pAigNew, pMiter, pCare ); + } + else // check X + { + pCare = Aig_And( pAigNew, Aig_Not(pTemp0), Aig_Not(pTemp1) ); + pMiter = Aig_Or( pAigNew, pMiter, pCare ); + } + } + } + // create PO + pMiter = Aig_NotCond( pMiter, fComplPo ); + Aig_ObjCreateCo( pAigNew, pMiter ); + // create flops + Saig_ManForEachLi( pAig, pObj, i ) + { + Saig_ObjDualFanin( pAigNew, vCopies, pObj, 0, &pTemp0, &pTemp1 ); + if ( vDcFlops ) + pTemp0 = Aig_NotCond( pTemp0, !Vec_IntEntry(vDcFlops, i) ); + else + pTemp0 = Aig_NotCond( pTemp0, !fDualFfs ); + Aig_ObjCreateCo( pAigNew, pTemp0 ); + Aig_ObjCreateCo( pAigNew, pTemp1 ); + } + // set the flops + Aig_ManSetRegNum( pAigNew, 2 * Aig_ManRegNum(pAig) ); + Aig_ManCleanup( pAigNew ); + Vec_PtrFree( vCopies ); + return pAigNew; +} + +/**Function************************************************************* + + Synopsis [Transforms sequential AIG to block the PO for N cycles.] + + Description [This procedure should be applied to a safety property + miter to make the propetry 'true' (const 0) during the first N cycles.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManBlockPo( Aig_Man_t * pAig, int nCycles ) +{ + Aig_Obj_t * pObj, * pCond, * pPrev, * pTemp; + int i; + assert( nCycles > 0 ); + // add N flops (assuming 1-hot encoding of cycles) + pPrev = Aig_ManConst1(pAig); + pCond = Aig_ManConst1(pAig); + for ( i = 0; i < nCycles; i++ ) + { + Aig_ObjCreateCo( pAig, pPrev ); + pPrev = Aig_ObjCreateCi( pAig ); + pCond = Aig_And( pAig, pCond, pPrev ); + } + // update the POs + Saig_ManForEachPo( pAig, pObj, i ) + { + pTemp = Aig_And( pAig, Aig_ObjChild0(pObj), pCond ); + Aig_ObjPatchFanin0( pAig, pObj, pTemp ); + } + // set the flops + Aig_ManSetRegNum( pAig, Aig_ManRegNum(pAig) + nCycles ); + Aig_ManCleanup( pAig ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigDup.c b/yosys/abc/src/aig/saig/saigDup.c new file mode 100644 index 00000000000..17dfcc40d73 --- /dev/null +++ b/yosys/abc/src/aig/saig/saigDup.c @@ -0,0 +1,602 @@ +/**CFile**************************************************************** + + FileName [saigDup.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Various duplication procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigDup.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Duplicates while ORing the POs of sequential circuit.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManDupOrpos( Aig_Man_t * pAig ) +{ + Aig_Man_t * pAigNew; + Aig_Obj_t * pObj, * pMiter; + int i; + if ( pAig->nConstrs > 0 ) + { + printf( "The AIG manager should have no constraints.\n" ); + return NULL; + } + // start the new manager + pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); + pAigNew->pName = Abc_UtilStrsav( pAig->pName ); + pAigNew->nConstrs = pAig->nConstrs; + // map the constant node + Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); + // create variables for PIs + Aig_ManForEachCi( pAig, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pAigNew ); + // add internal nodes of this frame + Aig_ManForEachNode( pAig, pObj, i ) + pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // create PO of the circuit + pMiter = Aig_ManConst0( pAigNew ); + Saig_ManForEachPo( pAig, pObj, i ) + pMiter = Aig_Or( pAigNew, pMiter, Aig_ObjChild0Copy(pObj) ); + Aig_ObjCreateCo( pAigNew, pMiter ); + // transfer to register outputs + Saig_ManForEachLi( pAig, pObj, i ) + Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); + Aig_ManCleanup( pAigNew ); + Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig) ); + return pAigNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates while ORing the POs of sequential circuit.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManCreateEquivMiter( Aig_Man_t * pAig, Vec_Int_t * vPairs, int fAddOuts ) +{ + Aig_Man_t * pAigNew; + Aig_Obj_t * pObj, * pObj2, * pMiter; + int i; + if ( pAig->nConstrs > 0 ) + { + printf( "The AIG manager should have no constraints.\n" ); + return NULL; + } + // start the new manager + pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); + pAigNew->pName = Abc_UtilStrsav( pAig->pName ); + pAigNew->nConstrs = pAig->nConstrs; + // map the constant node + Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); + // create variables for PIs + Aig_ManForEachCi( pAig, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pAigNew ); + // add internal nodes of this frame + Aig_ManForEachNode( pAig, pObj, i ) + pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // create POs + assert( Vec_IntSize(vPairs) % 2 == 0 ); + Aig_ManForEachObjVec( vPairs, pAig, pObj, i ) + { + pObj2 = Aig_ManObj( pAig, Vec_IntEntry(vPairs, ++i) ); + pMiter = Aig_Exor( pAigNew, (Aig_Obj_t *)pObj->pData, (Aig_Obj_t *)pObj2->pData ); + pMiter = Aig_NotCond( pMiter, pObj->fPhase ^ pObj2->fPhase ); + Aig_ObjCreateCo( pAigNew, pMiter ); + } + // transfer to register outputs + if ( fAddOuts ) + Saig_ManForEachLi( pAig, pObj, i ) + Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); + Aig_ManCleanup( pAigNew ); + if ( fAddOuts ) + Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig) ); + return pAigNew; +} + +/**Function************************************************************* + + Synopsis [Trims the model by removing PIs without fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManTrimPis( Aig_Man_t * p ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj; + int i, fAllPisHaveNoRefs; + // check the refs of PIs + fAllPisHaveNoRefs = 1; + Saig_ManForEachPi( p, pObj, i ) + if ( pObj->nRefs ) + fAllPisHaveNoRefs = 0; + // start the new manager + pNew = Aig_ManStart( Aig_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->nConstrs = p->nConstrs; + // start mapping of the CI numbers + pNew->vCiNumsOrig = Vec_IntAlloc( Aig_ManCiNum(p) ); + // map const and primary inputs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachCi( p, pObj, i ) + if ( fAllPisHaveNoRefs || pObj->nRefs || Saig_ObjIsLo(p, pObj) ) + { + pObj->pData = Aig_ObjCreateCi( pNew ); + Vec_IntPush( pNew->vCiNumsOrig, Vec_IntEntry(p->vCiNumsOrig, i) ); + } + Aig_ManForEachNode( p, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + Aig_ManForEachCo( p, pObj, i ) + pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager recursively.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Saig_ManAbstractionDfs_rec( Aig_Man_t * pNew, Aig_Obj_t * pObj ) +{ + if ( pObj->pData ) + return (Aig_Obj_t *)pObj->pData; + Saig_ManAbstractionDfs_rec( pNew, Aig_ObjFanin0(pObj) ); + Saig_ManAbstractionDfs_rec( pNew, Aig_ObjFanin1(pObj) ); + return (Aig_Obj_t *)(pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) )); +} + +/**Function************************************************************* + + Synopsis [Performs abstraction of the AIG to preserve the included flops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManDupAbstraction( Aig_Man_t * p, Vec_Int_t * vFlops ) +{ + Aig_Man_t * pNew;//, * pTemp; + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int i, Entry; + Aig_ManCleanData( p ); + // start the new manager + pNew = Aig_ManStart( 5000 ); + pNew->pName = Abc_UtilStrsav( p->pName ); + // map the constant node + Aig_ManConst1(p)->pData = Aig_ManConst1( pNew ); + // label included flops + Vec_IntForEachEntry( vFlops, Entry, i ) + { + pObjLi = Saig_ManLi( p, Entry ); + assert( pObjLi->fMarkA == 0 ); + pObjLi->fMarkA = 1; + pObjLo = Saig_ManLo( p, Entry ); + assert( pObjLo->fMarkA == 0 ); + pObjLo->fMarkA = 1; + } + // create variables for PIs + assert( p->vCiNumsOrig == NULL ); + pNew->vCiNumsOrig = Vec_IntAlloc( Aig_ManCiNum(p) ); + Aig_ManForEachCi( p, pObj, i ) + if ( !pObj->fMarkA ) + { + pObj->pData = Aig_ObjCreateCi( pNew ); + Vec_IntPush( pNew->vCiNumsOrig, i ); + } + // create variables for LOs + Aig_ManForEachCi( p, pObj, i ) + if ( pObj->fMarkA ) + { + pObj->fMarkA = 0; + pObj->pData = Aig_ObjCreateCi( pNew ); + Vec_IntPush( pNew->vCiNumsOrig, i ); + } + // add internal nodes +// Aig_ManForEachNode( p, pObj, i ) +// pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // create POs + Saig_ManForEachPo( p, pObj, i ) + { + Saig_ManAbstractionDfs_rec( pNew, Aig_ObjFanin0(pObj) ); + Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + } + // create LIs + Aig_ManForEachCo( p, pObj, i ) + if ( pObj->fMarkA ) + { + pObj->fMarkA = 0; + Saig_ManAbstractionDfs_rec( pNew, Aig_ObjFanin0(pObj) ); + Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + } + Aig_ManSetRegNum( pNew, Vec_IntSize(vFlops) ); + Aig_ManSeqCleanup( pNew ); + // remove PIs without fanout +// pNew = Saig_ManTrimPis( pTemp = pNew ); +// Aig_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Resimulates the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManVerifyCex( Aig_Man_t * pAig, Abc_Cex_t * p ) +{ + Aig_Obj_t * pObj, * pObjRi, * pObjRo; + int RetValue, i, k, iBit = 0; + Aig_ManCleanMarkB(pAig); + Aig_ManConst1(pAig)->fMarkB = 1; + Saig_ManForEachLo( pAig, pObj, i ) + pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); + for ( i = 0; i <= p->iFrame; i++ ) + { + Saig_ManForEachPi( pAig, pObj, k ) + pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); + Aig_ManForEachNode( pAig, pObj, k ) + pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & + (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj)); + Aig_ManForEachCo( pAig, pObj, k ) + pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj); + if ( i == p->iFrame ) + break; + Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k ) + pObjRo->fMarkB = pObjRi->fMarkB; + } + assert( iBit == p->nBits ); + RetValue = Aig_ManCo(pAig, p->iPo)->fMarkB; + Aig_ManCleanMarkB(pAig); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Resimulates the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManVerifyCexNoClear( Aig_Man_t * pAig, Abc_Cex_t * p ) +{ + Aig_Obj_t * pObj, * pObjRi, * pObjRo; + int RetValue, i, k, iBit = 0; + Aig_ManCleanMarkB(pAig); + Aig_ManConst1(pAig)->fMarkB = 1; + Saig_ManForEachLo( pAig, pObj, i ) + pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); + for ( i = 0; i <= p->iFrame; i++ ) + { + Saig_ManForEachPi( pAig, pObj, k ) + pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); + Aig_ManForEachNode( pAig, pObj, k ) + pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & + (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj)); + Aig_ManForEachCo( pAig, pObj, k ) + pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj); + if ( i == p->iFrame ) + break; + Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k ) + pObjRo->fMarkB = pObjRi->fMarkB; + } + assert( iBit == p->nBits ); + RetValue = Aig_ManCo(pAig, p->iPo)->fMarkB; + //Aig_ManCleanMarkB(pAig); + return RetValue; +} +Vec_Int_t * Saig_ManReturnFailingState( Aig_Man_t * pAig, Abc_Cex_t * p, int fNextOne ) +{ + Aig_Obj_t * pObj; + Vec_Int_t * vState; + int i, RetValue = Saig_ManVerifyCexNoClear( pAig, p ); + if ( RetValue == 0 ) + { + Aig_ManCleanMarkB(pAig); + printf( "CEX does fail the given sequential miter.\n" ); + return NULL; + } + vState = Vec_IntAlloc( Aig_ManRegNum(pAig) ); + if ( fNextOne ) + { + Saig_ManForEachLi( pAig, pObj, i ) + Vec_IntPush( vState, pObj->fMarkB ); + } + else + { + Saig_ManForEachLo( pAig, pObj, i ) + Vec_IntPush( vState, pObj->fMarkB ); + } + Aig_ManCleanMarkB(pAig); + return vState; +} + +/**Function************************************************************* + + Synopsis [Resimulates the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Saig_ManExtendCex( Aig_Man_t * pAig, Abc_Cex_t * p ) +{ + Abc_Cex_t * pNew; + Aig_Obj_t * pObj, * pObjRi, * pObjRo; + int RetValue, i, k, iBit = 0; + // create new counter-example + pNew = Abc_CexAlloc( 0, Aig_ManCiNum(pAig), p->iFrame + 1 ); + pNew->iPo = p->iPo; + pNew->iFrame = p->iFrame; + // simulate the AIG + Aig_ManCleanMarkB(pAig); + Aig_ManConst1(pAig)->fMarkB = 1; + Saig_ManForEachLo( pAig, pObj, i ) + pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); + for ( i = 0; i <= p->iFrame; i++ ) + { + Saig_ManForEachPi( pAig, pObj, k ) + pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); + ///////// write PI+LO values //////////// + Aig_ManForEachCi( pAig, pObj, k ) + if ( pObj->fMarkB ) + Abc_InfoSetBit(pNew->pData, Aig_ManCiNum(pAig)*i + k); + ///////////////////////////////////////// + Aig_ManForEachNode( pAig, pObj, k ) + pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & + (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj)); + Aig_ManForEachCo( pAig, pObj, k ) + pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj); + if ( i == p->iFrame ) + break; + Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k ) + pObjRo->fMarkB = pObjRi->fMarkB; + } + assert( iBit == p->nBits ); + RetValue = Aig_ManCo(pAig, p->iPo)->fMarkB; + Aig_ManCleanMarkB(pAig); + if ( RetValue == 0 ) + printf( "Saig_ManExtendCex(): The counter-example is invalid!!!\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Resimulates the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManFindFailedPoCex( Aig_Man_t * pAig, Abc_Cex_t * p ) +{ + Aig_Obj_t * pObj, * pObjRi, * pObjRo; + int RetValue, i, k, iBit = 0; + Aig_ManCleanMarkB(pAig); + Aig_ManConst1(pAig)->fMarkB = 1; + Saig_ManForEachLo( pAig, pObj, i ) + pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); + for ( i = 0; i <= p->iFrame; i++ ) + { + Saig_ManForEachPi( pAig, pObj, k ) + pObj->fMarkB = Abc_InfoHasBit(p->pData, iBit++); + Aig_ManForEachNode( pAig, pObj, k ) + pObj->fMarkB = (Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj)) & + (Aig_ObjFanin1(pObj)->fMarkB ^ Aig_ObjFaninC1(pObj)); + Aig_ManForEachCo( pAig, pObj, k ) + pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB ^ Aig_ObjFaninC0(pObj); + if ( i == p->iFrame ) + break; + Saig_ManForEachLiLo( pAig, pObjRi, pObjRo, k ) + pObjRo->fMarkB = pObjRi->fMarkB; + } + assert( iBit == p->nBits ); + // remember the number of failed output + RetValue = -1; + Saig_ManForEachPo( pAig, pObj, i ) + if ( pObj->fMarkB ) + { + RetValue = i; + break; + } + Aig_ManCleanMarkB(pAig); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Duplicates while ORing the POs of sequential circuit.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManDupWithPhase( Aig_Man_t * pAig, Vec_Int_t * vInit ) +{ + Aig_Man_t * pAigNew; + Aig_Obj_t * pObj; + int i; + assert( Aig_ManRegNum(pAig) <= Vec_IntSize(vInit) ); + // start the new manager + pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); + pAigNew->pName = Abc_UtilStrsav( pAig->pName ); + pAigNew->nConstrs = pAig->nConstrs; + // map the constant node + Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); + // create variables for PIs + Aig_ManForEachCi( pAig, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pAigNew ); + // update the flop variables + Saig_ManForEachLo( pAig, pObj, i ) + pObj->pData = Aig_NotCond( (Aig_Obj_t *)pObj->pData, Vec_IntEntry(vInit, i) ); + // add internal nodes of this frame + Aig_ManForEachNode( pAig, pObj, i ) + pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // transfer to register outputs + Saig_ManForEachPo( pAig, pObj, i ) + Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); + // update the flop variables + Saig_ManForEachLi( pAig, pObj, i ) + Aig_ObjCreateCo( pAigNew, Aig_NotCond(Aig_ObjChild0Copy(pObj), Vec_IntEntry(vInit, i)) ); + // finalize + Aig_ManCleanup( pAigNew ); + Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig) ); + return pAigNew; +} + +/**Function************************************************************* + + Synopsis [Copy an AIG structure related to the selected POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManDupCones_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vNodes, Vec_Ptr_t * vRoots ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Aig_ObjIsNode(pObj) ) + { + Saig_ManDupCones_rec( p, Aig_ObjFanin0(pObj), vLeaves, vNodes, vRoots ); + Saig_ManDupCones_rec( p, Aig_ObjFanin1(pObj), vLeaves, vNodes, vRoots ); + Vec_PtrPush( vNodes, pObj ); + } + else if ( Aig_ObjIsCo(pObj) ) + Saig_ManDupCones_rec( p, Aig_ObjFanin0(pObj), vLeaves, vNodes, vRoots ); + else if ( Saig_ObjIsLo(p, pObj) ) + Vec_PtrPush( vRoots, Saig_ObjLoToLi(p, pObj) ); + else if ( Saig_ObjIsPi(p, pObj) ) + Vec_PtrPush( vLeaves, pObj ); + else assert( 0 ); +} +Aig_Man_t * Saig_ManDupCones( Aig_Man_t * pAig, int * pPos, int nPos ) +{ + Aig_Man_t * pAigNew; + Vec_Ptr_t * vLeaves, * vNodes, * vRoots; + Aig_Obj_t * pObj; + int i; + + // collect initial POs + vLeaves = Vec_PtrAlloc( 100 ); + vNodes = Vec_PtrAlloc( 100 ); + vRoots = Vec_PtrAlloc( 100 ); + for ( i = 0; i < nPos; i++ ) + Vec_PtrPush( vRoots, Aig_ManCo(pAig, pPos[i]) ); + + // mark internal nodes + Aig_ManIncrementTravId( pAig ); + Aig_ObjSetTravIdCurrent( pAig, Aig_ManConst1(pAig) ); + Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i ) + Saig_ManDupCones_rec( pAig, pObj, vLeaves, vNodes, vRoots ); + + // start the new manager + pAigNew = Aig_ManStart( Vec_PtrSize(vNodes) ); + pAigNew->pName = Abc_UtilStrsav( pAig->pName ); + // map the constant node + Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); + // create PIs + Vec_PtrForEachEntry( Aig_Obj_t *, vLeaves, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pAigNew ); + // create LOs + Vec_PtrForEachEntryStart( Aig_Obj_t *, vRoots, pObj, i, nPos ) + Saig_ObjLiToLo(pAig, pObj)->pData = Aig_ObjCreateCi( pAigNew ); + // create internal nodes + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // create COs + Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i ) + Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); + // finalize + Aig_ManSetRegNum( pAigNew, Vec_PtrSize(vRoots)-nPos ); + Vec_PtrFree( vLeaves ); + Vec_PtrFree( vNodes ); + Vec_PtrFree( vRoots ); + return pAigNew; + +} + +#ifndef ABC_USE_CUDD +int Aig_ManVerifyUsingBdds( Aig_Man_t * pInit, Saig_ParBbr_t * pPars ) { return 0; } +void Bbr_ManSetDefaultParams( Saig_ParBbr_t * p ) {} +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigGlaCba.c b/yosys/abc/src/aig/saig/saigGlaCba.c new file mode 100644 index 00000000000..162795b0e94 --- /dev/null +++ b/yosys/abc/src/aig/saig/saigGlaCba.c @@ -0,0 +1,840 @@ +/**CFile**************************************************************** + + FileName [saigGlaCba.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Gate level abstraction.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigGlaCba.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" +#include "sat/bsat/satSolver.h" +#include "sat/cnf/cnf.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Aig_Gla1Man_t_ Aig_Gla1Man_t; +struct Aig_Gla1Man_t_ +{ + // user data + Aig_Man_t * pAig; + int nConfLimit; + int nFramesMax; + int fVerbose; + // unrolling + int nFrames; + Vec_Int_t * vObj2Vec; // maps obj ID into its vec ID + Vec_Int_t * vVec2Var; // maps vec ID into its sat Var (nFrames per vec ID) + Vec_Int_t * vVar2Inf; // maps sat Var into its frame and obj ID + // abstraction + Vec_Int_t * vAssigned; // collects objects whose SAT variables have been created + Vec_Int_t * vIncluded; // maps obj ID into its status (0=unused; 1=included in abstraction) + // components + Vec_Int_t * vPis; // primary inputs + Vec_Int_t * vPPis; // pseudo primary inputs + Vec_Int_t * vFlops; // flops + Vec_Int_t * vNodes; // nodes + // CNF computation + Vec_Ptr_t * vLeaves; + Vec_Ptr_t * vVolume; + Vec_Int_t * vCover; + Vec_Ptr_t * vObj2Cnf; + Vec_Int_t * vLits; + // SAT solver + sat_solver * pSat; + // statistics + clock_t timeSat; + clock_t timeRef; + clock_t timeTotal; +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Adds constant to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_Gla1AddConst( sat_solver * pSat, int iVar, int fCompl ) +{ + lit Lit = toLitCond( iVar, fCompl ); + if ( !sat_solver_addclause( pSat, &Lit, &Lit + 1 ) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Adds buffer to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_Gla1AddBuffer( sat_solver * pSat, int iVar0, int iVar1, int fCompl ) +{ + lit Lits[2]; + + Lits[0] = toLitCond( iVar0, 0 ); + Lits[1] = toLitCond( iVar1, !fCompl ); + if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) + return 0; + + Lits[0] = toLitCond( iVar0, 1 ); + Lits[1] = toLitCond( iVar1, fCompl ); + if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) + return 0; + + return 1; +} + +/**Function************************************************************* + + Synopsis [Adds buffer to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_Gla1AddNode( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1 ) +{ + lit Lits[3]; + + Lits[0] = toLitCond( iVar, 1 ); + Lits[1] = toLitCond( iVar0, fCompl0 ); + if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) + return 0; + + Lits[0] = toLitCond( iVar, 1 ); + Lits[1] = toLitCond( iVar1, fCompl1 ); + if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) + return 0; + + Lits[0] = toLitCond( iVar, 0 ); + Lits[1] = toLitCond( iVar0, !fCompl0 ); + Lits[2] = toLitCond( iVar1, !fCompl1 ); + if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) ) + return 0; + + return 1; +} + +/**Function************************************************************* + + Synopsis [Derives abstraction components (PIs, PPIs, flops, nodes).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_Gla1CollectAbstr( Aig_Gla1Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, Entry; +/* + // make sure every neighbor of included objects is assigned a variable + Vec_IntForEachEntry( p->vIncluded, Entry, i ) + { + if ( Entry == 0 ) + continue; + assert( Entry == 1 ); + pObj = Aig_ManObj( p->pAig, i ); + if ( Vec_IntFind( p->vAssigned, Aig_ObjId(pObj) ) == -1 ) + printf( "Aig_Gla1CollectAbstr(): Object not found\n" ); + if ( Aig_ObjIsNode(pObj) ) + { + if ( Vec_IntFind( p->vAssigned, Aig_ObjFaninId0(pObj) ) == -1 ) + printf( "Aig_Gla1CollectAbstr(): Node's fanin is not found\n" ); + if ( Vec_IntFind( p->vAssigned, Aig_ObjFaninId1(pObj) ) == -1 ) + printf( "Aig_Gla1CollectAbstr(): Node's fanin is not found\n" ); + } + else if ( Saig_ObjIsLo(p->pAig, pObj) ) + { + Aig_Obj_t * pObjLi; + pObjLi = Saig_ObjLoToLi(p->pAig, pObj); + if ( Vec_IntFind( p->vAssigned, Aig_ObjFaninId0(pObjLi) ) == -1 ) + printf( "Aig_Gla1CollectAbstr(): Flop's fanin is not found\n" ); + } + else assert( Aig_ObjIsConst1(pObj) ); + } +*/ + Vec_IntClear( p->vPis ); + Vec_IntClear( p->vPPis ); + Vec_IntClear( p->vFlops ); + Vec_IntClear( p->vNodes ); + Vec_IntForEachEntryReverse( p->vAssigned, Entry, i ) + { + pObj = Aig_ManObj( p->pAig, Entry ); + if ( Saig_ObjIsPi(p->pAig, pObj) ) + Vec_IntPush( p->vPis, Aig_ObjId(pObj) ); + else if ( !Vec_IntEntry(p->vIncluded, Aig_ObjId(pObj)) ) + Vec_IntPush( p->vPPis, Aig_ObjId(pObj) ); + else if ( Aig_ObjIsNode(pObj) ) + Vec_IntPush( p->vNodes, Aig_ObjId(pObj) ); + else if ( Saig_ObjIsLo(p->pAig, pObj) ) + Vec_IntPush( p->vFlops, Aig_ObjId(pObj) ); + else assert( Aig_ObjIsConst1(pObj) ); + } +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG manager recursively.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_Gla1DeriveAbs_rec( Aig_Man_t * pNew, Aig_Obj_t * pObj ) +{ + if ( pObj->pData ) + return; + assert( Aig_ObjIsNode(pObj) ); + Aig_Gla1DeriveAbs_rec( pNew, Aig_ObjFanin0(pObj) ); + Aig_Gla1DeriveAbs_rec( pNew, Aig_ObjFanin1(pObj) ); + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Derives abstraction.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_Gla1DeriveAbs( Aig_Gla1Man_t * p ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj; + int i, RetValue; + assert( Saig_ManPoNum(p->pAig) == 1 ); + // start the new manager + pNew = Aig_ManStart( 5000 ); + pNew->pName = Abc_UtilStrsav( p->pAig->pName ); + // create constant + Aig_ManCleanData( p->pAig ); + Aig_ManConst1(p->pAig)->pData = Aig_ManConst1(pNew); + // create PIs + Aig_ManForEachObjVec( p->vPis, p->pAig, pObj, i ) + pObj->pData = Aig_ObjCreateCi(pNew); + // create additional PIs + Aig_ManForEachObjVec( p->vPPis, p->pAig, pObj, i ) + pObj->pData = Aig_ObjCreateCi(pNew); + // create ROs + Aig_ManForEachObjVec( p->vFlops, p->pAig, pObj, i ) + pObj->pData = Aig_ObjCreateCi(pNew); + // create internal nodes + Aig_ManForEachObjVec( p->vNodes, p->pAig, pObj, i ) +// pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + Aig_Gla1DeriveAbs_rec( pNew, pObj ); + // create PO + Saig_ManForEachPo( p->pAig, pObj, i ) + pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + // create RIs + Aig_ManForEachObjVec( p->vFlops, p->pAig, pObj, i ) + { + assert( Saig_ObjIsLo(p->pAig, pObj) ); + pObj = Saig_ObjLoToLi( p->pAig, pObj ); + pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + } + Aig_ManSetRegNum( pNew, Vec_IntSize(p->vFlops) ); + // clean up + RetValue = Aig_ManCleanup( pNew ); + if ( RetValue > 0 ) + printf( "Aig_Gla1DeriveAbs(): Internal error! Object count mismatch.\n" ); + assert( RetValue == 0 ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Finds existing SAT variable or creates a new one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_Gla1FetchVecId( Aig_Gla1Man_t * p, Aig_Obj_t * pObj ) +{ + int i, iVecId; + iVecId = Vec_IntEntry( p->vObj2Vec, Aig_ObjId(pObj) ); + if ( iVecId == 0 ) + { + iVecId = Vec_IntSize( p->vVec2Var ) / p->nFrames; + for ( i = 0; i < p->nFrames; i++ ) + Vec_IntPush( p->vVec2Var, 0 ); + Vec_IntWriteEntry( p->vObj2Vec, Aig_ObjId(pObj), iVecId ); + Vec_IntPushOrderReverse( p->vAssigned, Aig_ObjId(pObj) ); + } + return iVecId; +} + +/**Function************************************************************* + + Synopsis [Finds existing SAT variable or creates a new one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_Gla1FetchVar( Aig_Gla1Man_t * p, Aig_Obj_t * pObj, int k ) +{ + int iVecId, iSatVar; + assert( k < p->nFrames ); + iVecId = Aig_Gla1FetchVecId( p, pObj ); + iSatVar = Vec_IntEntry( p->vVec2Var, iVecId * p->nFrames + k ); + if ( iSatVar == 0 ) + { + iSatVar = Vec_IntSize( p->vVar2Inf ) / 2; + Vec_IntPush( p->vVar2Inf, Aig_ObjId(pObj) ); + Vec_IntPush( p->vVar2Inf, k ); + Vec_IntWriteEntry( p->vVec2Var, iVecId * p->nFrames + k, iSatVar ); + sat_solver_setnvars( p->pSat, iSatVar + 1 ); + } + return iSatVar; +} + +/**Function************************************************************* + + Synopsis [Adds CNF for the given object in the given frame.] + + Description [Returns 0, if the solver becames UNSAT.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_Gla1ObjAddToSolver( Aig_Gla1Man_t * p, Aig_Obj_t * pObj, int k ) +{ + if ( k == p->nFrames ) + { + int i, j, nVecIds = Vec_IntSize( p->vVec2Var ) / p->nFrames; + Vec_Int_t * vVec2VarNew = Vec_IntAlloc( 4 * nVecIds * p->nFrames ); + for ( i = 0; i < nVecIds; i++ ) + { + for ( j = 0; j < p->nFrames; j++ ) + Vec_IntPush( vVec2VarNew, Vec_IntEntry( p->vVec2Var, i * p->nFrames + j ) ); + for ( j = 0; j < p->nFrames; j++ ) + Vec_IntPush( vVec2VarNew, i ? 0 : -1 ); + } + Vec_IntFree( p->vVec2Var ); + p->vVec2Var = vVec2VarNew; + p->nFrames *= 2; + } + assert( k < p->nFrames ); + assert( Vec_IntEntry(p->vIncluded, Aig_ObjId(pObj)) ); + if ( Aig_ObjIsConst1(pObj) ) + return Aig_Gla1AddConst( p->pSat, Aig_Gla1FetchVar(p, pObj, k), 0 ); + if ( Saig_ObjIsLo(p->pAig, pObj) ) + { + Aig_Obj_t * pObjLi = Saig_ObjLoToLi(p->pAig, pObj); + if ( k == 0 ) + { + Aig_Gla1FetchVecId( p, Aig_ObjFanin0(pObjLi) ); + return Aig_Gla1AddConst( p->pSat, Aig_Gla1FetchVar(p, pObj, k), 1 ); + } + return Aig_Gla1AddBuffer( p->pSat, Aig_Gla1FetchVar(p, pObj, k), + Aig_Gla1FetchVar(p, Aig_ObjFanin0(pObjLi), k-1), + Aig_ObjFaninC0(pObjLi) ); + } + else + { + Vec_Int_t * vClauses; + int i, Entry; + assert( Aig_ObjIsNode(pObj) ); + if ( p->vObj2Cnf == NULL ) + return Aig_Gla1AddNode( p->pSat, Aig_Gla1FetchVar(p, pObj, k), + Aig_Gla1FetchVar(p, Aig_ObjFanin0(pObj), k), + Aig_Gla1FetchVar(p, Aig_ObjFanin1(pObj), k), + Aig_ObjFaninC0(pObj), Aig_ObjFaninC1(pObj) ); + // derive clauses + assert( pObj->fMarkA ); + vClauses = (Vec_Int_t *)Vec_PtrEntry( p->vObj2Cnf, Aig_ObjId(pObj) ); + if ( vClauses == NULL ) + { + Vec_PtrWriteEntry( p->vObj2Cnf, Aig_ObjId(pObj), (vClauses = Vec_IntAlloc(16)) ); + Cnf_ComputeClauses( p->pAig, pObj, p->vLeaves, p->vVolume, NULL, p->vCover, vClauses ); + } + // derive variables + Cnf_CollectLeaves( pObj, p->vLeaves, 0 ); + Vec_PtrForEachEntry( Aig_Obj_t *, p->vLeaves, pObj, i ) + Aig_Gla1FetchVar( p, pObj, k ); + // translate clauses + assert( Vec_IntSize(vClauses) >= 2 ); + assert( Vec_IntEntry(vClauses, 0) == 0 ); + Vec_IntForEachEntry( vClauses, Entry, i ) + { + if ( Entry == 0 ) + { + Vec_IntClear( p->vLits ); + continue; + } + Vec_IntPush( p->vLits, (Entry & 1) ^ (2 * Aig_Gla1FetchVar(p, Aig_ManObj(p->pAig, Entry >> 1), k)) ); + if ( i == Vec_IntSize(vClauses) - 1 || Vec_IntEntry(vClauses, i+1) == 0 ) + { + if ( !sat_solver_addclause( p->pSat, Vec_IntArray(p->vLits), Vec_IntArray(p->vLits)+Vec_IntSize(p->vLits) ) ) + return 0; + } + } + return 1; + } +} + +/**Function************************************************************* + + Synopsis [Returns the array of neighbors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_Gla1CollectAssigned( Aig_Gla1Man_t * p, Vec_Int_t * vGateClasses ) +{ + Aig_Obj_t * pObj; + int i, Entry; + Vec_IntForEachEntryReverse( vGateClasses, Entry, i ) + { + if ( Entry == 0 ) + continue; + assert( Entry == 1 ); + pObj = Aig_ManObj( p->pAig, i ); + Aig_Gla1FetchVecId( p, pObj ); + if ( Aig_ObjIsNode(pObj) ) + { + Aig_Gla1FetchVecId( p, Aig_ObjFanin0(pObj) ); + Aig_Gla1FetchVecId( p, Aig_ObjFanin1(pObj) ); + } + else if ( Saig_ObjIsLo(p->pAig, pObj) ) + Aig_Gla1FetchVecId( p, Aig_ObjFanin0(Saig_ObjLoToLi(p->pAig, pObj)) ); + else assert( Aig_ObjIsConst1(pObj) ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Gla1Man_t * Aig_Gla1ManStart( Aig_Man_t * pAig, Vec_Int_t * vGateClassesOld, int fNaiveCnf ) +{ + Aig_Gla1Man_t * p; + int i; + + p = ABC_CALLOC( Aig_Gla1Man_t, 1 ); + p->pAig = pAig; + p->nFrames = 32; + + // unrolling + p->vObj2Vec = Vec_IntStart( Aig_ManObjNumMax(pAig) ); + p->vVec2Var = Vec_IntAlloc( 1 << 20 ); + p->vVar2Inf = Vec_IntAlloc( 1 << 20 ); + + // skip first vector ID + for ( i = 0; i < p->nFrames; i++ ) + Vec_IntPush( p->vVec2Var, -1 ); + // skip first SAT variable + Vec_IntPush( p->vVar2Inf, -1 ); + Vec_IntPush( p->vVar2Inf, -1 ); + + // abstraction + p->vAssigned = Vec_IntAlloc( 1000 ); + if ( vGateClassesOld ) + { + p->vIncluded = Vec_IntDup( vGateClassesOld ); + Aig_Gla1CollectAssigned( p, vGateClassesOld ); + assert( fNaiveCnf ); + } + else + p->vIncluded = Vec_IntStart( Aig_ManObjNumMax(pAig) ); + + // components + p->vPis = Vec_IntAlloc( 1000 ); + p->vPPis = Vec_IntAlloc( 1000 ); + p->vFlops = Vec_IntAlloc( 1000 ); + p->vNodes = Vec_IntAlloc( 1000 ); + + // CNF computation + if ( !fNaiveCnf ) + { + p->vLeaves = Vec_PtrAlloc( 100 ); + p->vVolume = Vec_PtrAlloc( 100 ); + p->vCover = Vec_IntAlloc( 1 << 16 ); + p->vObj2Cnf = Vec_PtrStart( Aig_ManObjNumMax(pAig) ); + p->vLits = Vec_IntAlloc( 100 ); + Cnf_DeriveFastMark( pAig ); + } + + // start the SAT solver + p->pSat = sat_solver_new(); + sat_solver_setnvars( p->pSat, 256 ); + return p; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_Gla1ManStop( Aig_Gla1Man_t * p ) +{ + Vec_IntFreeP( &p->vObj2Vec ); + Vec_IntFreeP( &p->vVec2Var ); + Vec_IntFreeP( &p->vVar2Inf ); + + Vec_IntFreeP( &p->vAssigned ); + Vec_IntFreeP( &p->vIncluded ); + + Vec_IntFreeP( &p->vPis ); + Vec_IntFreeP( &p->vPPis ); + Vec_IntFreeP( &p->vFlops ); + Vec_IntFreeP( &p->vNodes ); + + if ( p->vObj2Cnf ) + { + Vec_PtrFreeP( &p->vLeaves ); + Vec_PtrFreeP( &p->vVolume ); + Vec_IntFreeP( &p->vCover ); + Vec_VecFreeP( (Vec_Vec_t **)&p->vObj2Cnf ); + Vec_IntFreeP( &p->vLits ); + Aig_ManCleanMarkA( p->pAig ); + } + + if ( p->pSat ) + sat_solver_delete( p->pSat ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Aig_Gla1DeriveCex( Aig_Gla1Man_t * p, int iFrame ) +{ + Abc_Cex_t * pCex; + Aig_Obj_t * pObj; + int i, f, iVecId, iSatId; + pCex = Abc_CexAlloc( Vec_IntSize(p->vFlops), Vec_IntSize(p->vPis) + Vec_IntSize(p->vPPis), iFrame+1 ); + pCex->iFrame = iFrame; + Aig_ManForEachObjVec( p->vPis, p->pAig, pObj, i ) + { + iVecId = Vec_IntEntry( p->vObj2Vec, Aig_ObjId(pObj) ); + assert( iVecId > 0 ); + for ( f = 0; f <= iFrame; f++ ) + { + iSatId = Vec_IntEntry( p->vVec2Var, iVecId * p->nFrames + f ); + if ( iSatId == 0 ) + continue; + assert( iSatId > 0 ); + if ( sat_solver_var_value(p->pSat, iSatId) ) + Abc_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + i ); + } + } + Aig_ManForEachObjVec( p->vPPis, p->pAig, pObj, i ) + { + iVecId = Vec_IntEntry( p->vObj2Vec, Aig_ObjId(pObj) ); + assert( iVecId > 0 ); + for ( f = 0; f <= iFrame; f++ ) + { + iSatId = Vec_IntEntry( p->vVec2Var, iVecId * p->nFrames + f ); + if ( iSatId == 0 ) + continue; + assert( iSatId > 0 ); + if ( sat_solver_var_value(p->pSat, iSatId) ) + Abc_InfoSetBit( pCex->pData, pCex->nRegs + f * pCex->nPis + Vec_IntSize(p->vPis) + i ); + } + } + return pCex; +} + +/**Function************************************************************* + + Synopsis [Prints current abstraction statistics.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_Gla1PrintAbstr( Aig_Gla1Man_t * p, int f, int r, int v, int c ) +{ + if ( r == 0 ) + printf( "== %3d ==", f ); + else + printf( " " ); + printf( " %4d PI =%6d PPI =%6d FF =%6d Node =%6d Var =%7d Conf =%6d\n", + r, Vec_IntSize(p->vPis), Vec_IntSize(p->vPPis), Vec_IntSize(p->vFlops), Vec_IntSize(p->vNodes), v, c ); +} + +/**Function************************************************************* + + Synopsis [Prints current abstraction statistics.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_Gla1ExtendIncluded( Aig_Gla1Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, k; + Aig_ManForEachNode( p->pAig, pObj, i ) + { + if ( !Vec_IntEntry( p->vIncluded, i ) ) + continue; + Cnf_ComputeClauses( p->pAig, pObj, p->vLeaves, p->vVolume, NULL, p->vCover, p->vNodes ); + Vec_PtrForEachEntry( Aig_Obj_t *, p->vVolume, pObj, k ) + { + assert( Aig_ObjId(pObj) <= i ); + Vec_IntWriteEntry( p->vIncluded, Aig_ObjId(pObj), 1 ); + } + } +} + +/**Function************************************************************* + + Synopsis [Performs gate-level localization abstraction.] + + Description [Returns array of objects included in the abstraction. This array + may contain only const1, flop outputs, and internal nodes, that is, objects + that should have clauses added to the SAT solver.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Aig_Gla1ManPerform( Aig_Man_t * pAig, Vec_Int_t * vGateClassesOld, int nStart, int nFramesMax, int nConfLimit, int TimeLimit, int fNaiveCnf, int fVerbose, int * piFrame ) +{ + Vec_Int_t * vResult = NULL; + Aig_Gla1Man_t * p; + Aig_Man_t * pAbs; + Aig_Obj_t * pObj; + Abc_Cex_t * pCex; + Vec_Int_t * vPPiRefine; + int f, g, r, i, iSatVar, Lit, Entry, RetValue; + int nConfBef, nConfAft; + clock_t clk, clkTotal = clock(); + clock_t nTimeToStop = TimeLimit ? TimeLimit * CLOCKS_PER_SEC + clock(): 0; + assert( Saig_ManPoNum(pAig) == 1 ); + + if ( nFramesMax == 0 ) + nFramesMax = ABC_INFINITY; + + if ( fVerbose ) + { + if ( TimeLimit ) + printf( "Abstracting from frame %d to frame %d with timeout %d sec.\n", nStart, nFramesMax, TimeLimit ); + else + printf( "Abstracting from frame %d to frame %d with no timeout.\n", nStart, nFramesMax ); + } + + // start the solver + p = Aig_Gla1ManStart( pAig, vGateClassesOld, fNaiveCnf ); + p->nFramesMax = nFramesMax; + p->nConfLimit = nConfLimit; + p->fVerbose = fVerbose; + + // include constant node + Vec_IntWriteEntry( p->vIncluded, 0, 1 ); + Aig_Gla1FetchVecId( p, Aig_ManConst1(pAig) ); + + // set runtime limit + if ( TimeLimit ) + sat_solver_set_runtime_limit( p->pSat, nTimeToStop ); + + // iterate over the timeframes + for ( f = 0; f < nFramesMax; f++ ) + { + // initialize abstraction in this timeframe + Aig_ManForEachObjVec( p->vAssigned, pAig, pObj, i ) + if ( Vec_IntEntry(p->vIncluded, Aig_ObjId(pObj)) ) + if ( !Aig_Gla1ObjAddToSolver( p, pObj, f ) ) + printf( "Error! SAT solver became UNSAT.\n" ); + + // skip checking if we are not supposed to + if ( f < nStart ) + continue; + + // create output literal to represent property failure + pObj = Aig_ManCo( pAig, 0 ); + iSatVar = Aig_Gla1FetchVar( p, Aig_ObjFanin0(pObj), f ); + Lit = toLitCond( iSatVar, Aig_ObjFaninC0(pObj) ); + + // try solving the abstraction + Aig_Gla1CollectAbstr( p ); + for ( r = 0; r < ABC_INFINITY; r++ ) + { + // try to find a counter-example + clk = clock(); + nConfBef = p->pSat->stats.conflicts; + RetValue = sat_solver_solve( p->pSat, &Lit, &Lit + 1, + (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + nConfAft = p->pSat->stats.conflicts; + p->timeSat += clock() - clk; + if ( RetValue != l_True ) + { + if ( fVerbose ) + { + if ( r == 0 ) + printf( "== %3d ==", f ); + else + printf( " " ); + if ( TimeLimit && clock() > nTimeToStop ) + printf( " SAT solver timed out after %d seconds.\n", TimeLimit ); + else if ( RetValue != l_False ) + printf( " SAT solver returned UNDECIDED after %5d conflicts.\n", nConfAft - nConfBef ); + else + { + printf( " SAT solver returned UNSAT after %5d conflicts. ", nConfAft - nConfBef ); + Abc_PrintTime( 1, "Total time", clock() - clkTotal ); + } + } + break; + } + clk = clock(); + // derive abstraction + pAbs = Aig_Gla1DeriveAbs( p ); + // derive counter-example + pCex = Aig_Gla1DeriveCex( p, f ); + // verify the counter-example + RetValue = Saig_ManVerifyCex( pAbs, pCex ); + if ( RetValue == 0 ) + printf( "Error! CEX is invalid.\n" ); + // perform refinement + vPPiRefine = Saig_ManCbaFilterInputs( pAbs, Vec_IntSize(p->vPis), pCex, 0 ); + Vec_IntForEachEntry( vPPiRefine, Entry, i ) + { + pObj = Aig_ManObj( pAig, Vec_IntEntry(p->vPPis, Entry) ); + assert( Aig_ObjIsNode(pObj) || Saig_ObjIsLo(p->pAig, pObj) ); + assert( Vec_IntEntry( p->vIncluded, Aig_ObjId(pObj) ) == 0 ); + Vec_IntWriteEntry( p->vIncluded, Aig_ObjId(pObj), 1 ); + for ( g = 0; g <= f; g++ ) + if ( !Aig_Gla1ObjAddToSolver( p, pObj, g ) ) + printf( "Error! SAT solver became UNSAT.\n" ); + } + if ( Vec_IntSize(vPPiRefine) == 0 ) + { + Vec_IntFreeP( &p->vIncluded ); + Vec_IntFree( vPPiRefine ); + Aig_ManStop( pAbs ); + Abc_CexFree( pCex ); + break; + } + Vec_IntFree( vPPiRefine ); + Aig_ManStop( pAbs ); + Abc_CexFree( pCex ); + p->timeRef += clock() - clk; + + // prepare abstraction + Aig_Gla1CollectAbstr( p ); + if ( fVerbose ) + Aig_Gla1PrintAbstr( p, f, r, p->pSat->size, nConfAft - nConfBef ); + } + if ( RetValue != l_False ) + break; + } + p->timeTotal = clock() - clkTotal; + if ( f == nFramesMax ) + printf( "Finished %d frames without exceeding conflict limit (%d).\n", f, nConfLimit ); + else if ( p->vIncluded == NULL ) + printf( "The problem is SAT in frame %d. The CEX is currently not produced.\n", f ); + else + printf( "Ran out of conflict limit (%d) at frame %d.\n", nConfLimit, f ); + *piFrame = f; + // print stats + if ( fVerbose ) + { + ABC_PRTP( "Sat ", p->timeSat, p->timeTotal ); + ABC_PRTP( "Ref ", p->timeRef, p->timeTotal ); + ABC_PRTP( "Total ", p->timeTotal, p->timeTotal ); + } + // prepare return value + if ( !fNaiveCnf && p->vIncluded ) + Aig_Gla1ExtendIncluded( p ); + vResult = p->vIncluded; p->vIncluded = NULL; + Aig_Gla1ManStop( p ); + return vResult; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigGlaPba.c b/yosys/abc/src/aig/saig/saigGlaPba.c new file mode 100644 index 00000000000..d26bbe8900c --- /dev/null +++ b/yosys/abc/src/aig/saig/saigGlaPba.c @@ -0,0 +1,589 @@ +/**CFile**************************************************************** + + FileName [saigGlaPba.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Gate level abstraction.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigGlaPba.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" +#include "sat/bsat/satSolver.h" +#include "sat/bsat/satStore.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Aig_Gla2Man_t_ Aig_Gla2Man_t; +struct Aig_Gla2Man_t_ +{ + // user data + Aig_Man_t * pAig; + int nStart; + int nFramesMax; + int fVerbose; + // unrolling + Vec_Int_t * vObj2Vec; // maps obj ID into its vec ID + Vec_Int_t * vVec2Var; // maps vec ID into its sat Var (nFrames per vec ID) + Vec_Int_t * vVar2Inf; // maps sat Var into its frame and obj ID + // clause mapping + Vec_Int_t * vCla2Obj; // maps clause into its root object + Vec_Int_t * vCla2Fra; // maps clause into its frame + Vec_Int_t * vVec2Use; // maps vec ID into its used frames (nFrames per vec ID) + // SAT solver + sat_solver * pSat; + // statistics + clock_t timePre; + clock_t timeSat; + clock_t timeTotal; +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +/**Function************************************************************* + + Synopsis [Adds constant to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_Gla2AddConst( sat_solver * pSat, int iVar, int fCompl ) +{ + lit Lit = toLitCond( iVar, fCompl ); + if ( !sat_solver_addclause( pSat, &Lit, &Lit + 1 ) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Adds buffer to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_Gla2AddBuffer( sat_solver * pSat, int iVar0, int iVar1, int fCompl ) +{ + lit Lits[2]; + + Lits[0] = toLitCond( iVar0, 0 ); + Lits[1] = toLitCond( iVar1, !fCompl ); + if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) + return 0; + + Lits[0] = toLitCond( iVar0, 1 ); + Lits[1] = toLitCond( iVar1, fCompl ); + if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) + return 0; + + return 1; +} + +/**Function************************************************************* + + Synopsis [Adds buffer to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_Gla2AddNode( sat_solver * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1 ) +{ + lit Lits[3]; + + Lits[0] = toLitCond( iVar, 1 ); + Lits[1] = toLitCond( iVar0, fCompl0 ); + if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) + return 0; + + Lits[0] = toLitCond( iVar, 1 ); + Lits[1] = toLitCond( iVar1, fCompl1 ); + if ( !sat_solver_addclause( pSat, Lits, Lits + 2 ) ) + return 0; + + Lits[0] = toLitCond( iVar, 0 ); + Lits[1] = toLitCond( iVar0, !fCompl0 ); + Lits[2] = toLitCond( iVar1, !fCompl1 ); + if ( !sat_solver_addclause( pSat, Lits, Lits + 3 ) ) + return 0; + + return 1; +} + + +/**Function************************************************************* + + Synopsis [Finds existing SAT variable or creates a new one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_Gla2FetchVar( Aig_Gla2Man_t * p, Aig_Obj_t * pObj, int k ) +{ + int i, iVecId, iSatVar; + assert( k < p->nFramesMax ); + iVecId = Vec_IntEntry( p->vObj2Vec, Aig_ObjId(pObj) ); + if ( iVecId == 0 ) + { + iVecId = Vec_IntSize( p->vVec2Var ) / p->nFramesMax; + for ( i = 0; i < p->nFramesMax; i++ ) + Vec_IntPush( p->vVec2Var, 0 ); + Vec_IntWriteEntry( p->vObj2Vec, Aig_ObjId(pObj), iVecId ); + } + iSatVar = Vec_IntEntry( p->vVec2Var, iVecId * p->nFramesMax + k ); + if ( iSatVar == 0 ) + { + iSatVar = Vec_IntSize( p->vVar2Inf ) / 2; + Vec_IntPush( p->vVar2Inf, Aig_ObjId(pObj) ); + Vec_IntPush( p->vVar2Inf, k ); + Vec_IntWriteEntry( p->vVec2Var, iVecId * p->nFramesMax + k, iSatVar ); + } + return iSatVar; +} + +/**Function************************************************************* + + Synopsis [Assigns variables to the AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_Gla2AssignVars_rec( Aig_Gla2Man_t * p, Aig_Obj_t * pObj, int f ) +{ + int nVars = Vec_IntSize(p->vVar2Inf); + Aig_Gla2FetchVar( p, pObj, f ); + if ( nVars == Vec_IntSize(p->vVar2Inf) ) + return; + if ( Aig_ObjIsConst1(pObj) ) + return; + if ( Saig_ObjIsPo( p->pAig, pObj ) ) + { + Aig_Gla2AssignVars_rec( p, Aig_ObjFanin0(pObj), f ); + return; + } + if ( Aig_ObjIsCi( pObj ) ) + { + if ( Saig_ObjIsLo(p->pAig, pObj) && f > 0 ) + Aig_Gla2AssignVars_rec( p, Aig_ObjFanin0( Saig_ObjLoToLi(p->pAig, pObj) ), f-1 ); + return; + } + assert( Aig_ObjIsNode(pObj) ); + Aig_Gla2AssignVars_rec( p, Aig_ObjFanin0(pObj), f ); + Aig_Gla2AssignVars_rec( p, Aig_ObjFanin1(pObj), f ); +} + +/**Function************************************************************* + + Synopsis [Creates SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_Gla2CreateSatSolver( Aig_Gla2Man_t * p ) +{ + Vec_Int_t * vPoLits; + Aig_Obj_t * pObj; + int i, f, ObjId, nVars, RetValue = 1; + + // assign variables + for ( f = p->nFramesMax - 1; f >= 0; f-- ) +// for ( f = 0; f < p->nFramesMax; f++ ) + Aig_Gla2AssignVars_rec( p, Aig_ManCo(p->pAig, 0), f ); + + // create SAT solver + p->pSat = sat_solver_new(); + sat_solver_store_alloc( p->pSat ); + sat_solver_setnvars( p->pSat, Vec_IntSize(p->vVar2Inf)/2 ); + + // add clauses + nVars = Vec_IntSize( p->vVar2Inf ); + Vec_IntForEachEntryDouble( p->vVar2Inf, ObjId, f, i ) + { + if ( ObjId == -1 ) + continue; + pObj = Aig_ManObj( p->pAig, ObjId ); + if ( Aig_ObjIsNode(pObj) ) + { + RetValue &= Aig_Gla2AddNode( p->pSat, Aig_Gla2FetchVar(p, pObj, f), + Aig_Gla2FetchVar(p, Aig_ObjFanin0(pObj), f), + Aig_Gla2FetchVar(p, Aig_ObjFanin1(pObj), f), + Aig_ObjFaninC0(pObj), Aig_ObjFaninC1(pObj) ); + Vec_IntPush( p->vCla2Obj, ObjId ); + Vec_IntPush( p->vCla2Obj, ObjId ); + Vec_IntPush( p->vCla2Obj, ObjId ); + + Vec_IntPush( p->vCla2Fra, f ); + Vec_IntPush( p->vCla2Fra, f ); + Vec_IntPush( p->vCla2Fra, f ); + } + else if ( Saig_ObjIsLo(p->pAig, pObj) ) + { + if ( f == 0 ) + { + RetValue &= Aig_Gla2AddConst( p->pSat, Aig_Gla2FetchVar(p, pObj, f), 1 ); + Vec_IntPush( p->vCla2Obj, ObjId ); + + Vec_IntPush( p->vCla2Fra, f ); + } + else + { + Aig_Obj_t * pObjLi = Saig_ObjLoToLi(p->pAig, pObj); + RetValue &= Aig_Gla2AddBuffer( p->pSat, Aig_Gla2FetchVar(p, pObj, f), + Aig_Gla2FetchVar(p, Aig_ObjFanin0(pObjLi), f-1), + Aig_ObjFaninC0(pObjLi) ); + Vec_IntPush( p->vCla2Obj, ObjId ); + Vec_IntPush( p->vCla2Obj, ObjId ); + + Vec_IntPush( p->vCla2Fra, f ); + Vec_IntPush( p->vCla2Fra, f ); + } + } + else if ( Saig_ObjIsPo(p->pAig, pObj) ) + { + RetValue &= Aig_Gla2AddBuffer( p->pSat, Aig_Gla2FetchVar(p, pObj, f), + Aig_Gla2FetchVar(p, Aig_ObjFanin0(pObj), f), + Aig_ObjFaninC0(pObj) ); + Vec_IntPush( p->vCla2Obj, ObjId ); + Vec_IntPush( p->vCla2Obj, ObjId ); + + Vec_IntPush( p->vCla2Fra, f ); + Vec_IntPush( p->vCla2Fra, f ); + } + else if ( Aig_ObjIsConst1(pObj) ) + { + RetValue &= Aig_Gla2AddConst( p->pSat, Aig_Gla2FetchVar(p, pObj, f), 0 ); + Vec_IntPush( p->vCla2Obj, ObjId ); + + Vec_IntPush( p->vCla2Fra, f ); + } + else assert( Saig_ObjIsPi(p->pAig, pObj) ); + } + + // add output clause + vPoLits = Vec_IntAlloc( p->nFramesMax ); + for ( f = p->nStart; f < p->nFramesMax; f++ ) + Vec_IntPush( vPoLits, 2 * Aig_Gla2FetchVar(p, Aig_ManCo(p->pAig, 0), f) ); + RetValue &= sat_solver_addclause( p->pSat, Vec_IntArray(vPoLits), Vec_IntArray(vPoLits) + Vec_IntSize(vPoLits) ); + Vec_IntFree( vPoLits ); + Vec_IntPush( p->vCla2Obj, 0 ); + Vec_IntPush( p->vCla2Fra, 0 ); + assert( Vec_IntSize(p->vCla2Fra) == Vec_IntSize(p->vCla2Obj) ); + + assert( nVars == Vec_IntSize(p->vVar2Inf) ); + assert( ((Sto_Man_t *)p->pSat->pStore)->nClauses == Vec_IntSize(p->vCla2Obj) ); +// Sto_ManDumpClauses( ((Sto_Man_t *)p->pSat->pStore), "temp_sto.cnf" ); + sat_solver_store_mark_roots( p->pSat ); + + if ( p->fVerbose ) + printf( "The resulting SAT problem contains %d variables and %d clauses.\n", + p->pSat->size, p->pSat->stats.clauses ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Gla2Man_t * Aig_Gla2ManStart( Aig_Man_t * pAig, int nStart, int nFramesMax, int fVerbose ) +{ + Aig_Gla2Man_t * p; + int i; + + p = ABC_CALLOC( Aig_Gla2Man_t, 1 ); + p->pAig = pAig; + + p->vObj2Vec = Vec_IntStart( Aig_ManObjNumMax(pAig) ); + p->vVec2Var = Vec_IntAlloc( 1 << 20 ); + p->vVar2Inf = Vec_IntAlloc( 1 << 20 ); + p->vCla2Obj = Vec_IntAlloc( 1 << 20 ); + p->vCla2Fra = Vec_IntAlloc( 1 << 20 ); + + // skip first vector ID + p->nStart = nStart; + p->nFramesMax = nFramesMax; + p->fVerbose = fVerbose; + for ( i = 0; i < p->nFramesMax; i++ ) + Vec_IntPush( p->vVec2Var, -1 ); + + // skip first SAT variable + Vec_IntPush( p->vVar2Inf, -1 ); + Vec_IntPush( p->vVar2Inf, -1 ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_Gla2ManStop( Aig_Gla2Man_t * p ) +{ + Vec_IntFreeP( &p->vObj2Vec ); + Vec_IntFreeP( &p->vVec2Var ); + Vec_IntFreeP( &p->vVar2Inf ); + Vec_IntFreeP( &p->vCla2Obj ); + Vec_IntFreeP( &p->vCla2Fra ); + Vec_IntFreeP( &p->vVec2Use ); + + if ( p->pSat ) + sat_solver_delete( p->pSat ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [Finds the set of clauses involved in the UNSAT core.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_AbsSolverUnsatCore( sat_solver * pSat, int nConfMax, int fVerbose, int * piRetValue ) +{ + Vec_Int_t * vCore; + void * pSatCnf; + Intp_Man_t * pManProof; + int RetValue; + clock_t clk = clock(); + if ( piRetValue ) + *piRetValue = -1; + // solve the problem + RetValue = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfMax, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + if ( RetValue == l_Undef ) + { + printf( "Conflict limit is reached.\n" ); + return NULL; + } + if ( RetValue == l_True ) + { + printf( "The BMC problem is SAT.\n" ); + if ( piRetValue ) + *piRetValue = 0; + return NULL; + } + if ( fVerbose ) + { + printf( "SAT solver returned UNSAT after %7d conflicts. ", (int)pSat->stats.conflicts ); + Abc_PrintTime( 1, "Time", clock() - clk ); + } + assert( RetValue == l_False ); + pSatCnf = sat_solver_store_release( pSat ); + // derive the UNSAT core + clk = clock(); + pManProof = Intp_ManAlloc(); + vCore = (Vec_Int_t *)Intp_ManUnsatCore( pManProof, (Sto_Man_t *)pSatCnf, 0, 0 ); + Intp_ManFree( pManProof ); + if ( fVerbose ) + { + printf( "SAT core contains %8d clauses (out of %8d). ", Vec_IntSize(vCore), sat_solver_nclauses(pSat) ); + Abc_PrintTime( 1, "Time", clock() - clk ); + } + Sto_ManFree( (Sto_Man_t *)pSatCnf ); + return vCore; +} + +/**Function************************************************************* + + Synopsis [Collects abstracted objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Aig_Gla2ManCollect( Aig_Gla2Man_t * p, Vec_Int_t * vCore ) +{ + Vec_Int_t * vResult; + Aig_Obj_t * pObj; + int i, ClaId, iVecId; +// p->vVec2Use = Vec_IntStart( Vec_IntSize(p->vVec2Var) ); + + vResult = Vec_IntStart( Aig_ManObjNumMax(p->pAig) ); + Vec_IntWriteEntry( vResult, 0, 1 ); // add const1 + Vec_IntForEachEntry( vCore, ClaId, i ) + { + pObj = Aig_ManObj( p->pAig, Vec_IntEntry(p->vCla2Obj, ClaId) ); + if ( Saig_ObjIsPi(p->pAig, pObj) || Saig_ObjIsPo(p->pAig, pObj) || Aig_ObjIsConst1(pObj) ) + continue; + assert( Saig_ObjIsLo(p->pAig, pObj) || Aig_ObjIsNode(pObj) ); + Vec_IntWriteEntry( vResult, Aig_ObjId(pObj), 1 ); +/* + // add flop inputs with multiple fanouts + if ( Saig_ObjIsLo(p->pAig, pObj) ) + { + Aig_Obj_t * pObjLi = Saig_ObjLoToLi(p->pAig, pObj); + if ( !Saig_ObjIsPi(p->pAig, Aig_ObjFanin0(pObjLi)) ) +// if ( Aig_ObjRefs( Aig_ObjFanin0(pObjLi) ) > 1 ) + Vec_IntWriteEntry( vResult, Aig_ObjFaninId0(pObjLi), 1 ); + } + else + { + if ( !Saig_ObjIsPi(p->pAig, Aig_ObjFanin0(pObj)) ) + Vec_IntWriteEntry( vResult, Aig_ObjFaninId0(pObj), 1 ); + if ( !Saig_ObjIsPi(p->pAig, Aig_ObjFanin1(pObj)) ) + Vec_IntWriteEntry( vResult, Aig_ObjFaninId1(pObj), 1 ); + } +*/ + if ( p->vVec2Use ) + { + iVecId = Vec_IntEntry( p->vObj2Vec, Aig_ObjId(pObj) ); + Vec_IntWriteEntry( p->vVec2Use, iVecId * p->nFramesMax + Vec_IntEntry(p->vCla2Fra, ClaId), 1 ); + } + } +// printf( "Number of entries %d\n", Vec_IntCountPositive(vResult) ); + + // count the number of objects in each frame + if ( p->vVec2Use ) + { + Vec_Int_t * vCounts = Vec_IntStart( p->nFramesMax ); + int v, f, Entry, nVecIds = Vec_IntSize(p->vVec2Use) / p->nFramesMax; + for ( f = 0; f < p->nFramesMax; f++ ) + for ( v = 0; v < nVecIds; v++ ) + if ( Vec_IntEntry( p->vVec2Use, v * p->nFramesMax + f ) ) + Vec_IntAddToEntry( vCounts, f, 1 ); + Vec_IntForEachEntry( vCounts, Entry, f ) + printf( "%d ", Entry ); + printf( "\n" ); + Vec_IntFree( vCounts ); + } + return vResult; +} + +/**Function************************************************************* + + Synopsis [Performs gate-level localization abstraction.] + + Description [Returns array of objects included in the abstraction. This array + may contain only const1, flop outputs, and internal nodes, that is, objects + that should have clauses added to the SAT solver.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Aig_Gla2ManPerform( Aig_Man_t * pAig, int nStart, int nFramesMax, int nConfLimit, int TimeLimit, int fSkipRand, int fVerbose ) +{ + Aig_Gla2Man_t * p; + Vec_Int_t * vCore, * vResult; + clock_t nTimeToStop = TimeLimit ? TimeLimit * CLOCKS_PER_SEC + clock(): 0; + clock_t clk, clk2 = clock(); + assert( Saig_ManPoNum(pAig) == 1 ); + + if ( fVerbose ) + { + if ( TimeLimit ) + printf( "Abstracting from frame %d to frame %d with timeout %d sec.\n", nStart, nFramesMax, TimeLimit ); + else + printf( "Abstracting from frame %d to frame %d with no timeout.\n", nStart, nFramesMax ); + } + + // start the solver + clk = clock(); + p = Aig_Gla2ManStart( pAig, nStart, nFramesMax, fVerbose ); + if ( !Aig_Gla2CreateSatSolver( p ) ) + { + printf( "Error! SAT solver became UNSAT.\n" ); + Aig_Gla2ManStop( p ); + return NULL; + } + sat_solver_set_random( p->pSat, fSkipRand ); + p->timePre += clock() - clk; + + // set runtime limit + if ( TimeLimit ) + sat_solver_set_runtime_limit( p->pSat, nTimeToStop ); + + // compute UNSAT core + clk = clock(); + vCore = Saig_AbsSolverUnsatCore( p->pSat, nConfLimit, fVerbose, NULL ); + if ( vCore == NULL ) + { + Aig_Gla2ManStop( p ); + return NULL; + } + p->timeSat += clock() - clk; + p->timeTotal += clock() - clk2; + + // print stats + if ( fVerbose ) + { + ABC_PRTP( "Pre ", p->timePre, p->timeTotal ); + ABC_PRTP( "Sat ", p->timeSat, p->timeTotal ); + ABC_PRTP( "Total ", p->timeTotal, p->timeTotal ); + } + + // prepare return value + vResult = Aig_Gla2ManCollect( p, vCore ); + Vec_IntFree( vCore ); + Aig_Gla2ManStop( p ); + return vResult; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigGlaPba2.c b/yosys/abc/src/aig/saig/saigGlaPba2.c new file mode 100644 index 00000000000..cff7b7fc310 --- /dev/null +++ b/yosys/abc/src/aig/saig/saigGlaPba2.c @@ -0,0 +1,558 @@ +/**CFile**************************************************************** + + FileName [saigGlaPba.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Gate level abstraction.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigGlaPba.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" +#include "sat/bsat/satSolver2.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Aig_Gla3Man_t_ Aig_Gla3Man_t; +struct Aig_Gla3Man_t_ +{ + // user data + Aig_Man_t * pAig; + int nStart; + int nFramesMax; + int fVerbose; + // unrolling + Vec_Int_t * vObj2Vec; // maps obj ID into its vec ID + Vec_Int_t * vVec2Var; // maps vec ID into its sat Var (nFrames per vec ID) + Vec_Int_t * vVar2Inf; // maps sat Var into its frame and obj ID + // clause mapping + Vec_Int_t * vCla2Obj; // maps clause into its root object + Vec_Int_t * vCla2Fra; // maps clause into its frame + Vec_Int_t * vVec2Use; // maps vec ID into its used frames (nFrames per vec ID) + // SAT solver + sat_solver2 * pSat; + // statistics + clock_t timePre; + clock_t timeSat; + clock_t timeTotal; +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#define ABC_CPS 1000 + +/**Function************************************************************* + + Synopsis [Adds constant to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_Gla3AddConst( sat_solver2 * pSat, int iVar, int fCompl ) +{ + lit Lit = toLitCond( iVar, fCompl ); + if ( !sat_solver2_addclause( pSat, &Lit, &Lit + 1, 0 ) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Adds buffer to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_Gla3AddBuffer( sat_solver2 * pSat, int iVar0, int iVar1, int fCompl ) +{ + lit Lits[2]; + + Lits[0] = toLitCond( iVar0, 0 ); + Lits[1] = toLitCond( iVar1, !fCompl ); + if ( !sat_solver2_addclause( pSat, Lits, Lits + 2, 0 ) ) + return 0; + + Lits[0] = toLitCond( iVar0, 1 ); + Lits[1] = toLitCond( iVar1, fCompl ); + if ( !sat_solver2_addclause( pSat, Lits, Lits + 2, 0 ) ) + return 0; + + return 1; +} + +/**Function************************************************************* + + Synopsis [Adds buffer to the solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Aig_Gla3AddNode( sat_solver2 * pSat, int iVar, int iVar0, int iVar1, int fCompl0, int fCompl1 ) +{ + lit Lits[3]; + + Lits[0] = toLitCond( iVar, 1 ); + Lits[1] = toLitCond( iVar0, fCompl0 ); + if ( !sat_solver2_addclause( pSat, Lits, Lits + 2, 0 ) ) + return 0; + + Lits[0] = toLitCond( iVar, 1 ); + Lits[1] = toLitCond( iVar1, fCompl1 ); + if ( !sat_solver2_addclause( pSat, Lits, Lits + 2, 0 ) ) + return 0; + + Lits[0] = toLitCond( iVar, 0 ); + Lits[1] = toLitCond( iVar0, !fCompl0 ); + Lits[2] = toLitCond( iVar1, !fCompl1 ); + if ( !sat_solver2_addclause( pSat, Lits, Lits + 3, 0 ) ) + return 0; + + return 1; +} + + +/**Function************************************************************* + + Synopsis [Finds existing SAT variable or creates a new one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_Gla3FetchVar( Aig_Gla3Man_t * p, Aig_Obj_t * pObj, int k ) +{ + int i, iVecId, iSatVar; + assert( k < p->nFramesMax ); + iVecId = Vec_IntEntry( p->vObj2Vec, Aig_ObjId(pObj) ); + if ( iVecId == 0 ) + { + iVecId = Vec_IntSize( p->vVec2Var ) / p->nFramesMax; + for ( i = 0; i < p->nFramesMax; i++ ) + Vec_IntPush( p->vVec2Var, 0 ); + Vec_IntWriteEntry( p->vObj2Vec, Aig_ObjId(pObj), iVecId ); + } + iSatVar = Vec_IntEntry( p->vVec2Var, iVecId * p->nFramesMax + k ); + if ( iSatVar == 0 ) + { + iSatVar = Vec_IntSize( p->vVar2Inf ) / 2; + Vec_IntPush( p->vVar2Inf, Aig_ObjId(pObj) ); + Vec_IntPush( p->vVar2Inf, k ); + Vec_IntWriteEntry( p->vVec2Var, iVecId * p->nFramesMax + k, iSatVar ); + } + return iSatVar; +} + +/**Function************************************************************* + + Synopsis [Assigns variables to the AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_Gla3AssignVars_rec( Aig_Gla3Man_t * p, Aig_Obj_t * pObj, int f ) +{ + int nVars = Vec_IntSize(p->vVar2Inf); + Aig_Gla3FetchVar( p, pObj, f ); + if ( nVars == Vec_IntSize(p->vVar2Inf) ) + return; + if ( Aig_ObjIsConst1(pObj) ) + return; + if ( Saig_ObjIsPo( p->pAig, pObj ) ) + { + Aig_Gla3AssignVars_rec( p, Aig_ObjFanin0(pObj), f ); + return; + } + if ( Aig_ObjIsCi( pObj ) ) + { + if ( Saig_ObjIsLo(p->pAig, pObj) && f > 0 ) + Aig_Gla3AssignVars_rec( p, Aig_ObjFanin0( Saig_ObjLoToLi(p->pAig, pObj) ), f-1 ); + return; + } + assert( Aig_ObjIsNode(pObj) ); + Aig_Gla3AssignVars_rec( p, Aig_ObjFanin0(pObj), f ); + Aig_Gla3AssignVars_rec( p, Aig_ObjFanin1(pObj), f ); +} + +/**Function************************************************************* + + Synopsis [Creates SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_Gla3CreateSatSolver( Aig_Gla3Man_t * p ) +{ + Vec_Int_t * vPoLits; + Aig_Obj_t * pObj; + int i, f, ObjId, nVars, RetValue = 1; + + // assign variables + for ( f = p->nFramesMax - 1; f >= 0; f-- ) + Aig_Gla3AssignVars_rec( p, Aig_ManCo(p->pAig, 0), f ); + + // create SAT solver + p->pSat = sat_solver2_new(); + sat_solver2_setnvars( p->pSat, Vec_IntSize(p->vVar2Inf)/2 ); + + // add clauses + nVars = Vec_IntSize( p->vVar2Inf ); + Vec_IntForEachEntryDouble( p->vVar2Inf, ObjId, f, i ) + { + if ( ObjId == -1 ) + continue; + pObj = Aig_ManObj( p->pAig, ObjId ); + if ( Aig_ObjIsNode(pObj) ) + { + Aig_Gla3AddNode( p->pSat, Aig_Gla3FetchVar(p, pObj, f), + Aig_Gla3FetchVar(p, Aig_ObjFanin0(pObj), f), + Aig_Gla3FetchVar(p, Aig_ObjFanin1(pObj), f), + Aig_ObjFaninC0(pObj), Aig_ObjFaninC1(pObj) ); + Vec_IntPush( p->vCla2Obj, ObjId ); + Vec_IntPush( p->vCla2Obj, ObjId ); + Vec_IntPush( p->vCla2Obj, ObjId ); + + Vec_IntPush( p->vCla2Fra, f ); + Vec_IntPush( p->vCla2Fra, f ); + Vec_IntPush( p->vCla2Fra, f ); + } + else if ( Saig_ObjIsLo(p->pAig, pObj) ) + { + if ( f == 0 ) + { + Aig_Gla3AddConst( p->pSat, Aig_Gla3FetchVar(p, pObj, f), 1 ); + Vec_IntPush( p->vCla2Obj, ObjId ); + + Vec_IntPush( p->vCla2Fra, f ); + } + else + { + Aig_Obj_t * pObjLi = Saig_ObjLoToLi(p->pAig, pObj); + Aig_Gla3AddBuffer( p->pSat, Aig_Gla3FetchVar(p, pObj, f), + Aig_Gla3FetchVar(p, Aig_ObjFanin0(pObjLi), f-1), + Aig_ObjFaninC0(pObjLi) ); + Vec_IntPush( p->vCla2Obj, ObjId ); + Vec_IntPush( p->vCla2Obj, ObjId ); + + Vec_IntPush( p->vCla2Fra, f ); + Vec_IntPush( p->vCla2Fra, f ); + } + } + else if ( Saig_ObjIsPo(p->pAig, pObj) ) + { + Aig_Gla3AddBuffer( p->pSat, Aig_Gla3FetchVar(p, pObj, f), + Aig_Gla3FetchVar(p, Aig_ObjFanin0(pObj), f), + Aig_ObjFaninC0(pObj) ); + Vec_IntPush( p->vCla2Obj, ObjId ); + Vec_IntPush( p->vCla2Obj, ObjId ); + + Vec_IntPush( p->vCla2Fra, f ); + Vec_IntPush( p->vCla2Fra, f ); + } + else if ( Aig_ObjIsConst1(pObj) ) + { + Aig_Gla3AddConst( p->pSat, Aig_Gla3FetchVar(p, pObj, f), 0 ); + Vec_IntPush( p->vCla2Obj, ObjId ); + + Vec_IntPush( p->vCla2Fra, f ); + } + else assert( Saig_ObjIsPi(p->pAig, pObj) ); + } + + // add output clause + vPoLits = Vec_IntAlloc( p->nFramesMax ); + for ( f = p->nStart; f < p->nFramesMax; f++ ) + Vec_IntPush( vPoLits, 2 * Aig_Gla3FetchVar(p, Aig_ManCo(p->pAig, 0), f) ); + sat_solver2_addclause( p->pSat, Vec_IntArray(vPoLits), Vec_IntArray(vPoLits) + Vec_IntSize(vPoLits), 0 ); + Vec_IntFree( vPoLits ); + Vec_IntPush( p->vCla2Obj, 0 ); + Vec_IntPush( p->vCla2Fra, 0 ); + assert( Vec_IntSize(p->vCla2Fra) == Vec_IntSize(p->vCla2Obj) ); + assert( nVars == Vec_IntSize(p->vVar2Inf) ); + assert( Vec_IntSize(p->vCla2Obj) == (int)p->pSat->stats.clauses+1 ); + if ( p->fVerbose ) + printf( "The resulting SAT problem contains %d variables and %d clauses.\n", + p->pSat->size, p->pSat->stats.clauses ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Gla3Man_t * Aig_Gla3ManStart( Aig_Man_t * pAig, int nStart, int nFramesMax, int fVerbose ) +{ + Aig_Gla3Man_t * p; + int i; + + p = ABC_CALLOC( Aig_Gla3Man_t, 1 ); + p->pAig = pAig; + + p->vObj2Vec = Vec_IntStart( Aig_ManObjNumMax(pAig) ); + p->vVec2Var = Vec_IntAlloc( 1 << 20 ); + p->vVar2Inf = Vec_IntAlloc( 1 << 20 ); + p->vCla2Obj = Vec_IntAlloc( 1 << 20 ); Vec_IntPush( p->vCla2Obj, -1 ); + p->vCla2Fra = Vec_IntAlloc( 1 << 20 ); Vec_IntPush( p->vCla2Fra, -1 ); + + // skip first vector ID + p->nStart = nStart; + p->nFramesMax = nFramesMax; + p->fVerbose = fVerbose; + for ( i = 0; i < p->nFramesMax; i++ ) + Vec_IntPush( p->vVec2Var, -1 ); + + // skip first SAT variable + Vec_IntPush( p->vVar2Inf, -1 ); + Vec_IntPush( p->vVar2Inf, -1 ); + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_Gla3ManStop( Aig_Gla3Man_t * p ) +{ + Vec_IntFreeP( &p->vObj2Vec ); + Vec_IntFreeP( &p->vVec2Var ); + Vec_IntFreeP( &p->vVar2Inf ); + Vec_IntFreeP( &p->vCla2Obj ); + Vec_IntFreeP( &p->vCla2Fra ); + Vec_IntFreeP( &p->vVec2Use ); + + if ( p->pSat ) + sat_solver2_delete( p->pSat ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [Finds the set of clauses involved in the UNSAT core.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Aig_Gla3ManUnsatCore( sat_solver2 * pSat, int nConfMax, int fVerbose, int * piRetValue ) +{ + Vec_Int_t * vCore; + int RetValue; + clock_t clk = clock(); + if ( piRetValue ) + *piRetValue = -1; + // solve the problem + RetValue = sat_solver2_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfMax, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + if ( RetValue == l_Undef ) + { + printf( "Conflict limit is reached.\n" ); + return NULL; + } + if ( RetValue == l_True ) + { + printf( "The BMC problem is SAT.\n" ); + if ( piRetValue ) + *piRetValue = 0; + return NULL; + } + if ( fVerbose ) + { + printf( "SAT solver returned UNSAT after %7d conflicts. ", (int)pSat->stats.conflicts ); + Abc_PrintTime( 1, "Time", clock() - clk ); + } + assert( RetValue == l_False ); + + // derive the UNSAT core + clk = clock(); + vCore = (Vec_Int_t *)Sat_ProofCore( pSat ); + if ( fVerbose ) + { + printf( "SAT core contains %8d clauses (out of %8d). ", Vec_IntSize(vCore), sat_solver2_nclauses(pSat) ); + Abc_PrintTime( 1, "Time", clock() - clk ); + } + return vCore; +} + +/**Function************************************************************* + + Synopsis [Collects abstracted objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Aig_Gla3ManCollect( Aig_Gla3Man_t * p, Vec_Int_t * vCore ) +{ + Vec_Int_t * vResult; + Aig_Obj_t * pObj; + int i, ClaId, iVecId; +// p->vVec2Use = Vec_IntStart( Vec_IntSize(p->vVec2Var) ); + + vResult = Vec_IntStart( Aig_ManObjNumMax(p->pAig) ); + Vec_IntWriteEntry( vResult, 0, 1 ); // add const1 + Vec_IntForEachEntry( vCore, ClaId, i ) + { + pObj = Aig_ManObj( p->pAig, Vec_IntEntry(p->vCla2Obj, ClaId) ); + if ( Saig_ObjIsPi(p->pAig, pObj) || Saig_ObjIsPo(p->pAig, pObj) || Aig_ObjIsConst1(pObj) ) + continue; + assert( Saig_ObjIsLo(p->pAig, pObj) || Aig_ObjIsNode(pObj) ); + Vec_IntWriteEntry( vResult, Aig_ObjId(pObj), 1 ); + if ( p->vVec2Use ) + { + iVecId = Vec_IntEntry( p->vObj2Vec, Aig_ObjId(pObj) ); + Vec_IntWriteEntry( p->vVec2Use, iVecId * p->nFramesMax + Vec_IntEntry(p->vCla2Fra, ClaId), 1 ); + } + } + // count the number of objects in each frame + if ( p->vVec2Use ) + { + Vec_Int_t * vCounts = Vec_IntStart( p->nFramesMax ); + int v, f, Entry, nVecIds = Vec_IntSize(p->vVec2Use) / p->nFramesMax; + for ( f = 0; f < p->nFramesMax; f++ ) + for ( v = 0; v < nVecIds; v++ ) + if ( Vec_IntEntry( p->vVec2Use, v * p->nFramesMax + f ) ) + Vec_IntAddToEntry( vCounts, f, 1 ); + Vec_IntForEachEntry( vCounts, Entry, f ) + printf( "%d ", Entry ); + printf( "\n" ); + Vec_IntFree( vCounts ); + } + return vResult; +} + +/**Function************************************************************* + + Synopsis [Performs gate-level localization abstraction.] + + Description [Returns array of objects included in the abstraction. This array + may contain only const1, flop outputs, and internal nodes, that is, objects + that should have clauses added to the SAT solver.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Aig_Gla3ManPerform( Aig_Man_t * pAig, int nStart, int nFramesMax, int nConfLimit, int TimeLimit, int fSkipRand, int fVerbose ) +{ + Aig_Gla3Man_t * p; + Vec_Int_t * vCore, * vResult; + clock_t clk, clk2 = clock(); + assert( Saig_ManPoNum(pAig) == 1 ); + + if ( fVerbose ) + { + if ( TimeLimit ) + printf( "Abstracting from frame %d to frame %d with timeout %d sec.\n", nStart, nFramesMax, TimeLimit ); + else + printf( "Abstracting from frame %d to frame %d with no timeout.\n", nStart, nFramesMax ); + } + + // start the solver + clk = clock(); + p = Aig_Gla3ManStart( pAig, nStart, nFramesMax, fVerbose ); + if ( !Aig_Gla3CreateSatSolver( p ) ) + { + printf( "Error! SAT solver became UNSAT.\n" ); + Aig_Gla3ManStop( p ); + return NULL; + } + p->pSat->fNotUseRandom = fSkipRand; + p->timePre += clock() - clk; + + // set runtime limit + if ( TimeLimit ) + sat_solver2_set_runtime_limit( p->pSat, TimeLimit * CLOCKS_PER_SEC + clock() ); + + // compute UNSAT core + clk = clock(); + vCore = Aig_Gla3ManUnsatCore( p->pSat, nConfLimit, fVerbose, NULL ); + if ( vCore == NULL ) + { + Aig_Gla3ManStop( p ); + return NULL; + } + p->timeSat += clock() - clk; + p->timeTotal += clock() - clk2; + + // print stats + if ( fVerbose ) + { + ABC_PRTP( "Pre ", p->timePre, p->timeTotal ); + ABC_PRTP( "Sat ", p->timeSat, p->timeTotal ); + ABC_PRTP( "Total ", p->timeTotal, p->timeTotal ); + } + + // prepare return value + vResult = Aig_Gla3ManCollect( p, vCore ); + Vec_IntFree( vCore ); + Aig_Gla3ManStop( p ); + return vResult; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigInd.c b/yosys/abc/src/aig/saig/saigInd.c new file mode 100644 index 00000000000..d3665c85615 --- /dev/null +++ b/yosys/abc/src/aig/saig/saigInd.c @@ -0,0 +1,409 @@ +/**CFile**************************************************************** + + FileName [saigLoc.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [K-step induction for one property only.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigLoc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" +#include "sat/cnf/cnf.h" +#include "sat/bsat/satSolver.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns 1 if two state are equal.] + + Description [Array vState contains indexes of CNF variables for each + flop in the first N time frames (0 < i < k, i < N, k < N).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManStatesAreEqual( sat_solver * pSat, Vec_Int_t * vState, int nRegs, int i, int k ) +{ + int * pStateI = (int *)Vec_IntArray(vState) + nRegs * i; + int * pStateK = (int *)Vec_IntArray(vState) + nRegs * k; + int v; + assert( i && k && i < k ); + assert( nRegs * k <= Vec_IntSize(vState) ); + // check if the states are available + for ( v = 0; v < nRegs; v++ ) + if ( pStateI[v] >= 0 && pStateK[v] == -1 ) + return 0; +/* + printf( "\nchecking uniqueness\n" ); + printf( "%3d : ", i ); + for ( v = 0; v < nRegs; v++ ) + printf( "%d", sat_solver_var_value(pSat, pStateI[v]) ); + printf( "\n" ); + + printf( "%3d : ", k ); + for ( v = 0; v < nRegs; v++ ) + printf( "%d", sat_solver_var_value(pSat, pStateK[v]) ); + printf( "\n" ); +*/ + for ( v = 0; v < nRegs; v++ ) + if ( pStateI[v] >= 0 ) + { + if ( sat_solver_var_value(pSat, pStateI[v]) != sat_solver_var_value(pSat, pStateK[v]) ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Add uniqueness constraint.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManAddUniqueness( sat_solver * pSat, Vec_Int_t * vState, int nRegs, int i, int k, int * pnSatVarNum, int * pnClauses, int fVerbose ) +{ + int * pStateI = (int *)Vec_IntArray(vState) + nRegs * i; + int * pStateK = (int *)Vec_IntArray(vState) + nRegs * k; + int v, iVars, nSatVarsOld, RetValue, * pClause; + assert( i && k && i < k ); + assert( nRegs * k <= Vec_IntSize(vState) ); + // check if the states are available + for ( v = 0; v < nRegs; v++ ) + if ( pStateI[v] >= 0 && pStateK[v] == -1 ) + { + if ( fVerbose ) + printf( "Cannot constrain an incomplete state.\n" ); + return 0; + } + // add XORs + nSatVarsOld = *pnSatVarNum; + for ( v = 0; v < nRegs; v++ ) + if ( pStateI[v] >= 0 ) + { + *pnClauses += 4; + RetValue = Cnf_DataAddXorClause( pSat, pStateI[v], pStateK[v], (*pnSatVarNum)++ ); + if ( RetValue == 0 ) + { + if ( fVerbose ) + printf( "SAT solver became UNSAT after adding a uniqueness constraint.\n" ); + return 1; + } + } + // add OR clause + (*pnClauses)++; + iVars = 0; + pClause = ABC_ALLOC( int, nRegs ); + for ( v = nSatVarsOld; v < *pnSatVarNum; v++ ) + pClause[iVars++] = toLitCond( v, 0 ); + assert( iVars <= nRegs ); + RetValue = sat_solver_addclause( pSat, pClause, pClause + iVars ); + ABC_FREE( pClause ); + if ( RetValue == 0 ) + { + if ( fVerbose ) + printf( "SAT solver became UNSAT after adding a uniqueness constraint.\n" ); + return 1; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Performs induction by unrolling timeframes backward.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManInduction( Aig_Man_t * p, int nTimeOut, int nFramesMax, int nConfMax, int fUnique, int fUniqueAll, int fGetCex, int fVerbose, int fVeryVerbose ) +{ + sat_solver * pSat; + Aig_Man_t * pAigPart = NULL; + Cnf_Dat_t * pCnfPart = NULL; + Vec_Int_t * vTopVarNums, * vState, * vTopVarIds = NULL; + Vec_Ptr_t * vTop, * vBot; + Aig_Obj_t * pObjPi, * pObjPiCopy, * pObjPo; + int i, k, f, Lits[2], status = -1, RetValue, nSatVarNum, nConfPrev; + int nOldSize, iReg, iLast, fAdded, nConstrs = 0, nClauses = 0; + abctime clk, nTimeToStop = nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock() : 0; + assert( fUnique == 0 || fUniqueAll == 0 ); + assert( Saig_ManPoNum(p) == 1 ); + Aig_ManSetCioIds( p ); + + // start the top by including the PO + vBot = Vec_PtrAlloc( 100 ); + vTop = Vec_PtrAlloc( 100 ); + vState = Vec_IntAlloc( 1000 ); + Vec_PtrPush( vTop, Aig_ManCo(p, 0) ); + // start the array of CNF variables + vTopVarNums = Vec_IntAlloc( 100 ); + // start the solver + pSat = sat_solver_new(); + sat_solver_setnvars( pSat, 1000 ); + + // set runtime limit + if ( nTimeToStop ) + sat_solver_set_runtime_limit( pSat, nTimeToStop ); + + // iterate backward unrolling + RetValue = -1; + nSatVarNum = 0; + if ( fVerbose ) + printf( "Induction parameters: FramesMax = %5d. ConflictMax = %6d.\n", nFramesMax, nConfMax ); + for ( f = 0; ; f++ ) + { + if ( f > 0 ) + { + Aig_ManStop( pAigPart ); + Cnf_DataFree( pCnfPart ); + } + clk = Abc_Clock(); + // get the bottom + Aig_SupportNodes( p, (Aig_Obj_t **)Vec_PtrArray(vTop), Vec_PtrSize(vTop), vBot ); + // derive AIG for the part between top and bottom + pAigPart = Aig_ManDupSimpleDfsPart( p, vBot, vTop ); + // convert it into CNF + pCnfPart = Cnf_Derive( pAigPart, Aig_ManCoNum(pAigPart) ); + Cnf_DataLift( pCnfPart, nSatVarNum ); + nSatVarNum += pCnfPart->nVars; + nClauses += pCnfPart->nClauses; + + // remember top frame var IDs + if ( fGetCex && vTopVarIds == NULL ) + { + vTopVarIds = Vec_IntStartFull( Aig_ManCiNum(p) ); + Aig_ManForEachCi( p, pObjPi, i ) + { + if ( pObjPi->pData == NULL ) + continue; + pObjPiCopy = (Aig_Obj_t *)pObjPi->pData; + assert( Aig_ObjIsCi(pObjPiCopy) ); + if ( Saig_ObjIsPi(p, pObjPi) ) + Vec_IntWriteEntry( vTopVarIds, Aig_ObjCioId(pObjPi) + Saig_ManRegNum(p), pCnfPart->pVarNums[Aig_ObjId(pObjPiCopy)] ); + else if ( Saig_ObjIsLo(p, pObjPi) ) + Vec_IntWriteEntry( vTopVarIds, Aig_ObjCioId(pObjPi) - Saig_ManPiNum(p), pCnfPart->pVarNums[Aig_ObjId(pObjPiCopy)] ); + else assert( 0 ); + } + } + + // stitch variables of top and bot + assert( Aig_ManCoNum(pAigPart)-1 == Vec_IntSize(vTopVarNums) ); + Aig_ManForEachCo( pAigPart, pObjPo, i ) + { + if ( i == 0 ) + { + // do not perform inductive strengthening +// if ( f > 0 ) +// continue; + // add topmost literal + Lits[0] = toLitCond( pCnfPart->pVarNums[pObjPo->Id], f>0 ); + if ( !sat_solver_addclause( pSat, Lits, Lits+1 ) ) + assert( 0 ); + nClauses++; + continue; + } + Lits[0] = toLitCond( Vec_IntEntry(vTopVarNums, i-1), 0 ); + Lits[1] = toLitCond( pCnfPart->pVarNums[pObjPo->Id], 1 ); + if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) + assert( 0 ); + Lits[0] = toLitCond( Vec_IntEntry(vTopVarNums, i-1), 1 ); + Lits[1] = toLitCond( pCnfPart->pVarNums[pObjPo->Id], 0 ); + if ( !sat_solver_addclause( pSat, Lits, Lits+2 ) ) + assert( 0 ); + nClauses += 2; + } + // add CNF to the SAT solver + for ( i = 0; i < pCnfPart->nClauses; i++ ) + if ( !sat_solver_addclause( pSat, pCnfPart->pClauses[i], pCnfPart->pClauses[i+1] ) ) + break; + if ( i < pCnfPart->nClauses ) + { +// printf( "SAT solver became UNSAT after adding clauses.\n" ); + RetValue = 1; + break; + } + + // create new set of POs to derive new top + Vec_PtrClear( vTop ); + Vec_PtrPush( vTop, Aig_ManCo(p, 0) ); + Vec_IntClear( vTopVarNums ); + nOldSize = Vec_IntSize(vState); + Vec_IntFillExtra( vState, nOldSize + Aig_ManRegNum(p), -1 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vBot, pObjPi, i ) + { + assert( Aig_ObjIsCi(pObjPi) ); + if ( Saig_ObjIsLo(p, pObjPi) ) + { + pObjPiCopy = (Aig_Obj_t *)pObjPi->pData; + assert( pObjPiCopy != NULL ); + Vec_PtrPush( vTop, Saig_ObjLoToLi(p, pObjPi) ); + Vec_IntPush( vTopVarNums, pCnfPart->pVarNums[pObjPiCopy->Id] ); + + iReg = pObjPi->CioId - Saig_ManPiNum(p); + assert( iReg >= 0 && iReg < Aig_ManRegNum(p) ); + Vec_IntWriteEntry( vState, nOldSize+iReg, pCnfPart->pVarNums[pObjPiCopy->Id] ); + } + } + assert( Vec_IntSize(vState)%Aig_ManRegNum(p) == 0 ); + iLast = Vec_IntSize(vState)/Aig_ManRegNum(p); + if ( fUniqueAll ) + { + for ( i = 1; i < iLast-1; i++ ) + { + nConstrs++; + if ( fVeryVerbose ) + printf( "Adding constaint for state %2d and state %2d.\n", i, iLast-1 ); + if ( Saig_ManAddUniqueness( pSat, vState, Aig_ManRegNum(p), i, iLast-1, &nSatVarNum, &nClauses, fVerbose ) ) + break; + } + if ( i < iLast-1 ) + { + RetValue = 1; + break; + } + } + +nextrun: + fAdded = 0; + // run the SAT solver + nConfPrev = pSat->stats.conflicts; + status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfMax, 0, 0, 0 ); + if ( fVerbose ) + { + printf( "Frame %4d : PI =%5d. PO =%5d. AIG =%5d. Var =%7d. Clau =%7d. Conf =%7d. ", + f, Aig_ManCiNum(pAigPart), Aig_ManCoNum(pAigPart), Aig_ManNodeNum(pAigPart), + nSatVarNum, nClauses, (int)pSat->stats.conflicts-nConfPrev ); + ABC_PRT( "Time", Abc_Clock() - clk ); + } + if ( status == l_Undef ) + break; + if ( status == l_False ) + { + RetValue = 1; + break; + } + assert( status == l_True ); + // the problem is SAT - add more clauses + if ( fVeryVerbose ) + { + Vec_IntForEachEntry( vState, iReg, i ) + { + if ( i && (i % Aig_ManRegNum(p)) == 0 ) + printf( "\n" ); + if ( (i % Aig_ManRegNum(p)) == 0 ) + printf( " State %3d : ", i/Aig_ManRegNum(p) ); + printf( "%c", (iReg >= 0) ? ('0' + sat_solver_var_value(pSat, iReg)) : 'x' ); + } + printf( "\n" ); + } + if ( nFramesMax && f == nFramesMax - 1 ) + { + // derive counter-example + assert( status == l_True ); + if ( fGetCex ) + { + int VarNum, iBit = 0; + Abc_Cex_t * pCex = Abc_CexAlloc( Aig_ManRegNum(p)-1, Saig_ManPiNum(p), 1 ); + pCex->iFrame = 0; + pCex->iPo = 0; + Vec_IntForEachEntryStart( vTopVarIds, VarNum, i, 1 ) + { + if ( VarNum >= 0 && sat_solver_var_value( pSat, VarNum ) ) + Abc_InfoSetBit( pCex->pData, iBit ); + iBit++; + } + assert( iBit == pCex->nBits ); + Abc_CexFree( p->pSeqModel ); + p->pSeqModel = pCex; + } + break; + } + if ( fUnique ) + { + for ( i = 1; i < iLast; i++ ) + { + for ( k = i+1; k < iLast; k++ ) + { + if ( !Saig_ManStatesAreEqual( pSat, vState, Aig_ManRegNum(p), i, k ) ) + continue; + nConstrs++; + fAdded = 1; + if ( fVeryVerbose ) + printf( "Adding constaint for state %2d and state %2d.\n", i, k ); + if ( Saig_ManAddUniqueness( pSat, vState, Aig_ManRegNum(p), i, k, &nSatVarNum, &nClauses, fVerbose ) ) + break; + } + if ( k < iLast ) + break; + } + if ( i < iLast ) + { + RetValue = 1; + break; + } + } + if ( fAdded ) + goto nextrun; + } + if ( fVerbose ) + { + if ( nTimeToStop && Abc_Clock() >= nTimeToStop ) + printf( "Timeout (%d sec) was reached during iteration %d.\n", nTimeOut, f+1 ); + else if ( status == l_Undef ) + printf( "Conflict limit (%d) was reached during iteration %d.\n", nConfMax, f+1 ); + else if ( fUnique || fUniqueAll ) + printf( "Completed %d iterations and added %d uniqueness constraints.\n", f+1, nConstrs ); + else + printf( "Completed %d iterations.\n", f+1 ); + } + // cleanup + sat_solver_delete( pSat ); + Aig_ManStop( pAigPart ); + Cnf_DataFree( pCnfPart ); + Vec_IntFree( vTopVarNums ); + Vec_PtrFree( vTop ); + Vec_PtrFree( vBot ); + Vec_IntFree( vState ); + Vec_IntFreeP( &vTopVarIds ); + return RetValue; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigIoa.c b/yosys/abc/src/aig/saig/saigIoa.c new file mode 100644 index 00000000000..c235c186e8c --- /dev/null +++ b/yosys/abc/src/aig/saig/saigIoa.c @@ -0,0 +1,405 @@ +/**CFile**************************************************************** + + FileName [saigIoa.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Input/output for sequential AIGs using BLIF files.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigIoa.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include "saig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Saig_ObjName( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + static char Buffer[1000]; + if ( Aig_ObjIsNode(pObj) || Aig_ObjIsConst1(pObj) ) + sprintf( Buffer, "n%0*d", (unsigned char)Abc_Base10Log(Aig_ManObjNumMax(p)), Aig_ObjId(pObj) ); + else if ( Saig_ObjIsPi(p, pObj) ) + sprintf( Buffer, "pi%0*d", (unsigned char)Abc_Base10Log(Saig_ManPiNum(p)), Aig_ObjCioId(pObj) ); + else if ( Saig_ObjIsPo(p, pObj) ) + sprintf( Buffer, "po%0*d", (unsigned char)Abc_Base10Log(Saig_ManPoNum(p)), Aig_ObjCioId(pObj) ); + else if ( Saig_ObjIsLo(p, pObj) ) + sprintf( Buffer, "lo%0*d", (unsigned char)Abc_Base10Log(Saig_ManRegNum(p)), Aig_ObjCioId(pObj) - Saig_ManPiNum(p) ); + else if ( Saig_ObjIsLi(p, pObj) ) + sprintf( Buffer, "li%0*d", (unsigned char)Abc_Base10Log(Saig_ManRegNum(p)), Aig_ObjCioId(pObj) - Saig_ManPoNum(p) ); + else + assert( 0 ); + return Buffer; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManDumpBlif( Aig_Man_t * p, char * pFileName ) +{ + FILE * pFile; + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int i; + if ( Aig_ManCoNum(p) == 0 ) + { + printf( "Aig_ManDumpBlif(): AIG manager does not have POs.\n" ); + return; + } + Aig_ManSetCioIds( p ); + // write input file + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + printf( "Saig_ManDumpBlif(): Cannot open file for writing.\n" ); + return; + } + fprintf( pFile, "# BLIF file written by procedure Saig_ManDumpBlif()\n" ); + fprintf( pFile, "# If unedited, this file can be read by Saig_ManReadBlif()\n" ); + fprintf( pFile, "# AIG stats: pi=%d po=%d reg=%d and=%d obj=%d maxid=%d\n", + Saig_ManPiNum(p), Saig_ManPoNum(p), Saig_ManRegNum(p), + Aig_ManNodeNum(p), Aig_ManObjNum(p), Aig_ManObjNumMax(p) ); + fprintf( pFile, ".model %s\n", p->pName ); + // write primary inputs + fprintf( pFile, ".inputs" ); + Aig_ManForEachPiSeq( p, pObj, i ) + fprintf( pFile, " %s", Saig_ObjName(p, pObj) ); + fprintf( pFile, "\n" ); + // write primary outputs + fprintf( pFile, ".outputs" ); + Aig_ManForEachPoSeq( p, pObj, i ) + fprintf( pFile, " %s", Saig_ObjName(p, pObj) ); + fprintf( pFile, "\n" ); + // write registers + if ( Aig_ManRegNum(p) ) + { + Aig_ManForEachLiLoSeq( p, pObjLi, pObjLo, i ) + { + fprintf( pFile, ".latch" ); + fprintf( pFile, " %s", Saig_ObjName(p, pObjLi) ); + fprintf( pFile, " %s", Saig_ObjName(p, pObjLo) ); + fprintf( pFile, " 0\n" ); + } + } + // check if constant is used + if ( Aig_ObjRefs(Aig_ManConst1(p)) ) + fprintf( pFile, ".names %s\n 1\n", Saig_ObjName(p, Aig_ManConst1(p)) ); + // write the nodes in the DFS order + Aig_ManForEachNode( p, pObj, i ) + { + fprintf( pFile, ".names" ); + fprintf( pFile, " %s", Saig_ObjName(p, Aig_ObjFanin0(pObj)) ); + fprintf( pFile, " %s", Saig_ObjName(p, Aig_ObjFanin1(pObj)) ); + fprintf( pFile, " %s", Saig_ObjName(p, pObj) ); + fprintf( pFile, "\n%d%d 1\n", !Aig_ObjFaninC0(pObj), !Aig_ObjFaninC1(pObj) ); + } + // write the POs + Aig_ManForEachCo( p, pObj, i ) + { + fprintf( pFile, ".names" ); + fprintf( pFile, " %s", Saig_ObjName(p, Aig_ObjFanin0(pObj)) ); + fprintf( pFile, " %s", Saig_ObjName(p, pObj) ); + fprintf( pFile, "\n%d 1\n", !Aig_ObjFaninC0(pObj) ); + } + fprintf( pFile, ".end\n" ); + fclose( pFile ); +} + +/**Function************************************************************* + + Synopsis [Reads one token from file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Saig_ManReadToken( FILE * pFile ) +{ + static char Buffer[1000]; + if ( fscanf( pFile, "%s", Buffer ) == 1 ) + return Buffer; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Returns the corresponding number.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManReadNumber( Aig_Man_t * p, char * pToken ) +{ + if ( pToken[0] == 'n' ) + return atoi( pToken + 1 ); + if ( pToken[0] == 'p' ) + return atoi( pToken + 2 ); + if ( pToken[0] == 'l' ) + return atoi( pToken + 2 ); + assert( 0 ); + return -1; +} + +/**Function************************************************************* + + Synopsis [Returns the corresponding node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Saig_ManReadNode( Aig_Man_t * p, int * pNum2Id, char * pToken ) +{ + int Num; + if ( pToken[0] == 'n' ) + { + Num = atoi( pToken + 1 ); + return Aig_ManObj( p, pNum2Id[Num] ); + } + if ( pToken[0] == 'p' ) + { + pToken++; + if ( pToken[0] == 'i' ) + { + Num = atoi( pToken + 1 ); + return Aig_ManCi( p, Num ); + } + if ( pToken[0] == 'o' ) + return NULL; + assert( 0 ); + return NULL; + } + if ( pToken[0] == 'l' ) + { + pToken++; + if ( pToken[0] == 'o' ) + { + Num = atoi( pToken + 1 ); + return Saig_ManLo( p, Num ); + } + if ( pToken[0] == 'i' ) + return NULL; + assert( 0 ); + return NULL; + } + assert( 0 ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Reads BLIF previously dumped by Saig_ManDumpBlif().] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManReadBlif( char * pFileName ) +{ + FILE * pFile; + Aig_Man_t * p; + Aig_Obj_t * pFanin0, * pFanin1, * pNode; + char * pToken; + int i, nPis, nPos, nRegs, Number; + int * pNum2Id = NULL; // mapping of node numbers in the file into AIG node IDs + // open the file + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + printf( "Saig_ManReadBlif(): Cannot open file for reading.\n" ); + return NULL; + } + // skip through the comments + for ( i = 0; (pToken = Saig_ManReadToken( pFile )) && pToken[0] != '.'; i++ ); + if ( pToken == NULL ) + { printf( "Saig_ManReadBlif(): Error 1.\n" ); return NULL; } + // get he model + pToken = Saig_ManReadToken( pFile ); + if ( pToken == NULL ) + { printf( "Saig_ManReadBlif(): Error 2.\n" ); return NULL; } + // start the package + p = Aig_ManStart( 10000 ); + p->pName = Abc_UtilStrsav( pToken ); + p->pSpec = Abc_UtilStrsav( pFileName ); + // count PIs + pToken = Saig_ManReadToken( pFile ); + if ( pToken == NULL || strcmp( pToken, ".inputs" ) ) + { printf( "Saig_ManReadBlif(): Error 3.\n" ); Aig_ManStop(p); return NULL; } + for ( nPis = 0; (pToken = Saig_ManReadToken( pFile )) && pToken[0] != '.'; nPis++ ); + // count POs + if ( pToken == NULL || strcmp( pToken, ".outputs" ) ) + { printf( "Saig_ManReadBlif(): Error 4.\n" ); Aig_ManStop(p); return NULL; } + for ( nPos = 0; (pToken = Saig_ManReadToken( pFile )) && pToken[0] != '.'; nPos++ ); + // count latches + if ( pToken == NULL ) + { printf( "Saig_ManReadBlif(): Error 5.\n" ); Aig_ManStop(p); return NULL; } + for ( nRegs = 0; strcmp( pToken, ".latch" ) == 0; nRegs++ ) + { + pToken = Saig_ManReadToken( pFile ); + if ( pToken == NULL ) + { printf( "Saig_ManReadBlif(): Error 6.\n" ); Aig_ManStop(p); return NULL; } + pToken = Saig_ManReadToken( pFile ); + if ( pToken == NULL ) + { printf( "Saig_ManReadBlif(): Error 7.\n" ); Aig_ManStop(p); return NULL; } + pToken = Saig_ManReadToken( pFile ); + if ( pToken == NULL ) + { printf( "Saig_ManReadBlif(): Error 8.\n" ); Aig_ManStop(p); return NULL; } + pToken = Saig_ManReadToken( pFile ); + if ( pToken == NULL ) + { printf( "Saig_ManReadBlif(): Error 9.\n" ); Aig_ManStop(p); return NULL; } + } + // create PIs and LOs + for ( i = 0; i < nPis + nRegs; i++ ) + Aig_ObjCreateCi( p ); + Aig_ManSetRegNum( p, nRegs ); + // create nodes + for ( i = 0; strcmp( pToken, ".names" ) == 0; i++ ) + { + // first token + pToken = Saig_ManReadToken( pFile ); + if ( i == 0 && pToken[0] == 'n' ) + { // constant node + // read 1 + pToken = Saig_ManReadToken( pFile ); + if ( pToken == NULL || strcmp( pToken, "1" ) ) + { printf( "Saig_ManReadBlif(): Error 10.\n" ); Aig_ManStop(p); return NULL; } + // read next + pToken = Saig_ManReadToken( pFile ); + if ( pToken == NULL ) + { printf( "Saig_ManReadBlif(): Error 11.\n" ); Aig_ManStop(p); return NULL; } + continue; + } + pFanin0 = Saig_ManReadNode( p, pNum2Id, pToken ); + + // second token + pToken = Saig_ManReadToken( pFile ); + if ( (pToken[0] == 'p' && pToken[1] == 'o') || (pToken[0] == 'l' && pToken[1] == 'i') ) + { // buffer + // read complemented attribute + pToken = Saig_ManReadToken( pFile ); + if ( pToken == NULL ) + { printf( "Saig_ManReadBlif(): Error 12.\n" ); Aig_ManStop(p); return NULL; } + if ( pToken[0] == '0' ) + pFanin0 = Aig_Not(pFanin0); + // read 1 + pToken = Saig_ManReadToken( pFile ); + if ( pToken == NULL || strcmp( pToken, "1" ) ) + { printf( "Saig_ManReadBlif(): Error 13.\n" ); Aig_ManStop(p); return NULL; } + Aig_ObjCreateCo( p, pFanin0 ); + // read next + pToken = Saig_ManReadToken( pFile ); + if ( pToken == NULL ) + { printf( "Saig_ManReadBlif(): Error 14.\n" ); Aig_ManStop(p); return NULL; } + continue; + } + + // third token + // regular node + pFanin1 = Saig_ManReadNode( p, pNum2Id, pToken ); + pToken = Saig_ManReadToken( pFile ); + Number = Saig_ManReadNumber( p, pToken ); + // allocate mapping + if ( pNum2Id == NULL ) + { +// extern double pow( double x, double y ); + int Size = (int)pow(10.0, (double)(strlen(pToken) - 1)); + pNum2Id = ABC_CALLOC( int, Size ); + } + + // other tokens + // get the complemented attributes + pToken = Saig_ManReadToken( pFile ); + if ( pToken == NULL ) + { printf( "Saig_ManReadBlif(): Error 15.\n" ); Aig_ManStop(p); return NULL; } + if ( pToken[0] == '0' ) + pFanin0 = Aig_Not(pFanin0); + if ( pToken[1] == '0' ) + pFanin1 = Aig_Not(pFanin1); + // read 1 + pToken = Saig_ManReadToken( pFile ); + if ( pToken == NULL || strcmp( pToken, "1" ) ) + { printf( "Saig_ManReadBlif(): Error 16.\n" ); Aig_ManStop(p); return NULL; } + // read next + pToken = Saig_ManReadToken( pFile ); + if ( pToken == NULL ) + { printf( "Saig_ManReadBlif(): Error 17.\n" ); Aig_ManStop(p); return NULL; } + + // create new node + pNode = Aig_And( p, pFanin0, pFanin1 ); + if ( Aig_IsComplement(pNode) ) + { printf( "Saig_ManReadBlif(): Error 18.\n" ); Aig_ManStop(p); return NULL; } + // set mapping + pNum2Id[ Number ] = pNode->Id; + } + if ( pToken == NULL || strcmp( pToken, ".end" ) ) + { printf( "Saig_ManReadBlif(): Error 19.\n" ); Aig_ManStop(p); return NULL; } + if ( nPos + nRegs != Aig_ManCoNum(p) ) + { printf( "Saig_ManReadBlif(): Error 20.\n" ); Aig_ManStop(p); return NULL; } + // add non-node objects to the mapping + Aig_ManForEachCi( p, pNode, i ) + pNum2Id[pNode->Id] = pNode->Id; +// ABC_FREE( pNum2Id ); + p->pData = pNum2Id; + // check the new manager + Aig_ManSetRegNum( p, nRegs ); + if ( !Aig_ManCheck(p) ) + printf( "Saig_ManReadBlif(): Check has failed.\n" ); + return p; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigIso.c b/yosys/abc/src/aig/saig/saigIso.c new file mode 100644 index 00000000000..03ec21f3ad3 --- /dev/null +++ b/yosys/abc/src/aig/saig/saigIso.c @@ -0,0 +1,628 @@ +/**CFile**************************************************************** + + FileName [saigIso.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Sequential cleanup.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigIso.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "aig/ioa/ioa.h" +#include "saig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Find the canonical permutation of the COs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_ManFindIsoPermCos( Aig_Man_t * pAig, Vec_Int_t * vPermCis ) +{ + extern int Iso_ObjCompareByData( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 ); + Vec_Int_t * vPermCos; + Aig_Obj_t * pObj, * pFanin; + int i, Entry, Diff; + assert( Vec_IntSize(vPermCis) == Aig_ManCiNum(pAig) ); + vPermCos = Vec_IntAlloc( Aig_ManCoNum(pAig) ); + if ( Saig_ManPoNum(pAig) == 1 ) + Vec_IntPush( vPermCos, 0 ); + else + { + Vec_Ptr_t * vRoots = Vec_PtrAlloc( Saig_ManPoNum(pAig) ); + Saig_ManForEachPo( pAig, pObj, i ) + { + pFanin = Aig_ObjFanin0(pObj); + assert( Aig_ObjIsConst1(pFanin) || pFanin->iData > 0 ); + pObj->iData = Abc_Var2Lit( pFanin->iData, Aig_ObjFaninC0(pObj) ); + Vec_PtrPush( vRoots, pObj ); + } + Vec_PtrSort( vRoots, (int (*)(const void *, const void *))Iso_ObjCompareByData ); + Vec_PtrForEachEntry( Aig_Obj_t *, vRoots, pObj, i ) + Vec_IntPush( vPermCos, Aig_ObjCioId(pObj) ); + Vec_PtrFree( vRoots ); + } + // add flop outputs + Diff = Saig_ManPoNum(pAig) - Saig_ManPiNum(pAig); + Vec_IntForEachEntryStart( vPermCis, Entry, i, Saig_ManPiNum(pAig) ) + Vec_IntPush( vPermCos, Entry + Diff ); + return vPermCos; +} + +/**Function************************************************************* + + Synopsis [Performs canonical duplication of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManDupIsoCanonical_rec( Aig_Man_t * pNew, Aig_Man_t * pAig, Aig_Obj_t * pObj ) +{ + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent(pAig, pObj); + assert( Aig_ObjIsNode(pObj) ); + if ( !Aig_ObjIsNode(Aig_ObjFanin0(pObj)) || !Aig_ObjIsNode(Aig_ObjFanin1(pObj)) ) + { + Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin0(pObj) ); + Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin1(pObj) ); + } + else + { + assert( Aig_ObjFanin0(pObj)->iData != Aig_ObjFanin1(pObj)->iData ); + if ( Aig_ObjFanin0(pObj)->iData < Aig_ObjFanin1(pObj)->iData ) + { + Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin0(pObj) ); + Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin1(pObj) ); + } + else + { + Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin1(pObj) ); + Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin0(pObj) ); + } + } + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Performs canonical duplication of the AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManDupIsoCanonical( Aig_Man_t * pAig, int fVerbose ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj; + Vec_Int_t * vPerm, * vPermCo; + int i, Entry; + // derive permutations + vPerm = Saig_ManFindIsoPerm( pAig, fVerbose ); + vPermCo = Saig_ManFindIsoPermCos( pAig, vPerm ); + // create the new manager + pNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); + pNew->pName = Abc_UtilStrsav( pAig->pName ); + Aig_ManIncrementTravId( pAig ); + // create constant + pObj = Aig_ManConst1(pAig); + pObj->pData = Aig_ManConst1(pNew); + Aig_ObjSetTravIdCurrent( pAig, pObj ); + // create PIs + Vec_IntForEachEntry( vPerm, Entry, i ) + { + pObj = Aig_ManCi(pAig, Entry); + pObj->pData = Aig_ObjCreateCi(pNew); + Aig_ObjSetTravIdCurrent( pAig, pObj ); + } + // traverse from the POs + Vec_IntForEachEntry( vPermCo, Entry, i ) + { + pObj = Aig_ManCo(pAig, Entry); + Saig_ManDupIsoCanonical_rec( pNew, pAig, Aig_ObjFanin0(pObj) ); + } + // create POs + Vec_IntForEachEntry( vPermCo, Entry, i ) + { + pObj = Aig_ManCo(pAig, Entry); + Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + } + Aig_ManSetRegNum( pNew, Aig_ManRegNum(pAig) ); + Vec_IntFreeP( &vPerm ); + Vec_IntFreeP( &vPermCo ); + return pNew; +} + + + + + +/**Function************************************************************* + + Synopsis [Checks structural equivalence of AIG1 and AIG2.] + + Description [Returns 1 if AIG1 and AIG2 are structurally equivalent + under this mapping.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Iso_ManCheckMapping( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vMap2to1, int fVerbose ) +{ + Aig_Obj_t * pObj, * pFanin0, * pFanin1; + int i; + assert( Aig_ManCiNum(pAig1) == Aig_ManCiNum(pAig2) ); + assert( Aig_ManCoNum(pAig1) == Aig_ManCoNum(pAig2) ); + assert( Aig_ManRegNum(pAig1) == Aig_ManRegNum(pAig2) ); + assert( Aig_ManNodeNum(pAig1) == Aig_ManNodeNum(pAig2) ); + Aig_ManCleanData( pAig1 ); + // map const and PI nodes + Aig_ManConst1(pAig2)->pData = Aig_ManConst1(pAig1); + Aig_ManForEachCi( pAig2, pObj, i ) + pObj->pData = Aig_ManCi( pAig1, Vec_IntEntry(vMap2to1, i) ); + // try internal nodes + Aig_ManForEachNode( pAig2, pObj, i ) + { + pFanin0 = Aig_ObjChild0Copy( pObj ); + pFanin1 = Aig_ObjChild1Copy( pObj ); + pObj->pData = Aig_TableLookupTwo( pAig1, pFanin0, pFanin1 ); + if ( pObj->pData == NULL ) + { + if ( fVerbose ) + printf( "Structural equivalence failed at node %d.\n", i ); + return 0; + } + } + // make sure the first PO points to the same node + if ( Aig_ManCoNum(pAig1)-Aig_ManRegNum(pAig1) == 1 && Aig_ObjChild0Copy(Aig_ManCo(pAig2, 0)) != Aig_ObjChild0(Aig_ManCo(pAig1, 0)) ) + { + if ( fVerbose ) + printf( "Structural equivalence failed at primary output 0.\n" ); + return 0; + } + return 1; +} + +//static int s_Counter; + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Iso_ManNegEdgeNum( Aig_Man_t * pAig ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + if ( pAig->nComplEdges > 0 ) + return pAig->nComplEdges; + Aig_ManForEachObj( pAig, pObj, i ) + if ( Aig_ObjIsNode(pObj) ) + { + Counter += Aig_ObjFaninC0(pObj); + Counter += Aig_ObjFaninC1(pObj); + } + else if ( Aig_ObjIsCo(pObj) ) + Counter += Aig_ObjFaninC0(pObj); + return (pAig->nComplEdges = Counter); +} + +/**Function************************************************************* + + Synopsis [Finds mapping of CIs of AIG2 into those of AIG1.] + + Description [Returns the mapping of CIs of the two AIGs, or NULL + if there is no mapping.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Iso_ManFindMapping( Aig_Man_t * pAig1, Aig_Man_t * pAig2, Vec_Int_t * vPerm1_, Vec_Int_t * vPerm2_, int fVerbose ) +{ + Vec_Int_t * vPerm1, * vPerm2, * vInvPerm2; + int i, Entry; + if ( Aig_ManCiNum(pAig1) != Aig_ManCiNum(pAig2) ) + return NULL; + if ( Aig_ManCoNum(pAig1) != Aig_ManCoNum(pAig2) ) + return NULL; + if ( Aig_ManRegNum(pAig1) != Aig_ManRegNum(pAig2) ) + return NULL; + if ( Aig_ManNodeNum(pAig1) != Aig_ManNodeNum(pAig2) ) + return NULL; + if ( Aig_ManLevelNum(pAig1) != Aig_ManLevelNum(pAig2) ) + return NULL; +// if ( Iso_ManNegEdgeNum(pAig1) != Iso_ManNegEdgeNum(pAig2) ) +// return NULL; +// s_Counter++; + + if ( fVerbose ) + printf( "AIG1:\n" ); + vPerm1 = vPerm1_ ? vPerm1_ : Saig_ManFindIsoPerm( pAig1, fVerbose ); + if ( fVerbose ) + printf( "AIG1:\n" ); + vPerm2 = vPerm2_ ? vPerm2_ : Saig_ManFindIsoPerm( pAig2, fVerbose ); + if ( vPerm1_ ) + assert( Vec_IntSize(vPerm1_) == Aig_ManCiNum(pAig1) ); + if ( vPerm2_ ) + assert( Vec_IntSize(vPerm2_) == Aig_ManCiNum(pAig2) ); + // find canonical permutation + // vPerm1/vPerm2 give canonical order of CIs of AIG1/AIG2 + vInvPerm2 = Vec_IntInvert( vPerm2, -1 ); + Vec_IntForEachEntry( vInvPerm2, Entry, i ) + { + assert( Entry >= 0 && Entry < Aig_ManCiNum(pAig1) ); + Vec_IntWriteEntry( vInvPerm2, i, Vec_IntEntry(vPerm1, Entry) ); + } + if ( vPerm1_ == NULL ) + Vec_IntFree( vPerm1 ); + if ( vPerm2_ == NULL ) + Vec_IntFree( vPerm2 ); + // check if they are indeed equivalent + if ( !Iso_ManCheckMapping( pAig1, pAig2, vInvPerm2, fVerbose ) ) + Vec_IntFreeP( &vInvPerm2 ); + return vInvPerm2; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Iso_ManFilterPos_old( Aig_Man_t * pAig, int fVerbose ) +{ + int fVeryVerbose = 0; + Vec_Ptr_t * vParts, * vPerms, * vAigs; + Vec_Int_t * vPos, * vMap; + Aig_Man_t * pPart, * pTemp; + int i, k, nPos; + + // derive AIG for each PO + nPos = Aig_ManCoNum(pAig) - Aig_ManRegNum(pAig); + vParts = Vec_PtrAlloc( nPos ); + vPerms = Vec_PtrAlloc( nPos ); + for ( i = 0; i < nPos; i++ ) + { + pPart = Saig_ManDupCones( pAig, &i, 1 ); + vMap = Saig_ManFindIsoPerm( pPart, fVeryVerbose ); + Vec_PtrPush( vParts, pPart ); + Vec_PtrPush( vPerms, vMap ); + } +// s_Counter = 0; + + // check AIGs for each PO + vAigs = Vec_PtrAlloc( 1000 ); + vPos = Vec_IntAlloc( 1000 ); + Vec_PtrForEachEntry( Aig_Man_t *, vParts, pPart, i ) + { + if ( fVeryVerbose ) + { + printf( "AIG %4d : ", i ); + Aig_ManPrintStats( pPart ); + } + Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pTemp, k ) + { + if ( fVeryVerbose ) + printf( "Comparing AIG %4d and AIG %4d. ", Vec_IntEntry(vPos,k), i ); + vMap = Iso_ManFindMapping( pTemp, pPart, + (Vec_Int_t *)Vec_PtrEntry(vPerms, Vec_IntEntry(vPos,k)), + (Vec_Int_t *)Vec_PtrEntry(vPerms, i), + fVeryVerbose ); + if ( vMap != NULL ) + { + if ( fVeryVerbose ) + printf( "Found match\n" ); +// if ( fVerbose ) +// printf( "Found match for AIG %4d and AIG %4d.\n", Vec_IntEntry(vPos,k), i ); + Vec_IntFree( vMap ); + break; + } + if ( fVeryVerbose ) + printf( "No match.\n" ); + } + if ( k == Vec_PtrSize(vAigs) ) + { + Vec_PtrPush( vAigs, pPart ); + Vec_IntPush( vPos, i ); + } + } + // delete AIGs + Vec_PtrForEachEntry( Aig_Man_t *, vParts, pPart, i ) + Aig_ManStop( pPart ); + Vec_PtrFree( vParts ); + Vec_PtrForEachEntry( Vec_Int_t *, vPerms, vMap, i ) + Vec_IntFree( vMap ); + Vec_PtrFree( vPerms ); + // derive the resulting AIG + pPart = Saig_ManDupCones( pAig, Vec_IntArray(vPos), Vec_IntSize(vPos) ); + Vec_PtrFree( vAigs ); + Vec_IntFree( vPos ); + +// printf( "The number of all checks %d. Complex checks %d.\n", nPos*(nPos-1)/2, s_Counter ); + return pPart; +} + +/**Function************************************************************* + + Synopsis [Takes multi-output sequential AIG.] + + Description [Returns candidate equivalence classes of POs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Iso_StoCompareVecStr( Vec_Str_t ** p1, Vec_Str_t ** p2 ) +{ + return Vec_StrCompareVec( *p1, *p2 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Iso_ManFilterPos( Aig_Man_t * pAig, Vec_Ptr_t ** pvPosEquivs, int fVerbose ) +{ +// int fVeryVerbose = 0; + Aig_Man_t * pPart, * pTemp; + Vec_Ptr_t * vBuffers, * vClasses; + Vec_Int_t * vLevel, * vRemain; + Vec_Str_t * vStr, * vPrev; + int i, nPos; + abctime clk = Abc_Clock(); + abctime clkDup = 0, clkAig = 0, clkIso = 0, clk2; + *pvPosEquivs = NULL; + + // derive AIG for each PO + nPos = Aig_ManCoNum(pAig) - Aig_ManRegNum(pAig); + vBuffers = Vec_PtrAlloc( nPos ); + for ( i = 0; i < nPos; i++ ) + { + if ( i % 100 == 0 ) + printf( "%6d finished...\r", i ); + + clk2 = Abc_Clock(); + pPart = Saig_ManDupCones( pAig, &i, 1 ); + clkDup += Abc_Clock() - clk2; + + clk2 = Abc_Clock(); + pTemp = Saig_ManDupIsoCanonical( pPart, 0 ); + clkIso += Abc_Clock() - clk2; + + clk2 = Abc_Clock(); + vStr = Ioa_WriteAigerIntoMemoryStr( pTemp ); + clkAig += Abc_Clock() - clk2; + + Vec_PtrPush( vBuffers, vStr ); + Aig_ManStop( pTemp ); + Aig_ManStop( pPart ); + // remember the output number in nCap (attention: hack!) + vStr->nCap = i; + } +// s_Counter = 0; + if ( fVerbose ) + { + Abc_PrintTime( 1, "Duplicate time", clkDup ); + Abc_PrintTime( 1, "Isomorph time", clkIso ); + Abc_PrintTime( 1, "AIGER time", clkAig ); + } + + // sort the infos + clk = Abc_Clock(); + Vec_PtrSort( vBuffers, (int (*)(const void *, const void *))Iso_StoCompareVecStr ); + + // create classes + clk = Abc_Clock(); + vClasses = Vec_PtrAlloc( Saig_ManPoNum(pAig) ); + // start the first class + Vec_PtrPush( vClasses, (vLevel = Vec_IntAlloc(4)) ); + vPrev = (Vec_Str_t *)Vec_PtrEntry( vBuffers, 0 ); + Vec_IntPush( vLevel, vPrev->nCap ); + // consider other classes + Vec_PtrForEachEntryStart( Vec_Str_t *, vBuffers, vStr, i, 1 ) + { + if ( Vec_StrCompareVec(vPrev, vStr) ) + Vec_PtrPush( vClasses, Vec_IntAlloc(4) ); + vLevel = (Vec_Int_t *)Vec_PtrEntryLast( vClasses ); + Vec_IntPush( vLevel, vStr->nCap ); + vPrev = vStr; + } + Vec_VecFree( (Vec_Vec_t *)vBuffers ); + + if ( fVerbose ) + Abc_PrintTime( 1, "Sorting time", Abc_Clock() - clk ); +// Abc_PrintTime( 1, "Traversal time", time_Trav ); + + // report the results +// Vec_VecPrintInt( (Vec_Vec_t *)vClasses ); +// printf( "Divided %d outputs into %d cand equiv classes.\n", Saig_ManPoNum(pAig), Vec_PtrSize(vClasses) ); +/* + if ( fVerbose ) + { + Vec_PtrForEachEntry( Vec_Int_t *, vClasses, vLevel, i ) + if ( Vec_IntSize(vLevel) > 1 ) + printf( "%d ", Vec_IntSize(vLevel) ); + else + nUnique++; + printf( " Unique = %d\n", nUnique ); + } +*/ + + // canonicize order + Vec_PtrForEachEntry( Vec_Int_t *, vClasses, vLevel, i ) + Vec_IntSort( vLevel, 0 ); + Vec_VecSortByFirstInt( (Vec_Vec_t *)vClasses, 0 ); + + // collect the first ones + vRemain = Vec_IntAlloc( 100 ); + Vec_PtrForEachEntry( Vec_Int_t *, vClasses, vLevel, i ) + Vec_IntPush( vRemain, Vec_IntEntry(vLevel, 0) ); + + // derive the resulting AIG + pPart = Saig_ManDupCones( pAig, Vec_IntArray(vRemain), Vec_IntSize(vRemain) ); + Vec_IntFree( vRemain ); + +// return (Vec_Vec_t *)vClasses; +// Vec_VecFree( (Vec_Vec_t *)vClasses ); + *pvPosEquivs = vClasses; + return pPart; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Iso_ManTest( Aig_Man_t * pAig, int fVerbose ) +{ + Vec_Int_t * vPerm; + abctime clk = Abc_Clock(); + vPerm = Saig_ManFindIsoPerm( pAig, fVerbose ); + Vec_IntFree( vPerm ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManIsoReduce( Aig_Man_t * pAig, Vec_Ptr_t ** pvPosEquivs, int fVerbose ) +{ + Aig_Man_t * pPart; + abctime clk = Abc_Clock(); + pPart = Iso_ManFilterPos( pAig, pvPosEquivs, fVerbose ); + printf( "Reduced %d outputs to %d outputs. ", Saig_ManPoNum(pAig), Saig_ManPoNum(pPart) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + if ( fVerbose && *pvPosEquivs && Saig_ManPoNum(pAig) != Vec_PtrSize(*pvPosEquivs) ) + { + printf( "Nontrivial classes:\n" ); + Vec_VecPrintInt( (Vec_Vec_t *)*pvPosEquivs, 1 ); + } +// Aig_ManStopP( &pPart ); + return pPart; +} + +ABC_NAMESPACE_IMPL_END + +#include "base/abc/abc.h" + +ABC_NAMESPACE_IMPL_START + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Iso_ManTest888( Aig_Man_t * pAig1, int fVerbose ) +{ + extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); + extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); + Abc_Ntk_t * pNtk; + Aig_Man_t * pAig2; + Vec_Int_t * vMap; + + pNtk = Abc_NtkFromAigPhase( pAig1 ); + Abc_NtkPermute( pNtk, 1, 0, 1, NULL, NULL, NULL ); + pAig2 = Abc_NtkToDar( pNtk, 0, 1 ); + Abc_NtkDelete( pNtk ); + + vMap = Iso_ManFindMapping( pAig1, pAig2, NULL, NULL, fVerbose ); + Aig_ManStop( pAig2 ); + + if ( vMap != NULL ) + { + printf( "Mapping of AIGs is found.\n" ); + if ( fVerbose ) + Vec_IntPrint( vMap ); + } + else + printf( "Mapping of AIGs is NOT found.\n" ); + Vec_IntFreeP( &vMap ); + return NULL; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigIsoFast.c b/yosys/abc/src/aig/saig/saigIsoFast.c new file mode 100644 index 00000000000..90a04df37b8 --- /dev/null +++ b/yosys/abc/src/aig/saig/saigIsoFast.c @@ -0,0 +1,353 @@ +/**CFile**************************************************************** + + FileName [aigIsoFast.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Graph isomorphism package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigIsoFast.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define AIG_ISO_NUM 16 + +typedef struct Iso_Dat_t_ Iso_Dat_t; +struct Iso_Dat_t_ +{ + unsigned nFiNeg : 3; + unsigned nFoNeg : 2; + unsigned nFoPos : 2; + unsigned Fi0Lev : 3; + unsigned Fi1Lev : 3; + unsigned Level : 3; + unsigned fVisit : 16; +}; + +typedef struct Iso_Dat2_t_ Iso_Dat2_t; +struct Iso_Dat2_t_ +{ + unsigned Data : 16; +}; + +typedef struct Iso_Sto_t_ Iso_Sto_t; +struct Iso_Sto_t_ +{ + Aig_Man_t * pAig; // user's AIG manager + int nObjs; // number of objects + Iso_Dat_t * pData; // data for each object + Vec_Int_t * vVisited; // visited nodes + Vec_Ptr_t * vRoots; // root nodes + Vec_Int_t * vPlaces; // places in the counter lists + int * pCounters; // counters +}; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Iso_Sto_t * Iso_StoStart( Aig_Man_t * pAig ) +{ + Iso_Sto_t * p; + p = ABC_CALLOC( Iso_Sto_t, 1 ); + p->pAig = pAig; + p->nObjs = Aig_ManObjNumMax( pAig ); + p->pData = ABC_CALLOC( Iso_Dat_t, p->nObjs ); + p->vVisited = Vec_IntStart( 1000 ); + p->vPlaces = Vec_IntStart( 1000 ); + p->vRoots = Vec_PtrStart( 1000 ); + p->pCounters = ABC_CALLOC( int, (1 << AIG_ISO_NUM) ); + return p; +} +void Iso_StoStop( Iso_Sto_t * p ) +{ + Vec_IntFree( p->vPlaces ); + Vec_IntFree( p->vVisited ); + Vec_PtrFree( p->vRoots ); + ABC_FREE( p->pCounters ); + ABC_FREE( p->pData ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Collect statistics about one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Iso_StoCollectInfo_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int fCompl, Vec_Int_t * vVisited, Iso_Dat_t * pData, Vec_Ptr_t * vRoots ) +{ + Iso_Dat_t * pThis = pData + Aig_ObjId(pObj); + assert( Aig_ObjIsCi(pObj) || Aig_ObjIsNode(pObj) ); + if ( pThis->fVisit ) + { + if ( fCompl ) + pThis->nFoNeg++; + else + pThis->nFoPos++; + return; + } + assert( *((int *)pThis) == 0 ); + pThis->fVisit = 1; + if ( fCompl ) + pThis->nFoNeg++; + else + pThis->nFoPos++; + pThis->Level = pObj->Level; + pThis->nFiNeg = Aig_ObjFaninC0(pObj) + Aig_ObjFaninC1(pObj); + if ( Aig_ObjIsNode(pObj) ) + { + if ( Aig_ObjFaninC0(pObj) < Aig_ObjFaninC1(pObj) || (Aig_ObjFaninC0(pObj) == Aig_ObjFaninC1(pObj) && Aig_ObjFanin0(pObj)->Level < Aig_ObjFanin1(pObj)->Level) ) + { + pThis->Fi0Lev = pObj->Level - Aig_ObjFanin0(pObj)->Level; + pThis->Fi1Lev = pObj->Level - Aig_ObjFanin1(pObj)->Level; + } + else + { + pThis->Fi0Lev = pObj->Level - Aig_ObjFanin1(pObj)->Level; + pThis->Fi1Lev = pObj->Level - Aig_ObjFanin0(pObj)->Level; + } + Iso_StoCollectInfo_rec( p, Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj), vVisited, pData, vRoots ); + Iso_StoCollectInfo_rec( p, Aig_ObjFanin1(pObj), Aig_ObjFaninC1(pObj), vVisited, pData, vRoots ); + } + else if ( Saig_ObjIsLo(p, pObj) ) + { + pThis->Fi0Lev = 1; + pThis->Fi1Lev = 0; + Vec_PtrPush( vRoots, Saig_ObjLoToLi(p, pObj) ); + } + else if ( Saig_ObjIsPi(p, pObj) ) + { + pThis->Fi0Lev = 0; + pThis->Fi1Lev = 0; + } + else + assert( 0 ); + assert( pThis->nFoNeg + pThis->nFoPos ); + Vec_IntPush( vVisited, Aig_ObjId(pObj) ); +} + +//static abctime time_Trav = 0; + +/**Function************************************************************* + + Synopsis [Collect statistics about one output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Iso_StoCollectInfo( Iso_Sto_t * p, Aig_Obj_t * pPo ) +{ + int fVerboseShow = 0; + Vec_Int_t * vInfo; + Iso_Dat2_t * pData2 = (Iso_Dat2_t *)p->pData; + Aig_Man_t * pAig = p->pAig; + Aig_Obj_t * pObj; + int i, Value, Entry, * pPerm; +// abctime clk = Abc_Clock(); + + assert( Aig_ObjIsCo(pPo) ); + + // collect initial POs + Vec_IntClear( p->vVisited ); + Vec_PtrClear( p->vRoots ); + Vec_PtrPush( p->vRoots, pPo ); + + // mark internal nodes + Vec_PtrForEachEntry( Aig_Obj_t *, p->vRoots, pObj, i ) + if ( !Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) + Iso_StoCollectInfo_rec( pAig, Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj), p->vVisited, p->pData, p->vRoots ); +// time_Trav += Abc_Clock() - clk; + + // count how many times each data entry appears + Vec_IntClear( p->vPlaces ); + Vec_IntForEachEntry( p->vVisited, Entry, i ) + { + Value = pData2[Entry].Data; +// assert( Value > 0 ); + if ( p->pCounters[Value]++ == 0 ) + Vec_IntPush( p->vPlaces, Value ); +// pData2[Entry].Data = 0; + *((int *)(p->pData + Entry)) = 0; + } + + // collect non-trivial counters + Vec_IntClear( p->vVisited ); + Vec_IntForEachEntry( p->vPlaces, Entry, i ) + { + assert( p->pCounters[Entry] ); + Vec_IntPush( p->vVisited, p->pCounters[Entry] ); + p->pCounters[Entry] = 0; + } +// printf( "%d ", Vec_IntSize(p->vVisited) ); + + // sort the costs in the increasing order + pPerm = Abc_MergeSortCost( Vec_IntArray(p->vVisited), Vec_IntSize(p->vVisited) ); + assert( Vec_IntEntry(p->vVisited, pPerm[0]) <= Vec_IntEntry(p->vVisited, pPerm[Vec_IntSize(p->vVisited)-1]) ); + + // create information + vInfo = Vec_IntAlloc( Vec_IntSize(p->vVisited) ); + for ( i = Vec_IntSize(p->vVisited)-1; i >= 0; i-- ) + { + Entry = Vec_IntEntry( p->vVisited, pPerm[i] ); + Entry = (Entry << AIG_ISO_NUM) | Vec_IntEntry( p->vPlaces, pPerm[i] ); + Vec_IntPush( vInfo, Entry ); + } + ABC_FREE( pPerm ); + + // show the final result + if ( fVerboseShow ) + Vec_IntForEachEntry( vInfo, Entry, i ) + { + Iso_Dat2_t Data = { (unsigned)Entry & 0xFFFF }; + Iso_Dat_t * pData = (Iso_Dat_t *)&Data; + + printf( "%6d : ", i ); + printf( "Freq =%6d ", Entry >> 16 ); + + printf( "FiNeg =%3d ", pData->nFiNeg ); + printf( "FoNeg =%3d ", pData->nFoNeg ); + printf( "FoPos =%3d ", pData->nFoPos ); + printf( "Fi0L =%3d ", pData->Fi0Lev ); + printf( "Fi1L =%3d ", pData->Fi1Lev ); + printf( "Lev =%3d ", pData->Level ); + printf( "\n" ); + } + return vInfo; +} + +/**Function************************************************************* + + Synopsis [Takes multi-output sequential AIG.] + + Description [Returns candidate equivalence classes of POs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Iso_StoCompareVecInt( Vec_Int_t ** p1, Vec_Int_t ** p2 ) +{ + return Vec_IntCompareVec( *p1, *p2 ); +} + +/**Function************************************************************* + + Synopsis [Takes multi-output sequential AIG.] + + Description [Returns candidate equivalence classes of POs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Vec_t * Saig_IsoDetectFast( Aig_Man_t * pAig ) +{ + Iso_Sto_t * pMan; + Aig_Obj_t * pObj; + Vec_Ptr_t * vClasses, * vInfos; + Vec_Int_t * vInfo, * vPrev, * vLevel; + int i, Number, nUnique = 0; + abctime clk = Abc_Clock(); + + // collect infos and remember their number + pMan = Iso_StoStart( pAig ); + vInfos = Vec_PtrAlloc( Saig_ManPoNum(pAig) ); + Saig_ManForEachPo( pAig, pObj, i ) + { + vInfo = Iso_StoCollectInfo(pMan, pObj); + Vec_IntPush( vInfo, i ); + Vec_PtrPush( vInfos, vInfo ); + } + Iso_StoStop( pMan ); + Abc_PrintTime( 1, "Info computation time", Abc_Clock() - clk ); + + // sort the infos + clk = Abc_Clock(); + Vec_PtrSort( vInfos, (int (*)(const void *, const void *))Iso_StoCompareVecInt ); + + // create classes + clk = Abc_Clock(); + vClasses = Vec_PtrAlloc( Saig_ManPoNum(pAig) ); + // start the first class + Vec_PtrPush( vClasses, (vLevel = Vec_IntAlloc(4)) ); + vPrev = (Vec_Int_t *)Vec_PtrEntry( vInfos, 0 ); + Vec_IntPush( vLevel, Vec_IntPop(vPrev) ); + // consider other classes + Vec_PtrForEachEntryStart( Vec_Int_t *, vInfos, vInfo, i, 1 ) + { + Number = Vec_IntPop( vInfo ); + if ( Vec_IntCompareVec(vPrev, vInfo) ) + Vec_PtrPush( vClasses, Vec_IntAlloc(4) ); + vLevel = (Vec_Int_t *)Vec_PtrEntryLast( vClasses ); + Vec_IntPush( vLevel, Number ); + vPrev = vInfo; + } + Vec_VecFree( (Vec_Vec_t *)vInfos ); + Abc_PrintTime( 1, "Sorting time", Abc_Clock() - clk ); +// Abc_PrintTime( 1, "Traversal time", time_Trav ); + + // report the results +// Vec_VecPrintInt( (Vec_Vec_t *)vClasses ); + printf( "Divided %d outputs into %d cand equiv classes.\n", Saig_ManPoNum(pAig), Vec_PtrSize(vClasses) ); + + Vec_PtrForEachEntry( Vec_Int_t *, vClasses, vLevel, i ) + if ( Vec_IntSize(vLevel) > 1 ) + printf( "%d ", Vec_IntSize(vLevel) ); + else + nUnique++; + printf( " Unique = %d\n", nUnique ); + +// return (Vec_Vec_t *)vClasses; + Vec_VecFree( (Vec_Vec_t *)vClasses ); + return NULL; +} + + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigIsoSlow.c b/yosys/abc/src/aig/saig/saigIsoSlow.c new file mode 100644 index 00000000000..4784d98ac3d --- /dev/null +++ b/yosys/abc/src/aig/saig/saigIsoSlow.c @@ -0,0 +1,1224 @@ +/**CFile**************************************************************** + + FileName [aigIso.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [AIG package.] + + Synopsis [Graph isomorphism package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - April 28, 2007.] + + Revision [$Id: aigIso.c,v 1.00 2007/04/28 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" + +ABC_NAMESPACE_IMPL_START + +/* +#define ISO_MASK 0x3FF +static int s_1kPrimes[ISO_MASK+1] = +{ + 901403,984877,908741,966307,924437,965639,918787,931067,982621,917669,981473,936407,990487,926077,922897,970861, + 942317,961747,979717,978947,940157,987821,981221,917713,983083,992231,928253,961187,991817,927643,923129,934291, + 998071,967567,961087,988661,910031,930481,904489,974167,941351,959911,963811,921463,900161,934489,905629,930653, + 901819,909457,939871,924083,915113,937969,928457,946291,973787,912869,994093,959279,905803,995219,949903,911011, + 986707,995053,930583,955511,928307,930889,968729,911507,949043,939359,961679,918041,937681,909091,963913,923539, + 929587,953347,917573,913037,995387,976483,986239,946949,922489,917887,957553,931529,929813,949567,941683,905161, + 928819,932417,900089,935903,926587,914467,967361,944833,945881,941741,915949,903407,904157,971863,993893,963607, + 918943,912463,980957,962963,968089,904513,963763,907363,904097,904093,991343,918347,986983,986659,935819,903569, + 929171,913933,999749,923123,961531,935861,915053,994853,943511,969923,927191,968333,949391,950959,968311,991409, + 911681,987101,904027,975259,907399,946223,907259,900409,957221,901063,974657,912337,979001,970147,982301,968213, + 923959,964219,935443,950161,989251,936127,985679,958159,930077,971899,944857,956083,914293,941981,909481,909047, + 960527,958183,970687,914827,949051,928159,933551,964423,914041,915869,929953,901367,914219,975551,912391,917809, + 991499,904781,949153,959887,961957,970943,947741,941263,984541,951437,984301,947423,905761,964913,971357,927709, + 916441,941933,956993,988243,921197,905453,922081,950813,946331,998561,929023,937421,956231,907651,977897,905491, + 960173,931837,955217,911951,990643,971021,949439,988453,996781,951497,906011,944309,911293,917123,983803,928097, + 977747,928703,949957,919189,925513,923953,904997,986351,930689,902009,912007,906757,955793,926803,906809,962743, + 911917,909329,949021,974651,959083,945367,905137,948377,931757,945409,920279,915007,960121,920609,946163,946391, + 928903,932951,944329,901529,959809,918469,978643,911159,982573,965411,962233,911269,953273,974437,907589,992269, + 929399,980431,905693,968267,970481,911089,950557,913799,920407,974489,909863,918529,975277,929323,971549,969181, + 972787,964267,939971,943763,940483,971501,921637,945341,955211,920701,978349,969041,929861,904103,908539,995369, + 995567,917471,908879,993821,947783,954599,978463,914519,942869,947263,988343,914657,956987,903641,943343,991063, + 985403,926327,982829,958439,942017,960353,944987,934793,948971,999331,990767,915199,912211,946459,997019,965059, + 924907,983233,943273,945359,919613,933883,928927,942763,994087,996211,918971,924871,938491,957139,918839,914629, + 974329,900577,952823,941641,900461,946997,983123,935149,923693,908419,995651,912871,987067,920201,913921,929209, + 962509,974599,972001,920273,922099,951781,958549,909971,975133,937207,929941,961397,980677,923579,980081,942199, + 940319,942979,912349,942691,986989,947711,972343,932663,937877,940369,919571,927187,981439,932353,952313,915947, + 915851,974041,989381,921029,997013,999199,914801,918751,997327,992843,982133,932051,964861,903979,937463,916781, + 944389,986719,958369,961451,917767,954367,949853,934939,958807,975797,949699,957097,980773,969989,934907,909281, + 904679,909833,991741,946769,908381,932447,957889,981697,905701,919033,999023,993541,912953,911719,934603,925019, + 989341,912269,917789,981049,959149,989909,960521,952183,922627,936253,910957,972047,945037,940399,928313,928471, + 962459,959947,927541,917333,926899,911837,985631,955127,922729,911171,900511,926251,918209,943477,955277,959773, + 971039,917353,955313,930301,990799,957731,917519,938507,988111,911657,999721,968917,934537,903073,921703,966227, + 904661,998213,954307,931309,909331,933643,910099,958627,914533,902903,950149,972721,915157,969037,988219,944137, + 976411,952873,964787,970927,968963,920741,975187,966817,982909,975281,931907,959267,980711,924617,975691,962309, + 976307,932209,989921,907969,947927,932207,945397,948929,904903,938563,961691,977671,963173,927149,951061,966547, + 937661,983597,948139,948041,982759,941093,993703,910097,902347,990307,978217,996763,904919,924641,902299,929549, + 977323,975071,932917,996293,925579,925843,915487,917443,999541,943043,919109,959879,912173,986339,939193,939599, + 927077,977183,966521,959471,991943,985951,942187,932557,904297,972337,931751,964097,942341,966221,929113,960131, + 906427,970133,996511,925637,971651,983443,981703,933613,939749,929029,958043,961511,957241,901079,950479,975493, + 985799,909401,945601,911077,978359,948151,950333,968879,978727,961151,957823,950393,960293,915683,971513,915659, + 943841,902477,916837,911161,958487,963691,949607,935707,987607,901613,972557,938947,931949,919021,982217,914737, + 913753,971279,981683,915631,907807,970421,983173,916099,984587,912049,981391,947747,966233,932101,991733,969757, + 904283,996601,979807,974419,964693,931537,917251,967961,910093,989321,988129,997307,963427,999221,962447,991171, + 993137,914339,964973,908617,968567,920497,980719,949649,912239,907367,995623,906779,914327,918131,983113,962993, + 977849,914941,932681,905713,932579,923977,965507,916469,984119,931981,998423,984407,993841,901273,910799,939847, + 997153,971429,994927,912631,931657,968377,927833,920149,978041,947449,993233,927743,939737,975017,961861,984539, + 938857,977437,950921,963659,923917,932983,922331,982393,983579,935537,914357,973051,904531,962077,990281,989231, + 910643,948281,961141,911839,947413,923653,982801,903883,931943,930617,928679,962119,969977,926921,999773,954181, + 963019,973411,918139,959719,918823,941471,931883,925273,918173,949453,946993,945457,959561,968857,935603,978283, + 978269,947389,931267,902599,961189,947621,920039,964049,947603,913259,997811,943843,978277,972119,929431,918257, + 991663,954043,910883,948797,929197,985057,990023,960961,967139,923227,923371,963499,961601,971591,976501,989959, + 908731,951331,989887,925307,909299,949159,913447,969797,959449,976957,906617,901213,922667,953731,960199,960049, + 985447,942061,955613,965443,947417,988271,945887,976369,919823,971353,962537,929963,920473,974177,903649,955777, + 963877,973537,929627,994013,940801,985709,995341,936319,904681,945817,996617,953191,952859,934889,949513,965407, + 988357,946801,970391,953521,905413,976187,968419,940669,908591,976439,915731,945473,948517,939181,935183,978067, + 907663,967511,968111,981599,913907,933761,994933,980557,952073,906557,935621,914351,967903,949129,957917,971821, + 925937,926179,955729,966871,960737,968521,949997,956999,961273,962683,990377,908851,932231,929749,932149,966971, + 922079,978149,938453,958313,995381,906259,969503,922321,918947,972443,916411,935021,944429,928643,952199,918157, + 917783,998497,944777,917771,936731,999953,975157,908471,989557,914189,933787,933157,938953,922931,986569,964363, + 906473,963419,941467,946079,973561,957431,952429,965267,978473,924109,979529,991901,988583,918259,961991,978037, + 938033,949967,986071,986333,974143,986131,963163,940553,950933,936587,923407,950357,926741,959099,914891,976231, + 949387,949441,943213,915353,983153,975739,934243,969359,926557,969863,961097,934463,957547,916501,904901,928231, + 903673,974359,932219,916933,996019,934399,955813,938089,907693,918223,969421,940903,940703,913027,959323,940993, + 937823,906691,930841,923701,933259,911959,915601,960251,985399,914359,930827,950251,975379,903037,905783,971237 +}; +*/ + +/* +#define ISO_MASK 0x7F +static int s_1kPrimes[ISO_MASK+1] = { + 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, + 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, + 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, + 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, + 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, + 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, + 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, + 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, + 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, + 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, + 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, + 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, + 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 +}; +*/ + +/* +#define ISO_MASK 0x7 +static int s_1kPrimes[ISO_MASK+1] = { + 12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741 +}; +*/ + +#define ISO_MASK 0x3FF +static unsigned int s_1kPrimes[ISO_MASK+1] = +//#define ISO_MASK 0xFF +//static int s_1kPrimes[0x3FF+1] = +{ + 0x38c19891,0xde37b0ed,0xdebcd025,0xe19b7bbe,0x7e7ebd0e,0xaeed03a1,0x811230dc,0x10bfece0, + 0xb3b23fb1,0x74176098,0xc34ec7c5,0x6bef8939,0xc40be5e3,0x2ab51a09,0xafc17cea,0x0dccc7a2, + 0xdf7db34d,0x1009c96f,0x93fd7494,0x54385b33,0x6f36eed8,0xa1953f82,0xfbd1144a,0xde533a46, + 0x23aa1cad,0x9a18943c,0xb65000d8,0x867e9974,0xe7880035,0xf9931ad4,0xcfca1e45,0x6b5aec96, + 0xe9c1a119,0xfa4968c5,0x94cf93da,0xe8c9eac4,0x95884242,0x1bba52c7,0x9232c321,0x9cec8658, + 0x984b6ad9,0x18a6eed3,0x950353e2,0x6222f6eb,0xdfbedd47,0xef0f9023,0xac932a26,0x590eaf55, + 0x97d0a034,0xdc36cd2e,0x22736b37,0xdc9066b0,0x2eb2f98b,0x5d9c7baf,0x85747c9e,0x8aca1055, + 0x50d66b74,0x2f01ae9e,0xa1a80123,0x3e1ce2dc,0xebedbc57,0x4e68bc34,0x855ee0cf,0x17275120, + 0x2ae7f2df,0xf71039eb,0x7c283eec,0x70cd1137,0x7cf651f3,0xa87bfa7a,0x14d87f02,0xe82e197d, + 0x8d8a5ebe,0x1e6a15dc,0x197d49db,0x5bab9c89,0x4b55dea7,0x55dede49,0x9a6a8080,0xe5e51035, + 0xe148d658,0x8a17eb3b,0xe22e4b38,0xe5be2a9a,0xbe938cbb,0x3b981069,0x7f9c0c8e,0xf756df10, + 0x8fa783f7,0x252062ce,0x3dc46b4b,0xf70f6432,0x3f378276,0x44b137a1,0x2bf74b77,0x04892ed6, + 0xfd318de1,0xd58c235e,0x94c6d25b,0x7aa5f218,0x35c9e921,0x5732fbbb,0x06026481,0xf584a44f, + 0x946e1b5f,0x8463d5b2,0x4ebca7b2,0x54887b15,0x08d1e804,0x5b22067d,0x794580f6,0xb351ea43, + 0xbce555b9,0x19ae2194,0xd32f1396,0x6fc1a7f1,0x1fd8a867,0x3a89fdb0,0xea49c61c,0x25f8a879, + 0xde1e6437,0x7c74afca,0x8ba63e50,0xb1572074,0xe4655092,0xdb6f8b1c,0xc2955f3c,0x327f85ba, + 0x60a17021,0x95bd261d,0xdea94f28,0x04528b65,0xbe0109cc,0x26dd5688,0x6ab2729d,0xc4f029ce, + 0xacf7a0be,0x4c912f55,0x34c06e65,0x4fbb938e,0x1533fb5f,0x03da06bd,0x48262889,0xc2523d7d, + 0x28a71d57,0x89f9713a,0xf574c551,0x7a99deb5,0x52834d91,0x5a6f4484,0xc67ba946,0x13ae698f, + 0x3e390f34,0x34fc9593,0x894c7932,0x6cf414a3,0xdb7928ab,0x13a3b8a3,0x4b381c1d,0xa10b54cb, + 0x55359d9d,0x35a3422a,0x58d1b551,0x0fd4de20,0x199eb3f4,0x167e09e2,0x3ee6a956,0x5371a7fa, + 0xd424efda,0x74f521c5,0xcb899ff6,0x4a42e4f4,0x747917b6,0x4b08df0b,0x090c7a39,0x11e909e4, + 0x258e2e32,0xd9fad92d,0x48fe5f69,0x0545cde6,0x55937b37,0x9b4ae4e4,0x1332b40e,0xc3792351, + 0xaff982ef,0x4dba132a,0x38b81ef1,0x28e641bf,0x227208c1,0xec4bbe37,0xc4e1821c,0x512c9d09, + 0xdaef1257,0xb63e7784,0x043e04d7,0x9c2cea47,0x45a0e59a,0x281315ca,0x849f0aac,0xa4071ed3, + 0x0ef707b3,0xfe8dac02,0x12173864,0x471f6d46,0x24a53c0a,0x35ab9265,0xbbf77406,0xa2144e79, + 0xb39a884a,0x0baf5b6d,0xcccee3dd,0x12c77584,0x2907325b,0xfd1adcd2,0xd16ee972,0x345ad6c1, + 0x315ebe66,0xc7ad2b8d,0x99e82c8d,0xe52da8c8,0xba50f1d3,0x66689cd8,0x2e8e9138,0x43e15e74, + 0xf1ced14d,0x188ec52a,0xe0ef3cbb,0xa958aedc,0x4107a1bc,0x5a9e7a3e,0x3bde939f,0xb5b28d5a, + 0x596fe848,0xe85ad00c,0x0b6b3aae,0x44503086,0x25b5695c,0xc0c31dcd,0x5ee617f0,0x74d40c3a, + 0xd2cb2b9f,0x1e19f5fa,0x81e24faf,0xa01ed68f,0xcee172fc,0x7fdf2e4d,0x002f4774,0x664f82dd, + 0xc569c39a,0xa2d4dcbe,0xaadea306,0xa4c947bf,0xa413e4e3,0x81fb5486,0x8a404970,0x752c980c, + 0x98d1d881,0x5c932c1e,0xeee65dfb,0x37592cdd,0x0fd4e65b,0xad1d383f,0x62a1452f,0x8872f68d, + 0xb58c919b,0x345c8ee3,0xb583a6d6,0x43d72cb3,0x77aaa0aa,0xeb508242,0xf2db64f8,0x86294328, + 0x82211731,0x1239a9d5,0x673ba5de,0xaf4af007,0x44203b19,0x2399d955,0xa175cd12,0x595928a7, + 0x6918928b,0xde3126bb,0x6c99835c,0x63ba1fa2,0xdebbdff0,0x3d02e541,0xd6f7aac6,0xe80b4cd0, + 0xd0fa29f1,0x804cac5e,0x2c226798,0x462f624c,0xad05b377,0x22924fcd,0xfbea205c,0x1b47586d, + 0x214d04ab,0xe093e487,0x10607ada,0x42b261cc,0x1a85e0f6,0xb851bfc3,0x77d5591c,0xda13f344, + 0xc39c4c00,0xe60d75fc,0x7edae36a,0x3e4ac3ec,0x8bc38db4,0xe848dce9,0xb2407d4d,0x0d79c61e, + 0x1e6c293a,0x7bc30986,0xdf18cb8f,0x23003172,0x6948e3fa,0x9b7e4f09,0x14b3b339,0x9c8078c2, + 0x9a47c29f,0x85bb45ec,0x9ca35a93,0xd7db5227,0x1d9b0a10,0xb7fbbfe9,0x05b72426,0x6f30b2fa, + 0x9fb44078,0xedffd3f8,0x1b02b7bc,0x43e3cfd3,0x0d44293e,0x25c8d552,0xedd3f85d,0x6f921c8c, + 0x953cca0c,0x9c975b70,0xc6bd0b53,0x4f204f3e,0xa3cc69cc,0xceec390b,0x34905626,0x82ad5d41, + 0xe46589a5,0x7989841d,0x045d7d9f,0xe49b7b2f,0x46baf101,0x996f92de,0x427566c8,0x918a1ee1, + 0xf4baa589,0x6bdff7c7,0x3c6936ea,0xe85bfb70,0x5d96ea26,0x6d5a8991,0x7f0a528d,0x852f0634, + 0x2ec04501,0x5ca15c35,0xd8695e7a,0x456876c7,0x52e97b83,0x34b4c5ed,0x54d73fbb,0x44a6be01, + 0xf8019155,0x33d55a31,0x3fe51c99,0xe1cb94fd,0x8c39cd60,0xd585efba,0x2765579b,0xb8f7ed12, + 0xbb04b2cd,0xd8859981,0xd966988d,0xa68bfeda,0x73110705,0x38d6aec0,0x613bc275,0xc7283c2d, + 0xe051d0b1,0x32b8c2ee,0x0e73fb9e,0x7ab05c25,0x6ff652b9,0x45aeabc6,0x6be1a891,0x5b43531b, + 0xcd711248,0x2b777d40,0x46956d16,0x474355a8,0xe872d6c6,0xe4158d96,0xabe03036,0x5b4fd9a4, + 0xeceba1db,0xaac9713f,0xe953153b,0xf44a9229,0x460cba72,0xfd13fdf6,0x8bbf82ae,0xaf55778f, + 0xa447a5b2,0x98b647b3,0x5f351c57,0x69d0bb71,0xf14d2706,0x78b1a3af,0x7206c73f,0x3f5cd4a6, + 0x5c0e4515,0xdb46a663,0x10c3a9b0,0x8eda7748,0x52bb44c9,0x3df62689,0xc83e2732,0xf36c99af, + 0x7ec7a94c,0x5c823718,0x6586e58e,0x4b726e75,0xcfe03a05,0x34eb2f4b,0xf4eec9cf,0xb38d6d73, + 0x71fafa9e,0x0371a29a,0xc405f83b,0x889f49c2,0xd1443000,0x469665bf,0x609ed65d,0x67c8f9ba, + 0x9d2f6055,0xb91b8eb1,0x96c809fe,0x2d6ab0f5,0xc16d4f04,0x590171ab,0x73d67526,0xf724e44c, + 0x6aef02b7,0x6489a325,0x4458401e,0x22d94ad7,0x05e5be57,0x5634fad8,0x951fcf70,0x4baad7f0, + 0x40c1090d,0xedc28abd,0x343cc6e4,0x4ff7c030,0x0734a641,0x2635a90e,0x2e000c84,0x4b617a70, + 0x872e9c9e,0x3dceeb42,0xd0fcc398,0x9cc9b9c8,0x2de02f0c,0xaf0e2614,0xa60253aa,0xe0517492, + 0xa7bde4b4,0x3bb66d7d,0x7f215e82,0xf259de66,0xe17380fe,0xdbc718b4,0x66abcc29,0xf0826e1f, + 0x08f60995,0xce81b933,0xa832c0e9,0x37aed7d4,0x8a75c261,0x916627b4,0xd486a04b,0x64fd0fde, + 0x1261328a,0xe037772f,0xb5b71117,0x55d04bd8,0x8f6c1c7b,0xb9f5fcdd,0x5918f756,0x25c90099, + 0x2e8787db,0x58e14e38,0x0d397852,0x32c8e33b,0x5ae2b795,0x3a7b3ff7,0x5eebf893,0x1aeee816, + 0xc2ef31d0,0x1d86e615,0x183f1de3,0xb89d46c4,0x525ebbf6,0xfe0198ca,0x4986cc4a,0x2a75701e, + 0x382158b1,0x192ee88f,0x3e512912,0xcd571c3d,0xdf694fe8,0xec8ead1d,0x83719ac3,0x3f654079, + 0xf6a623c5,0x33e1fc6e,0xe7f7c426,0x5bff0f6c,0x698a9bb1,0xec2a29ba,0x75358b45,0x40c6ffef, + 0x6605bb55,0x53a8c97a,0x7bba1569,0x499bc51b,0x5849c89a,0xe6ddb267,0x8659c719,0x14a05548, + 0xeec648a9,0x618af87a,0x62214521,0x7f36e610,0x152efeeb,0xc2b0f0ed,0x1d657588,0xa5fcec4b, + 0xf872f109,0x46903038,0x04b57b97,0xe5d51b14,0x06c264ec,0x68aa8d14,0xa4e1bed8,0xdae169c2, + 0xeb90debd,0xe8c11a7a,0xcafce013,0x63820cee,0x948c23e5,0xc1d42ea3,0x8256c951,0x9b587773, + 0x2fa8380c,0x30255e09,0x1a809cdc,0xe1446068,0x2714621d,0xb3347d64,0x1f4cbf3d,0xd068bc26, + 0x2c422740,0x06c4a3ad,0x5dc9d63c,0x4724bf48,0x28e34add,0x27d5221d,0xe349c7e2,0x6119e0a5, + 0x4ae7d29f,0x53a7912d,0xfc5db779,0x7d28d357,0xfd80036d,0x06bcc597,0x36d70a8a,0x37738cb7, + 0xf11e6272,0xfdd5d153,0x5dc666dc,0x6b5a415d,0x1073b415,0x36f30d9a,0x807daf7b,0x387f6823, + 0x8970fe00,0xee560be5,0xea8c0bad,0xfac2b422,0xc845861d,0xa181a2ee,0x29c4dffd,0x4d441bb2, + 0x7a64cf93,0x0c33e6ac,0x0a35d034,0x1067d26d,0x8c7da0cc,0x2d6e2d5a,0x9932c25a,0x5fca4e2c, + 0x2c82fd71,0x41730b70,0x244bdbb9,0x96514307,0xc6a32a6b,0xc4c256a7,0x38517fd8,0x541aa859, + 0x0752afe3,0x741e22f9,0xa2565483,0x7588b0b9,0xdd404e42,0x4d86c49d,0x6fa93fc1,0x163bd200, + 0x745d0d31,0x8d3dd20e,0xebdc64db,0x9315c149,0x39db3299,0xb0c22004,0xa4c0295b,0x8b3573eb, + 0xd92a40a3,0x73d6c379,0x67673309,0xdaff1d7f,0x42fcfeb8,0xd57c11a4,0x402066ef,0x9d1134e0, + 0x9f417081,0x10f49e00,0x7e7ee855,0x314e6d25,0x602bdbe6,0xa4be4045,0xac511dc4,0x33d6bda8, + 0x2f2bc412,0x4b9c0b6c,0x98aaab06,0x7f0a5801,0xfbf1f16d,0x058f54ae,0x4fd97724,0x348cb50b, + 0xef6f659f,0x0cd8b184,0x1d71a666,0xae3c87dd,0x7bd56793,0xe0f8f6a8,0x90429c55,0x8a3cc4d0, + 0x49957b70,0x3baf3912,0x755efebb,0xa5eca17f,0x486065a1,0x1dffcefb,0xd914b3a0,0x1ced93c1, + 0xa4262dcd,0xc12a4adc,0x08f6de4e,0x4c204faf,0xca1815de,0xa4af836f,0x91d5e44d,0xd2a7caa4, + 0x68a9a3fe,0x844f8dac,0x3fc36c67,0x8be23937,0x69879d94,0x5d0dbecb,0x1f0f59a4,0x94721142, + 0xfca6064a,0x6d28aa48,0x804cd04e,0x4a3906de,0x8e352509,0x302326d9,0xed4937ed,0x4a570e63, + 0xcaa57efb,0x64bd4878,0x3419334a,0x712e5f6b,0x9fa9d687,0x06f8645f,0x620ca96f,0xdc5d6cce, + 0x392f3257,0x52140f06,0xc4b3bda4,0xe8c7eba7,0x066bd754,0xc5941f26,0xe6dfd573,0x328dd14d, + 0xb1cb4ba7,0x1d37a9b8,0x96a195a5,0x970e535a,0x290351b8,0x570000f6,0xe14ae341,0x35ede6a6, + 0x9a02f032,0xaf2ebb58,0x146be492,0x670b3e4b,0x72fa6cfd,0xa243af97,0xbbd5fc21,0xcb8852a2, + 0x5d5b4a42,0xeefff0ac,0xa59ad1b6,0x3ec55544,0x48d64f69,0x9065d3d0,0xdd09485b,0xdd63bd09, + 0x605e811d,0xc4b4ed7d,0xb0b58558,0x0644400b,0x12222346,0x086f146a,0xad6dee36,0x5488d1a3, + 0x0c93bc0c,0x18555d92,0x9f4427bf,0xa590a66a,0x3a630fda,0xf1681c2e,0x948a16fb,0x16fe3338, + 0xc9832357,0xd1e8e6b5,0xd9cfe034,0x05b22f26,0x27233c6e,0x355890e1,0xfbe6eaf3,0x0dcd8e8f, + 0x00b5df46,0xd97730ac,0xc6dfd8ff,0x0cb1840a,0x41e9d249,0xbb471b4e,0x480b8f63,0x1ffe8871, + 0x17b11821,0x1709e440,0xcefb3668,0xa4954ddd,0xf03ef8b5,0x6b3e633c,0xe5813096,0x3697c9a6, + 0x7800f52f,0x73a7aa39,0x59ac23b7,0xb4663166,0x9ca9d6f8,0x2d441072,0x38cef3d3,0x39a3faf6, + 0x89299fb9,0xd558295f,0xcf79c633,0x232dd96e,0xadb2955b,0xe962cbb9,0xab7c0061,0x1027c329, + 0xb4b43e07,0x25240a7a,0x98ea4825,0xdbf2edbd,0x8be15d26,0x879f3cd9,0xa4138089,0xa32dcb06, + 0x602af961,0x4b13f451,0x1c87d0d5,0xc3bb141b,0x9ebf55a1,0xef030a9a,0x8d199b93,0xdabcbb56, + 0xf412f80f,0x302e90ad,0xc4d9878b,0xc392f650,0x4fd3a614,0x0a96ddc4,0xcd1878c7,0x9ddd3ae1, + 0xdaf46458,0xba7c8656,0xf667948f,0xc37e3c23,0x04a577c6,0xbe615f1e,0xcc97406c,0xd497f16f, + 0x79586586,0xd2057d14,0x1bb92028,0xab888e5e,0x26bef100,0xf46b3671,0xf21f1acc,0x67f288c8, + 0x39c722df,0x61d21eaf,0x9c5853a0,0x63b693c7,0x1ea53c0a,0x95bc0a85,0xa7372f2d,0x3ef6a6b3, + 0x82c9c4ac,0x4dea10ee,0xdfcb543d,0xd412f427,0x53e27f2c,0x875d8422,0x5367a7d8,0x41acf3fa, + 0xbce47234,0x8056fb9a,0x4e9a4c48,0xe4a45945,0x2cfee3ae,0xb4554b10,0x5e37a915,0x591b1963, + 0x4fa255c1,0xe01c897b,0x504e6208,0x7c7368eb,0x13808fd7,0x02ac0816,0x30305d2c,0x6c4bbdb7, + 0xa48a9599,0x57466059,0x4c6ebfc7,0x8587ccdf,0x6ff0abf0,0x5b6b63fe,0x31d9ec64,0x63458abd, + 0x21245905,0xccdb28fc,0xac828acb,0xe5e82bea,0xa7d76141,0xa699038e,0xcaba7e06,0x2710253f, + 0x2ff9c94d,0x26e48a2c,0xd713ec5e,0x869f2ed4,0x25bcd712,0xcb3e918f,0x615c3a5a,0x9fb43903, + 0x37900eb9,0x4f682db0,0x35a80dc6,0x4eb27c65,0x502735ab,0xb163b4c8,0x604649a8,0xb23a6cd3, + 0x9f715091,0x2e6fbb51,0x2ec9144b,0x272cbe65,0x90a0a453,0x420e1503,0x2d00d338,0x4aa96675, + 0xd025b61c,0xab02d9d7,0x2afe2a37,0xf8129b9b,0x4db04c54,0x654a5c06,0x3213ff51,0x4e09d0b1, + 0x333369a3,0xae27310a,0x91d076d0,0xa96ebcd0,0xefde54f4,0x021c309a,0xd506f53d,0xa5635251, + 0x2f23916e,0x1fe86bb1,0xcbc62160,0x2147c8cc,0xdeb3e47c,0x028e3987,0x8061de42,0x39be931b, + 0x2b7e54c5,0xe64d2f96,0x4069522d,0x4aa66857,0x83b62634,0x4ba72095,0x9aade2a9,0xf1223cd9, + 0x91cbddf0,0xec5d237f,0x593f3280,0x0b924439,0x446f4063,0xc66f8d8c,0x8b7128ba,0xb597f451, + 0xc8925236,0x1720f235,0x7cd2e9a0,0x4c130339,0x8a665a52,0x5bef2733,0xba35d9bc,0x6d26644c, + 0x385cdce1,0x509e4280,0x12aa9ed7,0xf5314d21,0xbe249d4a,0xf32e9753,0x91821cf9,0x01d63491, + 0x49afa237,0x80e0bc27,0x844d796b,0xeff5ccb7,0x46303091,0x743484b4,0x77de1ab7,0x5ab00bea, + 0x6316cd81,0x8ded07f4,0x3845a3a5,0x206625c4,0x8c123c6f,0xc80a971e,0xd4d4fa3f,0x5eba911d, + 0xee168406,0x61cdcbad,0x981a44cd,0x718d030f,0xf653e92e,0xd5b77859,0x11e9e5d9,0xf6fe6ff3, + 0x5239f010,0xe289b21b,0x0b52832b,0xca700c62,0xee7a5e15,0x8543ce2c,0x94a703cc,0x0b844d34, + 0xf70638e5,0xfa286206,0xf8778906,0x1419e883,0xdb0fc46b,0xbeb74261,0xc6957b62,0x8352d2a8, + 0x460586ce,0x90b28336,0xc9107ea8,0x3590403b,0x259a4279,0x6a1a7bbe,0x0f3b76e1,0x4872a716, + 0xa5bfff13,0x8b30be72,0xe5a68957,0x17dbbc52,0x33a40187,0x7074220c,0xd8221b92,0x40ec7448, + 0x7dbbcdfc,0xd5a9bb83,0xb4c0d25c,0xa0040390,0x6fb429dc,0xb8cede12,0x87d193bd,0x55c6e004 +}; + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define ISO_NUM_INTS 3 + +typedef struct Iso_Obj_t_ Iso_Obj_t; +struct Iso_Obj_t_ +{ + // hashing entries (related to the parameter ISO_NUM_INTS!) + unsigned Level : 30; + unsigned nFinNeg : 2; + unsigned FaninSig; + unsigned FanoutSig; + // other data + int iNext; // hash table entry + int iClass; // next one in class + int Id; // unique ID +}; + +typedef struct Iso_Man_t_ Iso_Man_t; +struct Iso_Man_t_ +{ + Aig_Man_t * pAig; // user's AIG manager + Iso_Obj_t * pObjs; // isomorphism objects + int nObjIds; // counter of object IDs + int nClasses; // total number of classes + int nEntries; // total number of entries + int nSingles; // total number of singletons + int nObjs; // total objects + int nBins; // hash table size + int * pBins; // hash table + Vec_Ptr_t * vSingles; // singletons + Vec_Ptr_t * vClasses; // other classes + Vec_Ptr_t * vTemp1; // other classes + Vec_Ptr_t * vTemp2; // other classes + abctime timeHash; + abctime timeFout; + abctime timeSort; + abctime timeOther; + abctime timeTotal; +}; + +static inline Iso_Obj_t * Iso_ManObj( Iso_Man_t * p, int i ) { assert( i >= 0 && i < p->nObjs ); return i ? p->pObjs + i : NULL; } +static inline int Iso_ObjId( Iso_Man_t * p, Iso_Obj_t * pObj ) { assert( pObj > p->pObjs && pObj < p->pObjs + p->nObjs ); return pObj - p->pObjs; } +static inline Aig_Obj_t * Iso_AigObj( Iso_Man_t * p, Iso_Obj_t * q ) { return Aig_ManObj( p->pAig, Iso_ObjId(p, q) ); } + +#define Iso_ManForEachObj( p, pObj, i ) \ + for ( i = 1; (i < p->nObjs) && ((pObj) = Iso_ManObj(p, i)); i++ ) if ( pIso->Level == -1 ) {} else + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//extern void Iso_ReadPrimes( char * pFileName ); +//Iso_ReadPrimes( "primes.txt" ); + +/**Function************************************************************* + + Synopsis [Read primes from file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Iso_ReadPrimes( char * pFileName ) +{ + FILE * pFile; + int Nums[10000]; + int i, j, Temp, nSize = 0; + // read the numbers + pFile = fopen( pFileName, "rb" ); + while ( fscanf( pFile, "%d", Nums + nSize++ ) == 1 ); + fclose( pFile ); + assert( nSize >= (1<<10) ); + // randomly permute + srand( 111 ); + for ( i = 0; i < nSize; i++ ) + { + j = rand() % nSize; + Temp = Nums[i]; + Nums[i] = Nums[j]; + Nums[j] = Temp; + } + // write out + for ( i = 0; i < 64; i++ ) + { + printf( " " ); + for ( j = 0; j < 16; j++ ) + printf( "%d,", Nums[i*16+j] ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Read primes from file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Iso_FindNumbers() +{ + unsigned Nums[1024]; + unsigned char * pNums = (unsigned char *)Nums; + int i, j; + srand( 111 ); + for ( i = 0; i < 1024 * 4; i++ ) + pNums[i] = (unsigned char)rand(); + // write out + for ( i = 0; i < 128; i++ ) + { + printf( " " ); + for ( j = 0; j < 8; j++ ) + printf( "0x%08x,", Nums[i*8+j] ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Iso_ManObjCount_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int * pnNodes, int * pnEdges ) +{ + if ( Aig_ObjIsCi(pObj) ) + return; + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + Iso_ManObjCount_rec( p, Aig_ObjFanin0(pObj), pnNodes, pnEdges ); + Iso_ManObjCount_rec( p, Aig_ObjFanin1(pObj), pnNodes, pnEdges ); + (*pnEdges) += Aig_ObjFaninC0(pObj) + Aig_ObjFaninC1(pObj); + (*pnNodes)++; +} +void Iso_ManObjCount( Aig_Man_t * p, Aig_Obj_t * pObj, int * pnNodes, int * pnEdges ) +{ + assert( Aig_ObjIsNode(pObj) ); + *pnNodes = *pnEdges = 0; + Aig_ManIncrementTravId( p ); + Iso_ManObjCount_rec( p, pObj, pnNodes, pnEdges ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Iso_Man_t * Iso_ManStart( Aig_Man_t * pAig ) +{ + Iso_Man_t * p; + p = ABC_CALLOC( Iso_Man_t, 1 ); + p->pAig = pAig; + p->nObjs = Aig_ManObjNumMax( pAig ); + p->pObjs = ABC_CALLOC( Iso_Obj_t, p->nObjs ); + p->nBins = Abc_PrimeCudd( p->nObjs ); + p->pBins = ABC_CALLOC( int, p->nBins ); + p->vSingles = Vec_PtrAlloc( 1000 ); + p->vClasses = Vec_PtrAlloc( 1000 ); + p->vTemp1 = Vec_PtrAlloc( 1000 ); + p->vTemp2 = Vec_PtrAlloc( 1000 ); + p->nObjIds = 1; + return p; +} +void Iso_ManStop( Iso_Man_t * p, int fVerbose ) +{ + if ( fVerbose ) + { + p->timeOther = p->timeTotal - p->timeHash - p->timeFout; + ABC_PRTP( "Building ", p->timeFout, p->timeTotal ); + ABC_PRTP( "Hashing ", p->timeHash-p->timeSort, p->timeTotal ); + ABC_PRTP( "Sorting ", p->timeSort, p->timeTotal ); + ABC_PRTP( "Other ", p->timeOther, p->timeTotal ); + ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); + } + Vec_PtrFree( p->vTemp1 ); + Vec_PtrFree( p->vTemp2 ); + Vec_PtrFree( p->vClasses ); + Vec_PtrFree( p->vSingles ); + ABC_FREE( p->pBins ); + ABC_FREE( p->pObjs ); + ABC_FREE( p ); +} + + +/**Function************************************************************* + + Synopsis [Compares two objects by their signature.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Iso_ObjCompare( Iso_Obj_t ** pp1, Iso_Obj_t ** pp2 ) +{ + return -memcmp( *pp1, *pp2, sizeof(int) * ISO_NUM_INTS ); +} + +/**Function************************************************************* + + Synopsis [Compares two objects by their ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Iso_ObjCompareByData( Aig_Obj_t ** pp1, Aig_Obj_t ** pp2 ) +{ + Aig_Obj_t * pIso1 = *pp1; + Aig_Obj_t * pIso2 = *pp2; + assert( Aig_ObjIsCi(pIso1) || Aig_ObjIsCo(pIso1) ); + assert( Aig_ObjIsCi(pIso2) || Aig_ObjIsCo(pIso2) ); + return pIso1->iData - pIso2->iData; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Iso_ObjHash( Iso_Obj_t * pIso, int nBins ) +{ + static unsigned BigPrimes[8] = {12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741}; + unsigned * pArray = (unsigned *)pIso; + unsigned i, Value = 0; + assert( ISO_NUM_INTS < 8 ); + for ( i = 0; i < ISO_NUM_INTS; i++ ) + Value ^= BigPrimes[i] * pArray[i]; + return Value % nBins; +} +static inline int Iso_ObjHashAdd( Iso_Man_t * p, Iso_Obj_t * pIso ) +{ + Iso_Obj_t * pThis; + int * pPlace = p->pBins + Iso_ObjHash( pIso, p->nBins ); + p->nEntries++; + for ( pThis = Iso_ManObj(p, *pPlace); + pThis; pPlace = &pThis->iNext, + pThis = Iso_ManObj(p, *pPlace) ) + if ( Iso_ObjCompare( &pThis, &pIso ) == 0 ) // equal signatures + { + if ( pThis->iClass == 0 ) + { + p->nClasses++; + p->nSingles--; + } + // add to the list + pIso->iClass = pThis->iClass; + pThis->iClass = Iso_ObjId( p, pIso ); + return 1; + } + // create new list + *pPlace = Iso_ObjId( p, pIso ); + p->nSingles++; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Iso_ManCollectClasses( Iso_Man_t * p ) +{ + Iso_Obj_t * pIso; + int i; + abctime clk = Abc_Clock(); + Vec_PtrClear( p->vSingles ); + Vec_PtrClear( p->vClasses ); + for ( i = 0; i < p->nBins; i++ ) + { + for ( pIso = Iso_ManObj(p, p->pBins[i]); pIso; pIso = Iso_ManObj(p, pIso->iNext) ) + { + assert( pIso->Id == 0 ); + if ( pIso->iClass ) + Vec_PtrPush( p->vClasses, pIso ); + else + Vec_PtrPush( p->vSingles, pIso ); + } + } + clk = Abc_Clock(); + Vec_PtrSort( p->vSingles, (int (*)(const void *, const void *))Iso_ObjCompare ); + Vec_PtrSort( p->vClasses, (int (*)(const void *, const void *))Iso_ObjCompare ); + p->timeSort += Abc_Clock() - clk; + assert( Vec_PtrSize(p->vSingles) == p->nSingles ); + assert( Vec_PtrSize(p->vClasses) == p->nClasses ); + // assign IDs to singletons + Vec_PtrForEachEntry( Iso_Obj_t *, p->vSingles, pIso, i ) + if ( pIso->Id == 0 ) + pIso->Id = p->nObjIds++; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Iso_Man_t * Iso_ManCreate( Aig_Man_t * pAig ) +{ + int fUseXor = 0; + Iso_Man_t * p; + Iso_Obj_t * pIso, * pIsoF; + Aig_Obj_t * pObj, * pObjLi; + int i; + p = Iso_ManStart( pAig ); + + // create TFI signatures + Aig_ManForEachObj( pAig, pObj, i ) + { + if ( Aig_ObjIsCo(pObj) ) + continue; + pIso = p->pObjs + i; + pIso->Level = pObj->Level; +// pIso->nFinNeg = Aig_ObjFaninC0(pObj) + Aig_ObjFaninC1(pObj); + + assert( pIso->FaninSig == 0 ); + assert( pIso->FanoutSig == 0 ); + if ( fUseXor ) + { + if ( Aig_ObjIsNode(pObj) ) + { + pIsoF = p->pObjs + Aig_ObjFaninId0(pObj); + pIso->FaninSig ^= pIsoF->FaninSig; + pIso->FaninSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC0(pObj)) & ISO_MASK]; + + pIsoF = p->pObjs + Aig_ObjFaninId1(pObj); + pIso->FaninSig ^= pIsoF->FaninSig; + pIso->FaninSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC1(pObj)) & ISO_MASK]; + } + } + else + { + if ( Aig_ObjIsNode(pObj) ) + { + pIsoF = p->pObjs + Aig_ObjFaninId0(pObj); + pIso->FaninSig += pIsoF->FaninSig; + pIso->FaninSig += pIso->Level * s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC0(pObj)) & ISO_MASK]; + + pIsoF = p->pObjs + Aig_ObjFaninId1(pObj); + pIso->FaninSig += pIsoF->FaninSig; + pIso->FaninSig += pIso->Level * s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC1(pObj)) & ISO_MASK]; + } + } + } + + // create TFO signatures + Aig_ManForEachObjReverse( pAig, pObj, i ) + { + if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) ) + continue; + pIso = p->pObjs + i; + if ( fUseXor ) + { + if ( Aig_ObjIsNode(pObj) ) + { + pIsoF = p->pObjs + Aig_ObjFaninId0(pObj); + pIsoF->FanoutSig ^= pIso->FanoutSig; + pIsoF->FanoutSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC0(pObj)) & ISO_MASK]; + + pIsoF = p->pObjs + Aig_ObjFaninId1(pObj); + pIsoF->FanoutSig ^= pIso->FanoutSig; + pIsoF->FanoutSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC1(pObj)) & ISO_MASK]; + } + else if ( Aig_ObjIsCo(pObj) ) + { + pIsoF = p->pObjs + Aig_ObjFaninId0(pObj); + pIsoF->FanoutSig ^= pIso->FanoutSig; + pIsoF->FanoutSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC0(pObj)) & ISO_MASK]; + } + } + else + { + if ( Aig_ObjIsNode(pObj) ) + { + pIsoF = p->pObjs + Aig_ObjFaninId0(pObj); + pIsoF->FanoutSig += pIso->FanoutSig; + pIsoF->FanoutSig += pIso->Level * s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC0(pObj)) & ISO_MASK]; + + pIsoF = p->pObjs + Aig_ObjFaninId1(pObj); + pIsoF->FanoutSig += pIso->FanoutSig; + pIsoF->FanoutSig += pIso->Level * s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC1(pObj)) & ISO_MASK]; + } + else if ( Aig_ObjIsCo(pObj) ) + { + pIsoF = p->pObjs + Aig_ObjFaninId0(pObj); + pIsoF->FanoutSig += pIso->FanoutSig; + pIsoF->FanoutSig += pIso->Level * s_1kPrimes[Abc_Var2Lit(pIso->Level, Aig_ObjFaninC0(pObj)) & ISO_MASK]; + } + } + } + + // consider flops + Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObj, i ) + { + if ( Aig_ObjFaninId0(pObjLi) == 0 ) // ignore constant! + continue; + pIso = Iso_ManObj( p, Aig_ObjId(pObj) ); + pIsoF = Iso_ManObj( p, Aig_ObjFaninId0(pObjLi) ); + + assert( pIso->FaninSig == 0 ); + pIso->FaninSig = pIsoF->FaninSig; + +// assert( pIsoF->FanoutSig == 0 ); + pIsoF->FanoutSig += pIso->FanoutSig; + } +/* + Aig_ManForEachObj( pAig, pObj, i ) + { + pIso = p->pObjs + i; + Aig_ObjPrint( pAig, pObj ); + printf( "Lev = %4d. Pos = %4d. FaninSig = %10d. FanoutSig = %10d.\n", + pIso->Level, pIso->nFinNeg, pIso->FaninSig, pIso->FanoutSig ); + } +*/ + // add to the hash table + Aig_ManForEachObj( pAig, pObj, i ) + { + if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) ) + continue; + pIso = p->pObjs + i; + Iso_ObjHashAdd( p, pIso ); + } + // derive classes for the first time + Iso_ManCollectClasses( p ); + return p; +} + +/**Function************************************************************* + + Synopsis [Creates adjacency lists.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Iso_ManAssignAdjacency( Iso_Man_t * p ) +{ + int fUseXor = 0; + Iso_Obj_t * pIso, * pIsoF; + Aig_Obj_t * pObj, * pObjLi; + int i; + + // create TFI signatures + Aig_ManForEachObj( p->pAig, pObj, i ) + { + pIso = p->pObjs + i; + pIso->FaninSig = 0; + pIso->FanoutSig = 0; + + if ( Aig_ObjIsCo(pObj) ) + continue; + if ( fUseXor ) + { + if ( Aig_ObjIsNode(pObj) ) + { + pIsoF = p->pObjs + Aig_ObjFaninId0(pObj); + pIso->FaninSig ^= pIsoF->FaninSig; + if ( pIsoF->Id ) + pIso->FaninSig ^= s_1kPrimes[Abc_Var2Lit(pIsoF->Id, Aig_ObjFaninC0(pObj)) & ISO_MASK]; + + pIsoF = p->pObjs + Aig_ObjFaninId1(pObj); + pIso->FaninSig ^= pIsoF->FaninSig; + if ( pIsoF->Id ) + pIso->FaninSig ^= s_1kPrimes[Abc_Var2Lit(pIsoF->Id, Aig_ObjFaninC1(pObj)) & ISO_MASK]; + } + } + else + { + if ( Aig_ObjIsNode(pObj) ) + { + pIsoF = p->pObjs + Aig_ObjFaninId0(pObj); + pIso->FaninSig += pIsoF->FaninSig; + if ( pIsoF->Id ) + pIso->FaninSig += pIsoF->Id * s_1kPrimes[Abc_Var2Lit(pIsoF->Id, Aig_ObjFaninC0(pObj)) & ISO_MASK]; + + pIsoF = p->pObjs + Aig_ObjFaninId1(pObj); + pIso->FaninSig += pIsoF->FaninSig; + if ( pIsoF->Id ) + pIso->FaninSig += pIsoF->Id * s_1kPrimes[Abc_Var2Lit(pIsoF->Id, Aig_ObjFaninC1(pObj)) & ISO_MASK]; + } + } + } + // create TFO signatures + Aig_ManForEachObjReverse( p->pAig, pObj, i ) + { + if ( Aig_ObjIsCi(pObj) || Aig_ObjIsConst1(pObj) ) + continue; + pIso = p->pObjs + i; + assert( !Aig_ObjIsCo(pObj) || pIso->Id == 0 ); + if ( fUseXor ) + { + if ( Aig_ObjIsNode(pObj) ) + { + pIsoF = p->pObjs + Aig_ObjFaninId0(pObj); + pIsoF->FanoutSig ^= pIso->FanoutSig; + if ( pIso->Id ) + pIsoF->FanoutSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Id, Aig_ObjFaninC0(pObj)) & ISO_MASK]; + + pIsoF = p->pObjs + Aig_ObjFaninId1(pObj); + pIsoF->FanoutSig ^= pIso->FanoutSig; + if ( pIso->Id ) + pIsoF->FanoutSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Id, Aig_ObjFaninC1(pObj)) & ISO_MASK]; + } + else if ( Aig_ObjIsCo(pObj) ) + { + pIsoF = p->pObjs + Aig_ObjFaninId0(pObj); + pIsoF->FanoutSig ^= pIso->FanoutSig; + if ( pIso->Id ) + pIsoF->FanoutSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Id, Aig_ObjFaninC0(pObj)) & ISO_MASK]; + } + } + else + { + if ( Aig_ObjIsNode(pObj) ) + { + pIsoF = p->pObjs + Aig_ObjFaninId0(pObj); + pIsoF->FanoutSig += pIso->FanoutSig; + if ( pIso->Id ) + pIsoF->FanoutSig += pIso->Id * s_1kPrimes[Abc_Var2Lit(pIso->Id, Aig_ObjFaninC0(pObj)) & ISO_MASK]; + + pIsoF = p->pObjs + Aig_ObjFaninId1(pObj); + pIsoF->FanoutSig += pIso->FanoutSig; + if ( pIso->Id ) + pIsoF->FanoutSig += pIso->Id * s_1kPrimes[Abc_Var2Lit(pIso->Id, Aig_ObjFaninC1(pObj)) & ISO_MASK]; + } + else if ( Aig_ObjIsCo(pObj) ) + { + pIsoF = p->pObjs + Aig_ObjFaninId0(pObj); + pIsoF->FanoutSig += pIso->FanoutSig; + if ( pIso->Id ) + pIsoF->FanoutSig += pIso->Id * s_1kPrimes[Abc_Var2Lit(pIso->Id, Aig_ObjFaninC0(pObj)) & ISO_MASK]; + } + } + } + + // consider flops + Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObj, i ) + { + if ( Aig_ObjFaninId0(pObjLi) == 0 ) // ignore constant! + continue; + pIso = Iso_ManObj( p, Aig_ObjId(pObj) ); + pIsoF = Iso_ManObj( p, Aig_ObjFaninId0(pObjLi) ); + assert( pIso->FaninSig == 0 ); +// assert( pIsoF->FanoutSig == 0 ); + + if ( fUseXor ) + { + pIso->FaninSig = pIsoF->FaninSig; + if ( pIsoF->Id ) + pIso->FaninSig ^= s_1kPrimes[Abc_Var2Lit(pIsoF->Id, Aig_ObjFaninC0(pObjLi)) & ISO_MASK]; + + pIsoF->FanoutSig += pIso->FanoutSig; + if ( pIso->Id ) + pIsoF->FanoutSig ^= s_1kPrimes[Abc_Var2Lit(pIso->Id, Aig_ObjFaninC0(pObjLi)) & ISO_MASK]; + } + else + { + pIso->FaninSig = pIsoF->FaninSig; + if ( pIsoF->Id ) + pIso->FaninSig += pIsoF->Id * s_1kPrimes[Abc_Var2Lit(pIsoF->Id, Aig_ObjFaninC0(pObjLi)) & ISO_MASK]; + + pIsoF->FanoutSig += pIso->FanoutSig; + if ( pIso->Id ) + pIsoF->FanoutSig += pIso->Id * s_1kPrimes[Abc_Var2Lit(pIso->Id, Aig_ObjFaninC0(pObjLi)) & ISO_MASK]; + } + } +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Iso_ManPrintClasseSizes( Iso_Man_t * p ) +{ + Iso_Obj_t * pIso, * pTemp; + int i, Counter; + Vec_PtrForEachEntry( Iso_Obj_t *, p->vClasses, pIso, i ) + { + Counter = 0; + for ( pTemp = pIso; pTemp; pTemp = Iso_ManObj(p, pTemp->iClass) ) + Counter++; + printf( "%d ", Counter ); + } + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Iso_ManPrintClasses( Iso_Man_t * p, int fVerbose, int fVeryVerbose ) +{ + int fOnlyCis = 0; + Iso_Obj_t * pIso, * pTemp; + int i; + + // count unique objects + if ( fVerbose ) + printf( "Total objects =%7d. Entries =%7d. Classes =%7d. Singles =%7d.\n", + p->nObjs, p->nEntries, p->nClasses, p->nSingles ); + + if ( !fVeryVerbose ) + return; + + printf( "Non-trivial classes:\n" ); + Vec_PtrForEachEntry( Iso_Obj_t *, p->vClasses, pIso, i ) + { + if ( fOnlyCis && pIso->Level > 0 ) + continue; + + printf( "%5d : {", i ); + for ( pTemp = pIso; pTemp; pTemp = Iso_ManObj(p, pTemp->iClass) ) + { + if ( fOnlyCis ) + printf( " %d", Aig_ObjCioId( Iso_AigObj(p, pTemp) ) ); + else + { + Aig_Obj_t * pObj = Iso_AigObj(p, pTemp); + if ( Aig_ObjIsNode(pObj) ) + printf( " %d{%s%d(%d),%s%d(%d)}", Iso_ObjId(p, pTemp), + Aig_ObjFaninC0(pObj)? "-": "+", Aig_ObjFaninId0(pObj), Aig_ObjLevel(Aig_ObjFanin0(pObj)), + Aig_ObjFaninC1(pObj)? "-": "+", Aig_ObjFaninId1(pObj), Aig_ObjLevel(Aig_ObjFanin1(pObj)) ); + else + printf( " %d", Iso_ObjId(p, pTemp) ); + } + printf( "(%d)", pTemp->Level ); + } + printf( " }\n" ); + } +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Iso_ManRehashClassNodes( Iso_Man_t * p ) +{ + Iso_Obj_t * pIso, * pTemp; + int i; + // collect nodes + Vec_PtrClear( p->vTemp1 ); + Vec_PtrClear( p->vTemp2 ); + Vec_PtrForEachEntry( Iso_Obj_t *, p->vClasses, pIso, i ) + { + for ( pTemp = pIso; pTemp; pTemp = Iso_ManObj(p, pTemp->iClass) ) + if ( pTemp->Id == 0 ) + Vec_PtrPush( p->vTemp1, pTemp ); + else + Vec_PtrPush( p->vTemp2, pTemp ); + } + // clean and add nodes + p->nClasses = 0; // total number of classes + p->nEntries = 0; // total number of entries + p->nSingles = 0; // total number of singletons + memset( p->pBins, 0, sizeof(int) * p->nBins ); + Vec_PtrForEachEntry( Iso_Obj_t *, p->vTemp1, pTemp, i ) + { + assert( pTemp->Id == 0 ); + pTemp->iClass = pTemp->iNext = 0; + Iso_ObjHashAdd( p, pTemp ); + } + Vec_PtrForEachEntry( Iso_Obj_t *, p->vTemp2, pTemp, i ) + { + assert( pTemp->Id != 0 ); + pTemp->iClass = pTemp->iNext = 0; + } + // collect new classes + Iso_ManCollectClasses( p ); +} + +/**Function************************************************************* + + Synopsis [Find nodes with the min number of edges.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Iso_Obj_t * Iso_ManFindBestObj( Iso_Man_t * p, Iso_Obj_t * pIso ) +{ + Iso_Obj_t * pTemp, * pBest = NULL; + int nNodesBest = -1, nNodes; + int nEdgesBest = -1, nEdges; + assert( pIso->Id == 0 ); + if ( pIso->Level == 0 ) + return pIso; + for ( pTemp = pIso; pTemp; pTemp = Iso_ManObj(p, pTemp->iClass) ) + { + assert( pTemp->Id == 0 ); + Iso_ManObjCount( p->pAig, Iso_AigObj(p, pTemp), &nNodes, &nEdges ); +// printf( "%d,%d ", nNodes, nEdges ); + if ( nNodesBest < nNodes || (nNodesBest == nNodes && nEdgesBest < nEdges) ) + { + nNodesBest = nNodes; + nEdgesBest = nEdges; + pBest = pTemp; + } + } +// printf( "\n" ); + return pBest; +} + +/**Function************************************************************* + + Synopsis [Find nodes with the min number of edges.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Iso_ManBreakTies( Iso_Man_t * p, int fVerbose ) +{ + int fUseOneBest = 0; + Iso_Obj_t * pIso, * pTemp; + int i, LevelStart = 0; + pIso = (Iso_Obj_t *)Vec_PtrEntry( p->vClasses, 0 ); + LevelStart = pIso->Level; + if ( fVerbose ) + printf( "Best level %d\n", LevelStart ); + Vec_PtrForEachEntry( Iso_Obj_t *, p->vClasses, pIso, i ) + { + if ( (int)pIso->Level < LevelStart ) + break; + if ( !fUseOneBest ) + { + for ( pTemp = pIso; pTemp; pTemp = Iso_ManObj(p, pTemp->iClass) ) + { + assert( pTemp->Id == 0 ); + pTemp->Id = p->nObjIds++; + } + continue; + } + if ( pIso->Level == 0 )//&& pIso->nFoutPos + pIso->nFoutNeg == 0 ) + { + for ( pTemp = pIso; pTemp; pTemp = Iso_ManObj(p, pTemp->iClass) ) + pTemp->Id = p->nObjIds++; + continue; + } + pIso = Iso_ManFindBestObj( p, pIso ); + pIso->Id = p->nObjIds++; + } +} + +/**Function************************************************************* + + Synopsis [Finalizes unification of combinational outputs.] + + Description [Assigns IDs to the unclassified CIs in the order of obj IDs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Iso_ManFinalize( Iso_Man_t * p ) +{ + Vec_Int_t * vRes; + Aig_Obj_t * pObj; + int i; + assert( p->nClasses == 0 ); + assert( Vec_PtrSize(p->vClasses) == 0 ); + // set canonical numbers + Aig_ManForEachObj( p->pAig, pObj, i ) + { + if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) ) + { + pObj->iData = -1; + continue; + } + pObj->iData = Iso_ManObj(p, Aig_ObjId(pObj))->Id; + assert( pObj->iData > 0 ); + } + Aig_ManConst1(p->pAig)->iData = 0; + // assign unique IDs to the CIs + Vec_PtrClear( p->vTemp1 ); + Vec_PtrClear( p->vTemp2 ); + Aig_ManForEachCi( p->pAig, pObj, i ) + { + assert( pObj->iData > 0 ); + if ( Aig_ObjCioId(pObj) >= Aig_ManCiNum(p->pAig) - Aig_ManRegNum(p->pAig) ) // flop + Vec_PtrPush( p->vTemp2, pObj ); + else // PI + Vec_PtrPush( p->vTemp1, pObj ); + } + // sort CIs by their IDs + Vec_PtrSort( p->vTemp1, (int (*)(const void *, const void *))Iso_ObjCompareByData ); + Vec_PtrSort( p->vTemp2, (int (*)(const void *, const void *))Iso_ObjCompareByData ); + // create the result + vRes = Vec_IntAlloc( Aig_ManCiNum(p->pAig) ); + Vec_PtrForEachEntry( Aig_Obj_t *, p->vTemp1, pObj, i ) + Vec_IntPush( vRes, Aig_ObjCioId(pObj) ); + Vec_PtrForEachEntry( Aig_Obj_t *, p->vTemp2, pObj, i ) + Vec_IntPush( vRes, Aig_ObjCioId(pObj) ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [Find nodes with the min number of edges.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Iso_ManDumpOneClass( Iso_Man_t * p ) +{ + Vec_Ptr_t * vNodes = Vec_PtrAlloc( 100 ); + Iso_Obj_t * pIso, * pTemp; + Aig_Man_t * pNew = NULL; + assert( p->nClasses > 0 ); + pIso = (Iso_Obj_t *)Vec_PtrEntry( p->vClasses, 0 ); + assert( pIso->Id == 0 ); + for ( pTemp = pIso; pTemp; pTemp = Iso_ManObj(p, pTemp->iClass) ) + { + assert( pTemp->Id == 0 ); + Vec_PtrPush( vNodes, Iso_AigObj(p, pTemp) ); + } + pNew = Aig_ManDupNodes( p->pAig, vNodes ); + Vec_PtrFree( vNodes ); + Aig_ManShow( pNew, 0, NULL ); + Aig_ManStopP( &pNew ); +} + +/**Function************************************************************* + + Synopsis [Finds canonical permutation of CIs and assigns unique IDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_ManFindIsoPerm( Aig_Man_t * pAig, int fVerbose ) +{ + int fVeryVerbose = 0; + Vec_Int_t * vRes; + Iso_Man_t * p; + abctime clk = Abc_Clock(), clk2 = Abc_Clock(); + p = Iso_ManCreate( pAig ); + p->timeFout += Abc_Clock() - clk; + Iso_ManPrintClasses( p, fVerbose, fVeryVerbose ); + while ( p->nClasses ) + { + // assign adjacency to classes + clk = Abc_Clock(); + Iso_ManAssignAdjacency( p ); + p->timeFout += Abc_Clock() - clk; + // rehash the class nodes + clk = Abc_Clock(); + Iso_ManRehashClassNodes( p ); + p->timeHash += Abc_Clock() - clk; + Iso_ManPrintClasses( p, fVerbose, fVeryVerbose ); + // force refinement + while ( p->nSingles == 0 && p->nClasses ) + { +// Iso_ManPrintClasseSizes( p ); + // assign IDs to the topmost level of classes + Iso_ManBreakTies( p, fVerbose ); + // assign adjacency to classes + clk = Abc_Clock(); + Iso_ManAssignAdjacency( p ); + p->timeFout += Abc_Clock() - clk; + // rehash the class nodes + clk = Abc_Clock(); + Iso_ManRehashClassNodes( p ); + p->timeHash += Abc_Clock() - clk; + Iso_ManPrintClasses( p, fVerbose, fVeryVerbose ); + } + } + p->timeTotal = Abc_Clock() - clk2; +// printf( "IDs assigned = %d. Objects = %d.\n", p->nObjIds, 1+Aig_ManCiNum(p->pAig)+Aig_ManNodeNum(p->pAig) ); + assert( p->nObjIds == 1+Aig_ManCiNum(p->pAig)+Aig_ManNodeNum(p->pAig) ); +// if ( p->nClasses ) +// Iso_ManDumpOneClass( p ); + vRes = Iso_ManFinalize( p ); + Iso_ManStop( p, fVerbose ); + return vRes; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigMiter.c b/yosys/abc/src/aig/saig/saigMiter.c new file mode 100644 index 00000000000..5b15f932931 --- /dev/null +++ b/yosys/abc/src/aig/saig/saigMiter.c @@ -0,0 +1,1317 @@ +/**CFile**************************************************************** + + FileName [saigMiter.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Computes sequential miter of two sequential AIGs.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigMiter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" +#include "proof/fra/fra.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks the status of the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Sec_MtrStatus_t Sec_MiterStatus( Aig_Man_t * p ) +{ + Sec_MtrStatus_t Status; + Aig_Obj_t * pObj, * pChild; + int i; + memset( &Status, 0, sizeof(Sec_MtrStatus_t) ); + Status.iOut = -1; + Status.nInputs = Saig_ManPiNum( p ); + Status.nNodes = Aig_ManNodeNum( p ); + Status.nOutputs = Saig_ManPoNum(p); + Saig_ManForEachPo( p, pObj, i ) + { + pChild = Aig_ObjChild0(pObj); + // check if the output is constant 0 + if ( pChild == Aig_ManConst0(p) ) + Status.nUnsat++; + // check if the output is constant 1 + else if ( pChild == Aig_ManConst1(p) ) + { + Status.nSat++; + if ( Status.iOut == -1 ) + Status.iOut = i; + } + // check if the output is a primary input + else if ( Saig_ObjIsPi(p, Aig_Regular(pChild)) ) + { + Status.nSat++; + if ( Status.iOut == -1 ) + Status.iOut = i; + } + // check if the output is 1 for the 0000 pattern + else if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) ) + { + Status.nSat++; + if ( Status.iOut == -1 ) + Status.iOut = i; + } + else + Status.nUndec++; + } + return Status; +} + +/**Function************************************************************* + + Synopsis [Creates sequential miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManCreateMiter( Aig_Man_t * p0, Aig_Man_t * p1, int Oper ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj; + int i; + assert( Saig_ManRegNum(p0) > 0 || Saig_ManRegNum(p1) > 0 ); + assert( Saig_ManPiNum(p0) == Saig_ManPiNum(p1) ); + assert( Saig_ManPoNum(p0) == Saig_ManPoNum(p1) ); + pNew = Aig_ManStart( Aig_ManObjNumMax(p0) + Aig_ManObjNumMax(p1) ); + pNew->pName = Abc_UtilStrsav( "miter" ); + Aig_ManCleanData( p0 ); + Aig_ManCleanData( p1 ); + // map constant nodes + Aig_ManConst1(p0)->pData = Aig_ManConst1(pNew); + Aig_ManConst1(p1)->pData = Aig_ManConst1(pNew); + // map primary inputs + Saig_ManForEachPi( p0, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pNew ); + Saig_ManForEachPi( p1, pObj, i ) + pObj->pData = Aig_ManCi( pNew, i ); + // map register outputs + Saig_ManForEachLo( p0, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pNew ); + Saig_ManForEachLo( p1, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pNew ); + // map internal nodes + Aig_ManForEachNode( p0, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + Aig_ManForEachNode( p1, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // create primary outputs + Saig_ManForEachPo( p0, pObj, i ) + { + if ( Oper == 0 ) // XOR + pObj = Aig_Exor( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild0Copy(Aig_ManCo(p1,i)) ); + else if ( Oper == 1 ) // implication is PO(p0) -> PO(p1) ... complement is PO(p0) & !PO(p1) + pObj = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_Not(Aig_ObjChild0Copy(Aig_ManCo(p1,i))) ); + else + assert( 0 ); + Aig_ObjCreateCo( pNew, pObj ); + } + // create register inputs + Saig_ManForEachLi( p0, pObj, i ) + pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + Saig_ManForEachLi( p1, pObj, i ) + pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + // cleanup + Aig_ManSetRegNum( pNew, Saig_ManRegNum(p0) + Saig_ManRegNum(p1) ); +// Aig_ManCleanup( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Creates combinational miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManCreateMiterComb( Aig_Man_t * p0, Aig_Man_t * p1, int Oper ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj; + int i; + assert( Aig_ManCiNum(p0) == Aig_ManCiNum(p1) ); + assert( Aig_ManCoNum(p0) == Aig_ManCoNum(p1) ); + pNew = Aig_ManStart( Aig_ManObjNumMax(p0) + Aig_ManObjNumMax(p1) ); + pNew->pName = Abc_UtilStrsav( "miter" ); + // map constant nodes + Aig_ManConst1(p0)->pData = Aig_ManConst1(pNew); + Aig_ManConst1(p1)->pData = Aig_ManConst1(pNew); + // map primary inputs and register outputs + Aig_ManForEachCi( p0, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pNew ); + Aig_ManForEachCi( p1, pObj, i ) + pObj->pData = Aig_ManCi( pNew, i ); + // map internal nodes + Aig_ManForEachNode( p0, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + Aig_ManForEachNode( p1, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // create primary outputs + Aig_ManForEachCo( p0, pObj, i ) + { + if ( Oper == 0 ) // XOR + pObj = Aig_Exor( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild0Copy(Aig_ManCo(p1,i)) ); + else if ( Oper == 1 ) // implication is PO(p0) -> PO(p1) ... complement is PO(p0) & !PO(p1) + pObj = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_Not(Aig_ObjChild0Copy(Aig_ManCo(p1,i))) ); + else + assert( 0 ); + Aig_ObjCreateCo( pNew, pObj ); + } + // cleanup + Aig_ManSetRegNum( pNew, 0 ); + Aig_ManCleanup( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Derives dual-rail AIG.] + + Description [Orders nodes as follows: PIs, ANDs, POs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_AndDualRail( Aig_Man_t * pNew, Aig_Obj_t * pObj, Aig_Obj_t ** ppData, Aig_Obj_t ** ppNext ) +{ + Aig_Obj_t * pFanin0 = Aig_ObjFanin0(pObj); + Aig_Obj_t * pFanin1 = Aig_ObjFanin1(pObj); + Aig_Obj_t * p0Data = Aig_ObjFaninC0(pObj)? pFanin0->pNext : (Aig_Obj_t *)pFanin0->pData; + Aig_Obj_t * p0Next = Aig_ObjFaninC0(pObj)? (Aig_Obj_t *)pFanin0->pData : pFanin0->pNext; + Aig_Obj_t * p1Data = Aig_ObjFaninC1(pObj)? pFanin1->pNext : (Aig_Obj_t *)pFanin1->pData; + Aig_Obj_t * p1Next = Aig_ObjFaninC1(pObj)? (Aig_Obj_t *)pFanin1->pData : pFanin1->pNext; + *ppData = Aig_Or( pNew, + Aig_And(pNew, p0Data, Aig_Not(p0Next)), + Aig_And(pNew, p1Data, Aig_Not(p1Next)) ); + *ppNext = Aig_And( pNew, + Aig_And(pNew, Aig_Not(p0Data), p0Next), + Aig_And(pNew, Aig_Not(p1Data), p1Next) ); +} + +/**Function************************************************************* + + Synopsis [Derives dual-rail AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManDualRail( Aig_Man_t * p, int fMiter ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pMiter; + int i; + Aig_ManCleanData( p ); + Aig_ManCleanNext( p ); + // create the new manager + pNew = Aig_ManStart( 4*Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + // create the PIs + Aig_ManConst1(p)->pData = Aig_ManConst0(pNew); + Aig_ManConst1(p)->pNext = Aig_ManConst1(pNew); + Aig_ManForEachCi( p, pObj, i ) + { + pObj->pData = Aig_ObjCreateCi( pNew ); + pObj->pNext = Aig_ObjCreateCi( pNew ); + } + // duplicate internal nodes + Aig_ManForEachNode( p, pObj, i ) + Saig_AndDualRail( pNew, pObj, (Aig_Obj_t **)&pObj->pData, &pObj->pNext ); + // add the POs + if ( fMiter ) + { + pMiter = Aig_ManConst1(pNew); + Saig_ManForEachLo( p, pObj, i ) + { + pMiter = Aig_And( pNew, pMiter, + Aig_Or(pNew, (Aig_Obj_t *)pObj->pData, pObj->pNext) ); + } + Aig_ObjCreateCo( pNew, pMiter ); + Saig_ManForEachLi( p, pObj, i ) + { + if ( !Aig_ObjFaninC0(pObj) ) + { + Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); + Aig_ObjCreateCo( pNew, Aig_ObjFanin0(pObj)->pNext ); + } + else + { + Aig_ObjCreateCo( pNew, Aig_ObjFanin0(pObj)->pNext ); + Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); + } + } + } + else + { + Aig_ManForEachCo( p, pObj, i ) + { + if ( !Aig_ObjFaninC0(pObj) ) + { + Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); + Aig_ObjCreateCo( pNew, Aig_ObjFanin0(pObj)->pNext ); + } + else + { + Aig_ObjCreateCo( pNew, Aig_ObjFanin0(pObj)->pNext ); + Aig_ObjCreateCo( pNew, (Aig_Obj_t *)Aig_ObjFanin0(pObj)->pData ); + } + } + } + Aig_ManSetRegNum( pNew, 2*Aig_ManRegNum(p) ); + Aig_ManCleanData( p ); + Aig_ManCleanNext( p ); + Aig_ManCleanup( pNew ); + // check the resulting network + if ( !Aig_ManCheck(pNew) ) + printf( "Aig_ManDupSimple(): The check has failed.\n" ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Create combinational timeframes by unrolling sequential circuits.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManUnrollTwo( Aig_Man_t * pBot, Aig_Man_t * pTop, int nFrames ) +{ + Aig_Man_t * p, * pAig; + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int i, f; +// assert( nFrames > 1 ); + assert( Saig_ManPiNum(pBot) == Saig_ManPiNum(pTop) ); + assert( Saig_ManPoNum(pBot) == Saig_ManPoNum(pTop) ); + assert( Saig_ManRegNum(pBot) == Saig_ManRegNum(pTop) ); + assert( Saig_ManRegNum(pBot) > 0 || Saig_ManRegNum(pTop) > 0 ); + // start timeframes + p = Aig_ManStart( nFrames * Abc_MaxInt(Aig_ManObjNumMax(pBot), Aig_ManObjNumMax(pTop)) ); + p->pName = Abc_UtilStrsav( "frames" ); + // create variables for register outputs + pAig = pBot; + Saig_ManForEachLo( pAig, pObj, i ) + pObj->pData = Aig_ObjCreateCi( p ); + // add timeframes + for ( f = 0; f < nFrames; f++ ) + { + // create PI nodes for this frame + Aig_ManConst1(pAig)->pData = Aig_ManConst1( p ); + Saig_ManForEachPi( pAig, pObj, i ) + pObj->pData = Aig_ObjCreateCi( p ); + // add internal nodes of this frame + Aig_ManForEachNode( pAig, pObj, i ) + pObj->pData = Aig_And( p, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + if ( f == nFrames - 1 ) + { + // create POs for this frame + Aig_ManForEachCo( pAig, pObj, i ) + Aig_ObjCreateCo( p, Aig_ObjChild0Copy(pObj) ); + break; + } + // create POs for this frame + Saig_ManForEachPo( pAig, pObj, i ) + Aig_ObjCreateCo( p, Aig_ObjChild0Copy(pObj) ); + // save register inputs + Saig_ManForEachLi( pAig, pObj, i ) + pObj->pData = Aig_ObjChild0Copy(pObj); + // transfer to register outputs + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + pObjLo->pData = pObjLi->pData; + if ( f == 0 ) + { + // transfer from pOld to pNew + Saig_ManForEachLo( pAig, pObj, i ) + Saig_ManLo(pTop, i)->pData = pObj->pData; + pAig = pTop; + } + } + Aig_ManCleanup( p ); + return p; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG while creating POs from the set.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupNodesAll( Aig_Man_t * p, Vec_Ptr_t * vSet ) +{ + Aig_Man_t * pNew, * pCopy; + Aig_Obj_t * pObj; + int i; + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Aig_ManForEachCi( p, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pNew ); + Aig_ManForEachNode( p, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); +// Saig_ManForEachPo( p, pObj, i ) +// pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + Vec_PtrForEachEntry( Aig_Obj_t *, vSet, pObj, i ) + Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_Regular(pObj)->pData, Aig_IsComplement(pObj)) ); + Saig_ManForEachLi( p, pObj, i ) + pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + Aig_ManSetRegNum( pNew, Saig_ManRegNum(p) ); + // cleanup and return a copy + Aig_ManSeqCleanup( pNew ); + pCopy = Aig_ManDupSimpleDfs( pNew ); + Aig_ManStop( pNew ); + return pCopy; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG while creating POs from the set.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Aig_ManDupNodesHalf( Aig_Man_t * p, Vec_Ptr_t * vSet, int iPart ) +{ + Aig_Man_t * pNew, * pCopy; + Aig_Obj_t * pObj; + int i; + Aig_ManCleanData( p ); + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Saig_ManForEachPi( p, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pNew ); + if ( iPart == 0 ) + { + Saig_ManForEachLo( p, pObj, i ) + if ( i < Saig_ManRegNum(p)/2 ) + pObj->pData = Aig_ObjCreateCi( pNew ); + } + else + { + Saig_ManForEachLo( p, pObj, i ) + if ( i >= Saig_ManRegNum(p)/2 ) + pObj->pData = Aig_ObjCreateCi( pNew ); + } + Aig_ManForEachNode( p, pObj, i ) + if ( Aig_ObjFanin0(pObj)->pData && Aig_ObjFanin1(pObj)->pData ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); +// Saig_ManForEachPo( p, pObj, i ) +// pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + Vec_PtrForEachEntry( Aig_Obj_t *, vSet, pObj, i ) + { + assert( Aig_Regular(pObj)->pData != NULL ); + Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)Aig_Regular(pObj)->pData, Aig_IsComplement(pObj)) ); + } + if ( iPart == 0 ) + { + Saig_ManForEachLi( p, pObj, i ) + if ( i < Saig_ManRegNum(p)/2 ) + pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + } + else + { + Saig_ManForEachLi( p, pObj, i ) + if ( i >= Saig_ManRegNum(p)/2 ) + pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + } + Aig_ManSetRegNum( pNew, Saig_ManRegNum(p)/2 ); + // cleanup and return a copy +// Aig_ManSeqCleanup( pNew ); + Aig_ManCleanup( pNew ); + pCopy = Aig_ManDupSimpleDfs( pNew ); + Aig_ManStop( pNew ); + return pCopy; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG to have constant-0 initial state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManDemiterSimple( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 ) +{ + Vec_Ptr_t * vSet0, * vSet1; + Aig_Obj_t * pObj, * pFanin, * pObj0, * pObj1; + int i, Counter = 0; + assert( Saig_ManRegNum(p) % 2 == 0 ); + vSet0 = Vec_PtrAlloc( Saig_ManPoNum(p) ); + vSet1 = Vec_PtrAlloc( Saig_ManPoNum(p) ); + Saig_ManForEachPo( p, pObj, i ) + { + pFanin = Aig_ObjFanin0(pObj); + if ( Aig_ObjIsConst1( pFanin ) ) + { + if ( !Aig_ObjFaninC0(pObj) ) + printf( "The output number %d of the miter is constant 1.\n", i ); + Counter++; + continue; + } + if ( !Aig_ObjIsNode(pFanin) || !Aig_ObjRecognizeExor( pFanin, &pObj0, &pObj1 ) ) + { + printf( "The miter cannot be demitered.\n" ); + Vec_PtrFree( vSet0 ); + Vec_PtrFree( vSet1 ); + return 0; + } + if ( Aig_ObjFaninC0(pObj) ) + pObj0 = Aig_Not(pObj0); + +// printf( "%d %d ", Aig_Regular(pObj0)->Id, Aig_Regular(pObj1)->Id ); + if ( Aig_Regular(pObj0)->Id < Aig_Regular(pObj1)->Id ) + { + Vec_PtrPush( vSet0, pObj0 ); + Vec_PtrPush( vSet1, pObj1 ); + } + else + { + Vec_PtrPush( vSet0, pObj1 ); + Vec_PtrPush( vSet1, pObj0 ); + } + } +// printf( "Miter has %d constant outputs.\n", Counter ); +// printf( "\n" ); + if ( ppAig0 ) + { + *ppAig0 = Aig_ManDupNodesHalf( p, vSet0, 0 ); + ABC_FREE( (*ppAig0)->pName ); + (*ppAig0)->pName = Abc_UtilStrsav( "part0" ); + } + if ( ppAig1 ) + { + *ppAig1 = Aig_ManDupNodesHalf( p, vSet1, 1 ); + ABC_FREE( (*ppAig1)->pName ); + (*ppAig1)->pName = Abc_UtilStrsav( "part1" ); + } + Vec_PtrFree( vSet0 ); + Vec_PtrFree( vSet1 ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if PO can be demitered.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManDemiterMarkPos( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManCleanMarkAB( p ); + Saig_ManForEachLo( p, pObj, i ) + if ( i < Saig_ManRegNum(p)/2 ) + pObj->fMarkA = 1; + else + pObj->fMarkB = 1; + Aig_ManForEachNode( p, pObj, i ) + { + pObj->fMarkA = Aig_ObjFanin0(pObj)->fMarkA | Aig_ObjFanin1(pObj)->fMarkA; + pObj->fMarkB = Aig_ObjFanin0(pObj)->fMarkB | Aig_ObjFanin1(pObj)->fMarkB; + } +} + +/**Function************************************************************* + + Synopsis [Returns 1 if PO can be demitered.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManDemiterCheckPo( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t ** ppPo0, Aig_Obj_t ** ppPo1 ) +{ + Aig_Obj_t * pFanin, * pObj0, * pObj1, * pObjR0, * pObjR1; + assert( Saig_ObjIsPo(p, pObj) ); + pFanin = Aig_ObjFanin0( pObj ); + if ( Aig_ObjIsConst1(pFanin) ) + { + if ( !Aig_ObjFaninC0(pObj) ) + return 0; + *ppPo0 = Aig_ManConst0(p); + *ppPo1 = Aig_ManConst0(p); + return 1; + } + if ( !Aig_ObjIsNode(pFanin) ) + return 0; + if ( !Aig_ObjRecognizeExor( pFanin, &pObj0, &pObj1 ) ) + return 0; + if ( Aig_ObjFaninC0(pObj) ) + pObj0 = Aig_Not(pObj0); + // make sure they can reach only one + pObjR0 = Aig_Regular(pObj0); + pObjR1 = Aig_Regular(pObj1); + if ( (pObjR0->fMarkA && pObjR0->fMarkB) || (pObjR1->fMarkA && pObjR1->fMarkB) || + (pObjR0->fMarkA && pObjR1->fMarkA) || (pObjR0->fMarkB && pObjR1->fMarkB) ) + return 0; + + if ( pObjR1->fMarkA && !pObjR0->fMarkA ) + { + *ppPo0 = pObj1; + *ppPo1 = pObj0; + } + else if ( pObjR0->fMarkA && !pObjR1->fMarkA ) + { + *ppPo0 = pObj0; + *ppPo1 = pObj1; + } + else + { +/* +printf( "%d", pObjR0->fMarkA ); +printf( "%d", pObjR0->fMarkB ); +printf( ":" ); +printf( "%d", pObjR1->fMarkA ); +printf( "%d", pObjR1->fMarkB ); +printf( " " ); +*/ + if ( Aig_Regular(pObj0)->Id < Aig_Regular(pObj1)->Id ) + { + *ppPo0 = pObj0; + *ppPo1 = pObj1; + } + else + { + *ppPo0 = pObj1; + *ppPo1 = pObj0; + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if AIG can be demitered.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManDemiterSimpleDiff( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 ) +{ + Vec_Ptr_t * vSet0, * vSet1; + Aig_Obj_t * pObj, * pObj0, * pObj1; + int i; + if ( Aig_ManRegNum(p) == 0 || (Aig_ManRegNum(p) & 1) ) + return 0; + Saig_ManDemiterMarkPos( p ); + vSet0 = Vec_PtrAlloc( Saig_ManPoNum(p) ); + vSet1 = Vec_PtrAlloc( Saig_ManPoNum(p) ); + Saig_ManForEachPo( p, pObj, i ) + { + if ( !Saig_ManDemiterCheckPo( p, pObj, &pObj0, &pObj1 ) ) + { + Vec_PtrFree( vSet0 ); + Vec_PtrFree( vSet1 ); + Aig_ManCleanMarkAB( p ); + return 0; + } + Vec_PtrPush( vSet0, pObj0 ); + Vec_PtrPush( vSet1, pObj1 ); + } + // create new AIG + *ppAig0 = Aig_ManDupNodesHalf( p, vSet0, 0 ); + ABC_FREE( (*ppAig0)->pName ); + (*ppAig0)->pName = Abc_UtilStrsav( "part0" ); + // create new AIGs + *ppAig1 = Aig_ManDupNodesHalf( p, vSet1, 1 ); + ABC_FREE( (*ppAig1)->pName ); + (*ppAig1)->pName = Abc_UtilStrsav( "part1" ); + // cleanup + Vec_PtrFree( vSet0 ); + Vec_PtrFree( vSet1 ); + Aig_ManCleanMarkAB( p ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if AIG can be demitered.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManDemiterDual( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 ) +{ + Aig_Man_t * pTemp; + Aig_Obj_t * pObj; + int i, k; + + if ( p->pFanData ) + Aig_ManFanoutStop( p ); + + k = 0; + pTemp = Aig_ManDupSimple( p ); + Saig_ManForEachPo( pTemp, pObj, i ) + { + if ( i & 1 ) + Aig_ObjDeletePo( pTemp, pObj ); + else + Vec_PtrWriteEntry( pTemp->vCos, k++, pObj ); + } + Saig_ManForEachLi( pTemp, pObj, i ) + Vec_PtrWriteEntry( pTemp->vCos, k++, pObj ); + Vec_PtrShrink( pTemp->vCos, k ); + pTemp->nTruePos = k - Saig_ManRegNum(pTemp); + Aig_ManSeqCleanup( pTemp ); + *ppAig0 = Aig_ManDupSimple( pTemp ); + Aig_ManStop( pTemp ); + + k = 0; + pTemp = Aig_ManDupSimple( p ); + Saig_ManForEachPo( pTemp, pObj, i ) + { + if ( i & 1 ) + Vec_PtrWriteEntry( pTemp->vCos, k++, pObj ); + else + Aig_ObjDeletePo( pTemp, pObj ); + } + Saig_ManForEachLi( pTemp, pObj, i ) + Vec_PtrWriteEntry( pTemp->vCos, k++, pObj ); + Vec_PtrShrink( pTemp->vCos, k ); + pTemp->nTruePos = k - Saig_ManRegNum(pTemp); + Aig_ManSeqCleanup( pTemp ); + *ppAig1 = Aig_ManDupSimple( pTemp ); + Aig_ManStop( pTemp ); + + return 1; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG to have constant-0 initial state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManDemiterSimpleDiff_old( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 ) +{ + Vec_Ptr_t * vSet0, * vSet1; + Aig_Obj_t * pObj, * pFanin, * pObj0, * pObj1; + int i, Counter = 0; +// assert( Saig_ManRegNum(p) % 2 == 0 ); + vSet0 = Vec_PtrAlloc( Saig_ManPoNum(p) ); + vSet1 = Vec_PtrAlloc( Saig_ManPoNum(p) ); + Saig_ManForEachPo( p, pObj, i ) + { + pFanin = Aig_ObjFanin0(pObj); + if ( Aig_ObjIsConst1( pFanin ) ) + { + if ( !Aig_ObjFaninC0(pObj) ) + printf( "The output number %d of the miter is constant 1.\n", i ); + Counter++; + continue; + } + if ( !Aig_ObjIsNode(pFanin) || !Aig_ObjRecognizeExor( pFanin, &pObj0, &pObj1 ) ) + { +/* + printf( "The miter cannot be demitered.\n" ); + Vec_PtrFree( vSet0 ); + Vec_PtrFree( vSet1 ); + return 0; +*/ + printf( "The output number %d cannot be demitered.\n", i ); + continue; + } + if ( Aig_ObjFaninC0(pObj) ) + pObj0 = Aig_Not(pObj0); + +// printf( "%d %d ", Aig_Regular(pObj0)->Id, Aig_Regular(pObj1)->Id ); + if ( Aig_Regular(pObj0)->Id < Aig_Regular(pObj1)->Id ) + { + Vec_PtrPush( vSet0, pObj0 ); + Vec_PtrPush( vSet1, pObj1 ); + } + else + { + Vec_PtrPush( vSet0, pObj1 ); + Vec_PtrPush( vSet1, pObj0 ); + } + } +// printf( "Miter has %d constant outputs.\n", Counter ); +// printf( "\n" ); + if ( ppAig0 ) + { + *ppAig0 = Aig_ManDupNodesAll( p, vSet0 ); + ABC_FREE( (*ppAig0)->pName ); + (*ppAig0)->pName = Abc_UtilStrsav( "part0" ); + } + if ( ppAig1 ) + { + *ppAig1 = Aig_ManDupNodesAll( p, vSet1 ); + ABC_FREE( (*ppAig1)->pName ); + (*ppAig1)->pName = Abc_UtilStrsav( "part1" ); + } + Vec_PtrFree( vSet0 ); + Vec_PtrFree( vSet1 ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Labels logic reachable from the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManDemiterLabel_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int Value ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Value ) + pObj->fMarkB = 1; + else + pObj->fMarkA = 1; + if ( Saig_ObjIsPi(p, pObj) ) + return; + if ( Saig_ObjIsLo(p, pObj) ) + { + Saig_ManDemiterLabel_rec( p, Aig_ObjFanin0( Saig_ObjLoToLi(p, pObj) ), Value ); + return; + } + assert( Aig_ObjIsNode(pObj) ); + Saig_ManDemiterLabel_rec( p, Aig_ObjFanin0(pObj), Value ); + Saig_ManDemiterLabel_rec( p, Aig_ObjFanin1(pObj), Value ); +} + +/**Function************************************************************* + + Synopsis [Returns the first labeled register encountered during traversal.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Saig_ManGetLabeledRegister_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pResult; + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return NULL; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Saig_ObjIsPi(p, pObj) ) + return NULL; + if ( Saig_ObjIsLo(p, pObj) ) + { + if ( pObj->fMarkA || pObj->fMarkB ) + return pObj; + return Saig_ManGetLabeledRegister_rec( p, Aig_ObjFanin0( Saig_ObjLoToLi(p, pObj) ) ); + } + assert( Aig_ObjIsNode(pObj) ); + pResult = Saig_ManGetLabeledRegister_rec( p, Aig_ObjFanin0(pObj) ); + if ( pResult ) + return pResult; + return Saig_ManGetLabeledRegister_rec( p, Aig_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG to have constant-0 initial state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManDemiter( Aig_Man_t * p, Aig_Man_t ** ppAig0, Aig_Man_t ** ppAig1 ) +{ + Vec_Ptr_t * vPairs, * vSet0, * vSet1; + Aig_Obj_t * pObj, * pObj0, * pObj1, * pFlop0, * pFlop1; + int i, Counter; + assert( Saig_ManRegNum(p) > 0 ); + Aig_ManSetCioIds( p ); + // check if demitering is possible + vPairs = Vec_PtrAlloc( 2 * Saig_ManPoNum(p) ); + Saig_ManForEachPo( p, pObj, i ) + { + if ( !Aig_ObjRecognizeExor( Aig_ObjFanin0(pObj), &pObj0, &pObj1 ) ) + { + Vec_PtrFree( vPairs ); + return 0; + } + Vec_PtrPush( vPairs, pObj0 ); + Vec_PtrPush( vPairs, pObj1 ); + } + // start array of outputs + vSet0 = Vec_PtrAlloc( Saig_ManPoNum(p) ); + vSet1 = Vec_PtrAlloc( Saig_ManPoNum(p) ); + // get the first pair of outputs + pObj0 = (Aig_Obj_t *)Vec_PtrEntry( vPairs, 0 ); + pObj1 = (Aig_Obj_t *)Vec_PtrEntry( vPairs, 1 ); + // label registers reachable from the outputs + Aig_ManIncrementTravId( p ); + Saig_ManDemiterLabel_rec( p, Aig_Regular(pObj0), 0 ); + Vec_PtrPush( vSet0, pObj0 ); + Aig_ManIncrementTravId( p ); + Saig_ManDemiterLabel_rec( p, Aig_Regular(pObj1), 1 ); + Vec_PtrPush( vSet1, pObj1 ); + // find where each output belongs + for ( i = 2; i < Vec_PtrSize(vPairs); i += 2 ) + { + pObj0 = (Aig_Obj_t *)Vec_PtrEntry( vPairs, i ); + pObj1 = (Aig_Obj_t *)Vec_PtrEntry( vPairs, i+1 ); + + Aig_ManIncrementTravId( p ); + pFlop0 = Saig_ManGetLabeledRegister_rec( p, Aig_Regular(pObj0) ); + + Aig_ManIncrementTravId( p ); + pFlop1 = Saig_ManGetLabeledRegister_rec( p, Aig_Regular(pObj1) ); + + if ( (pFlop0->fMarkA && pFlop0->fMarkB) || (pFlop1->fMarkA && pFlop1->fMarkB) || + (pFlop0->fMarkA && pFlop1->fMarkA) || (pFlop0->fMarkB && pFlop1->fMarkB) ) + printf( "Output pair %4d: Difficult case...\n", i/2 ); + + if ( pFlop0->fMarkB ) + { + Saig_ManDemiterLabel_rec( p, pObj0, 1 ); + Vec_PtrPush( vSet0, pObj0 ); + } + else // if ( pFlop0->fMarkA ) or none + { + Saig_ManDemiterLabel_rec( p, pObj0, 0 ); + Vec_PtrPush( vSet1, pObj0 ); + } + + if ( pFlop1->fMarkB ) + { + Saig_ManDemiterLabel_rec( p, pObj1, 1 ); + Vec_PtrPush( vSet0, pObj1 ); + } + else // if ( pFlop1->fMarkA ) or none + { + Saig_ManDemiterLabel_rec( p, pObj1, 0 ); + Vec_PtrPush( vSet1, pObj1 ); + } + } + // check if there are any flops in common + Counter = 0; + Saig_ManForEachLo( p, pObj, i ) + if ( pObj->fMarkA && pObj->fMarkB ) + Counter++; + if ( Counter > 0 ) + printf( "The miters contains %d flops reachable from both AIGs.\n", Counter ); + + // produce two miters + if ( ppAig0 ) + { + assert( 0 ); + *ppAig0 = Aig_ManDupNodesHalf( p, vSet0, 0 ); // not ready + ABC_FREE( (*ppAig0)->pName ); + (*ppAig0)->pName = Abc_UtilStrsav( "part0" ); + } + if ( ppAig1 ) + { + assert( 0 ); + *ppAig1 = Aig_ManDupNodesHalf( p, vSet1, 1 ); // not ready + ABC_FREE( (*ppAig1)->pName ); + (*ppAig1)->pName = Abc_UtilStrsav( "part1" ); + } + Vec_PtrFree( vSet0 ); + Vec_PtrFree( vSet1 ); + Vec_PtrFree( vPairs ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Create specialized miter by unrolling two circuits.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManCreateMiterTwo( Aig_Man_t * pOld, Aig_Man_t * pNew, int nFrames ) +{ + Aig_Man_t * pFrames0, * pFrames1, * pMiter; +// assert( Aig_ManNodeNum(pOld) <= Aig_ManNodeNum(pNew) ); + pFrames0 = Saig_ManUnrollTwo( pOld, pOld, nFrames ); + pFrames1 = Saig_ManUnrollTwo( pNew, pOld, nFrames ); + pMiter = Saig_ManCreateMiterComb( pFrames0, pFrames1, 0 ); + Aig_ManStop( pFrames0 ); + Aig_ManStop( pFrames1 ); + return pMiter; +} + + +/**Function************************************************************* + + Synopsis [Resimulates counter-example and returns the failed output number.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SecCexResimulate( Aig_Man_t * p, int * pModel, int * pnOutputs ) +{ + Aig_Obj_t * pObj; + int i, RetValue = -1; + *pnOutputs = 0; + Aig_ManConst1(p)->fMarkA = 1; + Aig_ManForEachCi( p, pObj, i ) + pObj->fMarkA = pModel[i]; + Aig_ManForEachNode( p, pObj, i ) + pObj->fMarkA = ( Aig_ObjFanin0(pObj)->fMarkA ^ Aig_ObjFaninC0(pObj) ) & + ( Aig_ObjFanin1(pObj)->fMarkA ^ Aig_ObjFaninC1(pObj) ); + Aig_ManForEachCo( p, pObj, i ) + pObj->fMarkA = Aig_ObjFanin0(pObj)->fMarkA ^ Aig_ObjFaninC0(pObj); + Aig_ManForEachCo( p, pObj, i ) + if ( pObj->fMarkA ) + { + if ( RetValue == -1 ) + RetValue = i; + (*pnOutputs)++; + } + Aig_ManCleanMarkA(p); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Reduces SEC to CEC for the special case of seq synthesis.] + + Description [The first circuit (pPart0) should be circuit before synthesis. + The second circuit (pPart1) should be circuit after synthesis.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SecSpecial( Aig_Man_t * pPart0, Aig_Man_t * pPart1, int nFrames, int fVerbose ) +{ +// extern int Fra_FraigCec( Aig_Man_t ** ppAig, int nConfLimit, int fVerbose ); + int iOut, nOuts; + Aig_Man_t * pMiterCec; + int RetValue; + abctime clkTotal = Abc_Clock(); + if ( fVerbose ) + { + Aig_ManPrintStats( pPart0 ); + Aig_ManPrintStats( pPart1 ); + } +// Aig_ManDumpBlif( pPart0, "file0.blif", NULL, NULL ); +// Aig_ManDumpBlif( pPart1, "file1.blif", NULL, NULL ); +// assert( Aig_ManNodeNum(pPart0) <= Aig_ManNodeNum(pPart1) ); +/* + if ( Aig_ManNodeNum(pPart0) >= Aig_ManNodeNum(pPart1) ) + { + printf( "Warning: The design after synthesis is smaller!\n" ); + printf( "This warning may indicate that the order of designs is changed.\n" ); + printf( "The solver expects the original design as first argument and\n" ); + printf( "the modified design as the second argument in \"absec\".\n" ); + } +*/ + // create two-level miter + pMiterCec = Saig_ManCreateMiterTwo( pPart0, pPart1, nFrames ); + if ( fVerbose ) + { + Aig_ManPrintStats( pMiterCec ); +// Aig_ManDumpBlif( pMiterCec, "miter01.blif", NULL, NULL ); +// printf( "The new miter is written into file \"%s\".\n", "miter01.blif" ); + } + // run CEC on this miter + RetValue = Fra_FraigCec( &pMiterCec, 100000, fVerbose ); + // transfer model if given +// if ( pNtk2 == NULL ) +// pNtk1->pModel = pMiterCec->pData, pMiterCec->pData = NULL; + // report the miter + if ( RetValue == 1 ) + { + printf( "Networks are equivalent. " ); +ABC_PRT( "Time", Abc_Clock() - clkTotal ); + } + else if ( RetValue == 0 ) + { + printf( "Networks are NOT EQUIVALENT. " ); +ABC_PRT( "Time", Abc_Clock() - clkTotal ); + if ( pMiterCec->pData == NULL ) + printf( "Counter-example is not available.\n" ); + else + { + iOut = Ssw_SecCexResimulate( pMiterCec, (int *)pMiterCec->pData, &nOuts ); + if ( iOut == -1 ) + printf( "Counter-example verification has failed.\n" ); + else + { + if ( iOut < Saig_ManPoNum(pPart0) * nFrames ) + printf( "Primary output %d has failed in frame %d.\n", + iOut%Saig_ManPoNum(pPart0), iOut/Saig_ManPoNum(pPart0) ); + else + printf( "Flop input %d has failed in the last frame.\n", + iOut - Saig_ManPoNum(pPart0) * nFrames ); + printf( "The counter-example detected %d incorrect POs or flop inputs.\n", nOuts ); + } + } + } + else + { + printf( "Networks are UNDECIDED. " ); +ABC_PRT( "Time", Abc_Clock() - clkTotal ); + } + fflush( stdout ); + Aig_ManStop( pMiterCec ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Reduces SEC to CEC for the special case of seq synthesis.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_SecSpecialMiter( Aig_Man_t * p0, Aig_Man_t * p1, int nFrames, int fVerbose ) +{ + Aig_Man_t * pPart0, * pPart1; + int RetValue; + if ( fVerbose ) + printf( "Performing sequential verification using combinational A/B miter.\n" ); + // consider the case when a miter is given + if ( p1 == NULL ) + { + if ( fVerbose ) + { + Aig_ManPrintStats( p0 ); + } + // demiter the miter + if ( !Saig_ManDemiterSimpleDiff( p0, &pPart0, &pPart1 ) ) + { + printf( "Demitering has failed.\n" ); + return -1; + } + if ( Aig_ManRegNum(pPart0) != Aig_ManRegNum(pPart1) ) + { + Aig_ManStop( pPart0 ); + Aig_ManStop( pPart1 ); + printf( "After demitering AIGs have different number of flops. Quitting.\n" ); + return -1; + } + } + else + { + pPart0 = Aig_ManDupSimple( p0 ); + pPart1 = Aig_ManDupSimple( p1 ); + } + if ( fVerbose ) + { +// Aig_ManPrintStats( pPart0 ); +// Aig_ManPrintStats( pPart1 ); + if ( p1 == NULL ) + { +// Aig_ManDumpBlif( pPart0, "part0.blif", NULL, NULL ); +// Aig_ManDumpBlif( pPart1, "part1.blif", NULL, NULL ); +// printf( "The result of demitering is written into files \"%s\" and \"%s\".\n", "part0.blif", "part1.blif" ); + } + } + assert( Aig_ManRegNum(pPart0) > 0 ); + assert( Aig_ManRegNum(pPart1) > 0 ); + assert( Saig_ManPiNum(pPart0) == Saig_ManPiNum(pPart1) ); + assert( Saig_ManPoNum(pPart0) == Saig_ManPoNum(pPart1) ); + assert( Aig_ManRegNum(pPart0) == Aig_ManRegNum(pPart1) ); + RetValue = Ssw_SecSpecial( pPart0, pPart1, nFrames, fVerbose ); + if ( RetValue != 1 && Aig_ManNodeNum(pPart0) >= Aig_ManNodeNum(pPart1) ) + RetValue = Ssw_SecSpecial( pPart1, pPart0, nFrames, fVerbose ); + Aig_ManStop( pPart0 ); + Aig_ManStop( pPart1 ); + return RetValue; +} + + + +/**Function************************************************************* + + Synopsis [Performs demitering of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManDemiterNew( Aig_Man_t * pMan ) +{ + Vec_Ptr_t * vSuper, * vSupp0, * vSupp1; + Aig_Obj_t * pObj, * pTemp, * pFan0, * pFan1; + int i, k; + vSuper = Vec_PtrAlloc( 100 ); + Saig_ManForEachPo( pMan, pObj, i ) + { + if ( pMan->nConstrs && i >= Saig_ManPoNum(pMan) - pMan->nConstrs ) + break; + printf( "Output %3d : ", i ); + if ( Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) + { + if ( !Aig_ObjFaninC0(pObj) ) + printf( "Const1\n" ); + else + printf( "Const0\n" ); + continue; + } + if ( !Aig_ObjIsNode(Aig_ObjFanin0(pObj)) ) + { + printf( "Terminal\n" ); + continue; + } + // check AND + if ( !Aig_ObjFaninC0(pObj) ) + { + printf( "AND " ); + if ( Aig_ObjRecognizeExor(Aig_ObjFanin0(pObj), &pFan0, &pFan1) ) + printf( " Yes" ); + else + printf( " No" ); + printf( "\n" ); + continue; + } + // check OR + Aig_ObjCollectSuper( Aig_ObjFanin0(pObj), vSuper ); + printf( "OR with %d inputs ", Vec_PtrSize(vSuper) ); + if ( Vec_PtrSize(vSuper) == 2 ) + { + if ( Aig_ObjRecognizeExor(Aig_ObjFanin0(pObj), &pFan0, &pFan1) ) + { + printf( " Yes" ); + printf( "\n" ); + + vSupp0 = Aig_Support( pMan, Aig_Regular(pFan0) ); + Vec_PtrForEachEntry( Aig_Obj_t *, vSupp0, pTemp, k ) + if ( Saig_ObjIsLo(pMan, pTemp) ) + printf( " %d", Aig_ObjCioId(pTemp) ); + printf( "\n" ); + Vec_PtrFree( vSupp0 ); + + vSupp1 = Aig_Support( pMan, Aig_Regular(pFan1) ); + Vec_PtrForEachEntry( Aig_Obj_t *, vSupp1, pTemp, k ) + if ( Saig_ObjIsLo(pMan, pTemp) ) + printf( " %d", Aig_ObjCioId(pTemp) ); + printf( "\n" ); + Vec_PtrFree( vSupp1 ); + } + else + printf( " No" ); + printf( "\n" ); + continue; + } +/* + Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pTemp, k ) + if ( Aig_ObjRecognizeExor(Aig_Regular(pTemp), &pFan0, &pFan1) ) + { + printf( " Yes" ); + if ( Aig_IsComplement(pTemp) ) + pFan0 = Aig_Not(pFan0); + } + else + printf( " No" ); +*/ + printf( "\n" ); + } + Vec_PtrFree( vSuper ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigOutDec.c b/yosys/abc/src/aig/saig/saigOutDec.c new file mode 100644 index 00000000000..13c4ad745ca --- /dev/null +++ b/yosys/abc/src/aig/saig/saigOutDec.c @@ -0,0 +1,205 @@ +/**CFile**************************************************************** + + FileName [saigOutDec.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Output cone decomposition.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigOutDec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" +#include "sat/cnf/cnf.h" +#include "sat/bsat/satSolver.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs decomposition of the property output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Saig_ManFindPrimes( Aig_Man_t * pAig, int nLits, int fVerbose ) +{ + Cnf_Dat_t * pCnf; + sat_solver * pSat; + Aig_Obj_t * pObj0, * pObj1, * pRoot, * pMiter; + Vec_Ptr_t * vPrimes, * vNodes; + Vec_Int_t * vCube, * vMarks; + int i0, i1, m, RetValue, Lits[10]; + int fCompl0, fCompl1, nNodes1, nNodes2; + assert( nLits == 1 || nLits == 2 ); + assert( nLits < 10 ); + + // create SAT solver + pCnf = Cnf_DeriveSimple( pAig, Aig_ManCoNum(pAig) ); + pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + + // collect nodes in the property output cone + pMiter = Aig_ManCo( pAig, 0 ); + pRoot = Aig_ObjFanin0( pMiter ); + vNodes = Aig_ManDfsNodes( pAig, &pRoot, 1 ); + // sort nodes by level and remove the last few + + // try single nodes + vPrimes = Vec_PtrAlloc( 100 ); + // create assumptions + vMarks = Vec_IntStart( Vec_PtrSize(vNodes) ); + Lits[0] = toLitCond( pCnf->pVarNums[Aig_ObjId(pMiter)], 1 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj0, i0 ) + if ( pObj0 != pRoot ) + { + // create assumptions + Lits[1] = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj0)], pObj0->fPhase ); + // solve the problem + RetValue = sat_solver_solve( pSat, Lits, Lits+2, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + if ( RetValue == l_False ) + { + vCube = Vec_IntAlloc( 1 ); + Vec_IntPush( vCube, toLitCond(Aig_ObjId(pObj0), pObj0->fPhase) ); + Vec_PtrPush( vPrimes, vCube ); + if ( fVerbose ) + printf( "Adding prime %d%c\n", Aig_ObjId(pObj0), pObj0->fPhase?'-':'+' ); + Vec_IntWriteEntry( vMarks, i0, 1 ); + } + } + nNodes1 = Vec_PtrSize(vPrimes); + if ( nLits > 1 ) + { + // try adding second literal + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj0, i0 ) + if ( pObj0 != pRoot ) + Vec_PtrForEachEntryStart( Aig_Obj_t *, vNodes, pObj1, i1, i0+1 ) + if ( pObj1 != pRoot ) + { + if ( Vec_IntEntry(vMarks,i0) || Vec_IntEntry(vMarks,i1) ) + continue; + for ( m = 0; m < 3; m++ ) + { + fCompl0 = m & 1; + fCompl1 = (m >> 1) & 1; + // create assumptions + Lits[1] = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj0)], fCompl0 ^ pObj0->fPhase ); + Lits[2] = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj1)], fCompl1 ^ pObj1->fPhase ); + // solve the problem + RetValue = sat_solver_solve( pSat, Lits, Lits+3, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + if ( RetValue == l_False ) + { + vCube = Vec_IntAlloc( 2 ); + Vec_IntPush( vCube, toLitCond(Aig_ObjId(pObj0), fCompl0 ^ pObj0->fPhase) ); + Vec_IntPush( vCube, toLitCond(Aig_ObjId(pObj1), fCompl1 ^ pObj1->fPhase) ); + Vec_PtrPush( vPrimes, vCube ); + if ( fVerbose ) + printf( "Adding prime %d%c %d%c\n", + Aig_ObjId(pObj0), (fCompl0 ^ pObj0->fPhase)?'-':'+', + Aig_ObjId(pObj1), (fCompl1 ^ pObj1->fPhase)?'-':'+' ); + break; + } + } + } + } + nNodes2 = Vec_PtrSize(vPrimes) - nNodes1; + + printf( "Property cone size = %6d 1-lit primes = %5d 2-lit primes = %5d\n", + Vec_PtrSize(vNodes), nNodes1, nNodes2 ); + + // clean up + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + Vec_PtrFree( vNodes ); + Vec_IntFree( vMarks ); + return vPrimes; +} + +/**Function************************************************************* + + Synopsis [Performs decomposition of the property output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManDecPropertyOutput( Aig_Man_t * pAig, int nLits, int fVerbose ) +{ + Aig_Man_t * pAigNew = NULL; + Aig_Obj_t * pObj, * pMiter; + Vec_Ptr_t * vPrimes; + Vec_Int_t * vCube; + int i, k, Lit; + + // compute primes of the comb output function + vPrimes = Saig_ManFindPrimes( pAig, nLits, fVerbose ); + + // start the new manager + pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); + pAigNew->pName = Abc_UtilStrsav( pAig->pName ); + pAigNew->nConstrs = pAig->nConstrs; + // map the constant node + Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); + // create variables for PIs + Aig_ManForEachCi( pAig, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pAigNew ); + // add internal nodes of this frame + Aig_ManForEachNode( pAig, pObj, i ) + pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // create original POs of the circuit + Saig_ManForEachPo( pAig, pObj, i ) + Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); + // create prime POs of the circuit + if ( vPrimes ) + Vec_PtrForEachEntry( Vec_Int_t *, vPrimes, vCube, k ) + { + pMiter = Aig_ManConst1( pAigNew ); + Vec_IntForEachEntry( vCube, Lit, i ) + { + pObj = Aig_NotCond( Aig_ObjCopy(Aig_ManObj(pAig, Abc_Lit2Var(Lit))), Abc_LitIsCompl(Lit) ); + pMiter = Aig_And( pAigNew, pMiter, pObj ); + } + Aig_ObjCreateCo( pAigNew, pMiter ); + } + // transfer to register outputs + Saig_ManForEachLi( pAig, pObj, i ) + Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); + Aig_ManCleanup( pAigNew ); + Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig) ); + + Vec_VecFreeP( (Vec_Vec_t **)&vPrimes ); + return pAigNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigPhase.c b/yosys/abc/src/aig/saig/saigPhase.c new file mode 100644 index 00000000000..e7a586fe05c --- /dev/null +++ b/yosys/abc/src/aig/saig/saigPhase.c @@ -0,0 +1,1081 @@ +/**CFile**************************************************************** + + FileName [saigPhase.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Automated phase abstraction.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigPhase.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" + +ABC_NAMESPACE_IMPL_START + + +/* + The algorithm is described in the paper: Per Bjesse and Jim Kukula, + "Automatic Phase Abstraction for Formal Verification", ICCAD 2005 + http://www.iccad.com/data2/iccad/iccad_05acceptedpapers.nsf/9cfb1ebaaf59043587256a6a00031f78/1701ecf34b149e958725702f00708828?OpenDocument +*/ + +// the maximum number of cycles of termiry simulation +#define TSIM_MAX_ROUNDS 10000 +#define TSIM_ONE_SERIES 3000 + +#define SAIG_XVS0 1 +#define SAIG_XVS1 2 +#define SAIG_XVSX 3 + +static inline int Saig_XsimConvertValue( int v ) { return v == 0? SAIG_XVS0 : (v == 1? SAIG_XVS1 : (v == 2? SAIG_XVSX : -1)); } + +static inline void Saig_ObjSetXsim( Aig_Obj_t * pObj, int Value ) { pObj->nCuts = Value; } +static inline int Saig_ObjGetXsim( Aig_Obj_t * pObj ) { return pObj->nCuts; } +static inline int Saig_XsimInv( int Value ) +{ + if ( Value == SAIG_XVS0 ) + return SAIG_XVS1; + if ( Value == SAIG_XVS1 ) + return SAIG_XVS0; + assert( Value == SAIG_XVSX ); + return SAIG_XVSX; +} +static inline int Saig_XsimAnd( int Value0, int Value1 ) +{ + if ( Value0 == SAIG_XVS0 || Value1 == SAIG_XVS0 ) + return SAIG_XVS0; + if ( Value0 == SAIG_XVSX || Value1 == SAIG_XVSX ) + return SAIG_XVSX; + assert( Value0 == SAIG_XVS1 && Value1 == SAIG_XVS1 ); + return SAIG_XVS1; +} +static inline int Saig_XsimRand2() +{ + return (Aig_ManRandom(0) & 1) ? SAIG_XVS1 : SAIG_XVS0; +} +static inline int Saig_XsimRand3() +{ + int RetValue; + do { + RetValue = Aig_ManRandom(0) & 3; + } while ( RetValue == 0 ); + return RetValue; +} +static inline int Saig_ObjGetXsimFanin0( Aig_Obj_t * pObj ) +{ + int RetValue; + RetValue = Saig_ObjGetXsim(Aig_ObjFanin0(pObj)); + return Aig_ObjFaninC0(pObj)? Saig_XsimInv(RetValue) : RetValue; +} +static inline int Saig_ObjGetXsimFanin1( Aig_Obj_t * pObj ) +{ + int RetValue; + RetValue = Saig_ObjGetXsim(Aig_ObjFanin1(pObj)); + return Aig_ObjFaninC1(pObj)? Saig_XsimInv(RetValue) : RetValue; +} +static inline void Saig_XsimPrint( FILE * pFile, int Value ) +{ + if ( Value == SAIG_XVS0 ) + { + fprintf( pFile, "0" ); + return; + } + if ( Value == SAIG_XVS1 ) + { + fprintf( pFile, "1" ); + return; + } + assert( Value == SAIG_XVSX ); + fprintf( pFile, "x" ); +} + +// simulation manager +typedef struct Saig_Tsim_t_ Saig_Tsim_t; +struct Saig_Tsim_t_ +{ + Aig_Man_t * pAig; // the original AIG manager + int nWords; // the number of words in the states + // ternary state representation + Vec_Ptr_t * vStates; // the collection of ternary states + Aig_MmFixed_t * pMem; // memory for ternary states + int nPrefix; // prefix of the ternary state space + int nCycle; // cycle of the ternary state space + int nNonXRegs; // the number of candidate registers + Vec_Int_t * vNonXRegs; // the candidate registers + // hash table for terminary states + unsigned ** pBins; + int nBins; +}; + +static inline unsigned * Saig_TsiNext( unsigned * pState, int nWords ) { return *((unsigned **)(pState + nWords)); } +static inline void Saig_TsiSetNext( unsigned * pState, int nWords, unsigned * pNext ) { *((unsigned **)(pState + nWords)) = pNext; } + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Saig_Tsim_t * Saig_TsiStart( Aig_Man_t * pAig ) +{ + Saig_Tsim_t * p; + p = (Saig_Tsim_t *)ABC_ALLOC( char, sizeof(Saig_Tsim_t) ); + memset( p, 0, sizeof(Saig_Tsim_t) ); + p->pAig = pAig; + p->nWords = Abc_BitWordNum( 2*Aig_ManRegNum(pAig) ); + p->vStates = Vec_PtrAlloc( 1000 ); + p->pMem = Aig_MmFixedStart( sizeof(unsigned) * p->nWords + sizeof(unsigned *), 10000 ); + p->nBins = Abc_PrimeCudd(TSIM_MAX_ROUNDS/2); + p->pBins = ABC_ALLOC( unsigned *, p->nBins ); + memset( p->pBins, 0, sizeof(unsigned *) * p->nBins ); + return p; +} + +/**Function************************************************************* + + Synopsis [Deallocates simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_TsiStop( Saig_Tsim_t * p ) +{ + if ( p->vNonXRegs ) + Vec_IntFree( p->vNonXRegs ); + Aig_MmFixedStop( p->pMem, 0 ); + Vec_PtrFree( p->vStates ); + ABC_FREE( p->pBins ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Computes hash value of the node using its simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_TsiStateHash( unsigned * pState, int nWords, int nTableSize ) +{ + static int s_FPrimes[128] = { + 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, + 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, + 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, + 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, + 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, + 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, + 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, + 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, + 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, + 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, + 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, + 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, + 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 + }; + unsigned uHash; + int i; + uHash = 0; + for ( i = 0; i < nWords; i++ ) + uHash ^= pState[i] * s_FPrimes[i & 0x7F]; + return uHash % nTableSize; +} + +/**Function************************************************************* + + Synopsis [Count non-X-valued registers in the simulation data.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_TsiCountNonXValuedRegisters( Saig_Tsim_t * p, int nPref ) +{ + unsigned * pState; + int nRegs = p->pAig->nRegs; + int Value, i, k; + assert( p->vNonXRegs == NULL ); + p->vNonXRegs = Vec_IntAlloc( 10 ); + for ( i = 0; i < nRegs; i++ ) + { + Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, k, nPref ) + { + Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); + assert( Value != 0 ); + if ( Value == SAIG_XVSX ) + break; + } + if ( k == Vec_PtrSize(p->vStates) ) + Vec_IntPush( p->vNonXRegs, i ); + } + return Vec_IntSize(p->vNonXRegs); +} + +/**Function************************************************************* + + Synopsis [Computes flops that are stuck-at constant.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_TsiComputeTransient( Saig_Tsim_t * p, int nPref ) +{ + Vec_Int_t * vCounters; + unsigned * pState; + int ValueThis = -1, ValuePrev = -1, StepPrev = -1; + int i, k, nRegs = p->pAig->nRegs; + vCounters = Vec_IntStart( nPref ); + for ( i = 0; i < nRegs; i++ ) + { + Vec_PtrForEachEntry( unsigned *, p->vStates, pState, k ) + { + ValueThis = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); +//printf( "%s", (ValueThis == 1)? "0" : ((ValueThis == 2)? "1" : "x") ); + assert( ValueThis != 0 ); + if ( ValuePrev != ValueThis ) + { + ValuePrev = ValueThis; + StepPrev = k; + } + } +//printf( "\n" ); + if ( ValueThis == SAIG_XVSX ) + continue; + if ( StepPrev >= nPref ) + continue; + Vec_IntAddToEntry( vCounters, StepPrev, 1 ); + } + Vec_IntForEachEntry( vCounters, ValueThis, i ) + { + if ( ValueThis == 0 ) + continue; +// printf( "%3d : %3d\n", i, ValueThis ); + } + return vCounters; +} + +/**Function************************************************************* + + Synopsis [Count non-X-valued registers in the simulation data.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_TsiPrintTraces( Saig_Tsim_t * p, int nWords, int nPrefix, int nLoop ) +{ + unsigned * pState; + int nRegs = p->pAig->nRegs; + int Value, i, k, Counter = 0; + printf( "Ternary traces for each flop:\n" ); + printf( " : " ); + for ( i = 0; i < Vec_PtrSize(p->vStates) - nLoop - 1; i++ ) + printf( "%d", i%10 ); + printf( " " ); + for ( i = 0; i < nLoop; i++ ) + printf( "%d", i%10 ); + printf( "\n" ); + for ( i = 0; i < nRegs; i++ ) + { +/* + Vec_PtrForEachEntry( unsigned *, p->vStates, pState, k ) + { + Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); + if ( Value == SAIG_XVSX ) + break; + } + if ( k == Vec_PtrSize(p->vStates) ) + Counter++; + else + continue; +*/ + + // print trace +// printf( "%5d : %5d %5d ", Counter, i, Saig_ManLo(p->pAig, i)->Id ); + printf( "%5d : ", Counter++ ); + Vec_PtrForEachEntryStop( unsigned *, p->vStates, pState, k, Vec_PtrSize(p->vStates)-1 ) + { + Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); + if ( Value == SAIG_XVS0 ) + printf( "0" ); + else if ( Value == SAIG_XVS1 ) + printf( "1" ); + else if ( Value == SAIG_XVSX ) + printf( "x" ); + else + assert( 0 ); + if ( k == nPrefix - 1 ) + printf( " " ); + } + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Returns the number of the state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_TsiComputePrefix( Saig_Tsim_t * p, unsigned * pState, int nWords ) +{ + unsigned * pEntry, * pPrev; + int Hash, i; + Hash = Saig_TsiStateHash( pState, nWords, p->nBins ); + for ( pEntry = p->pBins[Hash]; pEntry; pEntry = Saig_TsiNext(pEntry, nWords) ) + if ( !memcmp( pEntry, pState, sizeof(unsigned) * nWords ) ) + { + Vec_PtrForEachEntry( unsigned *, p->vStates, pPrev, i ) + { + if ( pPrev == pEntry ) + return i; + } + assert( 0 ); + return -1; + } + return -1; +} + +/**Function************************************************************* + + Synopsis [Checks if the value exists in the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_TsiStateLookup( Saig_Tsim_t * p, unsigned * pState, int nWords ) +{ + unsigned * pEntry; + int Hash; + Hash = Saig_TsiStateHash( pState, nWords, p->nBins ); + for ( pEntry = p->pBins[Hash]; pEntry; pEntry = Saig_TsiNext(pEntry, nWords) ) + if ( !memcmp( pEntry, pState, sizeof(unsigned) * nWords ) ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Inserts value into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_TsiStateInsert( Saig_Tsim_t * p, unsigned * pState, int nWords ) +{ + int Hash = Saig_TsiStateHash( pState, nWords, p->nBins ); + assert( !Saig_TsiStateLookup( p, pState, nWords ) ); + Saig_TsiSetNext( pState, nWords, p->pBins[Hash] ); + p->pBins[Hash] = pState; +} + +/**Function************************************************************* + + Synopsis [Inserts value into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Saig_TsiStateNew( Saig_Tsim_t * p ) +{ + unsigned * pState; + pState = (unsigned *)Aig_MmFixedEntryFetch( p->pMem ); + memset( pState, 0, sizeof(unsigned) * p->nWords ); + Vec_PtrPush( p->vStates, pState ); + return pState; +} + +/**Function************************************************************* + + Synopsis [Inserts value into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_TsiStatePrint( Saig_Tsim_t * p, unsigned * pState ) +{ + int i, Value, nZeros = 0, nOnes = 0, nDcs = 0; + for ( i = 0; i < Aig_ManRegNum(p->pAig); i++ ) + { + Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); + if ( Value == SAIG_XVS0 ) + printf( "0" ), nZeros++; + else if ( Value == SAIG_XVS1 ) + printf( "1" ), nOnes++; + else if ( Value == SAIG_XVSX ) + printf( "x" ), nDcs++; + else + assert( 0 ); + } + printf( " (0=%5d, 1=%5d, x=%5d)\n", nZeros, nOnes, nDcs ); +} + +/**Function************************************************************* + + Synopsis [Count constant values in the state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_TsiStateCount( Saig_Tsim_t * p, unsigned * pState ) +{ + Aig_Obj_t * pObjLi, * pObjLo; + int i, Value, nCounter = 0; + Aig_ManForEachLiLoSeq( p->pAig, pObjLi, pObjLo, i ) + { + Value = (Abc_InfoHasBit( pState, 2 * i + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * i ); + nCounter += (Value == SAIG_XVS0 || Value == SAIG_XVS1); + } + return nCounter; +} + +/**Function************************************************************* + + Synopsis [Count constant values in the state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_TsiStateOrAll( Saig_Tsim_t * pTsi, unsigned * pState ) +{ + unsigned * pPrev; + int i, k; + Vec_PtrForEachEntry( unsigned *, pTsi->vStates, pPrev, i ) + { + for ( k = 0; k < pTsi->nWords; k++ ) + pState[k] |= pPrev[k]; + } +} + +/**Function************************************************************* + + Synopsis [Cycles the circuit to create a new initial state.] + + Description [Simulates the circuit with random input for the given + number of timeframes to get a better initial state.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Saig_Tsim_t * Saig_ManReachableTernary( Aig_Man_t * p, Vec_Int_t * vInits, int fVerbose ) +{ + Saig_Tsim_t * pTsi; + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + unsigned * pState; + int i, f, Value, nCounter; + // allocate the simulation manager + pTsi = Saig_TsiStart( p ); + // initialize the values + Saig_ObjSetXsim( Aig_ManConst1(p), SAIG_XVS1 ); + Saig_ManForEachPi( p, pObj, i ) + Saig_ObjSetXsim( pObj, SAIG_XVSX ); + if ( vInits ) + { + Saig_ManForEachLo( p, pObj, i ) + Saig_ObjSetXsim( pObj, Saig_XsimConvertValue(Vec_IntEntry(vInits, i)) ); + } + else + { + Saig_ManForEachLo( p, pObj, i ) + Saig_ObjSetXsim( pObj, SAIG_XVS0 ); + } + // simulate for the given number of timeframes + for ( f = 0; f < TSIM_MAX_ROUNDS; f++ ) + { + // collect this state + pState = Saig_TsiStateNew( pTsi ); + Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) + { + Value = Saig_ObjGetXsim(pObjLo); + if ( Value & 1 ) + Abc_InfoSetBit( pState, 2 * i ); + if ( Value & 2 ) + Abc_InfoSetBit( pState, 2 * i + 1 ); + } +// printf( "%d ", Saig_TsiStateCount(pTsi, pState) ); +// Saig_TsiStatePrint( pTsi, pState ); + // check if this state exists + if ( Saig_TsiStateLookup( pTsi, pState, pTsi->nWords ) ) + { + if ( fVerbose ) + printf( "Ternary simulation converged after %d iterations.\n", f ); + return pTsi; + } + // insert this state + Saig_TsiStateInsert( pTsi, pState, pTsi->nWords ); + // simulate internal nodes + Aig_ManForEachNode( p, pObj, i ) + Saig_ObjSetXsim( pObj, Saig_XsimAnd(Saig_ObjGetXsimFanin0(pObj), Saig_ObjGetXsimFanin1(pObj)) ); + // transfer the latch values + Saig_ManForEachLi( p, pObj, i ) + Saig_ObjSetXsim( pObj, Saig_ObjGetXsimFanin0(pObj) ); + nCounter = 0; + Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) + { + if ( f < TSIM_ONE_SERIES ) + Saig_ObjSetXsim( pObjLo, Saig_ObjGetXsim(pObjLi) ); + else + { + if ( Saig_ObjGetXsim(pObjLi) != Saig_ObjGetXsim(pObjLo) ) + Saig_ObjSetXsim( pObjLo, SAIG_XVSX ); + } + nCounter += (Saig_ObjGetXsim(pObjLo) == SAIG_XVS0); + } + } + printf( "Saig_ManReachableTernary(): Did not reach a fixed point after %d iterations (not a bug).\n", TSIM_MAX_ROUNDS ); + Saig_TsiStop( pTsi ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Analize initial value of the selected register.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManAnalizeControl( Aig_Man_t * p, int Reg ) +{ + Aig_Obj_t * pObj, * pReg, * pCtrl, * pAnd; + int i; + pReg = Saig_ManLo( p, Reg ); + pCtrl = Saig_ManLo( p, Saig_ManRegNum(p)-1 ); + assert( pReg->Id < pCtrl->Id ); + // find a node pointing to both + pAnd = NULL; + Aig_ManForEachNode( p, pObj, i ) + { + if ( Aig_ObjFanin0(pObj) == pReg && Aig_ObjFanin1(pObj) == pCtrl ) + { + pAnd = pObj; + break; + } + } + if ( pAnd == NULL ) + { + printf( "Register is not found.\n" ); + return; + } + printf( "Clock-like register: \n" ); + Aig_ObjPrint( p, pReg ); + printf( "\n" ); + printf( "Control register: \n" ); + Aig_ObjPrint( p, pCtrl ); + printf( "\n" ); + printf( "Their fanout: \n" ); + Aig_ObjPrint( p, pAnd ); + printf( "\n" ); + + // find the fanouts of pAnd + printf( "Fanouts of the fanout: \n" ); + Aig_ManForEachObj( p, pObj, i ) + if ( Aig_ObjFanin0(pObj) == pAnd || Aig_ObjFanin1(pObj) == pAnd ) + { + Aig_ObjPrint( p, pObj ); + printf( "\n" ); + } + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Finds the registers to phase-abstract.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManFindRegisters( Saig_Tsim_t * pTsi, int nFrames, int fIgnore, int fVerbose ) +{ + int Values[257] = {0}; + unsigned * pState; + int r, i, k, Reg, Value; + int nTests = pTsi->nPrefix + 2 * pTsi->nCycle; + assert( nFrames <= 256 ); + r = 0; + Vec_IntForEachEntry( pTsi->vNonXRegs, Reg, i ) + { + for ( k = 0; k < nTests; k++ ) + { + if ( k < pTsi->nPrefix + pTsi->nCycle ) + pState = (unsigned *)Vec_PtrEntry( pTsi->vStates, k ); + else + pState = (unsigned *)Vec_PtrEntry( pTsi->vStates, k - pTsi->nCycle ); + Value = (Abc_InfoHasBit( pState, 2 * Reg + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * Reg ); + assert( Value == SAIG_XVS0 || Value == SAIG_XVS1 ); + if ( k < nFrames || (fIgnore && k == nFrames) ) + Values[k % nFrames] = Value; + else if ( Values[k % nFrames] != Value ) + break; + } + if ( k < nTests ) + continue; + // skip stuck at + if ( fIgnore ) + { + for ( k = 1; k < nFrames; k++ ) + if ( Values[k] != Values[0] ) + break; + if ( k == nFrames ) + continue; + } + // report useful register + Vec_IntWriteEntry( pTsi->vNonXRegs, r++, Reg ); + if ( fVerbose ) + { + printf( "Register %5d has generator: [", Reg ); + for ( k = 0; k < nFrames; k++ ) + Saig_XsimPrint( stdout, Values[k] ); + printf( "]\n" ); + + if ( fVerbose ) + Saig_ManAnalizeControl( pTsi->pAig, Reg ); + } + } + Vec_IntShrink( pTsi->vNonXRegs, r ); + if ( fVerbose ) + printf( "Found %3d useful registers.\n", Vec_IntSize(pTsi->vNonXRegs) ); + return Vec_IntSize(pTsi->vNonXRegs); +} + + +/**Function************************************************************* + + Synopsis [Mapping of AIG nodes into frames nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Aig_Obj_t * Saig_ObjFrames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return pObjMap[nFs*pObj->Id + i]; } +static inline void Saig_ObjSetFrames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i, Aig_Obj_t * pNode ) { pObjMap[nFs*pObj->Id + i] = pNode; } + +static inline Aig_Obj_t * Saig_ObjChild0Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin0(pObj)? Aig_NotCond(Saig_ObjFrames(pObjMap,nFs,Aig_ObjFanin0(pObj),i), Aig_ObjFaninC0(pObj)) : NULL; } +static inline Aig_Obj_t * Saig_ObjChild1Frames( Aig_Obj_t ** pObjMap, int nFs, Aig_Obj_t * pObj, int i ) { return Aig_ObjFanin1(pObj)? Aig_NotCond(Saig_ObjFrames(pObjMap,nFs,Aig_ObjFanin1(pObj),i), Aig_ObjFaninC1(pObj)) : NULL; } + +/**Function************************************************************* + + Synopsis [Performs phase abstraction by unrolling the circuit.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManPerformAbstraction( Saig_Tsim_t * pTsi, int nFrames, int fVerbose ) +{ + Aig_Man_t * pFrames, * pAig = pTsi->pAig; + Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew; + Aig_Obj_t ** pObjMap; + unsigned * pState; + int i, f, Reg, Value; + + assert( Vec_IntSize(pTsi->vNonXRegs) > 0 ); + + // create mapping for the frames nodes + pObjMap = ABC_ALLOC( Aig_Obj_t *, nFrames * Aig_ManObjNumMax(pAig) ); + memset( pObjMap, 0, sizeof(Aig_Obj_t *) * nFrames * Aig_ManObjNumMax(pAig) ); + + // start the fraig package + pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFrames ); + pFrames->pName = Abc_UtilStrsav( pAig->pName ); + pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); + // map constant nodes + for ( f = 0; f < nFrames; f++ ) + Saig_ObjSetFrames( pObjMap, nFrames, Aig_ManConst1(pAig), f, Aig_ManConst1(pFrames) ); + // create PI nodes for the frames + for ( f = 0; f < nFrames; f++ ) + Aig_ManForEachPiSeq( pAig, pObj, i ) + Saig_ObjSetFrames( pObjMap, nFrames, pObj, f, Aig_ObjCreateCi(pFrames) ); + // create the latches + Aig_ManForEachLoSeq( pAig, pObj, i ) + Saig_ObjSetFrames( pObjMap, nFrames, pObj, 0, Aig_ObjCreateCi(pFrames) ); + + // add timeframes + for ( f = 0; f < nFrames; f++ ) + { + // replace abstracted registers by constants + Vec_IntForEachEntry( pTsi->vNonXRegs, Reg, i ) + { + pObj = Saig_ManLo( pAig, Reg ); + pState = (unsigned *)Vec_PtrEntry( pTsi->vStates, f ); + Value = (Abc_InfoHasBit( pState, 2 * Reg + 1 ) << 1) | Abc_InfoHasBit( pState, 2 * Reg ); + assert( Value == SAIG_XVS0 || Value == SAIG_XVS1 ); + pObjNew = (Value == SAIG_XVS1)? Aig_ManConst1(pFrames) : Aig_ManConst0(pFrames); + Saig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew ); + } + // add internal nodes of this frame + Aig_ManForEachNode( pAig, pObj, i ) + { + pObjNew = Aig_And( pFrames, Saig_ObjChild0Frames(pObjMap,nFrames,pObj,f), Saig_ObjChild1Frames(pObjMap,nFrames,pObj,f) ); + Saig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew ); + } + // set the latch inputs and copy them into the latch outputs of the next frame + Aig_ManForEachLiLoSeq( pAig, pObjLi, pObjLo, i ) + { + pObjNew = Saig_ObjChild0Frames(pObjMap,nFrames,pObjLi,f); + if ( f < nFrames - 1 ) + Saig_ObjSetFrames( pObjMap, nFrames, pObjLo, f+1, pObjNew ); + } + } + for ( f = 0; f < nFrames; f++ ) + { + Aig_ManForEachPoSeq( pAig, pObj, i ) + { + pObjNew = Aig_ObjCreateCo( pFrames, Saig_ObjChild0Frames(pObjMap,nFrames,pObj,f) ); + Saig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew ); + } + } + pFrames->nRegs = pAig->nRegs; + pFrames->nTruePis = Aig_ManCiNum(pFrames) - Aig_ManRegNum(pFrames); + pFrames->nTruePos = Aig_ManCoNum(pFrames) - Aig_ManRegNum(pFrames); + Aig_ManForEachLiSeq( pAig, pObj, i ) + { + pObjNew = Aig_ObjCreateCo( pFrames, Saig_ObjChild0Frames(pObjMap,nFrames,pObj,nFrames-1) ); + Saig_ObjSetFrames( pObjMap, nFrames, pObj, nFrames-1, pObjNew ); + } +//Aig_ManPrintStats( pFrames ); + Aig_ManSeqCleanup( pFrames ); +//Aig_ManPrintStats( pFrames ); +// Aig_ManCiCleanup( pFrames ); +//Aig_ManPrintStats( pFrames ); + ABC_FREE( pObjMap ); + return pFrames; +} + + +/**Function************************************************************* + + Synopsis [Performs automated phase abstraction.] + + Description [Takes the AIG manager and the array of initial states.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManPhaseFrameNum( Aig_Man_t * p, Vec_Int_t * vInits ) +{ + Saig_Tsim_t * pTsi; + int nFrames, nPrefix; + assert( Saig_ManRegNum(p) ); + assert( Saig_ManPiNum(p) ); + assert( Saig_ManPoNum(p) ); + // perform terminary simulation + pTsi = Saig_ManReachableTernary( p, vInits, 0 ); + if ( pTsi == NULL ) + return 1; + // derive information + nPrefix = Saig_TsiComputePrefix( pTsi, (unsigned *)Vec_PtrEntryLast(pTsi->vStates), pTsi->nWords ); + nFrames = Vec_PtrSize(pTsi->vStates) - 1 - nPrefix; + Saig_TsiStop( pTsi ); + // potentially, may need to reduce nFrames if nPrefix is less than nFrames + return nFrames; +} + +/**Function************************************************************* + + Synopsis [Performs automated phase abstraction.] + + Description [Takes the AIG manager and the array of initial states.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManPhasePrefixLength( Aig_Man_t * p, int fVerbose, int fVeryVerbose, Vec_Int_t ** pvTrans ) +{ + Saig_Tsim_t * pTsi; + int nFrames, nPrefix, nNonXRegs; + assert( Saig_ManRegNum(p) ); + assert( Saig_ManPiNum(p) ); + assert( Saig_ManPoNum(p) ); + // perform terminary simulation + pTsi = Saig_ManReachableTernary( p, NULL, 0 ); + if ( pTsi == NULL ) + return 0; + // derive information + nPrefix = Saig_TsiComputePrefix( pTsi, (unsigned *)Vec_PtrEntryLast(pTsi->vStates), pTsi->nWords ); + nFrames = Vec_PtrSize(pTsi->vStates) - 1 - nPrefix; + nNonXRegs = Saig_TsiCountNonXValuedRegisters( pTsi, nPrefix ); + + if ( pvTrans ) + *pvTrans = Saig_TsiComputeTransient( pTsi, nPrefix ); + + // print statistics + if ( fVerbose ) + printf( "Lead = %5d. Loop = %5d. Total flops = %5d. Binary flops = %5d.\n", nPrefix, nFrames, p->nRegs, nNonXRegs ); + if ( fVeryVerbose ) + Saig_TsiPrintTraces( pTsi, pTsi->nWords, nPrefix, nFrames ); + Saig_TsiStop( pTsi ); + // potentially, may need to reduce nFrames if nPrefix is less than nFrames + return nPrefix; +} + +/**Function************************************************************* + + Synopsis [Performs automated phase abstraction.] + + Description [Takes the AIG manager and the array of initial states.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManPhaseAbstract( Aig_Man_t * p, Vec_Int_t * vInits, int nFrames, int nPref, int fIgnore, int fPrint, int fVerbose ) +{ + Aig_Man_t * pNew = NULL; + Saig_Tsim_t * pTsi; + assert( Saig_ManRegNum(p) ); + assert( Saig_ManPiNum(p) ); + assert( Saig_ManPoNum(p) ); + // perform terminary simulation + pTsi = Saig_ManReachableTernary( p, vInits, fVerbose ); + if ( pTsi == NULL ) + return NULL; + // derive information + pTsi->nPrefix = Saig_TsiComputePrefix( pTsi, (unsigned *)Vec_PtrEntryLast(pTsi->vStates), pTsi->nWords ); + pTsi->nCycle = Vec_PtrSize(pTsi->vStates) - 1 - pTsi->nPrefix; + pTsi->nNonXRegs = Saig_TsiCountNonXValuedRegisters(pTsi, Abc_MinInt(pTsi->nPrefix,nPref)); + // print statistics + if ( fVerbose ) + { + printf( "Lead = %5d. Loop = %5d. Total flops = %5d. Binary flops = %5d.\n", + pTsi->nPrefix, pTsi->nCycle, p->nRegs, pTsi->nNonXRegs ); + if ( pTsi->nNonXRegs < 100 && Vec_PtrSize(pTsi->vStates) < 80 ) + Saig_TsiPrintTraces( pTsi, pTsi->nWords, pTsi->nPrefix, pTsi->nCycle ); + } + if ( fPrint ) + printf( "Print-out finished. Phase assignment is not performed.\n" ); + else if ( nFrames < 2 ) + printf( "The number of frames is less than 2. Phase assignment is not performed.\n" ); + else if ( nFrames > 256 ) + printf( "The number of frames is more than 256. Phase assignment is not performed.\n" ); + else if ( pTsi->nCycle == 1 ) + printf( "The cycle of ternary states is trivial. Phase abstraction cannot be done.\n" ); + else if ( pTsi->nCycle % nFrames != 0 ) + printf( "The cycle (%d) is not modulo the number of frames (%d). Phase abstraction cannot be done.\n", pTsi->nCycle, nFrames ); + else if ( pTsi->nNonXRegs == 0 ) + printf( "All registers have X-valued states. Phase abstraction cannot be done.\n" ); + else if ( !Saig_ManFindRegisters( pTsi, nFrames, fIgnore, fVerbose ) ) + printf( "There is no registers to abstract with %d frames.\n", nFrames ); + else + pNew = Saig_ManPerformAbstraction( pTsi, nFrames, fVerbose ); + Saig_TsiStop( pTsi ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Performs automated phase abstraction.] + + Description [Takes the AIG manager and the array of initial states.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManPhaseAbstractAuto( Aig_Man_t * p, int fVerbose ) +{ + Aig_Man_t * pNew = NULL; + Saig_Tsim_t * pTsi; + int fPrint = 0; + int nFrames; + assert( Saig_ManRegNum(p) ); + assert( Saig_ManPiNum(p) ); + assert( Saig_ManPoNum(p) ); + // perform terminary simulation + pTsi = Saig_ManReachableTernary( p, NULL, fVerbose ); + if ( pTsi == NULL ) + return NULL; + // derive information + pTsi->nPrefix = Saig_TsiComputePrefix( pTsi, (unsigned *)Vec_PtrEntryLast(pTsi->vStates), pTsi->nWords ); + pTsi->nCycle = Vec_PtrSize(pTsi->vStates) - 1 - pTsi->nPrefix; + pTsi->nNonXRegs = Saig_TsiCountNonXValuedRegisters(pTsi, 0); + // print statistics + if ( fVerbose ) + { + printf( "Lead = %5d. Loop = %5d. Total flops = %5d. Binary flops = %5d.\n", + pTsi->nPrefix, pTsi->nCycle, p->nRegs, pTsi->nNonXRegs ); + if ( pTsi->nNonXRegs < 100 && Vec_PtrSize(pTsi->vStates) < 80 ) + Saig_TsiPrintTraces( pTsi, pTsi->nWords, pTsi->nPrefix, pTsi->nCycle ); + } + nFrames = pTsi->nCycle; + if ( fPrint ) + { + printf( "Print-out finished. Phase assignment is not performed.\n" ); + } + else if ( nFrames < 2 ) + { +// printf( "The number of frames is less than 2. Phase assignment is not performed.\n" ); + } + else if ( nFrames > 256 ) + { +// printf( "The number of frames is more than 256. Phase assignment is not performed.\n" ); + } + else if ( pTsi->nCycle == 1 ) + { +// printf( "The cycle of ternary states is trivial. Phase abstraction cannot be done.\n" ); + } + else if ( pTsi->nCycle % nFrames != 0 ) + { +// printf( "The cycle (%d) is not modulo the number of frames (%d). Phase abstraction cannot be done.\n", pTsi->nCycle, nFrames ); + } + else if ( pTsi->nNonXRegs == 0 ) + { +// printf( "All registers have X-valued states. Phase abstraction cannot be done.\n" ); + } + else if ( !Saig_ManFindRegisters( pTsi, nFrames, 0, fVerbose ) ) + { +// printf( "There is no registers to abstract with %d frames.\n", nFrames ); + } + else + pNew = Saig_ManPerformAbstraction( pTsi, nFrames, fVerbose ); + Saig_TsiStop( pTsi ); + if ( pNew == NULL ) + pNew = Aig_ManDupSimple( p ); + if ( Aig_ManCiNum(pNew) == Aig_ManRegNum(pNew) ) + { + Aig_ManStop( pNew); + pNew = Aig_ManDupSimple( p ); + } + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Derives CEX for the original AIG from CEX of the unrolled AIG.] + + Description [The number of PIs of the given CEX should divide by the number + of PIs of the original AIG without a remainder.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Saig_PhaseTranslateCex( Aig_Man_t * p, Abc_Cex_t * pCex ) +{ + Abc_Cex_t * pNew; + int i, k, iFrame, nFrames; + // make sure the PI count of the AIG is a multiple of the PI count of the CEX + // if this is not true, the CEX is not derived as the result of unrolling of pAig + // or the unrolled CEX went through transformations that change the PI count + if ( pCex->nPis % Saig_ManPiNum(p) != 0 ) + { + printf( "The PI count in the AIG and in the CEX do not match.\n" ); + return NULL; + } + // get the number of unrolled frames + nFrames = pCex->nPis / Saig_ManPiNum(p); + // get the frame where it fails + iFrame = pCex->iFrame * nFrames + pCex->iPo / Saig_ManPoNum(p); + // start a new CEX (assigns: p->nRegs, p->nPis, p->nBits) + pNew = Abc_CexAlloc( Saig_ManRegNum(p), Saig_ManPiNum(p), iFrame+1 ); + assert( pNew->nBits == pNew->nPis * (iFrame + 1) + pNew->nRegs ); + // now assign the failed frame and the failed PO (p->iFrame and p->iPo) + pNew->iFrame = iFrame; + pNew->iPo = pCex->iPo % Saig_ManPoNum(p); + // copy the bit data + for ( i = pCex->nRegs, k = pNew->nRegs; k < pNew->nBits; k++, i++ ) + if ( Abc_InfoHasBit( pCex->pData, i ) ) + Abc_InfoSetBit( pNew->pData, k ); + assert( i <= pCex->nBits ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigRefSat.c b/yosys/abc/src/aig/saig/saigRefSat.c new file mode 100644 index 00000000000..fc03e182581 --- /dev/null +++ b/yosys/abc/src/aig/saig/saigRefSat.c @@ -0,0 +1,986 @@ +/**CFile**************************************************************** + + FileName [saigRefSat.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [SAT based refinement of a counter-example.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigRefSat.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" +#include "sat/cnf/cnf.h" +#include "sat/bsat/satSolver.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// local manager +typedef struct Saig_RefMan_t_ Saig_RefMan_t; +struct Saig_RefMan_t_ +{ + // user data + Aig_Man_t * pAig; // user's AIG + Abc_Cex_t * pCex; // user's CEX + int nInputs; // the number of first inputs to skip + int fVerbose; // verbose flag + // unrolling + Aig_Man_t * pFrames; // unrolled timeframes + Vec_Int_t * vMapPiF2A; // mapping of frame PIs into real PIs +}; + +// performs ternary simulation +extern int Saig_ManSimDataInit( Aig_Man_t * p, Abc_Cex_t * pCex, Vec_Ptr_t * vSimInfo, Vec_Int_t * vRes ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Maps array of frame PI IDs into array of original PI IDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_RefManReason2Inputs( Saig_RefMan_t * p, Vec_Int_t * vReasons ) +{ + Vec_Int_t * vOriginal, * vVisited; + int i, Entry; + vOriginal = Vec_IntAlloc( Saig_ManPiNum(p->pAig) ); + vVisited = Vec_IntStart( Saig_ManPiNum(p->pAig) ); + Vec_IntForEachEntry( vReasons, Entry, i ) + { + int iInput = Vec_IntEntry( p->vMapPiF2A, 2*Entry ); + assert( iInput >= 0 && iInput < Aig_ManCiNum(p->pAig) ); + if ( Vec_IntEntry(vVisited, iInput) == 0 ) + Vec_IntPush( vOriginal, iInput ); + Vec_IntAddToEntry( vVisited, iInput, 1 ); + } + Vec_IntFree( vVisited ); + return vOriginal; +} + +/**Function************************************************************* + + Synopsis [Creates the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Saig_RefManReason2Cex( Saig_RefMan_t * p, Vec_Int_t * vReasons ) +{ + Abc_Cex_t * pCare; + int i, Entry, iInput, iFrame; + pCare = Abc_CexDup( p->pCex, p->pCex->nRegs ); + memset( pCare->pData, 0, sizeof(unsigned) * Abc_BitWordNum(pCare->nBits) ); + Vec_IntForEachEntry( vReasons, Entry, i ) + { + assert( Entry >= 0 && Entry < Aig_ManCiNum(p->pFrames) ); + iInput = Vec_IntEntry( p->vMapPiF2A, 2*Entry ); + iFrame = Vec_IntEntry( p->vMapPiF2A, 2*Entry+1 ); + Abc_InfoSetBit( pCare->pData, pCare->nRegs + pCare->nPis * iFrame + iInput ); + } + return pCare; +} + +/**Function************************************************************* + + Synopsis [Returns reasons for the property to fail.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_RefManFindReason_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Int_t * vPrios, Vec_Int_t * vReasons ) +{ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Aig_ObjIsCi(pObj) ) + { + Vec_IntPush( vReasons, Aig_ObjCioId(pObj) ); + return; + } + assert( Aig_ObjIsNode(pObj) ); + if ( pObj->fPhase ) + { + Saig_RefManFindReason_rec( p, Aig_ObjFanin0(pObj), vPrios, vReasons ); + Saig_RefManFindReason_rec( p, Aig_ObjFanin1(pObj), vPrios, vReasons ); + } + else + { + int fPhase0 = Aig_ObjFaninC0(pObj) ^ Aig_ObjFanin0(pObj)->fPhase; + int fPhase1 = Aig_ObjFaninC1(pObj) ^ Aig_ObjFanin1(pObj)->fPhase; + assert( !fPhase0 || !fPhase1 ); + if ( !fPhase0 && fPhase1 ) + Saig_RefManFindReason_rec( p, Aig_ObjFanin0(pObj), vPrios, vReasons ); + else if ( fPhase0 && !fPhase1 ) + Saig_RefManFindReason_rec( p, Aig_ObjFanin1(pObj), vPrios, vReasons ); + else + { + int iPrio0 = Vec_IntEntry( vPrios, Aig_ObjFaninId0(pObj) ); + int iPrio1 = Vec_IntEntry( vPrios, Aig_ObjFaninId1(pObj) ); + if ( iPrio0 <= iPrio1 ) + Saig_RefManFindReason_rec( p, Aig_ObjFanin0(pObj), vPrios, vReasons ); + else + Saig_RefManFindReason_rec( p, Aig_ObjFanin1(pObj), vPrios, vReasons ); + } + } +} + +/**Function************************************************************* + + Synopsis [Returns reasons for the property to fail.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_RefManFindReason( Saig_RefMan_t * p ) +{ + Aig_Obj_t * pObj; + Vec_Int_t * vPrios, * vPi2Prio, * vReasons; + int i, CountPrios; + + vPi2Prio = Vec_IntStartFull( Saig_ManPiNum(p->pAig) ); + vPrios = Vec_IntStartFull( Aig_ManObjNumMax(p->pFrames) ); + + // set PI values according to CEX + CountPrios = 0; + Aig_ManConst1(p->pFrames)->fPhase = 1; + Aig_ManForEachCi( p->pFrames, pObj, i ) + { + int iInput = Vec_IntEntry( p->vMapPiF2A, 2*i ); + int iFrame = Vec_IntEntry( p->vMapPiF2A, 2*i+1 ); + pObj->fPhase = Abc_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput ); + // assign priority + if ( Vec_IntEntry(vPi2Prio, iInput) == ~0 ) + Vec_IntWriteEntry( vPi2Prio, iInput, CountPrios++ ); +// Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), Vec_IntEntry(vPi2Prio, iInput) ); + Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), i ); + } +// printf( "Priority numbers = %d.\n", CountPrios ); + Vec_IntFree( vPi2Prio ); + + // traverse and set the priority + Aig_ManForEachNode( p->pFrames, pObj, i ) + { + int fPhase0 = Aig_ObjFaninC0(pObj) ^ Aig_ObjFanin0(pObj)->fPhase; + int fPhase1 = Aig_ObjFaninC1(pObj) ^ Aig_ObjFanin1(pObj)->fPhase; + int iPrio0 = Vec_IntEntry( vPrios, Aig_ObjFaninId0(pObj) ); + int iPrio1 = Vec_IntEntry( vPrios, Aig_ObjFaninId1(pObj) ); + pObj->fPhase = fPhase0 && fPhase1; + if ( fPhase0 && fPhase1 ) // both are one + Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), Abc_MaxInt(iPrio0, iPrio1) ); + else if ( !fPhase0 && fPhase1 ) + Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), iPrio0 ); + else if ( fPhase0 && !fPhase1 ) + Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), iPrio1 ); + else // both are zero + Vec_IntWriteEntry( vPrios, Aig_ObjId(pObj), Abc_MinInt(iPrio0, iPrio1) ); + } + // check the property output + pObj = Aig_ManCo( p->pFrames, 0 ); + assert( (int)Aig_ObjFanin0(pObj)->fPhase == Aig_ObjFaninC0(pObj) ); + + // select the reason + vReasons = Vec_IntAlloc( 100 ); + Aig_ManIncrementTravId( p->pFrames ); + if ( !Aig_ObjIsConst1(Aig_ObjFanin0(pObj)) ) + Saig_RefManFindReason_rec( p->pFrames, Aig_ObjFanin0(pObj), vPrios, vReasons ); + Vec_IntFree( vPrios ); + return vReasons; +} + + +/**Function************************************************************* + + Synopsis [Collect nodes in the unrolled timeframes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManUnrollCollect_rec( Aig_Man_t * pAig, Aig_Obj_t * pObj, Vec_Int_t * vObjs, Vec_Int_t * vRoots ) +{ + if ( Aig_ObjIsTravIdCurrent(pAig, pObj) ) + return; + Aig_ObjSetTravIdCurrent(pAig, pObj); + if ( Aig_ObjIsCo(pObj) ) + Saig_ManUnrollCollect_rec( pAig, Aig_ObjFanin0(pObj), vObjs, vRoots ); + else if ( Aig_ObjIsNode(pObj) ) + { + Saig_ManUnrollCollect_rec( pAig, Aig_ObjFanin0(pObj), vObjs, vRoots ); + Saig_ManUnrollCollect_rec( pAig, Aig_ObjFanin1(pObj), vObjs, vRoots ); + } + if ( vRoots && Saig_ObjIsLo( pAig, pObj ) ) + Vec_IntPush( vRoots, Aig_ObjId( Saig_ObjLoToLi(pAig, pObj) ) ); + Vec_IntPush( vObjs, Aig_ObjId(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Derive unrolled timeframes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManUnrollWithCex( Aig_Man_t * pAig, Abc_Cex_t * pCex, int nInputs, Vec_Int_t ** pvMapPiF2A ) +{ + Aig_Man_t * pFrames; // unrolled timeframes + Vec_Vec_t * vFrameCos; // the list of COs per frame + Vec_Vec_t * vFrameObjs; // the list of objects per frame + Vec_Int_t * vRoots, * vObjs; + Aig_Obj_t * pObj; + int i, f; + // sanity checks + assert( Saig_ManPiNum(pAig) == pCex->nPis ); + assert( Saig_ManRegNum(pAig) == pCex->nRegs ); + assert( pCex->iPo >= 0 && pCex->iPo < Saig_ManPoNum(pAig) ); + + // map PIs of the unrolled frames into PIs of the original design + *pvMapPiF2A = Vec_IntAlloc( 1000 ); + + // collect COs and Objs visited in each frame + vFrameCos = Vec_VecStart( pCex->iFrame+1 ); + vFrameObjs = Vec_VecStart( pCex->iFrame+1 ); + // initialized the topmost frame + pObj = Aig_ManCo( pAig, pCex->iPo ); + Vec_VecPushInt( vFrameCos, pCex->iFrame, Aig_ObjId(pObj) ); + for ( f = pCex->iFrame; f >= 0; f-- ) + { + // collect nodes starting from the roots + Aig_ManIncrementTravId( pAig ); + vRoots = Vec_VecEntryInt( vFrameCos, f ); + Aig_ManForEachObjVec( vRoots, pAig, pObj, i ) + Saig_ManUnrollCollect_rec( pAig, pObj, + Vec_VecEntryInt(vFrameObjs, f), + (Vec_Int_t *)(f ? Vec_VecEntry(vFrameCos, f-1) : NULL) ); + } + + // derive unrolled timeframes + pFrames = Aig_ManStart( 10000 ); + pFrames->pName = Abc_UtilStrsav( pAig->pName ); + pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); + // initialize the flops + Saig_ManForEachLo( pAig, pObj, i ) + pObj->pData = Aig_NotCond( Aig_ManConst1(pFrames), !Abc_InfoHasBit(pCex->pData, i) ); + // iterate through the frames + for ( f = 0; f <= pCex->iFrame; f++ ) + { + // construct + vObjs = Vec_VecEntryInt( vFrameObjs, f ); + Aig_ManForEachObjVec( vObjs, pAig, pObj, i ) + { + if ( Aig_ObjIsNode(pObj) ) + pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + else if ( Aig_ObjIsCo(pObj) ) + pObj->pData = Aig_ObjChild0Copy(pObj); + else if ( Aig_ObjIsConst1(pObj) ) + pObj->pData = Aig_ManConst1(pFrames); + else if ( Saig_ObjIsPi(pAig, pObj) ) + { + if ( Aig_ObjCioId(pObj) < nInputs ) + { + int iBit = pCex->nRegs + f * pCex->nPis + Aig_ObjCioId(pObj); + pObj->pData = Aig_NotCond( Aig_ManConst1(pFrames), !Abc_InfoHasBit(pCex->pData, iBit) ); + } + else + { + pObj->pData = Aig_ObjCreateCi( pFrames ); + Vec_IntPush( *pvMapPiF2A, Aig_ObjCioId(pObj) ); + Vec_IntPush( *pvMapPiF2A, f ); + } + } + } + if ( f == pCex->iFrame ) + break; + // transfer + vRoots = Vec_VecEntryInt( vFrameCos, f ); + Aig_ManForEachObjVec( vRoots, pAig, pObj, i ) + Saig_ObjLiToLo( pAig, pObj )->pData = pObj->pData; + } + // create output + pObj = Aig_ManCo( pAig, pCex->iPo ); + Aig_ObjCreateCo( pFrames, Aig_Not((Aig_Obj_t *)pObj->pData) ); + Aig_ManSetRegNum( pFrames, 0 ); + // cleanup + Vec_VecFree( vFrameCos ); + Vec_VecFree( vFrameObjs ); + // finallize + Aig_ManCleanup( pFrames ); + // return + return pFrames; +} + +/**Function************************************************************* + + Synopsis [Creates refinement manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Saig_RefMan_t * Saig_RefManStart( Aig_Man_t * pAig, Abc_Cex_t * pCex, int nInputs, int fVerbose ) +{ + Saig_RefMan_t * p; + p = ABC_CALLOC( Saig_RefMan_t, 1 ); + p->pAig = pAig; + p->pCex = pCex; + p->nInputs = nInputs; + p->fVerbose = fVerbose; + p->pFrames = Saig_ManUnrollWithCex( pAig, pCex, nInputs, &p->vMapPiF2A ); + return p; +} + +/**Function************************************************************* + + Synopsis [Destroys refinement manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_RefManStop( Saig_RefMan_t * p ) +{ + Aig_ManStopP( &p->pFrames ); + Vec_IntFreeP( &p->vMapPiF2A ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Sets phase bits in the timeframe AIG.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_RefManSetPhases( Saig_RefMan_t * p, Abc_Cex_t * pCare, int fValue1 ) +{ + Aig_Obj_t * pObj; + int i, iFrame, iInput; + Aig_ManConst1( p->pFrames )->fPhase = 1; + Aig_ManForEachCi( p->pFrames, pObj, i ) + { + iInput = Vec_IntEntry( p->vMapPiF2A, 2*i ); + iFrame = Vec_IntEntry( p->vMapPiF2A, 2*i+1 ); + pObj->fPhase = Abc_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput ); + // update value if it is a don't-care + if ( pCare && !Abc_InfoHasBit( pCare->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput ) ) + pObj->fPhase = fValue1; + } + Aig_ManForEachNode( p->pFrames, pObj, i ) + pObj->fPhase = ( Aig_ObjFanin0(pObj)->fPhase ^ Aig_ObjFaninC0(pObj) ) + & ( Aig_ObjFanin1(pObj)->fPhase ^ Aig_ObjFaninC1(pObj) ); + Aig_ManForEachCo( p->pFrames, pObj, i ) + pObj->fPhase = ( Aig_ObjFanin0(pObj)->fPhase ^ Aig_ObjFaninC0(pObj) ); + pObj = Aig_ManCo( p->pFrames, 0 ); + return pObj->fPhase; +} + +/**Function************************************************************* + + Synopsis [Tries to remove literals from abstraction.] + + Description [The literals are sorted more desirable first.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Vec_t * Saig_RefManOrderLiterals( Saig_RefMan_t * p, Vec_Int_t * vVar2PiId, Vec_Int_t * vAssumps ) +{ + Vec_Vec_t * vLits; + Vec_Int_t * vVar2New; + int i, Entry, iInput, iFrame; + // collect literals + vLits = Vec_VecAlloc( 100 ); + vVar2New = Vec_IntStartFull( Saig_ManPiNum(p->pAig) ); + Vec_IntForEachEntry( vAssumps, Entry, i ) + { + int iPiNum = Vec_IntEntry( vVar2PiId, lit_var(Entry) ); + assert( iPiNum >= 0 && iPiNum < Aig_ManCiNum(p->pFrames) ); + iInput = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum ); + iFrame = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum+1 ); +// Abc_InfoSetBit( pCare->pData, pCare->nRegs + pCare->nPis * iFrame + iInput ); + if ( Vec_IntEntry( vVar2New, iInput ) == ~0 ) + Vec_IntWriteEntry( vVar2New, iInput, Vec_VecSize(vLits) ); + Vec_VecPushInt( vLits, Vec_IntEntry( vVar2New, iInput ), Entry ); + } + Vec_IntFree( vVar2New ); + return vLits; +} + + +/**Function************************************************************* + + Synopsis [Generate the care set using SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Saig_RefManCreateCex( Saig_RefMan_t * p, Vec_Int_t * vVar2PiId, Vec_Int_t * vAssumps ) +{ + Abc_Cex_t * pCare; + int i, Entry, iInput, iFrame; + // create counter-example + pCare = Abc_CexDup( p->pCex, p->pCex->nRegs ); + memset( pCare->pData, 0, sizeof(unsigned) * Abc_BitWordNum(pCare->nBits) ); + Vec_IntForEachEntry( vAssumps, Entry, i ) + { + int iPiNum = Vec_IntEntry( vVar2PiId, lit_var(Entry) ); + assert( iPiNum >= 0 && iPiNum < Aig_ManCiNum(p->pFrames) ); + iInput = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum ); + iFrame = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum+1 ); + Abc_InfoSetBit( pCare->pData, pCare->nRegs + pCare->nPis * iFrame + iInput ); + } + return pCare; +} + +/**Function************************************************************* + + Synopsis [Generate the care set using SAT solver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Saig_RefManRunSat( Saig_RefMan_t * p, int fNewOrder ) +{ + int nConfLimit = 1000000; + Abc_Cex_t * pCare; + Cnf_Dat_t * pCnf; + sat_solver * pSat; + Aig_Obj_t * pObj; + Vec_Vec_t * vLits = NULL; + Vec_Int_t * vAssumps, * vVar2PiId; + int i, k, Entry, RetValue;//, f = 0, Counter = 0; + int nCoreLits, * pCoreLits; + clock_t clk = clock(); + // create CNF + assert( Aig_ManRegNum(p->pFrames) == 0 ); +// pCnf = Cnf_Derive( p->pFrames, 0 ); // too slow + pCnf = Cnf_DeriveSimple( p->pFrames, 0 ); + RetValue = Saig_RefManSetPhases( p, NULL, 0 ); + if ( RetValue ) + { + printf( "Constructed frames are incorrect.\n" ); + Cnf_DataFree( pCnf ); + return NULL; + } + Cnf_DataTranformPolarity( pCnf, 0 ); + // create SAT solver + pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + if ( pSat == NULL ) + { + Cnf_DataFree( pCnf ); + return NULL; + } +//Abc_PrintTime( 1, "Preparing", clock() - clk ); + // look for a true counter-example + if ( p->nInputs > 0 ) + { + RetValue = sat_solver_solve( pSat, NULL, NULL, + (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + if ( RetValue == l_False ) + { + printf( "The problem is trivially UNSAT. The CEX is real.\n" ); + // create counter-example + pCare = Abc_CexDup( p->pCex, p->pCex->nRegs ); + memset( pCare->pData, 0, sizeof(unsigned) * Abc_BitWordNum(pCare->nBits) ); + return pCare; + } + // the problem is SAT - it is expected + } + // create assumptions + vVar2PiId = Vec_IntStartFull( pCnf->nVars ); + vAssumps = Vec_IntAlloc( Aig_ManCiNum(p->pFrames) ); + Aig_ManForEachCi( p->pFrames, pObj, i ) + { +// RetValue = Abc_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput ); +// Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !RetValue ) ); + Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 1 ) ); + Vec_IntWriteEntry( vVar2PiId, pCnf->pVarNums[Aig_ObjId(pObj)], i ); + } + + // reverse the order of assumptions +// if ( fNewOrder ) +// Vec_IntReverseOrder( vAssumps ); + + if ( fNewOrder ) + { + // create literals + vLits = Saig_RefManOrderLiterals( p, vVar2PiId, vAssumps ); + // sort literals + Vec_VecSort( vLits, 1 ); + // save literals + Vec_IntClear( vAssumps ); + Vec_VecForEachEntryInt( vLits, Entry, i, k ) + Vec_IntPush( vAssumps, Entry ); + + for ( i = 0; i < Vec_VecSize(vLits); i++ ) + printf( "%d ", Vec_IntSize( Vec_VecEntryInt(vLits, i) ) ); + printf( "\n" ); + + if ( p->fVerbose ) + printf( "Total PIs = %d. Essential PIs = %d.\n", + Saig_ManPiNum(p->pAig) - p->nInputs, Vec_VecSize(vLits) ); + } + + // solve +clk = clock(); + RetValue = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), + (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); +//Abc_PrintTime( 1, "Solving", clock() - clk ); + if ( RetValue != l_False ) + { + if ( RetValue == l_True ) + printf( "Internal Error!!! The resulting problem is SAT.\n" ); + else + printf( "Internal Error!!! SAT solver timed out.\n" ); + Cnf_DataFree( pCnf ); + sat_solver_delete( pSat ); + Vec_IntFree( vAssumps ); + Vec_IntFree( vVar2PiId ); + return NULL; + } + assert( RetValue == l_False ); // UNSAT + + // get relevant SAT literals + nCoreLits = sat_solver_final( pSat, &pCoreLits ); + assert( nCoreLits > 0 ); + if ( p->fVerbose ) + printf( "AnalizeFinal selected %d assumptions (out of %d). Conflicts = %d.\n", + nCoreLits, Vec_IntSize(vAssumps), (int)pSat->stats.conflicts ); + + // save literals + Vec_IntClear( vAssumps ); + for ( i = 0; i < nCoreLits; i++ ) + Vec_IntPush( vAssumps, pCoreLits[i] ); + + + // create literals + vLits = Saig_RefManOrderLiterals( p, vVar2PiId, vAssumps ); + // sort literals +// Vec_VecSort( vLits, 0 ); + // save literals + Vec_IntClear( vAssumps ); + Vec_VecForEachEntryInt( vLits, Entry, i, k ) + Vec_IntPush( vAssumps, Entry ); + +// for ( i = 0; i < Vec_VecSize(vLits); i++ ) +// printf( "%d ", Vec_IntSize( Vec_VecEntryInt(vLits, i) ) ); +// printf( "\n" ); + + if ( p->fVerbose ) + printf( "Total PIs = %d. Essential PIs = %d.\n", + Saig_ManPiNum(p->pAig) - p->nInputs, Vec_VecSize(vLits) ); +/* + // try assumptions in different order + RetValue = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), + (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + printf( "Assumpts = %2d. Intermediate instance is %5s. Conflicts = %2d.\n", + Vec_IntSize(vAssumps), (RetValue == l_False ? "UNSAT" : "SAT"), (int)pSat->stats.conflicts ); + + // create different sets of assumptions + Counter = Vec_VecSize(vLits); + for ( f = 0; f < Vec_VecSize(vLits); f++ ) + { + Vec_IntClear( vAssumps ); + Vec_VecForEachEntryInt( vLits, Entry, i, k ) + if ( i != f ) + Vec_IntPush( vAssumps, Entry ); + + // try the new assumptions + RetValue = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), + (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + printf( "Assumpts = %2d. Intermediate instance is %5s. Conflicts = %2d.\n", + Vec_IntSize(vAssumps), RetValue == l_False ? "UNSAT" : "SAT", (int)pSat->stats.conflicts ); + if ( RetValue != l_False ) + continue; + + // UNSAT - remove literals + Vec_IntClear( Vec_VecEntryInt(vLits, f) ); + Counter--; + } + + for ( i = 0; i < Vec_VecSize(vLits); i++ ) + printf( "%d ", Vec_IntSize( Vec_VecEntryInt(vLits, i) ) ); + printf( "\n" ); + + if ( p->fVerbose ) + printf( "Total PIs = %d. Essential PIs = %d.\n", + Saig_ManPiNum(p->pAig) - p->nInputs, Counter ); + + // save literals + Vec_IntClear( vAssumps ); + Vec_VecForEachEntryInt( vLits, Entry, i, k ) + Vec_IntPush( vAssumps, Entry ); +*/ + // create counter-example + pCare = Saig_RefManCreateCex( p, vVar2PiId, vAssumps ); + + // cleanup + Cnf_DataFree( pCnf ); + sat_solver_delete( pSat ); + Vec_IntFree( vAssumps ); + Vec_IntFree( vVar2PiId ); + Vec_VecFreeP( &vLits ); + + // verify counter-example + RetValue = Saig_RefManSetPhases( p, pCare, 0 ); + if ( RetValue ) + printf( "Reduced CEX verification has failed.\n" ); + RetValue = Saig_RefManSetPhases( p, pCare, 1 ); + if ( RetValue ) + printf( "Reduced CEX verification has failed.\n" ); + return pCare; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_RefManRefineWithSat( Saig_RefMan_t * p, Vec_Int_t * vAigPis ) +{ + int nConfLimit = 1000000; + Cnf_Dat_t * pCnf; + sat_solver * pSat; + Aig_Obj_t * pObj; + Vec_Vec_t * vLits; + Vec_Int_t * vReasons, * vAssumps, * vVisited, * vVar2PiId; + int i, k, f, Entry, RetValue, Counter; + + // create CNF and SAT solver + pCnf = Cnf_DeriveSimple( p->pFrames, 0 ); + pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + if ( pSat == NULL ) + { + Cnf_DataFree( pCnf ); + return NULL; + } + + // mark used AIG inputs + vVisited = Vec_IntStart( Saig_ManPiNum(p->pAig) ); + Vec_IntForEachEntry( vAigPis, Entry, i ) + { + assert( Entry >= 0 && Entry < Aig_ManCiNum(p->pAig) ); + Vec_IntWriteEntry( vVisited, Entry, 1 ); + } + + // create assumptions + vVar2PiId = Vec_IntStartFull( pCnf->nVars ); + vAssumps = Vec_IntAlloc( Aig_ManCiNum(p->pFrames) ); + Aig_ManForEachCi( p->pFrames, pObj, i ) + { + int iInput = Vec_IntEntry( p->vMapPiF2A, 2*i ); + int iFrame = Vec_IntEntry( p->vMapPiF2A, 2*i+1 ); + if ( Vec_IntEntry(vVisited, iInput) == 0 ) + continue; + RetValue = Abc_InfoHasBit( p->pCex->pData, p->pCex->nRegs + p->pCex->nPis * iFrame + iInput ); + Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], !RetValue ) ); +// Vec_IntPush( vAssumps, toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 1 ) ); + Vec_IntWriteEntry( vVar2PiId, pCnf->pVarNums[Aig_ObjId(pObj)], i ); + } + Vec_IntFree( vVisited ); + + // try assumptions in different order + RetValue = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), + (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + printf( "Assumpts = %2d. Intermediate instance is %5s. Conflicts = %2d.\n", + Vec_IntSize(vAssumps), (RetValue == l_False ? "UNSAT" : "SAT"), (int)pSat->stats.conflicts ); + +/* + // AnalizeFinal does not work because it implications propagate directly + // and SAT solver does not kick in (the number of conflicts in 0). + + // count the number of lits in the unsat core + { + int nCoreLits, * pCoreLits; + nCoreLits = sat_solver_final( pSat, &pCoreLits ); + assert( nCoreLits > 0 ); + + // count the number of flops + vVisited = Vec_IntStart( Saig_ManPiNum(p->pAig) ); + for ( i = 0; i < nCoreLits; i++ ) + { + int iPiNum = Vec_IntEntry( vVar2PiId, lit_var(pCoreLits[i]) ); + int iInput = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum ); + int iFrame = Vec_IntEntry( p->vMapPiF2A, 2*iPiNum+1 ); + Vec_IntWriteEntry( vVisited, iInput, 1 ); + } + // count the number of entries + Counter = 0; + Vec_IntForEachEntry( vVisited, Entry, i ) + Counter += Entry; + Vec_IntFree( vVisited ); + +// if ( p->fVerbose ) + printf( "AnalizeFinal: Assumptions %d (out of %d). Essential PIs = %d. Conflicts = %d.\n", + nCoreLits, Vec_IntSize(vAssumps), Counter, (int)pSat->stats.conflicts ); + } +*/ + + // derive literals + vLits = Saig_RefManOrderLiterals( p, vVar2PiId, vAssumps ); + for ( i = 0; i < Vec_VecSize(vLits); i++ ) + printf( "%d ", Vec_IntSize( Vec_VecEntryInt(vLits, i) ) ); + printf( "\n" ); + + // create different sets of assumptions + Counter = Vec_VecSize(vLits); + for ( f = 0; f < Vec_VecSize(vLits); f++ ) + { + Vec_IntClear( vAssumps ); + Vec_VecForEachEntryInt( vLits, Entry, i, k ) + if ( i != f ) + Vec_IntPush( vAssumps, Entry ); + + // try the new assumptions + RetValue = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), + (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + printf( "Assumpts = %2d. Intermediate instance is %5s. Conflicts = %2d.\n", + Vec_IntSize(vAssumps), RetValue == l_False ? "UNSAT" : "SAT", (int)pSat->stats.conflicts ); + if ( RetValue != l_False ) + continue; + + // UNSAT - remove literals + Vec_IntClear( Vec_VecEntryInt(vLits, f) ); + Counter--; + } + + for ( i = 0; i < Vec_VecSize(vLits); i++ ) + printf( "%d ", Vec_IntSize( Vec_VecEntryInt(vLits, i) ) ); + printf( "\n" ); + + // create assumptions + Vec_IntClear( vAssumps ); + Vec_VecForEachEntryInt( vLits, Entry, i, k ) + Vec_IntPush( vAssumps, Entry ); + + // try assumptions in different order + RetValue = sat_solver_solve( pSat, Vec_IntArray(vAssumps), Vec_IntArray(vAssumps) + Vec_IntSize(vAssumps), + (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + printf( "Assumpts = %2d. Intermediate instance is %5s. Conflicts = %2d.\n", + Vec_IntSize(vAssumps), (RetValue == l_False ? "UNSAT" : "SAT"), (int)pSat->stats.conflicts ); + +// if ( p->fVerbose ) +// printf( "Total PIs = %d. Essential PIs = %d.\n", +// Saig_ManPiNum(p->pAig) - p->nInputs, Counter ); + + + // transform assumptions into reasons + vReasons = Vec_IntAlloc( 100 ); + Vec_IntForEachEntry( vAssumps, Entry, i ) + { + int iPiNum = Vec_IntEntry( vVar2PiId, lit_var(Entry) ); + assert( iPiNum >= 0 && iPiNum < Aig_ManCiNum(p->pFrames) ); + Vec_IntPush( vReasons, iPiNum ); + } + + // cleanup + Cnf_DataFree( pCnf ); + sat_solver_delete( pSat ); + Vec_IntFree( vAssumps ); + Vec_IntFree( vVar2PiId ); + Vec_VecFreeP( &vLits ); + + return vReasons; +} + +/**Function************************************************************* + + Synopsis [SAT-based refinement of the counter-example.] + + Description [The first parameter (nInputs) indicates how many first + primary inputs to skip without considering as care candidates.] + + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Saig_ManFindCexCareBits( Aig_Man_t * pAig, Abc_Cex_t * pCex, int nInputs, int fNewOrder, int fVerbose ) +{ + Saig_RefMan_t * p; + Vec_Int_t * vReasons; + Abc_Cex_t * pCare; + clock_t clk = clock(); + + clk = clock(); + p = Saig_RefManStart( pAig, pCex, nInputs, fVerbose ); + vReasons = Saig_RefManFindReason( p ); + +if ( fVerbose ) +Aig_ManPrintStats( p->pFrames ); + +// if ( fVerbose ) + { + Vec_Int_t * vRes = Saig_RefManReason2Inputs( p, vReasons ); + printf( "Frame PIs = %4d (essential = %4d) AIG PIs = %4d (essential = %4d) ", + Aig_ManCiNum(p->pFrames), Vec_IntSize(vReasons), + Saig_ManPiNum(p->pAig) - p->nInputs, Vec_IntSize(vRes) ); +ABC_PRT( "Time", clock() - clk ); + + Vec_IntFree( vRes ); + +/* + //////////////////////////////////// + Vec_IntFree( vReasons ); + vReasons = Saig_RefManRefineWithSat( p, vRes ); + //////////////////////////////////// + + Vec_IntFree( vRes ); + vRes = Saig_RefManReason2Inputs( p, vReasons ); + printf( "Frame PIs = %4d (essential = %4d) AIG PIs = %4d (essential = %4d) ", + Aig_ManCiNum(p->pFrames), Vec_IntSize(vReasons), + Saig_ManPiNum(p->pAig) - p->nInputs, Vec_IntSize(vRes) ); + + Vec_IntFree( vRes ); +ABC_PRT( "Time", clock() - clk ); +*/ + } + + pCare = Saig_RefManReason2Cex( p, vReasons ); + Vec_IntFree( vReasons ); + Saig_RefManStop( p ); + +if ( fVerbose ) +Abc_CexPrintStats( pCex ); +if ( fVerbose ) +Abc_CexPrintStats( pCare ); + + return pCare; +} + +/**Function************************************************************* + + Synopsis [Returns the array of PIs for flops that should not be absracted.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_ManExtendCounterExampleTest3( Aig_Man_t * pAig, int iFirstFlopPi, Abc_Cex_t * pCex, int fVerbose ) +{ + Saig_RefMan_t * p; + Vec_Int_t * vRes, * vReasons; + clock_t clk; + if ( Saig_ManPiNum(pAig) != pCex->nPis ) + { + printf( "Saig_ManExtendCounterExampleTest3(): The PI count of AIG (%d) does not match that of cex (%d).\n", + Aig_ManCiNum(pAig), pCex->nPis ); + return NULL; + } + +clk = clock(); + + p = Saig_RefManStart( pAig, pCex, iFirstFlopPi, fVerbose ); + vReasons = Saig_RefManFindReason( p ); + vRes = Saig_RefManReason2Inputs( p, vReasons ); + +// if ( fVerbose ) + { + printf( "Frame PIs = %4d (essential = %4d) AIG PIs = %4d (essential = %4d) ", + Aig_ManCiNum(p->pFrames), Vec_IntSize(vReasons), + Saig_ManPiNum(p->pAig) - p->nInputs, Vec_IntSize(vRes) ); +ABC_PRT( "Time", clock() - clk ); + } + +/* + //////////////////////////////////// + Vec_IntFree( vReasons ); + vReasons = Saig_RefManRefineWithSat( p, vRes ); + //////////////////////////////////// + + // derive new result + Vec_IntFree( vRes ); + vRes = Saig_RefManReason2Inputs( p, vReasons ); +// if ( fVerbose ) + { + printf( "Frame PIs = %4d (essential = %4d) AIG PIs = %4d (essential = %4d) ", + Aig_ManCiNum(p->pFrames), Vec_IntSize(vReasons), + Saig_ManPiNum(p->pAig) - p->nInputs, Vec_IntSize(vRes) ); +ABC_PRT( "Time", clock() - clk ); + } +*/ + + Vec_IntFree( vReasons ); + Saig_RefManStop( p ); + return vRes; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigRetFwd.c b/yosys/abc/src/aig/saig/saigRetFwd.c new file mode 100644 index 00000000000..bac2ee4ab55 --- /dev/null +++ b/yosys/abc/src/aig/saig/saigRetFwd.c @@ -0,0 +1,248 @@ +/**CFile**************************************************************** + + FileName [saigRetFwd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Most-forward retiming.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigRetFwd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static inline Aig_Obj_t * Aig_ObjFanoutStatic( Aig_Obj_t * pObj, int i ) { return ((Aig_Obj_t **)pObj->pData)[i]; } +static inline void Aig_ObjSetFanoutStatic( Aig_Obj_t * pObj, Aig_Obj_t * pFan ) { ((Aig_Obj_t **)pObj->pData)[pObj->nRefs++] = pFan; } + +#define Aig_ObjForEachFanoutStatic( pObj, pFan, i ) \ + for ( i = 0; (i < (int)(pObj)->nRefs) && ((pFan) = Aig_ObjFanoutStatic(pObj, i)); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocate static fanout for all nodes in the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t ** Aig_ManStaticFanoutStart( Aig_Man_t * p ) +{ + Aig_Obj_t ** ppFanouts, * pObj; + int i, nFanouts, nFanoutsAlloc; + // allocate fanouts + nFanoutsAlloc = 2 * Aig_ManObjNumMax(p) - Aig_ManCiNum(p) - Aig_ManCoNum(p); + ppFanouts = ABC_ALLOC( Aig_Obj_t *, nFanoutsAlloc ); + // mark up storage + nFanouts = 0; + Aig_ManForEachObj( p, pObj, i ) + { + pObj->pData = ppFanouts + nFanouts; + nFanouts += pObj->nRefs; + pObj->nRefs = 0; + } + assert( nFanouts < nFanoutsAlloc ); + // add fanouts + Aig_ManForEachObj( p, pObj, i ) + { + if ( Aig_ObjChild0(pObj) ) + Aig_ObjSetFanoutStatic( Aig_ObjFanin0(pObj), pObj ); + if ( Aig_ObjChild1(pObj) ) + Aig_ObjSetFanoutStatic( Aig_ObjFanin1(pObj), pObj ); + } + return ppFanouts; +} + +/**Function************************************************************* + + Synopsis [Marks the objects reachable from the given object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_ManMarkAutonomous_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pFanout; + int i; + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + Aig_ObjForEachFanoutStatic( pObj, pFanout, i ) + Aig_ManMarkAutonomous_rec( p, pFanout ); +} + +/**Function************************************************************* + + Synopsis [Marks with current trav ID nodes reachable from Const1 and PIs.] + + Description [Returns the number of unreachable registers.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManMarkAutonomous( Aig_Man_t * p ) +{ + Aig_Obj_t ** ppFanouts; + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int i; + // temporarily connect register outputs to register inputs + Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) + { + pObjLo->pFanin0 = pObjLi; + pObjLi->nRefs = 1; + } + // mark nodes reachable from Const1 and PIs + Aig_ManIncrementTravId( p ); + ppFanouts = Aig_ManStaticFanoutStart( p ); + Aig_ManMarkAutonomous_rec( p, Aig_ManConst1(p) ); + Saig_ManForEachPi( p, pObj, i ) + Aig_ManMarkAutonomous_rec( p, pObj ); + ABC_FREE( ppFanouts ); + // disconnect LIs/LOs and label unreachable registers + Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) + { + assert( pObjLo->pFanin0 && pObjLi->nRefs == 1 ); + pObjLo->pFanin0 = NULL; + pObjLi->nRefs = 0; + } +} + +/**Function************************************************************* + + Synopsis [Derives the cut for forward retiming.] + + Description [Assumes topological ordering of the nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManRetimeForwardOne( Aig_Man_t * p, int * pnRegFixed, int * pnRegMoves ) +{ + Aig_Man_t * pNew; + Vec_Ptr_t * vCut; + Aig_Obj_t * pObj, * pFanin; + int i; + // mark the retimable nodes + Saig_ManMarkAutonomous( p ); + // mark the retimable registers with the fresh trav ID + Aig_ManIncrementTravId( p ); + *pnRegFixed = 0; + Saig_ManForEachLo( p, pObj, i ) + if ( Aig_ObjIsTravIdPrevious(p, pObj) ) + Aig_ObjSetTravIdCurrent(p, pObj); + else + (*pnRegFixed)++; + // mark all the nodes that can be retimed forward + *pnRegMoves = 0; + Aig_ManForEachNode( p, pObj, i ) + if ( Aig_ObjIsTravIdCurrent(p, Aig_ObjFanin0(pObj)) && Aig_ObjIsTravIdCurrent(p, Aig_ObjFanin1(pObj)) ) + { + Aig_ObjSetTravIdCurrent(p, pObj); + (*pnRegMoves)++; + } + // mark the remaining registers + Saig_ManForEachLo( p, pObj, i ) + Aig_ObjSetTravIdCurrent(p, pObj); + // find the cut (all such marked objects that fanout into unmarked nodes) + vCut = Vec_PtrAlloc( 1000 ); + Aig_ManIncrementTravId( p ); + Aig_ManForEachObj( p, pObj, i ) + { + if ( Aig_ObjIsTravIdPrevious(p, pObj) ) + continue; + pFanin = Aig_ObjFanin0(pObj); + if ( pFanin && Aig_ObjIsTravIdPrevious(p, pFanin) ) + { + Vec_PtrPush( vCut, pFanin ); + Aig_ObjSetTravIdCurrent( p, pFanin ); + } + pFanin = Aig_ObjFanin1(pObj); + if ( pFanin && Aig_ObjIsTravIdPrevious(p, pFanin) ) + { + Vec_PtrPush( vCut, pFanin ); + Aig_ObjSetTravIdCurrent( p, pFanin ); + } + } + // finally derive the new manager + pNew = Saig_ManRetimeDupForward( p, vCut ); + Vec_PtrFree( vCut ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Derives the cut for forward retiming.] + + Description [Assumes topological ordering of the nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManRetimeForward( Aig_Man_t * p, int nMaxIters, int fVerbose ) +{ + Aig_Man_t * pNew, * pTemp; + int i, nRegFixed, nRegMoves = 1; + abctime clk; + pNew = p; + for ( i = 0; i < nMaxIters && nRegMoves > 0; i++ ) + { + clk = Abc_Clock(); + pNew = Saig_ManRetimeForwardOne( pTemp = pNew, &nRegFixed, &nRegMoves ); + if ( fVerbose ) + { + printf( "%2d : And = %6d. Reg = %5d. Unret = %5d. Move = %6d. ", + i + 1, Aig_ManNodeNum(pTemp), Aig_ManRegNum(pTemp), nRegFixed, nRegMoves ); + ABC_PRT( "Time", Abc_Clock() - clk ); + } + if ( pTemp != p ) + Aig_ManStop( pTemp ); + } + clk = Abc_Clock(); + pNew = Aig_ManReduceLaches( pNew, fVerbose ); + if ( fVerbose ) + { + ABC_PRT( "Register sharing time", Abc_Clock() - clk ); + } + return pNew; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigRetMin.c b/yosys/abc/src/aig/saig/saigRetMin.c new file mode 100644 index 00000000000..a1bebd64507 --- /dev/null +++ b/yosys/abc/src/aig/saig/saigRetMin.c @@ -0,0 +1,705 @@ +/**CFile**************************************************************** + + FileName [saigRetMin.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Min-area retiming for the AIG.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigRetMin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" + +#include "opt/nwk/nwk.h" +#include "sat/cnf/cnf.h" +#include "sat/bsat/satSolver.h" +#include "sat/bsat/satStore.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Derives the initial state after backward retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_ManRetimeInitState( Aig_Man_t * p ) +{ + int nConfLimit = 1000000; + Vec_Int_t * vCiIds, * vInit = NULL; + Cnf_Dat_t * pCnf; + sat_solver * pSat; + Aig_Obj_t * pObj; + int i, RetValue, * pModel; + // solve the SAT problem + pCnf = Cnf_DeriveSimpleForRetiming( p ); + pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + if ( pSat == NULL ) + { + Cnf_DataFree( pCnf ); + return NULL; + } + RetValue = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + assert( RetValue != l_Undef ); + // create counter-example + if ( RetValue == l_True ) + { + // accumulate SAT variables of the CIs + vCiIds = Vec_IntAlloc( Aig_ManCiNum(p) ); + Aig_ManForEachCi( p, pObj, i ) + Vec_IntPush( vCiIds, pCnf->pVarNums[pObj->Id] ); + // create the model + pModel = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize ); + vInit = Vec_IntAllocArray( pModel, Aig_ManCiNum(p) ); + Vec_IntFree( vCiIds ); + } + sat_solver_delete( pSat ); + Cnf_DataFree( pCnf ); + return vInit; +} + +/**Function************************************************************* + + Synopsis [Uses UNSAT core to find the part of AIG to be excluded.] + + Description [Returns the number of the PO that appears in the UNSAT core.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManRetimeUnsatCore( Aig_Man_t * p, int fVerbose ) +{ + int fVeryVerbose = 0; + int nConfLimit = 1000000; + void * pSatCnf = NULL; + Intp_Man_t * pManProof; + Vec_Int_t * vCore = NULL; + Cnf_Dat_t * pCnf; + sat_solver * pSat; + Aig_Obj_t * pObj; + int * pClause1, * pClause2, * pLit, * pVars; + int i, RetValue, iBadPo, iClause, nVars, nPos; + // create the SAT solver + pCnf = Cnf_DeriveSimpleForRetiming( p ); + pSat = sat_solver_new(); + sat_solver_store_alloc( pSat ); + sat_solver_setnvars( pSat, pCnf->nVars ); + for ( i = 0; i < pCnf->nClauses; i++ ) + { + if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) ) + { + Cnf_DataFree( pCnf ); + sat_solver_delete( pSat ); + return -1; + } + } + sat_solver_store_mark_roots( pSat ); + // solve the problem + RetValue = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 ); + assert( RetValue != l_Undef ); + assert( RetValue == l_False ); + pSatCnf = sat_solver_store_release( pSat ); + sat_solver_delete( pSat ); + // derive the UNSAT core + pManProof = Intp_ManAlloc(); + vCore = (Vec_Int_t *)Intp_ManUnsatCore( pManProof, (Sto_Man_t *)pSatCnf, 0, fVeryVerbose ); + Intp_ManFree( pManProof ); + Sto_ManFree( (Sto_Man_t *)pSatCnf ); + // derive the set of variables on which the core depends + // collect the variable numbers + nVars = 0; + pVars = ABC_ALLOC( int, pCnf->nVars ); + memset( pVars, 0, sizeof(int) * pCnf->nVars ); + Vec_IntForEachEntry( vCore, iClause, i ) + { + pClause1 = pCnf->pClauses[iClause]; + pClause2 = pCnf->pClauses[iClause+1]; + for ( pLit = pClause1; pLit < pClause2; pLit++ ) + { + if ( pVars[ (*pLit) >> 1 ] == 0 ) + nVars++; + pVars[ (*pLit) >> 1 ] = 1; + if ( fVeryVerbose ) + printf( "%s%d ", ((*pLit) & 1)? "-" : "+", (*pLit) >> 1 ); + } + if ( fVeryVerbose ) + printf( "\n" ); + } + // collect the nodes + if ( fVeryVerbose ) { + Aig_ManForEachObj( p, pObj, i ) + if ( pCnf->pVarNums[pObj->Id] >= 0 && pVars[ pCnf->pVarNums[pObj->Id] ] == 1 ) + { + Aig_ObjPrint( p, pObj ); + printf( "\n" ); + } + } + // pick the first PO in the list + nPos = 0; + iBadPo = -1; + Aig_ManForEachCo( p, pObj, i ) + if ( pCnf->pVarNums[pObj->Id] >= 0 && pVars[ pCnf->pVarNums[pObj->Id] ] == 1 ) + { + if ( iBadPo == -1 ) + iBadPo = i; + nPos++; + } + if ( fVerbose ) + printf( "UNSAT core: %d clauses, %d variables, %d POs. ", Vec_IntSize(vCore), nVars, nPos ); + ABC_FREE( pVars ); + Vec_IntFree( vCore ); + Cnf_DataFree( pCnf ); + return iBadPo; +} + +/**Function************************************************************* + + Synopsis [Marks the TFI cone with the current traversal ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManMarkCone_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + if ( pObj == NULL ) + return; + if ( Aig_ObjIsTravIdCurrent( p, pObj ) ) + return; + Aig_ObjSetTravIdCurrent( p, pObj ); + Saig_ManMarkCone_rec( p, Aig_ObjFanin0(pObj) ); + Saig_ManMarkCone_rec( p, Aig_ObjFanin1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Counts the number of nodes to get registers after retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManRetimeCountCut( Aig_Man_t * p, Vec_Ptr_t * vCut ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj, * pFanin; + int i, RetValue; + // mark the cones + Aig_ManIncrementTravId( p ); + Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i ) + Saig_ManMarkCone_rec( p, pObj ); + // collect the new cut + vNodes = Vec_PtrAlloc( 1000 ); + Aig_ManForEachObj( p, pObj, i ) + { + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + continue; + pFanin = Aig_ObjFanin0( pObj ); + if ( pFanin && !pFanin->fMarkA && Aig_ObjIsTravIdCurrent(p, pFanin) ) + { + Vec_PtrPush( vNodes, pFanin ); + pFanin->fMarkA = 1; + } + pFanin = Aig_ObjFanin1( pObj ); + if ( pFanin && !pFanin->fMarkA && Aig_ObjIsTravIdCurrent(p, pFanin) ) + { + Vec_PtrPush( vNodes, pFanin ); + pFanin->fMarkA = 1; + } + } + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + pObj->fMarkA = 0; + RetValue = Vec_PtrSize( vNodes ); + Vec_PtrFree( vNodes ); + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG recursively.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManRetimeDup_rec( Aig_Man_t * pNew, Aig_Obj_t * pObj ) +{ + if ( pObj->pData ) + return; + assert( Aig_ObjIsNode(pObj) ); + Saig_ManRetimeDup_rec( pNew, Aig_ObjFanin0(pObj) ); + Saig_ManRetimeDup_rec( pNew, Aig_ObjFanin1(pObj) ); + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG while retiming the registers to the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManRetimeDupForward( Aig_Man_t * p, Vec_Ptr_t * vCut ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int i; + // mark the cones under the cut +// assert( Vec_PtrSize(vCut) == Saig_ManRetimeCountCut(p, vCut) ); + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nRegs = Vec_PtrSize(vCut); + pNew->nTruePis = p->nTruePis; + pNew->nTruePos = p->nTruePos; + // create the true PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Saig_ManForEachPi( p, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pNew ); + // create the registers + Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i ) + pObj->pData = Aig_NotCond( Aig_ObjCreateCi(pNew), pObj->fPhase ); + // duplicate logic above the cut + Aig_ManForEachCo( p, pObj, i ) + Saig_ManRetimeDup_rec( pNew, Aig_ObjFanin0(pObj) ); + // create the true POs + Saig_ManForEachPo( p, pObj, i ) + Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + // remember value in LI + Saig_ManForEachLi( p, pObj, i ) + pObj->pData = Aig_ObjChild0Copy(pObj); + // transfer values from the LIs to the LOs + Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) + pObjLo->pData = pObjLi->pData; + // erase the data values on the internal nodes of the cut + Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i ) + if ( Aig_ObjIsNode(pObj) ) + pObj->pData = NULL; + // duplicate logic below the cut + Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i ) + { + Saig_ManRetimeDup_rec( pNew, pObj ); + Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)pObj->pData, pObj->fPhase) ); + } + Aig_ManCleanup( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG while retiming the registers to the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManRetimeDupBackward( Aig_Man_t * p, Vec_Ptr_t * vCut, Vec_Int_t * vInit ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int i; + // mark the cones under the cut +// assert( Vec_PtrSize(vCut) == Saig_ManRetimeCountCut(p, vCut) ); + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + pNew->nRegs = Vec_PtrSize(vCut); + pNew->nTruePis = p->nTruePis; + pNew->nTruePos = p->nTruePos; + // create the true PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Saig_ManForEachPi( p, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pNew ); + // create the registers + Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i ) + pObj->pData = Aig_NotCond( Aig_ObjCreateCi(pNew), vInit?Vec_IntEntry(vInit,i):0 ); + // duplicate logic above the cut and remember values + Saig_ManForEachLi( p, pObj, i ) + { + Saig_ManRetimeDup_rec( pNew, Aig_ObjFanin0(pObj) ); + pObj->pData = Aig_ObjChild0Copy(pObj); + } + // transfer values from the LIs to the LOs + Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) + pObjLo->pData = pObjLi->pData; + // erase the data values on the internal nodes of the cut + Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i ) + if ( Aig_ObjIsNode(pObj) ) + pObj->pData = NULL; + // replicate the data on the constant node and the PIs + pObj = Aig_ManConst1(p); + pObj->pData = Aig_ManConst1(pNew); + Saig_ManForEachPi( p, pObj, i ) + pObj->pData = Aig_ManCi( pNew, i ); + // duplicate logic below the cut + Saig_ManForEachPo( p, pObj, i ) + { + Saig_ManRetimeDup_rec( pNew, Aig_ObjFanin0(pObj) ); + Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i ) + { + Saig_ManRetimeDup_rec( pNew, pObj ); + Aig_ObjCreateCo( pNew, Aig_NotCond((Aig_Obj_t *)pObj->pData, vInit?Vec_IntEntry(vInit,i):0) ); + } + Aig_ManCleanup( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Derives AIG for the initial state computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManRetimeDupInitState( Aig_Man_t * p, Vec_Ptr_t * vCut ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj; + int i; + // mark the cones under the cut +// assert( Vec_PtrSize(vCut) == Saig_ManRetimeCountCut(p, vCut) ); + // create the new manager + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + // create the true PIs + Aig_ManCleanData( p ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + // create the registers + Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i ) + pObj->pData = Aig_ObjCreateCi(pNew); + // duplicate logic above the cut and create POs + Saig_ManForEachLi( p, pObj, i ) + { + Saig_ManRetimeDup_rec( pNew, Aig_ObjFanin0(pObj) ); + Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + } + return pNew; +} + +/**Function************************************************************* + + Synopsis [Returns the array of bad registers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Saig_ManGetRegistersToExclude( Aig_Man_t * p ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj, * pFanin; + int i, Diffs; + assert( Saig_ManRegNum(p) > 0 ); + Saig_ManForEachLi( p, pObj, i ) + { + pFanin = Aig_ObjFanin0(pObj); + if ( !Aig_ObjFaninC0(pObj) ) + pFanin->fMarkA = 1; + else + pFanin->fMarkB = 1; + } + Diffs = 0; + Saig_ManForEachLi( p, pObj, i ) + { + pFanin = Aig_ObjFanin0(pObj); + Diffs += pFanin->fMarkA && pFanin->fMarkB; + } + vNodes = Vec_PtrAlloc( 100 ); + if ( Diffs > 0 ) + { + Saig_ManForEachLi( p, pObj, i ) + { + pFanin = Aig_ObjFanin0(pObj); + if ( pFanin->fMarkA && pFanin->fMarkB ) + Vec_PtrPush( vNodes, pObj ); + } + assert( Vec_PtrSize(vNodes) == Diffs ); + } + Saig_ManForEachLi( p, pObj, i ) + { + pFanin = Aig_ObjFanin0(pObj); + pFanin->fMarkA = pFanin->fMarkB = 0; + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Hides the registers that cannot be backward retimed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManHideBadRegs( Aig_Man_t * p, Vec_Ptr_t * vBadRegs ) +{ + Vec_Ptr_t * vPisNew, * vPosNew; + Aig_Obj_t * pObjLi, * pObjLo; + int nTruePi, nTruePo, nBadRegs, i; + if ( Vec_PtrSize(vBadRegs) == 0 ) + return 0; + // attached LOs to LIs + Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) + pObjLi->pData = pObjLo; + // reorder them by putting bad registers first + vPisNew = Vec_PtrDup( p->vCis ); + vPosNew = Vec_PtrDup( p->vCos ); + nTruePi = Aig_ManCiNum(p) - Aig_ManRegNum(p); + nTruePo = Aig_ManCoNum(p) - Aig_ManRegNum(p); + assert( nTruePi == p->nTruePis ); + assert( nTruePo == p->nTruePos ); + Vec_PtrForEachEntry( Aig_Obj_t *, vBadRegs, pObjLi, i ) + { + Vec_PtrWriteEntry( vPisNew, nTruePi++, pObjLi->pData ); + Vec_PtrWriteEntry( vPosNew, nTruePo++, pObjLi ); + pObjLi->fMarkA = 1; + } + Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) + { + if ( pObjLi->fMarkA ) + { + pObjLi->fMarkA = 0; + continue; + } + Vec_PtrWriteEntry( vPisNew, nTruePi++, pObjLo ); + Vec_PtrWriteEntry( vPosNew, nTruePo++, pObjLi ); + } + // check the sizes + assert( nTruePi == Aig_ManCiNum(p) ); + assert( nTruePo == Aig_ManCoNum(p) ); + // transfer the arrays + Vec_PtrFree( p->vCis ); p->vCis = vPisNew; + Vec_PtrFree( p->vCos ); p->vCos = vPosNew; + // update the PIs + nBadRegs = Vec_PtrSize(vBadRegs); + p->nRegs -= nBadRegs; + p->nTruePis += nBadRegs; + p->nTruePos += nBadRegs; + return nBadRegs; +} + +/**Function************************************************************* + + Synopsis [Exposes bad registers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManExposeBadRegs( Aig_Man_t * p, int nBadRegs ) +{ + p->nRegs += nBadRegs; + p->nTruePis -= nBadRegs; + p->nTruePos -= nBadRegs; +} + +/**Function************************************************************* + + Synopsis [Performs min-area retiming backward with initial state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManRetimeMinAreaBackward( Aig_Man_t * pNew, int fVerbose ) +{ + Aig_Man_t * pInit, * pFinal; + Vec_Ptr_t * vBadRegs, * vCut; + Vec_Int_t * vInit; + int iBadReg; + // transform the AIG to have no bad registers + vBadRegs = Saig_ManGetRegistersToExclude( pNew ); + if ( fVerbose && Vec_PtrSize(vBadRegs) ) + printf( "Excluding %d registers that cannot be backward retimed.\n", Vec_PtrSize(vBadRegs) ); + while ( 1 ) + { + Saig_ManHideBadRegs( pNew, vBadRegs ); + Vec_PtrFree( vBadRegs ); + // compute cut + vCut = Nwk_ManDeriveRetimingCut( pNew, 0, fVerbose ); + if ( Vec_PtrSize(vCut) >= Aig_ManRegNum(pNew) ) + { + Vec_PtrFree( vCut ); + return NULL; + } + // derive the initial state + pInit = Saig_ManRetimeDupInitState( pNew, vCut ); + vInit = Saig_ManRetimeInitState( pInit ); + if ( vInit != NULL ) + { + pFinal = Saig_ManRetimeDupBackward( pNew, vCut, vInit ); + Vec_IntFree( vInit ); + Vec_PtrFree( vCut ); + Aig_ManStop( pInit ); + return pFinal; + } + Vec_PtrFree( vCut ); + // there is no initial state - find the offending output + iBadReg = Saig_ManRetimeUnsatCore( pInit, fVerbose ); + Aig_ManStop( pInit ); + if ( fVerbose ) + printf( "Excluding register %d.\n", iBadReg ); + // prepare to remove this output + vBadRegs = Vec_PtrAlloc( 1 ); + Vec_PtrPush( vBadRegs, Aig_ManCo( pNew, Saig_ManPoNum(pNew) + iBadReg ) ); + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Performs min-area retiming.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose ) +{ + Vec_Ptr_t * vCut; + Aig_Man_t * pNew, * pTemp, * pCopy; + int i, fChanges; + pNew = Aig_ManDupSimple( p ); + // perform several iterations of forward retiming + fChanges = 0; + if ( !fBackwardOnly ) + for ( i = 0; i < nMaxIters; i++ ) + { + if ( Saig_ManRegNum(pNew) == 0 ) + break; + vCut = Nwk_ManDeriveRetimingCut( pNew, 1, fVerbose ); + if ( Vec_PtrSize(vCut) >= Aig_ManRegNum(pNew) ) + { + if ( fVerbose && !fChanges ) + printf( "Forward retiming cannot reduce registers.\n" ); + Vec_PtrFree( vCut ); + break; + } + pNew = Saig_ManRetimeDupForward( pTemp = pNew, vCut ); + Aig_ManStop( pTemp ); + Vec_PtrFree( vCut ); + if ( fVerbose ) + Aig_ManReportImprovement( p, pNew ); + fChanges = 1; + } + // perform several iterations of backward retiming + fChanges = 0; + if ( !fForwardOnly && !fInitial ) + for ( i = 0; i < nMaxIters; i++ ) + { + if ( Saig_ManRegNum(pNew) == 0 ) + break; + vCut = Nwk_ManDeriveRetimingCut( pNew, 0, fVerbose ); + if ( Vec_PtrSize(vCut) >= Aig_ManRegNum(pNew) ) + { + if ( fVerbose && !fChanges ) + printf( "Backward retiming cannot reduce registers.\n" ); + Vec_PtrFree( vCut ); + break; + } + pNew = Saig_ManRetimeDupBackward( pTemp = pNew, vCut, NULL ); + Aig_ManStop( pTemp ); + Vec_PtrFree( vCut ); + if ( fVerbose ) + Aig_ManReportImprovement( p, pNew ); + fChanges = 1; + } + else if ( !fForwardOnly && fInitial ) + for ( i = 0; i < nMaxIters; i++ ) + { + if ( Saig_ManRegNum(pNew) == 0 ) + break; + pCopy = Aig_ManDupSimple( pNew ); + pTemp = Saig_ManRetimeMinAreaBackward( pCopy, fVerbose ); + Aig_ManStop( pCopy ); + if ( pTemp == NULL ) + { + if ( fVerbose && !fChanges ) + printf( "Backward retiming cannot reduce registers.\n" ); + break; + } + Saig_ManExposeBadRegs( pTemp, Saig_ManPoNum(pTemp) - Saig_ManPoNum(pNew) ); + Aig_ManStop( pNew ); + pNew = pTemp; + if ( fVerbose ) + Aig_ManReportImprovement( p, pNew ); + fChanges = 1; + } + if ( !fForwardOnly && !fInitial && fChanges ) + printf( "Assuming const-0 init-state after backward retiming. Result will not verify.\n" ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigRetStep.c b/yosys/abc/src/aig/saig/saigRetStep.c new file mode 100644 index 00000000000..bf31f996f21 --- /dev/null +++ b/yosys/abc/src/aig/saig/saigRetStep.c @@ -0,0 +1,236 @@ +/**CFile**************************************************************** + + FileName [saigRetStep.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Implementation of retiming steps.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigRetStep.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs one retiming step forward.] + + Description [Returns the pointer to the register output after retiming.] + + SideEffects [Remember to run Aig_ManSetCioIds() in advance.] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Saig_ManRetimeNodeFwd( Aig_Man_t * p, Aig_Obj_t * pObj, int fMakeBug ) +{ + Aig_Obj_t * pFanin0, * pFanin1; + Aig_Obj_t * pInput0, * pInput1; + Aig_Obj_t * pObjNew, * pObjLi, * pObjLo; + int fCompl; + + assert( Saig_ManRegNum(p) > 0 ); + assert( Aig_ObjIsNode(pObj) ); + + // get the fanins + pFanin0 = Aig_ObjFanin0(pObj); + pFanin1 = Aig_ObjFanin1(pObj); + // skip of they are not primary inputs + if ( !Aig_ObjIsCi(pFanin0) || !Aig_ObjIsCi(pFanin1) ) + return NULL; + + // skip of they are not register outputs + if ( !Saig_ObjIsLo(p, pFanin0) || !Saig_ObjIsLo(p, pFanin1) ) + return NULL; + assert( Aig_ObjCioId(pFanin0) > 0 ); + assert( Aig_ObjCioId(pFanin1) > 0 ); + + // skip latch guns + if ( !Aig_ObjIsTravIdCurrent(p, pFanin0) && !Aig_ObjIsTravIdCurrent(p, pFanin1) ) + return NULL; + + // get the inputs of these registers + pInput0 = Saig_ManLi( p, Aig_ObjCioId(pFanin0) - Saig_ManPiNum(p) ); + pInput1 = Saig_ManLi( p, Aig_ObjCioId(pFanin1) - Saig_ManPiNum(p) ); + pInput0 = Aig_ObjChild0( pInput0 ); + pInput1 = Aig_ObjChild0( pInput1 ); + pInput0 = Aig_NotCond( pInput0, Aig_ObjFaninC0(pObj) ); + pInput1 = Aig_NotCond( pInput1, Aig_ObjFaninC1(pObj) ); + // get the condition when the register should be complemetned + fCompl = Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj); + + if ( fMakeBug ) + { + printf( "Introducing bug during retiming.\n" ); + pInput1 = Aig_Not( pInput1 ); + } + + // create new node + pObjNew = Aig_And( p, pInput0, pInput1 ); + + // create new register input + pObjLi = Aig_ObjCreateCo( p, Aig_NotCond(pObjNew, fCompl) ); + pObjLi->CioId = Aig_ManCoNum(p) - 1; + + // create new register output + pObjLo = Aig_ObjCreateCi( p ); + pObjLo->CioId = Aig_ManCiNum(p) - 1; + p->nRegs++; + + // make sure the register is retimable. + Aig_ObjSetTravIdCurrent(p, pObjLo); + +//printf( "Reg = %4d. Reg = %4d. Compl = %d. Phase = %d.\n", +// pFanin0->PioNum, pFanin1->PioNum, Aig_IsComplement(pObjNew), fCompl ); + + // return register output + return Aig_NotCond( pObjLo, fCompl ); +} + +/**Function************************************************************* + + Synopsis [Performs one retiming step backward.] + + Description [Returns the pointer to node after retiming.] + + SideEffects [Remember to run Aig_ManSetCioIds() in advance.] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Saig_ManRetimeNodeBwd( Aig_Man_t * p, Aig_Obj_t * pObjLo ) +{ + Aig_Obj_t * pFanin0, * pFanin1; + Aig_Obj_t * pLo0New, * pLo1New; + Aig_Obj_t * pLi0New, * pLi1New; + Aig_Obj_t * pObj, * pObjNew, * pObjLi; + int fCompl0, fCompl1; + + assert( Saig_ManRegNum(p) > 0 ); + assert( Aig_ObjCioId(pObjLo) > 0 ); + assert( Saig_ObjIsLo(p, pObjLo) ); + + // get the corresponding latch input + pObjLi = Saig_ManLi( p, Aig_ObjCioId(pObjLo) - Saig_ManPiNum(p) ); + + // get the node + pObj = Aig_ObjFanin0(pObjLi); + if ( !Aig_ObjIsNode(pObj) ) + return NULL; + + // get the fanins + pFanin0 = Aig_ObjFanin0(pObj); + pFanin1 = Aig_ObjFanin1(pObj); + + // get the complemented attributes of the fanins + fCompl0 = Aig_ObjFaninC0(pObj) ^ Aig_ObjFaninC0(pObjLi); + fCompl1 = Aig_ObjFaninC1(pObj) ^ Aig_ObjFaninC0(pObjLi); + + // create latch inputs + pLi0New = Aig_ObjCreateCo( p, Aig_NotCond(pFanin0, fCompl0) ); + pLi0New->CioId = Aig_ManCoNum(p) - 1; + pLi1New = Aig_ObjCreateCo( p, Aig_NotCond(pFanin1, fCompl1) ); + pLi1New->CioId = Aig_ManCoNum(p) - 1; + + // create latch outputs + pLo0New = Aig_ObjCreateCi(p); + pLo0New->CioId = Aig_ManCiNum(p) - 1; + pLo1New = Aig_ObjCreateCi(p); + pLo1New->CioId = Aig_ManCiNum(p) - 1; + pLo0New = Aig_NotCond( pLo0New, fCompl0 ); + pLo1New = Aig_NotCond( pLo1New, fCompl1 ); + p->nRegs += 2; + + // create node + pObjNew = Aig_And( p, pLo0New, pLo1New ); +// assert( pObjNew->fPhase == 0 ); + return pObjNew; +} + +/**Function************************************************************* + + Synopsis [Performs the given number of retiming steps.] + + Description [Returns the pointer to node after retiming.] + + SideEffects [Remember to run Aig_ManSetCioIds() in advance.] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManRetimeSteps( Aig_Man_t * p, int nSteps, int fForward, int fAddBugs ) +{ + Aig_Obj_t * pObj, * pObjNew; + int RetValue, s, i; + Aig_ManSetCioIds( p ); + Aig_ManFanoutStart( p ); + p->fCreatePios = 1; + if ( fForward ) + { + Saig_ManMarkAutonomous( p ); + for ( s = 0; s < nSteps; s++ ) + { + Aig_ManForEachNode( p, pObj, i ) + { + pObjNew = Saig_ManRetimeNodeFwd( p, pObj, fAddBugs && (s == 10) ); +// pObjNew = Saig_ManRetimeNodeFwd( p, pObj, 0 ); + if ( pObjNew == NULL ) + continue; + Aig_ObjReplace( p, pObj, pObjNew, 0 ); + break; + } + if ( i == Vec_PtrSize(p->vObjs) ) + break; + } + } + else + { + for ( s = 0; s < nSteps; s++ ) + { + Saig_ManForEachLo( p, pObj, i ) + { + pObjNew = Saig_ManRetimeNodeBwd( p, pObj ); + if ( pObjNew == NULL ) + continue; + Aig_ObjReplace( p, pObj, pObjNew, 0 ); + break; + } + if ( i == Vec_PtrSize(p->vObjs) ) + break; + } + } + p->fCreatePios = 0; + Aig_ManFanoutStop( p ); + RetValue = Aig_ManCleanup( p ); + assert( RetValue == 0 ); + Aig_ManSetRegNum( p, p->nRegs ); + return s; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigScl.c b/yosys/abc/src/aig/saig/saigScl.c new file mode 100644 index 00000000000..d8076196497 --- /dev/null +++ b/yosys/abc/src/aig/saig/saigScl.c @@ -0,0 +1,115 @@ +/**CFile**************************************************************** + + FileName [saigScl.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Sequential cleanup.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigScl.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Report registers useless for SEC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManReportUselessRegisters( Aig_Man_t * pAig ) +{ + Aig_Obj_t * pObj, * pDriver; + int i, Counter1, Counter2; + // set PIO numbers + Aig_ManSetCioIds( pAig ); + // check how many POs are driven by a register whose ref count is 1 + Counter1 = 0; + Saig_ManForEachPo( pAig, pObj, i ) + { + pDriver = Aig_ObjFanin0(pObj); + if ( Saig_ObjIsLo(pAig, pDriver) && Aig_ObjRefs(pDriver) == 1 ) + Counter1++; + } + // check how many PIs have ref count 1 and drive a register + Counter2 = 0; + Saig_ManForEachLi( pAig, pObj, i ) + { + pDriver = Aig_ObjFanin0(pObj); + if ( Saig_ObjIsPi(pAig, pDriver) && Aig_ObjRefs(pDriver) == 1 ) + Counter2++; + } + if ( Counter1 ) + printf( "Network has %d (out of %d) registers driving POs.\n", Counter1, Saig_ManRegNum(pAig) ); + if ( Counter2 ) + printf( "Network has %d (out of %d) registers driven by PIs.\n", Counter2, Saig_ManRegNum(pAig) ); +} + + +/**Function************************************************************* + + Synopsis [Report the number of pairs of complemented registers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_ManReportComplements( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj, * pFanin; + int i, Counter = 0; + assert( Aig_ManRegNum(p) > 0 ); + Aig_ManForEachObj( p, pObj, i ) + assert( !pObj->fMarkA ); + Aig_ManForEachLiSeq( p, pObj, i ) + { + pFanin = Aig_ObjFanin0(pObj); + if ( pFanin->fMarkA ) + Counter++; + else + pFanin->fMarkA = 1; + } + // count fanins that have both attributes + Aig_ManForEachLiSeq( p, pObj, i ) + { + pFanin = Aig_ObjFanin0(pObj); + pFanin->fMarkA = 0; + } + return Counter; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigSimFast.c b/yosys/abc/src/aig/saig/saigSimFast.c new file mode 100644 index 00000000000..fef8367533c --- /dev/null +++ b/yosys/abc/src/aig/saig/saigSimFast.c @@ -0,0 +1,451 @@ +/**CFile**************************************************************** + + FileName [saigSimFast.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Fast sequential AIG simulator.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigSimFast.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" + +#include "base/main/main.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// the AIG manager +typedef struct Faig_Man_t_ Faig_Man_t; +struct Faig_Man_t_ +{ + // parameters + int nPis; + int nPos; + int nCis; + int nCos; + int nFfs; + int nNos; + // offsets + int nPis1; + int nCis1; + int nCisNos1; + int nCisNosPos1; + int nObjs; + // allocated data + int nWords; + int pObjs[0]; +}; + +static inline int Faig_CheckIdPi( Faig_Man_t * p, int i ) { return i >= 1 && i < p->nPis1; } +static inline int Faig_CheckIdLo( Faig_Man_t * p, int i ) { return i >= p->nPis1 && i < p->nCis1; } +static inline int Faig_CheckIdNo( Faig_Man_t * p, int i ) { return i >= p->nCis1 && i < p->nCisNos1; } +static inline int Faig_CheckIdPo( Faig_Man_t * p, int i ) { return i >= p->nCisNos1 && i < p->nCisNosPos1; } +static inline int Faig_CheckIdLi( Faig_Man_t * p, int i ) { return i >= p->nCisNosPos1 && i < p->nObjs; } +static inline int Faig_CheckIdCo( Faig_Man_t * p, int i ) { return i >= p->nCisNos1 && i < p->nObjs; } +static inline int Faig_CheckIdObj( Faig_Man_t * p, int i ) { return i >= 0 && i < p->nObjs; } + +static inline int Faig_ObjIdToNumPi( Faig_Man_t * p, int i ) { assert( Faig_CheckIdPi(p,i) ); return i - 1; } +static inline int Faig_ObjIdToNumLo( Faig_Man_t * p, int i ) { assert( Faig_CheckIdLo(p,i) ); return i - p->nPis1; } +static inline int Faig_ObjIdToNumNo( Faig_Man_t * p, int i ) { assert( Faig_CheckIdNo(p,i) ); return i - p->nCis1; } +static inline int Faig_ObjIdToNumPo( Faig_Man_t * p, int i ) { assert( Faig_CheckIdPo(p,i) ); return i - p->nCisNos1; } +static inline int Faig_ObjIdToNumLi( Faig_Man_t * p, int i ) { assert( Faig_CheckIdLi(p,i) ); return i - p->nCisNosPos1; } +static inline int Faig_ObjIdToNumCo( Faig_Man_t * p, int i ) { assert( Faig_CheckIdCo(p,i) ); return i - p->nCisNos1; } + +static inline int Faig_ObjLoToLi( Faig_Man_t * p, int i ) { assert( Faig_CheckIdLo(p,i) ); return p->nObjs - (p->nCis1 - i); } +static inline int Faig_ObjLiToLo( Faig_Man_t * p, int i ) { assert( Faig_CheckIdLi(p,i) ); return p->nCis1 - (p->nObjs - i); } + +static inline int Faig_NodeChild0( Faig_Man_t * p, int n ) { return p->pObjs[n<<1]; } +static inline int Faig_NodeChild1( Faig_Man_t * p, int n ) { return p->pObjs[(n<<1)+1]; } +static inline int Faig_CoChild0( Faig_Man_t * p, int n ) { return p->pObjs[(p->nNos<<1)+n]; } +static inline int Faig_ObjFaninC( int iFan ) { return iFan & 1; } +static inline int Faig_ObjFanin( int iFan ) { return iFan >> 1; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks if the manager is correct.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Faig_ManIsCorrect( Aig_Man_t * pAig ) +{ + return Aig_ManObjNumMax(pAig) == + 1 + Aig_ManCiNum(pAig) + Aig_ManNodeNum(pAig) + Aig_ManCoNum(pAig); +} + +/**Function************************************************************* + + Synopsis [Creates fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Faig_Man_t * Faig_ManAlloc( Aig_Man_t * pAig ) +{ + Faig_Man_t * p; + int nWords; +// assert( Faig_ManIsCorrect(pAig) ); + nWords = 2 * Aig_ManNodeNum(pAig) + Aig_ManCoNum(pAig); + p = (Faig_Man_t *)ABC_ALLOC( char, sizeof(Faig_Man_t) + sizeof(int) * nWords ); +//printf( "Allocating %7.2f MB.\n", 1.0 * (sizeof(Faig_Man_t) + sizeof(int) * nWords)/(1<<20) ); + memset( p, 0, sizeof(Faig_Man_t) ); + p->nPis = Aig_ManCiNum(pAig) - Aig_ManRegNum(pAig); + p->nPos = Aig_ManCoNum(pAig) - Aig_ManRegNum(pAig); + p->nCis = Aig_ManCiNum(pAig); + p->nCos = Aig_ManCoNum(pAig); + p->nFfs = Aig_ManRegNum(pAig); + p->nNos = Aig_ManNodeNum(pAig); + // offsets + p->nPis1 = p->nPis + 1; + p->nCis1 = p->nCis + 1; + p->nCisNos1 = p->nCis + p->nNos + 1; + p->nCisNosPos1 = p->nCis + p->nNos + p->nPos + 1; + p->nObjs = p->nCis + p->nNos + p->nCos + 1; + p->nWords = nWords; + return p; +} + +/**Function************************************************************* + + Synopsis [Creates fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Faig_Man_t * Faig_ManCreate( Aig_Man_t * pAig ) +{ + Faig_Man_t * p; + Aig_Obj_t * pObj; + int i, iWord = 0; + p = Faig_ManAlloc( pAig ); + Aig_ManForEachNode( pAig, pObj, i ) + { + p->pObjs[iWord++] = (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj); + p->pObjs[iWord++] = (Aig_ObjFaninId1(pObj) << 1) | Aig_ObjFaninC1(pObj); + } + Aig_ManForEachCo( pAig, pObj, i ) + p->pObjs[iWord++] = (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj); + assert( iWord == p->nWords ); + return p; +} + +/**Function************************************************************* + + Synopsis [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Faig_SimulateNode( Faig_Man_t * p, int Id, unsigned * pSimInfo ) +{ + int n = Faig_ObjIdToNumNo( p, Id ); + int iFan0 = Faig_NodeChild0( p, n ); + int iFan1 = Faig_NodeChild1( p, n ); + if ( Faig_ObjFaninC(iFan0) && Faig_ObjFaninC(iFan1) ) + return ~(pSimInfo[Faig_ObjFanin(iFan0)] | pSimInfo[Faig_ObjFanin(iFan1)]); + if ( Faig_ObjFaninC(iFan0) && !Faig_ObjFaninC(iFan1) ) + return (~pSimInfo[Faig_ObjFanin(iFan0)] & pSimInfo[Faig_ObjFanin(iFan1)]); + if ( !Faig_ObjFaninC(iFan0) && Faig_ObjFaninC(iFan1) ) + return (pSimInfo[Faig_ObjFanin(iFan0)] & ~pSimInfo[Faig_ObjFanin(iFan1)]); + // if ( !Faig_ObjFaninC(iFan0) && !Faig_ObjFaninC(iFan1) ) + return (pSimInfo[Faig_ObjFanin(iFan0)] & pSimInfo[Faig_ObjFanin(iFan1)]); +} + +/**Function************************************************************* + + Synopsis [Simulates one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Faig_SimulateCo( Faig_Man_t * p, int Id, unsigned * pSimInfo ) +{ + int n = Faig_ObjIdToNumCo( p, Id ); + int iFan0 = Faig_CoChild0( p, n ); + if ( Faig_ObjFaninC(iFan0) ) + return ~pSimInfo[Faig_ObjFanin(iFan0)]; + // if ( !Faig_ObjFaninC(iFan0) ) + return pSimInfo[Faig_ObjFanin(iFan0)]; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Faig_SimulateRandomShift( unsigned uOld ) +{ + return (uOld << 16) | ((uOld ^ Aig_ManRandom(0)) & 0xffff); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned Faig_SimulateTransferShift( unsigned uOld, unsigned uNew ) +{ + return (uOld << 16) | (uNew & 0xffff); +} + +/**Function************************************************************* + + Synopsis [Simulates the timeframes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int * Faig_ManSimulateFrames( Faig_Man_t * p, int nFrames, int nPref, int fTrans ) +{ + int * pNumOnes = ABC_CALLOC( int, p->nObjs ); + unsigned * pSimInfo = ABC_ALLOC( unsigned, p->nObjs ); + int f, i; +//printf( "Allocating %7.2f MB.\n", 1.0 * 4 * p->nObjs/(1<<20) ); +//printf( "Allocating %7.2f MB.\n", 1.0 * 4 * p->nObjs/(1<<20) ); + // set constant 1 + pSimInfo[0] = ~0; + for ( f = 0; f < nFrames; f++ ) + { + if ( fTrans ) + { + for ( i = 1; i < p->nPis1; i++ ) + pSimInfo[i] = f? Faig_SimulateRandomShift( pSimInfo[i] ) : Aig_ManRandom( 0 ); + for ( ; i < p->nCis1; i++ ) + pSimInfo[i] = f? Faig_SimulateTransferShift( pSimInfo[i], pSimInfo[Faig_ObjLoToLi(p,i)] ) : 0; + } + else + { + for ( i = 1; i < p->nPis1; i++ ) + pSimInfo[i] = Aig_ManRandom( 0 ); + for ( ; i < p->nCis1; i++ ) + pSimInfo[i] = f? pSimInfo[Faig_ObjLoToLi(p,i)] : 0; + } + for ( ; i < p->nCisNos1; i++ ) + pSimInfo[i] = Faig_SimulateNode( p, i, pSimInfo ); + for ( ; i < p->nObjs; i++ ) + pSimInfo[i] = Faig_SimulateCo( p, i, pSimInfo ); + if ( f < nPref ) + continue; + if ( fTrans ) + { + for ( i = 0; i < p->nObjs; i++ ) + pNumOnes[i] += Aig_WordCountOnes( (pSimInfo[i] ^ (pSimInfo[i] >> 16)) & 0xffff ); + } + else + { + for ( i = 0; i < p->nObjs; i++ ) + pNumOnes[i] += Aig_WordCountOnes( pSimInfo[i] ); + } + } + ABC_FREE( pSimInfo ); + return pNumOnes; +} + +/**Function************************************************************* + + Synopsis [Computes switching activity of one node.] + + Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Faig_ManComputeSwitching( int nOnes, int nSimWords ) +{ + int nTotal = 32 * nSimWords; + return (float)2.0 * nOnes / nTotal * (nTotal - nOnes) / nTotal; +} + +/**Function************************************************************* + + Synopsis [Computes switching activity of one node.] + + Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Faig_ManComputeProbOne( int nOnes, int nSimWords ) +{ + int nTotal = 32 * nSimWords; + return (float)nOnes / nTotal; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Faig_ManComputeSwitchProbs4( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ) +{ + int fTrans = 1; + Faig_Man_t * pAig; + Vec_Int_t * vSwitching; + int * pProbs; + float * pSwitching; + int nFramesReal; + abctime clk;//, clkTotal = Abc_Clock(); + if ( fProbOne ) + fTrans = 0; + vSwitching = Vec_IntStart( Aig_ManObjNumMax(p) ); + pSwitching = (float *)vSwitching->pArray; +clk = Abc_Clock(); + pAig = Faig_ManCreate( p ); +//ABC_PRT( "\nCreation ", Abc_Clock() - clk ); + Aig_ManRandom( 1 ); + // get the number of frames to simulate + // if the parameter "seqsimframes" is defined, use it + // otherwise, use the given number of frames "nFrames" + nFramesReal = nFrames; + if ( Abc_FrameReadFlag("seqsimframes") ) + nFramesReal = atoi( Abc_FrameReadFlag("seqsimframes") ); + if ( nFramesReal <= nPref ) + { + printf( "The total number of frames (%d) should exceed prefix (%d).\n", nFramesReal, nPref ); + printf( "Setting the total number of frames to be %d.\n", nFrames ); + nFramesReal = nFrames; + } +//printf( "Simulating %d frames.\n", nFramesReal ); +clk = Abc_Clock(); + pProbs = Faig_ManSimulateFrames( pAig, nFramesReal, nPref, fTrans ); +//ABC_PRT( "Simulation", Abc_Clock() - clk ); +clk = Abc_Clock(); + if ( fTrans ) + { + Aig_Obj_t * pObj; + int i, Counter = 0; + pObj = Aig_ManConst1(p); + pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], (nFramesReal - nPref)/2 ); + Aig_ManForEachCi( p, pObj, i ) + pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], (nFramesReal - nPref)/2 ); + Aig_ManForEachNode( p, pObj, i ) + pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], (nFramesReal - nPref)/2 ); + Aig_ManForEachCo( p, pObj, i ) + pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], (nFramesReal - nPref)/2 ); + assert( Counter == pAig->nObjs ); + } + else if ( fProbOne ) + { + Aig_Obj_t * pObj; + int i, Counter = 0; + pObj = Aig_ManConst1(p); + pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], nFramesReal - nPref ); + Aig_ManForEachCi( p, pObj, i ) + pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], nFramesReal - nPref ); + Aig_ManForEachNode( p, pObj, i ) + pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], nFramesReal - nPref ); + Aig_ManForEachCo( p, pObj, i ) + pSwitching[pObj->Id] = Faig_ManComputeProbOne( pProbs[Counter++], nFramesReal - nPref ); + assert( Counter == pAig->nObjs ); + } + else + { + Aig_Obj_t * pObj; + int i, Counter = 0; + pObj = Aig_ManConst1(p); + pSwitching[pObj->Id] = Faig_ManComputeSwitching( pProbs[Counter++], nFramesReal - nPref ); + Aig_ManForEachCi( p, pObj, i ) + pSwitching[pObj->Id] = Faig_ManComputeSwitching( pProbs[Counter++], nFramesReal - nPref ); + Aig_ManForEachNode( p, pObj, i ) + pSwitching[pObj->Id] = Faig_ManComputeSwitching( pProbs[Counter++], nFramesReal - nPref ); + Aig_ManForEachCo( p, pObj, i ) + pSwitching[pObj->Id] = Faig_ManComputeSwitching( pProbs[Counter++], nFramesReal - nPref ); + assert( Counter == pAig->nObjs ); + } + ABC_FREE( pProbs ); + ABC_FREE( pAig ); +//ABC_PRT( "Switch ", Abc_Clock() - clk ); +//ABC_PRT( "TOTAL ", Abc_Clock() - clkTotal ); + return vSwitching; +} + +/**Function************************************************************* + + Synopsis [Computes probability of switching (or of being 1).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_ManComputeSwitchProb3s( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ) +{ +// return Faig_ManComputeSwitchProbs( p, nFrames, nPref, fProbOne ); + return NULL; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigSimMv.c b/yosys/abc/src/aig/saig/saigSimMv.c new file mode 100644 index 00000000000..18df5007960 --- /dev/null +++ b/yosys/abc/src/aig/saig/saigSimMv.c @@ -0,0 +1,956 @@ +/**CFile**************************************************************** + + FileName [saigSimMv.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Multi-valued simulation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigSimMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define SAIG_DIFF_VALUES 8 +#define SAIG_UNDEF_VALUE 0x1ffffffe //536870910 + +// old AIG +typedef struct Saig_MvObj_t_ Saig_MvObj_t; +struct Saig_MvObj_t_ +{ + int iFan0; + int iFan1; + unsigned Type : 3; + unsigned Value : 29; +}; + +// new AIG +typedef struct Saig_MvAnd_t_ Saig_MvAnd_t; +struct Saig_MvAnd_t_ +{ + int iFan0; + int iFan1; + int iNext; +}; + +// simulation manager +typedef struct Saig_MvMan_t_ Saig_MvMan_t; +struct Saig_MvMan_t_ +{ + // user data + Aig_Man_t * pAig; // original AIG + // parameters + int nStatesMax; // maximum number of states + int nLevelsMax; // maximum number of levels + int nValuesMax; // maximum number of values + int nFlops; // number of flops + // compacted AIG + Saig_MvObj_t * pAigOld; // AIG objects + Vec_Ptr_t * vFlops; // collected flops + Vec_Int_t * vXFlops; // flops that had at least one X-value + Vec_Ptr_t * vTired; // collected flops + unsigned * pTStates; // hash table for states + int nTStatesSize; // hash table size + Aig_MmFixed_t * pMemStates; // memory for states + Vec_Ptr_t * vStates; // reached states + int * pRegsUndef; // count the number of undef values + int ** pRegsValues; // write the first different values + int * nRegsValues; // count the number of different values + int nRUndefs; // the number of undef registers + int nRValues[SAIG_DIFF_VALUES+1]; // the number of registers with given values + // internal AIG + Saig_MvAnd_t * pAigNew; // AIG nodes + int nObjsAlloc; // the number of objects allocated + int nObjs; // the number of objects + int nPis; // the number of primary inputs + int * pTNodes; // hash table + int nTNodesSize; // hash table size + unsigned char * pLevels; // levels of AIG nodes +}; + +static inline int Saig_MvObjFaninC0( Saig_MvObj_t * pObj ) { return pObj->iFan0 & 1; } +static inline int Saig_MvObjFaninC1( Saig_MvObj_t * pObj ) { return pObj->iFan1 & 1; } +static inline int Saig_MvObjFanin0( Saig_MvObj_t * pObj ) { return pObj->iFan0 >> 1; } +static inline int Saig_MvObjFanin1( Saig_MvObj_t * pObj ) { return pObj->iFan1 >> 1; } + +static inline int Saig_MvConst0() { return 1; } +static inline int Saig_MvConst1() { return 0; } +static inline int Saig_MvConst( int c ) { return !c; } +static inline int Saig_MvUndef() { return SAIG_UNDEF_VALUE; } + +static inline int Saig_MvIsConst0( int iNode ) { return iNode == 1; } +static inline int Saig_MvIsConst1( int iNode ) { return iNode == 0; } +static inline int Saig_MvIsConst( int iNode ) { return iNode < 2; } +static inline int Saig_MvIsUndef( int iNode ) { return iNode == SAIG_UNDEF_VALUE; } + +static inline int Saig_MvRegular( int iNode ) { return (iNode & ~01); } +static inline int Saig_MvNot( int iNode ) { return (iNode ^ 01); } +static inline int Saig_MvNotCond( int iNode, int c ) { return (iNode ^ (c)); } +static inline int Saig_MvIsComplement( int iNode ) { return (int)(iNode & 01); } + +static inline int Saig_MvLit2Var( int iNode ) { return (iNode >> 1); } +static inline int Saig_MvVar2Lit( int iVar ) { return (iVar << 1); } +static inline int Saig_MvLev( Saig_MvMan_t * p, int iNode ) { return p->pLevels[iNode >> 1]; } + +// iterator over compacted objects +#define Saig_MvManForEachObj( pAig, pEntry ) \ + for ( pEntry = pAig; pEntry->Type != AIG_OBJ_VOID; pEntry++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates reduced manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Saig_MvObj_t * Saig_ManCreateReducedAig( Aig_Man_t * p, Vec_Ptr_t ** pvFlops ) +{ + Saig_MvObj_t * pAig, * pEntry; + Aig_Obj_t * pObj; + int i; + *pvFlops = Vec_PtrAlloc( Aig_ManRegNum(p) ); + pAig = ABC_CALLOC( Saig_MvObj_t, Aig_ManObjNumMax(p)+1 ); + Aig_ManForEachObj( p, pObj, i ) + { + pEntry = pAig + i; + pEntry->Type = pObj->Type; + if ( Aig_ObjIsCi(pObj) || i == 0 ) + { + if ( Saig_ObjIsLo(p, pObj) ) + { + pEntry->iFan0 = (Saig_ObjLoToLi(p, pObj)->Id << 1); + pEntry->iFan1 = -1; + Vec_PtrPush( *pvFlops, pEntry ); + } + continue; + } + pEntry->iFan0 = (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj); + if ( Aig_ObjIsCo(pObj) ) + continue; + assert( Aig_ObjIsNode(pObj) ); + pEntry->iFan1 = (Aig_ObjFaninId1(pObj) << 1) | Aig_ObjFaninC1(pObj); + } + pEntry = pAig + Aig_ManObjNumMax(p); + pEntry->Type = AIG_OBJ_VOID; + return pAig; +} + +/**Function************************************************************* + + Synopsis [Creates a new node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Saig_MvCreateObj( Saig_MvMan_t * p, int iFan0, int iFan1 ) +{ + Saig_MvAnd_t * pNode; + if ( p->nObjs == p->nObjsAlloc ) + { + p->pAigNew = ABC_REALLOC( Saig_MvAnd_t, p->pAigNew, 2*p->nObjsAlloc ); + p->pLevels = ABC_REALLOC( unsigned char, p->pLevels, 2*p->nObjsAlloc ); + p->nObjsAlloc *= 2; + } + pNode = p->pAigNew + p->nObjs; + pNode->iFan0 = iFan0; + pNode->iFan1 = iFan1; + pNode->iNext = 0; + if ( iFan0 || iFan1 ) + p->pLevels[p->nObjs] = 1 + Abc_MaxInt( Saig_MvLev(p, iFan0), Saig_MvLev(p, iFan1) ); + else + p->pLevels[p->nObjs] = 0, p->nPis++; + return p->nObjs++; +} + +/**Function************************************************************* + + Synopsis [Creates multi-valued simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Saig_MvMan_t * Saig_MvManStart( Aig_Man_t * pAig, int nFramesSatur ) +{ + Saig_MvMan_t * p; + int i; + assert( Aig_ManRegNum(pAig) > 0 ); + p = (Saig_MvMan_t *)ABC_ALLOC( Saig_MvMan_t, 1 ); + memset( p, 0, sizeof(Saig_MvMan_t) ); + // set parameters + p->pAig = pAig; + p->nStatesMax = 2 * nFramesSatur + 100; + p->nLevelsMax = 4; + p->nValuesMax = SAIG_DIFF_VALUES; + p->nFlops = Aig_ManRegNum(pAig); + // compacted AIG + p->pAigOld = Saig_ManCreateReducedAig( pAig, &p->vFlops ); + p->nTStatesSize = Abc_PrimeCudd( p->nStatesMax ); + p->pTStates = ABC_CALLOC( unsigned, p->nTStatesSize ); + p->pMemStates = Aig_MmFixedStart( sizeof(int) * (p->nFlops+1), p->nStatesMax ); + p->vStates = Vec_PtrAlloc( p->nStatesMax ); + Vec_PtrPush( p->vStates, NULL ); + p->pRegsUndef = ABC_CALLOC( int, p->nFlops ); + p->pRegsValues = ABC_ALLOC( int *, p->nFlops ); + p->pRegsValues[0] = ABC_ALLOC( int, p->nValuesMax * p->nFlops ); + for ( i = 1; i < p->nFlops; i++ ) + p->pRegsValues[i] = p->pRegsValues[i-1] + p->nValuesMax; + p->nRegsValues = ABC_CALLOC( int, p->nFlops ); + p->vTired = Vec_PtrAlloc( 100 ); + // internal AIG + p->nObjsAlloc = 1000000; + p->pAigNew = ABC_ALLOC( Saig_MvAnd_t, p->nObjsAlloc ); + p->nTNodesSize = Abc_PrimeCudd( p->nObjsAlloc / 3 ); + p->pTNodes = ABC_CALLOC( int, p->nTNodesSize ); + p->pLevels = ABC_ALLOC( unsigned char, p->nObjsAlloc ); + Saig_MvCreateObj( p, 0, 0 ); + return p; +} + +/**Function************************************************************* + + Synopsis [Destroys multi-valued simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_MvManStop( Saig_MvMan_t * p ) +{ + Aig_MmFixedStop( p->pMemStates, 0 ); + Vec_PtrFree( p->vStates ); + Vec_IntFreeP( &p->vXFlops ); + Vec_PtrFree( p->vFlops ); + Vec_PtrFree( p->vTired ); + ABC_FREE( p->pRegsValues[0] ); + ABC_FREE( p->pRegsValues ); + ABC_FREE( p->nRegsValues ); + ABC_FREE( p->pRegsUndef ); + ABC_FREE( p->pAigOld ); + ABC_FREE( p->pTStates ); + ABC_FREE( p->pAigNew ); + ABC_FREE( p->pTNodes ); + ABC_FREE( p->pLevels ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Hashing the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Saig_MvHash( int iFan0, int iFan1, int TableSize ) +{ + unsigned Key = 0; + assert( iFan0 < iFan1 ); + Key ^= Saig_MvLit2Var(iFan0) * 7937; + Key ^= Saig_MvLit2Var(iFan1) * 2971; + Key ^= Saig_MvIsComplement(iFan0) * 911; + Key ^= Saig_MvIsComplement(iFan1) * 353; + return (int)(Key % TableSize); +} + +/**Function************************************************************* + + Synopsis [Returns the place where this node is stored (or should be stored).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int * Saig_MvTableFind( Saig_MvMan_t * p, int iFan0, int iFan1 ) +{ + Saig_MvAnd_t * pEntry; + int * pPlace = p->pTNodes + Saig_MvHash( iFan0, iFan1, p->nTNodesSize ); + for ( pEntry = (*pPlace)? p->pAigNew + *pPlace : NULL; pEntry; + pPlace = &pEntry->iNext, pEntry = (*pPlace)? p->pAigNew + *pPlace : NULL ) + if ( pEntry->iFan0 == iFan0 && pEntry->iFan1 == iFan1 ) + break; + return pPlace; +} + +/**Function************************************************************* + + Synopsis [Performs an AND-operation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Saig_MvAnd( Saig_MvMan_t * p, int iFan0, int iFan1, int fFirst ) +{ + if ( iFan0 == iFan1 ) + return iFan0; + if ( iFan0 == Saig_MvNot(iFan1) ) + return Saig_MvConst0(); + if ( Saig_MvIsConst(iFan0) ) + return Saig_MvIsConst1(iFan0) ? iFan1 : Saig_MvConst0(); + if ( Saig_MvIsConst(iFan1) ) + return Saig_MvIsConst1(iFan1) ? iFan0 : Saig_MvConst0(); + if ( Saig_MvIsUndef(iFan0) || Saig_MvIsUndef(iFan1) ) + return Saig_MvUndef(); +// if ( Saig_MvLev(p, iFan0) >= p->nLevelsMax || Saig_MvLev(p, iFan1) >= p->nLevelsMax ) +// return Saig_MvUndef(); + + // go undef after the first frame + if ( !fFirst ) + return Saig_MvUndef(); + + if ( iFan0 > iFan1 ) + { + int Temp = iFan0; + iFan0 = iFan1; + iFan1 = Temp; + } + { + int * pPlace; + pPlace = Saig_MvTableFind( p, iFan0, iFan1 ); + if ( *pPlace == 0 ) + { + if ( pPlace >= (int*)p->pAigNew && pPlace < (int*)(p->pAigNew + p->nObjsAlloc) ) + { + int iPlace = pPlace - (int*)p->pAigNew; + int iNode = Saig_MvCreateObj( p, iFan0, iFan1 ); + ((int*)p->pAigNew)[iPlace] = iNode; + return Saig_MvVar2Lit( iNode ); + } + else + *pPlace = Saig_MvCreateObj( p, iFan0, iFan1 ); + } + return Saig_MvVar2Lit( *pPlace ); + } +} + +/**Function************************************************************* + + Synopsis [Propagates one edge.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Saig_MvSimulateValue0( Saig_MvObj_t * pAig, Saig_MvObj_t * pObj ) +{ + Saig_MvObj_t * pObj0 = pAig + Saig_MvObjFanin0(pObj); + if ( Saig_MvIsUndef( pObj0->Value ) ) + return Saig_MvUndef(); + return Saig_MvNotCond( pObj0->Value, Saig_MvObjFaninC0(pObj) ); +} +static inline int Saig_MvSimulateValue1( Saig_MvObj_t * pAig, Saig_MvObj_t * pObj ) +{ + Saig_MvObj_t * pObj1 = pAig + Saig_MvObjFanin1(pObj); + if ( Saig_MvIsUndef( pObj1->Value ) ) + return Saig_MvUndef(); + return Saig_MvNotCond( pObj1->Value, Saig_MvObjFaninC1(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Prints MV state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_MvPrintState( int Iter, Saig_MvMan_t * p ) +{ + Saig_MvObj_t * pEntry; + int i; + printf( "%3d : ", Iter ); + Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i ) + { + if ( pEntry->Value == SAIG_UNDEF_VALUE ) + printf( " *" ); + else + printf( "%5d", pEntry->Value ); + } + printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Performs one iteration of simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_MvSimulateFrame( Saig_MvMan_t * p, int fFirst, int fVerbose ) +{ + Saig_MvObj_t * pEntry; + int i; + Saig_MvManForEachObj( p->pAigOld, pEntry ) + { + if ( pEntry->Type == AIG_OBJ_AND ) + { + pEntry->Value = Saig_MvAnd( p, + Saig_MvSimulateValue0(p->pAigOld, pEntry), + Saig_MvSimulateValue1(p->pAigOld, pEntry), fFirst ); + } + else if ( pEntry->Type == AIG_OBJ_CO ) + pEntry->Value = Saig_MvSimulateValue0(p->pAigOld, pEntry); + else if ( pEntry->Type == AIG_OBJ_CI ) + { + if ( pEntry->iFan1 == 0 ) // true PI + { + if ( fFirst ) + pEntry->Value = Saig_MvVar2Lit( Saig_MvCreateObj( p, 0, 0 ) ); + else + pEntry->Value = SAIG_UNDEF_VALUE; + } +// else if ( fFirst ) // register output +// pEntry->Value = Saig_MvConst0(); +// else +// pEntry->Value = Saig_MvSimulateValue0(p->pAigOld, pEntry); + } + else if ( pEntry->Type == AIG_OBJ_CONST1 ) + pEntry->Value = Saig_MvConst1(); + else if ( pEntry->Type != AIG_OBJ_NONE ) + assert( 0 ); + } + // transfer to registers + Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i ) + pEntry->Value = Saig_MvSimulateValue0( p->pAigOld, pEntry ); +} + + +/**Function************************************************************* + + Synopsis [Computes hash value of the node using its simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_MvSimHash( unsigned * pState, int nFlops, int TableSize ) +{ + static int s_SPrimes[16] = { + 1610612741, + 805306457, + 402653189, + 201326611, + 100663319, + 50331653, + 25165843, + 12582917, + 6291469, + 3145739, + 1572869, + 786433, + 393241, + 196613, + 98317, + 49157 + }; + unsigned uHash = 0; + int i; + for ( i = 0; i < nFlops; i++ ) + uHash ^= pState[i] * s_SPrimes[i & 0xF]; + return (int)(uHash % TableSize); +} + +/**Function************************************************************* + + Synopsis [Returns the place where this state is stored (or should be stored).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline unsigned * Saig_MvSimTableFind( Saig_MvMan_t * p, unsigned * pState ) +{ + unsigned * pEntry; + unsigned * pPlace = p->pTStates + Saig_MvSimHash( pState+1, p->nFlops, p->nTStatesSize ); + for ( pEntry = (*pPlace)? (unsigned *)Vec_PtrEntry(p->vStates, *pPlace) : NULL; pEntry; + pPlace = pEntry, pEntry = (*pPlace)? (unsigned *)Vec_PtrEntry(p->vStates, *pPlace) : NULL ) + if ( memcmp( pEntry+1, pState+1, sizeof(int)*p->nFlops ) == 0 ) + break; + return pPlace; +} + +/**Function************************************************************* + + Synopsis [Saves current state.] + + Description [Returns -1 if there is no fixed point.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_MvSaveState( Saig_MvMan_t * p ) +{ + Saig_MvObj_t * pEntry; + unsigned * pState, * pPlace; + int i; + pState = (unsigned *)Aig_MmFixedEntryFetch( p->pMemStates ); + pState[0] = 0; + Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i ) + pState[i+1] = pEntry->Value; + pPlace = Saig_MvSimTableFind( p, pState ); + if ( *pPlace ) + return *pPlace; + *pPlace = Vec_PtrSize( p->vStates ); + Vec_PtrPush( p->vStates, pState ); + return -1; +} + +/**Function************************************************************* + + Synopsis [Performs multi-valued simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_MvManPostProcess( Saig_MvMan_t * p, int iState ) +{ + Saig_MvObj_t * pEntry; + unsigned * pState; + int i, k, j, nTotal = 0, iFlop; + Vec_Int_t * vUniques = Vec_IntAlloc( 100 ); + Vec_Int_t * vCounter = Vec_IntAlloc( 100 ); + // count registers that never became undef + Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i ) + if ( p->pRegsUndef[i] == 0 ) + nTotal++; + printf( "The number of registers that never became undef = %d. (Total = %d.)\n", nTotal, p->nFlops ); + Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i ) + { + if ( p->pRegsUndef[i] ) + continue; + Vec_IntForEachEntry( vUniques, iFlop, k ) + { + Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, j, 1 ) + if ( pState[iFlop+1] != pState[i+1] ) + break; + if ( j == Vec_PtrSize(p->vStates) ) + { + Vec_IntAddToEntry( vCounter, k, 1 ); + break; + } + } + if ( k == Vec_IntSize(vUniques) ) + { + Vec_IntPush( vUniques, i ); + Vec_IntPush( vCounter, 1 ); + } + } + Vec_IntForEachEntry( vUniques, iFlop, i ) + { + printf( "FLOP %5d : (%3d) ", iFlop, Vec_IntEntry(vCounter,i) ); +/* + for ( k = 0; k < p->nRegsValues[iFlop]; k++ ) + if ( p->pRegsValues[iFlop][k] == SAIG_UNDEF_VALUE ) + printf( "* " ); + else + printf( "%d ", p->pRegsValues[iFlop][k] ); + printf( "\n" ); +*/ + Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, k, 1 ) + { + if ( k == iState+1 ) + printf( " # " ); + if ( pState[iFlop+1] == SAIG_UNDEF_VALUE ) + printf( "*" ); + else + printf( "%d", pState[iFlop+1] ); + } + printf( "\n" ); +// if ( ++Counter == 10 ) +// break; + } + + Vec_IntFree( vUniques ); + Vec_IntFree( vCounter ); +} + +/**Function************************************************************* + + Synopsis [Performs multi-valued simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_MvManFindXFlops( Saig_MvMan_t * p ) +{ + Vec_Int_t * vXFlops; + unsigned * pState; + int i, k; + vXFlops = Vec_IntStart( p->nFlops ); + Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, i, 1 ) + { + for ( k = 0; k < p->nFlops; k++ ) + if ( Saig_MvIsUndef(pState[k+1]) ) + Vec_IntWriteEntry( vXFlops, k, 1 ); + } + return vXFlops; +} + +/**Function************************************************************* + + Synopsis [Checks if the flop is an oscilator.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_MvManCheckOscilator( Saig_MvMan_t * p, int iFlop ) +{ + Vec_Int_t * vValues; + unsigned * pState; + int k, Per, Entry; + // collect values of this flop + vValues = Vec_IntAlloc( 100 ); + Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, k, 1 ) + { + Vec_IntPush( vValues, pState[iFlop+1] ); +//printf( "%d ", pState[iFlop+1] ); + } +//printf( "\n" ); + assert( Saig_MvIsConst0( Vec_IntEntry(vValues,0) ) ); + // look for constants + for ( Per = 0; Per < Vec_IntSize(vValues)/2; Per++ ) + { + // find the first non-const0 + Vec_IntForEachEntryStart( vValues, Entry, Per, Per ) + if ( !Saig_MvIsConst0(Entry) ) + break; + if ( Per == Vec_IntSize(vValues) ) + break; + // find the first const0 + Vec_IntForEachEntryStart( vValues, Entry, Per, Per ) + if ( Saig_MvIsConst0(Entry) ) + break; + if ( Per == Vec_IntSize(vValues) ) + break; + // try to determine period + assert( Saig_MvIsConst0( Vec_IntEntry(vValues,Per) ) ); + for ( k = Per; k < Vec_IntSize(vValues); k++ ) + if ( Vec_IntEntry(vValues, k-Per) != Vec_IntEntry(vValues, k) ) + break; + if ( k < Vec_IntSize(vValues) ) + continue; + Vec_IntFree( vValues ); +//printf( "Period = %d\n", Per ); + return Per; + } + Vec_IntFree( vValues ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns const0 and binary flops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_MvManFindConstBinaryFlops( Saig_MvMan_t * p, Vec_Int_t ** pvBinary ) +{ + unsigned * pState; + Vec_Int_t * vBinary, * vConst0; + int i, k, fConst0; + // detect constant flops + vConst0 = Vec_IntAlloc( p->nFlops ); + vBinary = Vec_IntAlloc( p->nFlops ); + for ( k = 0; k < p->nFlops; k++ ) + { + // check if this flop is constant 0 in all states + fConst0 = 1; + Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, i, 1 ) + { + if ( !Saig_MvIsConst0(pState[k+1]) ) + fConst0 = 0; + if ( Saig_MvIsUndef(pState[k+1]) ) + break; + } + if ( i < Vec_PtrSize(p->vStates) ) + continue; + // the flop is binary-valued + if ( fConst0 ) + Vec_IntPush( vConst0, k ); + else + Vec_IntPush( vBinary, k ); + } + *pvBinary = vBinary; + return vConst0; +} + +/**Function************************************************************* + + Synopsis [Find oscilators.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_MvManFindOscilators( Saig_MvMan_t * p, Vec_Int_t ** pvConst0 ) +{ + Vec_Int_t * vBinary, * vOscils; + int Entry, i; + // detect constant flops + *pvConst0 = Saig_MvManFindConstBinaryFlops( p, &vBinary ); + // check binary flops + vOscils = Vec_IntAlloc( 100 ); + Vec_IntForEachEntry( vBinary, Entry, i ) + if ( Saig_MvManCheckOscilator( p, Entry ) ) + Vec_IntPush( vOscils, Entry ); + Vec_IntFree( vBinary ); + return vOscils; +} + +/**Function************************************************************* + + Synopsis [Find constants and oscilators.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_MvManCreateNextSkip( Saig_MvMan_t * p ) +{ + Vec_Int_t * vConst0, * vOscils, * vXFlops; + int i, Entry; + vOscils = Saig_MvManFindOscilators( p, &vConst0 ); +//printf( "Found %d constants and %d oscilators.\n", Vec_IntSize(vConst0), Vec_IntSize(vOscils) ); + vXFlops = Vec_IntAlloc( p->nFlops ); + Vec_IntFill( vXFlops, p->nFlops, 1 ); + Vec_IntForEachEntry( vConst0, Entry, i ) + Vec_IntWriteEntry( vXFlops, Entry, 0 ); + Vec_IntForEachEntry( vOscils, Entry, i ) + Vec_IntWriteEntry( vXFlops, Entry, 0 ); + Vec_IntFree( vOscils ); + Vec_IntFree( vConst0 ); + return vXFlops; +} + +/**Function************************************************************* + + Synopsis [Finds equivalent flops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Saig_MvManDeriveMap( Saig_MvMan_t * p, int fVerbose ) +{ + Vec_Int_t * vConst0, * vBinValued; + Vec_Ptr_t * vMap = NULL; + Aig_Obj_t * pObj; + unsigned * pState; + int i, k, j, FlopK, FlopJ; + int Counter1 = 0, Counter2 = 0; + // prepare CI map + vMap = Vec_PtrAlloc( Aig_ManCiNum(p->pAig) ); + Aig_ManForEachCi( p->pAig, pObj, i ) + Vec_PtrPush( vMap, pObj ); + // detect constant flops + vConst0 = Saig_MvManFindConstBinaryFlops( p, &vBinValued ); + // set constants + Vec_IntForEachEntry( vConst0, FlopK, k ) + { + Vec_PtrWriteEntry( vMap, Saig_ManPiNum(p->pAig) + FlopK, Aig_ManConst0(p->pAig) ); + Counter1++; + } + Vec_IntFree( vConst0 ); + + // detect equivalent (non-ternary flops) + Vec_IntForEachEntry( vBinValued, FlopK, k ) + if ( FlopK >= 0 ) + Vec_IntForEachEntryStart( vBinValued, FlopJ, j, k+1 ) + if ( FlopJ >= 0 ) + { + // check if they are equal + Vec_PtrForEachEntryStart( unsigned *, p->vStates, pState, i, 1 ) + if ( pState[FlopK+1] != pState[FlopJ+1] ) + break; + if ( i < Vec_PtrSize(p->vStates) ) + continue; + // set the equivalence + Vec_PtrWriteEntry( vMap, Saig_ManPiNum(p->pAig) + FlopJ, Saig_ManLo(p->pAig, FlopK) ); + Vec_IntWriteEntry( vBinValued, j, -1 ); + Counter2++; + } + if ( fVerbose ) + printf( "Detected %d const0 flops and %d pairs of equiv binary flops.\n", Counter1, Counter2 ); + Vec_IntFree( vBinValued ); + if ( Counter1 == 0 && Counter2 == 0 ) + Vec_PtrFreeP( &vMap ); + return vMap; +} + +/**Function************************************************************* + + Synopsis [Performs multi-valued simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Saig_MvManSimulate( Aig_Man_t * pAig, int nFramesSymb, int nFramesSatur, int fVerbose, int fVeryVerbose ) +{ + Vec_Ptr_t * vMap; + Saig_MvMan_t * p; + Saig_MvObj_t * pEntry; + int f, i, iState; + abctime clk = Abc_Clock(); + assert( nFramesSymb >= 1 && nFramesSymb <= nFramesSatur ); + + // start manager + p = Saig_MvManStart( pAig, nFramesSatur ); +if ( fVerbose ) +ABC_PRT( "Constructing the problem", Abc_Clock() - clk ); + + // initialize registers + Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i ) + pEntry->Value = Saig_MvConst0(); + Saig_MvSaveState( p ); + if ( fVeryVerbose ) + Saig_MvPrintState( 0, p ); + // simulate until convergence + clk = Abc_Clock(); + for ( f = 0; ; f++ ) + { + if ( f == nFramesSatur ) + { + if ( fVerbose ) + printf( "Beginning to saturate simulation after %d frames\n", f ); + // find all flops that have at least one X value in the past and set them to X forever + p->vXFlops = Saig_MvManFindXFlops( p ); + } + if ( f == 2 * nFramesSatur ) + { + if ( fVerbose ) + printf( "Aggressively saturating simulation after %d frames\n", f ); + Vec_IntFree( p->vXFlops ); + p->vXFlops = Saig_MvManCreateNextSkip( p ); + } + // retire some flops + if ( p->vXFlops ) + { + Vec_PtrForEachEntry( Saig_MvObj_t *, p->vFlops, pEntry, i ) + if ( Vec_IntEntry( p->vXFlops, i ) ) + pEntry->Value = SAIG_UNDEF_VALUE; + } + // simulate timeframe + Saig_MvSimulateFrame( p, (int)(f < nFramesSymb), fVerbose ); + // save and print state + iState = Saig_MvSaveState( p ); + if ( fVeryVerbose ) + Saig_MvPrintState( f+1, p ); + if ( iState >= 0 ) + { + if ( fVerbose ) + printf( "Converged after %d frames with lasso in state %d. Cycle = %d.\n", f+1, iState-1, f+2-iState ); +// printf( "Total number of PIs = %d. AND nodes = %d.\n", p->nPis, p->nObjs - p->nPis ); + break; + } + } +// printf( "Coverged after %d frames.\n", f ); +if ( fVerbose ) +ABC_PRT( "Multi-valued simulation", Abc_Clock() - clk ); + // implement equivalences +// Saig_MvManPostProcess( p, iState-1 ); + vMap = Saig_MvManDeriveMap( p, fVerbose ); + Saig_MvManStop( p ); +// return Aig_ManDupSimple( pAig ); + return vMap; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigSimSeq.c b/yosys/abc/src/aig/saig/saigSimSeq.c new file mode 100644 index 00000000000..ba4146802e7 --- /dev/null +++ b/yosys/abc/src/aig/saig/saigSimSeq.c @@ -0,0 +1,518 @@ +/**CFile**************************************************************** + + FileName [saigSimSeq.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Fast sequential AIG simulator.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigSimSeq.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" +#include "proof/ssw/ssw.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// combinational simulation manager +typedef struct Raig_Man_t_ Raig_Man_t; +struct Raig_Man_t_ +{ + // parameters + Aig_Man_t * pAig; // the AIG to be used for simulation + int nWords; // the number of words to simulate + // AIG representation + int nPis; // the number of primary inputs + int nPos; // the number of primary outputs + int nCis; // the number of combinational inputs + int nCos; // the number of combinational outputs + int nNodes; // the number of internal nodes + int nObjs; // nCis + nNodes + nCos + 2 + int * pFans0; // fanin0 for all objects + int * pFans1; // fanin1 for all objects + Vec_Int_t * vCis2Ids; // mapping of CIs into their PI ids + Vec_Int_t * vLos; // register outputs + Vec_Int_t * vLis; // register inputs + // simulation info + int * pRefs; // reference counter for each node + unsigned * pSims; // simlulation information for each node + // recycable memory + unsigned * pMems; // allocated simulaton memory + int nWordsAlloc; // the number of allocated entries + int nMems; // the number of used entries + int nMemsMax; // the max number of used entries + int MemFree; // next free entry +}; + +static inline int Raig_Var2Lit( int Var, int fCompl ) { return Var + Var + fCompl; } +static inline int Raig_Lit2Var( int Lit ) { return Lit >> 1; } +static inline int Raig_LitIsCompl( int Lit ) { return Lit & 1; } +static inline int Raig_LitNot( int Lit ) { return Lit ^ 1; } +static inline int Raig_LitNotCond( int Lit, int c ) { return Lit ^ (int)(c > 0); } +static inline int Raig_LitRegular( int Lit ) { return Lit & ~01; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Find the PO corresponding to the PO driver.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Raig_ManFindPo( Aig_Man_t * pAig, int iNode ) +{ + Aig_Obj_t * pObj; + int i; + Saig_ManForEachPo( pAig, pObj, i ) + if ( pObj->iData == iNode ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Creates fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Raig_ManCreate_rec( Raig_Man_t * p, Aig_Obj_t * pObj ) +{ + int iFan0, iFan1; + assert( !Aig_IsComplement(pObj) ); + if ( pObj->iData ) + return pObj->iData; + assert( !Aig_ObjIsConst1(pObj) ); + if ( Aig_ObjIsNode(pObj) ) + { + iFan0 = Raig_ManCreate_rec( p, Aig_ObjFanin0(pObj) ); + iFan0 = (iFan0 << 1) | Aig_ObjFaninC0(pObj); + iFan1 = Raig_ManCreate_rec( p, Aig_ObjFanin1(pObj) ); + iFan1 = (iFan1 << 1) | Aig_ObjFaninC1(pObj); + } + else if ( Aig_ObjIsCo(pObj) ) + { + iFan0 = Raig_ManCreate_rec( p, Aig_ObjFanin0(pObj) ); + iFan0 = (iFan0 << 1) | Aig_ObjFaninC0(pObj); + iFan1 = 0; + } + else + { + iFan0 = iFan1 = 0; + Vec_IntPush( p->vCis2Ids, Aig_ObjCioId(pObj) ); + } + p->pFans0[p->nObjs] = iFan0; + p->pFans1[p->nObjs] = iFan1; + p->pRefs[p->nObjs] = Aig_ObjRefs(pObj); + return pObj->iData = p->nObjs++; +} + +/**Function************************************************************* + + Synopsis [Creates fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Raig_Man_t * Raig_ManCreate( Aig_Man_t * pAig ) +{ + Raig_Man_t * p; + Aig_Obj_t * pObj; + int i, nObjs; + Aig_ManCleanData( pAig ); + p = (Raig_Man_t *)ABC_ALLOC( Raig_Man_t, 1 ); + memset( p, 0, sizeof(Raig_Man_t) ); + p->pAig = pAig; + p->nPis = Saig_ManPiNum(pAig); + p->nPos = Saig_ManPoNum(pAig); + p->nCis = Aig_ManCiNum(pAig); + p->nCos = Aig_ManCoNum(pAig); + p->nNodes = Aig_ManNodeNum(pAig); + nObjs = p->nCis + p->nCos + p->nNodes + 2; + p->pFans0 = ABC_ALLOC( int, nObjs ); + p->pFans1 = ABC_ALLOC( int, nObjs ); + p->pRefs = ABC_ALLOC( int, nObjs ); + p->pSims = ABC_CALLOC( unsigned, nObjs ); + p->vCis2Ids = Vec_IntAlloc( Aig_ManCiNum(pAig) ); + // add objects (0=unused; 1=const1) + p->nObjs = 2; + pObj = Aig_ManConst1( pAig ); + pObj->iData = 1; + Aig_ManForEachCi( pAig, pObj, i ) + if ( Aig_ObjRefs(pObj) == 0 ) + Raig_ManCreate_rec( p, pObj ); + Aig_ManForEachCo( pAig, pObj, i ) + Raig_ManCreate_rec( p, pObj ); + assert( Vec_IntSize(p->vCis2Ids) == Aig_ManCiNum(pAig) ); + assert( p->nObjs == nObjs ); + // collect flop outputs + p->vLos = Vec_IntAlloc( Aig_ManRegNum(pAig) ); + Saig_ManForEachLo( pAig, pObj, i ) + Vec_IntPush( p->vLos, pObj->iData ); + // collect flop inputs + p->vLis = Vec_IntAlloc( Aig_ManRegNum(pAig) ); + Saig_ManForEachLi( pAig, pObj, i ) + { + Vec_IntPush( p->vLis, pObj->iData ); + assert( p->pRefs[ pObj->iData ] == 0 ); + p->pRefs[ pObj->iData ]++; + } + return p; +} + +/**Function************************************************************* + + Synopsis [Creates fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Raig_ManDelete( Raig_Man_t * p ) +{ + Vec_IntFree( p->vCis2Ids ); + Vec_IntFree( p->vLos ); + Vec_IntFree( p->vLis ); + ABC_FREE( p->pFans0 ); + ABC_FREE( p->pFans1 ); + ABC_FREE( p->pRefs ); + ABC_FREE( p->pSims ); + ABC_FREE( p->pMems ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [References simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Raig_ManSimRef( Raig_Man_t * p, int i ) +{ + unsigned * pSim; + assert( i > 1 ); + assert( p->pSims[i] == 0 ); + if ( p->MemFree == 0 ) + { + unsigned * pPlace, Ent; + if ( p->nWordsAlloc == 0 ) + { + assert( p->pMems == NULL ); + p->nWordsAlloc = (1<<17); // -> 1Mb + p->nMems = 1; + } + p->nWordsAlloc *= 2; + p->pMems = ABC_REALLOC( unsigned, p->pMems, p->nWordsAlloc ); + memset( p->pMems, 0xff, sizeof(unsigned) * (p->nWords + 1) ); + pPlace = (unsigned *)&p->MemFree; + for ( Ent = p->nMems * (p->nWords + 1); + Ent + p->nWords + 1 < (unsigned)p->nWordsAlloc; + Ent += p->nWords + 1 ) + { + *pPlace = Ent; + pPlace = p->pMems + Ent; + } + *pPlace = 0; + } + p->pSims[i] = p->MemFree; + pSim = p->pMems + p->MemFree; + p->MemFree = pSim[0]; + pSim[0] = p->pRefs[i]; + p->nMems++; + if ( p->nMemsMax < p->nMems ) + p->nMemsMax = p->nMems; + return pSim; +} + +/**Function************************************************************* + + Synopsis [Dereference simulaton info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned * Raig_ManSimDeref( Raig_Man_t * p, int i ) +{ + unsigned * pSim; + assert( i ); + if ( i == 1 ) // const 1 + return p->pMems; + assert( p->pSims[i] > 0 ); + pSim = p->pMems + p->pSims[i]; + if ( --pSim[0] == 0 ) + { + pSim[0] = p->MemFree; + p->MemFree = p->pSims[i]; + p->pSims[i] = 0; + p->nMems--; + } + return pSim; +} + +/**Function************************************************************* + + Synopsis [Simulates one round.] + + Description [Returns the number of PO entry if failed; 0 otherwise.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Raig_ManSimulateRound( Raig_Man_t * p, int fMiter, int fFirst, int * piPat ) +{ + unsigned * pRes0, * pRes1, * pRes; + int i, w, nCis, nCos, iFan0, iFan1, iPioNum; + // nove the values to the register outputs + Vec_IntForEachEntry( p->vCis2Ids, iPioNum, i ) + { + if ( iPioNum < p->nPis ) + continue; + pRes = Raig_ManSimRef( p, Vec_IntEntry(p->vLos, iPioNum-p->nPis) ); + if ( fFirst ) + memset( pRes + 1, 0, sizeof(unsigned) * p->nWords ); + else + { + pRes0 = Raig_ManSimDeref( p, Vec_IntEntry(p->vLis, iPioNum-p->nPis) ); + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = pRes0[w]; + } + // handle unused PIs + if ( pRes[0] == 0 ) + { + pRes[0] = 1; + Raig_ManSimDeref( p, Vec_IntEntry(p->vLos, iPioNum-p->nPis) ); + } + } + // simulate the logic + nCis = nCos = 0; + for ( i = 2; i < p->nObjs; i++ ) + { + if ( p->pFans0[i] == 0 ) // ci always has zero first fanin + { + iPioNum = Vec_IntEntry( p->vCis2Ids, nCis ); + if ( iPioNum < p->nPis ) + { + pRes = Raig_ManSimRef( p, i ); + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = Aig_ManRandom( 0 ); + // handle unused PIs + if ( pRes[0] == 0 ) + { + pRes[0] = 1; + Raig_ManSimDeref( p, i ); + } + } + else + assert( Vec_IntEntry(p->vLos, iPioNum-p->nPis) == i ); + nCis++; + continue; + } + if ( p->pFans1[i] == 0 ) // co always has non-zero 1st fanin and zero 2nd fanin + { + pRes0 = Raig_ManSimDeref( p, Raig_Lit2Var(p->pFans0[i]) ); + if ( nCos < p->nPos && fMiter ) + { + unsigned Const = Raig_LitIsCompl(p->pFans0[i])? ~0 : 0; + for ( w = 1; w <= p->nWords; w++ ) + if ( pRes0[w] != Const ) + { + *piPat = 32*(w-1) + Aig_WordFindFirstBit( pRes0[w] ^ Const ); + return i; + } + } + else + { + pRes = Raig_ManSimRef( p, i ); + assert( pRes[0] == 1 ); + if ( Raig_LitIsCompl(p->pFans0[i]) ) + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = ~pRes0[w]; + else + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = pRes0[w]; + } + nCos++; + continue; + } + pRes = Raig_ManSimRef( p, i ); + assert( pRes[0] > 0 ); + iFan0 = p->pFans0[i]; + iFan1 = p->pFans1[i]; + pRes0 = Raig_ManSimDeref( p, Raig_Lit2Var(p->pFans0[i]) ); + pRes1 = Raig_ManSimDeref( p, Raig_Lit2Var(p->pFans1[i]) ); + if ( Raig_LitIsCompl(iFan0) && Raig_LitIsCompl(iFan1) ) + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = ~(pRes0[w] | pRes1[w]); + else if ( Raig_LitIsCompl(iFan0) && !Raig_LitIsCompl(iFan1) ) + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = ~pRes0[w] & pRes1[w]; + else if ( !Raig_LitIsCompl(iFan0) && Raig_LitIsCompl(iFan1) ) + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = pRes0[w] & ~pRes1[w]; + else if ( !Raig_LitIsCompl(iFan0) && !Raig_LitIsCompl(iFan1) ) + for ( w = 1; w <= p->nWords; w++ ) + pRes[w] = pRes0[w] & pRes1[w]; + } + assert( nCis == p->nCis ); + assert( nCos == p->nCos ); + assert( p->nMems == 1 + Vec_IntSize(p->vLis) ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns the counter-example.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Cex_t * Raig_ManGenerateCounter( Aig_Man_t * pAig, int iFrame, int iOut, int nWords, int iPat, Vec_Int_t * vCis2Ids ) +{ + Abc_Cex_t * p; + unsigned * pData; + int f, i, w, iPioId, Counter; + p = Abc_CexAlloc( Aig_ManRegNum(pAig), Saig_ManPiNum(pAig), iFrame+1 ); + p->iFrame = iFrame; + p->iPo = iOut; + // fill in the binary data + Aig_ManRandom( 1 ); + Counter = p->nRegs; + pData = ABC_ALLOC( unsigned, nWords ); + for ( f = 0; f <= iFrame; f++, Counter += p->nPis ) + for ( i = 0; i < Aig_ManCiNum(pAig); i++ ) + { + iPioId = Vec_IntEntry( vCis2Ids, i ); + if ( iPioId >= p->nPis ) + continue; + for ( w = 0; w < nWords; w++ ) + pData[w] = Aig_ManRandom( 0 ); + if ( Abc_InfoHasBit( pData, iPat ) ) + Abc_InfoSetBit( p->pData, Counter + iPioId ); + } + ABC_FREE( pData ); + return p; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the bug is detected, 0 otherwise.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Raig_ManSimulate( Aig_Man_t * pAig, int nWords, int nIters, int TimeLimit, int fMiter, int fVerbose ) +{ + Raig_Man_t * p; + Sec_MtrStatus_t Status; + int i, iPat, RetValue = 0; + abctime clk, clkTotal = Abc_Clock(); + assert( Aig_ManRegNum(pAig) > 0 ); + Status = Sec_MiterStatus( pAig ); + if ( Status.nSat > 0 ) + { + printf( "Miter is trivially satisfiable (output %d).\n", Status.iOut ); + return 1; + } + if ( Status.nUndec == 0 ) + { + printf( "Miter is trivially unsatisfiable.\n" ); + return 0; + } + Aig_ManRandom( 1 ); + p = Raig_ManCreate( pAig ); + p->nWords = nWords; + // iterate through objects + for ( i = 0; i < nIters; i++ ) + { + clk = Abc_Clock(); + RetValue = Raig_ManSimulateRound( p, fMiter, i==0, &iPat ); + if ( fVerbose ) + { + printf( "Frame %4d out of %4d and timeout %3d sec. ", i+1, nIters, TimeLimit ); + printf("Time = %7.2f sec\r", (1.0*Abc_Clock()-clkTotal)/CLOCKS_PER_SEC); + } + if ( RetValue > 0 ) + { + int iOut = Raig_ManFindPo(p->pAig, RetValue); + assert( pAig->pSeqModel == NULL ); + pAig->pSeqModel = Raig_ManGenerateCounter( pAig, i, iOut, nWords, iPat, p->vCis2Ids ); + if ( fVerbose ) + printf( "Miter is satisfiable after simulation (output %d).\n", iOut ); + break; + } + if ( (Abc_Clock() - clk)/CLOCKS_PER_SEC >= TimeLimit ) + { + printf( "No bug detected after %d frames with time limit %d seconds.\n", i+1, TimeLimit ); + break; + } + } + if ( fVerbose ) + { + printf( "Maxcut = %8d. AigMem = %7.2f MB. SimMem = %7.2f MB. ", + p->nMemsMax, + 1.0*(p->nObjs * 16)/(1<<20), + 1.0*(p->nMemsMax * 4 * (nWords+1))/(1<<20) ); + ABC_PRT( "Total time", Abc_Clock() - clkTotal ); + } + Raig_ManDelete( p ); + return RetValue > 0; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigStrSim.c b/yosys/abc/src/aig/saig/saigStrSim.c new file mode 100644 index 00000000000..6c4ffa8e717 --- /dev/null +++ b/yosys/abc/src/aig/saig/saigStrSim.c @@ -0,0 +1,976 @@ +/**CFile**************************************************************** + + FileName [saigStrSim.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Structural matching using simulation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigStrSim.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" +#include "proof/ssw/ssw.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define SAIG_WORDS 16 + +static inline Aig_Obj_t * Saig_ObjNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj ) { return ppNexts[pObj->Id]; } +static inline void Saig_ObjSetNext( Aig_Obj_t ** ppNexts, Aig_Obj_t * pObj, Aig_Obj_t * pNext ) { ppNexts[pObj->Id] = pNext; } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Computes hash value of the node using its simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +unsigned Saig_StrSimHash( Aig_Obj_t * pObj ) +{ + static int s_SPrimes[128] = { + 1009, 1049, 1093, 1151, 1201, 1249, 1297, 1361, 1427, 1459, + 1499, 1559, 1607, 1657, 1709, 1759, 1823, 1877, 1933, 1997, + 2039, 2089, 2141, 2213, 2269, 2311, 2371, 2411, 2467, 2543, + 2609, 2663, 2699, 2741, 2797, 2851, 2909, 2969, 3037, 3089, + 3169, 3221, 3299, 3331, 3389, 3461, 3517, 3557, 3613, 3671, + 3719, 3779, 3847, 3907, 3943, 4013, 4073, 4129, 4201, 4243, + 4289, 4363, 4441, 4493, 4549, 4621, 4663, 4729, 4793, 4871, + 4933, 4973, 5021, 5087, 5153, 5227, 5281, 5351, 5417, 5471, + 5519, 5573, 5651, 5693, 5749, 5821, 5861, 5923, 6011, 6073, + 6131, 6199, 6257, 6301, 6353, 6397, 6481, 6563, 6619, 6689, + 6737, 6803, 6863, 6917, 6977, 7027, 7109, 7187, 7237, 7309, + 7393, 7477, 7523, 7561, 7607, 7681, 7727, 7817, 7877, 7933, + 8011, 8039, 8059, 8081, 8093, 8111, 8123, 8147 + }; + unsigned * pSims; + unsigned uHash = 0; + int i; + assert( SAIG_WORDS <= 128 ); + pSims = (unsigned *)pObj->pData; + for ( i = 0; i < SAIG_WORDS; i++ ) + uHash ^= pSims[i] * s_SPrimes[i & 0x7F]; + return uHash; +} + +/**Function************************************************************* + + Synopsis [Computes hash value of the node using its simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_StrSimIsEqual( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) +{ + unsigned * pSims0 = (unsigned *)pObj0->pData; + unsigned * pSims1 = (unsigned *)pObj1->pData; + int i; + for ( i = 0; i < SAIG_WORDS; i++ ) + if ( pSims0[i] != pSims1[i] ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation info is zero.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_StrSimIsZero( Aig_Obj_t * pObj ) +{ + unsigned * pSims = (unsigned *)pObj->pData; + int i; + for ( i = 0; i < SAIG_WORDS; i++ ) + if ( pSims[i] != 0 ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if simulation info is one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_StrSimIsOne( Aig_Obj_t * pObj ) +{ + unsigned * pSims = (unsigned *)pObj->pData; + int i; + for ( i = 0; i < SAIG_WORDS; i++ ) + if ( pSims[i] != ~0 ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Assigns random simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimAssignRandom( Aig_Obj_t * pObj ) +{ + unsigned * pSims = (unsigned *)pObj->pData; + int i; + for ( i = 0; i < SAIG_WORDS; i++ ) + pSims[i] = Aig_ManRandom(0); +} + +/**Function************************************************************* + + Synopsis [Assigns constant 0 simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimAssignOne( Aig_Obj_t * pObj ) +{ + unsigned * pSims = (unsigned *)pObj->pData; + int i; + for ( i = 0; i < SAIG_WORDS; i++ ) + pSims[i] = ~0; +} + +/**Function************************************************************* + + Synopsis [Assigns constant 0 simulation info.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimAssignZeroInit( Aig_Obj_t * pObj ) +{ + unsigned * pSims = (unsigned *)pObj->pData; + pSims[0] = 0; +} + +/**Function************************************************************* + + Synopsis [Simulated one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimulateNode( Aig_Obj_t * pObj, int i ) +{ + unsigned * pSims = (unsigned *)pObj->pData; + unsigned * pSims0 = (unsigned *)Aig_ObjFanin0(pObj)->pData; + unsigned * pSims1 = (unsigned *)Aig_ObjFanin1(pObj)->pData; + if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) + pSims[i] = ~(pSims0[i] | pSims1[i]); + else if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) ) + pSims[i] = (~pSims0[i] & pSims1[i]); + else if ( !Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) + pSims[i] = (pSims0[i] & ~pSims1[i]); + else // if ( !Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) ) + pSims[i] = (pSims0[i] & pSims1[i]); +} + +/**Function************************************************************* + + Synopsis [Saves output of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimSaveOutput( Aig_Obj_t * pObj, int i ) +{ + unsigned * pSims = (unsigned *)pObj->pData; + unsigned * pSims0 = (unsigned *)Aig_ObjFanin0(pObj)->pData; + if ( Aig_ObjFaninC0(pObj) ) + pSims[i] = ~pSims0[i]; + else + pSims[i] = pSims0[i]; +} + +/**Function************************************************************* + + Synopsis [Transfers simulation output to another node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimTransfer( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1 ) +{ + unsigned * pSims0 = (unsigned *)pObj0->pData; + unsigned * pSims1 = (unsigned *)pObj1->pData; + int i; + for ( i = 0; i < SAIG_WORDS; i++ ) + pSims1[i] = pSims0[i]; +} + +/**Function************************************************************* + + Synopsis [Transfers simulation output to another node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimTransferNext( Aig_Obj_t * pObj0, Aig_Obj_t * pObj1, int i ) +{ + unsigned * pSims0 = (unsigned *)pObj0->pData; + unsigned * pSims1 = (unsigned *)pObj1->pData; + assert( i < SAIG_WORDS - 1 ); + pSims1[i+1] = pSims0[i]; +} + +/**Function************************************************************* + + Synopsis [Perform one round of simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimulateRound( Aig_Man_t * p0, Aig_Man_t * p1 ) +{ + Aig_Obj_t * pObj0, * pObj1; + int f, i; + // simulate the nodes + Aig_ManForEachObj( p0, pObj0, i ) + { + if ( !Aig_ObjIsCi(pObj0) && !Aig_ObjIsNode(pObj0) ) + continue; + pObj1 = Aig_ObjRepr(p0, pObj0); + if ( pObj1 == NULL ) + continue; + assert( Aig_ObjRepr(p1, pObj1) == pObj0 ); + Saig_StrSimAssignRandom( pObj0 ); + Saig_StrSimTransfer( pObj0, pObj1 ); + } + // simulate the timeframes + for ( f = 0; f < SAIG_WORDS; f++ ) + { + // simulate the first AIG + Aig_ManForEachNode( p0, pObj0, i ) + if ( Aig_ObjRepr(p0, pObj0) == NULL ) + Saig_StrSimulateNode( pObj0, f ); + Saig_ManForEachLi( p0, pObj0, i ) + Saig_StrSimSaveOutput( pObj0, f ); + if ( f < SAIG_WORDS - 1 ) + Saig_ManForEachLiLo( p0, pObj0, pObj1, i ) + Saig_StrSimTransferNext( pObj0, pObj1, f ); + // simulate the second AIG + Aig_ManForEachNode( p1, pObj1, i ) + if ( Aig_ObjRepr(p1, pObj1) == NULL ) + Saig_StrSimulateNode( pObj1, f ); + Saig_ManForEachLi( p1, pObj1, i ) + Saig_StrSimSaveOutput( pObj1, f ); + if ( f < SAIG_WORDS - 1 ) + Saig_ManForEachLiLo( p1, pObj1, pObj0, i ) + Saig_StrSimTransferNext( pObj1, pObj0, f ); + } +} + +/**Function************************************************************* + + Synopsis [Checks if the entry exists in the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Saig_StrSimTableLookup( Aig_Obj_t ** ppTable, Aig_Obj_t ** ppNexts, int nTableSize, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pEntry; + int iEntry; + // find the hash entry + iEntry = Saig_StrSimHash( pObj ) % nTableSize; + // check if there are nodes with this signatures + for ( pEntry = ppTable[iEntry]; pEntry; pEntry = Saig_ObjNext(ppNexts,pEntry) ) + if ( Saig_StrSimIsEqual( pEntry, pObj ) ) + return pEntry; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Inserts the entry into the table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimTableInsert( Aig_Obj_t ** ppTable, Aig_Obj_t ** ppNexts, int nTableSize, Aig_Obj_t * pObj ) +{ + // find the hash entry + int iEntry = Saig_StrSimHash( pObj ) % nTableSize; + // check if there are nodes with this signatures + if ( ppTable[iEntry] == NULL ) + ppTable[iEntry] = pObj; + else + { + Saig_ObjSetNext( ppNexts, pObj, Saig_ObjNext(ppNexts, ppTable[iEntry]) ); + Saig_ObjSetNext( ppNexts, ppTable[iEntry], pObj ); + } +} + +/**Function************************************************************* + + Synopsis [Perform one round of matching.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_StrSimDetectUnique( Aig_Man_t * p0, Aig_Man_t * p1 ) +{ + Aig_Obj_t ** ppTable, ** ppNexts, ** ppCands; + Aig_Obj_t * pObj, * pEntry; + int i, nTableSize, Counter; + + // allocate the hash table hashing simulation info into nodes + nTableSize = Abc_PrimeCudd( Aig_ManObjNum(p0)/2 ); + ppTable = ABC_CALLOC( Aig_Obj_t *, nTableSize ); + ppNexts = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p0) ); + ppCands = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(p0) ); + + // hash nodes of the first AIG + Aig_ManForEachObj( p0, pObj, i ) + { + if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) ) + continue; + if ( Aig_ObjRepr(p0, pObj) ) + continue; + if ( Saig_StrSimIsZero(pObj) || Saig_StrSimIsOne(pObj) ) + continue; + // check if the entry exists + pEntry = Saig_StrSimTableLookup( ppTable, ppNexts, nTableSize, pObj ); + if ( pEntry == NULL ) // insert + Saig_StrSimTableInsert( ppTable, ppNexts, nTableSize, pObj ); + else // mark the entry as not unique + pEntry->fMarkA = 1; + } + + // hash nodes from the second AIG + Aig_ManForEachObj( p1, pObj, i ) + { + if ( !Aig_ObjIsCi(pObj) && !Aig_ObjIsNode(pObj) ) + continue; + if ( Aig_ObjRepr(p1, pObj) ) + continue; + if ( Saig_StrSimIsZero(pObj) || Saig_StrSimIsOne(pObj) ) + continue; + // check if the entry exists + pEntry = Saig_StrSimTableLookup( ppTable, ppNexts, nTableSize, pObj ); + if ( pEntry == NULL ) // skip + continue; + // if there is no candidate, label it + if ( Saig_ObjNext( ppCands, pEntry ) == NULL ) + Saig_ObjSetNext( ppCands, pEntry, pObj ); + else // mark the entry as not unique + pEntry->fMarkA = 1; + } + + // create representatives for the unique entries + Counter = 0; + for ( i = 0; i < nTableSize; i++ ) + for ( pEntry = ppTable[i]; pEntry; pEntry = Saig_ObjNext(ppNexts,pEntry) ) + if ( !pEntry->fMarkA && (pObj = Saig_ObjNext( ppCands, pEntry )) ) + { +// assert( Aig_ObjIsNode(pEntry) == Aig_ObjIsNode(pObj) ); + if ( Aig_ObjType(pEntry) != Aig_ObjType(pObj) ) + continue; + Aig_ObjSetRepr( p0, pEntry, pObj ); + Aig_ObjSetRepr( p1, pObj, pEntry ); + Counter++; + } + + // cleanup + Aig_ManCleanMarkA( p0 ); + ABC_FREE( ppTable ); + ABC_FREE( ppNexts ); + ABC_FREE( ppCands ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of matched flops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_StrSimCountMatchedFlops( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + Saig_ManForEachLo( p, pObj, i ) + if ( Aig_ObjRepr(p, pObj) ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of matched nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_StrSimCountMatchedNodes( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + Aig_ManForEachNode( p, pObj, i ) + if ( Aig_ObjRepr(p, pObj) ) + Counter++; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Performs structural matching of two AIGs using simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimPrepareAig( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i; + Aig_ManReprStart( p, Aig_ManObjNumMax(p) ); + // allocate simulation info + p->pData2 = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(p), SAIG_WORDS ); + Aig_ManForEachObj( p, pObj, i ) + pObj->pData = Vec_PtrEntry( (Vec_Ptr_t *)p->pData2, i ); + // set simulation info for constant1 and register outputs + Saig_StrSimAssignOne( Aig_ManConst1(p) ); + Saig_ManForEachLo( p, pObj, i ) + Saig_StrSimAssignZeroInit( pObj ); +} + +/**Function************************************************************* + + Synopsis [Performs structural matching of two AIGs using simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimSetInitMatching( Aig_Man_t * p0, Aig_Man_t * p1 ) +{ + Aig_Obj_t * pObj0, * pObj1; + int i; + pObj0 = Aig_ManConst1( p0 ); + pObj1 = Aig_ManConst1( p1 ); + Aig_ObjSetRepr( p0, pObj0, pObj1 ); + Aig_ObjSetRepr( p1, pObj1, pObj0 ); + Saig_ManForEachPi( p0, pObj0, i ) + { + pObj1 = Aig_ManCi( p1, i ); + Aig_ObjSetRepr( p0, pObj0, pObj1 ); + Aig_ObjSetRepr( p1, pObj1, pObj0 ); + } +} + +/**Function************************************************************* + + Synopsis [Performs structural matching of two AIGs using simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimSetFinalMatching( Aig_Man_t * p0, Aig_Man_t * p1 ) +{ + Aig_Obj_t * pObj0, * pObj1; + Aig_Obj_t * pFanin00, * pFanin01; + Aig_Obj_t * pFanin10, * pFanin11; + int i, CountAll = 0, CountNot = 0; + Aig_ManIncrementTravId( p0 ); + Aig_ManForEachObj( p0, pObj0, i ) + { + pObj1 = Aig_ObjRepr( p0, pObj0 ); + if ( pObj1 == NULL ) + continue; + CountAll++; + assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) ); + if ( Aig_ObjIsNode(pObj0) ) + { + assert( Aig_ObjIsNode(pObj1) ); + pFanin00 = Aig_ObjFanin0(pObj0); + pFanin01 = Aig_ObjFanin1(pObj0); + pFanin10 = Aig_ObjFanin0(pObj1); + pFanin11 = Aig_ObjFanin1(pObj1); + if ( Aig_ObjRepr(p0, pFanin00) != pFanin10 || + Aig_ObjRepr(p0, pFanin01) != pFanin11 ) + { + Aig_ObjSetTravIdCurrent(p0, pObj0); + CountNot++; + } + } + else if ( Saig_ObjIsLo(p0, pObj0) ) + { + assert( Saig_ObjIsLo(p1, pObj1) ); + pFanin00 = Aig_ObjFanin0( Saig_ObjLoToLi(p0, pObj0) ); + pFanin10 = Aig_ObjFanin0( Saig_ObjLoToLi(p1, pObj1) ); + if ( Aig_ObjRepr(p0, pFanin00) != pFanin10 ) + { + Aig_ObjSetTravIdCurrent(p0, pObj0); + CountNot++; + } + } + } + // remove irrelevant matches + Aig_ManForEachObj( p0, pObj0, i ) + { + pObj1 = Aig_ObjRepr( p0, pObj0 ); + if ( pObj1 == NULL ) + continue; + assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) ); + if ( Aig_ObjIsTravIdCurrent( p0, pObj0 ) ) + { + Aig_ObjSetRepr( p0, pObj0, NULL ); + Aig_ObjSetRepr( p1, pObj1, NULL ); + } + } + Abc_Print( 1, "Total matches = %6d. Wrong matches = %6d. Ratio = %5.2f %%\n", + CountAll, CountNot, 100.0*CountNot/CountAll ); +} + +/**Function************************************************************* + + Synopsis [Returns the number of dangling nodes removed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimSetContiguousMatching_rec( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pFanout; + int i, iFanout = -1; + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + return; + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Saig_ObjIsPo( p, pObj ) ) + return; + if ( Saig_ObjIsLi( p, pObj ) ) + { + Saig_StrSimSetContiguousMatching_rec( p, Saig_ObjLiToLo(p, pObj) ); + return; + } + assert( Aig_ObjIsCi(pObj) || Aig_ObjIsNode(pObj) ); + if ( Aig_ObjRepr(p, pObj) == NULL ) + return; + // go through the fanouts + Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) + Saig_StrSimSetContiguousMatching_rec( p, pFanout ); + // go through the fanins + if ( !Aig_ObjIsCi( pObj ) ) + { + Saig_StrSimSetContiguousMatching_rec( p, Aig_ObjFanin0(pObj) ); + Saig_StrSimSetContiguousMatching_rec( p, Aig_ObjFanin1(pObj) ); + } +} + +/**Function************************************************************* + + Synopsis [Performs structural matching of two AIGs using simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_StrSimSetContiguousMatching( Aig_Man_t * p0, Aig_Man_t * p1 ) +{ + Aig_Obj_t * pObj0, * pObj1; + int i, CountAll = 0, CountNot = 0; + // mark nodes reachable through the PIs + Aig_ManIncrementTravId( p0 ); + Aig_ObjSetTravIdCurrent( p0, Aig_ManConst1(p0) ); + Saig_ManForEachPi( p0, pObj0, i ) + Saig_StrSimSetContiguousMatching_rec( p0, pObj0 ); + // remove irrelevant matches + Aig_ManForEachObj( p0, pObj0, i ) + { + pObj1 = Aig_ObjRepr( p0, pObj0 ); + if ( pObj1 == NULL ) + continue; + CountAll++; + assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) ); + if ( !Aig_ObjIsTravIdCurrent( p0, pObj0 ) ) + { + Aig_ObjSetRepr( p0, pObj0, NULL ); + Aig_ObjSetRepr( p1, pObj1, NULL ); + CountNot++; + } + } + Abc_Print( 1, "Total matches = %6d. Wrong matches = %6d. Ratio = %5.2f %%\n", + CountAll, CountNot, 100.0*CountNot/CountAll ); +} + + + +/**Function************************************************************* + + Synopsis [Establishes relationship between nodes using pairing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_StrSimMatchingExtendOne( Aig_Man_t * p, Vec_Ptr_t * vNodes ) +{ + Aig_Obj_t * pNext, * pObj; + int i, k, iFan = -1; + Vec_PtrClear( vNodes ); + Aig_ManIncrementTravId( p ); + Aig_ManForEachObj( p, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) ) + continue; + if ( Aig_ObjRepr( p, pObj ) != NULL ) + continue; + if ( Saig_ObjIsLo(p, pObj) ) + { + pNext = Saig_ObjLoToLi(p, pObj); + pNext = Aig_ObjFanin0(pNext); + if ( Aig_ObjRepr( p, pNext ) && !Aig_ObjIsTravIdCurrent(p, pNext) && !Aig_ObjIsConst1(pNext) ) + { + Aig_ObjSetTravIdCurrent(p, pNext); + Vec_PtrPush( vNodes, pNext ); + } + } + if ( Aig_ObjIsNode(pObj) ) + { + pNext = Aig_ObjFanin0(pObj); + if ( Aig_ObjRepr( p, pNext )&& !Aig_ObjIsTravIdCurrent(p, pNext) ) + { + Aig_ObjSetTravIdCurrent(p, pNext); + Vec_PtrPush( vNodes, pNext ); + } + pNext = Aig_ObjFanin1(pObj); + if ( Aig_ObjRepr( p, pNext ) && !Aig_ObjIsTravIdCurrent(p, pNext) ) + { + Aig_ObjSetTravIdCurrent(p, pNext); + Vec_PtrPush( vNodes, pNext ); + } + } + Aig_ObjForEachFanout( p, pObj, pNext, iFan, k ) + { + if ( Saig_ObjIsPo(p, pNext) ) + continue; + if ( Saig_ObjIsLi(p, pNext) ) + pNext = Saig_ObjLiToLo(p, pNext); + if ( Aig_ObjRepr( p, pNext ) && !Aig_ObjIsTravIdCurrent(p, pNext) ) + { + Aig_ObjSetTravIdCurrent(p, pNext); + Vec_PtrPush( vNodes, pNext ); + } + } + } +} + +/**Function************************************************************* + + Synopsis [Establishes relationship between nodes using pairing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Ssw_StrSimMatchingCountUnmached( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, Counter = 0; + Aig_ManForEachObj( p, pObj, i ) + { + if ( !Aig_ObjIsNode(pObj) && !Aig_ObjIsCi(pObj) ) + continue; + if ( Aig_ObjRepr( p, pObj ) != NULL ) + continue; + Counter++; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Establishes relationship between nodes using pairing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Ssw_StrSimMatchingExtend( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose ) +{ + Vec_Ptr_t * vNodes0, * vNodes1; + Aig_Obj_t * pNext0, * pNext1; + int d, k; + vNodes0 = Vec_PtrAlloc( 1000 ); + vNodes1 = Vec_PtrAlloc( 1000 ); + if ( fVerbose ) + { + int nUnmached = Ssw_StrSimMatchingCountUnmached(p0); + Abc_Print( 1, "Extending islands by %d steps:\n", nDist ); + Abc_Print( 1, "%2d : Total = %6d. Unmatched = %6d. Ratio = %6.2f %%\n", + 0, Aig_ManCiNum(p0) + Aig_ManNodeNum(p0), + nUnmached, 100.0 * nUnmached/(Aig_ManCiNum(p0) + Aig_ManNodeNum(p0)) ); + } + for ( d = 0; d < nDist; d++ ) + { + Ssw_StrSimMatchingExtendOne( p0, vNodes0 ); + Ssw_StrSimMatchingExtendOne( p1, vNodes1 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes0, pNext0, k ) + { + pNext1 = Aig_ObjRepr( p0, pNext0 ); + if ( pNext1 == NULL ) + continue; + assert( pNext0 == Aig_ObjRepr( p1, pNext1 ) ); + if ( Saig_ObjIsPi(p1, pNext1) ) + continue; + Aig_ObjSetRepr( p0, pNext0, NULL ); + Aig_ObjSetRepr( p1, pNext1, NULL ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes1, pNext1, k ) + { + pNext0 = Aig_ObjRepr( p1, pNext1 ); + if ( pNext0 == NULL ) + continue; + assert( pNext1 == Aig_ObjRepr( p0, pNext0 ) ); + if ( Saig_ObjIsPi(p0, pNext0) ) + continue; + Aig_ObjSetRepr( p0, pNext0, NULL ); + Aig_ObjSetRepr( p1, pNext1, NULL ); + } + if ( fVerbose ) + { + int nUnmached = Ssw_StrSimMatchingCountUnmached(p0); + Abc_Print( 1, "%2d : Total = %6d. Unmatched = %6d. Ratio = %6.2f %%\n", + d+1, Aig_ManCiNum(p0) + Aig_ManNodeNum(p0), + nUnmached, 100.0 * nUnmached/(Aig_ManCiNum(p0) + Aig_ManNodeNum(p0)) ); + } + } + Vec_PtrFree( vNodes0 ); + Vec_PtrFree( vNodes1 ); +} + + +/**Function************************************************************* + + Synopsis [Performs structural matching of two AIGs using simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_StrSimPerformMatching( Aig_Man_t * p0, Aig_Man_t * p1, int nDist, int fVerbose, Aig_Man_t ** ppMiter ) +{ + extern Aig_Man_t * Saig_ManWindowExtractMiter( Aig_Man_t * p0, Aig_Man_t * p1 ); + + Vec_Int_t * vPairs; + Aig_Man_t * pPart0, * pPart1; + Aig_Obj_t * pObj0, * pObj1; + int i, nMatches; + abctime clk, clkTotal = Abc_Clock(); + Aig_ManRandom( 1 ); + // consider the case when a miter is given + if ( p1 == NULL ) + { + if ( fVerbose ) + { + Aig_ManPrintStats( p0 ); + } + // demiter the miter + if ( !Saig_ManDemiterSimpleDiff( p0, &pPart0, &pPart1 ) ) + { + Abc_Print( 1, "Demitering has failed.\n" ); + return NULL; + } + } + else + { + pPart0 = Aig_ManDupSimple( p0 ); + pPart1 = Aig_ManDupSimple( p1 ); + } + if ( fVerbose ) + { + Aig_ManPrintStats( pPart0 ); + Aig_ManPrintStats( pPart1 ); + } + // start simulation + Saig_StrSimPrepareAig( pPart0 ); + Saig_StrSimPrepareAig( pPart1 ); + Saig_StrSimSetInitMatching( pPart0, pPart1 ); + if ( fVerbose ) + { + Abc_Print( 1, "Allocated %6.2f MB to simulate the first AIG.\n", + 1.0 * Aig_ManObjNumMax(pPart0) * SAIG_WORDS * sizeof(unsigned) / (1<<20) ); + Abc_Print( 1, "Allocated %6.2f MB to simulate the second AIG.\n", + 1.0 * Aig_ManObjNumMax(pPart1) * SAIG_WORDS * sizeof(unsigned) / (1<<20) ); + } + // iterate matching + nMatches = 1; + for ( i = 0; nMatches > 0; i++ ) + { + clk = Abc_Clock(); + Saig_StrSimulateRound( pPart0, pPart1 ); + nMatches = Saig_StrSimDetectUnique( pPart0, pPart1 ); + if ( fVerbose ) + { + int nFlops = Saig_StrSimCountMatchedFlops(pPart0); + int nNodes = Saig_StrSimCountMatchedNodes(pPart0); + Abc_Print( 1, "%3d : Match =%6d. FF =%6d. (%6.2f %%) Node =%6d. (%6.2f %%) ", + i, nMatches, + nFlops, 100.0*nFlops/Aig_ManRegNum(pPart0), + nNodes, 100.0*nNodes/Aig_ManNodeNum(pPart0) ); + ABC_PRT( "Time", Abc_Clock() - clk ); + } + if ( i == 20 ) + break; + } + // cleanup + Vec_PtrFree( (Vec_Ptr_t *)pPart0->pData2 ); pPart0->pData2 = NULL; + Vec_PtrFree( (Vec_Ptr_t *)pPart1->pData2 ); pPart1->pData2 = NULL; + // extend the islands + Aig_ManFanoutStart( pPart0 ); + Aig_ManFanoutStart( pPart1 ); + if ( nDist ) + Ssw_StrSimMatchingExtend( pPart0, pPart1, nDist, fVerbose ); + Saig_StrSimSetFinalMatching( pPart0, pPart1 ); +// Saig_StrSimSetContiguousMatching( pPart0, pPart1 ); + // copy the results into array + vPairs = Vec_IntAlloc( 2*Aig_ManObjNumMax(pPart0) ); + Aig_ManForEachObj( pPart0, pObj0, i ) + { + pObj1 = Aig_ObjRepr(pPart0, pObj0); + if ( pObj1 == NULL ) + continue; + assert( pObj0 == Aig_ObjRepr(pPart1, pObj1) ); + Vec_IntPush( vPairs, pObj0->Id ); + Vec_IntPush( vPairs, pObj1->Id ); + } + // this procedure adds matching of PO and LI + if ( ppMiter ) + *ppMiter = Saig_ManWindowExtractMiter( pPart0, pPart1 ); + Aig_ManFanoutStop( pPart0 ); + Aig_ManFanoutStop( pPart1 ); + Aig_ManStop( pPart0 ); + Aig_ManStop( pPart1 ); + ABC_PRT( "Total runtime", Abc_Clock() - clkTotal ); + return vPairs; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END diff --git a/yosys/abc/src/aig/saig/saigSwitch.c b/yosys/abc/src/aig/saig/saigSwitch.c new file mode 100644 index 00000000000..b18ca8035b3 --- /dev/null +++ b/yosys/abc/src/aig/saig/saigSwitch.c @@ -0,0 +1,573 @@ +/**CFile**************************************************************** + + FileName [saigSwitch.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Returns switching propabilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigSwitch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" + +#include "base/main/main.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Saig_SimObj_t_ Saig_SimObj_t; +struct Saig_SimObj_t_ +{ + int iFan0; + int iFan1; + unsigned Type : 8; + unsigned Number : 24; + unsigned pData[1]; +}; + +static inline int Saig_SimObjFaninC0( Saig_SimObj_t * pObj ) { return pObj->iFan0 & 1; } +static inline int Saig_SimObjFaninC1( Saig_SimObj_t * pObj ) { return pObj->iFan1 & 1; } +static inline int Saig_SimObjFanin0( Saig_SimObj_t * pObj ) { return pObj->iFan0 >> 1; } +static inline int Saig_SimObjFanin1( Saig_SimObj_t * pObj ) { return pObj->iFan1 >> 1; } + +//typedef struct Aig_CMan_t_ Aig_CMan_t; + +//static Aig_CMan_t * Aig_CManCreate( Aig_Man_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates fast simulation manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Saig_SimObj_t * Saig_ManCreateMan( Aig_Man_t * p ) +{ + Saig_SimObj_t * pAig, * pEntry; + Aig_Obj_t * pObj; + int i; + pAig = ABC_CALLOC( Saig_SimObj_t, Aig_ManObjNumMax(p)+1 ); +// printf( "Allocating %7.2f MB.\n", 1.0 * sizeof(Saig_SimObj_t) * (Aig_ManObjNumMax(p)+1)/(1<<20) ); + Aig_ManForEachObj( p, pObj, i ) + { + pEntry = pAig + i; + pEntry->Type = pObj->Type; + if ( Aig_ObjIsCi(pObj) || i == 0 ) + { + if ( Saig_ObjIsLo(p, pObj) ) + { + pEntry->iFan0 = (Saig_ObjLoToLi(p, pObj)->Id << 1); + pEntry->iFan1 = -1; + } + continue; + } + pEntry->iFan0 = (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj); + if ( Aig_ObjIsCo(pObj) ) + continue; + assert( Aig_ObjIsNode(pObj) ); + pEntry->iFan1 = (Aig_ObjFaninId1(pObj) << 1) | Aig_ObjFaninC1(pObj); + } + pEntry = pAig + Aig_ManObjNumMax(p); + pEntry->Type = AIG_OBJ_VOID; + return pAig; +} + +/**Function************************************************************* + + Synopsis [Simulated one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Saig_ManSimulateNode2( Saig_SimObj_t * pAig, Saig_SimObj_t * pObj ) +{ + Saig_SimObj_t * pObj0 = pAig + Saig_SimObjFanin0( pObj ); + Saig_SimObj_t * pObj1 = pAig + Saig_SimObjFanin1( pObj ); + if ( Saig_SimObjFaninC0(pObj) && Saig_SimObjFaninC1(pObj) ) + pObj->pData[0] = ~(pObj0->pData[0] | pObj1->pData[0]); + else if ( Saig_SimObjFaninC0(pObj) && !Saig_SimObjFaninC1(pObj) ) + pObj->pData[0] = (~pObj0->pData[0] & pObj1->pData[0]); + else if ( !Saig_SimObjFaninC0(pObj) && Saig_SimObjFaninC1(pObj) ) + pObj->pData[0] = (pObj0->pData[0] & ~pObj1->pData[0]); + else // if ( !Saig_SimObjFaninC0(pObj) && !Saig_SimObjFaninC1(pObj) ) + pObj->pData[0] = (pObj0->pData[0] & pObj1->pData[0]); +} + +/**Function************************************************************* + + Synopsis [Simulated one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Saig_ManSimulateNode( Saig_SimObj_t * pAig, Saig_SimObj_t * pObj ) +{ + Saig_SimObj_t * pObj0 = pAig + Saig_SimObjFanin0( pObj ); + Saig_SimObj_t * pObj1 = pAig + Saig_SimObjFanin1( pObj ); + pObj->pData[0] = (Saig_SimObjFaninC0(pObj)? ~pObj0->pData[0] : pObj0->pData[0]) + & (Saig_SimObjFaninC1(pObj)? ~pObj1->pData[0] : pObj1->pData[0]); +} + +/**Function************************************************************* + + Synopsis [Simulated buffer/inverter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Saig_ManSimulateOneInput( Saig_SimObj_t * pAig, Saig_SimObj_t * pObj ) +{ + Saig_SimObj_t * pObj0 = pAig + Saig_SimObjFanin0( pObj ); + if ( Saig_SimObjFaninC0(pObj) ) + pObj->pData[0] = ~pObj0->pData[0]; + else // if ( !Saig_SimObjFaninC0(pObj) ) + pObj->pData[0] = pObj0->pData[0]; +} + +/**Function************************************************************* + + Synopsis [Simulates the timeframes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManSimulateFrames( Saig_SimObj_t * pAig, int nFrames, int nPref ) +{ + Saig_SimObj_t * pEntry; + int f; + for ( f = 0; f < nFrames; f++ ) + { + for ( pEntry = pAig; pEntry->Type != AIG_OBJ_VOID; pEntry++ ) + { + if ( pEntry->Type == AIG_OBJ_AND ) + Saig_ManSimulateNode( pAig, pEntry ); + else if ( pEntry->Type == AIG_OBJ_CO ) + Saig_ManSimulateOneInput( pAig, pEntry ); + else if ( pEntry->Type == AIG_OBJ_CI ) + { + if ( pEntry->iFan0 == 0 ) // true PI + pEntry->pData[0] = Aig_ManRandom( 0 ); + else if ( f > 0 ) // register output + Saig_ManSimulateOneInput( pAig, pEntry ); + } + else if ( pEntry->Type == AIG_OBJ_CONST1 ) + pEntry->pData[0] = ~0; + else if ( pEntry->Type != AIG_OBJ_NONE ) + assert( 0 ); + if ( f >= nPref ) + pEntry->Number += Aig_WordCountOnes( pEntry->pData[0] ); + } + } +} + +/**Function************************************************************* + + Synopsis [Computes switching activity of one node.] + + Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Saig_ManComputeSwitching( int nOnes, int nSimWords ) +{ + int nTotal = 32 * nSimWords; + return (float)2.0 * nOnes / nTotal * (nTotal - nOnes) / nTotal; +} + +/**Function************************************************************* + + Synopsis [Computes switching activity of one node.] + + Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Saig_ManComputeProbOne( int nOnes, int nSimWords ) +{ + int nTotal = 32 * nSimWords; + return (float)nOnes / nTotal; +} + +/**Function************************************************************* + + Synopsis [Computes switching activity of one node.] + + Description [Uses the formula: Switching = 2 * nOnes * nZeros / (nTotal ^ 2) ] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Saig_ManComputeProbOnePlus( int nOnes, int nSimWords, int fCompl ) +{ + int nTotal = 32 * nSimWords; + if ( fCompl ) + return (float)(nTotal-nOnes) / nTotal; + else + return (float)nOnes / nTotal; +} + +/**Function************************************************************* + + Synopsis [Compute switching probabilities of all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Saig_ManComputeSwitchProb4s( Aig_Man_t * p, int nFrames, int nPref, int fProbOne ) +{ + Saig_SimObj_t * pAig, * pEntry; + Vec_Int_t * vSwitching; + float * pSwitching; + int nFramesReal; + abctime clk;//, clkTotal = Abc_Clock(); + vSwitching = Vec_IntStart( Aig_ManObjNumMax(p) ); + pSwitching = (float *)vSwitching->pArray; +clk = Abc_Clock(); + pAig = Saig_ManCreateMan( p ); +//ABC_PRT( "\nCreation ", Abc_Clock() - clk ); + + Aig_ManRandom( 1 ); + // get the number of frames to simulate + // if the parameter "seqsimframes" is defined, use it + // otherwise, use the given number of frames "nFrames" + nFramesReal = nFrames; + if ( Abc_FrameReadFlag("seqsimframes") ) + nFramesReal = atoi( Abc_FrameReadFlag("seqsimframes") ); + if ( nFramesReal <= nPref ) + { + printf( "The total number of frames (%d) should exceed prefix (%d).\n", nFramesReal, nPref );\ + printf( "Setting the total number of frames to be %d.\n", nFrames ); + nFramesReal = nFrames; + } +//printf( "Simulating %d frames.\n", nFramesReal ); +clk = Abc_Clock(); + Saig_ManSimulateFrames( pAig, nFramesReal, nPref ); +//ABC_PRT( "Simulation", Abc_Clock() - clk ); +clk = Abc_Clock(); + for ( pEntry = pAig; pEntry->Type != AIG_OBJ_VOID; pEntry++ ) + { +/* + if ( pEntry->Type == AIG_OBJ_AND ) + { + Saig_SimObj_t * pObj0 = pAig + Saig_SimObjFanin0( pEntry ); + Saig_SimObj_t * pObj1 = pAig + Saig_SimObjFanin1( pEntry ); + printf( "%5.2f = %5.2f * %5.2f (%7.4f)\n", + Saig_ManComputeProbOnePlus( pEntry->Number, nFrames - nPref, 0 ), + Saig_ManComputeProbOnePlus( pObj0->Number, nFrames - nPref, Saig_SimObjFaninC0(pEntry) ), + Saig_ManComputeProbOnePlus( pObj1->Number, nFrames - nPref, Saig_SimObjFaninC1(pEntry) ), + Saig_ManComputeProbOnePlus( pEntry->Number, nFrames - nPref, 0 ) - + Saig_ManComputeProbOnePlus( pObj0->Number, nFrames - nPref, Saig_SimObjFaninC0(pEntry) ) * + Saig_ManComputeProbOnePlus( pObj1->Number, nFrames - nPref, Saig_SimObjFaninC1(pEntry) ) + ); + } +*/ + if ( fProbOne ) + pSwitching[pEntry-pAig] = Saig_ManComputeProbOne( pEntry->Number, nFramesReal - nPref ); + else + pSwitching[pEntry-pAig] = Saig_ManComputeSwitching( pEntry->Number, nFramesReal - nPref ); +//printf( "%3d : %7.2f\n", pEntry-pAig, pSwitching[pEntry-pAig] ); + } + ABC_FREE( pAig ); +//ABC_PRT( "Switch ", Abc_Clock() - clk ); +//ABC_PRT( "TOTAL ", Abc_Clock() - clkTotal ); + +// Aig_CManCreate( p ); + return vSwitching; +} + + + + +typedef struct Aig_CMan_t_ Aig_CMan_t; +struct Aig_CMan_t_ +{ + // parameters + int nIns; + int nNodes; + int nOuts; + // current state + int iNode; + int iDiff0; + int iDiff1; + unsigned char * pCur; + // stored data + int iPrev; + int nBytes; + unsigned char Data[0]; +}; + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_CMan_t * Aig_CManStart( int nIns, int nNodes, int nOuts ) +{ + Aig_CMan_t * p; + p = (Aig_CMan_t *)ABC_ALLOC( char, sizeof(Aig_CMan_t) + 2*(2*nNodes + nOuts) ); + memset( p, 0, sizeof(Aig_CMan_t) ); + // set parameters + p->nIns = nIns; + p->nOuts = nOuts; + p->nNodes = nNodes; + p->nBytes = 2*(2*nNodes + nOuts); + // prepare the manager + p->iNode = 1 + p->nIns; + p->iPrev = -1; + p->pCur = p->Data; + return p; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_CManStop( Aig_CMan_t * p ) +{ + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_CManRestart( Aig_CMan_t * p ) +{ + assert( p->iNode == 1 + p->nIns + p->nNodes + p->nOuts ); + p->iNode = 1 + p->nIns; + p->iPrev = -1; + p->pCur = p->Data; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_CManStoreNum( Aig_CMan_t * p, unsigned x ) +{ + while ( x & ~0x7f ) + { + *p->pCur++ = (x & 0x7f) | 0x80; + x >>= 7; + } + *p->pCur++ = x; + assert( p->pCur - p->Data < p->nBytes - 10 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_CManRestoreNum( Aig_CMan_t * p ) +{ + int ch, i, x = 0; + for ( i = 0; (ch = *p->pCur++) & 0x80; i++ ) + x |= (ch & 0x7f) << (7 * i); + return x | (ch << (7 * i)); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_CManAddNode( Aig_CMan_t * p, int iFan0, int iFan1 ) +{ + assert( iFan0 < iFan1 ); + assert( iFan1 < (p->iNode << 1) ); + Aig_CManStoreNum( p, (p->iNode++ << 1) - iFan1 ); + Aig_CManStoreNum( p, iFan1 - iFan0 ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_CManAddPo( Aig_CMan_t * p, int iFan0 ) +{ + if ( p->iPrev == -1 ) + Aig_CManStoreNum( p, p->iNode - iFan0 ); + else if ( p->iPrev <= iFan0 ) + Aig_CManStoreNum( p, (iFan0 - p->iPrev) << 1 ); + else + Aig_CManStoreNum( p,((p->iPrev - iFan0) << 1) | 1 ); + p->iPrev = iFan0; + p->iNode++; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Aig_CManGetNode( Aig_CMan_t * p, int * piFan0, int * piFan1 ) +{ + *piFan1 = (p->iNode++ << 1) - Aig_CManRestoreNum( p ); + *piFan0 = *piFan1 - Aig_CManRestoreNum( p ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Aig_CManGetPo( Aig_CMan_t * p ) +{ + int Num = Aig_CManRestoreNum( p ); + if ( p->iPrev == -1 ) + p->iPrev = p->iNode; + p->iNode++; + if ( Num & 1 ) + return p->iPrev = p->iPrev + (Num >> 1); + return p->iPrev = p->iPrev - (Num >> 1); +} + +/**Function************************************************************* + + Synopsis [Compute switching probabilities of all nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_CMan_t * Aig_CManCreate( Aig_Man_t * p ) +{ + Aig_CMan_t * pCMan; + Aig_Obj_t * pObj; + int i; + pCMan = Aig_CManStart( Aig_ManCiNum(p), Aig_ManNodeNum(p), Aig_ManCoNum(p) ); + Aig_ManForEachNode( p, pObj, i ) + Aig_CManAddNode( pCMan, + (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj), + (Aig_ObjFaninId1(pObj) << 1) | Aig_ObjFaninC1(pObj) ); + Aig_ManForEachCo( p, pObj, i ) + Aig_CManAddPo( pCMan, + (Aig_ObjFaninId0(pObj) << 1) | Aig_ObjFaninC0(pObj) ); + printf( "\nBytes alloc = %5d. Bytes used = %7d. Ave per node = %4.2f. \n", + pCMan->nBytes, (int)(pCMan->pCur - pCMan->Data), + 1.0 * (pCMan->pCur - pCMan->Data) / (pCMan->nNodes + pCMan->nOuts ) ); +// Aig_CManStop( pCMan ); + return pCMan; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigSynch.c b/yosys/abc/src/aig/saig/saigSynch.c new file mode 100644 index 00000000000..b239d3a6a6c --- /dev/null +++ b/yosys/abc/src/aig/saig/saigSynch.c @@ -0,0 +1,665 @@ +/**CFile**************************************************************** + + FileName [saigSynch.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Computation of synchronizing sequence.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigSynch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// 0 1 x +// 00 01 11 +// 0 00 00 00 00 +// 1 01 00 01 11 +// x 11 00 11 11 + +static inline unsigned Saig_SynchNot( unsigned w ) +{ + return w^((~(w&(w>>1)))&0x55555555); +} +static inline unsigned Saig_SynchAnd( unsigned u, unsigned w ) +{ + return (u&w)|((((u&(u>>1)&w&~(w>>1))|(w&(w>>1)&u&~(u>>1)))&0x55555555)<<1); +} +static inline unsigned Saig_SynchRandomBinary() +{ + return Aig_ManRandom(0) & 0x55555555; +} +static inline unsigned Saig_SynchRandomTernary() +{ + unsigned w = Aig_ManRandom(0); + return w^((~w)&(w>>1)&0x55555555); +} +static inline unsigned Saig_SynchTernary( int v ) +{ + assert( v == 0 || v == 1 || v == 3 ); + return v? ((v==1)? 0x55555555 : 0xffffffff) : 0; +} + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Initializes registers to the ternary state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_SynchSetConstant1( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords ) +{ + Aig_Obj_t * pObj; + unsigned * pSim; + int w; + pObj = Aig_ManConst1( pAig ); + pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id ); + for ( w = 0; w < nWords; w++ ) + pSim[w] = 0x55555555; +} + +/**Function************************************************************* + + Synopsis [Initializes registers to the ternary state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_SynchInitRegsTernary( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords ) +{ + Aig_Obj_t * pObj; + unsigned * pSim; + int i, w; + Saig_ManForEachLo( pAig, pObj, i ) + { + pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id ); + for ( w = 0; w < nWords; w++ ) + pSim[w] = 0xffffffff; + } +} + +/**Function************************************************************* + + Synopsis [Initializes registers to the given binary state.] + + Description [The binary state is stored in pObj->fMarkA.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_SynchInitRegsBinary( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords ) +{ + Aig_Obj_t * pObj; + unsigned * pSim; + int i, w; + Saig_ManForEachLo( pAig, pObj, i ) + { + pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id ); + for ( w = 0; w < nWords; w++ ) + pSim[w] = Saig_SynchTernary( pObj->fMarkA ); + } +} + +/**Function************************************************************* + + Synopsis [Initializes random binary primary inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_SynchInitPisRandom( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords ) +{ + Aig_Obj_t * pObj; + unsigned * pSim; + int i, w; + Saig_ManForEachPi( pAig, pObj, i ) + { + pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id ); + for ( w = 0; w < nWords; w++ ) + pSim[w] = Saig_SynchRandomBinary(); + } +} + +/**Function************************************************************* + + Synopsis [Initializes random binary primary inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_SynchInitPisGiven( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords, char * pValues ) +{ + Aig_Obj_t * pObj; + unsigned * pSim; + int i, w; + Saig_ManForEachPi( pAig, pObj, i ) + { + pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id ); + for ( w = 0; w < nWords; w++ ) + pSim[w] = Saig_SynchTernary( pValues[i] ); + } +} + +/**Function************************************************************* + + Synopsis [Performs ternary simulation of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_SynchTernarySimulate( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords ) +{ + Aig_Obj_t * pObj; + unsigned * pSim0, * pSim1, * pSim; + int i, w; + // simulate nodes + Aig_ManForEachNode( pAig, pObj, i ) + { + pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id ); + pSim0 = (unsigned *)Vec_PtrEntry( vSimInfo, Aig_ObjFaninId0(pObj) ); + pSim1 = (unsigned *)Vec_PtrEntry( vSimInfo, Aig_ObjFaninId1(pObj) ); + if ( Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) + { + for ( w = 0; w < nWords; w++ ) + pSim[w] = Saig_SynchAnd( Saig_SynchNot(pSim0[w]), Saig_SynchNot(pSim1[w]) ); + } + else if ( !Aig_ObjFaninC0(pObj) && Aig_ObjFaninC1(pObj) ) + { + for ( w = 0; w < nWords; w++ ) + pSim[w] = Saig_SynchAnd( pSim0[w], Saig_SynchNot(pSim1[w]) ); + } + else if ( Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) ) + { + for ( w = 0; w < nWords; w++ ) + pSim[w] = Saig_SynchAnd( Saig_SynchNot(pSim0[w]), pSim1[w] ); + } + else // if ( !Aig_ObjFaninC0(pObj) && !Aig_ObjFaninC1(pObj) ) + { + for ( w = 0; w < nWords; w++ ) + pSim[w] = Saig_SynchAnd( pSim0[w], pSim1[w] ); + } + } + // transfer values to register inputs + Saig_ManForEachLi( pAig, pObj, i ) + { + pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id ); + pSim0 = (unsigned *)Vec_PtrEntry( vSimInfo, Aig_ObjFaninId0(pObj) ); + if ( Aig_ObjFaninC0(pObj) ) + { + for ( w = 0; w < nWords; w++ ) + pSim[w] = Saig_SynchNot( pSim0[w] ); + } + else + { + for ( w = 0; w < nWords; w++ ) + pSim[w] = pSim0[w]; + } + } +} + +/**Function************************************************************* + + Synopsis [Performs ternary simulation of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_SynchTernaryTransferState( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords ) +{ + Aig_Obj_t * pObjLi, * pObjLo; + unsigned * pSim0, * pSim1; + int i, w; + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + { + pSim0 = (unsigned *)Vec_PtrEntry( vSimInfo, pObjLi->Id ); + pSim1 = (unsigned *)Vec_PtrEntry( vSimInfo, pObjLo->Id ); + for ( w = 0; w < nWords; w++ ) + pSim1[w] = pSim0[w]; + } +} + +/**Function************************************************************* + + Synopsis [Returns the number of Xs in the smallest ternary pattern.] + + Description [Returns the number of this pattern.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_SynchCountX( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords, int * piPat ) +{ + Aig_Obj_t * pObj; + unsigned * pSim; + int * pCounters, i, w, b; + int iPatBest, iTernMin; + // count the number of ternary values in each pattern + pCounters = ABC_CALLOC( int, nWords * 16 ); + Saig_ManForEachLi( pAig, pObj, i ) + { + pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id ); + for ( w = 0; w < nWords; w++ ) + for ( b = 0; b < 16; b++ ) + if ( ((pSim[w] >> (b << 1)) & 3) == 3 ) + pCounters[16 * w + b]++; + } + // get the best pattern + iPatBest = -1; + iTernMin = 1 + Saig_ManRegNum(pAig); + for ( b = 0; b < 16 * nWords; b++ ) + if ( iTernMin > pCounters[b] ) + { + iTernMin = pCounters[b]; + iPatBest = b; + if ( iTernMin == 0 ) + break; + } + ABC_FREE( pCounters ); + *piPat = iPatBest; + return iTernMin; +} + +/**Function************************************************************* + + Synopsis [Saves the best pattern found and initializes the registers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_SynchSavePattern( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, int nWords, int iPat, Vec_Str_t * vSequence ) +{ + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + unsigned * pSim; + int Counter, Value, i, w; + assert( iPat < 16 * nWords ); + Saig_ManForEachPi( pAig, pObj, i ) + { + pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id ); + Value = (pSim[iPat>>4] >> ((iPat&0xf) << 1)) & 3; + Vec_StrPush( vSequence, (char)Value ); +// printf( "%d ", Value ); + } +// printf( "\n" ); + Counter = 0; + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + { + pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObjLi->Id ); + Value = (pSim[iPat>>4] >> ((iPat&0xf) << 1)) & 3; + Counter += (Value == 3); + // save patern in the same register + pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObjLo->Id ); + for ( w = 0; w < nWords; w++ ) + pSim[w] = Saig_SynchTernary( Value ); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Implement synchronizing sequence.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Saig_SynchSequenceRun( Aig_Man_t * pAig, Vec_Ptr_t * vSimInfo, Vec_Str_t * vSequence, int fTernary ) +{ + unsigned * pSim; + Aig_Obj_t * pObj; + int Counter, nIters, Value, i; + assert( Vec_StrSize(vSequence) % Saig_ManPiNum(pAig) == 0 ); + nIters = Vec_StrSize(vSequence) / Saig_ManPiNum(pAig); + Saig_SynchSetConstant1( pAig, vSimInfo, 1 ); + if ( fTernary ) + Saig_SynchInitRegsTernary( pAig, vSimInfo, 1 ); + else + Saig_SynchInitRegsBinary( pAig, vSimInfo, 1 ); + for ( i = 0; i < nIters; i++ ) + { + Saig_SynchInitPisGiven( pAig, vSimInfo, 1, Vec_StrArray(vSequence) + i * Saig_ManPiNum(pAig) ); + Saig_SynchTernarySimulate( pAig, vSimInfo, 1 ); + Saig_SynchTernaryTransferState( pAig, vSimInfo, 1 ); + } + // save the resulting state in the registers + Counter = 0; + Saig_ManForEachLo( pAig, pObj, i ) + { + pSim = (unsigned *)Vec_PtrEntry( vSimInfo, pObj->Id ); + Value = pSim[0] & 3; + assert( Value != 2 ); + Counter += (Value == 3); + pObj->fMarkA = Value; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Determines synchronizing sequence using ternary simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Str_t * Saig_SynchSequence( Aig_Man_t * pAig, int nWords ) +{ + int nStepsMax = 100; // the maximum number of simulation steps + int nTriesMax = 100; // the maximum number of attempts at each step + int fVerify = 1; // verify the resulting pattern + Vec_Str_t * vSequence; + Vec_Ptr_t * vSimInfo; + int nTerPrev, nTerCur = 0, nTerCur2; + int iPatBest, RetValue, s, t; + assert( Saig_ManRegNum(pAig) > 0 ); + // reset random numbers + Aig_ManRandom( 1 ); + // start the sequence + vSequence = Vec_StrAlloc( 20 * Saig_ManRegNum(pAig) ); + // create sim info and init registers + vSimInfo = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(pAig), nWords ); + Saig_SynchSetConstant1( pAig, vSimInfo, nWords ); + // iterate over the timeframes + nTerPrev = Saig_ManRegNum(pAig); + Saig_SynchInitRegsTernary( pAig, vSimInfo, nWords ); + for ( s = 0; s < nStepsMax && nTerPrev > 0; s++ ) + { + for ( t = 0; t < nTriesMax; t++ ) + { + Saig_SynchInitPisRandom( pAig, vSimInfo, nWords ); + Saig_SynchTernarySimulate( pAig, vSimInfo, nWords ); + nTerCur = Saig_SynchCountX( pAig, vSimInfo, nWords, &iPatBest ); + if ( nTerCur < nTerPrev ) + break; + } + if ( t == nTriesMax ) + break; + nTerCur2 = Saig_SynchSavePattern( pAig, vSimInfo, nWords, iPatBest, vSequence ); + assert( nTerCur == nTerCur2 ); + nTerPrev = nTerCur; + } + if ( nTerPrev > 0 ) + { + printf( "Count not initialize %d registers.\n", nTerPrev ); + Vec_PtrFree( vSimInfo ); + Vec_StrFree( vSequence ); + return NULL; + } + // verify that the sequence is correct + if ( fVerify ) + { + RetValue = Saig_SynchSequenceRun( pAig, vSimInfo, vSequence, 1 ); + assert( RetValue == 0 ); + Aig_ManCleanMarkA( pAig ); + } + Vec_PtrFree( vSimInfo ); + return vSequence; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG to have constant-0 initial state.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManDupInitZero( Aig_Man_t * p ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj; + int i; + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + Aig_ManConst1(p)->pData = Aig_ManConst1(pNew); + Saig_ManForEachPi( p, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pNew ); + Saig_ManForEachLo( p, pObj, i ) + pObj->pData = Aig_NotCond( Aig_ObjCreateCi( pNew ), pObj->fMarkA ); + Aig_ManForEachNode( p, pObj, i ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + Saig_ManForEachPo( p, pObj, i ) + pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + Saig_ManForEachLi( p, pObj, i ) + pObj->pData = Aig_ObjCreateCo( pNew, Aig_NotCond( Aig_ObjChild0Copy(pObj), pObj->fMarkA ) ); + Aig_ManSetRegNum( pNew, Saig_ManRegNum(p) ); + assert( Aig_ManNodeNum(pNew) == Aig_ManNodeNum(p) ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Determines synchronizing sequence using ternary simulation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_SynchSequenceApply( Aig_Man_t * pAig, int nWords, int fVerbose ) +{ + Aig_Man_t * pAigZero; + Vec_Str_t * vSequence; + Vec_Ptr_t * vSimInfo; + int RetValue; + abctime clk; + +clk = Abc_Clock(); + // derive synchronization sequence + vSequence = Saig_SynchSequence( pAig, nWords ); + if ( vSequence == NULL ) + printf( "Design 1: Synchronizing sequence is not found. " ); + else if ( fVerbose ) + printf( "Design 1: Synchronizing sequence of length %4d is found. ", Vec_StrSize(vSequence) / Saig_ManPiNum(pAig) ); + if ( fVerbose ) + { + ABC_PRT( "Time", Abc_Clock() - clk ); + } + else + printf( "\n" ); + if ( vSequence == NULL ) + { + printf( "Quitting synchronization.\n" ); + return NULL; + } + + // apply synchronization sequence + vSimInfo = Vec_PtrAllocSimInfo( Aig_ManObjNumMax(pAig), 1 ); + RetValue = Saig_SynchSequenceRun( pAig, vSimInfo, vSequence, 1 ); + assert( RetValue == 0 ); + // duplicate + pAigZero = Saig_ManDupInitZero( pAig ); + // cleanup + Vec_PtrFree( vSimInfo ); + Vec_StrFree( vSequence ); + Aig_ManCleanMarkA( pAig ); + return pAigZero; +} + +/**Function************************************************************* + + Synopsis [Creates SEC miter for two designs without initial state.] + + Description [The designs (pAig1 and pAig2) are assumed to have ternary + initial state. Determines synchronizing sequences using ternary simulation. + Simulates the sequences on both designs to come up with equivalent binary + initial states. Create seq miter for the designs starting in these states.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_Synchronize( Aig_Man_t * pAig1, Aig_Man_t * pAig2, int nWords, int fVerbose ) +{ + Aig_Man_t * pAig1z, * pAig2z, * pMiter; + Vec_Str_t * vSeq1, * vSeq2; + Vec_Ptr_t * vSimInfo; + int RetValue; + abctime clk; +/* + { + unsigned u = Saig_SynchRandomTernary(); + unsigned w = Saig_SynchRandomTernary(); + unsigned x = Saig_SynchNot( u ); + unsigned y = Saig_SynchNot( w ); + unsigned z = Saig_SynchAnd( x, y ); + + Extra_PrintBinary( stdout, &u, 32 ); printf( "\n" ); + Extra_PrintBinary( stdout, &w, 32 ); printf( "\n" ); printf( "\n" ); + Extra_PrintBinary( stdout, &x, 32 ); printf( "\n" ); + Extra_PrintBinary( stdout, &y, 32 ); printf( "\n" ); printf( "\n" ); + Extra_PrintBinary( stdout, &z, 32 ); printf( "\n" ); + } +*/ + // report statistics + if ( fVerbose ) + { + printf( "Design 1: " ); + Aig_ManPrintStats( pAig1 ); + printf( "Design 2: " ); + Aig_ManPrintStats( pAig2 ); + } + + // synchronize the first design + clk = Abc_Clock(); + vSeq1 = Saig_SynchSequence( pAig1, nWords ); + if ( vSeq1 == NULL ) + printf( "Design 1: Synchronizing sequence is not found. " ); + else if ( fVerbose ) + printf( "Design 1: Synchronizing sequence of length %4d is found. ", Vec_StrSize(vSeq1) / Saig_ManPiNum(pAig1) ); + if ( fVerbose ) + { + ABC_PRT( "Time", Abc_Clock() - clk ); + } + else + printf( "\n" ); + + // synchronize the first design + clk = Abc_Clock(); + vSeq2 = Saig_SynchSequence( pAig2, nWords ); + if ( vSeq2 == NULL ) + printf( "Design 2: Synchronizing sequence is not found. " ); + else if ( fVerbose ) + printf( "Design 2: Synchronizing sequence of length %4d is found. ", Vec_StrSize(vSeq2) / Saig_ManPiNum(pAig2) ); + if ( fVerbose ) + { + ABC_PRT( "Time", Abc_Clock() - clk ); + } + else + printf( "\n" ); + + // quit if one of the designs cannot be synchronized + if ( vSeq1 == NULL || vSeq2 == NULL ) + { + printf( "Quitting synchronization.\n" ); + if ( vSeq1 ) Vec_StrFree( vSeq1 ); + if ( vSeq2 ) Vec_StrFree( vSeq2 ); + return NULL; + } + clk = Abc_Clock(); + vSimInfo = Vec_PtrAllocSimInfo( Abc_MaxInt( Aig_ManObjNumMax(pAig1), Aig_ManObjNumMax(pAig2) ), 1 ); + + // process Design 1 + RetValue = Saig_SynchSequenceRun( pAig1, vSimInfo, vSeq1, 1 ); + assert( RetValue == 0 ); + RetValue = Saig_SynchSequenceRun( pAig1, vSimInfo, vSeq2, 0 ); + assert( RetValue == 0 ); + + // process Design 2 + RetValue = Saig_SynchSequenceRun( pAig2, vSimInfo, vSeq2, 1 ); + assert( RetValue == 0 ); + + // duplicate designs + pAig1z = Saig_ManDupInitZero( pAig1 ); + pAig2z = Saig_ManDupInitZero( pAig2 ); + pMiter = Saig_ManCreateMiter( pAig1z, pAig2z, 0 ); + Aig_ManCleanup( pMiter ); + Aig_ManStop( pAig1z ); + Aig_ManStop( pAig2z ); + + // cleanup + Vec_PtrFree( vSimInfo ); + Vec_StrFree( vSeq1 ); + Vec_StrFree( vSeq2 ); + Aig_ManCleanMarkA( pAig1 ); + Aig_ManCleanMarkA( pAig2 ); + + if ( fVerbose ) + { + printf( "Miter of the synchronized designs is constructed. " ); + ABC_PRT( "Time", Abc_Clock() - clk ); + } + return pMiter; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigTempor.c b/yosys/abc/src/aig/saig/saigTempor.c new file mode 100644 index 00000000000..3ba22bec72e --- /dev/null +++ b/yosys/abc/src/aig/saig/saigTempor.c @@ -0,0 +1,256 @@ +/**CFile**************************************************************** + + FileName [saigTempor.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Temporal decomposition.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigTempor.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" +#include "sat/bmc/bmc.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates initialized timeframes for temporal decomposition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManTemporFrames( Aig_Man_t * pAig, int nFrames ) +{ + Aig_Man_t * pFrames; + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int i, f; + // start the frames package + Aig_ManCleanData( pAig ); + pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFrames ); + pFrames->pName = Abc_UtilStrsav( pAig->pName ); + // initiliaze the flops + Saig_ManForEachLo( pAig, pObj, i ) + pObj->pData = Aig_ManConst0(pFrames); + // for each timeframe + for ( f = 0; f < nFrames; f++ ) + { + Aig_ManConst1(pAig)->pData = Aig_ManConst1(pFrames); + Saig_ManForEachPi( pAig, pObj, i ) + pObj->pData = Aig_ObjCreateCi(pFrames); + Aig_ManForEachNode( pAig, pObj, i ) + pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + Aig_ManForEachCo( pAig, pObj, i ) + pObj->pData = Aig_ObjChild0Copy(pObj); + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + pObjLo->pData = pObjLi->pData; + } + // create POs for the flop inputs + Saig_ManForEachLi( pAig, pObj, i ) + Aig_ObjCreateCo( pFrames, (Aig_Obj_t *)pObj->pData ); + Aig_ManCleanup( pFrames ); + return pFrames; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManTemporDecompose( Aig_Man_t * pAig, int nFrames ) +{ + Aig_Man_t * pAigNew, * pFrames; + Aig_Obj_t * pObj, * pReset; + int i; + if ( pAig->nConstrs > 0 ) + { + printf( "The AIG manager should have no constraints.\n" ); + return NULL; + } + // create initialized timeframes + pFrames = Saig_ManTemporFrames( pAig, nFrames ); + assert( Aig_ManCoNum(pFrames) == Aig_ManRegNum(pAig) ); + + // start the new manager + Aig_ManCleanData( pAig ); + pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); + pAigNew->pName = Abc_UtilStrsav( pAig->pName ); + // map the constant node and primary inputs + Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); + Saig_ManForEachPi( pAig, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pAigNew ); + + // insert initialization logic + Aig_ManConst1(pFrames)->pData = Aig_ManConst1( pAigNew ); + Aig_ManForEachCi( pFrames, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pAigNew ); + Aig_ManForEachNode( pFrames, pObj, i ) + pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + Aig_ManForEachCo( pFrames, pObj, i ) + pObj->pData = Aig_ObjChild0Copy(pObj); + + // create reset latch (the first one among the latches) + pReset = Aig_ObjCreateCi( pAigNew ); + + // create flop output values + Saig_ManForEachLo( pAig, pObj, i ) + pObj->pData = Aig_Mux( pAigNew, pReset, Aig_ObjCreateCi(pAigNew), (Aig_Obj_t *)Aig_ManCo(pFrames, i)->pData ); + Aig_ManStop( pFrames ); + + // add internal nodes of this frame + Aig_ManForEachNode( pAig, pObj, i ) + pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // create primary outputs + Saig_ManForEachPo( pAig, pObj, i ) + Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); + + // create reset latch (the first one among the latches) + Aig_ObjCreateCo( pAigNew, Aig_ManConst1(pAigNew) ); + // create latch inputs + Saig_ManForEachLi( pAig, pObj, i ) + Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); + + // finalize + Aig_ManCleanup( pAigNew ); + Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig)+1 ); // + reset latch (011111...) + return pAigNew; +} + +/**Function************************************************************* + + Synopsis [Find index of first non-zero entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Vec_IntLastNonZeroBeforeLimit( Vec_Int_t * vTemp, int Limit ) +{ + int Entry, i; + if ( vTemp == NULL ) + return -1; + Vec_IntForEachEntryReverse( vTemp, Entry, i ) + { + if ( i >= Limit ) + continue; + if ( Entry ) + return i; + } + return -1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManTempor( Aig_Man_t * pAig, int nFrames, int TimeOut, int nConfLimit, int fUseBmc, int fUseTransSigs, int fVerbose, int fVeryVerbose ) +{ + extern int Saig_ManPhasePrefixLength( Aig_Man_t * p, int fVerbose, int fVeryVerbose, Vec_Int_t ** pvTrans ); + + Vec_Int_t * vTransSigs = NULL; + int RetValue, nFramesFinished = -1; + assert( nFrames >= 0 ); + if ( nFrames == 0 ) + { + nFrames = Saig_ManPhasePrefixLength( pAig, fVerbose, fVeryVerbose, &vTransSigs ); + if ( nFrames == 0 ) + { + Vec_IntFreeP( &vTransSigs ); + printf( "The leading sequence has length 0. Temporal decomposition is not performed.\n" ); + return NULL; + } + if ( nFrames == 1 ) + { + Vec_IntFreeP( &vTransSigs ); + printf( "The leading sequence has length 1. Temporal decomposition is not performed.\n" ); + return NULL; + } + if ( fUseTransSigs ) + { + int Entry, i, iLast = -1; + Vec_IntForEachEntry( vTransSigs, Entry, i ) + iLast = Entry ? i :iLast; + if ( iLast > 0 && iLast < nFrames ) + { + Abc_Print( 1, "Reducing frame count from %d to %d to fit the last transient.\n", nFrames, iLast ); + nFrames = iLast; + } + } + Abc_Print( 1, "Using computed frame number (%d).\n", nFrames ); + } + else + Abc_Print( 1, "Using user-given frame number (%d).\n", nFrames ); + // run BMC2 + if ( fUseBmc ) + { + RetValue = Saig_BmcPerform( pAig, 0, nFrames, 2000, TimeOut, nConfLimit, 0, fVerbose, 0, &nFramesFinished, 0, 0 ); + if ( RetValue == 0 ) + { + Vec_IntFreeP( &vTransSigs ); + printf( "A cex found in the first %d frames.\n", nFrames ); + return NULL; + } + if ( nFramesFinished + 1 < nFrames ) + { + int iLastBefore = Vec_IntLastNonZeroBeforeLimit( vTransSigs, nFramesFinished ); + if ( iLastBefore < 1 || !fUseTransSigs ) + { + Vec_IntFreeP( &vTransSigs ); + printf( "BMC for %d frames could not be completed. A cex may exist!\n", nFrames ); + return NULL; + } + assert( iLastBefore < nFramesFinished ); + printf( "BMC succeeded to frame %d. Adjusting frame count to be (%d) based on the last transient signal.\n", nFramesFinished, iLastBefore ); + nFrames = iLastBefore; + } + } + Vec_IntFreeP( &vTransSigs ); + return Saig_ManTemporDecompose( pAig, nFrames ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigTrans.c b/yosys/abc/src/aig/saig/saigTrans.c new file mode 100644 index 00000000000..6d6a2f22667 --- /dev/null +++ b/yosys/abc/src/aig/saig/saigTrans.c @@ -0,0 +1,428 @@ +/**CFile**************************************************************** + + FileName [saigTrans.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Dynamic simplification of the transition relation.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigTrans.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" +#include "proof/fra/fra.h" + +ABC_NAMESPACE_IMPL_START + + +/* + A similar approach is presented in the his paper: + A. Kuehlmann. Dynamic transition relation simplification for + bounded property checking. ICCAD'04, pp. 50-57. +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Maps a node/frame into a node of a different manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Saig_ManStartMap1( Aig_Man_t * p, int nFrames ) +{ + Vec_Int_t * vMap; + int i; + assert( p->pData == NULL ); + vMap = Vec_IntAlloc( Aig_ManObjNumMax(p) * nFrames ); + for ( i = 0; i < vMap->nCap; i++ ) + vMap->pArray[i] = -1; + vMap->nSize = vMap->nCap; + p->pData = vMap; +} +static inline void Saig_ManStopMap1( Aig_Man_t * p ) +{ + assert( p->pData != NULL ); + Vec_IntFree( (Vec_Int_t *)p->pData ); + p->pData = NULL; +} +static inline int Saig_ManHasMap1( Aig_Man_t * p ) +{ + return (int)(p->pData != NULL); +} +static inline void Saig_ManSetMap1( Aig_Man_t * p, Aig_Obj_t * pOld, int f1, Aig_Obj_t * pNew ) +{ + Vec_Int_t * vMap = (Vec_Int_t *)p->pData; + int nOffset = f1 * Aig_ManObjNumMax(p) + pOld->Id; + assert( !Aig_IsComplement(pOld) ); + assert( !Aig_IsComplement(pNew) ); + Vec_IntWriteEntry( vMap, nOffset, pNew->Id ); +} +static inline int Saig_ManGetMap1( Aig_Man_t * p, Aig_Obj_t * pOld, int f1 ) +{ + Vec_Int_t * vMap = (Vec_Int_t *)p->pData; + int nOffset = f1 * Aig_ManObjNumMax(p) + pOld->Id; + return Vec_IntEntry( vMap, nOffset ); +} + +/**Function************************************************************* + + Synopsis [Maps a node/frame into a node/frame of a different manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Saig_ManStartMap2( Aig_Man_t * p, int nFrames ) +{ + Vec_Int_t * vMap; + int i; + assert( p->pData2 == NULL ); + vMap = Vec_IntAlloc( Aig_ManObjNumMax(p) * nFrames * 2 ); + for ( i = 0; i < vMap->nCap; i++ ) + vMap->pArray[i] = -1; + vMap->nSize = vMap->nCap; + p->pData2 = vMap; +} +static inline void Saig_ManStopMap2( Aig_Man_t * p ) +{ + assert( p->pData2 != NULL ); + Vec_IntFree( (Vec_Int_t *)p->pData2 ); + p->pData2 = NULL; +} +static inline int Saig_ManHasMap2( Aig_Man_t * p ) +{ + return (int)(p->pData2 != NULL); +} +static inline void Saig_ManSetMap2( Aig_Man_t * p, Aig_Obj_t * pOld, int f1, Aig_Obj_t * pNew, int f2 ) +{ + Vec_Int_t * vMap = (Vec_Int_t *)p->pData2; + int nOffset = f1 * Aig_ManObjNumMax(p) + pOld->Id; + assert( !Aig_IsComplement(pOld) ); + assert( !Aig_IsComplement(pNew) ); + Vec_IntWriteEntry( vMap, 2*nOffset + 0, pNew->Id ); + Vec_IntWriteEntry( vMap, 2*nOffset + 1, f2 ); +} +static inline int Saig_ManGetMap2( Aig_Man_t * p, Aig_Obj_t * pOld, int f1, int * pf2 ) +{ + Vec_Int_t * vMap = (Vec_Int_t *)p->pData2; + int nOffset = f1 * Aig_ManObjNumMax(p) + pOld->Id; + *pf2 = Vec_IntEntry( vMap, 2*nOffset + 1 ); + return Vec_IntEntry( vMap, 2*nOffset ); +} + +/**Function************************************************************* + + Synopsis [Create mapping for the first nFrames timeframes of pAig.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManCreateMapping( Aig_Man_t * pAig, Aig_Man_t * pFrames, int nFrames ) +{ + Aig_Obj_t * pObj, * pObjFrame, * pObjRepr; + int i, f, iNum, iFrame; + assert( pFrames->pReprs != NULL ); // mapping from nodes into their representatives + // start step mapping for both orignal manager and fraig + Saig_ManStartMap2( pAig, nFrames ); + Saig_ManStartMap2( pFrames, 1 ); + // for each object in each frame + for ( f = 0; f < nFrames; f++ ) + Aig_ManForEachObj( pAig, pObj, i ) + { + // get the frame object + iNum = Saig_ManGetMap1( pAig, pObj, f ); + pObjFrame = Aig_ManObj( pFrames, iNum ); + // if the node has no prototype, map it into itself + if ( pObjFrame == NULL ) + { + Saig_ManSetMap2( pAig, pObj, f, pObj, f ); + continue; + } + // get the representative object + pObjRepr = Aig_ObjRepr( pFrames, pObjFrame ); + if ( pObjRepr == NULL ) + pObjRepr = pObjFrame; + // check if this is the first time this object is reached + if ( Saig_ManGetMap2( pFrames, pObjRepr, 0, &iFrame ) == -1 ) + Saig_ManSetMap2( pFrames, pObjRepr, 0, pObj, f ); + // set the map for the main object + iNum = Saig_ManGetMap2( pFrames, pObjRepr, 0, &iFrame ); + Saig_ManSetMap2( pAig, pObj, f, Aig_ManObj(pAig, iNum), iFrame ); + } + Saig_ManStopMap2( pFrames ); + assert( Saig_ManHasMap2(pAig) ); +} + +/**Function************************************************************* + + Synopsis [Unroll without initialization.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManFramesNonInitial( Aig_Man_t * pAig, int nFrames ) +{ + Aig_Man_t * pFrames; + Aig_Obj_t * pObj, * pObjLi, * pObjLo; + int i, f; + assert( Saig_ManRegNum(pAig) > 0 ); + // start node map + Saig_ManStartMap1( pAig, nFrames ); + // start the new manager + pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFrames ); + // map the constant node + Aig_ManConst1(pAig)->pData = Aig_ManConst1( pFrames ); + // create variables for register outputs + Saig_ManForEachLo( pAig, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pFrames ); + // add timeframes + for ( f = 0; f < nFrames; f++ ) + { + // create PI nodes for this frame + Saig_ManForEachPi( pAig, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pFrames ); + // add internal nodes of this frame + Aig_ManForEachNode( pAig, pObj, i ) + pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + // create POs for this frame + Saig_ManForEachPo( pAig, pObj, i ) + pObj->pData = Aig_ObjCreateCo( pFrames, Aig_ObjChild0Copy(pObj) ); + // save register inputs + Saig_ManForEachLi( pAig, pObj, i ) + pObj->pData = Aig_ObjChild0Copy(pObj); + // save the mapping + Aig_ManForEachObj( pAig, pObj, i ) + { + assert( pObj->pData != NULL ); + Saig_ManSetMap1( pAig, pObj, f, Aig_Regular((Aig_Obj_t *)pObj->pData) ); + } + // quit if the last frame + if ( f == nFrames - 1 ) + break; + // transfer to register outputs + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + pObjLo->pData = pObjLi->pData; + } + // remember register outputs + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + Aig_ObjCreateCo( pFrames, (Aig_Obj_t *)pObjLi->pData ); + Aig_ManCleanup( pFrames ); + return pFrames; +} + +/**Function************************************************************* + + Synopsis [Unroll with initialization and mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManFramesInitialMapped( Aig_Man_t * pAig, int nFrames, int nFramesMax, int fInit ) +{ + Aig_Man_t * pFrames; + Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pRepr; + int i, f, iNum1, iNum2, iFrame2; + assert( nFrames <= nFramesMax ); + assert( Saig_ManRegNum(pAig) > 0 ); + // start node map + Saig_ManStartMap1( pAig, nFramesMax ); + // start the new manager + pFrames = Aig_ManStart( Aig_ManNodeNum(pAig) * nFramesMax ); + // create variables for register outputs + if ( fInit ) + { + Saig_ManForEachLo( pAig, pObj, i ) + { + pObj->pData = Aig_ManConst0( pFrames ); + Saig_ManSetMap1( pAig, pObj, 0, Aig_Regular((Aig_Obj_t *)pObj->pData) ); + } + } + else + { + // create PIs first + for ( f = 0; f < nFramesMax; f++ ) + Saig_ManForEachPi( pAig, pObj, i ) + Aig_ObjCreateCi( pFrames ); + // create registers second + Saig_ManForEachLo( pAig, pObj, i ) + { + pObj->pData = Aig_ObjCreateCi( pFrames ); + Saig_ManSetMap1( pAig, pObj, 0, Aig_Regular((Aig_Obj_t *)pObj->pData) ); + } + } + // add timeframes + for ( f = 0; f < nFramesMax; f++ ) + { + // map the constant node + pObj = Aig_ManConst1(pAig); + pObj->pData = Aig_ManConst1( pFrames ); + Saig_ManSetMap1( pAig, pObj, f, Aig_Regular((Aig_Obj_t *)pObj->pData) ); + // create PI nodes for this frame + Saig_ManForEachPi( pAig, pObj, i ) + { + if ( fInit ) + pObj->pData = Aig_ObjCreateCi( pFrames ); + else + pObj->pData = Aig_ManCi( pFrames, f * Saig_ManPiNum(pAig) + i ); + Saig_ManSetMap1( pAig, pObj, f, Aig_Regular((Aig_Obj_t *)pObj->pData) ); + } + // add internal nodes of this frame + Aig_ManForEachNode( pAig, pObj, i ) + { + pObj->pData = Aig_And( pFrames, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + Saig_ManSetMap1( pAig, pObj, f, Aig_Regular((Aig_Obj_t *)pObj->pData) ); + if ( !Saig_ManHasMap2(pAig) ) + continue; + if ( f < nFrames ) + { + // get the mapping for this node + iNum2 = Saig_ManGetMap2( pAig, pObj, f, &iFrame2 ); + } + else + { + // get the mapping for this node + iNum2 = Saig_ManGetMap2( pAig, pObj, nFrames-1, &iFrame2 ); + iFrame2 += f - (nFrames-1); + } + assert( iNum2 != -1 ); + assert( f >= iFrame2 ); + // get the corresponding frames node + iNum1 = Saig_ManGetMap1( pAig, Aig_ManObj(pAig, iNum2), iFrame2 ); + pRepr = Aig_ManObj( pFrames, iNum1 ); + // compare the phases of these nodes + pObj->pData = Aig_NotCond( pRepr, pRepr->fPhase ^ Aig_ObjPhaseReal((Aig_Obj_t *)pObj->pData) ); + } + // create POs for this frame + Saig_ManForEachPo( pAig, pObj, i ) + { + pObj->pData = Aig_ObjCreateCo( pFrames, Aig_ObjChild0Copy(pObj) ); + Saig_ManSetMap1( pAig, pObj, f, Aig_Regular((Aig_Obj_t *)pObj->pData) ); + } + // save register inputs + Saig_ManForEachLi( pAig, pObj, i ) + { + pObj->pData = Aig_ObjChild0Copy(pObj); + Saig_ManSetMap1( pAig, pObj, f, Aig_Regular((Aig_Obj_t *)pObj->pData) ); + } + // quit if the last frame + if ( f == nFramesMax - 1 ) + break; + // transfer to register outputs + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + { + pObjLo->pData = pObjLi->pData; + if ( !fInit ) + Saig_ManSetMap1( pAig, pObjLo, f+1, Aig_Regular((Aig_Obj_t *)pObjLo->pData) ); + } + } + if ( !fInit ) + { + // create registers + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) + Aig_ObjCreateCo( pFrames, (Aig_Obj_t *)pObjLi->pData ); + // set register number + Aig_ManSetRegNum( pFrames, pAig->nRegs ); + } + Aig_ManCleanup( pFrames ); + Saig_ManStopMap1( pAig ); + return pFrames; +} + +/**Function************************************************************* + + Synopsis [Implements dynamic simplification.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManTimeframeSimplify( Aig_Man_t * pAig, int nFrames, int nFramesMax, int fInit, int fVerbose ) +{ +// extern Aig_Man_t * Fra_FraigEquivence( Aig_Man_t * pManAig, int nConfMax, int fProve ); + Aig_Man_t * pFrames, * pFraig, * pRes1, * pRes2; + abctime clk; + // create uninitialized timeframes with map1 + pFrames = Saig_ManFramesNonInitial( pAig, nFrames ); + // perform fraiging for the unrolled timeframes +clk = Abc_Clock(); + pFraig = Fra_FraigEquivence( pFrames, 1000, 0 ); + // report the results + if ( fVerbose ) + { + Aig_ManPrintStats( pFrames ); + Aig_ManPrintStats( pFraig ); +ABC_PRT( "Fraiging", Abc_Clock() - clk ); + } + Aig_ManStop( pFraig ); + assert( pFrames->pReprs != NULL ); + // create AIG with map2 + Saig_ManCreateMapping( pAig, pFrames, nFrames ); + Aig_ManStop( pFrames ); + Saig_ManStopMap1( pAig ); + // create reduced initialized timeframes +clk = Abc_Clock(); + pRes2 = Saig_ManFramesInitialMapped( pAig, nFrames, nFramesMax, fInit ); +ABC_PRT( "Mapped", Abc_Clock() - clk ); + // free mapping + Saig_ManStopMap2( pAig ); +clk = Abc_Clock(); + pRes1 = Saig_ManFramesInitialMapped( pAig, nFrames, nFramesMax, fInit ); +ABC_PRT( "Normal", Abc_Clock() - clk ); + // report the results + if ( fVerbose ) + { + Aig_ManPrintStats( pRes1 ); + Aig_ManPrintStats( pRes2 ); + } + Aig_ManStop( pRes1 ); + assert( !Saig_ManHasMap1(pAig) ); + assert( !Saig_ManHasMap2(pAig) ); + return pRes2; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saigUnfold2.c b/yosys/abc/src/aig/saig/saigUnfold2.c new file mode 100644 index 00000000000..4eafa9b6a29 --- /dev/null +++ b/yosys/abc/src/aig/saig/saigUnfold2.c @@ -0,0 +1,497 @@ + +int Saig_ManFilterUsingIndOne2( Aig_Man_t * p, Aig_Man_t * pFrame, sat_solver * pSat, Cnf_Dat_t * pCnf, int nConfs, int nProps, int Counter + , int type_ /* jlong -- */ + ) +{ + Aig_Obj_t * pObj; + int Lit, status; + pObj = Aig_ManCo( pFrame, Counter*3+type_ ); /* which co */ + Lit = toLitCond( pCnf->pVarNums[Aig_ObjId(pObj)], 0 ); + status = sat_solver_solve( pSat, &Lit, &Lit + 1, (ABC_INT64_T)nConfs, 0, 0, 0 ); + if ( status == l_False ) /* unsat */ + return status; + if ( status == l_Undef ) + { + printf( "Solver returned undecided.\n" ); + return status; + } + assert( status == l_True ); + return status; +} + +Aig_Man_t * Saig_ManCreateIndMiter2( Aig_Man_t * pAig, Vec_Vec_t * vCands ) +{ + int nFrames = 3; + Vec_Ptr_t * vNodes; + Aig_Man_t * pFrames; + Aig_Obj_t * pObj, * pObjLi, * pObjLo, * pObjNew; + Aig_Obj_t ** pObjMap; + int i, f, k; + + // create mapping for the frames nodes + pObjMap = ABC_CALLOC( Aig_Obj_t *, nFrames * Aig_ManObjNumMax(pAig) ); + + // start the fraig package + pFrames = Aig_ManStart( Aig_ManObjNumMax(pAig) * nFrames ); + pFrames->pName = Abc_UtilStrsav( pAig->pName ); + pFrames->pSpec = Abc_UtilStrsav( pAig->pSpec ); + // map constant nodes + for ( f = 0; f < nFrames; f++ ) + Aig_ObjSetFrames( pObjMap, nFrames, Aig_ManConst1(pAig), f, Aig_ManConst1(pFrames) ); + // create PI nodes for the frames + for ( f = 0; f < nFrames; f++ ) + Aig_ManForEachPiSeq( pAig, pObj, i ) + Aig_ObjSetFrames( pObjMap, nFrames, pObj, f, Aig_ObjCreateCi(pFrames) ); + // set initial state for the latches + Aig_ManForEachLoSeq( pAig, pObj, i ) + Aig_ObjSetFrames( pObjMap, nFrames, pObj, 0, Aig_ObjCreateCi(pFrames) ); + + // add timeframes + for ( f = 0; f < nFrames; f++ ) + { + // add internal nodes of this frame + Aig_ManForEachNode( pAig, pObj, i ) + { + pObjNew = Aig_And( pFrames, Aig_ObjChild0Frames(pObjMap,nFrames,pObj,f), Aig_ObjChild1Frames(pObjMap,nFrames,pObj,f) ); + Aig_ObjSetFrames( pObjMap, nFrames, pObj, f, pObjNew ); + } + // set the latch inputs and copy them into the latch outputs of the next frame + Aig_ManForEachLiLoSeq( pAig, pObjLi, pObjLo, i ) + { + pObjNew = Aig_ObjChild0Frames(pObjMap,nFrames,pObjLi,f); + if ( f < nFrames - 1 ) + Aig_ObjSetFrames( pObjMap, nFrames, pObjLo, f+1, pObjNew ); + } + } + + // go through the candidates + Vec_VecForEachLevel( vCands, vNodes, i ) + { + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, k ) + { + Aig_Obj_t * pObjR = Aig_Regular(pObj); + Aig_Obj_t * pNode0 = pObjMap[nFrames*Aig_ObjId(pObjR)+0]; + Aig_Obj_t * pNode1 = pObjMap[nFrames*Aig_ObjId(pObjR)+1]; + { + Aig_Obj_t * pFan0 = Aig_NotCond( pNode0, Aig_IsComplement(pObj) ); + Aig_Obj_t * pFan1 = Aig_NotCond( pNode1, !Aig_IsComplement(pObj) ); + Aig_Obj_t * pMiter = Aig_And( pFrames, pFan0, pFan1 ); + Aig_ObjCreateCo( pFrames, pMiter ); + + /* need to check p & Xp is satisfiable */ + /* jlong -- begin */ + { + Aig_Obj_t * pMiter2 = Aig_And( pFrames, pFan0, Aig_Not(pFan1)); + Aig_ObjCreateCo( pFrames, pMiter2 ); + } + /* jlong -- end */ + } + + { /* jlong -- begin */ + Aig_Obj_t * pNode2 = pObjMap[nFrames*Aig_ObjId(pObjR)+2]; + Aig_Obj_t * pFan0 = Aig_NotCond( pNode0, Aig_IsComplement(pObj) ); + Aig_Obj_t * pFan1 = Aig_NotCond( pNode1, Aig_IsComplement(pObj) ); + Aig_Obj_t * pFan2 = Aig_NotCond( pNode2, !Aig_IsComplement(pObj) ); + Aig_Obj_t * pMiter = Aig_And( pFrames, Aig_And(pFrames, pFan0, pFan1 ), pFan2); + Aig_ObjCreateCo( pFrames, pMiter ); /* jlong -- end */ + } + + } + } + Aig_ManCleanup( pFrames ); + ABC_FREE( pObjMap ); + +//Aig_ManShow( pAig, 0, NULL ); +//Aig_ManShow( pFrames, 0, NULL ); + return pFrames; +} + +/**Function************************************************************* + + Synopsis [Detects constraints functionally.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManFilterUsingInd2( Aig_Man_t * p, Vec_Vec_t * vCands, int nConfs, int nProps, int fVerbose ) +{ + Vec_Ptr_t * vNodes; + Aig_Man_t * pFrames; + sat_solver * pSat; + Cnf_Dat_t * pCnf; + Aig_Obj_t * pObj; + int i, k, k2, Counter; + /* + Vec_VecForEachLevel( vCands, vNodes, i ) + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, k ) + printf( "%d ", Aig_ObjId(Aig_Regular(pObj)) ); + printf( "\n" ); + */ + // create timeframes + // pFrames = Saig_ManUnrollInd( p ); + pFrames = Saig_ManCreateIndMiter2( p, vCands ); + assert( Aig_ManCoNum(pFrames) == Vec_VecSizeSize(vCands)*3 ); + // start the SAT solver + pCnf = Cnf_DeriveSimple( pFrames, Aig_ManCoNum(pFrames) ); + pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + // check candidates + if ( fVerbose ) + printf( "Filtered cands: \n" ); + Counter = 0; + Vec_VecForEachLevel( vCands, vNodes, i ) + { + assert(i==0); /* only one item */ + k2 = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, k ) + { + if ( Saig_ManFilterUsingIndOne2( p, pFrames, pSat, pCnf, nConfs, nProps, Counter++ , 0) == l_False) + // if ( Saig_ManFilterUsingIndOne_old( p, pSat, pCnf, nConfs, pObj ) ) + { + Vec_PtrWriteEntry( vNodes, k2++, pObj ); + if ( fVerbose ) + printf( "%d:%s%d \n", i, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); + printf( " type I : %d:%s%d \n", i, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); + Vec_PtrPush(p->unfold2_type_I, pObj); + } + /* jlong -- begin */ + else if ( Saig_ManFilterUsingIndOne2( p, pFrames, pSat, pCnf, nConfs, nProps, Counter-1 , 1) == l_True ) /* can be self-conflicting */ + { + if ( Saig_ManFilterUsingIndOne2( p, pFrames, pSat, pCnf, nConfs, nProps, Counter-1 , 2) == l_False ){ + //Vec_PtrWriteEntry( vNodes, k2++, pObj ); + if ( fVerbose ) + printf( "%d:%s%d \n", i, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); + printf( " type II: %d:%s%d \n", i, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); + Vec_PtrWriteEntry( vNodes, k2++, pObj ); /* add type II constraints */ + Vec_PtrPush(p->unfold2_type_II, pObj); + } + } + /* jlong -- end */ + } + Vec_PtrShrink( vNodes, k2 ); + } + + // clean up + Cnf_DataFree( pCnf ); + sat_solver_delete( pSat ); + if ( fVerbose ) + Aig_ManPrintStats( pFrames ); + Aig_ManStop( pFrames ); +} + + +/**Function************************************************************* + + Synopsis [Returns the number of variables implied by the output.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Vec_t * Ssw_ManFindDirectImplications2( Aig_Man_t * p, int nFrames, int nConfs, int nProps, int fVerbose ) +{ + Vec_Vec_t * vCands = NULL; + Vec_Ptr_t * vNodes; + Cnf_Dat_t * pCnf; + sat_solver * pSat; + Aig_Man_t * pFrames; + Aig_Obj_t * pObj, * pRepr, * pReprR; + int i, f, k, value; + assert(nFrames == 1); + vCands = Vec_VecAlloc( nFrames ); + assert(nFrames == 1); + // perform unrolling + pFrames = Saig_ManUnrollCOI( p, nFrames ); + assert( Aig_ManCoNum(pFrames) == 1 ); + // start the SAT solver + pCnf = Cnf_DeriveSimple( pFrames, 0 ); + pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 ); + if ( pSat != NULL ) + { + Aig_ManIncrementTravId( p ); + for ( f = 0; f < nFrames; f++ ) + { + Aig_ManForEachObj( p, pObj, i ) + { + if ( !Aig_ObjIsCand(pObj) ) + continue; + //--jlong : also use internal nodes as well + /* if ( !Aig_ObjIsCi(pObj) ) */ + /* continue; */ + if ( Aig_ObjIsTravIdCurrent(p, pObj) ) + continue; + // get the node from timeframes + pRepr = p->pObjCopies[nFrames*i + nFrames-1-f]; + pReprR = Aig_Regular(pRepr); + if ( pCnf->pVarNums[Aig_ObjId(pReprR)] < 0 ) + continue; + // value = pSat->assigns[ pCnf->pVarNums[Aig_ObjId(pReprR)] ]; + value = sat_solver_get_var_value( pSat, pCnf->pVarNums[Aig_ObjId(pReprR)] ); + if ( value == l_Undef ) + continue; + // label this node as taken + Aig_ObjSetTravIdCurrent(p, pObj); + if ( Saig_ObjIsLo(p, pObj) ) + Aig_ObjSetTravIdCurrent( p, Aig_ObjFanin0(Saig_ObjLoToLi(p, pObj)) ); + // remember the node + Vec_VecPush( vCands, f, Aig_NotCond( pObj, (value == l_True) ^ Aig_IsComplement(pRepr) ) ); + // printf( "%s%d ", (value == l_False)? "":"!", i ); + } + } + // printf( "\n" ); + sat_solver_delete( pSat ); + } + Aig_ManStop( pFrames ); + Cnf_DataFree( pCnf ); + + if ( fVerbose ) + { + printf( "Found %3d candidates.\n", Vec_VecSizeSize(vCands) ); + Vec_VecForEachLevel( vCands, vNodes, k ) + { + printf( "Level %d. Cands =%d ", k, Vec_PtrSize(vNodes) ); + // Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + // printf( "%d:%s%d ", k, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); + printf( "\n" ); + } + } + + ABC_FREE( p->pObjCopies ); + /* -- jlong -- this does the SAT proof of the constraints */ + Saig_ManFilterUsingInd2( p, vCands, nConfs, nProps, fVerbose ); + if ( Vec_VecSizeSize(vCands) ) + printf( "Found %3d constraints after filtering.\n", Vec_VecSizeSize(vCands) ); + if ( fVerbose ) + { + Vec_VecForEachLevel( vCands, vNodes, k ) + { + printf( "Level %d. Constr =%d ", k, Vec_PtrSize(vNodes) ); + // Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + // printf( "%d:%s%d ", k, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); + printf( "\n" ); + } + } + + return vCands; +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG while unfolding constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManDupUnfoldConstrsFunc2( Aig_Man_t * pAig, int nFrames, int nConfs, int nProps, int fOldAlgo, int fVerbose , int * typeII_cnt){ + Aig_Man_t * pNew; + Vec_Vec_t * vCands; + Vec_Ptr_t * vNewFlops; + Aig_Obj_t * pObj; + int i, k, nNewFlops; + const int fCompl = 0 ; + if ( fOldAlgo ) + vCands = Saig_ManDetectConstrFunc( pAig, nFrames, nConfs, nProps, fVerbose ); + else + vCands = Ssw_ManFindDirectImplications2( pAig, nFrames, nConfs, nProps, fVerbose ); + if ( vCands == NULL || Vec_VecSizeSize(vCands) == 0 ) + { + Vec_VecFreeP( &vCands ); + return Aig_ManDupDfs( pAig ); + } + // create new manager + pNew = Aig_ManDupWithoutPos( pAig ); /* good */ + pNew->nConstrs = pAig->nConstrs + Vec_VecSizeSize(vCands); + pNew->nConstrs = pAig->nConstrs + Vec_PtrSize(pAig->unfold2_type_II) + + Vec_PtrSize(pAig->unfold2_type_I); + // pNew->nConstrsTypeII = Vec_PtrSize(pAig->unfold2_type_II); + *typeII_cnt = Vec_PtrSize(pAig->unfold2_type_II); + + /* new set of registers */ + + // add normal POs + Saig_ManForEachPo( pAig, pObj, i ) + Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + // create constraint outputs + vNewFlops = Vec_PtrAlloc( 100 ); + + + Vec_PtrForEachEntry(Aig_Obj_t * , pAig->unfold2_type_I, pObj, k){ + Aig_Obj_t * x = Aig_ObjRealCopy(pObj); + Aig_ObjCreateCo(pNew, x); + } + + Vec_PtrForEachEntry(Aig_Obj_t * , pAig->unfold2_type_II, pObj, k){ + Aig_Obj_t * type_II_latch + = Aig_ObjCreateCi(pNew); /* will get connected later; */ + Aig_Obj_t * x = Aig_ObjRealCopy(pObj); + + Aig_Obj_t * n = Aig_And(pNew, + Aig_NotCond(type_II_latch, fCompl), + Aig_NotCond(x, fCompl)); + Aig_ObjCreateCo(pNew, n);//Aig_Not(n)); + } + + // add latch outputs + Saig_ManForEachLi( pAig, pObj, i ) + Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + + Vec_PtrForEachEntry(Aig_Obj_t * , pAig->unfold2_type_II, pObj, k){ + Aig_Obj_t * x = Aig_ObjRealCopy(pObj); + Aig_ObjCreateCo(pNew, x); + } + + // add new latch outputs + nNewFlops = Vec_PtrSize(pAig->unfold2_type_II); + //assert( nNewFlops == Vec_PtrSize(vNewFlops) ); + Aig_ManSetRegNum( pNew, Aig_ManRegNum(pAig) + nNewFlops ); + printf("#reg after unfold2: %d\n", Aig_ManRegNum(pAig) + nNewFlops ); + Vec_VecFreeP( &vCands ); + Vec_PtrFree( vNewFlops ); + return pNew; + +} + +/**Function************************************************************* + + Synopsis [Duplicates the AIG while unfolding constraints.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManDupFoldConstrsFunc2( Aig_Man_t * pAig, int fCompl, int fVerbose , + int typeII_cnt) +{ + Aig_Man_t * pAigNew; + Aig_Obj_t * pMiter, * pFlopOut, * pFlopIn, * pObj; + int i, typeII_cc, type_II; + if ( Aig_ManConstrNum(pAig) == 0 ) + return Aig_ManDupDfs( pAig ); + assert( Aig_ManConstrNum(pAig) < Saig_ManPoNum(pAig) ); + // start the new manager + pAigNew = Aig_ManStart( Aig_ManNodeNum(pAig) ); + pAigNew->pName = Abc_UtilStrsav( pAig->pName ); + pAigNew->pSpec = Abc_UtilStrsav( pAig->pSpec ); + // map the constant node + Aig_ManConst1(pAig)->pData = Aig_ManConst1( pAigNew ); + // create variables for PIs + Aig_ManForEachCi( pAig, pObj, i ) + pObj->pData = Aig_ObjCreateCi( pAigNew ); + // add internal nodes of this frame + Aig_ManForEachNode( pAig, pObj, i ) + pObj->pData = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + + // OR the constraint outputs + pMiter = Aig_ManConst0( pAigNew ); + typeII_cc = 0;//typeII_cnt; + typeII_cnt = 0; + type_II = 0; + + Saig_ManForEachPo( pAig, pObj, i ) + { + + if ( i < Saig_ManPoNum(pAig)-Aig_ManConstrNum(pAig) ) + continue; + if (i + typeII_cnt >= Saig_ManPoNum(pAig) ) { + type_II = 1; + } + /* now we got the constraint */ + if (type_II) { + + Aig_Obj_t * type_II_latch + = Aig_ObjCreateCi(pAigNew); /* will get connected later; */ + pMiter = Aig_Or(pAigNew, pMiter, + Aig_And(pAigNew, + Aig_NotCond(type_II_latch, fCompl), + Aig_NotCond( Aig_ObjChild0Copy(pObj), fCompl ) ) + ); + printf( "modeling typeII : %d:%s%d \n", i, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); + } else + pMiter = Aig_Or( pAigNew, pMiter, Aig_NotCond( Aig_ObjChild0Copy(pObj), fCompl ) ); + } + + // create additional flop + if ( Saig_ManRegNum(pAig) > 0 ) + { + pFlopOut = Aig_ObjCreateCi( pAigNew ); + pFlopIn = Aig_Or( pAigNew, pMiter, pFlopOut ); + } + else + pFlopIn = pMiter; + + // create primary output + Saig_ManForEachPo( pAig, pObj, i ) + { + if ( i >= Saig_ManPoNum(pAig)-Aig_ManConstrNum(pAig) ) + continue; + pMiter = Aig_And( pAigNew, Aig_ObjChild0Copy(pObj), Aig_Not(pFlopIn) ); + Aig_ObjCreateCo( pAigNew, pMiter ); + } + + // transfer to register outputs + { + /* the same for type I and type II */ + Aig_Obj_t * pObjLi, *pObjLo; + + Saig_ManForEachLiLo( pAig, pObjLi, pObjLo, i ) { + if( i + typeII_cc < Aig_ManRegNum(pAig)) { + Aig_Obj_t *c = Aig_Mux(pAigNew, Aig_Not(pFlopIn), + Aig_ObjChild0Copy(pObjLi) , + (Aig_Obj_t*)pObjLo->pData); + Aig_ObjCreateCo( pAigNew, c); + } else { + printf ( "skipping: reg%d\n", i); + Aig_ObjCreateCo( pAigNew,Aig_ObjChild0Copy(pObjLi)); + } + } + + } + if(0)Saig_ManForEachLi( pAig, pObj, i ) { + Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj) ); + } + Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAig) ); + + type_II = 0; + Saig_ManForEachPo( pAig, pObj, i ) + { + + if ( i < Saig_ManPoNum(pAig)-Aig_ManConstrNum(pAig) ) + continue; + if (i + typeII_cnt >= Saig_ManPoNum(pAig) ) { + type_II = 1; + } + /* now we got the constraint */ + if (type_II) { + Aig_ObjCreateCo( pAigNew, Aig_ObjChild0Copy(pObj)); + Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAigNew)+1 ); + printf( "Latch for typeII : %d:%s%d \n", i, Aig_IsComplement(pObj)? "!":"", Aig_ObjId(Aig_Regular(pObj)) ); + } + } + + + // create additional flop + + if ( Saig_ManRegNum(pAig) > 0 ) + { + Aig_ObjCreateCo( pAigNew, pFlopIn ); + Aig_ManSetRegNum( pAigNew, Aig_ManRegNum(pAigNew)+1 ); + } + printf("#reg after fold2: %d\n", Aig_ManRegNum(pAigNew)); + // perform cleanup + Aig_ManCleanup( pAigNew ); + Aig_ManSeqCleanup( pAigNew ); + return pAigNew; +} diff --git a/yosys/abc/src/aig/saig/saigWnd.c b/yosys/abc/src/aig/saig/saigWnd.c new file mode 100644 index 00000000000..949a2728ec8 --- /dev/null +++ b/yosys/abc/src/aig/saig/saigWnd.c @@ -0,0 +1,816 @@ +/**CFile**************************************************************** + + FileName [saigWnd.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [Sequential windowing.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saigWnd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the array of PI/internal nodes.] + + Description [Marks all the visited nodes with the current ID. + Does not collect constant node and PO/LI nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManWindowOutline_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist, Vec_Ptr_t * vNodes, int * pDists ) +{ + Aig_Obj_t * pMatch, * pFanout; + int fCollected, iFanout = -1, i; + if ( nDist == 0 ) + return; + if ( pDists[pObj->Id] >= nDist ) + return; + pDists[pObj->Id] = nDist; + fCollected = Aig_ObjIsTravIdCurrent( p, pObj ); + Aig_ObjSetTravIdCurrent( p, pObj ); + if ( Aig_ObjIsConst1(pObj) ) + return; + if ( Saig_ObjIsPo(p, pObj) ) + return; + if ( Saig_ObjIsLi(p, pObj) ) + { + pMatch = Saig_ObjLiToLo( p, pObj ); + if ( !Aig_ObjIsTravIdCurrent( p, pMatch ) ) + Saig_ManWindowOutline_rec( p, pMatch, nDist, vNodes, pDists ); + Saig_ManWindowOutline_rec( p, Aig_ObjFanin0(pObj), nDist-1, vNodes, pDists ); + return; + } + if ( !fCollected ) + Vec_PtrPush( vNodes, pObj ); + if ( Saig_ObjIsPi(p, pObj) ) + return; + if ( Saig_ObjIsLo(p, pObj) ) + { + pMatch = Saig_ObjLoToLi( p, pObj ); + if ( !Aig_ObjIsTravIdCurrent( p, pMatch ) ) + Saig_ManWindowOutline_rec( p, pMatch, nDist, vNodes, pDists ); + Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) + Saig_ManWindowOutline_rec( p, pFanout, nDist-1, vNodes, pDists ); + return; + } + assert( Aig_ObjIsNode(pObj) ); + Saig_ManWindowOutline_rec( p, Aig_ObjFanin0(pObj), nDist-1, vNodes, pDists ); + Saig_ManWindowOutline_rec( p, Aig_ObjFanin1(pObj), nDist-1, vNodes, pDists ); + Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) + Saig_ManWindowOutline_rec( p, pFanout, nDist-1, vNodes, pDists ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of PI/internal nodes.] + + Description [Marks all the visited nodes with the current ID.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Saig_ManWindowOutline( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObjLi, * pObjLo; + int * pDists, i; + pDists = ABC_CALLOC( int, Aig_ManObjNumMax(p) ); + vNodes = Vec_PtrAlloc( 1000 ); + Aig_ManIncrementTravId( p ); + Saig_ManWindowOutline_rec( p, pObj, nDist, vNodes, pDists ); + Vec_PtrSort( vNodes, (int (*)(const void *, const void *))Aig_ObjCompareIdIncrease ); + // make sure LI/LO are labeled/unlabeled mutually + Saig_ManForEachLiLo( p, pObjLi, pObjLo, i ) + assert( Aig_ObjIsTravIdCurrent(p, pObjLi) == + Aig_ObjIsTravIdCurrent(p, pObjLo) ); + ABC_FREE( pDists ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node has unlabeled fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Saig_ObjHasUnlabeledFanout( Aig_Man_t * p, Aig_Obj_t * pObj ) +{ + Aig_Obj_t * pFanout; + int iFanout = -1, i; + Aig_ObjForEachFanout( p, pObj, pFanout, iFanout, i ) + if ( Saig_ObjIsPo(p, pFanout) || !Aig_ObjIsTravIdCurrent(p, pFanout) ) + return pFanout; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Collects primary inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Saig_ManWindowCollectPis( Aig_Man_t * p, Vec_Ptr_t * vNodes ) +{ + Vec_Ptr_t * vNodesPi; + Aig_Obj_t * pObj, * pMatch, * pFanin; + int i; + vNodesPi = Vec_PtrAlloc( 1000 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + if ( Saig_ObjIsPi(p, pObj) ) + { + assert( pObj->pData == NULL ); + Vec_PtrPush( vNodesPi, pObj ); + } + else if ( Saig_ObjIsLo(p, pObj) ) + { + pMatch = Saig_ObjLoToLi( p, pObj ); + pFanin = Aig_ObjFanin0(pMatch); + if ( !Aig_ObjIsTravIdCurrent(p, pFanin) && pFanin->pData == NULL ) + Vec_PtrPush( vNodesPi, pFanin ); + } + else + { + assert( Aig_ObjIsNode(pObj) ); + pFanin = Aig_ObjFanin0(pObj); + if ( !Aig_ObjIsTravIdCurrent(p, pFanin) && pFanin->pData == NULL ) + Vec_PtrPush( vNodesPi, pFanin ); + pFanin = Aig_ObjFanin1(pObj); + if ( !Aig_ObjIsTravIdCurrent(p, pFanin) && pFanin->pData == NULL ) + Vec_PtrPush( vNodesPi, pFanin ); + } + } + return vNodesPi; +} + +/**Function************************************************************* + + Synopsis [Collects primary outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Saig_ManWindowCollectPos( Aig_Man_t * p, Vec_Ptr_t * vNodes, Vec_Ptr_t ** pvPointers ) +{ + Vec_Ptr_t * vNodesPo; + Aig_Obj_t * pObj, * pPointer; + int i; + vNodesPo = Vec_PtrAlloc( 1000 ); + if ( pvPointers ) + *pvPointers = Vec_PtrAlloc( 1000 ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + if ( (pPointer = Saig_ObjHasUnlabeledFanout(p, pObj)) ) + { + Vec_PtrPush( vNodesPo, pObj ); + if ( pvPointers ) + Vec_PtrPush( *pvPointers, pPointer ); + } + } + return vNodesPo; +} + +/**Function************************************************************* + + Synopsis [Extracts the window AIG from the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManWindowExtractNodes( Aig_Man_t * p, Vec_Ptr_t * vNodes ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj, * pMatch; + Vec_Ptr_t * vNodesPi, * vNodesPo; + int i, nRegCount; + Aig_ManCleanData( p ); + // create the new manager + pNew = Aig_ManStart( Vec_PtrSize(vNodes) ); + pNew->pName = Abc_UtilStrsav( "wnd" ); + pNew->pSpec = NULL; + // map constant nodes + pObj = Aig_ManConst1( p ); + pObj->pData = Aig_ManConst1( pNew ); + // create real PIs + vNodesPi = Saig_ManWindowCollectPis( p, vNodes ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodesPi, pObj, i ) + pObj->pData = Aig_ObjCreateCi(pNew); + Vec_PtrFree( vNodesPi ); + // create register outputs + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + if ( Saig_ObjIsLo(p, pObj) ) + pObj->pData = Aig_ObjCreateCi(pNew); + } + // create internal nodes + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + if ( Aig_ObjIsNode(pObj) ) + pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) ); + } + // create POs + vNodesPo = Saig_ManWindowCollectPos( p, vNodes, NULL ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodesPo, pObj, i ) + Aig_ObjCreateCo( pNew, (Aig_Obj_t *)pObj->pData ); + Vec_PtrFree( vNodesPo ); + // create register inputs + nRegCount = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i ) + { + if ( Saig_ObjIsLo(p, pObj) ) + { + pMatch = Saig_ObjLoToLi( p, pObj ); + Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pMatch) ); + nRegCount++; + } + } + Aig_ManSetRegNum( pNew, nRegCount ); + Aig_ManCleanup( pNew ); + return pNew; +} + +static void Saig_ManWindowInsertSmall_rec( Aig_Man_t * pNew, Aig_Obj_t * pObjSmall, + Vec_Ptr_t * vBigNode2SmallPo, Vec_Ptr_t * vSmallPi2BigNode ); + +/**Function************************************************************* + + Synopsis [Adds nodes for the big manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManWindowInsertBig_rec( Aig_Man_t * pNew, Aig_Obj_t * pObjBig, + Vec_Ptr_t * vBigNode2SmallPo, Vec_Ptr_t * vSmallPi2BigNode ) +{ + Aig_Obj_t * pMatch; + if ( pObjBig->pData ) + return; + if ( (pMatch = (Aig_Obj_t *)Vec_PtrEntry( vBigNode2SmallPo, pObjBig->Id )) ) + { + Saig_ManWindowInsertSmall_rec( pNew, Aig_ObjFanin0(pMatch), vBigNode2SmallPo, vSmallPi2BigNode ); + pObjBig->pData = Aig_ObjChild0Copy(pMatch); + return; + } + assert( Aig_ObjIsNode(pObjBig) ); + Saig_ManWindowInsertBig_rec( pNew, Aig_ObjFanin0(pObjBig), vBigNode2SmallPo, vSmallPi2BigNode ); + Saig_ManWindowInsertBig_rec( pNew, Aig_ObjFanin1(pObjBig), vBigNode2SmallPo, vSmallPi2BigNode ); + pObjBig->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObjBig), Aig_ObjChild1Copy(pObjBig) ); +} + +/**Function************************************************************* + + Synopsis [Adds nodes for the small manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManWindowInsertSmall_rec( Aig_Man_t * pNew, Aig_Obj_t * pObjSmall, + Vec_Ptr_t * vBigNode2SmallPo, Vec_Ptr_t * vSmallPi2BigNode ) +{ + Aig_Obj_t * pMatch; + if ( pObjSmall->pData ) + return; + if ( (pMatch = (Aig_Obj_t *)Vec_PtrEntry( vSmallPi2BigNode, pObjSmall->Id )) ) + { + Saig_ManWindowInsertBig_rec( pNew, pMatch, vBigNode2SmallPo, vSmallPi2BigNode ); + pObjSmall->pData = pMatch->pData; + return; + } + assert( Aig_ObjIsNode(pObjSmall) ); + Saig_ManWindowInsertSmall_rec( pNew, Aig_ObjFanin0(pObjSmall), vBigNode2SmallPo, vSmallPi2BigNode ); + Saig_ManWindowInsertSmall_rec( pNew, Aig_ObjFanin1(pObjSmall), vBigNode2SmallPo, vSmallPi2BigNode ); + pObjSmall->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObjSmall), Aig_ObjChild1Copy(pObjSmall) ); +} + +/**Function************************************************************* + + Synopsis [Extracts the network from the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManWindowInsertNodes( Aig_Man_t * p, Vec_Ptr_t * vNodes, Aig_Man_t * pWnd ) +{ + Aig_Man_t * pNew; + Vec_Ptr_t * vBigNode2SmallPo, * vSmallPi2BigNode; + Vec_Ptr_t * vNodesPi, * vNodesPo; + Aig_Obj_t * pObj; + int i; + + // set mapping of small PIs into big nodes + vSmallPi2BigNode = Vec_PtrStart( Aig_ManObjNumMax(pWnd) ); + vNodesPi = Saig_ManWindowCollectPis( p, vNodes ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodesPi, pObj, i ) + Vec_PtrWriteEntry( vSmallPi2BigNode, Aig_ManCi(pWnd, i)->Id, pObj ); + assert( i == Saig_ManPiNum(pWnd) ); + Vec_PtrFree( vNodesPi ); + + // set mapping of big nodes into small POs + vBigNode2SmallPo = Vec_PtrStart( Aig_ManObjNumMax(p) ); + vNodesPo = Saig_ManWindowCollectPos( p, vNodes, NULL ); + Vec_PtrForEachEntry( Aig_Obj_t *, vNodesPo, pObj, i ) + Vec_PtrWriteEntry( vBigNode2SmallPo, pObj->Id, Aig_ManCo(pWnd, i) ); + assert( i == Saig_ManPoNum(pWnd) ); + Vec_PtrFree( vNodesPo ); + + // create the new manager + Aig_ManCleanData( p ); + Aig_ManCleanData( pWnd ); + pNew = Aig_ManStart( Aig_ManObjNumMax(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + // map constant nodes + pObj = Aig_ManConst1( p ); + pObj->pData = Aig_ManConst1( pNew ); + pObj = Aig_ManConst1( pWnd ); + pObj->pData = Aig_ManConst1( pNew ); + + // create real PIs + Aig_ManForEachCi( p, pObj, i ) + if ( Saig_ObjIsPi(p, pObj) || !Aig_ObjIsTravIdCurrent(p, pObj) ) + pObj->pData = Aig_ObjCreateCi(pNew); + // create additional latch outputs + Saig_ManForEachLo( pWnd, pObj, i ) + pObj->pData = Aig_ObjCreateCi(pNew); + + // create internal nodes starting from the big + Aig_ManForEachCo( p, pObj, i ) + if ( Saig_ObjIsPo(p, pObj) || !Aig_ObjIsTravIdCurrent(p, pObj) ) + { + Saig_ManWindowInsertBig_rec( pNew, Aig_ObjFanin0(pObj), vBigNode2SmallPo, vSmallPi2BigNode ); + pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + } + // create internal nodes starting from the small + Saig_ManForEachLi( pWnd, pObj, i ) + { + Saig_ManWindowInsertSmall_rec( pNew, Aig_ObjFanin0(pObj), vBigNode2SmallPo, vSmallPi2BigNode ); + pObj->pData = Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pObj) ); + } + Vec_PtrFree( vBigNode2SmallPo ); + Vec_PtrFree( vSmallPi2BigNode ); + // set the new number of registers + assert( Aig_ManCiNum(pNew) - Aig_ManCiNum(p) == Aig_ManCoNum(pNew) - Aig_ManCoNum(p) ); + Aig_ManSetRegNum( pNew, Aig_ManRegNum(p) + (Aig_ManCiNum(pNew) - Aig_ManCiNum(p)) ); + Aig_ManCleanup( pNew ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Find a good object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Obj_t * Saig_ManFindPivot( Aig_Man_t * p ) +{ + Aig_Obj_t * pObj; + int i, Counter; + if ( Aig_ManRegNum(p) > 0 ) + { + if ( Aig_ManRegNum(p) == 1 ) + return Saig_ManLo( p, 0 ); + Saig_ManForEachLo( p, pObj, i ) + { + if ( i == Aig_ManRegNum(p)/2 ) + return pObj; + } + } + else + { + Counter = 0; + assert( Aig_ManNodeNum(p) > 1 ); + Aig_ManForEachNode( p, pObj, i ) + { + if ( Counter++ == Aig_ManNodeNum(p)/2 ) + return pObj; + } + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Computes sequential window of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManWindowExtract( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist ) +{ + Aig_Man_t * pWnd; + Vec_Ptr_t * vNodes; + Aig_ManFanoutStart( p ); + vNodes = Saig_ManWindowOutline( p, pObj, nDist ); + pWnd = Saig_ManWindowExtractNodes( p, vNodes ); + Vec_PtrFree( vNodes ); + Aig_ManFanoutStop( p ); + return pWnd; +} + +/**Function************************************************************* + + Synopsis [Computes sequential window of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManWindowInsert( Aig_Man_t * p, Aig_Obj_t * pObj, int nDist, Aig_Man_t * pWnd ) +{ + Aig_Man_t * pNew, * pWndTest; + Vec_Ptr_t * vNodes; + Aig_ManFanoutStart( p ); + + vNodes = Saig_ManWindowOutline( p, pObj, nDist ); + pWndTest = Saig_ManWindowExtractNodes( p, vNodes ); + if ( Saig_ManPiNum(pWndTest) != Saig_ManPiNum(pWnd) || + Saig_ManPoNum(pWndTest) != Saig_ManPoNum(pWnd) ) + { + printf( "The window cannot be reinserted because PI/PO counts do not match.\n" ); + Aig_ManStop( pWndTest ); + Vec_PtrFree( vNodes ); + Aig_ManFanoutStop( p ); + return NULL; + } + Aig_ManStop( pWndTest ); + Vec_PtrFree( vNodes ); + + // insert the nodes + Aig_ManCleanData( p ); + vNodes = Saig_ManWindowOutline( p, pObj, nDist ); + pNew = Saig_ManWindowInsertNodes( p, vNodes, pWnd ); + Vec_PtrFree( vNodes ); + Aig_ManFanoutStop( p ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Tests the above computation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManWindowTest( Aig_Man_t * p ) +{ + int nDist = 3; + Aig_Man_t * pWnd, * pNew; + Aig_Obj_t * pPivot; + pPivot = Saig_ManFindPivot( p ); + assert( pPivot != NULL ); + pWnd = Saig_ManWindowExtract( p, pPivot, nDist ); + pNew = Saig_ManWindowInsert( p, pPivot, nDist, pWnd ); + Aig_ManStop( pWnd ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Collects the nodes that are not linked to each other.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Saig_ManCollectedDiffNodes( Aig_Man_t * p0, Aig_Man_t * p1 ) +{ + Vec_Ptr_t * vNodes; + Aig_Obj_t * pObj0, * pObj1; + int i; + // collect nodes that are not linked + Aig_ManIncrementTravId( p0 ); + vNodes = Vec_PtrAlloc( 1000 ); + Aig_ManForEachObj( p0, pObj0, i ) + { + pObj1 = Aig_ObjRepr( p0, pObj0 ); + if ( pObj1 != NULL ) + { + assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) ); + continue; + } + // mark and collect unmatched objects + Aig_ObjSetTravIdCurrent( p0, pObj0 ); + if ( Aig_ObjIsNode(pObj0) || Aig_ObjIsCi(pObj0) ) + Vec_PtrPush( vNodes, pObj0 ); + } + // make sure LI/LO are labeled/unlabeled mutually + Saig_ManForEachLiLo( p0, pObj0, pObj1, i ) + assert( Aig_ObjIsTravIdCurrent(p0, pObj0) == + Aig_ObjIsTravIdCurrent(p0, pObj1) ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Creates PIs of the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManWindowCreatePis( Aig_Man_t * pNew, Aig_Man_t * p0, Aig_Man_t * p1, Vec_Ptr_t * vNodes0 ) +{ + Aig_Obj_t * pObj, * pMatch, * pFanin; + int i, Counter = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes0, pObj, i ) + { + if ( Saig_ObjIsLo(p0, pObj) ) + { + pMatch = Saig_ObjLoToLi( p0, pObj ); + pFanin = Aig_ObjFanin0(pMatch); + if ( !Aig_ObjIsTravIdCurrent(p0, pFanin) && pFanin->pData == NULL ) + { + pFanin->pData = Aig_ObjCreateCi(pNew); + pMatch = Aig_ObjRepr( p0, pFanin ); + assert( pFanin == Aig_ObjRepr( p1, pMatch ) ); + assert( pMatch != NULL ); + pMatch->pData = pFanin->pData; + Counter++; + } + } + else + { + assert( Aig_ObjIsNode(pObj) ); + pFanin = Aig_ObjFanin0(pObj); + if ( !Aig_ObjIsTravIdCurrent(p0, pFanin) && pFanin->pData == NULL ) + { + pFanin->pData = Aig_ObjCreateCi(pNew); + pMatch = Aig_ObjRepr( p0, pFanin ); + assert( pFanin == Aig_ObjRepr( p1, pMatch ) ); + assert( pMatch != NULL ); + pMatch->pData = pFanin->pData; + Counter++; + } + pFanin = Aig_ObjFanin1(pObj); + if ( !Aig_ObjIsTravIdCurrent(p0, pFanin) && pFanin->pData == NULL ) + { + pFanin->pData = Aig_ObjCreateCi(pNew); + pMatch = Aig_ObjRepr( p0, pFanin ); + assert( pFanin == Aig_ObjRepr( p1, pMatch ) ); + assert( pMatch != NULL ); + pMatch->pData = pFanin->pData; + Counter++; + } + } + } +// printf( "Added %d primary inputs.\n", Counter ); +} + +/**Function************************************************************* + + Synopsis [Creates POs of the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Saig_ManWindowCreatePos( Aig_Man_t * pNew, Aig_Man_t * p0, Aig_Man_t * p1 ) +{ + Aig_Obj_t * pObj0, * pObj1, * pMiter; + Aig_Obj_t * pFanin0, * pFanin1; + int i; + Aig_ManForEachObj( p0, pObj0, i ) + { + if ( Aig_ObjIsTravIdCurrent(p0, pObj0) ) + continue; + if ( Aig_ObjIsConst1(pObj0) ) + continue; + if ( Aig_ObjIsCi(pObj0) ) + continue; + pObj1 = Aig_ObjRepr( p0, pObj0 ); + assert( pObj0 == Aig_ObjRepr( p1, pObj1 ) ); + if ( Aig_ObjIsCo(pObj0) ) + { + pFanin0 = Aig_ObjFanin0(pObj0); + pFanin1 = Aig_ObjFanin0(pObj1); + assert( Aig_ObjIsTravIdCurrent(p0, pFanin0) == + Aig_ObjIsTravIdCurrent(p1, pFanin1) ); + if ( Aig_ObjIsTravIdCurrent(p0, pFanin0) ) + { + pMiter = Aig_Exor( pNew, (Aig_Obj_t *)pFanin0->pData, (Aig_Obj_t *)pFanin1->pData ); + Aig_ObjCreateCo( pNew, pMiter ); + } + } + else + { + assert( Aig_ObjIsNode(pObj0) ); + + pFanin0 = Aig_ObjFanin0(pObj0); + pFanin1 = Aig_ObjFanin0(pObj1); + assert( Aig_ObjIsTravIdCurrent(p0, pFanin0) == + Aig_ObjIsTravIdCurrent(p1, pFanin1) ); + if ( Aig_ObjIsTravIdCurrent(p0, pFanin0) ) + { + pMiter = Aig_Exor( pNew, (Aig_Obj_t *)pFanin0->pData, (Aig_Obj_t *)pFanin1->pData ); + Aig_ObjCreateCo( pNew, pMiter ); + } + + pFanin0 = Aig_ObjFanin1(pObj0); + pFanin1 = Aig_ObjFanin1(pObj1); + assert( Aig_ObjIsTravIdCurrent(p0, pFanin0) == + Aig_ObjIsTravIdCurrent(p1, pFanin1) ); + if ( Aig_ObjIsTravIdCurrent(p0, pFanin0) ) + { + pMiter = Aig_Exor( pNew, (Aig_Obj_t *)pFanin0->pData, (Aig_Obj_t *)pFanin1->pData ); + Aig_ObjCreateCo( pNew, pMiter ); + } + } + } +} + + +/**Function************************************************************* + + Synopsis [Extracts the window AIG from the AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Saig_ManWindowExtractMiter( Aig_Man_t * p0, Aig_Man_t * p1 ) +{ + Aig_Man_t * pNew; + Aig_Obj_t * pObj0, * pObj1, * pMatch0, * pMatch1; + Vec_Ptr_t * vNodes0, * vNodes1; + int i, nRegCount; + // add matching of POs and LIs + Saig_ManForEachPo( p0, pObj0, i ) + { + pObj1 = Aig_ManCo( p1, i ); + Aig_ObjSetRepr( p0, pObj0, pObj1 ); + Aig_ObjSetRepr( p1, pObj1, pObj0 ); + } + Saig_ManForEachLi( p0, pObj0, i ) + { + pMatch0 = Saig_ObjLiToLo( p0, pObj0 ); + pMatch1 = Aig_ObjRepr( p0, pMatch0 ); + if ( pMatch1 == NULL ) + continue; + assert( pMatch0 == Aig_ObjRepr( p1, pMatch1 ) ); + pObj1 = Saig_ObjLoToLi( p1, pMatch1 ); + Aig_ObjSetRepr( p0, pObj0, pObj1 ); + Aig_ObjSetRepr( p1, pObj1, pObj0 ); + } + // clean the markings + Aig_ManCleanData( p0 ); + Aig_ManCleanData( p1 ); + // collect nodes that are not linked + vNodes0 = Saig_ManCollectedDiffNodes( p0, p1 ); + vNodes1 = Saig_ManCollectedDiffNodes( p1, p0 ); + // create the new manager + pNew = Aig_ManStart( Vec_PtrSize(vNodes0) + Vec_PtrSize(vNodes1) ); + pNew->pName = Abc_UtilStrsav( "wnd" ); + pNew->pSpec = NULL; + // map constant nodes + pObj0 = Aig_ManConst1( p0 ); + pObj0->pData = Aig_ManConst1( pNew ); + pObj1 = Aig_ManConst1( p1 ); + pObj1->pData = Aig_ManConst1( pNew ); + // create real PIs + Saig_ManWindowCreatePis( pNew, p0, p1, vNodes0 ); + Saig_ManWindowCreatePis( pNew, p1, p0, vNodes1 ); + // create register outputs + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes0, pObj0, i ) + { + if ( Saig_ObjIsLo(p0, pObj0) ) + pObj0->pData = Aig_ObjCreateCi(pNew); + } + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes1, pObj1, i ) + { + if ( Saig_ObjIsLo(p1, pObj1) ) + pObj1->pData = Aig_ObjCreateCi(pNew); + } + // create internal nodes + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes0, pObj0, i ) + { + if ( Aig_ObjIsNode(pObj0) ) + pObj0->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj0), Aig_ObjChild1Copy(pObj0) ); + } + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes1, pObj1, i ) + { + if ( Aig_ObjIsNode(pObj1) ) + pObj1->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj1), Aig_ObjChild1Copy(pObj1) ); + } + // create POs + Saig_ManWindowCreatePos( pNew, p0, p1 ); +// Saig_ManWindowCreatePos( pNew, p1, p0 ); + // create register inputs + nRegCount = 0; + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes0, pObj0, i ) + { + if ( Saig_ObjIsLo(p0, pObj0) ) + { + pMatch0 = Saig_ObjLoToLi( p0, pObj0 ); + Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pMatch0) ); + nRegCount++; + } + } + Vec_PtrForEachEntry( Aig_Obj_t *, vNodes1, pObj1, i ) + { + if ( Saig_ObjIsLo(p1, pObj1) ) + { + pMatch1 = Saig_ObjLoToLi( p1, pObj1 ); + Aig_ObjCreateCo( pNew, Aig_ObjChild0Copy(pMatch1) ); + nRegCount++; + } + } + Aig_ManSetRegNum( pNew, nRegCount ); + Aig_ManCleanup( pNew ); + Vec_PtrFree( vNodes0 ); + Vec_PtrFree( vNodes1 ); + return pNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/aig/saig/saig_.c b/yosys/abc/src/aig/saig/saig_.c new file mode 100644 index 00000000000..f0f293fd6ba --- /dev/null +++ b/yosys/abc/src/aig/saig/saig_.c @@ -0,0 +1,52 @@ +/**CFile**************************************************************** + + FileName [saig_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Sequential AIG package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: saig_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "saig.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/abc.h b/yosys/abc/src/base/abc/abc.h new file mode 100644 index 00000000000..1d4bde4d74e --- /dev/null +++ b/yosys/abc/src/base/abc/abc.h @@ -0,0 +1,1075 @@ +/**CFile**************************************************************** + + FileName [abc.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [External declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abc.h,v 1.1 2008/05/14 22:13:11 wudenni Exp $] + +***********************************************************************/ + +#ifndef ABC__base__abc__abc_h +#define ABC__base__abc__abc_h + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#include "misc/vec/vec.h" +#include "aig/hop/hop.h" +#include "aig/gia/gia.h" +#include "misc/st/st.h" +#include "misc/st/stmm.h" +#include "misc/nm/nm.h" +#include "misc/mem/mem.h" +#include "misc/util/utilCex.h" +#include "misc/extra/extra.h" + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_START + + +// network types +typedef enum { + ABC_NTK_NONE = 0, // 0: unknown + ABC_NTK_NETLIST, // 1: network with PIs/POs, latches, nodes, and nets + ABC_NTK_LOGIC, // 2: network with PIs/POs, latches, and nodes + ABC_NTK_STRASH, // 3: structurally hashed AIG (two input AND gates with c-attributes on edges) + ABC_NTK_OTHER // 4: unused +} Abc_NtkType_t; + +// network functionality +typedef enum { + ABC_FUNC_NONE = 0, // 0: unknown + ABC_FUNC_SOP, // 1: sum-of-products + ABC_FUNC_BDD, // 2: binary decision diagrams + ABC_FUNC_AIG, // 3: and-inverter graphs + ABC_FUNC_MAP, // 4: standard cell library + ABC_FUNC_BLIFMV, // 5: BLIF-MV node functions + ABC_FUNC_BLACKBOX, // 6: black box about which nothing is known + ABC_FUNC_OTHER // 7: unused +} Abc_NtkFunc_t; + +// Supported type/functionality combinations: +/*------------------------------------------| +| | SOP | BDD | AIG | Map | +|-----------|-------|-------|-------|-------| +| Netlist | x | | x | x | +|-----------|-------|-------|-------|-------| +| Logic | x | x | x | x | +|-----------|-------|-------|-------|-------| +| Strash | | | x | | +--------------------------------------------|*/ + +// object types +typedef enum { + ABC_OBJ_NONE = 0, // 0: unknown + ABC_OBJ_CONST1, // 1: constant 1 node (AIG only) + ABC_OBJ_PI, // 2: primary input terminal + ABC_OBJ_PO, // 3: primary output terminal + ABC_OBJ_BI, // 4: box input terminal + ABC_OBJ_BO, // 5: box output terminal + ABC_OBJ_NET, // 6: net + ABC_OBJ_NODE, // 7: node + ABC_OBJ_LATCH, // 8: latch + ABC_OBJ_WHITEBOX, // 9: box with known contents + ABC_OBJ_BLACKBOX, // 10: box with unknown contents + ABC_OBJ_NUMBER // 11: unused +} Abc_ObjType_t; + +// latch initial values +typedef enum { + ABC_INIT_NONE = 0, // 0: unknown + ABC_INIT_ZERO, // 1: zero + ABC_INIT_ONE, // 2: one + ABC_INIT_DC, // 3: don't-care + ABC_INIT_OTHER // 4: unused +} Abc_InitType_t; + +//////////////////////////////////////////////////////////////////////// +/// BASIC TYPES /// +//////////////////////////////////////////////////////////////////////// + +typedef struct Abc_Des_t_ Abc_Des_t; +typedef struct Abc_Ntk_t_ Abc_Ntk_t; +typedef struct Abc_Obj_t_ Abc_Obj_t; +typedef struct Abc_Aig_t_ Abc_Aig_t; +typedef struct Abc_ManTime_t_ Abc_ManTime_t; +typedef struct Abc_ManCut_t_ Abc_ManCut_t; +typedef struct Abc_Time_t_ Abc_Time_t; + +struct Abc_Time_t_ +{ + float Rise; + float Fall; +}; + +struct Abc_Obj_t_ // 48/72 bytes (32-bits/64-bits) +{ + Abc_Ntk_t * pNtk; // the host network + Abc_Obj_t * pNext; // the next pointer in the hash table + int Id; // the object ID + unsigned Type : 4; // the object type + unsigned fMarkA : 1; // the multipurpose mark + unsigned fMarkB : 1; // the multipurpose mark + unsigned fMarkC : 1; // the multipurpose mark + unsigned fPhase : 1; // the flag to mark the phase of equivalent node + unsigned fExor : 1; // marks AIG node that is a root of EXOR + unsigned fPersist: 1; // marks the persistant AIG node + unsigned fCompl0 : 1; // complemented attribute of the first fanin in the AIG + unsigned fCompl1 : 1; // complemented attribute of the second fanin in the AIG + unsigned Level : 20; // the level of the node + Vec_Int_t vFanins; // the array of fanins + Vec_Int_t vFanouts; // the array of fanouts + union { void * pData; // the network specific data + int iData; }; // (SOP, BDD, gate, equiv class, etc) + union { void * pTemp; // temporary store for user's data + Abc_Obj_t * pCopy; // the copy of this object + int iTemp; + float dTemp; }; +}; + +struct Abc_Ntk_t_ +{ + // general information + Abc_NtkType_t ntkType; // type of the network + Abc_NtkFunc_t ntkFunc; // functionality of the network + char * pName; // the network name + char * pSpec; // the name of the spec file if present + Nm_Man_t * pManName; // name manager (stores names of objects) + // components of the network + Vec_Ptr_t * vObjs; // the array of all objects (net, nodes, latches, etc) + Vec_Ptr_t * vPis; // the array of primary inputs + Vec_Ptr_t * vPos; // the array of primary outputs + Vec_Ptr_t * vCis; // the array of combinational inputs (PIs, latches) + Vec_Ptr_t * vCos; // the array of combinational outputs (POs, asserts, latches) + Vec_Ptr_t * vPios; // the array of PIOs + Vec_Ptr_t * vBoxes; // the array of boxes + Vec_Ptr_t * vLtlProperties; + // the number of living objects + int nObjCounts[ABC_OBJ_NUMBER]; // the number of objects by type + int nObjs; // the number of live objs + int nConstrs; // the number of constraints + int nBarBufs; // the number of barrier buffers + int nBarBufs2; // the number of barrier buffers + // the backup network and the step number + Abc_Ntk_t * pNetBackup; // the pointer to the previous backup network + int iStep; // the generation number for the given network + // hierarchy + Abc_Des_t * pDesign; // design (hierarchical networks only) + Abc_Ntk_t * pAltView; // alternative structural view of the network + int fHieVisited; // flag to mark the visited network + int fHiePath; // flag to mark the network on the path + int Id; // model ID + double dTemp; // temporary value + // miscellaneous data members + int nTravIds; // the unique traversal IDs of nodes + Vec_Int_t vTravIds; // trav IDs of the objects + Mem_Fixed_t * pMmObj; // memory manager for objects + Mem_Step_t * pMmStep; // memory manager for arrays + void * pManFunc; // functionality manager (AIG manager, BDD manager, or memory manager for SOPs) + Abc_ManTime_t * pManTime; // the timing manager (for mapped networks) stores arrival/required times for all nodes + void * pManCut; // the cut manager (for AIGs) stores information about the cuts computed for the nodes + float AndGateDelay; // an average estimated delay of one AND gate + int LevelMax; // maximum number of levels + Vec_Int_t * vLevelsR; // level in the reverse topological order (for AIGs) + Vec_Ptr_t * vSupps; // CO support information + int * pModel; // counter-example (for miters) + Abc_Cex_t * pSeqModel; // counter-example (for sequential miters) + Vec_Ptr_t * vSeqModelVec; // vector of counter-examples (for sequential miters) + Abc_Ntk_t * pExdc; // the EXDC network (if given) + void * pExcare; // the EXDC network (if given) + void * pData; // misc + Abc_Ntk_t * pCopy; // copy of this network + void * pBSMan; // application manager + void * pSCLib; // SC library + Vec_Int_t * vGates; // SC library gates + Vec_Int_t * vPhases; // fanins phases in the mapped netlist + char * pWLoadUsed; // wire load model used + float * pLutTimes; // arrivals/requireds/slacks using LUT-delay model + Vec_Ptr_t * vOnehots; // names of one-hot-encoded registers + Vec_Int_t * vObjPerm; // permutation saved + Vec_Int_t * vTopo; + Vec_Ptr_t * vAttrs; // managers of various node attributes (node functionality, global BDDs, etc) + Vec_Int_t * vNameIds; // name IDs + Vec_Int_t * vFins; // obj/type info + Vec_Int_t * vOrigNodeIds; // original node IDs +}; + +struct Abc_Des_t_ +{ + char * pName; // the name of the library + void * pManFunc; // functionality manager for the nodes + Vec_Ptr_t * vTops; // the array of top-level modules + Vec_Ptr_t * vModules; // the array of modules + st__table * tModules; // the table hashing module names into their networks + Abc_Des_t * pLibrary; // the library used to map this design + void * pGenlib; // the genlib library used to map this design +}; + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +// transforming floats into ints and back +static inline unsigned Abc_InfoRandomWord() { return ((((unsigned)rand()) << 24) ^ (((unsigned)rand()) << 12) ^ ((unsigned)rand())); } // #define RAND_MAX 0x7fff +static inline void Abc_InfoRandom( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = Abc_InfoRandomWord(); } +static inline void Abc_InfoClear( unsigned * p, int nWords ) { memset( p, 0, sizeof(unsigned) * nWords ); } +static inline void Abc_InfoFill( unsigned * p, int nWords ) { memset( p, 0xff, sizeof(unsigned) * nWords );} +static inline void Abc_InfoNot( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = ~p[i]; } +static inline int Abc_InfoIsZero( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) if ( p[i] ) return 0; return 1; } +static inline int Abc_InfoIsOne( unsigned * p, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) if ( ~p[i] ) return 0; return 1; } +static inline void Abc_InfoCopy( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] = q[i]; } +static inline void Abc_InfoAnd( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] &= q[i]; } +static inline void Abc_InfoOr( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] |= q[i]; } +static inline void Abc_InfoXor( unsigned * p, unsigned * q, int nWords ) { int i; for ( i = nWords - 1; i >= 0; i-- ) p[i] ^= q[i]; } +static inline int Abc_InfoIsOrOne( unsigned * p, unsigned * q, int nWords ){ int i; for ( i = nWords - 1; i >= 0; i-- ) if ( ~(p[i] | q[i]) ) return 0; return 1; } +static inline int Abc_InfoIsOrOne3( unsigned * p, unsigned * q, unsigned * r, int nWords ){ int i; for ( i = nWords - 1; i >= 0; i-- ) if ( ~(p[i] | q[i] | r[i]) ) return 0; return 1; } + +// checking the network type +static inline int Abc_NtkIsNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_NTK_NETLIST; } +static inline int Abc_NtkIsLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_NTK_LOGIC; } +static inline int Abc_NtkIsStrash( Abc_Ntk_t * pNtk ) { return pNtk->ntkType == ABC_NTK_STRASH; } + +static inline int Abc_NtkHasSop( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP; } +static inline int Abc_NtkHasBdd( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BDD; } +static inline int Abc_NtkHasAig( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_AIG; } +static inline int Abc_NtkHasMapping( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP; } +static inline int Abc_NtkHasBlifMv( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BLIFMV; } +static inline int Abc_NtkHasBlackbox( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BLACKBOX; } + +static inline int Abc_NtkIsSopNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP && pNtk->ntkType == ABC_NTK_NETLIST; } +static inline int Abc_NtkIsBddNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BDD && pNtk->ntkType == ABC_NTK_NETLIST; } +static inline int Abc_NtkIsAigNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_AIG && pNtk->ntkType == ABC_NTK_NETLIST; } +static inline int Abc_NtkIsMappedNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP && pNtk->ntkType == ABC_NTK_NETLIST; } +static inline int Abc_NtkIsBlifMvNetlist( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BLIFMV && pNtk->ntkType == ABC_NTK_NETLIST; } +static inline int Abc_NtkIsSopLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_SOP && pNtk->ntkType == ABC_NTK_LOGIC ; } +static inline int Abc_NtkIsBddLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_BDD && pNtk->ntkType == ABC_NTK_LOGIC ; } +static inline int Abc_NtkIsAigLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_AIG && pNtk->ntkType == ABC_NTK_LOGIC ; } +static inline int Abc_NtkIsMappedLogic( Abc_Ntk_t * pNtk ) { return pNtk->ntkFunc == ABC_FUNC_MAP && pNtk->ntkType == ABC_NTK_LOGIC ; } + +// reading data members of the network +static inline char * Abc_NtkName( Abc_Ntk_t * pNtk ) { return pNtk->pName; } +static inline char * Abc_NtkSpec( Abc_Ntk_t * pNtk ) { return pNtk->pSpec; } +static inline Abc_Ntk_t * Abc_NtkExdc( Abc_Ntk_t * pNtk ) { return pNtk->pExdc; } +static inline Abc_Ntk_t * Abc_NtkBackup( Abc_Ntk_t * pNtk ) { return pNtk->pNetBackup; } +static inline int Abc_NtkStep ( Abc_Ntk_t * pNtk ) { return pNtk->iStep; } + +// setting data members of the network +static inline void Abc_NtkSetName ( Abc_Ntk_t * pNtk, char * pName ) { pNtk->pName = pName; } +static inline void Abc_NtkSetSpec ( Abc_Ntk_t * pNtk, char * pName ) { pNtk->pSpec = pName; } +static inline void Abc_NtkSetBackup( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNetBackup ) { pNtk->pNetBackup = pNetBackup; } +static inline void Abc_NtkSetStep ( Abc_Ntk_t * pNtk, int iStep ) { pNtk->iStep = iStep; } + +// getting the number of objects +static inline int Abc_NtkObjNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjs; } +static inline int Abc_NtkObjNumMax( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vObjs); } +static inline int Abc_NtkPiNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vPis); } +static inline int Abc_NtkPoNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vPos); } +static inline int Abc_NtkCiNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vCis); } +static inline int Abc_NtkCoNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vCos); } +static inline int Abc_NtkBoxNum( Abc_Ntk_t * pNtk ) { return Vec_PtrSize(pNtk->vBoxes); } +static inline int Abc_NtkBiNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_BI]; } +static inline int Abc_NtkBoNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_BO]; } +static inline int Abc_NtkNetNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_NET]; } +static inline int Abc_NtkNodeNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_NODE]; } +static inline int Abc_NtkLatchNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_LATCH]; } +static inline int Abc_NtkWhiteboxNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_WHITEBOX]; } +static inline int Abc_NtkBlackboxNum( Abc_Ntk_t * pNtk ) { return pNtk->nObjCounts[ABC_OBJ_BLACKBOX]; } +static inline int Abc_NtkIsComb( Abc_Ntk_t * pNtk ) { return Abc_NtkLatchNum(pNtk) == 0; } +static inline int Abc_NtkHasOnlyLatchBoxes(Abc_Ntk_t * pNtk ){ return Abc_NtkLatchNum(pNtk) == Abc_NtkBoxNum(pNtk); } +static inline int Abc_NtkConstrNum( Abc_Ntk_t * pNtk ) { return pNtk->nConstrs; } + +// creating simple objects +extern ABC_DLL Abc_Obj_t * Abc_NtkCreateObj( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ); +static inline Abc_Obj_t * Abc_NtkCreatePi( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_PI ); } +static inline Abc_Obj_t * Abc_NtkCreatePo( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_PO ); } +static inline Abc_Obj_t * Abc_NtkCreateBi( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BI ); } +static inline Abc_Obj_t * Abc_NtkCreateBo( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BO ); } +static inline Abc_Obj_t * Abc_NtkCreateNet( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_NET ); } +static inline Abc_Obj_t * Abc_NtkCreateNode( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_NODE ); } +static inline Abc_Obj_t * Abc_NtkCreateLatch( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_LATCH ); } +static inline Abc_Obj_t * Abc_NtkCreateWhitebox( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_WHITEBOX ); } +static inline Abc_Obj_t * Abc_NtkCreateBlackbox( Abc_Ntk_t * pNtk ) { return Abc_NtkCreateObj( pNtk, ABC_OBJ_BLACKBOX ); } + +// reading objects +static inline Abc_Obj_t * Abc_NtkObj( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vObjs, i ); } +static inline Abc_Obj_t * Abc_NtkPi( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPis, i ); } +static inline Abc_Obj_t * Abc_NtkPo( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPos, i ); } +static inline Abc_Obj_t * Abc_NtkCi( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCis, i ); } +static inline Abc_Obj_t * Abc_NtkCo( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCos, i ); } +static inline Abc_Obj_t * Abc_NtkBox( Abc_Ntk_t * pNtk, int i ) { return (Abc_Obj_t *)Vec_PtrEntry( pNtk->vBoxes, i ); } + +// working with complemented attributes of objects +static inline int Abc_ObjIsComplement( Abc_Obj_t * p ) { return (int )((ABC_PTRUINT_T)p & (ABC_PTRUINT_T)01); } +static inline Abc_Obj_t * Abc_ObjRegular( Abc_Obj_t * p ) { return (Abc_Obj_t *)((ABC_PTRUINT_T)p & ~(ABC_PTRUINT_T)01); } +static inline Abc_Obj_t * Abc_ObjNot( Abc_Obj_t * p ) { return (Abc_Obj_t *)((ABC_PTRUINT_T)p ^ (ABC_PTRUINT_T)01); } +static inline Abc_Obj_t * Abc_ObjNotCond( Abc_Obj_t * p, int c ) { return (Abc_Obj_t *)((ABC_PTRUINT_T)p ^ (ABC_PTRUINT_T)(c!=0)); } + +// reading data members of the object +static inline unsigned Abc_ObjType( Abc_Obj_t * pObj ) { return pObj->Type; } +static inline unsigned Abc_ObjId( Abc_Obj_t * pObj ) { return pObj->Id; } +static inline int Abc_ObjLevel( Abc_Obj_t * pObj ) { return pObj->Level; } +static inline Vec_Int_t * Abc_ObjFaninVec( Abc_Obj_t * pObj ) { return &pObj->vFanins; } +static inline Vec_Int_t * Abc_ObjFanoutVec( Abc_Obj_t * pObj ) { return &pObj->vFanouts; } +static inline Abc_Obj_t * Abc_ObjCopy( Abc_Obj_t * pObj ) { return pObj->pCopy; } +static inline Abc_Ntk_t * Abc_ObjNtk( Abc_Obj_t * pObj ) { return pObj->pNtk; } +static inline Abc_Ntk_t * Abc_ObjModel( Abc_Obj_t * pObj ) { assert( pObj->Type == ABC_OBJ_WHITEBOX ); return (Abc_Ntk_t *)pObj->pData; } +static inline void * Abc_ObjData( Abc_Obj_t * pObj ) { return pObj->pData; } +static inline Abc_Obj_t * Abc_ObjEquiv( Abc_Obj_t * pObj ) { return (Abc_Obj_t *)pObj->pData; } +static inline Abc_Obj_t * Abc_ObjCopyCond( Abc_Obj_t * pObj ) { return Abc_ObjRegular(pObj)->pCopy? Abc_ObjNotCond(Abc_ObjRegular(pObj)->pCopy, Abc_ObjIsComplement(pObj)) : NULL; } + +// setting data members of the network +static inline void Abc_ObjSetLevel( Abc_Obj_t * pObj, int Level ) { pObj->Level = Level; } +static inline void Abc_ObjSetCopy( Abc_Obj_t * pObj, Abc_Obj_t * pCopy ) { pObj->pCopy = pCopy; } +static inline void Abc_ObjSetData( Abc_Obj_t * pObj, void * pData ) { pObj->pData = pData; } + +// checking the object type +static inline int Abc_ObjIsNone( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_NONE; } +static inline int Abc_ObjIsPi( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PI; } +static inline int Abc_ObjIsPo( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PO; } +static inline int Abc_ObjIsBi( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_BI; } +static inline int Abc_ObjIsBo( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_BO; } +static inline int Abc_ObjIsCi( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PI || pObj->Type == ABC_OBJ_BO; } +static inline int Abc_ObjIsCo( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PO || pObj->Type == ABC_OBJ_BI; } +static inline int Abc_ObjIsTerm( Abc_Obj_t * pObj ) { return Abc_ObjIsCi(pObj) || Abc_ObjIsCo(pObj); } +static inline int Abc_ObjIsNet( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_NET; } +static inline int Abc_ObjIsNode( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_NODE; } +static inline int Abc_ObjIsLatch( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_LATCH; } +static inline int Abc_ObjIsBox( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_LATCH || pObj->Type == ABC_OBJ_WHITEBOX || pObj->Type == ABC_OBJ_BLACKBOX; } +static inline int Abc_ObjIsWhitebox( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_WHITEBOX;} +static inline int Abc_ObjIsBlackbox( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_BLACKBOX;} +static inline int Abc_ObjIsBarBuf( Abc_Obj_t * pObj ) { return Abc_NtkHasMapping(pObj->pNtk) && Abc_ObjIsNode(pObj) && Vec_IntSize(&pObj->vFanins) == 1 && pObj->pData == NULL; } +static inline void Abc_ObjBlackboxToWhitebox( Abc_Obj_t * pObj ) { assert( Abc_ObjIsBlackbox(pObj) ); pObj->Type = ABC_OBJ_WHITEBOX; pObj->pNtk->nObjCounts[ABC_OBJ_BLACKBOX]--; pObj->pNtk->nObjCounts[ABC_OBJ_WHITEBOX]++; } + +// working with fanin/fanout edges +static inline int Abc_ObjFaninNum( Abc_Obj_t * pObj ) { return pObj->vFanins.nSize; } +static inline int Abc_ObjFanoutNum( Abc_Obj_t * pObj ) { return pObj->vFanouts.nSize; } +static inline int Abc_ObjFaninId( Abc_Obj_t * pObj, int i) { return pObj->vFanins.pArray[i]; } +static inline int Abc_ObjFaninId0( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[0]; } +static inline int Abc_ObjFaninId1( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[1]; } +static inline int Abc_ObjFanoutEdgeNum( Abc_Obj_t * pObj, Abc_Obj_t * pFanout ) { assert( Abc_NtkHasAig(pObj->pNtk) ); if ( Abc_ObjFaninId0(pFanout) == pObj->Id ) return 0; if ( Abc_ObjFaninId1(pFanout) == pObj->Id ) return 1; assert( 0 ); return -1; } +static inline Abc_Obj_t * Abc_ObjFanout( Abc_Obj_t * pObj, int i ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanouts.pArray[i] ]; } +static inline Abc_Obj_t * Abc_ObjFanout0( Abc_Obj_t * pObj ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanouts.pArray[0] ]; } +static inline Abc_Obj_t * Abc_ObjFanin( Abc_Obj_t * pObj, int i ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[i] ]; } +static inline Abc_Obj_t * Abc_ObjFanin0( Abc_Obj_t * pObj ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[0] ]; } +static inline Abc_Obj_t * Abc_ObjFanin1( Abc_Obj_t * pObj ) { return (Abc_Obj_t *)pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[1] ]; } +static inline Abc_Obj_t * Abc_ObjFanin0Ntk( Abc_Obj_t * pObj ) { return (Abc_NtkIsNetlist(pObj->pNtk)? Abc_ObjFanin0(pObj) : pObj); } +static inline Abc_Obj_t * Abc_ObjFanout0Ntk( Abc_Obj_t * pObj ) { return (Abc_NtkIsNetlist(pObj->pNtk)? Abc_ObjFanout0(pObj) : pObj); } +static inline int Abc_ObjFaninC0( Abc_Obj_t * pObj ) { return pObj->fCompl0; } +static inline int Abc_ObjFaninC1( Abc_Obj_t * pObj ) { return pObj->fCompl1; } +static inline int Abc_ObjFaninC( Abc_Obj_t * pObj, int i ) { assert( i >=0 && i < 2 ); return i? pObj->fCompl1 : pObj->fCompl0; } +static inline void Abc_ObjSetFaninC( Abc_Obj_t * pObj, int i ){ assert( i >=0 && i < 2 ); if ( i ) pObj->fCompl1 = 1; else pObj->fCompl0 = 1; } +static inline void Abc_ObjXorFaninC( Abc_Obj_t * pObj, int i ){ assert( i >=0 && i < 2 ); if ( i ) pObj->fCompl1^= 1; else pObj->fCompl0^= 1; } +static inline Abc_Obj_t * Abc_ObjChild( Abc_Obj_t * pObj, int i ) { return Abc_ObjNotCond( Abc_ObjFanin(pObj,i), Abc_ObjFaninC(pObj,i) );} +static inline Abc_Obj_t * Abc_ObjChild0( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin0(pObj), Abc_ObjFaninC0(pObj) ); } +static inline Abc_Obj_t * Abc_ObjChild1( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin1(pObj), Abc_ObjFaninC1(pObj) ); } +static inline Abc_Obj_t * Abc_ObjChildCopy( Abc_Obj_t * pObj, int i ){ return Abc_ObjNotCond( Abc_ObjFanin(pObj,i)->pCopy, Abc_ObjFaninC(pObj,i) ); } +static inline Abc_Obj_t * Abc_ObjChild0Copy( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj) ); } +static inline Abc_Obj_t * Abc_ObjChild1Copy( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin1(pObj)->pCopy, Abc_ObjFaninC1(pObj) ); } +static inline Abc_Obj_t * Abc_ObjChild0Data( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Abc_ObjFanin0(pObj)->pData, Abc_ObjFaninC0(pObj) ); } +static inline Abc_Obj_t * Abc_ObjChild1Data( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( (Abc_Obj_t *)Abc_ObjFanin1(pObj)->pData, Abc_ObjFaninC1(pObj) ); } +static inline Abc_Obj_t * Abc_ObjFromLit( Abc_Ntk_t * p, int iLit ) { return Abc_ObjNotCond( Abc_NtkObj(p, Abc_Lit2Var(iLit)), Abc_LitIsCompl(iLit) ); } +static inline int Abc_ObjToLit( Abc_Obj_t * p ) { return Abc_Var2Lit( Abc_ObjId(Abc_ObjRegular(p)), Abc_ObjIsComplement(p) ); } +static inline int Abc_ObjFaninPhase( Abc_Obj_t * p, int i ) { assert(p->pNtk->vPhases); assert( i >= 0 && i < Abc_ObjFaninNum(p) ); return (Vec_IntEntry(p->pNtk->vPhases, Abc_ObjId(p)) >> i) & 1; } +static inline void Abc_ObjFaninFlipPhase( Abc_Obj_t * p,int i){ assert(p->pNtk->vPhases); assert( i >= 0 && i < Abc_ObjFaninNum(p) ); *Vec_IntEntryP(p->pNtk->vPhases, Abc_ObjId(p)) ^= (1 << i); } + +// checking the AIG node types +static inline int Abc_AigNodeIsConst( Abc_Obj_t * pNode ) { assert(Abc_NtkIsStrash(Abc_ObjRegular(pNode)->pNtk)); return Abc_ObjRegular(pNode)->Type == ABC_OBJ_CONST1; } +static inline int Abc_AigNodeIsAnd( Abc_Obj_t * pNode ) { assert(!Abc_ObjIsComplement(pNode)); assert(Abc_NtkIsStrash(pNode->pNtk)); return Abc_ObjFaninNum(pNode) == 2; } +static inline int Abc_AigNodeIsChoice( Abc_Obj_t * pNode ) { assert(!Abc_ObjIsComplement(pNode)); assert(Abc_NtkIsStrash(pNode->pNtk)); return pNode->pData != NULL && Abc_ObjFanoutNum(pNode) > 0; } + +// handling persistent nodes +static inline int Abc_NodeIsPersistant( Abc_Obj_t * pNode ) { assert( Abc_AigNodeIsAnd(pNode) ); return pNode->fPersist; } +static inline void Abc_NodeSetPersistant( Abc_Obj_t * pNode ) { assert( Abc_AigNodeIsAnd(pNode) ); pNode->fPersist = 1; } +static inline void Abc_NodeClearPersistant( Abc_Obj_t * pNode ) { assert( Abc_AigNodeIsAnd(pNode) ); pNode->fPersist = 0; } + +// working with the traversal ID +static inline void Abc_NtkIncrementTravId( Abc_Ntk_t * p ) { if (!p->vTravIds.pArray) Vec_IntFill(&p->vTravIds, Abc_NtkObjNumMax(p)+500, 0); p->nTravIds++; assert(p->nTravIds < (1<<30)); } +static inline int Abc_NodeTravId( Abc_Obj_t * p ) { return Vec_IntGetEntry(&Abc_ObjNtk(p)->vTravIds, Abc_ObjId(p)); } +static inline void Abc_NodeSetTravId( Abc_Obj_t * p, int TravId ) { Vec_IntSetEntry(&Abc_ObjNtk(p)->vTravIds, Abc_ObjId(p), TravId ); } +static inline void Abc_NodeSetTravIdCurrent( Abc_Obj_t * p ) { Abc_NodeSetTravId( p, Abc_ObjNtk(p)->nTravIds ); } +static inline void Abc_NodeSetTravIdPrevious( Abc_Obj_t * p ) { Abc_NodeSetTravId( p, Abc_ObjNtk(p)->nTravIds-1 ); } +static inline int Abc_NodeIsTravIdCurrent( Abc_Obj_t * p ) { return (Abc_NodeTravId(p) == Abc_ObjNtk(p)->nTravIds); } +static inline int Abc_NodeIsTravIdPrevious( Abc_Obj_t * p ) { return (Abc_NodeTravId(p) == Abc_ObjNtk(p)->nTravIds-1); } +static inline void Abc_NodeSetTravIdCurrentId( Abc_Ntk_t * p, int i) { Vec_IntSetEntry(&p->vTravIds, i, p->nTravIds ); } +static inline int Abc_NodeIsTravIdCurrentId( Abc_Ntk_t * p, int i) { return (Vec_IntGetEntry(&p->vTravIds, i) == p->nTravIds); } + +// checking initial state of the latches +static inline void Abc_LatchSetInitNone( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_NONE; } +static inline void Abc_LatchSetInit0( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_ZERO; } +static inline void Abc_LatchSetInit1( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_ONE; } +static inline void Abc_LatchSetInitDc( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); pLatch->pData = (void *)ABC_INIT_DC; } +static inline int Abc_LatchIsInitNone( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_NONE; } +static inline int Abc_LatchIsInit0( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_ZERO; } +static inline int Abc_LatchIsInit1( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_ONE; } +static inline int Abc_LatchIsInitDc( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return pLatch->pData == (void *)ABC_INIT_DC; } +static inline int Abc_LatchInit( Abc_Obj_t * pLatch ) { assert(Abc_ObjIsLatch(pLatch)); return (int)(ABC_PTRINT_T)pLatch->pData; } + +// global BDDs of the nodes +static inline void * Abc_NtkGlobalBdd( Abc_Ntk_t * pNtk ) { return Vec_PtrEntry(pNtk->vAttrs, VEC_ATTR_GLOBAL_BDD); } +static inline void * Abc_NtkGlobalBddMan( Abc_Ntk_t * pNtk ) { return Vec_AttMan( (Vec_Att_t *)Abc_NtkGlobalBdd(pNtk) ); } +static inline void ** Abc_NtkGlobalBddArray( Abc_Ntk_t * pNtk ) { return Vec_AttArray( (Vec_Att_t *)Abc_NtkGlobalBdd(pNtk) ); } +static inline void * Abc_ObjGlobalBdd( Abc_Obj_t * pObj ) { return Vec_AttEntry( (Vec_Att_t *)Abc_NtkGlobalBdd(pObj->pNtk), pObj->Id ); } +static inline void Abc_ObjSetGlobalBdd( Abc_Obj_t * pObj, void * bF ) { Vec_AttWriteEntry( (Vec_Att_t *)Abc_NtkGlobalBdd(pObj->pNtk), pObj->Id, bF ); } + +// MV variables of the nodes +static inline void * Abc_NtkMvVar( Abc_Ntk_t * pNtk ) { return Vec_PtrEntry(pNtk->vAttrs, VEC_ATTR_MVVAR); } +static inline void * Abc_NtkMvVarMan( Abc_Ntk_t * pNtk ) { return Abc_NtkMvVar(pNtk)? Vec_AttMan( (Vec_Att_t *)Abc_NtkMvVar(pNtk) ) : NULL; } +static inline void * Abc_ObjMvVar( Abc_Obj_t * pObj ) { return Abc_NtkMvVar(pObj->pNtk)? Vec_AttEntry( (Vec_Att_t *)Abc_NtkMvVar(pObj->pNtk), pObj->Id ) : NULL; } +static inline int Abc_ObjMvVarNum( Abc_Obj_t * pObj ) { return (Abc_NtkMvVar(pObj->pNtk) && Abc_ObjMvVar(pObj))? *((int*)Abc_ObjMvVar(pObj)) : 2; } +static inline void Abc_ObjSetMvVar( Abc_Obj_t * pObj, void * pV) { Vec_AttWriteEntry( (Vec_Att_t *)Abc_NtkMvVar(pObj->pNtk), pObj->Id, pV ); } + +//////////////////////////////////////////////////////////////////////// +/// ITERATORS /// +//////////////////////////////////////////////////////////////////////// + +// objects of the network +#define Abc_NtkForEachObj( pNtk, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pObj) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ + if ( (pObj) == NULL ) {} else +#define Abc_NtkForEachObjReverse( pNtk, pNode, i ) \ + for ( i = Vec_PtrSize((pNtk)->vObjs) - 1; (i >= 0) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i-- ) \ + if ( (pNode) == NULL ) {} else +#define Abc_NtkForEachObjVec( vIds, pNtk, pObj, i ) \ + for ( i = 0; i < Vec_IntSize(vIds) && (((pObj) = Abc_NtkObj(pNtk, Vec_IntEntry(vIds,i))), 1); i++ ) \ + if ( (pObj) == NULL ) {} else +#define Abc_NtkForEachObjVecStart( vIds, pNtk, pObj, i, Start ) \ + for ( i = Start; i < Vec_IntSize(vIds) && (((pObj) = Abc_NtkObj(pNtk, Vec_IntEntry(vIds,i))), 1); i++ ) \ + if ( (pObj) == NULL ) {} else +#define Abc_NtkForEachNet( pNtk, pNet, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNet) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ + if ( (pNet) == NULL || !Abc_ObjIsNet(pNet) ) {} else +#define Abc_NtkForEachNode( pNtk, pNode, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ + if ( (pNode) == NULL || !Abc_ObjIsNode(pNode) ) {} else +#define Abc_NtkForEachNodeNotBarBuf( pNtk, pNode, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ + if ( (pNode) == NULL || !Abc_ObjIsNode(pNode) || Abc_ObjIsBarBuf(pNode) ) {} else +#define Abc_NtkForEachNode1( pNtk, pNode, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ + if ( (pNode) == NULL || !Abc_ObjIsNode(pNode) || !Abc_ObjFaninNum(pNode) ) {} else +#define Abc_NtkForEachNodeNotBarBuf1( pNtk, pNode, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ + if ( (pNode) == NULL || !Abc_ObjIsNode(pNode) || !Abc_ObjFaninNum(pNode) || Abc_ObjIsBarBuf(pNode) ) {} else +#define Abc_NtkForEachNodeReverse( pNtk, pNode, i ) \ + for ( i = Vec_PtrSize((pNtk)->vObjs) - 1; (i >= 0) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i-- ) \ + if ( (pNode) == NULL || !Abc_ObjIsNode(pNode) ) {} else +#define Abc_NtkForEachNodeReverse1( pNtk, pNode, i ) \ + for ( i = Vec_PtrSize((pNtk)->vObjs) - 1; (i >= 0) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i-- ) \ + if ( (pNode) == NULL || !Abc_ObjIsNode(pNode) || !Abc_ObjFaninNum(pNode) ) {} else +#define Abc_NtkForEachBarBuf( pNtk, pNode, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ + if ( (pNode) == NULL || !Abc_ObjIsBarBuf(pNode) ) {} else +#define Abc_NtkForEachGate( pNtk, pNode, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ + if ( (pNode) == NULL || !Abc_ObjIsGate(pNode) ) {} else +#define Abc_AigForEachAnd( pNtk, pNode, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ + if ( (pNode) == NULL || !Abc_AigNodeIsAnd(pNode) ) {} else +#define Abc_NtkForEachNodeCi( pNtk, pNode, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ + if ( (pNode) == NULL || (!Abc_ObjIsNode(pNode) && !Abc_ObjIsCi(pNode)) ) {} else +#define Abc_NtkForEachNodeCo( pNtk, pNode, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vObjs)) && (((pNode) = Abc_NtkObj(pNtk, i)), 1); i++ ) \ + if ( (pNode) == NULL || (!Abc_ObjIsNode(pNode) && !Abc_ObjIsCo(pNode)) ) {} else +// various boxes +#define Abc_NtkForEachBox( pNtk, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ ) +#define Abc_NtkForEachLatch( pNtk, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ ) \ + if ( !Abc_ObjIsLatch(pObj) ) {} else +#define Abc_NtkForEachLatchInput( pNtk, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)); i++ ) \ + if ( !(Abc_ObjIsLatch(Abc_NtkBox(pNtk, i)) && (((pObj) = Abc_ObjFanin0(Abc_NtkBox(pNtk, i))), 1)) ) {} else +#define Abc_NtkForEachLatchOutput( pNtk, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)); i++ ) \ + if ( !(Abc_ObjIsLatch(Abc_NtkBox(pNtk, i)) && (((pObj) = Abc_ObjFanout0(Abc_NtkBox(pNtk, i))), 1)) ) {} else +#define Abc_NtkForEachWhitebox( pNtk, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ ) \ + if ( !Abc_ObjIsWhitebox(pObj) ) {} else +#define Abc_NtkForEachBlackbox( pNtk, pObj, i ) \ + for ( i = 0; (i < Vec_PtrSize((pNtk)->vBoxes)) && (((pObj) = Abc_NtkBox(pNtk, i)), 1); i++ ) \ + if ( !Abc_ObjIsBlackbox(pObj) ) {} else +// inputs and outputs +#define Abc_NtkForEachPi( pNtk, pPi, i ) \ + for ( i = 0; (i < Abc_NtkPiNum(pNtk)) && (((pPi) = Abc_NtkPi(pNtk, i)), 1); i++ ) +#define Abc_NtkForEachCi( pNtk, pCi, i ) \ + for ( i = 0; (i < Abc_NtkCiNum(pNtk)) && (((pCi) = Abc_NtkCi(pNtk, i)), 1); i++ ) +#define Abc_NtkForEachPo( pNtk, pPo, i ) \ + for ( i = 0; (i < Abc_NtkPoNum(pNtk)) && (((pPo) = Abc_NtkPo(pNtk, i)), 1); i++ ) +#define Abc_NtkForEachCo( pNtk, pCo, i ) \ + for ( i = 0; (i < Abc_NtkCoNum(pNtk)) && (((pCo) = Abc_NtkCo(pNtk, i)), 1); i++ ) +#define Abc_NtkForEachLiPo( pNtk, pCo, i ) \ + for ( i = 0; (i < Abc_NtkCoNum(pNtk)) && (((pCo) = Abc_NtkCo(pNtk, i < pNtk->nBarBufs ? Abc_NtkCoNum(pNtk) - pNtk->nBarBufs + i : i - pNtk->nBarBufs)), 1); i++ ) +// fanin and fanouts +#define Abc_ObjForEachFanin( pObj, pFanin, i ) \ + for ( i = 0; (i < Abc_ObjFaninNum(pObj)) && (((pFanin) = Abc_ObjFanin(pObj, i)), 1); i++ ) +#define Abc_ObjForEachFanout( pObj, pFanout, i ) \ + for ( i = 0; (i < Abc_ObjFanoutNum(pObj)) && (((pFanout) = Abc_ObjFanout(pObj, i)), 1); i++ ) +#define Abc_ObjForEachFaninId( pObj, iFanin, i ) \ + for ( i = 0; (i < Abc_ObjFaninNum(pObj)) && (((iFanin) = Abc_ObjFaninId(pObj, i)), 1); i++ ) +#define Abc_ObjForEachFanoutId( pObj, iFanout, i ) \ + for ( i = 0; (i < Abc_ObjFanoutNum(pObj)) && (((iFanout) = Abc_ObjFanoutId(pObj, i)), 1); i++ ) +// cubes and literals +#define Abc_CubeForEachVar( pCube, Value, i ) \ + for ( i = 0; (pCube[i] != ' ') && (Value = pCube[i]); i++ ) +#define Abc_SopForEachCube( pSop, nFanins, pCube ) \ + for ( pCube = (pSop); *pCube; pCube += (nFanins) + 3 ) +#define Abc_SopForEachCubePair( pSop, nFanins, pCube, pCube2 ) \ + Abc_SopForEachCube( pSop, nFanins, pCube ) \ + Abc_SopForEachCube( pCube + (nFanins) + 3, nFanins, pCube2 ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +/*=== abcAig.c ==========================================================*/ +extern ABC_DLL Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_AigFree( Abc_Aig_t * pMan ); +extern ABC_DLL int Abc_AigCleanup( Abc_Aig_t * pMan ); +extern ABC_DLL int Abc_AigCheck( Abc_Aig_t * pMan ); +extern ABC_DLL int Abc_AigLevel( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Obj_t * Abc_AigConst1( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Obj_t * Abc_AigAnd( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); +extern ABC_DLL Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); +extern ABC_DLL Abc_Obj_t * Abc_AigXorLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, int * pType ); +extern ABC_DLL Abc_Obj_t * Abc_AigMuxLookup( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * pT, Abc_Obj_t * pE, int * pType ); +extern ABC_DLL Abc_Obj_t * Abc_AigOr( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); +extern ABC_DLL Abc_Obj_t * Abc_AigXor( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); +extern ABC_DLL Abc_Obj_t * Abc_AigMux( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * p1, Abc_Obj_t * p0 ); +extern ABC_DLL Abc_Obj_t * Abc_AigMiter( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs, int fImplic ); +extern ABC_DLL int Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel ); +extern ABC_DLL void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pOld ); +extern ABC_DLL void Abc_AigRehash( Abc_Aig_t * pMan ); +extern ABC_DLL int Abc_AigNodeHasComplFanoutEdge( Abc_Obj_t * pNode ); +extern ABC_DLL int Abc_AigNodeHasComplFanoutEdgeTrav( Abc_Obj_t * pNode ); +extern ABC_DLL void Abc_AigPrintNode( Abc_Obj_t * pNode ); +extern ABC_DLL int Abc_AigNodeIsAcyclic( Abc_Obj_t * pNode, Abc_Obj_t * pRoot ); +extern ABC_DLL void Abc_AigCheckFaninOrder( Abc_Aig_t * pMan ); +extern ABC_DLL void Abc_AigSetNodePhases( Abc_Ntk_t * pNtk ); +extern ABC_DLL Vec_Ptr_t * Abc_AigUpdateStart( Abc_Aig_t * pMan, Vec_Ptr_t ** pvUpdatedNets ); +extern ABC_DLL void Abc_AigUpdateStop( Abc_Aig_t * pMan ); +extern ABC_DLL void Abc_AigUpdateReset( Abc_Aig_t * pMan ); +/*=== abcAttach.c ==========================================================*/ +extern ABC_DLL int Abc_NtkAttach( Abc_Ntk_t * pNtk ); +/*=== abcBarBuf.c ==========================================================*/ +extern ABC_DLL Abc_Ntk_t * Abc_NtkToBarBufs( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkFromBarBufs( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkBarBufsToBuffers( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkBarBufsFromBuffers( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtk ); +/*=== abcBlifMv.c ==========================================================*/ +extern ABC_DLL void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkFreeMvVars( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkSetMvVarValues( Abc_Obj_t * pObj, int nValues ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkStrashBlifMv( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkInsertBlifMv( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtkLogic ); +extern ABC_DLL int Abc_NtkConvertToBlifMv( Abc_Ntk_t * pNtk ); +extern ABC_DLL char * Abc_NodeConvertSopToMvSop( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 ); +extern ABC_DLL int Abc_NodeEvalMvCost( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 ); +/*=== abcBalance.c ==========================================================*/ +extern ABC_DLL Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, int fDuplicate, int fSelective, int fUpdateLevel ); +/*=== abcCheck.c ==========================================================*/ +extern ABC_DLL int Abc_NtkCheck( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkCheckRead( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkDoCheck( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ); +extern ABC_DLL int Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOnlyPis, int fComb ); +extern ABC_DLL int Abc_NtkIsAcyclicHierarchy( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkCheckUniqueCiNames( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkCheckUniqueCoNames( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkCheckUniqueCioNames( Abc_Ntk_t * pNtk ); +/*=== abcCollapse.c ==========================================================*/ +extern ABC_DLL Abc_Ntk_t * Abc_NtkCollapse( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDualRail, int fReorder, int fReverse, int fDumpOrder, int fVerbose ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkCollapseSat( Abc_Ntk_t * pNtk, int nCubeLim, int nBTLimit, int nCostMax, int fCanon, int fReverse, int fCnfShared, int fVerbose ); +extern ABC_DLL Gia_Man_t * Abc_NtkClpGia( Abc_Ntk_t * pNtk ); +/*=== abcCut.c ==========================================================*/ +extern ABC_DLL void * Abc_NodeGetCutsRecursive( void * p, Abc_Obj_t * pObj, int fDag, int fTree ); +extern ABC_DLL void * Abc_NodeGetCuts( void * p, Abc_Obj_t * pObj, int fDag, int fTree ); +extern ABC_DLL void Abc_NodeGetCutsSeq( void * p, Abc_Obj_t * pObj, int fFirst ); +extern ABC_DLL void * Abc_NodeReadCuts( void * p, Abc_Obj_t * pObj ); +extern ABC_DLL void Abc_NodeFreeCuts( void * p, Abc_Obj_t * pObj ); +/*=== abcDar.c ============================================================*/ +extern ABC_DLL int Abc_NtkPhaseFrameNum( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkDarPrintCone( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkBalanceExor( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkDarLatchSweep( Abc_Ntk_t * pNtk, int fLatchConst, int fLatchEqual, int fSaveNames, int fUseMvSweep, int nFramesSymb, int nFramesSatur, int fVerbose, int fVeryVerbose ); +/*=== abcDelay.c ==========================================================*/ +extern ABC_DLL float Abc_NtkDelayTraceLut( Abc_Ntk_t * pNtk, int fUseLutLib ); +/*=== abcDfs.c ==========================================================*/ +extern ABC_DLL Vec_Ptr_t * Abc_NtkDfs( Abc_Ntk_t * pNtk, int fCollectAll ); +extern ABC_DLL Vec_Ptr_t * Abc_NtkDfs2( Abc_Ntk_t * pNtk ); +extern ABC_DLL Vec_Ptr_t * Abc_NtkDfsNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ); +extern ABC_DLL Vec_Ptr_t * Abc_NtkDfsReverse( Abc_Ntk_t * pNtk ); +extern ABC_DLL Vec_Ptr_t * Abc_NtkDfsReverseNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ); +extern ABC_DLL Vec_Ptr_t * Abc_NtkDfsReverseNodesContained( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ); +extern ABC_DLL Vec_Ptr_t * Abc_NtkDfsSeq( Abc_Ntk_t * pNtk ); +extern ABC_DLL Vec_Ptr_t * Abc_NtkDfsSeqReverse( Abc_Ntk_t * pNtk ); +extern ABC_DLL Vec_Ptr_t * Abc_NtkDfsIter( Abc_Ntk_t * pNtk, int fCollectAll ); +extern ABC_DLL Vec_Ptr_t * Abc_NtkDfsIterNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots ); +extern ABC_DLL Vec_Ptr_t * Abc_NtkDfsHie( Abc_Ntk_t * pNtk, int fCollectAll ); +extern ABC_DLL int Abc_NtkIsDfsOrdered( Abc_Ntk_t * pNtk ); +extern ABC_DLL Vec_Ptr_t * Abc_NtkDfsWithBoxes( Abc_Ntk_t * pNtk ); +extern ABC_DLL Vec_Ptr_t * Abc_NtkSupport( Abc_Ntk_t * pNtk ); +extern ABC_DLL Vec_Ptr_t * Abc_NtkNodeSupport( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ); +extern ABC_DLL Vec_Int_t * Abc_NtkNodeSupportInt( Abc_Ntk_t * pNtk, int iCo ); +extern ABC_DLL int Abc_NtkFunctionalIso( Abc_Ntk_t * pNtk, int iCo1, int iCo2, int fCommon ); +extern ABC_DLL Vec_Ptr_t * Abc_AigDfs( Abc_Ntk_t * pNtk, int fCollectAll, int fCollectCos ); +extern ABC_DLL Vec_Ptr_t * Abc_AigDfsMap( Abc_Ntk_t * pNtk ); +extern ABC_DLL Vec_Vec_t * Abc_DfsLevelized( Abc_Obj_t * pNode, int fTfi ); +extern ABC_DLL Vec_Vec_t * Abc_NtkLevelize( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkLevel( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkLevelR( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkLevelReverse( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkIsAcyclicWithBoxes( Abc_Ntk_t * pNtk ); +extern ABC_DLL Vec_Ptr_t * Abc_AigGetLevelizedOrder( Abc_Ntk_t * pNtk, int fCollectCis ); +/*=== abcExact.c ==========================================================*/ +extern ABC_DLL int Abc_ExactInputNum(); +extern ABC_DLL int Abc_ExactIsRunning(); +extern ABC_DLL Abc_Obj_t * Abc_ExactBuildNode( word * pTruth, int nVars, int * pArrTimeProfile, Abc_Obj_t ** pFanins, Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkFindExact( word * pTruth, int nVars, int nFunc, int nMaxDepth, int * pArrivalTimes, int nBTLimit, int nStartGates, int fVerbose ); +/*=== abcFanio.c ==========================================================*/ +extern ABC_DLL void Abc_ObjAddFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ); +extern ABC_DLL void Abc_ObjDeleteFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ); +extern ABC_DLL void Abc_ObjRemoveFanins( Abc_Obj_t * pObj ); +extern ABC_DLL void Abc_ObjPatchFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFaninOld, Abc_Obj_t * pFaninNew ); +extern ABC_DLL void Abc_ObjPatchFanoutFanin( Abc_Obj_t * pObj, int iObjNew ); +extern ABC_DLL Abc_Obj_t * Abc_ObjInsertBetween( Abc_Obj_t * pNodeIn, Abc_Obj_t * pNodeOut, Abc_ObjType_t Type ); +extern ABC_DLL void Abc_ObjTransferFanout( Abc_Obj_t * pObjOld, Abc_Obj_t * pObjNew ); +extern ABC_DLL void Abc_ObjReplace( Abc_Obj_t * pObjOld, Abc_Obj_t * pObjNew ); +extern ABC_DLL void Abc_ObjReplaceByConstant( Abc_Obj_t * pNode, int fConst1 ); +extern ABC_DLL int Abc_ObjFanoutFaninNum( Abc_Obj_t * pFanout, Abc_Obj_t * pFanin ); +/*=== abcFanOrder.c ==========================================================*/ +extern ABC_DLL int Abc_NtkMakeLegit( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkSortSops( Abc_Ntk_t * pNtk ); +/*=== abcFraig.c ==========================================================*/ +extern ABC_DLL Abc_Ntk_t * Abc_NtkFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc ); +extern ABC_DLL void * Abc_NtkToFraig( Abc_Ntk_t * pNtk, void * pParams, int fAllNodes, int fExdc ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkFraigTrust( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkFraigStore( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkFraigRestore( int nPatsRand, int nPatsDyna, int nBTLimit ); +extern ABC_DLL void Abc_NtkFraigStoreClean(); +/*=== abcFunc.c ==========================================================*/ +extern ABC_DLL int Abc_NtkSopToBdd( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit, int fCubeSort ); +extern ABC_DLL void Abc_NodeBddToCnf( Abc_Obj_t * pNode, Mem_Flex_t * pMmMan, Vec_Str_t * vCube, int fAllPrimes, char ** ppSop0, char ** ppSop1 ); +extern ABC_DLL void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkSopToAig( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkAigToBdd( Abc_Ntk_t * pNtk ); +extern ABC_DLL Gia_Man_t * Abc_NtkAigToGia( Abc_Ntk_t * p, int fGiaSimple ); +extern ABC_DLL int Abc_NtkMapToSopUsingLibrary( Abc_Ntk_t * pNtk, void* library ); +extern ABC_DLL int Abc_NtkMapToSop( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit ); +extern ABC_DLL int Abc_NtkToBdd( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkToAig( Abc_Ntk_t * pNtk ); +/*=== abcHaig.c ==========================================================*/ +extern ABC_DLL int Abc_NtkHaigStart( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkHaigStop( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkHaigUse( Abc_Ntk_t * pNtk ); +/*=== abcHie.c ==========================================================*/ +extern ABC_DLL Abc_Ntk_t * Abc_NtkFlattenLogicHierarchy( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkConvertBlackboxes( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkInsertNewLogic( Abc_Ntk_t * pNtkH, Abc_Ntk_t * pNtkL ); +extern ABC_DLL void Abc_NtkPrintBoxInfo( Abc_Ntk_t * pNtk ); +/*=== abcHieGia.c ==========================================================*/ +extern ABC_DLL Gia_Man_t * Abc_NtkFlattenHierarchyGia( Abc_Ntk_t * pNtk, Vec_Ptr_t ** pvBuffers, int fVerbose ); +extern ABC_DLL void Abc_NtkInsertHierarchyGia( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNew, int fVerbose ); +/*=== abcLatch.c ==========================================================*/ +extern ABC_DLL int Abc_NtkLatchIsSelfFeed( Abc_Obj_t * pLatch ); +extern ABC_DLL int Abc_NtkCountSelfFeedLatches( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkRemoveSelfFeedLatches( Abc_Ntk_t * pNtk ); +extern ABC_DLL Vec_Int_t * Abc_NtkCollectLatchValues( Abc_Ntk_t * pNtk ); +extern ABC_DLL char * Abc_NtkCollectLatchValuesStr( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues ); +extern ABC_DLL Abc_Obj_t * Abc_NtkAddLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pDriver, Abc_InitType_t Init ); +extern ABC_DLL void Abc_NtkConvertDcLatches( Abc_Ntk_t * pNtk ); +extern ABC_DLL Vec_Ptr_t * Abc_NtkConverLatchNamesIntoNumbers( Abc_Ntk_t * pNtk ); + /*=== abcLib.c ==========================================================*/ +extern ABC_DLL Abc_Des_t * Abc_DesCreate( char * pName ); +extern ABC_DLL void Abc_DesCleanManPointer( Abc_Des_t * p, void * pMan ); +extern ABC_DLL void Abc_DesFree( Abc_Des_t * p, Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Des_t * Abc_DesDup( Abc_Des_t * p ); +extern ABC_DLL void Abc_DesPrint( Abc_Des_t * p ); +extern ABC_DLL int Abc_DesAddModel( Abc_Des_t * p, Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Ntk_t * Abc_DesFindModelByName( Abc_Des_t * p, char * pName ); +extern ABC_DLL int Abc_DesFindTopLevelModels( Abc_Des_t * p ); +extern ABC_DLL Abc_Ntk_t * Abc_DesDeriveRoot( Abc_Des_t * p ); +/*=== abcLog.c ==========================================================*/ +extern ABC_DLL void Abc_NtkWriteLogFile( char * pFileName, Abc_Cex_t * pSeqCex, int Status, int nFrames, char * pCommand ); +/*=== abcMap.c ==========================================================*/ +extern ABC_DLL Abc_Obj_t * Abc_NtkFetchTwinNode( Abc_Obj_t * pNode ); +/*=== abcMiter.c ==========================================================*/ +extern ABC_DLL int Abc_NtkMinimumBase( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NodeMinimumBase( Abc_Obj_t * pNode ); +extern ABC_DLL int Abc_NtkRemoveDupFanins( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NodeRemoveDupFanins( Abc_Obj_t * pNode ); +/*=== abcMiter.c ==========================================================*/ +extern ABC_DLL Abc_Ntk_t * Abc_NtkMiter( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb, int nPartSize, int fImplic, int fMulti ); +extern ABC_DLL void Abc_NtkMiterAddCone( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkMiter, Abc_Obj_t * pNode ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkMiterAnd( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOr, int fCompl2 ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkMiterCofactor( Abc_Ntk_t * pNtk, Vec_Int_t * vPiValues ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkMiterForCofactors( Abc_Ntk_t * pNtk, int Out, int In1, int In2 ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkMiterQuantify( Abc_Ntk_t * pNtk, int In, int fExist ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkMiterQuantifyPis( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkMiterIsConstant( Abc_Ntk_t * pMiter ); +extern ABC_DLL void Abc_NtkMiterReport( Abc_Ntk_t * pMiter ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkFrames( Abc_Ntk_t * pNtk, int nFrames, int fInitial, int fVerbose ); +extern ABC_DLL int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd, int fXor ); +/*=== abcNames.c ====================================================*/ +extern ABC_DLL char * Abc_ObjName( Abc_Obj_t * pNode ); +extern ABC_DLL char * Abc_ObjAssignName( Abc_Obj_t * pObj, char * pName, char * pSuffix ); +extern ABC_DLL char * Abc_ObjNamePrefix( Abc_Obj_t * pObj, char * pPrefix ); +extern ABC_DLL char * Abc_ObjNameSuffix( Abc_Obj_t * pObj, char * pSuffix ); +extern ABC_DLL char * Abc_ObjNameDummy( char * pPrefix, int Num, int nDigits ); +extern ABC_DLL void Abc_NtkTrasferNames( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); +extern ABC_DLL void Abc_NtkTrasferNamesNoLatches( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); +extern ABC_DLL Vec_Ptr_t * Abc_NodeGetFaninNames( Abc_Obj_t * pNode ); +extern ABC_DLL Vec_Ptr_t * Abc_NodeGetFakeNames( int nNames ); +extern ABC_DLL void Abc_NodeFreeNames( Vec_Ptr_t * vNames ); +extern ABC_DLL char ** Abc_NtkCollectCioNames( Abc_Ntk_t * pNtk, int fCollectCos ); +extern ABC_DLL int Abc_NodeCompareNames( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ); +extern ABC_DLL void Abc_NtkOrderObjsByName( Abc_Ntk_t * pNtk, int fComb ); +extern ABC_DLL void Abc_NtkAddDummyPiNames( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkAddDummyPoNames( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkAddDummyBoxNames( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkShortNames( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkCleanNames( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkStartNameIds( Abc_Ntk_t * p ); +extern ABC_DLL void Abc_NtkTransferNameIds( Abc_Ntk_t * p, Abc_Ntk_t * pNew ); +extern ABC_DLL void Abc_NtkUpdateNameIds( Abc_Ntk_t * p ); +/*=== abcNetlist.c ==========================================================*/ +extern ABC_DLL Abc_Ntk_t * Abc_NtkToLogic( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkToNetlist( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkToNetlistBench( Abc_Ntk_t * pNtk ); +/*=== abcNtbdd.c ==========================================================*/ +extern ABC_DLL Abc_Ntk_t * Abc_NtkDeriveFromBdd( void * dd, void * bFunc, char * pNamePo, Vec_Ptr_t * vNamesPi ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkBddToMuxes( Abc_Ntk_t * pNtk, int fGlobal, int Limit, int fUseAdd ); +extern ABC_DLL void * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int fBddSizeMax, int fDropInternal, int fReorder, int fReverse, int fVerbose ); +extern ABC_DLL void * Abc_NtkFreeGlobalBdds( Abc_Ntk_t * pNtk, int fFreeMan ); +extern ABC_DLL int Abc_NtkSizeOfGlobalBdds( Abc_Ntk_t * pNtk ); +/*=== abcNtk.c ==========================================================*/ +extern ABC_DLL Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func, int fUseMemMan ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkStartFromNoLatches( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ); +extern ABC_DLL void Abc_NtkFinalize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkStartRead( char * pName ); +extern ABC_DLL void Abc_NtkFinalizeRead( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkDupDfs( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkDupDfsNoBarBufs( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkDupTransformMiter( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName, int fUseAllCis ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateConeArray( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, int fUseAllCis ); +extern ABC_DLL void Abc_NtkAppendToCone( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateMffc( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateTarget( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateFromNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateFromRange( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateWithNode( char * pSop ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateWithNodes( Vec_Ptr_t * vSops ); +extern ABC_DLL void Abc_NtkDelete( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkMakeComb( Abc_Ntk_t * pNtk, int fRemoveLatches ); +extern ABC_DLL void Abc_NtkPermute( Abc_Ntk_t * pNtk, int fInputs, int fOutputs, int fFlops, char * pInPermFile, char * pOutPermFile, char * pFlopPermFile ); +extern ABC_DLL void Abc_NtkUnpermute( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateFromSops( char * pName, Vec_Ptr_t * vSops ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateFromGias( char * pName, Vec_Ptr_t * vGias, Gia_Man_t * pMulti ); +/*=== abcObj.c ==========================================================*/ +extern ABC_DLL Abc_Obj_t * Abc_ObjAlloc( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ); +extern ABC_DLL void Abc_ObjRecycle( Abc_Obj_t * pObj ); +extern ABC_DLL Abc_Obj_t * Abc_NtkCreateObj( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ); +extern ABC_DLL void Abc_NtkDeleteObj( Abc_Obj_t * pObj ); +extern ABC_DLL void Abc_NtkDeleteObjPo( Abc_Obj_t * pObj ); +extern ABC_DLL void Abc_NtkDeleteObj_rec( Abc_Obj_t * pObj, int fOnlyNodes ); +extern ABC_DLL void Abc_NtkDeleteAll_rec( Abc_Obj_t * pObj ); +extern ABC_DLL Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCopyName ); +extern ABC_DLL Abc_Obj_t * Abc_NtkDupBox( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pBox, int fCopyName ); +extern ABC_DLL Abc_Obj_t * Abc_NtkCloneObj( Abc_Obj_t * pNode ); +extern ABC_DLL Abc_Obj_t * Abc_NtkFindNode( Abc_Ntk_t * pNtk, char * pName ); +extern ABC_DLL Abc_Obj_t * Abc_NtkFindNet( Abc_Ntk_t * pNtk, char * pName ); +extern ABC_DLL Abc_Obj_t * Abc_NtkFindCi( Abc_Ntk_t * pNtk, char * pName ); +extern ABC_DLL Abc_Obj_t * Abc_NtkFindCo( Abc_Ntk_t * pNtk, char * pName ); +extern ABC_DLL Abc_Obj_t * Abc_NtkFindOrCreateNet( Abc_Ntk_t * pNtk, char * pName ); +extern ABC_DLL Abc_Obj_t * Abc_NtkCreateNodeConst0( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Obj_t * Abc_NtkCreateNodeConst1( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Obj_t * Abc_NtkCreateNodeInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ); +extern ABC_DLL Abc_Obj_t * Abc_NtkCreateNodeBuf( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ); +extern ABC_DLL Abc_Obj_t * Abc_NtkCreateNodeAnd( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ); +extern ABC_DLL Abc_Obj_t * Abc_NtkCreateNodeOr( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ); +extern ABC_DLL Abc_Obj_t * Abc_NtkCreateNodeExor( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ); +extern ABC_DLL Abc_Obj_t * Abc_NtkCreateNodeMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0 ); +extern ABC_DLL int Abc_NodeIsConst( Abc_Obj_t * pNode ); +extern ABC_DLL int Abc_NodeIsConst0( Abc_Obj_t * pNode ); +extern ABC_DLL int Abc_NodeIsConst1( Abc_Obj_t * pNode ); +extern ABC_DLL int Abc_NodeIsBuf( Abc_Obj_t * pNode ); +extern ABC_DLL int Abc_NodeIsInv( Abc_Obj_t * pNode ); +extern ABC_DLL void Abc_NodeComplement( Abc_Obj_t * pNode ); +extern ABC_DLL void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin ); +/*=== abcOdc.c ==========================================================*/ +typedef struct Odc_Man_t_ Odc_Man_t; +extern ABC_DLL Odc_Man_t * Abc_NtkDontCareAlloc( int nVarsMax, int nLevels, int fVerbose, int fVeryVerbose ); +extern ABC_DLL void Abc_NtkDontCareClear( Odc_Man_t * p ); +extern ABC_DLL void Abc_NtkDontCareFree( Odc_Man_t * p ); +extern ABC_DLL int Abc_NtkDontCareCompute( Odc_Man_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, unsigned * puTruth ); +/*=== abcPrint.c ==========================================================*/ +extern ABC_DLL float Abc_NtkMfsTotalSwitching( Abc_Ntk_t * pNtk ); +extern ABC_DLL float Abc_NtkMfsTotalGlitching( Abc_Ntk_t * pNtk, int nPats, int Prob, int fVerbose ); +extern ABC_DLL void Abc_NtkPrintStats( Abc_Ntk_t * pNtk, int fFactored, int fSaveBest, int fDumpResult, int fUseLutLib, int fPrintMuxes, int fPower, int fGlitch, int fSkipBuf, int fSkipSmall, int fPrintMem ); +extern ABC_DLL void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk, int fPrintFlops ); +extern ABC_DLL void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkPrintFanio( FILE * pFile, Abc_Ntk_t * pNtk, int fUseFanio, int fUsePio, int fUseSupp, int fUseCone ); +extern ABC_DLL void Abc_NtkPrintFanioNew( FILE * pFile, Abc_Ntk_t * pNtk, int fMffc ); +extern ABC_DLL void Abc_NodePrintFanio( FILE * pFile, Abc_Obj_t * pNode ); +extern ABC_DLL void Abc_NtkPrintFactor( FILE * pFile, Abc_Ntk_t * pNtk, int fUseRealNames ); +extern ABC_DLL void Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames ); +extern ABC_DLL void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile, int fListNodes, int fOutputs, int fVerbose ); +extern ABC_DLL void Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode ); +extern ABC_DLL void Abc_NtkPrintSkews( FILE * pFile, Abc_Ntk_t * pNtk, int fPrintAll ); +extern ABC_DLL void Abc_ObjPrint( FILE * pFile, Abc_Obj_t * pObj ); +extern ABC_DLL void Abc_NtkShow6VarFunc( char * pF0, char * pF1 ); +/*=== abcProve.c ==========================================================*/ +extern ABC_DLL int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, void * pParams ); +extern ABC_DLL int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars ); +/*=== abcRec3.c ==========================================================*/ +extern ABC_DLL void Abc_NtkRecStart3( Gia_Man_t * p, int nVars, int nCuts, int fFuncOnly, int fVerbose ); +extern ABC_DLL void Abc_NtkRecStop3(); +extern ABC_DLL void Abc_NtkRecAdd3( Abc_Ntk_t * pNtk, int fUseSOPB ); +extern ABC_DLL void Abc_NtkRecPs3(int fPrintLib); +extern ABC_DLL Gia_Man_t * Abc_NtkRecGetGia3(); +extern ABC_DLL int Abc_NtkRecIsRunning3(); +extern ABC_DLL void Abc_NtkRecLibMerge3(Gia_Man_t * pGia); +extern ABC_DLL int Abc_NtkRecInputNum3(); +//extern ABC_DLL void Abc_NtkRecFilter3(int nLimit); +/*=== abcReconv.c ==========================================================*/ +extern ABC_DLL Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax, int nNodeFanStop, int nConeFanStop ); +extern ABC_DLL void Abc_NtkManCutStop( Abc_ManCut_t * p ); +extern ABC_DLL Vec_Ptr_t * Abc_NtkManCutReadCutLarge( Abc_ManCut_t * p ); +extern ABC_DLL Vec_Ptr_t * Abc_NtkManCutReadCutSmall( Abc_ManCut_t * p ); +extern ABC_DLL Vec_Ptr_t * Abc_NtkManCutReadVisited( Abc_ManCut_t * p ); +extern ABC_DLL Vec_Ptr_t * Abc_NodeFindCut( Abc_ManCut_t * p, Abc_Obj_t * pRoot, int fContain ); +extern ABC_DLL void Abc_NodeConeCollect( Abc_Obj_t ** ppRoots, int nRoots, Vec_Ptr_t * vFanins, Vec_Ptr_t * vVisited, int fIncludeFanins ); +extern ABC_DLL Vec_Ptr_t * Abc_NodeCollectTfoCands( Abc_ManCut_t * p, Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins, int LevelMax ); +/*=== abcRefs.c ==========================================================*/ +extern ABC_DLL int Abc_NodeMffcSize( Abc_Obj_t * pNode ); +extern ABC_DLL int Abc_NodeMffcSizeSupp( Abc_Obj_t * pNode ); +extern ABC_DLL int Abc_NodeMffcSizeStop( Abc_Obj_t * pNode ); +extern ABC_DLL int Abc_NodeMffcLabelAig( Abc_Obj_t * pNode ); +extern ABC_DLL int Abc_NodeMffcLabel( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); +extern ABC_DLL void Abc_NodeMffcConeSupp( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp ); +extern ABC_DLL int Abc_NodeDeref_rec( Abc_Obj_t * pNode ); +extern ABC_DLL int Abc_NodeRef_rec( Abc_Obj_t * pNode ); +/*=== abcRefactor.c ==========================================================*/ +extern ABC_DLL int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nMinSaved, int nConeSizeMax, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose ); +/*=== abcRewrite.c ==========================================================*/ +extern ABC_DLL int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeros, int fVerbose, int fVeryVerbose, int fPlaceEnable ); +/*=== abcSat.c ==========================================================*/ +extern ABC_DLL int Abc_NtkMiterSat( Abc_Ntk_t * pNtk, ABC_INT64_T nConfLimit, ABC_INT64_T nInsLimit, int fVerbose, ABC_INT64_T * pNumConfs, ABC_INT64_T * pNumInspects ); +extern ABC_DLL void * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk, int fAllPrimes ); +/*=== abcSop.c ==========================================================*/ +extern ABC_DLL char * Abc_SopRegister( Mem_Flex_t * pMan, const char * pName ); +extern ABC_DLL char * Abc_SopStart( Mem_Flex_t * pMan, int nCubes, int nVars ); +extern ABC_DLL char * Abc_SopCreateConst0( Mem_Flex_t * pMan ); +extern ABC_DLL char * Abc_SopCreateConst1( Mem_Flex_t * pMan ); +extern ABC_DLL char * Abc_SopCreateAnd2( Mem_Flex_t * pMan, int fCompl0, int fCompl1 ); +extern ABC_DLL char * Abc_SopCreateAnd( Mem_Flex_t * pMan, int nVars, int * pfCompl ); +extern ABC_DLL char * Abc_SopCreateNand( Mem_Flex_t * pMan, int nVars ); +extern ABC_DLL char * Abc_SopCreateOr( Mem_Flex_t * pMan, int nVars, int * pfCompl ); +extern ABC_DLL char * Abc_SopCreateOrMultiCube( Mem_Flex_t * pMan, int nVars, int * pfCompl ); +extern ABC_DLL char * Abc_SopCreateNor( Mem_Flex_t * pMan, int nVars ); +extern ABC_DLL char * Abc_SopCreateXor( Mem_Flex_t * pMan, int nVars ); +extern ABC_DLL char * Abc_SopCreateXorSpecial( Mem_Flex_t * pMan, int nVars ); +extern ABC_DLL char * Abc_SopCreateNxor( Mem_Flex_t * pMan, int nVars ); +extern ABC_DLL char * Abc_SopCreateMux( Mem_Flex_t * pMan ); +extern ABC_DLL char * Abc_SopCreateInv( Mem_Flex_t * pMan ); +extern ABC_DLL char * Abc_SopCreateBuf( Mem_Flex_t * pMan ); +extern ABC_DLL char * Abc_SopCreateFromTruth( Mem_Flex_t * pMan, int nVars, unsigned * pTruth ); +extern ABC_DLL char * Abc_SopCreateFromIsop( Mem_Flex_t * pMan, int nVars, Vec_Int_t * vCover ); +extern ABC_DLL char * Abc_SopCreateFromTruthIsop( Mem_Flex_t * pMan, int nVars, word * pTruth, Vec_Int_t * vCover ); +extern ABC_DLL int Abc_SopGetCubeNum( char * pSop ); +extern ABC_DLL int Abc_SopGetLitNum( char * pSop ); +extern ABC_DLL int Abc_SopGetVarNum( char * pSop ); +extern ABC_DLL int Abc_SopGetPhase( char * pSop ); +extern ABC_DLL int Abc_SopGetIthCareLit( char * pSop, int i ); +extern ABC_DLL void Abc_SopComplement( char * pSop ); +extern ABC_DLL void Abc_SopComplementVar( char * pSop, int iVar ); +extern ABC_DLL int Abc_SopIsComplement( char * pSop ); +extern ABC_DLL int Abc_SopIsConst0( char * pSop ); +extern ABC_DLL int Abc_SopIsConst1( char * pSop ); +extern ABC_DLL int Abc_SopIsBuf( char * pSop ); +extern ABC_DLL int Abc_SopIsInv( char * pSop ); +extern ABC_DLL int Abc_SopIsAndType( char * pSop ); +extern ABC_DLL int Abc_SopIsOrType( char * pSop ); +extern ABC_DLL int Abc_SopIsExorType( char * pSop ); +extern ABC_DLL int Abc_SopCheck( char * pSop, int nFanins ); +extern ABC_DLL char * Abc_SopFromTruthBin( char * pTruth ); +extern ABC_DLL char * Abc_SopFromTruthHex( char * pTruth ); +extern ABC_DLL Vec_Ptr_t * Abc_SopFromTruthsBin( char * pTruth ); +extern ABC_DLL Vec_Ptr_t * Abc_SopFromTruthsHex( char * pTruth ); +extern ABC_DLL char * Abc_SopEncoderPos( Mem_Flex_t * pMan, int iValue, int nValues ); +extern ABC_DLL char * Abc_SopEncoderLog( Mem_Flex_t * pMan, int iBit, int nValues ); +extern ABC_DLL char * Abc_SopDecoderPos( Mem_Flex_t * pMan, int nValues ); +extern ABC_DLL char * Abc_SopDecoderLog( Mem_Flex_t * pMan, int nValues ); +extern ABC_DLL word Abc_SopToTruth( char * pSop, int nInputs ); +extern ABC_DLL void Abc_SopToTruth7( char * pSop, int nInputs, word r[2] ); +extern ABC_DLL void Abc_SopToTruthBig( char * pSop, int nInputs, word ** pVars, word * pCube, word * pRes ); +/*=== abcStrash.c ==========================================================*/ +extern ABC_DLL Abc_Ntk_t * Abc_NtkRestrash( Abc_Ntk_t * pNtk, int fCleanup ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkRestrashZero( Abc_Ntk_t * pNtk, int fCleanup ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, int fAllNodes, int fCleanup, int fRecord ); +extern ABC_DLL Abc_Obj_t * Abc_NodeStrash( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int fRecord ); +extern ABC_DLL int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fAddPos ); +extern ABC_DLL Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ); +/*=== abcSweep.c ==========================================================*/ +extern ABC_DLL int Abc_NtkSweep( Abc_Ntk_t * pNtk, int fVerbose ); +extern ABC_DLL int Abc_NtkCleanup( Abc_Ntk_t * pNtk, int fVerbose ); +extern ABC_DLL int Abc_NtkCleanupNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, int fVerbose ); +extern ABC_DLL int Abc_NtkCleanupSeq( Abc_Ntk_t * pNtk, int fLatchSweep, int fAutoSweep, int fVerbose ); +extern ABC_DLL int Abc_NtkSweepBufsInvs( Abc_Ntk_t * pNtk, int fVerbose ); +/*=== abcTiming.c ==========================================================*/ +extern ABC_DLL Abc_Time_t * Abc_NtkReadDefaultArrival( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Time_t * Abc_NtkReadDefaultRequired( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Time_t * Abc_NodeReadArrival( Abc_Obj_t * pNode ); +extern ABC_DLL Abc_Time_t * Abc_NodeReadRequired( Abc_Obj_t * pNode ); +extern ABC_DLL float Abc_NtkReadDefaultArrivalWorst( Abc_Ntk_t * pNtk ); +extern ABC_DLL float Abc_NtkReadDefaultRequiredWorst( Abc_Ntk_t * pNtk ); +extern ABC_DLL float Abc_NodeReadArrivalAve( Abc_Obj_t * pNode ); +extern ABC_DLL float Abc_NodeReadRequiredAve( Abc_Obj_t * pNode ); +extern ABC_DLL float Abc_NodeReadArrivalWorst( Abc_Obj_t * pNode ); +extern ABC_DLL float Abc_NodeReadRequiredWorst( Abc_Obj_t * pNode ); +extern ABC_DLL Abc_Time_t * Abc_NtkReadDefaultInputDrive( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Time_t * Abc_NtkReadDefaultOutputLoad( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Time_t * Abc_NodeReadInputDrive( Abc_Ntk_t * pNtk, int iPi ); +extern ABC_DLL Abc_Time_t * Abc_NodeReadOutputLoad( Abc_Ntk_t * pNtk, int iPo ); +extern ABC_DLL float Abc_NodeReadInputDriveWorst( Abc_Ntk_t * pNtk, int iPi ); +extern ABC_DLL float Abc_NodeReadOutputLoadWorst( Abc_Ntk_t * pNtk, int iPo ); +extern ABC_DLL void Abc_NtkTimeSetDefaultArrival( Abc_Ntk_t * pNtk, float Rise, float Fall ); +extern ABC_DLL void Abc_NtkTimeSetDefaultRequired( Abc_Ntk_t * pNtk, float Rise, float Fall ); +extern ABC_DLL void Abc_NtkTimeSetArrival( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall ); +extern ABC_DLL void Abc_NtkTimeSetRequired( Abc_Ntk_t * pNtk, int ObjId, float Rise, float Fall ); +extern ABC_DLL void Abc_NtkTimeSetDefaultInputDrive( Abc_Ntk_t * pNtk, float Rise, float Fall ); +extern ABC_DLL void Abc_NtkTimeSetDefaultOutputLoad( Abc_Ntk_t * pNtk, float Rise, float Fall ); +extern ABC_DLL void Abc_NtkTimeSetInputDrive( Abc_Ntk_t * pNtk, int PiNum, float Rise, float Fall ); +extern ABC_DLL void Abc_NtkTimeSetOutputLoad( Abc_Ntk_t * pNtk, int PoNum, float Rise, float Fall ); +extern ABC_DLL void Abc_NtkTimeInitialize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkOld ); +extern ABC_DLL void Abc_ManTimeStop( Abc_ManTime_t * p ); +extern ABC_DLL void Abc_ManTimeDup( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ); +extern ABC_DLL void Abc_NtkSetNodeLevelsArrival( Abc_Ntk_t * pNtk ); +extern ABC_DLL float * Abc_NtkGetCiArrivalFloats( Abc_Ntk_t * pNtk ); +extern ABC_DLL float * Abc_NtkGetCoRequiredFloats( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Time_t * Abc_NtkGetCiArrivalTimes( Abc_Ntk_t * pNtk ); +extern ABC_DLL Abc_Time_t * Abc_NtkGetCoRequiredTimes( Abc_Ntk_t * pNtk ); +extern ABC_DLL float Abc_NtkDelayTrace( Abc_Ntk_t * pNtk, Abc_Obj_t * pOut, Abc_Obj_t * pIn, int fPrint ); +extern ABC_DLL int Abc_ObjLevelNew( Abc_Obj_t * pObj ); +extern ABC_DLL int Abc_ObjReverseLevelNew( Abc_Obj_t * pObj ); +extern ABC_DLL int Abc_ObjRequiredLevel( Abc_Obj_t * pObj ); +extern ABC_DLL int Abc_ObjReverseLevel( Abc_Obj_t * pObj ); +extern ABC_DLL void Abc_ObjSetReverseLevel( Abc_Obj_t * pObj, int LevelR ); +extern ABC_DLL void Abc_NtkStartReverseLevels( Abc_Ntk_t * pNtk, int nMaxLevelIncrease ); +extern ABC_DLL void Abc_NtkStopReverseLevels( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkUpdateLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ); +extern ABC_DLL void Abc_NtkUpdateReverseLevel( Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ); +extern ABC_DLL void Abc_NtkUpdate( Abc_Obj_t * pObj, Abc_Obj_t * pObjNew, Vec_Vec_t * vLevels ); +/*=== abcUtil.c ==========================================================*/ +extern ABC_DLL void * Abc_NtkAttrFree( Abc_Ntk_t * pNtk, int Attr, int fFreeMan ); +extern ABC_DLL void Abc_NtkOrderCisCos( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkGetCubeNum( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkGetCubePairNum( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkGetLitNum( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkGetLitFactNum( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkGetBddNodeNum( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkGetAigNodeNum( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkGetClauseNum( Abc_Ntk_t * pNtk ); +extern ABC_DLL double Abc_NtkGetMappedArea( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkGetExorNum( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkGetMuxNum( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkGetBufNum( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkGetLargeNodeNum( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkGetChoiceNum( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkGetFaninMax( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkGetFanoutMax( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkGetTotalFanins( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkCleanCopy( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkCleanCopy_rec( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkCleanData( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkFillTemp( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkCountCopy( Abc_Ntk_t * pNtk ); +extern ABC_DLL Vec_Ptr_t * Abc_NtkSaveCopy( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkLoadCopy( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCopies ); +extern ABC_DLL void Abc_NtkCleanNext( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkCleanNext_rec( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkCleanMarkA( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkCleanMarkB( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkCleanMarkC( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkCleanMarkAB( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkCleanMarkABC( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NodeFindFanin( Abc_Obj_t * pNode, Abc_Obj_t * pFanin ); +extern ABC_DLL Abc_Obj_t * Abc_NodeFindCoFanout( Abc_Obj_t * pNode ); +extern ABC_DLL Abc_Obj_t * Abc_NodeFindNonCoFanout( Abc_Obj_t * pNode ); +extern ABC_DLL Abc_Obj_t * Abc_NodeHasUniqueCoFanout( Abc_Obj_t * pNode ); +extern ABC_DLL int Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkLogicMakeSimpleCos( Abc_Ntk_t * pNtk, int fDuplicate ); +extern ABC_DLL void Abc_VecObjPushUniqueOrderByLevel( Vec_Ptr_t * p, Abc_Obj_t * pNode ); +extern ABC_DLL int Abc_NodeIsExorType( Abc_Obj_t * pNode ); +extern ABC_DLL int Abc_NodeIsMuxType( Abc_Obj_t * pNode ); +extern ABC_DLL int Abc_NodeIsMuxControlType( Abc_Obj_t * pNode ); +extern ABC_DLL Abc_Obj_t * Abc_NodeRecognizeMux( Abc_Obj_t * pNode, Abc_Obj_t ** ppNodeT, Abc_Obj_t ** ppNodeE ); +extern ABC_DLL int Abc_NtkPrepareTwoNtks( FILE * pErr, Abc_Ntk_t * pNtk, char ** argv, int argc, Abc_Ntk_t ** ppNtk1, Abc_Ntk_t ** ppNtk2, int * pfDelete1, int * pfDelete2, int fCheck ); +extern ABC_DLL void Abc_NodeCollectFanins( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); +extern ABC_DLL void Abc_NodeCollectFanouts( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ); +extern ABC_DLL Vec_Ptr_t * Abc_NtkCollectLatches( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NodeCompareLevelsIncrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ); +extern ABC_DLL int Abc_NodeCompareLevelsDecrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ); +extern ABC_DLL Vec_Int_t * Abc_NtkFanoutCounts( Abc_Ntk_t * pNtk ); +extern ABC_DLL Vec_Ptr_t * Abc_NtkCollectObjects( Abc_Ntk_t * pNtk ); +extern ABC_DLL Vec_Int_t * Abc_NtkGetCiIds( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkReassignIds( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_ObjPointerCompare( void ** pp1, void ** pp2 ); +extern ABC_DLL void Abc_NtkTransferCopy( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkInvertConstraints( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkPrintCiLevels( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkReverseTopoOrder( Abc_Ntk_t * pNtk ); +extern ABC_DLL int Abc_NtkIsTopo( Abc_Ntk_t * pNtk ); +extern ABC_DLL void Abc_NtkTransferPhases( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk ); +extern ABC_DLL Gia_Man_t * Abc_SopSynthesizeOne( char * pSop, int fClp ); + + + +/*=== abcVerify.c ==========================================================*/ +extern ABC_DLL int * Abc_NtkVerifyGetCleanModel( Abc_Ntk_t * pNtk, int nFrames ); +extern ABC_DLL int * Abc_NtkVerifySimulatePattern( Abc_Ntk_t * pNtk, int * pModel ); +extern ABC_DLL int Abc_NtkIsTrueCex( Abc_Ntk_t * pNtk, Abc_Cex_t * pCex ); +extern ABC_DLL int Abc_NtkIsValidCex( Abc_Ntk_t * pNtk, Abc_Cex_t * pCex ); + + + +ABC_NAMESPACE_HEADER_END + + + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// diff --git a/yosys/abc/src/base/abc/abcAig.c b/yosys/abc/src/base/abc/abcAig.c new file mode 100644 index 00000000000..e3f3ce457be --- /dev/null +++ b/yosys/abc/src/base/abc/abcAig.c @@ -0,0 +1,1522 @@ +/**CFile**************************************************************** + + FileName [abcAig.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Simple structural hashing package.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcAig.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +ABC_NAMESPACE_IMPL_START + +/* + AIG is an And-Inv Graph with structural hashing. + It is always structurally hashed. It means that at any time: + - for each AND gate, there are no other AND gates with the same children + - the constants are propagated + - there is no single-input nodes (inverters/buffers) + Additionally the following invariants are satisfied: + - there are no dangling nodes (the nodes without fanout) + - the level of each AND gate reflects the levels of this fanins + - the EXOR-status of each node is up-to-date + - the AND nodes are in the topological order + - the constant 1 node has always number 0 in the object list + The operations that are performed on AIGs: + - building new nodes (Abc_AigAnd) + - performing elementary Boolean operations (Abc_AigOr, Abc_AigXor, etc) + - replacing one node by another (Abc_AigReplace) + - propagating constants (Abc_AigReplace) + When AIG is duplicated, the new graph is structurally hashed too. + If this repeated hashing leads to fewer nodes, it means the original + AIG was not strictly hashed (one of the conditions above is violated). +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +// the simple AIG manager +struct Abc_Aig_t_ +{ + Abc_Ntk_t * pNtkAig; // the AIG network + Abc_Obj_t * pConst1; // the constant 1 object (not a node!) + Abc_Obj_t ** pBins; // the table bins + int nBins; // the size of the table + int nEntries; // the total number of entries in the table + Vec_Ptr_t * vNodes; // the temporary array of nodes + Vec_Ptr_t * vStackReplaceOld; // the nodes to be replaced + Vec_Ptr_t * vStackReplaceNew; // the nodes to be used for replacement + Vec_Vec_t * vLevels; // the nodes to be updated + Vec_Vec_t * vLevelsR; // the nodes to be updated + Vec_Ptr_t * vAddedCells; // the added nodes + Vec_Ptr_t * vUpdatedNets; // the nodes whose fanouts have changed + + int nStrash0; + int nStrash1; + int nStrash5; + int nStrash2; +}; + +// iterators through the entries in the linked lists of nodes +#define Abc_AigBinForEachEntry( pBin, pEnt ) \ + for ( pEnt = pBin; \ + pEnt; \ + pEnt = pEnt->pNext ) +#define Abc_AigBinForEachEntrySafe( pBin, pEnt, pEnt2 ) \ + for ( pEnt = pBin, \ + pEnt2 = pEnt? pEnt->pNext: NULL; \ + pEnt; \ + pEnt = pEnt2, \ + pEnt2 = pEnt? pEnt->pNext: NULL ) + +// hash key for the structural hash table +//static inline unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) { return ((unsigned)(p0) + (unsigned)(p1) * 12582917) % TableSize; } +//static inline unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) { return ((unsigned)((a)->Id + (b)->Id) * ((a)->Id + (b)->Id + 1) / 2) % TableSize; } + +// hashing the node +static unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) +{ + unsigned Key = 0; + Key ^= Abc_ObjRegular(p0)->Id * 7937; + Key ^= Abc_ObjRegular(p1)->Id * 2971; + Key ^= Abc_ObjIsComplement(p0) * 911; + Key ^= Abc_ObjIsComplement(p1) * 353; + return Key % TableSize; +} + +// structural hash table procedures +static Abc_Obj_t * Abc_AigAndCreate( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ); +static Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, Abc_Obj_t * pAnd ); +static void Abc_AigAndDelete( Abc_Aig_t * pMan, Abc_Obj_t * pThis ); +static void Abc_AigResize( Abc_Aig_t * pMan ); +// incremental AIG procedures +static void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel ); +static void Abc_AigUpdateLevel_int( Abc_Aig_t * pMan ); +static void Abc_AigUpdateLevelR_int( Abc_Aig_t * pMan ); +static void Abc_AigRemoveFromLevelStructure( Vec_Vec_t * vStruct, Abc_Obj_t * pNode ); +static void Abc_AigRemoveFromLevelStructureR( Vec_Vec_t * vStruct, Abc_Obj_t * pNode ); + + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Allocates the local AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtkAig ) +{ + Abc_Aig_t * pMan; + // start the manager + pMan = ABC_ALLOC( Abc_Aig_t, 1 ); + memset( pMan, 0, sizeof(Abc_Aig_t) ); + // allocate the table + pMan->nBins = Abc_PrimeCudd( 10000 ); + pMan->pBins = ABC_ALLOC( Abc_Obj_t *, pMan->nBins ); + memset( pMan->pBins, 0, sizeof(Abc_Obj_t *) * pMan->nBins ); + pMan->vNodes = Vec_PtrAlloc( 100 ); + pMan->vLevels = Vec_VecAlloc( 100 ); + pMan->vLevelsR = Vec_VecAlloc( 100 ); + pMan->vStackReplaceOld = Vec_PtrAlloc( 100 ); + pMan->vStackReplaceNew = Vec_PtrAlloc( 100 ); + // create the constant node + assert( pNtkAig->vObjs->nSize == 0 ); + pMan->pConst1 = Abc_NtkCreateObj( pNtkAig, ABC_OBJ_NODE ); + pMan->pConst1->Type = ABC_OBJ_CONST1; + pMan->pConst1->fPhase = 1; + pNtkAig->nObjCounts[ABC_OBJ_NODE]--; + // save the current network + pMan->pNtkAig = pNtkAig; + return pMan; +} + +/**Function************************************************************* + + Synopsis [Deallocates the local AIG manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigFree( Abc_Aig_t * pMan ) +{ + assert( Vec_PtrSize( pMan->vStackReplaceOld ) == 0 ); + assert( Vec_PtrSize( pMan->vStackReplaceNew ) == 0 ); + // free the table + if ( pMan->vAddedCells ) + Vec_PtrFree( pMan->vAddedCells ); + if ( pMan->vUpdatedNets ) + Vec_PtrFree( pMan->vUpdatedNets ); + Vec_VecFree( pMan->vLevels ); + Vec_VecFree( pMan->vLevelsR ); + Vec_PtrFree( pMan->vStackReplaceOld ); + Vec_PtrFree( pMan->vStackReplaceNew ); + Vec_PtrFree( pMan->vNodes ); + ABC_FREE( pMan->pBins ); + ABC_FREE( pMan ); +} + +/**Function************************************************************* + + Synopsis [Returns the number of dangling nodes removed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_AigCleanup( Abc_Aig_t * pMan ) +{ + Vec_Ptr_t * vDangles; + Abc_Obj_t * pAnd; + int i, nNodesOld; +// printf( "Strash0 = %d. Strash1 = %d. Strash100 = %d. StrashM = %d.\n", +// pMan->nStrash0, pMan->nStrash1, pMan->nStrash5, pMan->nStrash2 ); + nNodesOld = pMan->nEntries; + // collect the AND nodes that do not fanout + vDangles = Vec_PtrAlloc( 100 ); + for ( i = 0; i < pMan->nBins; i++ ) + Abc_AigBinForEachEntry( pMan->pBins[i], pAnd ) + if ( Abc_ObjFanoutNum(pAnd) == 0 ) + Vec_PtrPush( vDangles, pAnd ); + // process the dangling nodes and their MFFCs + Vec_PtrForEachEntry( Abc_Obj_t *, vDangles, pAnd, i ) + Abc_AigDeleteNode( pMan, pAnd ); + Vec_PtrFree( vDangles ); + return nNodesOld - pMan->nEntries; +} + +/**Function************************************************************* + + Synopsis [Makes sure that every node in the table is in the network and vice versa.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_AigCheck( Abc_Aig_t * pMan ) +{ + Abc_Obj_t * pObj, * pAnd; + int i, nFanins, Counter; + Abc_NtkForEachNode( pMan->pNtkAig, pObj, i ) + { + nFanins = Abc_ObjFaninNum(pObj); + if ( nFanins == 0 ) + { + if ( !Abc_AigNodeIsConst(pObj) ) + { + printf( "Abc_AigCheck: The AIG has non-standard constant nodes.\n" ); + return 0; + } + continue; + } + if ( nFanins == 1 ) + { + printf( "Abc_AigCheck: The AIG has single input nodes.\n" ); + return 0; + } + if ( nFanins > 2 ) + { + printf( "Abc_AigCheck: The AIG has non-standard nodes.\n" ); + return 0; + } + if ( pObj->Level != 1 + (unsigned)Abc_MaxInt( Abc_ObjFanin0(pObj)->Level, Abc_ObjFanin1(pObj)->Level ) ) + printf( "Abc_AigCheck: Node \"%s\" has level that does not agree with the fanin levels.\n", Abc_ObjName(pObj) ); + pAnd = Abc_AigAndLookup( pMan, Abc_ObjChild0(pObj), Abc_ObjChild1(pObj) ); + if ( pAnd != pObj ) + printf( "Abc_AigCheck: Node \"%s\" is not in the structural hashing table.\n", Abc_ObjName(pObj) ); + } + // count the number of nodes in the table + Counter = 0; + for ( i = 0; i < pMan->nBins; i++ ) + Abc_AigBinForEachEntry( pMan->pBins[i], pAnd ) + Counter++; + if ( Counter != Abc_NtkNodeNum(pMan->pNtkAig) ) + { + printf( "Abc_AigCheck: The number of nodes in the structural hashing table is wrong.\n" ); + return 0; + } + // if the node is a choice node, nodes in its class should not have fanouts + Abc_NtkForEachNode( pMan->pNtkAig, pObj, i ) + if ( Abc_AigNodeIsChoice(pObj) ) + for ( pAnd = (Abc_Obj_t *)pObj->pData; pAnd; pAnd = (Abc_Obj_t *)pAnd->pData ) + if ( Abc_ObjFanoutNum(pAnd) > 0 ) + { + printf( "Abc_AigCheck: Representative %s", Abc_ObjName(pAnd) ); + printf( " of choice node %s has %d fanouts.\n", Abc_ObjName(pObj), Abc_ObjFanoutNum(pAnd) ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Computes the number of logic levels not counting PIs/POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_AigLevel( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, LevelsMax; + assert( Abc_NtkIsStrash(pNtk) ); + if ( pNtk->nBarBufs ) + return Abc_NtkLevel( pNtk ); + // perform the traversal + LevelsMax = 0; + Abc_NtkForEachCo( pNtk, pNode, i ) + if ( LevelsMax < (int)Abc_ObjFanin0(pNode)->Level ) + LevelsMax = (int)Abc_ObjFanin0(pNode)->Level; + return LevelsMax; +} + + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigAndCreate( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) +{ + Abc_Obj_t * pAnd; + unsigned Key; + // check if it is a good time for table resizing + if ( pMan->nEntries > 2 * pMan->nBins ) + Abc_AigResize( pMan ); + // order the arguments + if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id ) + pAnd = p0, p0 = p1, p1 = pAnd; + // create the new node + pAnd = Abc_NtkCreateNode( pMan->pNtkAig ); + Abc_ObjAddFanin( pAnd, p0 ); + Abc_ObjAddFanin( pAnd, p1 ); + // set the level of the new node + pAnd->Level = 1 + Abc_MaxInt( Abc_ObjRegular(p0)->Level, Abc_ObjRegular(p1)->Level ); + pAnd->fExor = Abc_NodeIsExorType(pAnd); + pAnd->fPhase = (Abc_ObjIsComplement(p0) ^ Abc_ObjRegular(p0)->fPhase) & (Abc_ObjIsComplement(p1) ^ Abc_ObjRegular(p1)->fPhase); + // add the node to the corresponding linked list in the table + Key = Abc_HashKey2( p0, p1, pMan->nBins ); + pAnd->pNext = pMan->pBins[Key]; + pMan->pBins[Key] = pAnd; + pMan->nEntries++; + // create the cuts if defined +// if ( pAnd->pNtk->pManCut ) +// Abc_NodeGetCuts( pAnd->pNtk->pManCut, pAnd ); + pAnd->pCopy = NULL; + // add the node to the list of updated nodes + if ( pMan->vAddedCells ) + Vec_PtrPush( pMan->vAddedCells, pAnd ); + return pAnd; +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, Abc_Obj_t * pAnd ) +{ + Abc_Obj_t * pTemp; + unsigned Key; + assert( !Abc_ObjIsComplement(pAnd) ); + // order the arguments + if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id ) + pTemp = p0, p0 = p1, p1 = pTemp; + // create the new node + Abc_ObjAddFanin( pAnd, p0 ); + Abc_ObjAddFanin( pAnd, p1 ); + // set the level of the new node + pAnd->Level = 1 + Abc_MaxInt( Abc_ObjRegular(p0)->Level, Abc_ObjRegular(p1)->Level ); + pAnd->fExor = Abc_NodeIsExorType(pAnd); + // add the node to the corresponding linked list in the table + Key = Abc_HashKey2( p0, p1, pMan->nBins ); + pAnd->pNext = pMan->pBins[Key]; + pMan->pBins[Key] = pAnd; + pMan->nEntries++; + // create the cuts if defined +// if ( pAnd->pNtk->pManCut ) +// Abc_NodeGetCuts( pAnd->pNtk->pManCut, pAnd ); + pAnd->pCopy = NULL; + // add the node to the list of updated nodes +// if ( pMan->vAddedCells ) +// Vec_PtrPush( pMan->vAddedCells, pAnd ); + return pAnd; +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) +{ + Abc_Obj_t * pAnd, * pConst1; + unsigned Key; + assert( Abc_ObjRegular(p0)->pNtk->pManFunc == pMan ); + assert( Abc_ObjRegular(p1)->pNtk->pManFunc == pMan ); + // check for trivial cases + pConst1 = Abc_AigConst1(pMan->pNtkAig); + if ( p0 == p1 ) + return p0; + if ( p0 == Abc_ObjNot(p1) ) + return Abc_ObjNot(pConst1); + if ( Abc_ObjRegular(p0) == pConst1 ) + { + if ( p0 == pConst1 ) + return p1; + return Abc_ObjNot(pConst1); + } + if ( Abc_ObjRegular(p1) == pConst1 ) + { + if ( p1 == pConst1 ) + return p0; + return Abc_ObjNot(pConst1); + } +/* + { + int nFans0 = Abc_ObjFanoutNum( Abc_ObjRegular(p0) ); + int nFans1 = Abc_ObjFanoutNum( Abc_ObjRegular(p1) ); + if ( nFans0 == 0 || nFans1 == 0 ) + pMan->nStrash0++; + else if ( nFans0 == 1 || nFans1 == 1 ) + pMan->nStrash1++; + else if ( nFans0 <= 100 && nFans1 <= 100 ) + pMan->nStrash5++; + else + pMan->nStrash2++; + } +*/ + { + int nFans0 = Abc_ObjFanoutNum( Abc_ObjRegular(p0) ); + int nFans1 = Abc_ObjFanoutNum( Abc_ObjRegular(p1) ); + if ( nFans0 == 0 || nFans1 == 0 ) + return NULL; + } + + // order the arguments + if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id ) + pAnd = p0, p0 = p1, p1 = pAnd; + // get the hash key for these two nodes + Key = Abc_HashKey2( p0, p1, pMan->nBins ); + // find the matching node in the table + Abc_AigBinForEachEntry( pMan->pBins[Key], pAnd ) + if ( p0 == Abc_ObjChild0(pAnd) && p1 == Abc_ObjChild1(pAnd) ) + { +// assert( Abc_ObjFanoutNum(Abc_ObjRegular(p0)) && Abc_ObjFanoutNum(p1) ); + return pAnd; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Returns the gate implementing EXOR of the two arguments if it exists.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigXorLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, int * pType ) +{ + Abc_Obj_t * pNode1, * pNode2, * pNode; + // set the flag to zero + if ( pType ) *pType = 0; + // check the case of XOR(a,b) = OR(ab, a'b')' + if ( (pNode1 = Abc_AigAndLookup(pMan, Abc_ObjNot(p0), Abc_ObjNot(p1))) && + (pNode2 = Abc_AigAndLookup(pMan, p0, p1)) ) + { + pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); + if ( pNode && pType ) *pType = 1; + return pNode; + } + // check the case of XOR(a,b) = OR(a'b, ab') + if ( (pNode1 = Abc_AigAndLookup(pMan, p0, Abc_ObjNot(p1))) && + (pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(p0), p1)) ) + { + pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); + return pNode? Abc_ObjNot(pNode) : NULL; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Returns the gate implementing EXOR of the two arguments if it exists.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigMuxLookup( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * pT, Abc_Obj_t * pE, int * pType ) +{ + Abc_Obj_t * pNode1, * pNode2, * pNode; + // set the flag to zero + if ( pType ) *pType = 0; + // check the case of MUX(c,t,e) = OR(ct', c'e')' + if ( (pNode1 = Abc_AigAndLookup(pMan, pC, Abc_ObjNot(pT))) && + (pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(pC), Abc_ObjNot(pE))) ) + { + pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); + if ( pNode && pType ) *pType = 1; + return pNode; + } + // check the case of MUX(c,t,e) = OR(ct, c'e) + if ( (pNode1 = Abc_AigAndLookup(pMan, pC, pT)) && + (pNode2 = Abc_AigAndLookup(pMan, Abc_ObjNot(pC), pE)) ) + { + pNode = Abc_AigAndLookup( pMan, Abc_ObjNot(pNode1), Abc_ObjNot(pNode2) ); + return pNode? Abc_ObjNot(pNode) : NULL; + } + return NULL; +} + +/**Function************************************************************* + + Synopsis [Deletes an AIG node from the hash table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigAndDelete( Abc_Aig_t * pMan, Abc_Obj_t * pThis ) +{ + Abc_Obj_t * pAnd, * pAnd0, * pAnd1, ** ppPlace; + unsigned Key; + assert( !Abc_ObjIsComplement(pThis) ); + assert( Abc_ObjIsNode(pThis) ); + assert( Abc_ObjFaninNum(pThis) == 2 ); + assert( pMan->pNtkAig == pThis->pNtk ); + // get the hash key for these two nodes + pAnd0 = Abc_ObjRegular( Abc_ObjChild0(pThis) ); + pAnd1 = Abc_ObjRegular( Abc_ObjChild1(pThis) ); + Key = Abc_HashKey2( Abc_ObjChild0(pThis), Abc_ObjChild1(pThis), pMan->nBins ); + // find the matching node in the table + ppPlace = pMan->pBins + Key; + Abc_AigBinForEachEntry( pMan->pBins[Key], pAnd ) + { + if ( pAnd != pThis ) + { + ppPlace = &pAnd->pNext; + continue; + } + *ppPlace = pAnd->pNext; + break; + } + assert( pAnd == pThis ); + pMan->nEntries--; + // delete the cuts if defined + if ( pThis->pNtk->pManCut ) + Abc_NodeFreeCuts( pThis->pNtk->pManCut, pThis ); +} + +/**Function************************************************************* + + Synopsis [Resizes the hash table of AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigResize( Abc_Aig_t * pMan ) +{ + Abc_Obj_t ** pBinsNew; + Abc_Obj_t * pEnt, * pEnt2; + int nBinsNew, Counter, i; + abctime clk; + unsigned Key; + +clk = Abc_Clock(); + // get the new table size + nBinsNew = Abc_PrimeCudd( 3 * pMan->nBins ); + // allocate a new array + pBinsNew = ABC_ALLOC( Abc_Obj_t *, nBinsNew ); + memset( pBinsNew, 0, sizeof(Abc_Obj_t *) * nBinsNew ); + // rehash the entries from the old table + Counter = 0; + for ( i = 0; i < pMan->nBins; i++ ) + Abc_AigBinForEachEntrySafe( pMan->pBins[i], pEnt, pEnt2 ) + { + Key = Abc_HashKey2( Abc_ObjChild0(pEnt), Abc_ObjChild1(pEnt), nBinsNew ); + pEnt->pNext = pBinsNew[Key]; + pBinsNew[Key] = pEnt; + Counter++; + } + assert( Counter == pMan->nEntries ); +// printf( "Increasing the structural table size from %6d to %6d. ", pMan->nBins, nBinsNew ); +// ABC_PRT( "Time", Abc_Clock() - clk ); + // replace the table and the parameters + ABC_FREE( pMan->pBins ); + pMan->pBins = pBinsNew; + pMan->nBins = nBinsNew; +} + +/**Function************************************************************* + + Synopsis [Resizes the hash table of AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigRehash( Abc_Aig_t * pMan ) +{ + Abc_Obj_t ** pBinsNew; + Abc_Obj_t * pEnt, * pEnt2; + int * pArray; + unsigned Key; + int Counter, Temp, i; + + // allocate a new array + pBinsNew = ABC_ALLOC( Abc_Obj_t *, pMan->nBins ); + memset( pBinsNew, 0, sizeof(Abc_Obj_t *) * pMan->nBins ); + // rehash the entries from the old table + Counter = 0; + for ( i = 0; i < pMan->nBins; i++ ) + Abc_AigBinForEachEntrySafe( pMan->pBins[i], pEnt, pEnt2 ) + { + // swap the fanins if needed + pArray = pEnt->vFanins.pArray; + if ( pArray[0] > pArray[1] ) + { + Temp = pArray[0]; + pArray[0] = pArray[1]; + pArray[1] = Temp; + Temp = pEnt->fCompl0; + pEnt->fCompl0 = pEnt->fCompl1; + pEnt->fCompl1 = Temp; + } + // rehash the node + Key = Abc_HashKey2( Abc_ObjChild0(pEnt), Abc_ObjChild1(pEnt), pMan->nBins ); + pEnt->pNext = pBinsNew[Key]; + pBinsNew[Key] = pEnt; + Counter++; + } + assert( Counter == pMan->nEntries ); + // replace the table and the parameters + ABC_FREE( pMan->pBins ); + pMan->pBins = pBinsNew; +} + + + + + + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigConst1( Abc_Ntk_t * pNtk ) +{ + assert( Abc_NtkIsStrash(pNtk) ); + return ((Abc_Aig_t *)pNtk->pManFunc)->pConst1; +} + +/**Function************************************************************* + + Synopsis [Performs canonicization step.] + + Description [The argument nodes can be complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigAnd( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) +{ + Abc_Obj_t * pAnd; + if ( (pAnd = Abc_AigAndLookup( pMan, p0, p1 )) ) + return pAnd; + return Abc_AigAndCreate( pMan, p0, p1 ); +} + +/**Function************************************************************* + + Synopsis [Implements Boolean OR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigOr( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) +{ + return Abc_ObjNot( Abc_AigAnd( pMan, Abc_ObjNot(p0), Abc_ObjNot(p1) ) ); +} + +/**Function************************************************************* + + Synopsis [Implements Boolean XOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigXor( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 ) +{ + return Abc_AigOr( pMan, Abc_AigAnd(pMan, p0, Abc_ObjNot(p1)), + Abc_AigAnd(pMan, p1, Abc_ObjNot(p0)) ); +} + +/**Function************************************************************* + + Synopsis [Implements Boolean XOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigMux( Abc_Aig_t * pMan, Abc_Obj_t * pC, Abc_Obj_t * p1, Abc_Obj_t * p0 ) +{ + return Abc_AigOr( pMan, Abc_AigAnd(pMan, pC, p1), Abc_AigAnd(pMan, Abc_ObjNot(pC), p0) ); +} + +/**Function************************************************************* + + Synopsis [Implements the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigMiter_rec( Abc_Aig_t * pMan, Abc_Obj_t ** ppObjs, int nObjs ) +{ + Abc_Obj_t * pObj1, * pObj2; + if ( nObjs == 1 ) + return ppObjs[0]; + pObj1 = Abc_AigMiter_rec( pMan, ppObjs, nObjs/2 ); + pObj2 = Abc_AigMiter_rec( pMan, ppObjs + nObjs/2, nObjs - nObjs/2 ); + return Abc_AigOr( pMan, pObj1, pObj2 ); +} + +/**Function************************************************************* + + Synopsis [Implements the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigMiter( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs, int fImplic ) +{ + int i; + if ( vPairs->nSize == 0 ) + return Abc_ObjNot( Abc_AigConst1(pMan->pNtkAig) ); + assert( vPairs->nSize % 2 == 0 ); + // go through the cubes of the node's SOP + if ( fImplic ) + { + for ( i = 0; i < vPairs->nSize; i += 2 ) + vPairs->pArray[i/2] = Abc_AigAnd( pMan, (Abc_Obj_t *)vPairs->pArray[i], Abc_ObjNot((Abc_Obj_t *)vPairs->pArray[i+1]) ); + } + else + { + for ( i = 0; i < vPairs->nSize; i += 2 ) + vPairs->pArray[i/2] = Abc_AigXor( pMan, (Abc_Obj_t *)vPairs->pArray[i], (Abc_Obj_t *)vPairs->pArray[i+1] ); + } + vPairs->nSize = vPairs->nSize/2; + return Abc_AigMiter_rec( pMan, (Abc_Obj_t **)vPairs->pArray, vPairs->nSize ); +} + +/**Function************************************************************* + + Synopsis [Implements the miter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_AigMiter2( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs ) +{ + Abc_Obj_t * pMiter, * pXor; + int i; + assert( vPairs->nSize % 2 == 0 ); + // go through the cubes of the node's SOP + pMiter = Abc_ObjNot( Abc_AigConst1(pMan->pNtkAig) ); + for ( i = 0; i < vPairs->nSize; i += 2 ) + { + pXor = Abc_AigXor( pMan, (Abc_Obj_t *)vPairs->pArray[i], (Abc_Obj_t *)vPairs->pArray[i+1] ); + pMiter = Abc_AigOr( pMan, pMiter, pXor ); + } + return pMiter; +} + + + + +/**Function************************************************************* + + Synopsis [Replaces one AIG node by the other.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel ) +{ + assert( Vec_PtrSize(pMan->vStackReplaceOld) == 0 ); + assert( Vec_PtrSize(pMan->vStackReplaceNew) == 0 ); + Vec_PtrPush( pMan->vStackReplaceOld, pOld ); + Vec_PtrPush( pMan->vStackReplaceNew, pNew ); + assert( !Abc_ObjIsComplement(pOld) ); + // process the replacements + while ( Vec_PtrSize(pMan->vStackReplaceOld) ) + { + pOld = (Abc_Obj_t *)Vec_PtrPop( pMan->vStackReplaceOld ); + pNew = (Abc_Obj_t *)Vec_PtrPop( pMan->vStackReplaceNew ); + if ( Abc_ObjFanoutNum(pOld) == 0 ) + //return 0; + continue; + Abc_AigReplace_int( pMan, pOld, pNew, fUpdateLevel ); + } + if ( fUpdateLevel ) + { + Abc_AigUpdateLevel_int( pMan ); + if ( pMan->pNtkAig->vLevelsR ) + Abc_AigUpdateLevelR_int( pMan ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Performs internal replacement step.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigReplace_int( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew, int fUpdateLevel ) +{ + Abc_Obj_t * pFanin1, * pFanin2, * pFanout, * pFanoutNew, * pFanoutFanout; + int k, v, iFanin; + // make sure the old node is regular and has fanouts + // (the new node can be complemented and can have fanouts) + assert( !Abc_ObjIsComplement(pOld) ); + assert( Abc_ObjFanoutNum(pOld) > 0 ); + // look at the fanouts of old node + Abc_NodeCollectFanouts( pOld, pMan->vNodes ); + Vec_PtrForEachEntry( Abc_Obj_t *, pMan->vNodes, pFanout, k ) + { + if ( Abc_ObjIsCo(pFanout) ) + { + pFanin1 = Abc_ObjRegular( pNew ); + if ( pFanin1->fMarkB ) + Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pFanin1 ); + if ( fUpdateLevel && pMan->pNtkAig->vLevelsR ) + { + Abc_ObjSetReverseLevel( pFanin1, Abc_ObjReverseLevel(pOld) ); + assert( pFanin1->fMarkB == 0 ); + if ( !Abc_ObjIsCi(pFanin1) ) + { + pFanin1->fMarkB = 1; + Vec_VecPush( pMan->vLevelsR, Abc_ObjReverseLevel(pFanin1), pFanin1 ); + } + } + Abc_ObjPatchFanin( pFanout, pOld, pNew ); + continue; + } + // find the old node as a fanin of this fanout + iFanin = Vec_IntFind( &pFanout->vFanins, pOld->Id ); + assert( iFanin == 0 || iFanin == 1 ); + // get the new fanin + pFanin1 = Abc_ObjNotCond( pNew, Abc_ObjFaninC(pFanout, iFanin) ); + assert( Abc_ObjRegular(pFanin1) != pFanout ); + // get another fanin + pFanin2 = Abc_ObjChild( pFanout, iFanin ^ 1 ); + assert( Abc_ObjRegular(pFanin2) != pFanout ); + // check if the node with these fanins exists + if ( (pFanoutNew = Abc_AigAndLookup( pMan, pFanin1, pFanin2 )) ) + { // such node exists (it may be a constant) + // schedule replacement of the old fanout by the new fanout + Vec_PtrPush( pMan->vStackReplaceOld, pFanout ); + Vec_PtrPush( pMan->vStackReplaceNew, pFanoutNew ); + continue; + } + // such node does not exist - modify the old fanout node + // (this way the change will not propagate all the way to the COs) + assert( Abc_ObjRegular(pFanin1) != Abc_ObjRegular(pFanin2) ); + + // if the node is in the level structure, remove it + if ( pFanout->fMarkA ) + Abc_AigRemoveFromLevelStructure( pMan->vLevels, pFanout ); + // if the node is in the level structure, remove it + if ( pFanout->fMarkB ) + Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pFanout ); + + // remove the old fanout node from the structural hashing table + Abc_AigAndDelete( pMan, pFanout ); + // remove the fanins of the old fanout + Abc_ObjRemoveFanins( pFanout ); + // recreate the old fanout with new fanins and add it to the table + Abc_AigAndCreateFrom( pMan, pFanin1, pFanin2, pFanout ); + assert( Abc_AigNodeIsAcyclic(pFanout, pFanout) ); + + if ( fUpdateLevel ) + { + // schedule the updated fanout for updating direct level + assert( pFanout->fMarkA == 0 ); + pFanout->fMarkA = 1; + Vec_VecPush( pMan->vLevels, pFanout->Level, pFanout ); + // schedule the updated fanout for updating reverse level + if ( pMan->pNtkAig->vLevelsR ) + { + assert( pFanout->fMarkB == 0 ); + pFanout->fMarkB = 1; + Vec_VecPush( pMan->vLevelsR, Abc_ObjReverseLevel(pFanout), pFanout ); + } + } + + // the fanout has changed, update EXOR status of its fanouts + Abc_ObjForEachFanout( pFanout, pFanoutFanout, v ) + if ( Abc_AigNodeIsAnd(pFanoutFanout) ) + pFanoutFanout->fExor = Abc_NodeIsExorType(pFanoutFanout); + } + // if the node has no fanouts left, remove its MFFC + if ( Abc_ObjFanoutNum(pOld) == 0 ) + Abc_AigDeleteNode( pMan, pOld ); +} + +/**Function************************************************************* + + Synopsis [Performs internal deletion step.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNode0, * pNode1, * pTemp; + int i, k; + + // make sure the node is regular and dangling + assert( !Abc_ObjIsComplement(pNode) ); + assert( Abc_ObjIsNode(pNode) ); + assert( Abc_ObjFaninNum(pNode) == 2 ); + assert( Abc_ObjFanoutNum(pNode) == 0 ); + + // when deleting an old node that is scheduled for replacement, remove it from the replacement queue + Vec_PtrForEachEntry( Abc_Obj_t *, pMan->vStackReplaceOld, pTemp, i ) + if ( pNode == pTemp ) + { + // remove the entry from the replacement array + for ( k = i; k < pMan->vStackReplaceOld->nSize - 1; k++ ) + { + pMan->vStackReplaceOld->pArray[k] = pMan->vStackReplaceOld->pArray[k+1]; + pMan->vStackReplaceNew->pArray[k] = pMan->vStackReplaceNew->pArray[k+1]; + } + pMan->vStackReplaceOld->nSize--; + pMan->vStackReplaceNew->nSize--; + } + + // when deleting a new node that should replace another node, do not delete + Vec_PtrForEachEntry( Abc_Obj_t *, pMan->vStackReplaceNew, pTemp, i ) + if ( pNode == Abc_ObjRegular(pTemp) ) + return; + + // remember the node's fanins + pNode0 = Abc_ObjFanin0( pNode ); + pNode1 = Abc_ObjFanin1( pNode ); + + // add the node to the list of updated nodes + if ( pMan->vUpdatedNets ) + { + Vec_PtrPushUnique( pMan->vUpdatedNets, pNode0 ); + Vec_PtrPushUnique( pMan->vUpdatedNets, pNode1 ); + } + + // remove the node from the table + Abc_AigAndDelete( pMan, pNode ); + // if the node is in the level structure, remove it + if ( pNode->fMarkA ) + Abc_AigRemoveFromLevelStructure( pMan->vLevels, pNode ); + if ( pNode->fMarkB ) + Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pNode ); + // remove the node from the network + Abc_NtkDeleteObj( pNode ); + + // call recursively for the fanins + if ( Abc_ObjIsNode(pNode0) && pNode0->vFanouts.nSize == 0 ) + Abc_AigDeleteNode( pMan, pNode0 ); + if ( Abc_ObjIsNode(pNode1) && pNode1->vFanouts.nSize == 0 ) + Abc_AigDeleteNode( pMan, pNode1 ); +} + + +/**Function************************************************************* + + Synopsis [Updates the level of the node after it has changed.] + + Description [This procedure is based on the observation that + after the node's level has changed, the fanouts levels can change too, + but the new fanout levels are always larger than the node's level. + As a result, we can accumulate the nodes to be updated in the queue + and process them in the increasing order of levels.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigUpdateLevel_int( Abc_Aig_t * pMan ) +{ + Abc_Obj_t * pNode, * pFanout; + Vec_Ptr_t * vVec; + int LevelNew, i, k, v; + + // go through the nodes and update the level of their fanouts + Vec_VecForEachLevel( pMan->vLevels, vVec, i ) + { + if ( Vec_PtrSize(vVec) == 0 ) + continue; + Vec_PtrForEachEntry( Abc_Obj_t *, vVec, pNode, k ) + { + if ( pNode == NULL ) + continue; + assert( Abc_ObjIsNode(pNode) ); + assert( (int)pNode->Level == i ); + // clean the mark + assert( pNode->fMarkA == 1 ); + pNode->fMarkA = 0; + // iterate through the fanouts + Abc_ObjForEachFanout( pNode, pFanout, v ) + { + if ( Abc_ObjIsCo(pFanout) ) + continue; + // get the new level of this fanout + LevelNew = 1 + Abc_MaxInt( Abc_ObjFanin0(pFanout)->Level, Abc_ObjFanin1(pFanout)->Level ); + assert( LevelNew > i ); + if ( (int)pFanout->Level == LevelNew ) // no change + continue; + // if the fanout is present in the data structure, pull it out + if ( pFanout->fMarkA ) + Abc_AigRemoveFromLevelStructure( pMan->vLevels, pFanout ); + // update the fanout level + pFanout->Level = LevelNew; + // add the fanout to the data structure to update its fanouts + assert( pFanout->fMarkA == 0 ); + pFanout->fMarkA = 1; + Vec_VecPush( pMan->vLevels, pFanout->Level, pFanout ); + } + } + Vec_PtrClear( vVec ); + } +} + +/**Function************************************************************* + + Synopsis [Updates the level of the node after it has changed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigUpdateLevelR_int( Abc_Aig_t * pMan ) +{ + Abc_Obj_t * pNode, * pFanin, * pFanout; + Vec_Ptr_t * vVec; + int LevelNew, i, k, v, j; + + // go through the nodes and update the level of their fanouts + Vec_VecForEachLevel( pMan->vLevelsR, vVec, i ) + { + if ( Vec_PtrSize(vVec) == 0 ) + continue; + Vec_PtrForEachEntry( Abc_Obj_t *, vVec, pNode, k ) + { + if ( pNode == NULL ) + continue; + assert( Abc_ObjIsNode(pNode) ); + assert( Abc_ObjReverseLevel(pNode) == i ); + // clean the mark + assert( pNode->fMarkB == 1 ); + pNode->fMarkB = 0; + // iterate through the fanins + Abc_ObjForEachFanin( pNode, pFanin, v ) + { + if ( Abc_ObjIsCi(pFanin) ) + continue; + // get the new reverse level of this fanin + LevelNew = 0; + Abc_ObjForEachFanout( pFanin, pFanout, j ) + if ( LevelNew < Abc_ObjReverseLevel(pFanout) ) + LevelNew = Abc_ObjReverseLevel(pFanout); + LevelNew += 1; + assert( LevelNew > i ); + if ( Abc_ObjReverseLevel(pFanin) == LevelNew ) // no change + continue; + // if the fanin is present in the data structure, pull it out + if ( pFanin->fMarkB ) + Abc_AigRemoveFromLevelStructureR( pMan->vLevelsR, pFanin ); + // update the reverse level + Abc_ObjSetReverseLevel( pFanin, LevelNew ); + // add the fanin to the data structure to update its fanins + assert( pFanin->fMarkB == 0 ); + pFanin->fMarkB = 1; + Vec_VecPush( pMan->vLevelsR, LevelNew, pFanin ); + } + } + Vec_PtrClear( vVec ); + } +} + +/**Function************************************************************* + + Synopsis [Removes the node from the level structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigRemoveFromLevelStructure( Vec_Vec_t * vStruct, Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vVecTemp; + Abc_Obj_t * pTemp; + int m; + assert( pNode->fMarkA ); + vVecTemp = Vec_VecEntry( vStruct, pNode->Level ); + Vec_PtrForEachEntry( Abc_Obj_t *, vVecTemp, pTemp, m ) + { + if ( pTemp != pNode ) + continue; + Vec_PtrWriteEntry( vVecTemp, m, NULL ); + break; + } + assert( m < Vec_PtrSize(vVecTemp) ); // found + pNode->fMarkA = 0; +} + +/**Function************************************************************* + + Synopsis [Removes the node from the level structure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigRemoveFromLevelStructureR( Vec_Vec_t * vStruct, Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vVecTemp; + Abc_Obj_t * pTemp; + int m; + assert( pNode->fMarkB ); + vVecTemp = Vec_VecEntry( vStruct, Abc_ObjReverseLevel(pNode) ); + Vec_PtrForEachEntry( Abc_Obj_t *, vVecTemp, pTemp, m ) + { + if ( pTemp != pNode ) + continue; + Vec_PtrWriteEntry( vVecTemp, m, NULL ); + break; + } + assert( m < Vec_PtrSize(vVecTemp) ); // found + pNode->fMarkB = 0; +} + + + + +/**Function************************************************************* + + Synopsis [Returns 1 if the node has at least one complemented fanout.] + + Description [A fanout is complemented if the fanout's fanin edge pointing + to the given node is complemented.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_AigNodeHasComplFanoutEdge( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanout; + int i, iFanin; + Abc_ObjForEachFanout( pNode, pFanout, i ) + { + iFanin = Vec_IntFind( &pFanout->vFanins, pNode->Id ); + assert( iFanin >= 0 ); + if ( Abc_ObjFaninC( pFanout, iFanin ) ) + return 1; + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node has at least one complemented fanout.] + + Description [A fanout is complemented if the fanout's fanin edge pointing + to the given node is complemented. Only the fanouts with current TravId + are counted.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_AigNodeHasComplFanoutEdgeTrav( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanout; + int i, iFanin; + Abc_ObjForEachFanout( pNode, pFanout, i ) + { + if ( !Abc_NodeIsTravIdCurrent(pFanout) ) + continue; + iFanin = Vec_IntFind( &pFanout->vFanins, pNode->Id ); + assert( iFanin >= 0 ); + if ( Abc_ObjFaninC( pFanout, iFanin ) ) + return 1; + } + return 0; +} + + +/**Function************************************************************* + + Synopsis [Prints the AIG node for debugging purposes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigPrintNode( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNodeR = Abc_ObjRegular(pNode); + if ( Abc_ObjIsCi(pNodeR) ) + { + printf( "CI %4s%s.\n", Abc_ObjName(pNodeR), Abc_ObjIsComplement(pNode)? "\'" : "" ); + return; + } + if ( Abc_AigNodeIsConst(pNodeR) ) + { + printf( "Constant 1 %s.\n", Abc_ObjIsComplement(pNode)? "(complemented)" : "" ); + return; + } + // print the node's function + printf( "%7s%s", Abc_ObjName(pNodeR), Abc_ObjIsComplement(pNode)? "\'" : "" ); + printf( " = " ); + printf( "%7s%s", Abc_ObjName(Abc_ObjFanin0(pNodeR)), Abc_ObjFaninC0(pNodeR)? "\'" : "" ); + printf( " * " ); + printf( "%7s%s", Abc_ObjName(Abc_ObjFanin1(pNodeR)), Abc_ObjFaninC1(pNodeR)? "\'" : "" ); + printf( "\n" ); +} + + +/**Function************************************************************* + + Synopsis [Check if the node has a combination loop of depth 1 or 2.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_AigNodeIsAcyclic( Abc_Obj_t * pNode, Abc_Obj_t * pRoot ) +{ + Abc_Obj_t * pFanin0, * pFanin1; + Abc_Obj_t * pChild00, * pChild01; + Abc_Obj_t * pChild10, * pChild11; + if ( !Abc_AigNodeIsAnd(pNode) ) + return 1; + pFanin0 = Abc_ObjFanin0(pNode); + pFanin1 = Abc_ObjFanin1(pNode); + if ( pRoot == pFanin0 || pRoot == pFanin1 ) + return 0; + if ( Abc_ObjIsCi(pFanin0) ) + { + pChild00 = NULL; + pChild01 = NULL; + } + else + { + pChild00 = Abc_ObjFanin0(pFanin0); + pChild01 = Abc_ObjFanin1(pFanin0); + if ( pRoot == pChild00 || pRoot == pChild01 ) + return 0; + } + if ( Abc_ObjIsCi(pFanin1) ) + { + pChild10 = NULL; + pChild11 = NULL; + } + else + { + pChild10 = Abc_ObjFanin0(pFanin1); + pChild11 = Abc_ObjFanin1(pFanin1); + if ( pRoot == pChild10 || pRoot == pChild11 ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Resizes the hash table of AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigCheckFaninOrder( Abc_Aig_t * pMan ) +{ + Abc_Obj_t * pEnt; + int i; + for ( i = 0; i < pMan->nBins; i++ ) + Abc_AigBinForEachEntry( pMan->pBins[i], pEnt ) + { + if ( Abc_ObjRegular(Abc_ObjChild0(pEnt))->Id > Abc_ObjRegular(Abc_ObjChild1(pEnt))->Id ) + { +// int i0 = Abc_ObjRegular(Abc_ObjChild0(pEnt))->Id; +// int i1 = Abc_ObjRegular(Abc_ObjChild1(pEnt))->Id; + printf( "Node %d has incorrect ordering of fanins.\n", pEnt->Id ); + } + } +} + +/**Function************************************************************* + + Synopsis [Sets the correct phase of the nodes.] + + Description [The AIG nodes should be in the DFS order.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigSetNodePhases( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkIsDfsOrdered(pNtk) ); + Abc_AigConst1(pNtk)->fPhase = 1; + Abc_NtkForEachPi( pNtk, pObj, i ) + pObj->fPhase = 0; + Abc_NtkForEachLatchOutput( pNtk, pObj, i ) + pObj->fPhase = Abc_LatchIsInit1(pObj); + Abc_AigForEachAnd( pNtk, pObj, i ) + pObj->fPhase = (Abc_ObjFanin0(pObj)->fPhase ^ Abc_ObjFaninC0(pObj)) & (Abc_ObjFanin1(pObj)->fPhase ^ Abc_ObjFaninC1(pObj)); + Abc_NtkForEachPo( pNtk, pObj, i ) + pObj->fPhase = (Abc_ObjFanin0(pObj)->fPhase ^ Abc_ObjFaninC0(pObj)); + Abc_NtkForEachLatchInput( pNtk, pObj, i ) + pObj->fPhase = (Abc_ObjFanin0(pObj)->fPhase ^ Abc_ObjFaninC0(pObj)); +} + + + +/**Function************************************************************* + + Synopsis [Start the update list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_AigUpdateStart( Abc_Aig_t * pMan, Vec_Ptr_t ** pvUpdatedNets ) +{ + assert( pMan->vAddedCells == NULL ); + pMan->vAddedCells = Vec_PtrAlloc( 1000 ); + pMan->vUpdatedNets = Vec_PtrAlloc( 1000 ); + *pvUpdatedNets = pMan->vUpdatedNets; + return pMan->vAddedCells; +} + +/**Function************************************************************* + + Synopsis [Start the update list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigUpdateStop( Abc_Aig_t * pMan ) +{ + assert( pMan->vAddedCells != NULL ); + Vec_PtrFree( pMan->vAddedCells ); + Vec_PtrFree( pMan->vUpdatedNets ); + pMan->vAddedCells = NULL; + pMan->vUpdatedNets = NULL; +} + +/**Function************************************************************* + + Synopsis [Start the update list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigUpdateReset( Abc_Aig_t * pMan ) +{ + assert( pMan->vAddedCells != NULL ); + Vec_PtrClear( pMan->vAddedCells ); + Vec_PtrClear( pMan->vUpdatedNets ); +} + +/**Function************************************************************* + + Synopsis [Start the update list.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_AigCountNext( Abc_Aig_t * pMan ) +{ + Abc_Obj_t * pAnd; + int i, Counter = 0, CounterTotal = 0; + // count how many nodes have pNext set + for ( i = 0; i < pMan->nBins; i++ ) + Abc_AigBinForEachEntry( pMan->pBins[i], pAnd ) + { + Counter += (pAnd->pNext != NULL); + CounterTotal++; + } + printf( "Counter = %d. Nodes = %d. Ave = %6.2f\n", Counter, CounterTotal, 1.0 * CounterTotal/pMan->nBins ); + return Counter; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +void Abc_NtkHelloWorld( Abc_Ntk_t * pNtk ) +{ + printf( "Hello, World!\n" ); +} + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/abcBarBuf.c b/yosys/abc/src/base/abc/abcBarBuf.c new file mode 100644 index 00000000000..2b9c692ff56 --- /dev/null +++ b/yosys/abc/src/base/abc/abcBarBuf.c @@ -0,0 +1,513 @@ +/**CFile**************************************************************** + + FileName [abcHie.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures to handle hierarchy.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcHie.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define ABC_OBJ_VOID ((Abc_Obj_t *)(ABC_PTRINT_T)1) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks the the hie design has no duplicated networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCheckSingleInstance( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pTemp, * pModel; + Abc_Obj_t * pBox; + int i, k, RetValue = 1; + if ( pNtk->pDesign == NULL ) + return 1; + Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pTemp, i ) + pTemp->fHieVisited = 0; + Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pTemp, i ) + Abc_NtkForEachBox( pTemp, pBox, k ) + { + pModel = (Abc_Ntk_t *)pBox->pData; + if ( pModel == NULL ) + continue; + if ( Abc_NtkLatchNum(pModel) > 0 ) + { + printf( "Network \"%s\" contains %d flops.\n", + Abc_NtkName(pNtk), Abc_NtkLatchNum(pModel) ); + RetValue = 0; + } + if ( pModel->fHieVisited ) + { + printf( "Network \"%s\" contains box \"%s\" whose model \"%s\" is instantiated more than once.\n", + Abc_NtkName(pNtk), Abc_ObjName(pBox), Abc_NtkName(pModel) ); + RetValue = 0; + } + pModel->fHieVisited = 1; + } + Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pTemp, i ) + pTemp->fHieVisited = 0; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Collect PIs and POs of internal networks in the topo order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCollectPiPos_rec( Abc_Obj_t * pNet, Vec_Ptr_t * vLiMaps, Vec_Ptr_t * vLoMaps ) +{ + extern int Abc_NtkCollectPiPos_int( Abc_Obj_t * pBox, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLiMaps, Vec_Ptr_t * vLoMaps ); + Abc_Obj_t * pObj, * pFanin; + int i, Counter = 0; + assert( Abc_ObjIsNet(pNet) ); + if ( Abc_NodeIsTravIdCurrent( pNet ) ) + return 0; + Abc_NodeSetTravIdCurrent( pNet ); + pObj = Abc_ObjFanin0(pNet); + if ( Abc_ObjIsNode(pObj) ) + Abc_ObjForEachFanin( pObj, pFanin, i ) + Counter += Abc_NtkCollectPiPos_rec( pFanin, vLiMaps, vLoMaps ); + if ( Abc_ObjIsNode(pObj) ) + return Counter; + if ( Abc_ObjIsBo(pObj) ) + pObj = Abc_ObjFanin0(pObj); + assert( Abc_ObjIsBox(pObj) ); + Abc_ObjForEachFanout( pObj, pFanin, i ) + Abc_NodeSetTravIdCurrent( Abc_ObjFanout0(pFanin) ); + Abc_ObjForEachFanin( pObj, pFanin, i ) + Counter += Abc_NtkCollectPiPos_rec( Abc_ObjFanin0(pFanin), vLiMaps, vLoMaps ); + Counter += Abc_NtkCollectPiPos_int( pObj, Abc_ObjModel(pObj), vLiMaps, vLoMaps ); + return Counter; +} +int Abc_NtkCollectPiPos_int( Abc_Obj_t * pBox, Abc_Ntk_t * pNtk, Vec_Ptr_t * vLiMaps, Vec_Ptr_t * vLoMaps ) +{ + Abc_Obj_t * pObj; + int i, Counter = 0; + // mark primary inputs + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NodeSetTravIdCurrent( Abc_ObjFanout0(pObj) ); + // add primary inputs + if ( pBox ) + { + Abc_ObjForEachFanin( pBox, pObj, i ) + Vec_PtrPush( vLiMaps, pObj ); + Abc_NtkForEachPi( pNtk, pObj, i ) + Vec_PtrPush( vLoMaps, pObj ); + } + // visit primary outputs + Abc_NtkForEachPo( pNtk, pObj, i ) + Counter += Abc_NtkCollectPiPos_rec( Abc_ObjFanin0(pObj), vLiMaps, vLoMaps ); + // add primary outputs + if ( pBox ) + { + Abc_NtkForEachPo( pNtk, pObj, i ) + Vec_PtrPush( vLiMaps, pObj ); + Abc_ObjForEachFanout( pBox, pObj, i ) + Vec_PtrPush( vLoMaps, pObj ); + Counter++; + } + return Counter; +} +int Abc_NtkCollectPiPos( Abc_Ntk_t * pNtk, Vec_Ptr_t ** pvLiMaps, Vec_Ptr_t ** pvLoMaps ) +{ + assert( Abc_NtkIsNetlist(pNtk) ); + *pvLiMaps = Vec_PtrAlloc( 1000 ); + *pvLoMaps = Vec_PtrAlloc( 1000 ); + return Abc_NtkCollectPiPos_int( NULL, pNtk, *pvLiMaps, *pvLoMaps ); +} + +/**Function************************************************************* + + Synopsis [Derives logic network with barbufs from the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkToBarBufs_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNet ) +{ + Abc_Obj_t * pObj, * pFanin; + int i; + assert( Abc_ObjIsNet(pNet) ); + if ( pNet->pCopy ) + return pNet->pCopy; + pObj = Abc_ObjFanin0(pNet); + assert( Abc_ObjIsNode(pObj) ); + pNet->pCopy = Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_ObjForEachFanin( pObj, pFanin, i ) + Abc_ObjAddFanin( pObj->pCopy, Abc_NtkToBarBufs_rec(pNtkNew, pFanin) ); + return pNet->pCopy; +} +Abc_Ntk_t * Abc_NtkToBarBufs( Abc_Ntk_t * pNtk ) +{ + char Buffer[1000]; + Vec_Ptr_t * vLiMaps, * vLoMaps; + Abc_Ntk_t * pNtkNew, * pTemp; + Abc_Obj_t * pLatch, * pObjLi, * pObjLo; + Abc_Obj_t * pObj, * pLiMap, * pLoMap; + int i, k, nBoxes; + assert( Abc_NtkIsNetlist(pNtk) ); + if ( !Abc_NtkCheckSingleInstance(pNtk) ) + return NULL; + assert( pNtk->pDesign != NULL ); + // start the network + pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, pNtk->ntkFunc, 1 ); + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); + // clone CIs/CIs/boxes + Abc_NtkCleanCopy_rec( pNtk ); + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_ObjFanout0(pObj)->pCopy = Abc_NtkDupObj( pNtkNew, pObj, 1 ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 1 ); + // create latches and transfer copy labels + nBoxes = Abc_NtkCollectPiPos( pNtk, &vLiMaps, &vLoMaps ); + Vec_PtrForEachEntryTwo( Abc_Obj_t *, vLiMaps, Abc_Obj_t *, vLoMaps, pLiMap, pLoMap, i ) + { + pObjLi = Abc_NtkCreateBi(pNtkNew); + pLatch = Abc_NtkCreateLatch(pNtkNew); + pObjLo = Abc_NtkCreateBo(pNtkNew); + Abc_ObjAddFanin( pLatch, pObjLi ); + Abc_ObjAddFanin( pObjLo, pLatch ); + pLatch->pData = (void *)ABC_INIT_ZERO; + pTemp = NULL; + if ( Abc_ObjFanin0(pLiMap)->pNtk != pNtk ) + pTemp = Abc_ObjFanin0(pLiMap)->pNtk; + else if ( Abc_ObjFanout0(pLoMap)->pNtk != pNtk ) + pTemp = Abc_ObjFanout0(pLoMap)->pNtk; + else assert( 0 ); + sprintf( Buffer, "_%s_in", Abc_NtkName(pTemp) ); + Abc_ObjAssignName( pObjLi, Abc_ObjName(Abc_ObjFanin0(pLiMap)), Buffer ); + sprintf( Buffer, "_%s_out", Abc_NtkName(pTemp) ); + Abc_ObjAssignName( pObjLo, Abc_ObjName(Abc_ObjFanout0(pLoMap)), Buffer ); + pLiMap->pCopy = pObjLi; + Abc_ObjFanout0(pLoMap)->pCopy = pObjLo; + assert( Abc_ObjIsNet(Abc_ObjFanout0(pLoMap)) ); + } + Vec_PtrFree( vLiMaps ); + Vec_PtrFree( vLoMaps ); + // rebuild networks + Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pTemp, i ) + Abc_NtkForEachCo( pTemp, pObj, k ) + Abc_ObjAddFanin( pObj->pCopy, Abc_NtkToBarBufs_rec(pNtkNew, Abc_ObjFanin0(pObj)) ); + pNtkNew->nBarBufs = Abc_NtkLatchNum(pNtkNew); + printf( "Hierarchy reader flattened %d instances of logic boxes and introduced %d barbufs.\n", nBoxes, pNtkNew->nBarBufs ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Converts the logic with barbufs into a hierarchical network.] + + Description [The base network is the original hierarchical network. The + second argument is the optimized network with barbufs. This procedure + reconstructs the original hierarcical network which adding logic from + the optimized network. It is assumed that the PIs/POs of the original + network one-to-one mapping with the flops of the optimized network.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkFromBarBufs_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin; + int i; + if ( pObj->pCopy ) + return pObj->pCopy; + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_ObjForEachFanin( pObj, pFanin, i ) + Abc_ObjAddFanin( pObj->pCopy, Abc_NtkFromBarBufs_rec(pNtkNew, pFanin) ); + return pObj->pCopy; +} +Abc_Ntk_t * Abc_NtkFromBarBufs( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew, * pTemp; + Vec_Ptr_t * vLiMaps, * vLoMaps; + Abc_Obj_t * pObj, * pLiMap, * pLoMap; + int i, k; + assert( pNtkBase->pDesign != NULL ); + assert( Abc_NtkIsNetlist(pNtk) ); + assert( Abc_NtkIsNetlist(pNtkBase) ); + assert( Abc_NtkLatchNum(pNtkBase) == 0 ); + assert( Abc_NtkLatchNum(pNtk) == pNtk->nBarBufs ); + assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + assert( Abc_NtkBlackboxNum(pNtk) == 0 ); + assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkBase) ); + assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkBase) ); + // start networks + Abc_NtkCleanCopy_rec( pNtkBase ); + Vec_PtrForEachEntry( Abc_Ntk_t *, pNtkBase->pDesign->vModules, pTemp, i ) + pTemp->pCopy = Abc_NtkStartFrom( pTemp, pNtk->ntkType, pNtk->ntkFunc ); + Vec_PtrForEachEntry( Abc_Ntk_t *, pNtkBase->pDesign->vModules, pTemp, i ) + pTemp->pCopy->pAltView = pTemp->pAltView ? pTemp->pAltView->pCopy : NULL; + // update box models + Vec_PtrForEachEntry( Abc_Ntk_t *, pNtkBase->pDesign->vModules, pTemp, i ) + Abc_NtkForEachBox( pTemp, pObj, k ) + if ( Abc_ObjIsWhitebox(pObj) || Abc_ObjIsBlackbox(pObj) ) + pObj->pCopy->pData = Abc_ObjModel(pObj)->pCopy; + // create the design + pNtkNew = pNtkBase->pCopy; + pNtkNew->pDesign = Abc_DesCreate( pNtkBase->pDesign->pName ); + Vec_PtrForEachEntry( Abc_Ntk_t *, pNtkBase->pDesign->vModules, pTemp, i ) + Abc_DesAddModel( pNtkNew->pDesign, pTemp->pCopy ); + Vec_PtrForEachEntry( Abc_Ntk_t *, pNtkBase->pDesign->vTops, pTemp, i ) + Vec_PtrPush( pNtkNew->pDesign->vTops, pTemp->pCopy ); + assert( Vec_PtrEntry(pNtkNew->pDesign->vTops, 0) == pNtkNew ); + // transfer copy attributes to pNtk + Abc_NtkCleanCopy( pNtk ); + Abc_NtkForEachPi( pNtk, pObj, i ) + pObj->pCopy = Abc_NtkPi(pNtkNew, i); + Abc_NtkForEachPo( pNtk, pObj, i ) + pObj->pCopy = Abc_NtkPo(pNtkNew, i); + Abc_NtkCollectPiPos( pNtkBase, &vLiMaps, &vLoMaps ); + assert( Vec_PtrSize(vLiMaps) == Abc_NtkLatchNum(pNtk) ); + assert( Vec_PtrSize(vLoMaps) == Abc_NtkLatchNum(pNtk) ); + Vec_PtrForEachEntryTwo( Abc_Obj_t *, vLiMaps, Abc_Obj_t *, vLoMaps, pLiMap, pLoMap, i ) + { + pObj = Abc_NtkBox( pNtk, i ); + Abc_ObjFanin0(pObj)->pCopy = pLiMap->pCopy; + Abc_ObjFanout0(pObj)->pCopy = pLoMap->pCopy; + } + Vec_PtrFree( vLiMaps ); + Vec_PtrFree( vLoMaps ); + // create internal nodes + Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_ObjAddFanin( pObj->pCopy, Abc_NtkFromBarBufs_rec(pObj->pCopy->pNtk, Abc_ObjFanin0(pObj)) ); + // transfer net names + Abc_NtkForEachCi( pNtk, pObj, i ) + { + if ( Abc_ObjFanoutNum(pObj->pCopy) == 0 ) // handle PI without fanout + Abc_ObjAddFanin( Abc_NtkCreateNet(pObj->pCopy->pNtk), pObj->pCopy ); + Nm_ManStoreIdName( pObj->pCopy->pNtk->pManName, Abc_ObjFanout0(pObj->pCopy)->Id, Abc_ObjFanout0(pObj->pCopy)->Type, Abc_ObjName(Abc_ObjFanout0(pObj)), NULL ); + } + Abc_NtkForEachCo( pNtk, pObj, i ) + Nm_ManStoreIdName( pObj->pCopy->pNtk->pManName, Abc_ObjFanin0(pObj->pCopy)->Id, Abc_ObjFanin0(pObj->pCopy)->Type, Abc_ObjName(Abc_ObjFanin0(pObj)), NULL ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Collect nodes in the barbuf-friendly order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkToBarBufsCollect_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanin; + int i; + if ( Abc_NodeIsTravIdCurrent( pObj ) ) + return; + Abc_NodeSetTravIdCurrent( pObj ); + assert( Abc_ObjIsNode(pObj) ); + Abc_ObjForEachFanin( pObj, pFanin, i ) + Abc_NtkToBarBufsCollect_rec( pFanin, vNodes ); + Vec_PtrPush( vNodes, pObj ); +} +Vec_Ptr_t * Abc_NtkToBarBufsCollect( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkIsLogic(pNtk) ); + assert( pNtk->nBarBufs > 0 ); + assert( pNtk->nBarBufs == Abc_NtkLatchNum(pNtk) ); + vNodes = Vec_PtrAlloc( Abc_NtkObjNum(pNtk) ); + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachCi( pNtk, pObj, i ) + { + if ( i >= Abc_NtkCiNum(pNtk) - pNtk->nBarBufs ) + break; + Vec_PtrPush( vNodes, pObj ); + Abc_NodeSetTravIdCurrent( pObj ); + } + Abc_NtkForEachCo( pNtk, pObj, i ) + { + if ( i < Abc_NtkCoNum(pNtk) - pNtk->nBarBufs ) + continue; + Abc_NtkToBarBufsCollect_rec( Abc_ObjFanin0(pObj), vNodes ); + Vec_PtrPush( vNodes, pObj ); + Vec_PtrPush( vNodes, Abc_ObjFanout0(pObj) ); + Vec_PtrPush( vNodes, Abc_ObjFanout0(Abc_ObjFanout0(pObj)) ); + Abc_NodeSetTravIdCurrent( pObj ); + Abc_NodeSetTravIdCurrent( Abc_ObjFanout0(pObj) ); + Abc_NodeSetTravIdCurrent( Abc_ObjFanout0(Abc_ObjFanout0(pObj)) ); + } + Abc_NtkForEachCo( pNtk, pObj, i ) + { + if ( i >= Abc_NtkCoNum(pNtk) - pNtk->nBarBufs ) + break; + Abc_NtkToBarBufsCollect_rec( Abc_ObjFanin0(pObj), vNodes ); + Vec_PtrPush( vNodes, pObj ); + Abc_NodeSetTravIdCurrent( pObj ); + } + assert( Vec_PtrSize(vNodes) == Abc_NtkObjNum(pNtk) ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Count barrier buffers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCountBarBufs( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i, Counter = 0; + Abc_NtkForEachNode( pNtk, pObj, i ) + Counter += Abc_ObjIsBarBuf( pObj ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Converts the network to dedicated barbufs and back.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkBarBufsToBuffers( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin; + int i, k; + assert( Abc_NtkIsLogic(pNtk) ); + assert( pNtk->pDesign == NULL ); + assert( pNtk->nBarBufs > 0 ); + assert( pNtk->nBarBufs == Abc_NtkLatchNum(pNtk) ); + vNodes = Abc_NtkToBarBufsCollect( pNtk ); + // start the network + pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, pNtk->ntkFunc, 1 ); + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); + // create objects + Abc_NtkCleanCopy( pNtk ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + { + if ( Abc_ObjIsPi(pObj) ) + Abc_NtkDupObj( pNtkNew, pObj, 1 ); + else if ( Abc_ObjIsPo( pObj) ) + Abc_ObjAddFanin( Abc_NtkDupObj(pNtkNew, pObj, 1), Abc_ObjFanin0(pObj)->pCopy ); + else if ( Abc_ObjIsBi(pObj) || Abc_ObjIsBo(pObj) ) + pObj->pCopy = Abc_ObjFanin0(pObj)->pCopy; + else if ( Abc_ObjIsLatch(pObj) ) + Abc_ObjAddFanin( (pObj->pCopy = Abc_NtkCreateNode(pNtkNew)), Abc_ObjFanin0(pObj)->pCopy ); + else if ( Abc_ObjIsNode(pObj) ) + { + Abc_NtkDupObj( pNtkNew, pObj, 1 ); + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + else assert( 0 ); + } + Vec_PtrFree( vNodes ); + return pNtkNew; +} +Abc_Ntk_t * Abc_NtkBarBufsFromBuffers( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin, * pLatch; + int i, k, nBarBufs; + assert( Abc_NtkIsLogic(pNtkBase) ); + assert( Abc_NtkIsLogic(pNtk) ); + assert( pNtkBase->nBarBufs == Abc_NtkLatchNum(pNtkBase) ); + // start the network + pNtkNew = Abc_NtkStartFrom( pNtkBase, pNtk->ntkType, pNtk->ntkFunc ); + // transfer PI pointers + Abc_NtkForEachPi( pNtk, pObj, i ) + pObj->pCopy = Abc_NtkPi(pNtkNew, i); + // assuming that the order/number of barbufs remains the same + nBarBufs = 0; + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( Abc_ObjIsBarBuf(pObj) ) + { + pLatch = Abc_NtkBox(pNtkNew, nBarBufs++); + Abc_ObjAddFanin( Abc_ObjFanin0(pLatch), Abc_ObjFanin0(pObj)->pCopy ); + pObj->pCopy = Abc_ObjFanout0(pLatch); + } + else + { + Abc_NtkDupObj( pNtkNew, pObj, 1 ); + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + } + assert( nBarBufs == pNtkBase->nBarBufs ); + // connect POs + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_ObjAddFanin( Abc_NtkPo(pNtkNew, i), Abc_ObjFanin0(pObj)->pCopy ); + return pNtkNew; +} +Abc_Ntk_t * Abc_NtkBarBufsOnOffTest( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew, * pNtkNew2; + pNtkNew = Abc_NtkBarBufsToBuffers( pNtk ); + pNtkNew2 = Abc_NtkBarBufsFromBuffers( pNtk, pNtkNew ); + Abc_NtkDelete( pNtkNew ); + return pNtkNew2; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/abcBlifMv.c b/yosys/abc/src/base/abc/abcBlifMv.c new file mode 100644 index 00000000000..8c9b2a7014d --- /dev/null +++ b/yosys/abc/src/base/abc/abcBlifMv.c @@ -0,0 +1,1167 @@ +/**CFile**************************************************************** + + FileName [abcBlifMv.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures to process BLIF-MV networks and AIGs.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcBlifMv.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +#ifdef ABC_USE_CUDD +#include "bdd/extrab/extraBdd.h" +#endif + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Starts the Mv-Var manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkStartMvVars( Abc_Ntk_t * pNtk ) +{ + Vec_Att_t * pAttMan; + assert( Abc_NtkMvVar(pNtk) == NULL ); + pAttMan = Vec_AttAlloc( Abc_NtkObjNumMax(pNtk) + 1, Mem_FlexStart(), (void(*)(void*))Mem_FlexStop, NULL, NULL ); + Vec_PtrWriteEntry( pNtk->vAttrs, VEC_ATTR_MVVAR, pAttMan ); +//printf( "allocing attr\n" ); +} + +/**Function************************************************************* + + Synopsis [Stops the Mv-Var manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFreeMvVars( Abc_Ntk_t * pNtk ) +{ + Mem_Flex_t * pUserMan; + pUserMan = (Mem_Flex_t *)Abc_NtkAttrFree( pNtk, VEC_ATTR_GLOBAL_BDD, 0 ); + Mem_FlexStop( pUserMan, 0 ); +} + +/**Function************************************************************* + + Synopsis [Duplicate the MV variable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSetMvVarValues( Abc_Obj_t * pObj, int nValues ) +{ + Mem_Flex_t * pFlex; + struct temp + { + int nValues; + char ** pNames; + } * pVarStruct; + assert( nValues > 1 ); + // skip binary signals + if ( nValues == 2 ) + return; + // skip already assigned signals + if ( Abc_ObjMvVar(pObj) != NULL ) + return; + // create the structure + pFlex = (Mem_Flex_t *)Abc_NtkMvVarMan( pObj->pNtk ); + pVarStruct = (struct temp *)Mem_FlexEntryFetch( pFlex, sizeof(struct temp) ); + pVarStruct->nValues = nValues; + pVarStruct->pNames = NULL; + Abc_ObjSetMvVar( pObj, pVarStruct ); +} + +/**Function************************************************************* + + Synopsis [Strashes the BLIF-MV netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Abc_StringGetNumber( char ** ppStr ) +{ + char * pStr = *ppStr; + int Number = 0; + assert( *pStr >= '0' && *pStr <= '9' ); + for ( ; *pStr >= '0' && *pStr <= '9'; pStr++ ) + Number = 10 * Number + *pStr - '0'; + *ppStr = pStr; + return Number; +} + +/**Function************************************************************* + + Synopsis [Strashes one node in the BLIF-MV netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeStrashBlifMv( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj ) +{ + int fAddFreeVars = 1; + char * pSop; + Abc_Obj_t ** pValues, ** pValuesF, ** pValuesF2; + Abc_Obj_t * pTemp, * pTemp2, * pFanin, * pFanin2, * pNet; + int k, v, Def, DefIndex, Index, nValues, nValuesF, nValuesF2; + + // start the output values + assert( Abc_ObjIsNode(pObj) ); + pNet = Abc_ObjFanout0(pObj); + nValues = Abc_ObjMvVarNum(pNet); + pValues = ABC_ALLOC( Abc_Obj_t *, nValues ); + for ( k = 0; k < nValues; k++ ) + pValues[k] = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); + + // get the BLIF-MV formula + pSop = (char *)pObj->pData; + // skip the value line +// while ( *pSop++ != '\n' ); + + // handle the constant + if ( Abc_ObjFaninNum(pObj) == 0 ) + { + // skip the default if present + if ( *pSop == 'd' ) + while ( *pSop++ != '\n' ); + // skip space if present + if ( *pSop == ' ' ) + pSop++; + // assume don't-care constant to be zero + if ( *pSop == '-' ) + Index = 0; + else + Index = Abc_StringGetNumber( &pSop ); + assert( Index < nValues ); + //////////////////////////////////////////// + // adding free variables for binary ND-constants + if ( fAddFreeVars && nValues == 2 && *pSop == '-' ) + { + pValues[1] = Abc_NtkCreatePi(pNtkNew); + pValues[0] = Abc_ObjNot( pValues[1] ); + Abc_ObjAssignName( pValues[1], "free_var_", Abc_ObjName(pValues[1]) ); + } + else + pValues[Index] = Abc_AigConst1(pNtkNew); + //////////////////////////////////////////// + // save the values in the fanout net + pNet->pCopy = (Abc_Obj_t *)pValues; + return 1; + } + + // parse the default line + Def = DefIndex = -1; + if ( *pSop == 'd' ) + { + pSop++; + if ( *pSop == '=' ) + { + pSop++; + DefIndex = Abc_StringGetNumber( &pSop ); + assert( DefIndex < Abc_ObjFaninNum(pObj) ); + } + else if ( *pSop == '-' ) + { + pSop++; + Def = 0; + } + else + { + Def = Abc_StringGetNumber( &pSop ); + assert( Def < nValues ); + } + assert( *pSop == '\n' ); + pSop++; + } + + // convert the values + while ( *pSop ) + { + // extract the values for each cube + pTemp = Abc_AigConst1(pNtkNew); + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + if ( *pSop == '-' ) + { + pSop += 2; + continue; + } + if ( *pSop == '!' ) + { + ABC_FREE( pValues ); + printf( "Abc_NodeStrashBlifMv(): Cannot handle complement in the MV function of node %s.\n", Abc_ObjName(Abc_ObjFanout0(pObj)) ); + return 0; + } + if ( *pSop == '{' ) + { + ABC_FREE( pValues ); + printf( "Abc_NodeStrashBlifMv(): Cannot handle braces in the MV function of node %s.\n", Abc_ObjName(Abc_ObjFanout0(pObj)) ); + return 0; + } + // get the value set + nValuesF = Abc_ObjMvVarNum(pFanin); + pValuesF = (Abc_Obj_t **)pFanin->pCopy; + if ( *pSop == '(' ) + { + pSop++; + pTemp2 = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); + while ( *pSop != ')' ) + { + Index = Abc_StringGetNumber( &pSop ); + assert( Index < nValuesF ); + pTemp2 = Abc_AigOr( (Abc_Aig_t *)pNtkNew->pManFunc, pTemp2, pValuesF[Index] ); + assert( *pSop == ')' || *pSop == ',' ); + if ( *pSop == ',' ) + pSop++; + } + assert( *pSop == ')' ); + pSop++; + } + else if ( *pSop == '=' ) + { + pSop++; + // get the fanin index + Index = Abc_StringGetNumber( &pSop ); + assert( Index < Abc_ObjFaninNum(pObj) ); + assert( Index != k ); + // get the fanin + pFanin2 = Abc_ObjFanin( pObj, Index ); + nValuesF2 = Abc_ObjMvVarNum(pFanin2); + pValuesF2 = (Abc_Obj_t **)pFanin2->pCopy; + // create the sum of products of values + assert( nValuesF == nValuesF2 ); + pTemp2 = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); + for ( v = 0; v < nValues; v++ ) + pTemp2 = Abc_AigOr( (Abc_Aig_t *)pNtkNew->pManFunc, pTemp2, Abc_AigAnd((Abc_Aig_t *)pNtkNew->pManFunc, pValuesF[v], pValuesF2[v]) ); + } + else + { + Index = Abc_StringGetNumber( &pSop ); + assert( Index < nValuesF ); + pTemp2 = pValuesF[Index]; + } + // compute the compute + pTemp = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, pTemp, pTemp2 ); + // advance the reading point + assert( *pSop == ' ' ); + pSop++; + } + // check if the output value is an equal construct + if ( *pSop == '=' ) + { + pSop++; + // get the output value + Index = Abc_StringGetNumber( &pSop ); + assert( Index < Abc_ObjFaninNum(pObj) ); + // add values of the given fanin with the given cube + pFanin = Abc_ObjFanin( pObj, Index ); + nValuesF = Abc_ObjMvVarNum(pFanin); + pValuesF = (Abc_Obj_t **)pFanin->pCopy; + assert( nValuesF == nValues ); // should be guaranteed by the parser + for ( k = 0; k < nValuesF; k++ ) + pValues[k] = Abc_AigOr( (Abc_Aig_t *)pNtkNew->pManFunc, pValues[k], Abc_AigAnd((Abc_Aig_t *)pNtkNew->pManFunc, pTemp, pValuesF[k]) ); + } + else + { + // get the output value + Index = Abc_StringGetNumber( &pSop ); + assert( Index < nValues ); + pValues[Index] = Abc_AigOr( (Abc_Aig_t *)pNtkNew->pManFunc, pValues[Index], pTemp ); + } + // advance the reading point + assert( *pSop == '\n' ); + pSop++; + } + + // compute the default value + if ( Def >= 0 || DefIndex >= 0 ) + { + pTemp = Abc_AigConst1(pNtkNew); + for ( k = 0; k < nValues; k++ ) + { + if ( k == Def ) + continue; + pTemp = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, pTemp, Abc_ObjNot(pValues[k]) ); + } + + // assign the default value + if ( Def >= 0 ) + pValues[Def] = pTemp; + else + { + assert( DefIndex >= 0 ); + // add values of the given fanin with the given cube + pFanin = Abc_ObjFanin( pObj, DefIndex ); + nValuesF = Abc_ObjMvVarNum(pFanin); + pValuesF = (Abc_Obj_t **)pFanin->pCopy; + assert( nValuesF == nValues ); // should be guaranteed by the parser + for ( k = 0; k < nValuesF; k++ ) + pValues[k] = Abc_AigOr( (Abc_Aig_t *)pNtkNew->pManFunc, pValues[k], Abc_AigAnd((Abc_Aig_t *)pNtkNew->pManFunc, pTemp, pValuesF[k]) ); + } + + } + + // save the values in the fanout net + pNet->pCopy = (Abc_Obj_t *)pValues; + return 1; +} + +/**Function************************************************************* + + Synopsis [Assigns name with index.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Abc_NtkConvertAssignName( Abc_Obj_t * pObj, Abc_Obj_t * pNet, int Index ) +{ + char Suffix[16]; + assert( Abc_ObjIsTerm(pObj) ); + assert( Abc_ObjIsNet(pNet) ); + sprintf( Suffix, "[%d]", Index ); + Abc_ObjAssignName( pObj, Abc_ObjName(pNet), Suffix ); +} + +/**Function************************************************************* + + Synopsis [Strashes the BLIF-MV netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkStrashBlifMv( Abc_Ntk_t * pNtk ) +{ + int fUsePositional = 0; + Vec_Ptr_t * vNodes; + Abc_Obj_t ** pBits; + Abc_Obj_t ** pValues; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pTemp, * pBit, * pNet; + int i, k, v, nValues, nValuesMax, nBits; + int nCount1, nCount2; + + assert( Abc_NtkIsNetlist(pNtk) ); + assert( Abc_NtkHasBlifMv(pNtk) ); + assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + assert( Abc_NtkBlackboxNum(pNtk) == 0 ); + + // get the largest number of values + nValuesMax = 2; + Abc_NtkForEachNet( pNtk, pObj, i ) + { + nValues = Abc_ObjMvVarNum(pObj); + if ( nValuesMax < nValues ) + nValuesMax = nValues; + } + nBits = Abc_Base2Log( nValuesMax ); + pBits = ABC_ALLOC( Abc_Obj_t *, nBits ); + + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + // collect the nodes + vNodes = Abc_NtkDfs( pNtk, 0 ); + + // start the network + pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav( pNtk->pName ); +// pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pName ); + + nCount1 = nCount2 = 0; + // encode the CI nets + Abc_NtkIncrementTravId( pNtk ); + if ( fUsePositional ) + { + Abc_NtkForEachCi( pNtk, pObj, i ) + { + if ( !Abc_ObjIsPi(pObj) ) + continue; + pNet = Abc_ObjFanout0(pObj); + nValues = Abc_ObjMvVarNum(pNet); + pValues = ABC_ALLOC( Abc_Obj_t *, nValues ); + // create PIs for the values + for ( v = 0; v < nValues; v++ ) + { + pValues[v] = Abc_NtkCreatePi( pNtkNew ); + if ( nValuesMax == 2 ) + Abc_ObjAssignName( pValues[v], Abc_ObjName(pNet), NULL ); + else + Abc_NtkConvertAssignName( pValues[v], pNet, v ); + } + // save the values in the fanout net + pNet->pCopy = (Abc_Obj_t *)pValues; + // mark the net + Abc_NodeSetTravIdCurrent( pNet ); + } + Abc_NtkForEachCi( pNtk, pObj, i ) + { + if ( Abc_ObjIsPi(pObj) ) + continue; + pNet = Abc_ObjFanout0(pObj); + nValues = Abc_ObjMvVarNum(pNet); + pValues = ABC_ALLOC( Abc_Obj_t *, nValues ); + // create PIs for the values + for ( v = 0; v < nValues; v++ ) + { + pValues[v] = Abc_NtkCreateBo( pNtkNew ); + if ( nValuesMax == 2 ) + Abc_ObjAssignName( pValues[v], Abc_ObjName(pNet), NULL ); + else + Abc_NtkConvertAssignName( pValues[v], pNet, v ); + nCount1++; + } + // save the values in the fanout net + pNet->pCopy = (Abc_Obj_t *)pValues; + // mark the net + Abc_NodeSetTravIdCurrent( pNet ); + } + } + else + { + Abc_NtkForEachCi( pNtk, pObj, i ) + { + if ( !Abc_ObjIsPi(pObj) ) + continue; + pNet = Abc_ObjFanout0(pObj); + nValues = Abc_ObjMvVarNum(pNet); + pValues = ABC_ALLOC( Abc_Obj_t *, nValues ); + // create PIs for the encoding bits + nBits = Abc_Base2Log( nValues ); + for ( k = 0; k < nBits; k++ ) + { + pBits[k] = Abc_NtkCreatePi( pNtkNew ); + if ( nValuesMax == 2 ) + Abc_ObjAssignName( pBits[k], Abc_ObjName(pNet), NULL ); + else + Abc_NtkConvertAssignName( pBits[k], pNet, k ); + } + // encode the values + for ( v = 0; v < nValues; v++ ) + { + pValues[v] = Abc_AigConst1(pNtkNew); + for ( k = 0; k < nBits; k++ ) + { + pBit = Abc_ObjNotCond( pBits[k], (v&(1<pManFunc, pValues[v], pBit ); + } + } + // save the values in the fanout net + pNet->pCopy = (Abc_Obj_t *)pValues; + // mark the net + Abc_NodeSetTravIdCurrent( pNet ); + } + Abc_NtkForEachCi( pNtk, pObj, i ) + { + if ( Abc_ObjIsPi(pObj) ) + continue; + pNet = Abc_ObjFanout0(pObj); + nValues = Abc_ObjMvVarNum(pNet); + pValues = ABC_ALLOC( Abc_Obj_t *, nValues ); + // create PIs for the encoding bits + nBits = Abc_Base2Log( nValues ); + for ( k = 0; k < nBits; k++ ) + { + pBits[k] = Abc_NtkCreateBo( pNtkNew ); + if ( nValuesMax == 2 ) + Abc_ObjAssignName( pBits[k], Abc_ObjName(pNet), NULL ); + else + Abc_NtkConvertAssignName( pBits[k], pNet, k ); + nCount1++; + } + // encode the values + for ( v = 0; v < nValues; v++ ) + { + pValues[v] = Abc_AigConst1(pNtkNew); + for ( k = 0; k < nBits; k++ ) + { + pBit = Abc_ObjNotCond( pBits[k], (v&(1<pManFunc, pValues[v], pBit ); + } + } + // save the values in the fanout net + pNet->pCopy = (Abc_Obj_t *)pValues; + // mark the net + Abc_NodeSetTravIdCurrent( pNet ); + } + } + + // process nodes in the topological order + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + if ( !Abc_NodeStrashBlifMv( pNtkNew, pObj ) ) + { + Abc_NtkDelete( pNtkNew ); + return NULL; + } + Vec_PtrFree( vNodes ); + + // encode the CO nets + if ( fUsePositional ) + { + Abc_NtkForEachCo( pNtk, pObj, i ) + { + if ( !Abc_ObjIsPo(pObj) ) + continue; + pNet = Abc_ObjFanin0(pObj); + // skip marked nets +// if ( Abc_NodeIsTravIdCurrent(pNet) ) +// continue; +// Abc_NodeSetTravIdCurrent( pNet ); + nValues = Abc_ObjMvVarNum(pNet); + pValues = (Abc_Obj_t **)pNet->pCopy; + for ( v = 0; v < nValues; v++ ) + { + pTemp = Abc_NtkCreatePo( pNtkNew ); + Abc_ObjAddFanin( pTemp, pValues[v] ); + if ( nValuesMax == 2 ) + Abc_ObjAssignName( pTemp, Abc_ObjName(pNet), NULL ); + else + Abc_NtkConvertAssignName( pTemp, pNet, v ); + } + } + Abc_NtkForEachCo( pNtk, pObj, i ) + { + if ( Abc_ObjIsPo(pObj) ) + continue; + pNet = Abc_ObjFanin0(pObj); + // skip marked nets +// if ( Abc_NodeIsTravIdCurrent(pNet) ) +// continue; +// Abc_NodeSetTravIdCurrent( pNet ); + nValues = Abc_ObjMvVarNum(pNet); + pValues = (Abc_Obj_t **)pNet->pCopy; + for ( v = 0; v < nValues; v++ ) + { + pTemp = Abc_NtkCreateBi( pNtkNew ); + Abc_ObjAddFanin( pTemp, pValues[v] ); + if ( nValuesMax == 2 ) + Abc_ObjAssignName( pTemp, Abc_ObjName(pNet), NULL ); + else + Abc_NtkConvertAssignName( pTemp, pNet, v ); + nCount2++; + } + } + } + else // if ( fPositional == 0 ) + { + Abc_NtkForEachCo( pNtk, pObj, i ) + { + if ( !Abc_ObjIsPo(pObj) ) + continue; + pNet = Abc_ObjFanin0(pObj); + // skip marked nets +// if ( Abc_NodeIsTravIdCurrent(pNet) ) +// continue; +// Abc_NodeSetTravIdCurrent( pNet ); + nValues = Abc_ObjMvVarNum(pNet); + pValues = (Abc_Obj_t **)pNet->pCopy; + nBits = Abc_Base2Log( nValues ); + for ( k = 0; k < nBits; k++ ) + { + pBit = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); + for ( v = 0; v < nValues; v++ ) + if ( v & (1<pManFunc, pBit, pValues[v] ); + pTemp = Abc_NtkCreatePo( pNtkNew ); + Abc_ObjAddFanin( pTemp, pBit ); + if ( nValuesMax == 2 ) + Abc_ObjAssignName( pTemp, Abc_ObjName(pNet), NULL ); + else + Abc_NtkConvertAssignName( pTemp, pNet, k ); + } + } + Abc_NtkForEachCo( pNtk, pObj, i ) + { + if ( Abc_ObjIsPo(pObj) ) + continue; + pNet = Abc_ObjFanin0(pObj); + // skip marked nets +// if ( Abc_NodeIsTravIdCurrent(pNet) ) +// continue; +// Abc_NodeSetTravIdCurrent( pNet ); + nValues = Abc_ObjMvVarNum(pNet); + pValues = (Abc_Obj_t **)pNet->pCopy; + nBits = Abc_Base2Log( nValues ); + for ( k = 0; k < nBits; k++ ) + { + pBit = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); + for ( v = 0; v < nValues; v++ ) + if ( v & (1<pManFunc, pBit, pValues[v] ); + pTemp = Abc_NtkCreateBi( pNtkNew ); + Abc_ObjAddFanin( pTemp, pBit ); + if ( nValuesMax == 2 ) + Abc_ObjAssignName( pTemp, Abc_ObjName(pNet), NULL ); + else + Abc_NtkConvertAssignName( pTemp, pNet, k ); + nCount2++; + } + } + } + + if ( Abc_NtkLatchNum(pNtk) ) + { + Vec_Ptr_t * vTemp; + Abc_Obj_t * pLatch, * pObjLi, * pObjLo; + int i; + // move free vars to the front among the PIs + vTemp = Vec_PtrAlloc( Vec_PtrSize(pNtkNew->vPis) ); + Abc_NtkForEachPi( pNtkNew, pObj, i ) + if ( strncmp( Abc_ObjName(pObj), "free_var_", 9 ) == 0 ) + Vec_PtrPush( vTemp, pObj ); + Abc_NtkForEachPi( pNtkNew, pObj, i ) + if ( strncmp( Abc_ObjName(pObj), "free_var_", 9 ) != 0 ) + Vec_PtrPush( vTemp, pObj ); + assert( Vec_PtrSize(vTemp) == Vec_PtrSize(pNtkNew->vPis) ); + Vec_PtrFree( pNtkNew->vPis ); + pNtkNew->vPis = vTemp; + // move free vars to the front among the CIs + vTemp = Vec_PtrAlloc( Vec_PtrSize(pNtkNew->vCis) ); + Abc_NtkForEachCi( pNtkNew, pObj, i ) + if ( strncmp( Abc_ObjName(pObj), "free_var_", 9 ) == 0 ) + Vec_PtrPush( vTemp, pObj ); + Abc_NtkForEachCi( pNtkNew, pObj, i ) + if ( strncmp( Abc_ObjName(pObj), "free_var_", 9 ) != 0 ) + Vec_PtrPush( vTemp, pObj ); + assert( Vec_PtrSize(vTemp) == Vec_PtrSize(pNtkNew->vCis) ); + Vec_PtrFree( pNtkNew->vCis ); + pNtkNew->vCis = vTemp; + // create registers + assert( nCount1 == nCount2 ); + for ( i = 0; i < nCount1; i++ ) + { + // create latch + pLatch = Abc_NtkCreateLatch( pNtkNew ); + Abc_LatchSetInit0( pLatch ); + Abc_ObjAssignName( pLatch, Abc_ObjName(pLatch), NULL ); + // connect + pObjLi = Abc_NtkCo( pNtkNew, Abc_NtkCoNum(pNtkNew)-nCount1+i ); + pObjLo = Abc_NtkCi( pNtkNew, Abc_NtkCiNum(pNtkNew)-nCount1+i ); + Abc_ObjAddFanin( pLatch, pObjLi ); + Abc_ObjAddFanin( pObjLo, pLatch ); + } + } + + // cleanup + ABC_FREE( pBits ); + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( pObj->pCopy ) + ABC_FREE( pObj->pCopy ); + + // remove dangling nodes + i = Abc_AigCleanup((Abc_Aig_t *)pNtkNew->pManFunc); +// printf( "Cleanup removed %d nodes.\n", i ); +// Abc_NtkReassignIds( pNtkNew ); + + // check integrity + if ( !Abc_NtkCheck( pNtkNew ) ) + { + fprintf( stdout, "Abc_NtkStrashBlifMv(): Network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Extract the MV-skeleton of the BLIF-MV network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkSkeletonBlifMv( Abc_Ntk_t * pNtk ) +{ + int fUsePositional = 0; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pNet, * pNetNew, * pNodeNew, * pTermNew, * pBoxNew; + int i, k, v, nValues, nBits; + + assert( Abc_NtkIsNetlist(pNtk) ); + assert( Abc_NtkHasBlifMv(pNtk) ); + assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + assert( Abc_NtkBlackboxNum(pNtk) == 0 ); + + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav( pNtk->pName ); + pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pName ); + // create the internal box (it is important to put it first!) + pBoxNew = Abc_NtkCreateWhitebox( pNtkNew ); + // create PIs and their nets + Abc_NtkForEachPi( pNtk, pObj, i ) + { + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + pNet = Abc_ObjFanout0(pObj); + Abc_NtkDupObj( pNtkNew, pNet, 1 ); + Abc_ObjAddFanin( pNet->pCopy, pObj->pCopy ); + } + // create POs and their nets + Abc_NtkForEachPo( pNtk, pObj, i ) + { + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + pNet = Abc_ObjFanin0(pObj); + if ( pNet->pCopy == NULL ) + Abc_NtkDupObj( pNtkNew, pNet, 1 ); + Abc_ObjAddFanin( pObj->pCopy, pNet->pCopy ); + } + // create latches + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + Abc_NtkDupBox( pNtkNew, pObj, 0 ); + // latch outputs + pNet = Abc_ObjFanout0(Abc_ObjFanout0(pObj)); + assert( pNet->pCopy == NULL ); + Abc_NtkDupObj( pNtkNew, pNet, 1 ); + Abc_ObjAddFanin( pNet->pCopy, Abc_ObjFanout0(pObj)->pCopy ); + // latch inputs + pNet = Abc_ObjFanin0(Abc_ObjFanin0(pObj)); + if ( pNet->pCopy == NULL ) + Abc_NtkDupObj( pNtkNew, pNet, 1 ); + Abc_ObjAddFanin( Abc_ObjFanin0(pObj)->pCopy, pNet->pCopy ); + } + + // encode the CI nets + Abc_NtkIncrementTravId( pNtk ); + if ( fUsePositional ) + { + Abc_NtkForEachCi( pNtk, pObj, i ) + { + pNet = Abc_ObjFanout0(pObj); + nValues = Abc_ObjMvVarNum(pNet); + for ( v = 0; v < nValues; v++ ) + { + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + pNodeNew->pData = Abc_SopEncoderPos( (Mem_Flex_t *)pNtkNew->pManFunc, v, nValues ); + pNetNew = Abc_NtkCreateNet( pNtkNew ); + pTermNew = Abc_NtkCreateBi( pNtkNew ); + Abc_ObjAddFanin( pNodeNew, pNet->pCopy ); + Abc_ObjAddFanin( pNetNew, pNodeNew ); + Abc_ObjAddFanin( pTermNew, pNetNew ); + Abc_ObjAddFanin( pBoxNew, pTermNew ); + } + // mark the net + Abc_NodeSetTravIdCurrent( pNet ); + } + } + else + { + Abc_NtkForEachCi( pNtk, pObj, i ) + { + pNet = Abc_ObjFanout0(pObj); + nValues = Abc_ObjMvVarNum(pNet); + nBits = Abc_Base2Log( nValues ); + for ( k = 0; k < nBits; k++ ) + { + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + pNodeNew->pData = Abc_SopEncoderLog( (Mem_Flex_t *)pNtkNew->pManFunc, k, nValues ); + pNetNew = Abc_NtkCreateNet( pNtkNew ); + pTermNew = Abc_NtkCreateBi( pNtkNew ); + Abc_ObjAddFanin( pNodeNew, pNet->pCopy ); + Abc_ObjAddFanin( pNetNew, pNodeNew ); + Abc_ObjAddFanin( pTermNew, pNetNew ); + Abc_ObjAddFanin( pBoxNew, pTermNew ); + } + // mark the net + Abc_NodeSetTravIdCurrent( pNet ); + } + } + + // encode the CO nets + if ( fUsePositional ) + { + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pNet = Abc_ObjFanin0(pObj); + // skip marked nets + if ( Abc_NodeIsTravIdCurrent(pNet) ) + continue; + Abc_NodeSetTravIdCurrent( pNet ); + nValues = Abc_ObjMvVarNum(pNet); + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + pNodeNew->pData = Abc_SopDecoderPos( (Mem_Flex_t *)pNtkNew->pManFunc, nValues ); + for ( v = 0; v < nValues; v++ ) + { + pTermNew = Abc_NtkCreateBo( pNtkNew ); + pNetNew = Abc_NtkCreateNet( pNtkNew ); + Abc_ObjAddFanin( pTermNew, pBoxNew ); + Abc_ObjAddFanin( pNetNew, pTermNew ); + Abc_ObjAddFanin( pNodeNew, pNetNew ); + } + Abc_ObjAddFanin( pNet->pCopy, pNodeNew ); + } + } + else + { + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pNet = Abc_ObjFanin0(pObj); + // skip marked nets + if ( Abc_NodeIsTravIdCurrent(pNet) ) + continue; + Abc_NodeSetTravIdCurrent( pNet ); + nValues = Abc_ObjMvVarNum(pNet); + nBits = Abc_Base2Log( nValues ); + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + pNodeNew->pData = Abc_SopDecoderLog( (Mem_Flex_t *)pNtkNew->pManFunc, nValues ); + for ( k = 0; k < nBits; k++ ) + { + pTermNew = Abc_NtkCreateBo( pNtkNew ); + pNetNew = Abc_NtkCreateNet( pNtkNew ); + Abc_ObjAddFanin( pTermNew, pBoxNew ); + Abc_ObjAddFanin( pNetNew, pTermNew ); + Abc_ObjAddFanin( pNodeNew, pNetNew ); + } + Abc_ObjAddFanin( pNet->pCopy, pNodeNew ); + } + } + + // if it is a BLIF-MV netlist transfer the values of all nets + if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) ) + { + if ( Abc_NtkMvVar( pNtkNew ) == NULL ) + Abc_NtkStartMvVars( pNtkNew ); + Abc_NtkForEachNet( pNtk, pObj, i ) + if ( pObj->pCopy ) + Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) ); + } + + // check integrity + if ( !Abc_NtkCheck( pNtkNew ) ) + { + fprintf( stdout, "Abc_NtkSkeletonBlifMv(): Network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Inserts processed network into original base MV network.] + + Description [The original network remembers the interface of combinational + logic (PIs/POs/latches names and values). The processed network may + be binary or multi-valued (currently, multi-value is not supported). + The resulting network has the same interface as the original network + while the internal logic is the same as that of the processed network.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkInsertBlifMv( Abc_Ntk_t * pNtkBase, Abc_Ntk_t * pNtkLogic ) +{ + Abc_Ntk_t * pNtkSkel, * pNtkNew; + Abc_Obj_t * pBox; + + assert( Abc_NtkIsNetlist(pNtkBase) ); + assert( Abc_NtkHasBlifMv(pNtkBase) ); + assert( Abc_NtkWhiteboxNum(pNtkBase) == 0 ); + assert( Abc_NtkBlackboxNum(pNtkBase) == 0 ); + + assert( Abc_NtkIsNetlist(pNtkLogic) ); + assert( Abc_NtkHasBlifMv(pNtkLogic) ); + assert( Abc_NtkWhiteboxNum(pNtkLogic) == 0 ); + assert( Abc_NtkBlackboxNum(pNtkLogic) == 0 ); + + // extract the skeleton of the old network + pNtkSkel = Abc_NtkSkeletonBlifMv( pNtkBase ); + + // set the implementation of the box to be the same as the processed network + assert( Abc_NtkWhiteboxNum(pNtkSkel) == 1 ); + pBox = Abc_NtkBox( pNtkSkel, 0 ); + assert( Abc_ObjIsWhitebox(pBox) ); + assert( pBox->pData == NULL ); + assert( Abc_ObjFaninNum(pBox) == Abc_NtkPiNum(pNtkLogic) ); + assert( Abc_ObjFanoutNum(pBox) == Abc_NtkPoNum(pNtkLogic) ); + pBox->pData = pNtkLogic; + + // flatten the hierarchy to insert the processed network + pNtkNew = Abc_NtkFlattenLogicHierarchy( pNtkSkel ); + pBox->pData = NULL; + Abc_NtkDelete( pNtkSkel ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Converts SOP netlist into BLIF-MV netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkConvertToBlifMv( Abc_Ntk_t * pNtk ) +{ +#ifdef ABC_USE_CUDD + Mem_Flex_t * pMmFlex; + Abc_Obj_t * pNode; + Vec_Str_t * vCube; + char * pSop0, * pSop1, * pBlifMv, * pCube, * pCur; + int Value, nCubes, nSize, i, k; + + assert( Abc_NtkIsNetlist(pNtk) ); + if ( !Abc_NtkToBdd(pNtk) ) + { + printf( "Converting logic functions to BDDs has failed.\n" ); + return 0; + } + + pMmFlex = Mem_FlexStart(); + vCube = Vec_StrAlloc( 100 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // convert BDD into cubes for on-set and off-set + Abc_NodeBddToCnf( pNode, pMmFlex, vCube, 0, &pSop0, &pSop1 ); + // allocate room for the MV-SOP + nCubes = Abc_SopGetCubeNum(pSop0) + Abc_SopGetCubeNum(pSop1); + nSize = nCubes*(2*Abc_ObjFaninNum(pNode) + 2)+1; + pBlifMv = Mem_FlexEntryFetch( pMmFlex, nSize ); + // add the cubes + pCur = pBlifMv; + Abc_SopForEachCube( pSop0, Abc_ObjFaninNum(pNode), pCube ) + { + Abc_CubeForEachVar( pCube, Value, k ) + { + *pCur++ = Value; + *pCur++ = ' '; + } + *pCur++ = '0'; + *pCur++ = '\n'; + } + Abc_SopForEachCube( pSop1, Abc_ObjFaninNum(pNode), pCube ) + { + Abc_CubeForEachVar( pCube, Value, k ) + { + *pCur++ = Value; + *pCur++ = ' '; + } + *pCur++ = '1'; + *pCur++ = '\n'; + } + *pCur++ = 0; + assert( pCur - pBlifMv == nSize ); + // update the node representation + Cudd_RecursiveDeref( (DdManager *)pNtk->pManFunc, (DdNode *)pNode->pData ); + pNode->pData = pBlifMv; + } + + // update the functionality type + pNtk->ntkFunc = ABC_FUNC_BLIFMV; + Cudd_Quit( (DdManager *)pNtk->pManFunc ); + pNtk->pManFunc = pMmFlex; + + Vec_StrFree( vCube ); +#endif + return 1; +} + +/**Function************************************************************* + + Synopsis [Converts SOP into MV-SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_NodeConvertSopToMvSop( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 ) +{ + char * pMvSop, * pCur; + unsigned uCube; + int nCubes, nSize, Value, i, k; + // consider the case of the constant node + if ( Vec_IntSize(vSop0) == 0 || Vec_IntSize(vSop1) == 0 ) + { + // (temporary) create a tautology cube + pMvSop = ABC_ALLOC( char, nVars + 3 ); + for ( k = 0; k < nVars; k++ ) + pMvSop[k] = '-'; + pMvSop[nVars] = '0' + (int)(Vec_IntSize(vSop1) > 0); + pMvSop[nVars+1] = '\n'; + pMvSop[nVars+2] = 0; + return pMvSop; + } + // find the total number of cubes + nCubes = Vec_IntSize(vSop0) + Vec_IntSize(vSop1); + // find the size of the MVSOP represented as a C-string + // (each cube has nVars variables + one output literal + end-of-line, + // and the string is zero-terminated) + nSize = nCubes * (nVars + 2) + 1; + // allocate memory + pMvSop = pCur = ABC_ALLOC( char, nSize ); + // fill in the negative polarity cubes + Vec_IntForEachEntry( vSop0, uCube, i ) + { + for ( k = 0; k < nVars; k++ ) + { + Value = (uCube >> (2*k)) & 3; + if ( Value == 1 ) + *pCur++ = '0'; + else if ( Value == 2 ) + *pCur++ = '1'; + else if ( Value == 0 ) + *pCur++ = '-'; + else + assert( 0 ); + } + *pCur++ = '0'; + *pCur++ = '\n'; + } + // fill in the positive polarity cubes + Vec_IntForEachEntry( vSop1, uCube, i ) + { + for ( k = 0; k < nVars; k++ ) + { + Value = (uCube >> (2*k)) & 3; + if ( Value == 1 ) + *pCur++ = '0'; + else if ( Value == 2 ) + *pCur++ = '1'; + else if ( Value == 0 ) + *pCur++ = '-'; + else + assert( 0 ); + } + *pCur++ = '1'; + *pCur++ = '\n'; + } + *pCur++ = 0; + assert( pCur - pMvSop == nSize ); + return pMvSop; +} + + +/**Function************************************************************* + + Synopsis [A prototype of internal cost evaluation procedure.] + + Description [This procedure takes the number of variables (nVars), + the array of values of the inputs and the output (pVarValues) + (note that this array has nVars+1 entries), and an MV-SOP represented + as a C-string with one charater for each literal, including inputs + and output. Each cube is terminated with the new-line character ('\n'). + The string is zero-terminated.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeEvalMvCostInternal( int nVars, int * pVarValues, char * pMvSop ) +{ + // for now, return the number of cubes in the MV-SOP + int Counter = 0; + while ( *pMvSop ) Counter += (*pMvSop++ == '\n'); + return Counter; +} + + +/**Function************************************************************* + + Synopsis [Evaluates the cost of the cut.] + + Description [The Boolean function of the cut is specified by two SOPs, + which represent the negative/positive polarities of the cut function. + Converts these two SOPs into a mutually-agreed-upon representation + to be passed to the internal cost-evaluation procedure (see the above + prototype Abc_NodeEvalMvCostInternal).] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeEvalMvCost( int nVars, Vec_Int_t * vSop0, Vec_Int_t * vSop1 ) +{ + char * pMvSop; + int * pVarValues; + int i, RetValue; + // collect the input and output values (currently, they are binary) + pVarValues = ABC_ALLOC( int, nVars + 1 ); + for ( i = 0; i <= nVars; i++ ) + pVarValues[i] = 2; + // prepare MV-SOP for evaluation + pMvSop = Abc_NodeConvertSopToMvSop( nVars, vSop0, vSop1 ); + // have a look at the MV-SOP: +// printf( "%s\n", pMvSop ); + // get the result of internal cost evaluation + RetValue = Abc_NodeEvalMvCostInternal( nVars, pVarValues, pMvSop ); + // cleanup + ABC_FREE( pVarValues ); + ABC_FREE( pMvSop ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/abcCheck.c b/yosys/abc/src/base/abc/abcCheck.c new file mode 100644 index 00000000000..c492b7093d7 --- /dev/null +++ b/yosys/abc/src/base/abc/abcCheck.c @@ -0,0 +1,956 @@ +/**CFile**************************************************************** + + FileName [abcCheck.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Consistency checking procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcCheck.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "base/main/main.h" + +#ifdef ABC_USE_CUDD +#include "bdd/extrab/extraBdd.h" +#endif + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Abc_NtkCheckNames( Abc_Ntk_t * pNtk ); +static int Abc_NtkCheckPis( Abc_Ntk_t * pNtk ); +static int Abc_NtkCheckPos( Abc_Ntk_t * pNtk ); +//static int Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ); +static int Abc_NtkCheckNet( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet ); +static int Abc_NtkCheckNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ); +static int Abc_NtkCheckLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pLatch ); + +static int Abc_NtkComparePis( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ); +static int Abc_NtkComparePos( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ); +static int Abc_NtkCompareLatches( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ); + +static inline char * Abc_ObjNameNet( Abc_Obj_t * pObj ) { return (Abc_ObjIsNode(pObj) && Abc_NtkIsNetlist(pObj->pNtk)) ? Abc_ObjName(Abc_ObjFanout0(pObj)) : Abc_ObjName(pObj); } + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks the integrity of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCheck( Abc_Ntk_t * pNtk ) +{ + return !Abc_FrameIsFlagEnabled( "check" ) || Abc_NtkDoCheck( pNtk ); +} + +/**Function************************************************************* + + Synopsis [Checks the integrity of the network after reading.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCheckRead( Abc_Ntk_t * pNtk ) +{ + return !Abc_FrameIsFlagEnabled( "checkread" ) || Abc_NtkDoCheck( pNtk ); +} + +/**Function************************************************************* + + Synopsis [Checks the integrity of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDoCheck( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj, * pNet, * pNode; + int i; + + // check network types + if ( !Abc_NtkIsNetlist(pNtk) && !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) + { + fprintf( stdout, "NetworkCheck: Unknown network type.\n" ); + return 0; + } + if ( !Abc_NtkHasSop(pNtk) && !Abc_NtkHasBdd(pNtk) && !Abc_NtkHasAig(pNtk) && !Abc_NtkHasMapping(pNtk) && !Abc_NtkHasBlifMv(pNtk) && !Abc_NtkHasBlackbox(pNtk) ) + { + fprintf( stdout, "NetworkCheck: Unknown functionality type.\n" ); + return 0; + } + if ( Abc_NtkHasMapping(pNtk) ) + { + if ( pNtk->pManFunc != Abc_FrameReadLibGen() ) + { + fprintf( stdout, "NetworkCheck: The library of the mapped network is not the global library.\n" ); + return 0; + } + } + + if ( Abc_NtkHasOnlyLatchBoxes(pNtk) ) + { + // check CI/CO numbers + if ( Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) != Abc_NtkCiNum(pNtk) ) + { + fprintf( stdout, "NetworkCheck: Number of CIs does not match number of PIs and latches.\n" ); + fprintf( stdout, "One possible reason is that latches are added twice:\n" ); + fprintf( stdout, "in procedure Abc_NtkCreateObj() and in the user's code.\n" ); + return 0; + } + if ( Abc_NtkPoNum(pNtk) + Abc_NtkLatchNum(pNtk) != Abc_NtkCoNum(pNtk) ) + { + fprintf( stdout, "NetworkCheck: Number of COs does not match number of POs, asserts, and latches.\n" ); + fprintf( stdout, "One possible reason is that latches are added twice:\n" ); + fprintf( stdout, "in procedure Abc_NtkCreateObj() and in the user's code.\n" ); + return 0; + } + } + + // check the names + if ( !Abc_NtkCheckNames( pNtk ) ) + return 0; + + // check PIs and POs + Abc_NtkCleanCopy( pNtk ); + if ( !Abc_NtkCheckPis( pNtk ) ) + return 0; + if ( !Abc_NtkCheckPos( pNtk ) ) + return 0; + + if ( Abc_NtkHasBlackbox(pNtk) ) + return 1; + + // check the connectivity of objects + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_NtkCheckObj( pNtk, pObj ) ) + return 0; + + // if it is a netlist change nets and latches + if ( Abc_NtkIsNetlist(pNtk) ) + { + if ( Abc_NtkNetNum(pNtk) == 0 ) + fprintf( stdout, "NetworkCheck: Warning! Netlist has no nets.\n" ); + // check the nets + Abc_NtkForEachNet( pNtk, pNet, i ) + if ( !Abc_NtkCheckNet( pNtk, pNet ) ) + return 0; + } + else + { + if ( Abc_NtkNetNum(pNtk) != 0 ) + { + fprintf( stdout, "NetworkCheck: A network that is not a netlist has nets.\n" ); + return 0; + } + } + + // check the nodes + if ( Abc_NtkIsStrash(pNtk) ) + { + if ( !Abc_AigCheck( (Abc_Aig_t *)pNtk->pManFunc ) ) + return 0; + } + else + { + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( !Abc_NtkCheckNode( pNtk, pNode ) ) + return 0; + } + + // check the latches + Abc_NtkForEachLatch( pNtk, pNode, i ) + if ( !Abc_NtkCheckLatch( pNtk, pNode ) ) + return 0; + + // finally, check for combinational loops +// clk = Abc_Clock(); + if ( !Abc_NtkIsAcyclic( pNtk ) ) + { + fprintf( stdout, "NetworkCheck: Network contains a combinational loop.\n" ); + return 0; + } +// ABC_PRT( "Acyclic ", Abc_Clock() - clk ); + + // check the EXDC network if present + if ( pNtk->pExdc ) + Abc_NtkCheck( pNtk->pExdc ); +/* + // check the hierarchy + if ( Abc_NtkIsNetlist(pNtk) && pNtk->tName2Model ) + { + stmm_generator * gen; + Abc_Ntk_t * pNtkTemp; + char * pName; + // check other networks + stmm_foreach_item( pNtk->tName2Model, gen, &pName, (char **)&pNtkTemp ) + { + pNtkTemp->fHiePath = pNtkTemp->fHieVisited = 0; + if ( !Abc_NtkCheck( pNtkTemp ) ) + return 0; + } + // check acyclic dependency of the models + if ( !Abc_NtkIsAcyclicHierarchy( pNtk ) ) + { + fprintf( stdout, "NetworkCheck: Network hierarchical dependences contains a cycle.\n" ); + return 0; + } + } +*/ + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks the names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCheckNames( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj = NULL; // Ensure pObj isn't used uninitialized. + Vec_Int_t * vNameIds; + char * pName; + int i, NameId; + + if ( Abc_NtkIsNetlist(pNtk) ) + return 1; + + // check that each CI/CO has a name + Abc_NtkForEachCi( pNtk, pObj, i ) + { + pObj = Abc_ObjFanout0Ntk(pObj); + if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) == NULL ) + { + fprintf( stdout, "NetworkCheck: CI with ID %d is in the network but not in the name table.\n", pObj->Id ); + return 0; + } + } + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pObj = Abc_ObjFanin0Ntk(pObj); + if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) == NULL ) + { + fprintf( stdout, "NetworkCheck: CO with ID %d is in the network but not in the name table.\n", pObj->Id ); + return 0; + } + } + + assert(pObj); // pObj should point to something here. + + // return the array of all IDs, which have names + vNameIds = Nm_ManReturnNameIds( pNtk->pManName ); + // make sure that these IDs correspond to live objects + Vec_IntForEachEntry( vNameIds, NameId, i ) + { + if ( Vec_PtrEntry( pNtk->vObjs, NameId ) == NULL ) + { + Vec_IntFree( vNameIds ); + pName = Nm_ManFindNameById(pObj->pNtk->pManName, NameId); + fprintf( stdout, "NetworkCheck: Object with ID %d is deleted but its name \"%s\" remains in the name table.\n", NameId, pName ); + return 0; + } + } + Vec_IntFree( vNameIds ); + + // make sure the CI names are unique + if ( !Abc_NtkCheckUniqueCiNames(pNtk) ) + return 0; + + // make sure the CO names are unique + if ( !Abc_NtkCheckUniqueCoNames(pNtk) ) + return 0; + + // make sure that if a CO has the same name as a CI, they point directly + if ( !Abc_NtkCheckUniqueCioNames(pNtk) ) + return 0; + + return 1; +} + + +/**Function************************************************************* + + Synopsis [Checks the PIs of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCheckPis( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + + // check that PIs are indeed PIs + Abc_NtkForEachPi( pNtk, pObj, i ) + { + if ( !Abc_ObjIsPi(pObj) ) + { + fprintf( stdout, "NetworkCheck: Object \"%s\" (id=%d) is in the PI list but is not a PI.\n", Abc_ObjName(pObj), pObj->Id ); + return 0; + } + if ( pObj->pData ) + { + fprintf( stdout, "NetworkCheck: A PI \"%s\" has a logic function.\n", Abc_ObjName(pObj) ); + return 0; + } + if ( Abc_ObjFaninNum(pObj) > 0 ) + { + fprintf( stdout, "NetworkCheck: A PI \"%s\" has fanins.\n", Abc_ObjName(pObj) ); + return 0; + } + pObj->pCopy = (Abc_Obj_t *)1; + } + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( pObj->pCopy == NULL && Abc_ObjIsPi(pObj) ) + { + fprintf( stdout, "NetworkCheck: Object \"%s\" (id=%d) is a PI but is not in the PI list.\n", Abc_ObjName(pObj), pObj->Id ); + return 0; + } + pObj->pCopy = NULL; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks the POs of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCheckPos( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + + // check that POs are indeed POs + Abc_NtkForEachPo( pNtk, pObj, i ) + { + if ( !Abc_ObjIsPo(pObj) ) + { + fprintf( stdout, "NetworkCheck: Net \"%s\" (id=%d) is in the PO list but is not a PO.\n", Abc_ObjName(pObj), pObj->Id ); + return 0; + } + if ( pObj->pData ) + { + fprintf( stdout, "NetworkCheck: A PO \"%s\" has a logic function.\n", Abc_ObjName(pObj) ); + return 0; + } + if ( Abc_ObjFaninNum(pObj) != 1 ) + { + fprintf( stdout, "NetworkCheck: A PO \"%s\" does not have one fanin (but %d).\n", Abc_ObjName(pObj), Abc_ObjFaninNum(pObj) ); + return 0; + } + if ( Abc_ObjFanoutNum(pObj) > 0 ) + { + fprintf( stdout, "NetworkCheck: A PO \"%s\" has %d fanout(s).\n", Abc_ObjName(pObj), Abc_ObjFanoutNum(pObj) ); + return 0; + } + pObj->pCopy = (Abc_Obj_t *)1; + } + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( pObj->pCopy == NULL && Abc_ObjIsPo(pObj) ) + { + fprintf( stdout, "NetworkCheck: Net \"%s\" (id=%d) is in a PO but is not in the PO list.\n", Abc_ObjName(pObj), pObj->Id ); + return 0; + } + pObj->pCopy = NULL; + } + return 1; +} + + +/**Function************************************************************* + + Synopsis [Checks the connectivity of the object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin, * pFanout; + int Value = 1; + int i, k; + + // check the network + if ( pObj->pNtk != pNtk ) + { + fprintf( stdout, "NetworkCheck: Object \"%s\" does not belong to the network.\n", Abc_ObjName(pObj) ); + return 0; + } + // check the object ID + if ( pObj->Id < 0 || (int)pObj->Id >= Abc_NtkObjNumMax(pNtk) ) + { + fprintf( stdout, "NetworkCheck: Object \"%s\" has incorrect ID.\n", Abc_ObjName(pObj) ); + return 0; + } + + if ( !Abc_FrameIsFlagEnabled("checkfio") ) + return Value; + + // go through the fanins of the object and make sure fanins have this object as a fanout + Abc_ObjForEachFanin( pObj, pFanin, i ) + { + if ( Vec_IntFind( &pFanin->vFanouts, pObj->Id ) == -1 ) + { + fprintf( stdout, "NodeCheck: Object \"%s\" has fanin ", Abc_ObjName(pObj) ); + fprintf( stdout, "\"%s\" but the fanin does not have it as a fanout.\n", Abc_ObjName(pFanin) ); + Value = 0; + } + } + // go through the fanouts of the object and make sure fanouts have this object as a fanin + Abc_ObjForEachFanout( pObj, pFanout, i ) + { + if ( Vec_IntFind( &pFanout->vFanins, pObj->Id ) == -1 ) + { + fprintf( stdout, "NodeCheck: Object \"%s\" has fanout ", Abc_ObjName(pObj) ); + fprintf( stdout, "\"%s\" but the fanout does not have it as a fanin.\n", Abc_ObjName(pFanout) ); + Value = 0; + } + } + + // make sure fanins are not duplicated + for ( i = 0; i < pObj->vFanins.nSize; i++ ) + for ( k = i + 1; k < pObj->vFanins.nSize; k++ ) + if ( pObj->vFanins.pArray[k] == pObj->vFanins.pArray[i] ) + { + printf( "Warning: Node %s has", Abc_ObjName(pObj) ); + printf( " duplicated fanin %s.\n", Abc_ObjName(Abc_ObjFanin(pObj,k)) ); + } + + // save time: do not check large fanout lists + if ( pObj->vFanouts.nSize > 100 ) + return Value; + + // make sure fanouts are not duplicated + for ( i = 0; i < pObj->vFanouts.nSize; i++ ) + for ( k = i + 1; k < pObj->vFanouts.nSize; k++ ) + if ( pObj->vFanouts.pArray[k] == pObj->vFanouts.pArray[i] ) + { + printf( "Warning: Node %s has", Abc_ObjName(pObj) ); + printf( " duplicated fanout %s.\n", Abc_ObjName(Abc_ObjFanout(pObj,k)) ); + } + + return Value; +} + +/**Function************************************************************* + + Synopsis [Checks the integrity of a net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCheckNet( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet ) +{ + if ( Abc_ObjFaninNum(pNet) == 0 ) + { + fprintf( stdout, "NetworkCheck: Net \"%s\" is not driven.\n", Abc_ObjName(pNet) ); + return 0; + } + if ( Abc_ObjFaninNum(pNet) > 1 ) + { + fprintf( stdout, "NetworkCheck: Net \"%s\" has more than one driver.\n", Abc_ObjName(pNet) ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks the integrity of a node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCheckNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ) +{ + // detect internal nodes that do not have nets + if ( Abc_NtkIsNetlist(pNtk) && Abc_ObjFanoutNum(pNode) == 0 ) + { + fprintf( stdout, "Node (id = %d) has no net to drive.\n", pNode->Id ); + return 0; + } + // the node should have a function assigned unless it is an AIG + if ( pNode->pData == NULL ) + { + if ( Abc_ObjIsBarBuf(pNode) ) + return 1; + fprintf( stdout, "NodeCheck: An internal node \"%s\" does not have a logic function.\n", Abc_ObjNameNet(pNode) ); + return 0; + } + // the netlist and SOP logic network should have SOPs + if ( Abc_NtkHasSop(pNtk) ) + { + if ( !Abc_SopCheck( (char *)pNode->pData, Abc_ObjFaninNum(pNode) ) ) + { + fprintf( stdout, "NodeCheck: SOP check for node \"%s\" has failed.\n", Abc_ObjNameNet(pNode) ); + return 0; + } + } + else if ( Abc_NtkHasBdd(pNtk) ) + { +#ifdef ABC_USE_CUDD + int nSuppSize = Cudd_SupportSize((DdManager *)pNtk->pManFunc, (DdNode *)pNode->pData); + if ( nSuppSize > Abc_ObjFaninNum(pNode) ) + { + fprintf( stdout, "NodeCheck: BDD of the node \"%s\" has incorrect support size.\n", Abc_ObjNameNet(pNode) ); + return 0; + } +#endif + } + else if ( !Abc_NtkHasMapping(pNtk) && !Abc_NtkHasBlifMv(pNtk) && !Abc_NtkHasAig(pNtk) ) + { + assert( 0 ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks the integrity of a latch.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCheckLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pLatch ) +{ + int Value = 1; + // check whether the object is a latch + if ( !Abc_ObjIsLatch(pLatch) ) + { + fprintf( stdout, "NodeCheck: Latch \"%s\" is in a latch list but is not a latch.\n", Abc_ObjName(pLatch) ); + Value = 0; + } + // make sure the latch has a reasonable return value + if ( (int)(ABC_PTRINT_T)pLatch->pData < ABC_INIT_ZERO || (int)(ABC_PTRINT_T)pLatch->pData > ABC_INIT_DC ) + { + fprintf( stdout, "NodeCheck: Latch \"%s\" has incorrect reset value (%d).\n", + Abc_ObjName(pLatch), (int)(ABC_PTRINT_T)pLatch->pData ); + Value = 0; + } + // make sure the latch has only one fanin + if ( Abc_ObjFaninNum(pLatch) != 1 ) + { + fprintf( stdout, "NodeCheck: Latch \"%s\" has wrong number (%d) of fanins.\n", Abc_ObjName(pLatch), Abc_ObjFaninNum(pLatch) ); + Value = 0; + } + // make sure the latch has only one fanout + if ( Abc_ObjFanoutNum(pLatch) != 1 ) + { + fprintf( stdout, "NodeCheck: Latch \"%s\" has wrong number (%d) of fanouts.\n", Abc_ObjName(pLatch), Abc_ObjFanoutNum(pLatch) ); + Value = 0; + } + // make sure the latch input has only one fanin + if ( Abc_ObjFaninNum(Abc_ObjFanin0(pLatch)) != 1 ) + { + fprintf( stdout, "NodeCheck: Input of latch \"%s\" has wrong number (%d) of fanins.\n", + Abc_ObjName(Abc_ObjFanin0(pLatch)), Abc_ObjFaninNum(Abc_ObjFanin0(pLatch)) ); + Value = 0; + } + // make sure the latch input has only one fanout + if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pLatch)) != 1 ) + { + fprintf( stdout, "NodeCheck: Input of latch \"%s\" has wrong number (%d) of fanouts.\n", + Abc_ObjName(Abc_ObjFanin0(pLatch)), Abc_ObjFanoutNum(Abc_ObjFanin0(pLatch)) ); + Value = 0; + } + // make sure the latch output has only one fanin + if ( Abc_ObjFaninNum(Abc_ObjFanout0(pLatch)) != 1 ) + { + fprintf( stdout, "NodeCheck: Output of latch \"%s\" has wrong number (%d) of fanins.\n", + Abc_ObjName(Abc_ObjFanout0(pLatch)), Abc_ObjFaninNum(Abc_ObjFanout0(pLatch)) ); + Value = 0; + } + return Value; +} + + + + +/**Function************************************************************* + + Synopsis [Compares the PIs of the two networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkComparePis( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) +{ + Abc_Obj_t * pObj1; + int i; + if ( Abc_NtkPiNum(pNtk1) != Abc_NtkPiNum(pNtk2) ) + { + printf( "Networks have different number of primary inputs.\n" ); + return 0; + } + // for each PI of pNet1 find corresponding PI of pNet2 and reorder them + Abc_NtkForEachPi( pNtk1, pObj1, i ) + { + if ( strcmp( Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPi(pNtk2,i)) ) != 0 ) + { + printf( "Primary input #%d is different in network 1 ( \"%s\") and in network 2 (\"%s\").\n", + i, Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPi(pNtk2,i)) ); + return 0; + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Compares the POs of the two networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkComparePos( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) +{ + Abc_Obj_t * pObj1; + int i; + if ( Abc_NtkPoNum(pNtk1) != Abc_NtkPoNum(pNtk2) ) + { + printf( "Networks have different number of primary outputs.\n" ); + return 0; + } + // for each PO of pNet1 find corresponding PO of pNet2 and reorder them + Abc_NtkForEachPo( pNtk1, pObj1, i ) + { + if ( strcmp( Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPo(pNtk2,i)) ) != 0 ) + { + printf( "Primary output #%d is different in network 1 ( \"%s\") and in network 2 (\"%s\").\n", + i, Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPo(pNtk2,i)) ); + return 0; + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Compares the latches of the two networks.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCompareBoxes( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb ) +{ + Abc_Obj_t * pObj1; + int i; + assert( Abc_NtkHasOnlyLatchBoxes(pNtk1) ); + assert( Abc_NtkHasOnlyLatchBoxes(pNtk2) ); + if ( !fComb ) + return 1; + if ( Abc_NtkBoxNum(pNtk1) != Abc_NtkBoxNum(pNtk2) ) + { + printf( "Networks have different number of latches.\n" ); + return 0; + } + // for each PI of pNet1 find corresponding PI of pNet2 and reorder them + Abc_NtkForEachBox( pNtk1, pObj1, i ) + { + if ( strcmp( Abc_ObjName(Abc_ObjFanout0(pObj1)), Abc_ObjName(Abc_ObjFanout0(Abc_NtkBox(pNtk2,i))) ) != 0 ) + { + printf( "Box #%d is different in network 1 ( \"%s\") and in network 2 (\"%s\").\n", + i, Abc_ObjName(Abc_ObjFanout0(pObj1)), Abc_ObjName(Abc_ObjFanout0(Abc_NtkBox(pNtk2,i))) ); + return 0; + } + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Compares the signals of the networks.] + + Description [] + + SideEffects [Ordering POs by name is a very bad idea! It destroys + the natural order of the logic in the circuit.] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOnlyPis, int fComb ) +{ + Abc_NtkOrderObjsByName( pNtk1, fComb ); + Abc_NtkOrderObjsByName( pNtk2, fComb ); + if ( !Abc_NtkComparePis( pNtk1, pNtk2, fComb ) ) + return 0; + if ( !fOnlyPis ) + { + if ( !Abc_NtkCompareBoxes( pNtk1, pNtk2, fComb ) ) + return 0; + if ( !Abc_NtkComparePos( pNtk1, pNtk2, fComb ) ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 0 if the network hierachy contains a cycle.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkIsAcyclicHierarchy_rec( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNext; + Abc_Obj_t * pObj; + int i; + // return if visited + if ( pNtk->fHieVisited ) + return 1; + pNtk->fHieVisited = 1; + // return if black box + if ( Abc_NtkHasBlackbox(pNtk) ) + return 1; + assert( Abc_NtkIsNetlist(pNtk) ); + // go through all the children networks + Abc_NtkForEachBox( pNtk, pObj, i ) + { + if ( Abc_ObjIsLatch(pObj) ) + continue; + pNtkNext = (Abc_Ntk_t *)pObj->pData; + assert( pNtkNext != NULL ); + if ( pNtkNext->fHiePath ) + return 0; + pNtk->fHiePath = 1; + if ( !Abc_NtkIsAcyclicHierarchy_rec( pNtkNext ) ) + return 0; + pNtk->fHiePath = 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 0 if the network hierachy contains a cycle.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkIsAcyclicHierarchy( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pTemp; + int i, RetValue; + assert( Abc_NtkIsNetlist(pNtk) && pNtk->pDesign ); + // clear the modules + Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pTemp, i ) + pTemp->fHieVisited = pTemp->fHiePath = 0; + // traverse + pNtk->fHiePath = 1; + RetValue = Abc_NtkIsAcyclicHierarchy_rec( pNtk ); + pNtk->fHiePath = 0; + // clear the modules + Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pTemp, i ) + pTemp->fHieVisited = pTemp->fHiePath = 0; + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Returns 0 if CI names are repeated.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkNamesCompare( char ** pName1, char ** pName2 ) +{ + return strcmp( *pName1, *pName2 ); +} + +/**Function************************************************************* + + Synopsis [Returns 0 if CI names are repeated.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCheckUniqueCiNames( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNames; + Abc_Obj_t * pObj; + int i, fRetValue = 1; + assert( !Abc_NtkIsNetlist(pNtk) ); + vNames = Vec_PtrAlloc( Abc_NtkCiNum(pNtk) ); + Abc_NtkForEachCi( pNtk, pObj, i ) + Vec_PtrPush( vNames, Abc_ObjName(pObj) ); + Vec_PtrSort( vNames, (int (*)(const void *, const void *))Abc_NtkNamesCompare ); + for ( i = 1; i < Abc_NtkCiNum(pNtk); i++ ) + if ( !strcmp( (const char *)Vec_PtrEntry(vNames,i-1), (const char *)Vec_PtrEntry(vNames,i) ) ) + { + printf( "Abc_NtkCheck: Repeated CI names: %s and %s.\n", (char*)Vec_PtrEntry(vNames,i-1), (char*)Vec_PtrEntry(vNames,i) ); + fRetValue = 0; + } + Vec_PtrFree( vNames ); + return fRetValue; +} + +/**Function************************************************************* + + Synopsis [Returns 0 if CO names are repeated.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCheckUniqueCoNames( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNames; + Abc_Obj_t * pObj; + int i, fRetValue = 1; + assert( !Abc_NtkIsNetlist(pNtk) ); + vNames = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Vec_PtrPush( vNames, Abc_ObjName(pObj) ); + Vec_PtrSort( vNames, (int (*)(const void *, const void *))Abc_NtkNamesCompare ); + for ( i = 1; i < Abc_NtkCoNum(pNtk); i++ ) + { +// printf( "%s\n", Vec_PtrEntry(vNames,i) ); + if ( !strcmp( (const char *)Vec_PtrEntry(vNames,i-1), (const char *)Vec_PtrEntry(vNames,i) ) ) + { + printf( "Abc_NtkCheck: Repeated CO names: %s and %s.\n", (char*)Vec_PtrEntry(vNames,i-1), (char*)Vec_PtrEntry(vNames,i) ); + fRetValue = 0; + } + } + Vec_PtrFree( vNames ); + return fRetValue; +} + +/**Function************************************************************* + + Synopsis [Returns 0 if there is a pair of CI/CO with the same name and logic in between.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCheckUniqueCioNames( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj, * pObjCi, * pFanin; + int i, nCiId, fRetValue = 1; + assert( !Abc_NtkIsNetlist(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + nCiId = Nm_ManFindIdByNameTwoTypes( pNtk->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO ); + if ( nCiId == -1 ) + continue; + pObjCi = Abc_NtkObj( pNtk, nCiId ); + assert( !strcmp( Abc_ObjName(pObj), Abc_ObjName(pObjCi) ) ); + pFanin = Abc_ObjFanin0(pObj); + if ( pFanin != pObjCi ) + { + printf( "Abc_NtkCheck: A CI/CO pair share the name (%s) but do not link directly. The name of the CO fanin is %s.\n", + Abc_ObjName(pObj), Abc_ObjName(Abc_ObjFanin0(pObj)) ); + fRetValue = 0; + } + } + return fRetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/abcDfs.c b/yosys/abc/src/base/abc/abcDfs.c new file mode 100644 index 00000000000..68c005a5e32 --- /dev/null +++ b/yosys/abc/src/base/abc/abcDfs.c @@ -0,0 +1,1918 @@ +/**CFile**************************************************************** + + FileName [abcDfs.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures that use depth-first search.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcDfs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "proof/cec/cec.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanin; + int i; + assert( !Abc_ObjIsNet(pNode) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // skip the CI + if ( Abc_ObjIsCi(pNode) || (Abc_NtkIsStrash(pNode->pNtk) && Abc_AigNodeIsConst(pNode)) ) + return; + assert( Abc_ObjIsNode( pNode ) || Abc_ObjIsBox( pNode ) ); + // visit the transitive fanin of the node + Abc_ObjForEachFanin( pNode, pFanin, i ) + { +// pFanin = Abc_ObjFanin( pNode, Abc_ObjFaninNum(pNode)-1-i ); + Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(pFanin), vNodes ); + } + // add the node after the fanins have been added + Vec_PtrPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns the DFS ordered array of logic nodes.] + + Description [Collects only the internal nodes, leaving out CIs and CO. + However it marks with the current TravId both CIs and COs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfs( Abc_Ntk_t * pNtk, int fCollectAll ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + if ( pNtk->nBarBufs2 > 0 ) + { + Abc_NtkForEachBarBuf( pNtk, pObj, i ) + { + Abc_NodeSetTravIdCurrent( pObj ); + Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)), vNodes ); + Vec_PtrPush( vNodes, pObj ); + } + } + Abc_NtkForEachCo( pNtk, pObj, i ) + { + Abc_NodeSetTravIdCurrent( pObj ); + Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)), vNodes ); + } + // collect dangling nodes if asked to + if ( fCollectAll ) + { + Abc_NtkForEachNode( pNtk, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + Abc_NtkDfs_rec( pObj, vNodes ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Returns the DFS ordered array of logic nodes.] + + Description [Collects only the internal nodes, leaving out CIs and CO. + However it marks with the current TravId both CIs and COs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfs2( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes = Vec_PtrAlloc( 100 ); + Abc_Obj_t * pObj; int i; + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + Abc_NodeSetTravIdCurrent( pObj ); + Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)), vNodes ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Returns the DFS ordered array of logic nodes.] + + Description [Collects only the internal nodes, leaving out PIs, POs and latches.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ) +{ + Vec_Ptr_t * vNodes; + int i; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + // go through the PO nodes and call for each of them + for ( i = 0; i < nNodes; i++ ) + { + if ( Abc_NtkIsStrash(pNtk) && Abc_AigNodeIsConst(ppNodes[i]) ) + continue; + if ( Abc_ObjIsCo(ppNodes[i]) ) + { + Abc_NodeSetTravIdCurrent(ppNodes[i]); + Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(Abc_ObjFanin0(ppNodes[i])), vNodes ); + } + else if ( Abc_ObjIsNode(ppNodes[i]) || Abc_ObjIsCi(ppNodes[i]) ) + Abc_NtkDfs_rec( ppNodes[i], vNodes ); + } + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfsReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanout; + int i; + assert( !Abc_ObjIsNet(pNode) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // skip the CI + if ( Abc_ObjIsCo(pNode) ) + return; + assert( Abc_ObjIsNode( pNode ) ); + // visit the transitive fanin of the node + pNode = Abc_ObjFanout0Ntk(pNode); + Abc_ObjForEachFanout( pNode, pFanout, i ) + Abc_NtkDfsReverse_rec( pFanout, vNodes ); + // add the node after the fanins have been added + Vec_PtrPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns the reverse DFS ordered array of logic nodes.] + + Description [Collects only the internal nodes, leaving out CIs/COs. + However it marks both CIs and COs with the current TravId.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsReverse( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pFanout; + int i, k; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachCi( pNtk, pObj, i ) + { + Abc_NodeSetTravIdCurrent( pObj ); + pObj = Abc_ObjFanout0Ntk(pObj); + Abc_ObjForEachFanout( pObj, pFanout, k ) + Abc_NtkDfsReverse_rec( pFanout, vNodes ); + } + // add constant nodes in the end + if ( !Abc_NtkIsStrash(pNtk) ) { + Abc_NtkForEachNode( pNtk, pObj, i ) + if ( Abc_NodeIsConst(pObj) ) + Vec_PtrPush( vNodes, pObj ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfsReverseNodes_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanout; + int i; + assert( !Abc_ObjIsNet(pNode) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // skip the CI + if ( Abc_ObjIsCo(pNode) ) + return; + assert( Abc_ObjIsNode( pNode ) ); + // visit the transitive fanin of the node + pNode = Abc_ObjFanout0Ntk(pNode); + Abc_ObjForEachFanout( pNode, pFanout, i ) + Abc_NtkDfsReverseNodes_rec( pFanout, vNodes ); + // add the node after the fanins have been added +// Vec_PtrPush( vNodes, pNode ); + Vec_PtrFillExtra( vNodes, pNode->Level + 1, NULL ); + pNode->pCopy = (Abc_Obj_t *)Vec_PtrEntry( vNodes, pNode->Level ); + Vec_PtrWriteEntry( vNodes, pNode->Level, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns the levelized array of TFO nodes.] + + Description [Collects the levelized array of internal nodes, leaving out CIs/COs. + However it marks both CIs and COs with the current TravId.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsReverseNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pFanout; + int i, k; + assert( Abc_NtkIsStrash(pNtk) ); + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrStart( Abc_AigLevel(pNtk) + 1 ); + for ( i = 0; i < nNodes; i++ ) + { + pObj = ppNodes[i]; + assert( Abc_ObjIsCi(pObj) ); + Abc_NodeSetTravIdCurrent( pObj ); + pObj = Abc_ObjFanout0Ntk(pObj); + Abc_ObjForEachFanout( pObj, pFanout, k ) + Abc_NtkDfsReverseNodes_rec( pFanout, vNodes ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Returns the levelized array of TFO nodes.] + + Description [Collects the levelized array of internal nodes, leaving out CIs/COs. + However it marks both CIs and COs with the current TravId. + Collects only the nodes whose support does not exceed the set of given CI nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsReverseNodesContained( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pFanout, * pFanin; + int i, k, m, nLevels; + // set the levels + nLevels = Abc_NtkLevel( pNtk ); + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrStart( nLevels + 2 ); + for ( i = 0; i < nNodes; i++ ) + { + pObj = ppNodes[i]; + assert( Abc_ObjIsCi(pObj) ); + Abc_NodeSetTravIdCurrent( pObj ); + // add to the array + assert( pObj->Level == 0 ); + pObj->pCopy = (Abc_Obj_t *)Vec_PtrEntry( vNodes, pObj->Level ); + Vec_PtrWriteEntry( vNodes, pObj->Level, pObj ); + } + // iterate through the levels + for ( i = 0; i <= nLevels; i++ ) + { + // iterate through the nodes on each level + for ( pObj = (Abc_Obj_t *)Vec_PtrEntry(vNodes, i); pObj; pObj = pObj->pCopy ) + { + // iterate through the fanouts of each node + Abc_ObjForEachFanout( pObj, pFanout, k ) + { + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pFanout) ) + continue; + // visit the fanins of this fanout + Abc_ObjForEachFanin( pFanout, pFanin, m ) + { + if ( !Abc_NodeIsTravIdCurrent(pFanin) ) + break; + } + if ( m < Abc_ObjFaninNum(pFanout) ) + continue; + // all fanins are already collected + + // mark the node as visited + Abc_NodeSetTravIdCurrent( pFanout ); + // handle the COs + if ( Abc_ObjIsCo(pFanout) ) + pFanout->Level = nLevels + 1; + // add to the array + pFanout->pCopy = (Abc_Obj_t *)Vec_PtrEntry( vNodes, pFanout->Level ); + Vec_PtrWriteEntry( vNodes, pFanout->Level, pFanout ); + // handle the COs + if ( Abc_ObjIsCo(pFanout) ) + pFanout->Level = 0; + } + } + } + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfsSeq_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanin; + int i; + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // visit the transitive fanin of the node + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_NtkDfsSeq_rec( pFanin, vNodes ); + // add the node after the fanins have been added + Vec_PtrPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of nodes and latches reachable from POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsSeq( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i; + assert( !Abc_NtkIsNetlist(pNtk) ); + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkDfsSeq_rec( pObj, vNodes ); + // mark the PIs + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkDfsSeq_rec( pObj, vNodes ); + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfsSeqReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanout; + int i; + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // visit the transitive fanin of the node + Abc_ObjForEachFanout( pNode, pFanout, i ) + Abc_NtkDfsSeqReverse_rec( pFanout, vNodes ); + // add the node after the fanins have been added + Vec_PtrPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of nodes and latches reachable from POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsSeqReverse( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i; + assert( !Abc_NtkIsNetlist(pNtk) ); + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkDfsSeqReverse_rec( pObj, vNodes ); + // mark the logic feeding into POs + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkDfsSeq_rec( pObj, vNodes ); + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Iterative version of the DFS procedure.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfs_iter( Vec_Ptr_t * vStack, Abc_Obj_t * pRoot, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pNode, * pFanin; + int iFanin; + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pRoot ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pRoot ); + // skip the CI + if ( Abc_ObjIsCi(pRoot) || (Abc_NtkIsStrash(pRoot->pNtk) && Abc_AigNodeIsConst(pRoot)) ) + return; + // add the CI + Vec_PtrClear( vStack ); + Vec_PtrPush( vStack, pRoot ); + Vec_PtrPush( vStack, (void *)0 ); + while ( Vec_PtrSize(vStack) > 0 ) + { + // get the node and its fanin + iFanin = (int)(ABC_PTRINT_T)Vec_PtrPop(vStack); + pNode = (Abc_Obj_t *)Vec_PtrPop(vStack); + assert( !Abc_ObjIsNet(pNode) ); + // add it to the array of nodes if we finished + if ( iFanin == Abc_ObjFaninNum(pNode) ) + { + Vec_PtrPush( vNodes, pNode ); + continue; + } + // explore the next fanin + Vec_PtrPush( vStack, pNode ); + Vec_PtrPush( vStack, (void *)(ABC_PTRINT_T)(iFanin+1) ); + // get the fanin + pFanin = Abc_ObjFanin0Ntk( Abc_ObjFanin(pNode,iFanin) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pFanin ) ) + continue; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pFanin ); + // skip the CI + if ( Abc_ObjIsCi(pFanin) || (Abc_NtkIsStrash(pFanin->pNtk) && Abc_AigNodeIsConst(pFanin)) ) + continue; + Vec_PtrPush( vStack, pFanin ); + Vec_PtrPush( vStack, (void *)0 ); + } +} + +/**Function************************************************************* + + Synopsis [Returns the DFS ordered array of logic nodes.] + + Description [Collects only the internal nodes, leaving CIs and CO. + However it marks with the current TravId both CIs and COs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsIter( Abc_Ntk_t * pNtk, int fCollectAll ) +{ + Vec_Ptr_t * vNodes, * vStack; + Abc_Obj_t * pObj; + int i; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 1000 ); + vStack = Vec_PtrAlloc( 1000 ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + Abc_NodeSetTravIdCurrent( pObj ); + Abc_NtkDfs_iter( vStack, Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)), vNodes ); + } + // collect dangling nodes if asked to + if ( fCollectAll ) + { + Abc_NtkForEachNode( pNtk, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + Abc_NtkDfs_iter( vStack, pObj, vNodes ); + } + Vec_PtrFree( vStack ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Returns the DFS ordered array of logic nodes.] + + Description [Collects only the internal nodes, leaving CIs and CO. + However it marks with the current TravId both CIs and COs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsIterNodes( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots ) +{ + Vec_Ptr_t * vNodes, * vStack; + Abc_Obj_t * pObj; + int i; + Abc_NtkIncrementTravId( pNtk ); + vNodes = Vec_PtrAlloc( 1000 ); + vStack = Vec_PtrAlloc( 1000 ); + Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent(Abc_ObjRegular(pObj)) ) + Abc_NtkDfs_iter( vStack, Abc_ObjRegular(pObj), vNodes ); + Vec_PtrFree( vStack ); + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfsHie_rec( Abc_Obj_t * pObj, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanin; + int i; + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pObj ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pObj ); + // visit the transitive fanin of the node + Abc_ObjForEachFanin( pObj, pFanin, i ) + Abc_NtkDfsHie_rec( pFanin, vNodes ); + // add the node after the fanins have been added + Vec_PtrPush( vNodes, pObj ); +} + +/**Function************************************************************* + + Synopsis [Returns the DFS ordered array of all objects.] + + Description [This procedure collects everything from POs to PIs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsHie( Abc_Ntk_t * pNtk, int fCollectAll ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkDfsHie_rec( pObj, vNodes ); + // collect dangling nodes if asked to + if ( fCollectAll ) + { + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + Abc_NtkDfs_rec( pObj, vNodes ); + } + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if the ordering of nodes is DFS.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkIsDfsOrdered( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode, * pFanin; + int i, k; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // mark the CIs + Abc_NtkForEachCi( pNtk, pNode, i ) + Abc_NodeSetTravIdCurrent( pNode ); + // go through the nodes + Abc_NtkForEachNode( pNtk, pNode, i ) + { + // check the fanins of the node + Abc_ObjForEachFanin( pNode, pFanin, k ) + if ( !Abc_NodeIsTravIdCurrent(pFanin) ) + return 0; + // check the choices of the node + if ( Abc_NtkIsStrash(pNtk) && Abc_AigNodeIsChoice(pNode) ) + for ( pFanin = (Abc_Obj_t *)pNode->pData; pFanin; pFanin = (Abc_Obj_t *)pFanin->pData ) + if ( !Abc_NodeIsTravIdCurrent(pFanin) ) + return 0; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Create DFS ordering of nets.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfsNets_rec( Abc_Obj_t * pNet, Vec_Ptr_t * vNets ) +{ + Abc_Obj_t * pNext; + Abc_Obj_t * pNode; int i; + assert( Abc_ObjIsNet(pNet) ); + if ( Abc_NodeIsTravIdCurrent( pNet ) ) + return; + Abc_NodeSetTravIdCurrent( pNet ); + pNode = Abc_ObjFanin0( pNet ); + Abc_ObjForEachFanin( pNode, pNext, i ) + Abc_NtkDfsNets_rec( pNext, vNets ); + Abc_ObjForEachFanout( pNode, pNext, i ) + Vec_PtrPush( vNets, pNext ); +} +Vec_Ptr_t * Abc_NtkDfsNets( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNets; + Abc_Obj_t * pObj; int i; + vNets = Vec_PtrAlloc( 100 ); + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachCi( pNtk, pObj, i ) + Abc_NodeSetTravIdCurrent( Abc_ObjFanout0(pObj) ); + Abc_NtkForEachCi( pNtk, pObj, i ) + Vec_PtrPush( vNets, Abc_ObjFanout0(pObj) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_NtkDfsNets_rec( Abc_ObjFanin0(pObj), vNets ); + return vNets; +} + +/**Function************************************************************* + + Synopsis [Returns the DFS ordered array of logic nodes.] + + Description [Collects only the internal nodes, leaving out CIs and CO. + However it marks with the current TravId both CIs and COs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfsWithBoxes_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanin; + int i; + assert( !Abc_ObjIsNet(pNode) ); + if ( Abc_ObjIsBo(pNode) ) + pNode = Abc_ObjFanin0(pNode); + if ( Abc_ObjIsPi(pNode) ) + return; + assert( Abc_ObjIsNode( pNode ) || Abc_ObjIsBox( pNode ) ); + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + Abc_NodeSetTravIdCurrent( pNode ); + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( Abc_ObjIsBox(pNode) ) + pFanin = Abc_ObjFanin0(pFanin); + assert( Abc_ObjIsNet(pFanin) ); + Abc_NtkDfsWithBoxes_rec( Abc_ObjFanin0Ntk(pFanin), vNodes ); + } + Vec_PtrPush( vNodes, pNode ); +} +Vec_Ptr_t * Abc_NtkDfsWithBoxes( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i; + Abc_NtkIncrementTravId( pNtk ); + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachPo( pNtk, pObj, i ) + { + assert( Abc_ObjIsNet(Abc_ObjFanin0(pObj)) ); + Abc_NtkDfsWithBoxes_rec( Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)), vNodes ); + } + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkNodeSupport_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanin; + int i; + assert( !Abc_ObjIsNet(pNode) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // collect the CI + if ( Abc_ObjIsCi(pNode) || (Abc_NtkIsStrash(pNode->pNtk) && Abc_ObjFaninNum(pNode) == 0) ) + { + Vec_PtrPush( vNodes, pNode ); + return; + } + assert( Abc_ObjIsNode( pNode ) ); + // visit the transitive fanin of the node + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_NtkNodeSupport_rec( Abc_ObjFanin0Ntk(pFanin), vNodes ); +} + +/**Function************************************************************* + + Synopsis [Returns the set of CI nodes in the support of the given nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkSupport( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode; + int i; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + // go through the PO nodes and call for each of them + Abc_NtkForEachCo( pNtk, pNode, i ) + Abc_NtkNodeSupport_rec( Abc_ObjFanin0(pNode), vNodes ); + // add unused CIs + Abc_NtkForEachCi( pNtk, pNode, i ) + if ( !Abc_NodeIsTravIdCurrent( pNode ) ) + Vec_PtrPush( vNodes, pNode ); + assert( Vec_PtrSize(vNodes) == Abc_NtkCiNum(pNtk) ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Returns the set of CI nodes in the support of the given nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkNodeSupport( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes ) +{ + Vec_Ptr_t * vNodes; + int i; + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + // go through the PO nodes and call for each of them + for ( i = 0; i < nNodes; i++ ) + if ( Abc_ObjIsCo(ppNodes[i]) && Abc_ObjFaninNum(Abc_ObjFanin0(ppNodes[i])) != 0 ) + Abc_NtkNodeSupport_rec( Abc_ObjFanin0(ppNodes[i]), vNodes ); + else if ( !Abc_ObjIsCo(ppNodes[i]) && Abc_ObjFaninNum(ppNodes[i]) != 0 ) + Abc_NtkNodeSupport_rec( ppNodes[i], vNodes ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Returns the set of CI node IDs in the support of the given node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkNodeSupportInt_rec( Abc_Obj_t * pNode, Vec_Int_t * vNodes ) +{ + Abc_Obj_t * pFanin; + int i; + assert( !Abc_ObjIsNet(pNode) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // collect the CI + if ( Abc_ObjIsCi(pNode) || (Abc_NtkIsStrash(pNode->pNtk) && Abc_ObjFaninNum(pNode) == 0) ) + { + if ( Abc_ObjIsCi(pNode) ) + Vec_IntPush( vNodes, pNode->iTemp ); + return; + } + assert( Abc_ObjIsNode( pNode ) ); + // visit the transitive fanin of the node + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_NtkNodeSupportInt_rec( Abc_ObjFanin0Ntk(pFanin), vNodes ); +} +Vec_Int_t * Abc_NtkNodeSupportInt( Abc_Ntk_t * pNtk, int iCo ) +{ + Vec_Int_t * vNodes; + Abc_Obj_t * pObj; + int i; + if ( iCo < 0 || iCo >= Abc_NtkCoNum(pNtk) ) + return NULL; + // save node indices in the CI nodes + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->iTemp = i; + // collect the indexes of CI nodes in the TFI of the CO node + Abc_NtkIncrementTravId( pNtk ); + pObj = Abc_NtkCo( pNtk, iCo ); + vNodes = Vec_IntAlloc( 100 ); + Abc_NtkNodeSupportInt_rec( Abc_ObjFanin0(pObj), vNodes ); + Vec_IntSort( vNodes, 0 ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Derives GIA comparing two outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkFunctionalIsoGia_rec( Gia_Man_t * pNew, Abc_Obj_t * pNode ) +{ + int iLit0, iLit1; + if ( Abc_NodeIsTravIdCurrent(pNode) || Abc_ObjFaninNum(pNode) == 0 || Abc_ObjIsCi(pNode) ) + return pNode->iTemp; + assert( Abc_ObjIsNode( pNode ) ); + Abc_NodeSetTravIdCurrent( pNode ); + iLit0 = Abc_NtkFunctionalIsoGia_rec( pNew, Abc_ObjFanin0(pNode) ); + iLit1 = Abc_NtkFunctionalIsoGia_rec( pNew, Abc_ObjFanin1(pNode) ); + iLit0 = Abc_LitNotCond( iLit0, Abc_ObjFaninC0(pNode) ); + iLit1 = Abc_LitNotCond( iLit1, Abc_ObjFaninC1(pNode) ); + return (pNode->iTemp = Gia_ManHashAnd(pNew, iLit0, iLit1)); +} +Gia_Man_t * Abc_NtkFunctionalIsoGia( Abc_Ntk_t * pNtk, int iCo1, int iCo2, int fCommon ) +{ + Gia_Man_t * pNew = NULL, * pTemp; + Vec_Int_t * vSupp1 = Abc_NtkNodeSupportInt( pNtk, iCo1 ); + Vec_Int_t * vSupp2 = Abc_NtkNodeSupportInt( pNtk, iCo2 ); + if ( Vec_IntSize(vSupp1) == Vec_IntSize(vSupp2) ) + { + Abc_Obj_t * pObj; + int i, iCi, iLit1, iLit2; + pNew = Gia_ManStart( 1000 ); + pNew->pName = Abc_UtilStrsav( pNtk->pName ); + pNew->pSpec = Abc_UtilStrsav( pNtk->pSpec ); + Gia_ManHashStart( pNew ); + // put commom together + if ( fCommon ) + { + Vec_Int_t * vCommon = Vec_IntAlloc( Vec_IntSize(vSupp1) ); + Vec_IntTwoRemoveCommon( vSupp1, vSupp2, vCommon ); + Vec_IntAppend( vSupp1, vCommon ); + Vec_IntAppend( vSupp2, vCommon ); + Vec_IntFree( vCommon ); + assert( Vec_IntSize(vSupp1) == Vec_IntSize(vSupp2) ); + } + // primary inputs + Abc_AigConst1(pNtk)->iTemp = 1; + Vec_IntForEachEntry( vSupp1, iCi, i ) + Abc_NtkCi(pNtk, iCi)->iTemp = Gia_ManAppendCi(pNew); + // create the first cone + Abc_NtkIncrementTravId( pNtk ); + pObj = Abc_NtkCo( pNtk, iCo1 ); + iLit1 = Abc_NtkFunctionalIsoGia_rec( pNew, Abc_ObjFanin0(pObj) ); + iLit1 = Abc_LitNotCond( iLit1, Abc_ObjFaninC0(pObj) ); + // primary inputs + Vec_IntForEachEntry( vSupp2, iCi, i ) + Abc_NtkCi(pNtk, iCi)->iTemp = Gia_ManCiLit(pNew, i); + // create the second cone + Abc_NtkIncrementTravId( pNtk ); + pObj = Abc_NtkCo( pNtk, iCo2 ); + iLit2 = Abc_NtkFunctionalIsoGia_rec( pNew, Abc_ObjFanin0(pObj) ); + iLit2 = Abc_LitNotCond( iLit2, Abc_ObjFaninC0(pObj) ); + Gia_ManAppendCo( pNew, iLit1 ); + Gia_ManAppendCo( pNew, iLit2 ); + // perform cleanup + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + } + Vec_IntFree( vSupp1 ); + Vec_IntFree( vSupp2 ); + return pNew; +} +int Abc_NtkFunctionalIsoInt( Abc_Ntk_t * pNtk, int iCo1, int iCo2, int fCommon ) +{ + Gia_Man_t * pGia; int Value; + assert( Abc_NtkIsStrash(pNtk) ); + if ( iCo1 < 0 || iCo1 >= Abc_NtkCoNum(pNtk) ) + return 0; + if ( iCo2 < 0 || iCo2 >= Abc_NtkCoNum(pNtk) ) + return 0; + pGia = Abc_NtkFunctionalIsoGia( pNtk, iCo1, iCo2, fCommon ); + if ( pGia == NULL ) + return 0; + Value = Cec_ManVerifySimple( pGia ); + Gia_ManStop( pGia ); + return (int)(Value == 1); +} +int Abc_NtkFunctionalIso( Abc_Ntk_t * pNtk, int iCo1, int iCo2, int fCommon ) +{ + Abc_Ntk_t * pNtkNew; int Result; + if ( Abc_NtkIsStrash(pNtk) ) + return Abc_NtkFunctionalIsoInt( pNtk, iCo1, iCo2, fCommon ); + pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 ); + Result = Abc_NtkFunctionalIsoInt( pNtkNew, iCo1, iCo2, fCommon ); + Abc_NtkDelete( pNtkNew ); + return Result; +} + + +/**Function************************************************************* + + Synopsis [Computes support size of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjSuppSize_rec( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin; + int i, Counter = 0; + if ( Abc_NodeIsTravIdCurrent(pObj) ) + return 0; + Abc_NodeSetTravIdCurrent(pObj); + if ( Abc_ObjIsPi(pObj) ) + return 1; + assert( Abc_ObjIsNode(pObj) || Abc_ObjIsBox(pObj) ); + Abc_ObjForEachFanin( pObj, pFanin, i ) + Counter += Abc_ObjSuppSize_rec( pFanin ); + return Counter; +} +/**Function************************************************************* + + Synopsis [Computes support size of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjSuppSize( Abc_Obj_t * pObj ) +{ + Abc_NtkIncrementTravId( Abc_ObjNtk(pObj) ); + return Abc_ObjSuppSize_rec( pObj ); +} +/**Function************************************************************* + + Synopsis [Computes support size of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkSuppSizeTest( Abc_Ntk_t * p ) +{ + Abc_Obj_t * pObj; + int i, Counter = 0; + abctime clk = Abc_Clock(); + Abc_NtkForEachObj( p, pObj, i ) + if ( Abc_ObjIsNode(pObj) ) + Counter += (Abc_ObjSuppSize(pObj) <= 16); + printf( "Nodes with small support %d (out of %d)\n", Counter, Abc_NtkNodeNum(p) ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Computes the sum total of supports of all outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSupportSum( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vSupp; + Abc_Obj_t * pObj; + int i, nTotalSupps = 0; + Abc_NtkForEachCo( pNtk, pObj, i ) + { + vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); + nTotalSupps += Vec_PtrSize( vSupp ); + Vec_PtrFree( vSupp ); + } + printf( "Total supports = %d.\n", nTotalSupps ); +} + + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_AigDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanin; + int i; + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // skip the PI + if ( Abc_ObjIsCi(pNode) || Abc_AigNodeIsConst(pNode) ) + return; + assert( Abc_ObjIsNode( pNode ) ); + // visit the transitive fanin of the node + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_AigDfs_rec( pFanin, vNodes ); + // visit the equivalent nodes + if ( Abc_AigNodeIsChoice( pNode ) ) + for ( pFanin = (Abc_Obj_t *)pNode->pData; pFanin; pFanin = (Abc_Obj_t *)pFanin->pData ) + Abc_AigDfs_rec( pFanin, vNodes ); + // add the node after the fanins have been added + Vec_PtrPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns the DFS ordered array of logic nodes.] + + Description [Collects only the internal nodes, leaving out CIs/COs. + However it marks both CIs and COs with the current TravId.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_AigDfs( Abc_Ntk_t * pNtk, int fCollectAll, int fCollectCos ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode; + int i; + assert( Abc_NtkIsStrash(pNtk) ); + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + // go through the PO nodes and call for each of them + Abc_NtkForEachCo( pNtk, pNode, i ) + { + Abc_AigDfs_rec( Abc_ObjFanin0(pNode), vNodes ); + Abc_NodeSetTravIdCurrent( pNode ); + if ( fCollectCos ) + Vec_PtrPush( vNodes, pNode ); + } + // collect dangling nodes if asked to + if ( fCollectAll ) + { + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( !Abc_NodeIsTravIdCurrent(pNode) ) + Abc_AigDfs_rec( pNode, vNodes ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Returns the DFS ordered array of logic nodes.] + + Description [Collects only the internal nodes, leaving out CIs/COs. + However it marks both CIs and COs with the current TravId.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_AigDfsMap( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode; + int i; + assert( Abc_NtkIsStrash(pNtk) ); + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + // collect cones of barbufs + Abc_NtkForEachCo( pNtk, pNode, i ) + { + if ( i < Abc_NtkCoNum(pNtk) - pNtk->nBarBufs ) + continue; + Abc_AigDfs_rec( Abc_ObjFanin0(pNode), vNodes ); + Abc_NodeSetTravIdCurrent( pNode ); + // collect latch as a placeholder + assert( Abc_ObjIsLatch(Abc_ObjFanout0(pNode)) ); + Vec_PtrPush( vNodes, Abc_ObjFanout0(pNode) ); + } + // collect nodes of real POs + Abc_NtkForEachCo( pNtk, pNode, i ) + { + if ( i >= Abc_NtkCoNum(pNtk) - pNtk->nBarBufs ) + break; + Abc_AigDfs_rec( Abc_ObjFanin0(pNode), vNodes ); + assert( Abc_ObjIsCo(pNode) ); + Abc_NodeSetTravIdCurrent( pNode ); + } + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Collects nodes in the DFS manner by level.] + + Description [The number of levels should be set!!!] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_DfsLevelizedTfo_rec( Abc_Obj_t * pNode, Vec_Vec_t * vLevels ) +{ + Abc_Obj_t * pFanout; + int i; + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // skip the terminals + if ( Abc_ObjIsCo(pNode) ) + return; + assert( Abc_ObjIsNode(pNode) ); + // add the node to the structure + Vec_VecPush( vLevels, pNode->Level, pNode ); + // visit the TFO + Abc_ObjForEachFanout( pNode, pFanout, i ) + Abc_DfsLevelizedTfo_rec( pFanout, vLevels ); +} + +/**Function************************************************************* + + Synopsis [Collects nodes in the DFS manner by level.] + + Description [The number of levels should be set!!!] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Vec_t * Abc_DfsLevelized( Abc_Obj_t * pNode, int fTfi ) +{ + Vec_Vec_t * vLevels; + Abc_Obj_t * pFanout; + int i; + assert( fTfi == 0 ); + assert( !Abc_NtkIsNetlist(pNode->pNtk) ); + // set the traversal ID + Abc_NtkIncrementTravId( pNode->pNtk ); + vLevels = Vec_VecAlloc( 100 ); + if ( Abc_ObjIsNode(pNode) ) + Abc_DfsLevelizedTfo_rec( pNode, vLevels ); + else + { + assert( Abc_ObjIsCi(pNode) ); + Abc_NodeSetTravIdCurrent( pNode ); + Abc_ObjForEachFanout( pNode, pFanout, i ) + Abc_DfsLevelizedTfo_rec( pFanout, vLevels ); + } + return vLevels; +} + + +/**Function************************************************************* + + Synopsis [Recursively counts the number of logic levels of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkLevel_rec( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNext; + int i, Level; + assert( !Abc_ObjIsNet(pNode) ); + // skip the PI + if ( Abc_ObjIsCi(pNode) ) + return pNode->Level; + assert( Abc_ObjIsNode( pNode ) || pNode->Type == ABC_OBJ_CONST1); + // if this node is already visited, return + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return pNode->Level; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // visit the transitive fanin + pNode->Level = 0; + Abc_ObjForEachFanin( pNode, pNext, i ) + { + Level = Abc_NtkLevel_rec( Abc_ObjFanin0Ntk(pNext) ); + if ( pNode->Level < (unsigned)Level ) + pNode->Level = Level; + } + if ( Abc_ObjFaninNum(pNode) > 0 && !Abc_ObjIsBarBuf(pNode) ) + pNode->Level++; + return pNode->Level; +} + +/**Function************************************************************* + + Synopsis [Recursively counts the number of logic levels of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkLevelReverse_rec( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNext; + int i, Level; + assert( !Abc_ObjIsNet(pNode) ); + // skip the PI + if ( Abc_ObjIsCo(pNode) ) + return pNode->Level; + assert( Abc_ObjIsNode( pNode ) || pNode->Type == ABC_OBJ_CONST1); + // if this node is already visited, return + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return pNode->Level; + // mark the node as visited + Abc_NodeSetTravIdCurrent( pNode ); + // visit the transitive fanin + pNode->Level = 0; + Abc_ObjForEachFanout( pNode, pNext, i ) + { + Level = Abc_NtkLevelReverse_rec( Abc_ObjFanout0Ntk(pNext) ); + if ( pNode->Level < (unsigned)Level ) + pNode->Level = Level; + } + if ( Abc_ObjFaninNum(pNode) > 0 && !Abc_ObjIsBarBuf(pNode) ) + pNode->Level++; + return pNode->Level; +} + +/**Function************************************************************* + + Synopsis [Computes the number of logic levels not counting PIs/POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Vec_t * Abc_NtkLevelize( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + Vec_Vec_t * vLevels; + int nLevels, i; + nLevels = Abc_NtkLevel( pNtk ); + vLevels = Vec_VecStart( nLevels + 1 ); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + assert( (int)pObj->Level <= nLevels ); + Vec_VecPush( vLevels, pObj->Level, pObj ); + } + return vLevels; +} + +/**Function************************************************************* + + Synopsis [Computes the number of logic levels not counting PIs/POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkLevel( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, LevelsMax; + // set the CI levels + if ( pNtk->pManTime == NULL || pNtk->AndGateDelay <= 0 ) + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->Level = 0; + else + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->Level = (int)(Abc_MaxFloat(0, Abc_NodeReadArrivalWorst(pNode)) / pNtk->AndGateDelay); + // perform the traversal + LevelsMax = 0; + Abc_NtkIncrementTravId( pNtk ); + if ( pNtk->nBarBufs == 0 ) + { + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Abc_NtkLevel_rec( pNode ); + if ( LevelsMax < (int)pNode->Level ) + LevelsMax = (int)pNode->Level; + } + } + else + { + Abc_NtkForEachLiPo( pNtk, pNode, i ) + { + Abc_Obj_t * pDriver = Abc_ObjFanin0(pNode); + Abc_NtkLevel_rec( pDriver ); + if ( LevelsMax < (int)pDriver->Level ) + LevelsMax = (int)pDriver->Level; + // transfer the delay + if ( i < pNtk->nBarBufs ) + Abc_ObjFanout0(Abc_ObjFanout0(pNode))->Level = pDriver->Level; + } + } + return LevelsMax; +} + +/**Function************************************************************* + + Synopsis [Computes the number of logic levels not counting PIs/POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkLevelReverse( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, LevelsMax; + // set the CO levels to zero + Abc_NtkForEachCo( pNtk, pNode, i ) + pNode->Level = 0; + // perform the traversal + LevelsMax = 0; + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + Abc_NtkLevelReverse_rec( pNode ); + if ( LevelsMax < (int)pNode->Level ) + LevelsMax = (int)pNode->Level; + } + return LevelsMax; +} +int Abc_NtkLevelR( Abc_Ntk_t * pNtk ) +{ + int i, LevelMax = Abc_NtkLevelReverse( pNtk ); + Abc_Obj_t * pNode; + Abc_NtkForEachObj( pNtk, pNode, i ) + pNode->Level = (int)(LevelMax - pNode->Level + 1); + return LevelMax; +} + + +/**Function************************************************************* + + Synopsis [Recursively detects combinational loops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkIsAcyclic_rec( Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtk = pNode->pNtk; + Abc_Obj_t * pFanin; + int fAcyclic, i; + assert( !Abc_ObjIsNet(pNode) ); + if ( Abc_ObjIsCi(pNode) || Abc_ObjIsBox(pNode) || (Abc_NtkIsStrash(pNode->pNtk) && Abc_AigNodeIsConst(pNode)) ) + return 1; + assert( Abc_ObjIsNode(pNode) ); + // make sure the node is not visited + assert( !Abc_NodeIsTravIdPrevious(pNode) ); + // check if the node is part of the combinational loop + if ( Abc_NodeIsTravIdCurrent(pNode) ) + { + fprintf( stdout, "Network \"%s\" contains combinational loop!\n", Abc_NtkName(pNtk) ); + fprintf( stdout, "Node \"%s\" is encountered twice on the following path to the COs:\n", Abc_ObjName(pNode) ); + return 0; + } + // mark this node as a node on the current path + Abc_NodeSetTravIdCurrent( pNode ); + // visit the transitive fanin + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + pFanin = Abc_ObjFanin0Ntk(pFanin); + // make sure there is no mixing of networks + assert( pFanin->pNtk == pNode->pNtk ); + // check if the fanin is visited + if ( Abc_NodeIsTravIdPrevious(pFanin) ) + continue; + // traverse the fanin's cone searching for the loop + if ( (fAcyclic = Abc_NtkIsAcyclic_rec(pFanin)) ) + continue; + // return as soon as the loop is detected + fprintf( stdout, " %s ->", Abc_ObjName(pFanin) ); + return 0; + } + // visit choices + if ( Abc_NtkIsStrash(pNode->pNtk) && Abc_AigNodeIsChoice(pNode) ) + { + for ( pFanin = (Abc_Obj_t *)pNode->pData; pFanin; pFanin = (Abc_Obj_t *)pFanin->pData ) + { + // check if the fanin is visited + if ( Abc_NodeIsTravIdPrevious(pFanin) ) + continue; + // traverse the fanin's cone searching for the loop + if ( (fAcyclic = Abc_NtkIsAcyclic_rec(pFanin)) ) + continue; + // return as soon as the loop is detected + fprintf( stdout, " %s", Abc_ObjName(pFanin) ); + fprintf( stdout, " (choice of %s) -> ", Abc_ObjName(pNode) ); + return 0; + } + } + // mark this node as a visited node + Abc_NodeSetTravIdPrevious( pNode ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Detects combinational loops.] + + Description [This procedure is based on the idea suggested by Donald Chai. + As we traverse the network and visit the nodes, we need to distinquish + three types of nodes: (1) those that are visited for the first time, + (2) those that have been visited in this traversal but are currently not + on the traversal path, (3) those that have been visited and are currently + on the travesal path. When the node of type (3) is encountered, it means + that there is a combinational loop. To mark the three types of nodes, + two new values of the traversal IDs are used.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int fAcyclic; + int i; + // set the traversal ID for this DFS ordering + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkIncrementTravId( pNtk ); + // pNode->TravId == pNet->nTravIds means "pNode is on the path" + // pNode->TravId == pNet->nTravIds - 1 means "pNode is visited but is not on the path" + // pNode->TravId < pNet->nTravIds - 1 means "pNode is not visited" + // traverse the network to detect cycles + fAcyclic = 1; + Abc_NtkForEachCo( pNtk, pNode, i ) + { + pNode = Abc_ObjFanin0Ntk(Abc_ObjFanin0(pNode)); + if ( Abc_NodeIsTravIdPrevious(pNode) ) + continue; + // traverse the output logic cone + if ( (fAcyclic = Abc_NtkIsAcyclic_rec(pNode)) ) + continue; + // stop as soon as the first loop is detected + fprintf( stdout, " CO \"%s\"\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + break; + } + return fAcyclic; +} + +/**Function************************************************************* + + Synopsis [Checks for the loops with boxes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkIsAcyclicWithBoxes_rec( Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtk = pNode->pNtk; + Abc_Obj_t * pFanin; + int fAcyclic, i; + assert( !Abc_ObjIsNet(pNode) ); + if ( Abc_ObjIsPi(pNode) || Abc_ObjIsLatch(pNode) || Abc_ObjIsBlackbox(pNode) ) + return 1; + assert( Abc_ObjIsNode(pNode) || Abc_ObjIsBox(pNode) ); + // make sure the node is not visited + assert( !Abc_NodeIsTravIdPrevious(pNode) ); + // check if the node is part of the combinational loop + if ( Abc_NodeIsTravIdCurrent(pNode) ) + { + fprintf( stdout, "Network \"%s\" contains combinational loop!\n", Abc_NtkName(pNtk) ); + if ( Abc_ObjIsBox(pNode) ) + fprintf( stdout, "Box \"%s\" is encountered twice on the following path to the COs:\n", Abc_ObjName(pNode) ); + else + fprintf( stdout, "Node \"%s\" is encountered twice on the following path to the COs:\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + return 0; + } + // mark this node as a node on the current path + Abc_NodeSetTravIdCurrent( pNode ); + // visit the transitive fanin + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( Abc_ObjIsBox(pNode) ) + pFanin = Abc_ObjFanin0(pFanin); + pFanin = Abc_ObjFanin0Ntk(pFanin); + if ( Abc_ObjIsBo(pFanin) ) + pFanin = Abc_ObjFanin0(pFanin); + // check if the fanin is visited + if ( Abc_ObjIsPi(pFanin) || Abc_ObjIsLatch(pFanin) || Abc_ObjIsBlackbox(pFanin) ) + continue; + assert( Abc_ObjIsNode(pFanin) || Abc_ObjIsBox(pFanin) ); + if ( Abc_NodeIsTravIdPrevious(pFanin) ) + continue; + // traverse the fanin's cone searching for the loop + if ( (fAcyclic = Abc_NtkIsAcyclicWithBoxes_rec(pFanin)) ) + continue; + // return as soon as the loop is detected + fprintf( stdout, " %s ->", Abc_ObjName( Abc_ObjIsBox(pFanin) ? pFanin : Abc_ObjFanout0(pFanin) ) ); + return 0; + } + // mark this node as a visited node + assert( Abc_ObjIsNode(pNode) || Abc_ObjIsBox(pNode) ); + Abc_NodeSetTravIdPrevious( pNode ); + return 1; +} +int Abc_NtkIsAcyclicWithBoxes( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int fAcyclic; + int i; + // set the traversal ID for this DFS ordering + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkIncrementTravId( pNtk ); + // pNode->TravId == pNet->nTravIds means "pNode is on the path" + // pNode->TravId == pNet->nTravIds - 1 means "pNode is visited but is not on the path" + // pNode->TravId < pNet->nTravIds - 1 means "pNode is not visited" + // traverse the network to detect cycles + fAcyclic = 1; + Abc_NtkForEachPo( pNtk, pNode, i ) + { + pNode = Abc_ObjFanin0Ntk(Abc_ObjFanin0(pNode)); + if ( Abc_ObjIsBo(pNode) ) + pNode = Abc_ObjFanin0(pNode); + if ( Abc_NodeIsTravIdPrevious(pNode) ) + continue; + // traverse the output logic cone + if ( (fAcyclic = Abc_NtkIsAcyclicWithBoxes_rec(pNode)) ) + continue; + // stop as soon as the first loop is detected + fprintf( stdout, " PO \"%s\"\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + break; + } + if ( fAcyclic ) + { + Abc_NtkForEachLatchInput( pNtk, pNode, i ) + { + pNode = Abc_ObjFanin0Ntk(Abc_ObjFanin0(pNode)); + if ( Abc_ObjIsBo(pNode) ) + pNode = Abc_ObjFanin0(pNode); + if ( Abc_NodeIsTravIdPrevious(pNode) ) + continue; + // traverse the output logic cone + if ( (fAcyclic = Abc_NtkIsAcyclicWithBoxes_rec(pNode)) ) + continue; + // stop as soon as the first loop is detected + fprintf( stdout, " PO \"%s\"\n", Abc_ObjName(Abc_ObjFanout0(pNode)) ); + break; + } + } + return fAcyclic; +} + + + +/**Function************************************************************* + + Synopsis [Analyses choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeSetChoiceLevel_rec( Abc_Obj_t * pNode, int fMaximum ) +{ + Abc_Obj_t * pTemp; + int Level1, Level2, Level, LevelE; + // skip the visited node + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return (int)(ABC_PTRINT_T)pNode->pCopy; + Abc_NodeSetTravIdCurrent( pNode ); + // compute levels of the children nodes + Level1 = Abc_NodeSetChoiceLevel_rec( Abc_ObjFanin0(pNode), fMaximum ); + Level2 = Abc_NodeSetChoiceLevel_rec( Abc_ObjFanin1(pNode), fMaximum ); + Level = 1 + Abc_MaxInt( Level1, Level2 ); + if ( pNode->pData ) + { + LevelE = Abc_NodeSetChoiceLevel_rec( (Abc_Obj_t *)pNode->pData, fMaximum ); + if ( fMaximum ) + Level = Abc_MaxInt( Level, LevelE ); + else + Level = Abc_MinInt( Level, LevelE ); + // set the level of all equivalent nodes to be the same minimum + for ( pTemp = (Abc_Obj_t *)pNode->pData; pTemp; pTemp = (Abc_Obj_t *)pTemp->pData ) + pTemp->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)Level; + } + pNode->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)Level; + return Level; +} + +/**Function************************************************************* + + Synopsis [Resets the levels of the nodes in the choice graph.] + + Description [Makes the level of the choice nodes to be equal to the + maximum of the level of the nodes in the equivalence class. This way + sorting by level leads to the reverse topological order, which is + needed for the required time computation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_AigSetChoiceLevels( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i, LevelMax, LevelCur; + assert( Abc_NtkIsStrash(pNtk) ); + // set the new travid counter + Abc_NtkIncrementTravId( pNtk ); + // set levels of the CI and constant + Abc_NtkForEachCi( pNtk, pObj, i ) + { + Abc_NodeSetTravIdCurrent( pObj ); + pObj->pCopy = NULL; + } + pObj = Abc_AigConst1( pNtk ); + Abc_NodeSetTravIdCurrent( pObj ); + pObj->pCopy = NULL; + // set levels of all other nodes + LevelMax = 0; + Abc_NtkForEachCo( pNtk, pObj, i ) + { + LevelCur = Abc_NodeSetChoiceLevel_rec( Abc_ObjFanin0(pObj), 1 ); + LevelMax = Abc_MaxInt( LevelMax, LevelCur ); + } + return LevelMax; +} + +/**Function************************************************************* + + Synopsis [Returns nodes by level from the smallest to the largest.] + + Description [Correctly handles the case of choice nodes, by first + spreading them out across several levels and then collecting.] + + SideEffects [What happens with dangling nodes???] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_AigGetLevelizedOrder( Abc_Ntk_t * pNtk, int fCollectCis ) +{ + Vec_Ptr_t * vNodes, * vLevels; + Abc_Obj_t * pNode, ** ppHead; + int LevelMax, i; + assert( Abc_NtkIsStrash(pNtk) ); + // set the correct levels + Abc_NtkCleanCopy( pNtk ); + LevelMax = Abc_AigSetChoiceLevels( pNtk ); + // relink nodes by level + vLevels = Vec_PtrStart( LevelMax + 1 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + ppHead = ((Abc_Obj_t **)vLevels->pArray) + (int)(ABC_PTRINT_T)pNode->pCopy; + pNode->pCopy = *ppHead; + *ppHead = pNode; + } + // recollect nodes + vNodes = Vec_PtrStart( Abc_NtkNodeNum(pNtk) ); + Vec_PtrForEachEntryStart( Abc_Obj_t *, vLevels, pNode, i, !fCollectCis ) + for ( ; pNode; pNode = pNode->pCopy ) + Vec_PtrPush( vNodes, pNode ); + Vec_PtrFree( vLevels ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Count the number of nodes in the subgraph.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjSugraphSize( Abc_Obj_t * pObj ) +{ + if ( Abc_ObjIsCi(pObj) ) + return 0; + if ( Abc_ObjFanoutNum(pObj) > 1 ) + return 0; + return 1 + Abc_ObjSugraphSize(Abc_ObjFanin0(pObj)) + + Abc_ObjSugraphSize(Abc_ObjFanin1(pObj)); +} + +/**Function************************************************************* + + Synopsis [Prints subgraphs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkPrintSubraphSizes( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkIsStrash(pNtk) ); + Abc_NtkForEachNode( pNtk, pObj, i ) + if ( Abc_ObjFanoutNum(pObj) > 1 && !Abc_NodeIsExorType(pObj) ) + printf( "%d(%d) ", 1 + Abc_ObjSugraphSize(Abc_ObjFanin0(pObj)) + + Abc_ObjSugraphSize(Abc_ObjFanin1(pObj)), Abc_ObjFanoutNum(pObj) ); + printf( "\n" ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/abcFanOrder.c b/yosys/abc/src/base/abc/abcFanOrder.c new file mode 100644 index 00000000000..949170aa78b --- /dev/null +++ b/yosys/abc/src/base/abc/abcFanOrder.c @@ -0,0 +1,652 @@ +/**CFile**************************************************************** + + FileName [abcFanOrder.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Fanin ordering procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcFanOrder.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +/**Function************************************************************* + + Synopsis [Reorder fanins of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkOrderFaninsById( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vOrder; + Vec_Str_t * vStore; + Abc_Obj_t * pNode; + char * pSop, * pSopNew; + char * pCube, * pCubeNew; + int nVars, i, v, * pOrder; + assert( Abc_NtkHasSop(pNtk) ); + vOrder = Vec_IntAlloc( 100 ); + vStore = Vec_StrAlloc( 100 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + pSop = (char *)pNode->pData; + nVars = Abc_SopGetVarNum(pSop); + assert( nVars == Abc_ObjFaninNum(pNode) ); + Vec_IntClear( vOrder ); + for ( v = 0; v < nVars; v++ ) + Vec_IntPush( vOrder, v ); + pOrder = Vec_IntArray(vOrder); + Vec_IntSelectSortCost( pOrder, nVars, &pNode->vFanins ); + // copy the cover + Vec_StrGrow( vStore, Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1 ); + memcpy( Vec_StrArray(vStore), pSop, (size_t)(Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1) ); + pSopNew = pCubeNew = pSop; + pSop = Vec_StrArray(vStore); + // generate permuted one + Abc_SopForEachCube( pSop, nVars, pCube ) + { + for ( v = 0; v < nVars; v++ ) + pCubeNew[v] = '-'; + for ( v = 0; v < nVars; v++ ) + if ( pCube[pOrder[v]] == '0' ) + pCubeNew[v] = '0'; + else if ( pCube[pOrder[v]] == '1' ) + pCubeNew[v] = '1'; + pCubeNew += nVars + 3; + } + pNode->pData = pSopNew; + Vec_IntSort( &pNode->vFanins, 0 ); +// Vec_IntPrint( vOrder ); + } + Vec_IntFree( vOrder ); + Vec_StrFree( vStore ); +} + +/**Function************************************************************* + + Synopsis [Returns fanin permutation to reorders columns lexicographically.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSopTranspose( char * pSop, int nVars, Vec_Ptr_t * vCubes, Vec_Str_t * vStore ) +{ + char * pCube; + int nCubes, v, c; + // collect original cubes + Vec_PtrClear( vCubes ); + Abc_SopForEachCube( pSop, nVars, pCube ) + Vec_PtrPush( vCubes, pCube ); + // rebuild the cubes + Vec_StrClear( vStore ); + for ( v = 0; v < nVars; v++ ) + { + Vec_PtrForEachEntry( char *, vCubes, pCube, c ) + Vec_StrPush( vStore, pCube[v] ); + Vec_StrPush( vStore, '\0' ); + } + // get the cubes + nCubes = Vec_PtrSize( vCubes ); + Vec_PtrClear( vCubes ); + for ( v = 0; v < nVars; v++ ) + Vec_PtrPush( vCubes, Vec_StrEntryP(vStore, v*(nCubes+1)) ); +} +static inline void Vec_StrSelectSortCost( char ** pArray, int nSize, Vec_Int_t * vPerm ) +{ + int i, j, best_i, * pPerm; + Vec_IntClear( vPerm ); + for ( i = 0; i < nSize; i++ ) + Vec_IntPush( vPerm, i ); + pPerm = Vec_IntArray( vPerm ); + for ( i = 0; i < nSize-1; i++ ) + { + best_i = i; + for ( j = i+1; j < nSize; j++ ) + if ( strcmp(pArray[j], pArray[best_i]) < 0 ) + best_i = j; + ABC_SWAP( char *, pArray[i], pArray[best_i] ); + ABC_SWAP( int, pPerm[i], pPerm[best_i] ); + } +} +void Abc_NtkOrderFaninsBySortingColumns( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vOrder; + Vec_Int_t * vCounts; + Vec_Int_t * vFanins; + Vec_Str_t * vStore; + Vec_Ptr_t * vCubes; + Abc_Obj_t * pNode; + char * pSop, * pSopNew; + char * pCube, * pCubeNew; + int nVars, i, v, * pOrder; + assert( Abc_NtkHasSop(pNtk) ); + vOrder = Vec_IntAlloc( 100 ); + vStore = Vec_StrAlloc( 100 ); + vCubes = Vec_PtrAlloc( 100 ); + vCounts = Vec_IntAlloc( 100 ); + vFanins = Vec_IntAlloc( 100 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + pSop = (char *)pNode->pData; + nVars = Abc_SopGetVarNum(pSop); + assert( nVars == Abc_ObjFaninNum(pNode) ); + // create a transposed SOP + Abc_NtkSopTranspose( pSop, nVars, vCubes, vStore ); + // create permutation + Vec_StrSelectSortCost( (char **)Vec_PtrArray(vCubes), nVars, vOrder ); + pOrder = Vec_IntArray(vOrder); + // copy the cover + Vec_StrGrow( vStore, Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1 ); + memcpy( Vec_StrArray(vStore), pSop, (size_t)(Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1) ); + pSopNew = pCubeNew = pSop; + pSop = Vec_StrArray(vStore); + // generate permuted one + Abc_SopForEachCube( pSop, nVars, pCube ) + { + for ( v = 0; v < nVars; v++ ) + pCubeNew[v] = '-'; + for ( v = 0; v < nVars; v++ ) + if ( pCube[pOrder[v]] == '0' ) + pCubeNew[v] = '0'; + else if ( pCube[pOrder[v]] == '1' ) + pCubeNew[v] = '1'; + pCubeNew += nVars + 3; + } + pNode->pData = pSopNew; + // generate the fanin order + Vec_IntClear( vFanins ); + for ( v = 0; v < nVars; v++ ) + Vec_IntPush( vFanins, Abc_ObjFaninId( pNode, pOrder[v] ) ); + Vec_IntClear( &pNode->vFanins ); + Vec_IntAppend( &pNode->vFanins, vFanins ); + } + Vec_IntFree( vFanins ); + Vec_IntFree( vCounts ); + Vec_IntFree( vOrder ); + Vec_StrFree( vStore ); + Vec_PtrFree( vCubes ); +} + + +/**Function************************************************************* + + Synopsis [Reorders columns by literal and then lexicographically.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_StrSelectSortCost2( char ** pArray, int nSize, Vec_Int_t * vCounts, Vec_Int_t * vPerm ) +{ + int i, j, best_i, * pPerm; + Vec_IntClear( vPerm ); + for ( i = 0; i < nSize; i++ ) + Vec_IntPush( vPerm, i ); + pPerm = Vec_IntArray( vPerm ); + for ( i = 0; i < nSize-1; i++ ) + { + best_i = i; + for ( j = i+1; j < nSize; j++ ) + if ( Vec_IntEntry(vCounts, pPerm[j]) < Vec_IntEntry(vCounts, pPerm[best_i]) || + (Vec_IntEntry(vCounts, pPerm[j]) == Vec_IntEntry(vCounts, pPerm[best_i]) && strcmp(pArray[j], pArray[best_i]) < 0) ) + best_i = j; + ABC_SWAP( char *, pArray[i], pArray[best_i] ); + ABC_SWAP( int, pPerm[i], pPerm[best_i] ); + } +} +void Abc_NtkOrderFaninsByLitCount( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vOrder; + Vec_Int_t * vCounts; + Vec_Int_t * vFanins; + Vec_Str_t * vStore; + Vec_Ptr_t * vCubes; + Abc_Obj_t * pNode; + char * pSop, * pSopNew; + char * pCube, * pCubeNew; + int nVars, i, v, * pOrder; + assert( Abc_NtkHasSop(pNtk) ); + vOrder = Vec_IntAlloc( 100 ); + vStore = Vec_StrAlloc( 100 ); + vCubes = Vec_PtrAlloc( 100 ); + vCounts = Vec_IntAlloc( 100 ); + vFanins = Vec_IntAlloc( 100 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + pSop = (char *)pNode->pData; + nVars = Abc_SopGetVarNum(pSop); + assert( nVars == Abc_ObjFaninNum(pNode) ); + // count literals + Vec_IntFill( vCounts, nVars, 0 ); + Abc_SopForEachCube( pSop, nVars, pCube ) + for ( v = 0; v < nVars; v++ ) + if ( pCube[v] != '-' ) + Vec_IntAddToEntry( vCounts, v, 1 ); + + // create a transposed SOP + Abc_NtkSopTranspose( pSop, nVars, vCubes, vStore ); + // create permutation + Vec_StrSelectSortCost2( (char **)Vec_PtrArray(vCubes), nVars, vCounts, vOrder ); + pOrder = Vec_IntArray(vOrder); +/* + // find good order + Vec_IntClear( vOrder ); + for ( v = 0; v < nVars; v++ ) + Vec_IntPush( vOrder, v ); + pOrder = Vec_IntArray(vOrder); + Vec_IntSelectSortCost( pOrder, nVars, vCounts ); +*/ + // copy the cover + Vec_StrGrow( vStore, Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1 ); + memcpy( Vec_StrArray(vStore), pSop, (size_t)(Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1) ); + pSopNew = pCubeNew = pSop; + pSop = Vec_StrArray(vStore); + // generate permuted one + Abc_SopForEachCube( pSop, nVars, pCube ) + { + for ( v = 0; v < nVars; v++ ) + pCubeNew[v] = '-'; + for ( v = 0; v < nVars; v++ ) + if ( pCube[pOrder[v]] == '0' ) + pCubeNew[v] = '0'; + else if ( pCube[pOrder[v]] == '1' ) + pCubeNew[v] = '1'; + pCubeNew += nVars + 3; + } + pNode->pData = pSopNew; + // generate the fanin order + Vec_IntClear( vFanins ); + for ( v = 0; v < nVars; v++ ) + Vec_IntPush( vFanins, Abc_ObjFaninId( pNode, pOrder[v] ) ); + Vec_IntClear( &pNode->vFanins ); + Vec_IntAppend( &pNode->vFanins, vFanins ); + } + Vec_IntFree( vFanins ); + Vec_IntFree( vCounts ); + Vec_IntFree( vOrder ); + Vec_StrFree( vStore ); + Vec_PtrFree( vCubes ); +} +void Abc_NtkOrderFaninsByLitCountAndCubeCount( Abc_Ntk_t * pNtk ) +{ + // assuming that the fanins are sorted by the number of literals in each cube + // this procedure sorts the literals appearing only once by the number of their cube + Vec_Int_t * vOrder; + Vec_Int_t * vCounts; + Vec_Int_t * vFanins; + Vec_Int_t * vCubeNum; + Vec_Str_t * vStore; + Abc_Obj_t * pNode; + char * pSop, * pSopNew; + char * pCube, * pCubeNew; + int nVars, i, v, iCube, * pOrder; + assert( Abc_NtkHasSop(pNtk) ); + vStore = Vec_StrAlloc( 100 ); + vOrder = Vec_IntAlloc( 100 ); + vCounts = Vec_IntAlloc( 100 ); + vFanins = Vec_IntAlloc( 100 ); + vCubeNum = Vec_IntAlloc( 100 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + pSop = (char *)pNode->pData; + nVars = Abc_SopGetVarNum(pSop); + assert( nVars == Abc_ObjFaninNum(pNode) ); + // count literals and remember the cube where each literal appears + Vec_IntFill( vCounts, nVars, 0 ); + Vec_IntFill( vCubeNum, nVars, 0 ); + iCube = 0; + Abc_SopForEachCube( pSop, nVars, pCube ) + { + for ( v = 0; v < nVars; v++ ) + if ( pCube[v] != '-' ) + { + Vec_IntAddToEntry( vCounts, v, 1 ); + Vec_IntWriteEntry( vCubeNum, v, iCube ); + } + iCube++; + } + // create new order + for ( v = 0; v < nVars; v++ ) + if ( Vec_IntEntry(vCounts, v) == 1 ) + Vec_IntWriteEntry( vCounts, v, Vec_IntEntry(vCubeNum, v) ); + else + Vec_IntWriteEntry( vCounts, v, ABC_INFINITY ); + // find good order + Vec_IntClear( vOrder ); + for ( v = 0; v < nVars; v++ ) + Vec_IntPush( vOrder, v ); + pOrder = Vec_IntArray(vOrder); + Vec_IntSelectSortCost( pOrder, nVars, vCounts ); + // copy the cover + Vec_StrGrow( vStore, Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1 ); + memcpy( Vec_StrArray(vStore), pSop, (size_t)(Abc_SopGetCubeNum(pSop) * (nVars + 3) + 1) ); + pSopNew = pCubeNew = pSop; + pSop = Vec_StrArray(vStore); + // generate permuted one + Abc_SopForEachCube( pSop, nVars, pCube ) + { + for ( v = 0; v < nVars; v++ ) + pCubeNew[v] = '-'; + for ( v = 0; v < nVars; v++ ) + if ( pCube[pOrder[v]] == '0' ) + pCubeNew[v] = '0'; + else if ( pCube[pOrder[v]] == '1' ) + pCubeNew[v] = '1'; + pCubeNew += nVars + 3; + } + pNode->pData = pSopNew; + // generate the fanin order + Vec_IntClear( vFanins ); + for ( v = 0; v < nVars; v++ ) + Vec_IntPush( vFanins, Abc_ObjFaninId( pNode, pOrder[v] ) ); + Vec_IntClear( &pNode->vFanins ); + Vec_IntAppend( &pNode->vFanins, vFanins ); + } + Vec_IntFree( vCubeNum ); + Vec_IntFree( vFanins ); + Vec_IntFree( vCounts ); + Vec_IntFree( vOrder ); + Vec_StrFree( vStore ); +} + +/**Function************************************************************* + + Synopsis [Split large nodes by dividing their SOPs in half.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeSplitLarge( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNode1, * pNode2, * pFanin; + int CutPoint, nVars = Abc_ObjFaninNum(pNode); + int i, nCubes = Abc_SopGetCubeNum((char *)pNode->pData); + pNode1 = Abc_NtkDupObj( pNode->pNtk, pNode, 0 ); + pNode2 = Abc_NtkDupObj( pNode->pNtk, pNode, 0 ); + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_ObjAddFanin( pNode1, pFanin ); + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_ObjAddFanin( pNode2, pFanin ); + // update the node + Abc_ObjRemoveFanins( pNode ); + Abc_ObjAddFanin( pNode, pNode1 ); + Abc_ObjAddFanin( pNode, pNode2 ); + pNode->pData = Abc_SopCreateOr( (Mem_Flex_t *)pNode->pNtk->pManFunc, 2, NULL ); + // update covers of the nodes + assert( nCubes > 1 ); + CutPoint = (nCubes / 2) * (nVars + 3); + ((char *)pNode1->pData)[CutPoint] = 0; + pNode2->pData = (char *)pNode2->pData + CutPoint; +} +void Abc_NtkSplitLarge( Abc_Ntk_t * pNtk, int nFaninsMax, int nCubesMax ) +{ + Abc_Obj_t * pNode; + int nObjOld = Abc_NtkObjNumMax(pNtk); + int i, nCubes; + assert( Abc_NtkHasSop(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( i == nObjOld ) + break; + nCubes = Abc_SopGetCubeNum((char *)pNode->pData); + if ( (Abc_ObjFaninNum(pNode) > nFaninsMax && nCubes > 1) || nCubes > nCubesMax ) + Abc_NodeSplitLarge( pNode ); + } +} + +/**Function************************************************************* + + Synopsis [Sorts the cubes in a topological order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeCompareCubes1( char ** pp1, char ** pp2 ) +{ + return strcmp( *pp1, *pp2 ); +} +int Abc_NodeCompareCubes2( char ** pp1, char ** pp2 ) +{ + char * pStr1 = *pp1; + char * pStr2 = *pp2; + int i, nNum1 = 0, nNum2 = 0; + for ( i = 0; pStr1[i]; i++ ) + { + nNum1 += (pStr1[i] != '-'); + nNum2 += (pStr2[i] != '-'); + } + if ( nNum1 > nNum2 ) + return -1; + if ( nNum1 < nNum2 ) + return 1; + return strcmp( *pp1, *pp2 ); +} +void Abc_NodeSortCubes( Abc_Obj_t * pNode, Vec_Ptr_t * vCubes, Vec_Str_t * vStore, int fWeight ) +{ + char * pCube, * pPivot; + char * pSop = (char *)pNode->pData; + int i, nVars = Abc_ObjFaninNum(pNode); + Vec_PtrClear( vCubes ); + Abc_SopForEachCube( pSop, nVars, pCube ) + { + assert( pCube[nVars] == ' ' ); + pCube[nVars] = 0; + Vec_PtrPush( vCubes, pCube ); + } + if ( fWeight ) + Vec_PtrSort( vCubes, (int (*)(const void *, const void *))Abc_NodeCompareCubes2 ); + else + Vec_PtrSort( vCubes, (int (*)(const void *, const void *))Abc_NodeCompareCubes1 ); + Vec_StrGrow( vStore, Vec_PtrSize(vCubes) * (nVars + 3) ); + pPivot = Vec_StrArray( vStore ); + Vec_PtrForEachEntry( char *, vCubes, pCube, i ) + { + assert( pCube[nVars] == 0 ); + pCube[nVars] = ' '; + memcpy( pPivot, pCube, (size_t)(nVars + 3) ); + pPivot += nVars + 3; + } + memcpy( pSop, Vec_StrArray(vStore), (size_t)(Vec_PtrSize(vCubes) * (nVars + 3)) ); +} +void Abc_NtkSortCubes( Abc_Ntk_t * pNtk, int fWeight ) +{ + Vec_Ptr_t * vCubes; + Vec_Str_t * vStore; + Abc_Obj_t * pNode; + int i; + assert( Abc_NtkHasSop(pNtk) ); + vCubes = Vec_PtrAlloc( 1000 ); + vStore = Vec_StrAlloc( 1000 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + Abc_NodeSortCubes( pNode, vCubes, vStore, fWeight ); + Vec_StrFree( vStore ); + Vec_PtrFree( vCubes ); +} + + +/**Function************************************************************* + + Synopsis [Sorts fanins of each node to make SOPs more readable.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSortSops( Abc_Ntk_t * pNtk ) +{ + Abc_NtkSortCubes( pNtk, 1 ); + Abc_NtkOrderFaninsByLitCount( pNtk ); + Abc_NtkSortCubes( pNtk, 0 ); + Abc_NtkOrderFaninsByLitCountAndCubeCount( pNtk ); + Abc_NtkSortCubes( pNtk, 0 ); +} + +/**Function************************************************************* + + Synopsis [Makes cover legitimate for "fast_extract".] + + Description [Iteratively removes distance-1 and contained cubes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Abc_CubeContain( char * pCube1, char * pCube2, int nVars ) +{ + int v, fCont12 = 1, fCont21 = 1; + for ( v = 0; v < nVars; v++ ) + { + if ( pCube1[v] == pCube2[v] ) + continue; + if ( pCube1[v] == '-' ) + fCont21 = 0; + else if ( pCube2[v] == '-' ) + fCont12 = 0; + else + return 0; + if ( !fCont12 && !fCont21 ) + return 0; + } + assert( fCont21 || fCont12 ); + return (fCont21 << 1) | fCont12; +} +int Abc_NodeMakeSCCFree( Abc_Obj_t * pNode ) +{ + char * pSop = (char *)pNode->pData; + char * pCube, * pCube2, * pSopNew; + int nVars = Abc_ObjFaninNum(pNode); + int Status, nCount = 0; + Abc_SopForEachCubePair( pSop, nVars, pCube, pCube2 ) + { + if ( pCube[0] == 'z' || pCube2[0] == 'z' ) + continue; + Status = Abc_CubeContain( pCube, pCube2, nVars ); + nCount += (int)(Status > 0); + if ( Status & 1 ) + pCube2[0] = 'z'; + else if ( Status & 2 ) + pCube[0] = 'z'; + } + if ( nCount == 0 ) + return 0; + // create new cover + pSopNew = (char *)pNode->pData; + Abc_SopForEachCube( pSop, nVars, pCube ) + { + if ( pCube[0] == 'z' ) + continue; + memcpy( pSopNew, pCube, (size_t)(nVars + 3) ); + pSopNew += nVars + 3; + } + *pSopNew = 0; + return 1; +} +void Abc_NodeMakeDist1Free( Abc_Obj_t * pNode ) +{ + char * pSop = (char *)pNode->pData; + char * pCube, * pCube2; + int i, nVars = Abc_ObjFaninNum(pNode); + Abc_SopForEachCube( pSop, nVars, pCube ) + Abc_SopForEachCube( pCube + nVars + 3, nVars, pCube2 ) + { + int Counter = 0, iDiff = -1; + for ( i = 0; i < nVars; i++ ) + if ( pCube[i] != pCube2[i] ) + Counter++, iDiff = i; + if ( Counter == 1 && ((pCube[iDiff] == '0' && pCube2[iDiff] == '1') || (pCube[iDiff] == '1' && pCube2[iDiff] == '0')) ) + pCube[iDiff] = pCube2[iDiff] = '-'; + } +} +void Abc_NodeCheckDist1Free( Abc_Obj_t * pNode ) +{ + char * pSop = (char *)pNode->pData; + char * pCube, * pCube2; + int i, nVars = Abc_ObjFaninNum(pNode); + Abc_SopForEachCube( pSop, nVars, pCube ) + Abc_SopForEachCube( pSop, nVars, pCube2 ) + { + int Counter = 0; + if ( pCube == pCube2 ) + continue; + for ( i = 0; i < nVars; i++ ) + if ( pCube[i] != pCube2[i] ) + Counter++; + assert( Counter > 1 ); + } +} +int Abc_NodeMakeLegit( Abc_Obj_t * pNode ) +{ + int i, fChanges = 1; + for ( i = 0; fChanges; i++ ) + { + Abc_NodeMakeDist1Free( pNode ); + fChanges = Abc_NodeMakeSCCFree( pNode ); + } +// Abc_NodeCheckDist1Free( pNode ); + return i > 1; +} +int Abc_NtkMakeLegit( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, Counter = 0; + assert( Abc_NtkHasSop(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + Counter += Abc_NodeMakeLegit( pNode ); + if ( Counter ) + Abc_Print( 0, "%d nodes were made dist1-cube-free and/or single-cube-containment-free.\n", Counter ); + return 1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/abcFanio.c b/yosys/abc/src/base/abc/abcFanio.c new file mode 100644 index 00000000000..519debb1f80 --- /dev/null +++ b/yosys/abc/src/base/abc/abcFanio.c @@ -0,0 +1,390 @@ +/**CFile**************************************************************** + + FileName [abcFanio.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Various procedures to connect fanins/fanouts.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcFanio.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Vec_IntPushMem( Mem_Step_t * pMemMan, Vec_Int_t * p, int Entry ) +{ + if ( p->nSize == p->nCap ) + { + int * pArray; + int i; + + if ( p->nSize == 0 ) + p->nCap = 1; + if ( pMemMan ) + pArray = (int *)Mem_StepEntryFetch( pMemMan, p->nCap * 8 ); + else + pArray = ABC_ALLOC( int, p->nCap * 2 ); + if ( p->pArray ) + { + for ( i = 0; i < p->nSize; i++ ) + pArray[i] = p->pArray[i]; + if ( pMemMan ) + Mem_StepEntryRecycle( pMemMan, (char *)p->pArray, p->nCap * 4 ); + else + ABC_FREE( p->pArray ); + } + p->nCap *= 2; + p->pArray = pArray; + } + p->pArray[p->nSize++] = Entry; +} + +/**Function************************************************************* + + Synopsis [Creates fanout/fanin relationship between the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjAddFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) +{ + Abc_Obj_t * pFaninR = Abc_ObjRegular(pFanin); + assert( !Abc_ObjIsComplement(pObj) ); + assert( pObj->pNtk == pFaninR->pNtk ); + assert( pObj->Id >= 0 && pFaninR->Id >= 0 ); + assert( !Abc_ObjIsPi(pObj) && !Abc_ObjIsPo(pFaninR) ); // fanin of PI or fanout of PO + assert( !Abc_ObjIsCo(pObj) || !Abc_ObjFaninNum(pObj) ); // CO with two fanins + assert( !Abc_ObjIsNet(pObj) || !Abc_ObjFaninNum(pObj) ); // net with two fanins + Vec_IntPushMem( pObj->pNtk->pMmStep, &pObj->vFanins, pFaninR->Id ); + Vec_IntPushMem( pObj->pNtk->pMmStep, &pFaninR->vFanouts, pObj->Id ); + if ( Abc_ObjIsComplement(pFanin) ) + Abc_ObjSetFaninC( pObj, Abc_ObjFaninNum(pObj)-1 ); +} + + +/**Function************************************************************* + + Synopsis [Destroys fanout/fanin relationship between the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjDeleteFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin ) +{ + assert( !Abc_ObjIsComplement(pObj) ); + assert( !Abc_ObjIsComplement(pFanin) ); + assert( pObj->pNtk == pFanin->pNtk ); + assert( pObj->Id >= 0 && pFanin->Id >= 0 ); + if ( !Vec_IntRemove( &pObj->vFanins, pFanin->Id ) ) + { + printf( "The obj %d is not found among the fanins of obj %d ...\n", pFanin->Id, pObj->Id ); + return; + } + if ( !Vec_IntRemove( &pFanin->vFanouts, pObj->Id ) ) + { + printf( "The obj %d is not found among the fanouts of obj %d ...\n", pObj->Id, pFanin->Id ); + return; + } +} + + +/**Function************************************************************* + + Synopsis [Destroys fanout/fanin relationship between the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjRemoveFanins( Abc_Obj_t * pObj ) +{ + Vec_Int_t * vFaninsOld; + Abc_Obj_t * pFanin; + int k; + // remove old fanins + vFaninsOld = &pObj->vFanins; + for ( k = vFaninsOld->nSize - 1; k >= 0; k-- ) + { + pFanin = Abc_NtkObj( pObj->pNtk, vFaninsOld->pArray[k] ); + Abc_ObjDeleteFanin( pObj, pFanin ); + } + pObj->fCompl0 = 0; + pObj->fCompl1 = 0; + assert( vFaninsOld->nSize == 0 ); +} + +/**Function************************************************************* + + Synopsis [Replaces a fanin of the node.] + + Description [The node is pObj. An old fanin of this node (pFaninOld) has to be + replaced by a new fanin (pFaninNew). Assumes that the node and the old fanin + are not complemented. The new fanin can be complemented. In this case, the + polarity of the new fanin will change, compared to the polarity of the old fanin.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjPatchFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFaninOld, Abc_Obj_t * pFaninNew ) +{ + Abc_Obj_t * pFaninNewR = Abc_ObjRegular(pFaninNew); + int iFanin;//, nLats;//, fCompl; + assert( !Abc_ObjIsComplement(pObj) ); + assert( !Abc_ObjIsComplement(pFaninOld) ); + assert( pFaninOld != pFaninNewR ); +// assert( pObj != pFaninOld ); +// assert( pObj != pFaninNewR ); + assert( pObj->pNtk == pFaninOld->pNtk ); + assert( pObj->pNtk == pFaninNewR->pNtk ); + if ( (iFanin = Vec_IntFind( &pObj->vFanins, pFaninOld->Id )) == -1 ) + { + printf( "Node %s is not among", Abc_ObjName(pFaninOld) ); + printf( " the fanins of node %s...\n", Abc_ObjName(pObj) ); + return; + } + + // remember the attributes of the old fanin +// fCompl = Abc_ObjFaninC(pObj, iFanin); + // replace the old fanin entry by the new fanin entry (removes attributes) + Vec_IntWriteEntry( &pObj->vFanins, iFanin, pFaninNewR->Id ); + // set the attributes of the new fanin +// if ( fCompl ^ Abc_ObjIsComplement(pFaninNew) ) +// Abc_ObjSetFaninC( pObj, iFanin ); + if ( Abc_ObjIsComplement(pFaninNew) ) + Abc_ObjXorFaninC( pObj, iFanin ); + +// if ( Abc_NtkIsSeq(pObj->pNtk) && (nLats = Seq_ObjFaninL(pObj, iFanin)) ) +// Seq_ObjSetFaninL( pObj, iFanin, nLats ); + // update the fanout of the fanin + if ( !Vec_IntRemove( &pFaninOld->vFanouts, pObj->Id ) ) + { + printf( "Node %s is not among", Abc_ObjName(pObj) ); + printf( " the fanouts of its old fanin %s...\n", Abc_ObjName(pFaninOld) ); +// return; + } + Vec_IntPushMem( pObj->pNtk->pMmStep, &pFaninNewR->vFanouts, pObj->Id ); +} + +/**Function************************************************************* + + Synopsis [Replaces pObj by iObjNew in the fanin arrays of the fanouts.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjPatchFanoutFanin( Abc_Obj_t * pObj, int iObjNew ) +{ + Abc_Obj_t * pFanout; + int i, k, Entry; + // update fanouts of the node to point to this one + Abc_ObjForEachFanout( pObj, pFanout, i ) + { + Vec_IntForEachEntry( &pFanout->vFanins, Entry, k ) + if ( Entry == (int)Abc_ObjId(pObj) ) + { + Vec_IntWriteEntry( &pFanout->vFanins, k, iObjNew ); + break; + } + assert( k < Vec_IntSize(&pFanout->vFanins) ); + } +} + +/**Function************************************************************* + + Synopsis [Inserts one-input node of the type specified between the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_ObjInsertBetween( Abc_Obj_t * pNodeIn, Abc_Obj_t * pNodeOut, Abc_ObjType_t Type ) +{ + Abc_Obj_t * pNodeNew; + int iFanoutIndex, iFaninIndex; + // find pNodeOut among the fanouts of pNodeIn + if ( (iFanoutIndex = Vec_IntFind( &pNodeIn->vFanouts, pNodeOut->Id )) == -1 ) + { + printf( "Node %s is not among", Abc_ObjName(pNodeOut) ); + printf( " the fanouts of node %s...\n", Abc_ObjName(pNodeIn) ); + return NULL; + } + // find pNodeIn among the fanins of pNodeOut + if ( (iFaninIndex = Vec_IntFind( &pNodeOut->vFanins, pNodeIn->Id )) == -1 ) + { + printf( "Node %s is not among", Abc_ObjName(pNodeIn) ); + printf( " the fanins of node %s...\n", Abc_ObjName(pNodeOut) ); + return NULL; + } + // create the new node + pNodeNew = Abc_NtkCreateObj( pNodeIn->pNtk, Type ); + // add pNodeIn as fanin and pNodeOut as fanout + Vec_IntPushMem( pNodeNew->pNtk->pMmStep, &pNodeNew->vFanins, pNodeIn->Id ); + Vec_IntPushMem( pNodeNew->pNtk->pMmStep, &pNodeNew->vFanouts, pNodeOut->Id ); + // update the fanout of pNodeIn + Vec_IntWriteEntry( &pNodeIn->vFanouts, iFanoutIndex, pNodeNew->Id ); + // update the fanin of pNodeOut + Vec_IntWriteEntry( &pNodeOut->vFanins, iFaninIndex, pNodeNew->Id ); + return pNodeNew; +} + +/**Function************************************************************* + + Synopsis [Transfers fanout from the old node to the new node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjTransferFanout( Abc_Obj_t * pNodeFrom, Abc_Obj_t * pNodeTo ) +{ + Vec_Ptr_t * vFanouts; + int nFanoutsOld, i; + assert( !Abc_ObjIsComplement(pNodeFrom) ); + assert( !Abc_ObjIsComplement(pNodeTo) ); + assert( !Abc_ObjIsPo(pNodeFrom) && !Abc_ObjIsPo(pNodeTo) ); + assert( pNodeFrom->pNtk == pNodeTo->pNtk ); + assert( pNodeFrom != pNodeTo ); + assert( !Abc_ObjIsNode(pNodeFrom) || Abc_ObjFanoutNum(pNodeFrom) > 0 ); + // get the fanouts of the old node + nFanoutsOld = Abc_ObjFanoutNum(pNodeTo); + vFanouts = Vec_PtrAlloc( nFanoutsOld ); + Abc_NodeCollectFanouts( pNodeFrom, vFanouts ); + // patch the fanin of each of them + for ( i = 0; i < vFanouts->nSize; i++ ) + Abc_ObjPatchFanin( (Abc_Obj_t *)vFanouts->pArray[i], pNodeFrom, pNodeTo ); + assert( Abc_ObjFanoutNum(pNodeFrom) == 0 ); + assert( Abc_ObjFanoutNum(pNodeTo) == nFanoutsOld + vFanouts->nSize ); + Vec_PtrFree( vFanouts ); +} + +/**Function************************************************************* + + Synopsis [Replaces the node by a new node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjReplace( Abc_Obj_t * pNodeOld, Abc_Obj_t * pNodeNew ) +{ + assert( !Abc_ObjIsComplement(pNodeOld) ); + assert( !Abc_ObjIsComplement(pNodeNew) ); + assert( pNodeOld->pNtk == pNodeNew->pNtk ); + assert( pNodeOld != pNodeNew ); + assert( Abc_ObjFanoutNum(pNodeOld) > 0 ); + // transfer the fanouts to the old node + Abc_ObjTransferFanout( pNodeOld, pNodeNew ); + // remove the old node + Abc_NtkDeleteObj_rec( pNodeOld, 1 ); +} + +/**Function************************************************************* + + Synopsis [Replaces a node by a constant.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjReplaceByConstant( Abc_Obj_t * pNode, int fConst1 ) +{ + Abc_Obj_t * pNodeNew; + assert( Abc_NtkIsLogic(pNode->pNtk) ); + assert( !Abc_ObjIsCo(pNode) ); + pNodeNew = fConst1 ? Abc_NtkCreateNodeConst1(pNode->pNtk) : Abc_NtkCreateNodeConst0(pNode->pNtk); + // transfer the fanouts to the old node + Abc_ObjTransferFanout( pNode, pNodeNew ); + // remove the old node + if ( Abc_ObjIsNode(pNode) ) + Abc_NtkDeleteObj_rec( pNode, 1 ); +} + +/**Function************************************************************* + + Synopsis [Returns the index of the fanin in the fanin list of the fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjFanoutFaninNum( Abc_Obj_t * pFanout, Abc_Obj_t * pFanin ) +{ + Abc_Obj_t * pObj; + int i; + Abc_ObjForEachFanin( pFanout, pObj, i ) + if ( pObj == pFanin ) + return i; + return -1; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/abcFunc.c b/yosys/abc/src/base/abc/abcFunc.c new file mode 100644 index 00000000000..68b5688b8b2 --- /dev/null +++ b/yosys/abc/src/base/abc/abcFunc.c @@ -0,0 +1,1400 @@ +/**CFile**************************************************************** + + FileName [abcFunc.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Transformations between different functionality representations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcFunc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "base/main/main.h" +#include "map/mio/mio.h" + +#ifdef ABC_USE_CUDD +#include "bdd/extrab/extraBdd.h" +#endif + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define ABC_MAX_CUBES 1000000 +#define ABC_MAX_CUBES2 10000 + +static Hop_Obj_t * Abc_ConvertSopToAig( Hop_Man_t * pMan, char * pSop ); + +#ifdef ABC_USE_CUDD + +int Abc_ConvertZddToSop( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase ); +static DdNode * Abc_ConvertAigToBdd( DdManager * dd, Hop_Obj_t * pRoot); +extern int Abc_CountZddCubes( DdManager * dd, DdNode * zCover ); +extern void Abc_NtkSortCubes( Abc_Ntk_t * pNtk, int fWeight ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Converts the node from SOP to BDD representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ConvertSopToBdd2Count( char * pSop, int nCubes, int nStep, int iVar, int pRes[3] ) +{ + int i; + for ( i = 0; i < nCubes; i++ ) + if ( pSop[i*nStep+iVar] == '-' ) + pRes[0]++, assert( pRes[1] == 0 && pRes[2] == 0 ); + else if ( pSop[i*nStep+iVar] == '0' ) + pRes[1]++, assert( pRes[2] == 0 ); + else if ( pSop[i*nStep+iVar] == '1' ) + pRes[2]++; + else assert( 0 ); +} +DdNode * Abc_ConvertSopToBdd2_rec( DdManager * dd, char * pSop, DdNode ** pbVars, int nCubes, int nStep, int iVar ) +{ + DdNode * bRes[5] = {NULL}; + int pRes[3] = {0}, i, Start = 0; + if ( nCubes == 0 ) + return Cudd_ReadLogicZero(dd); + if ( iVar == nStep - 3 ) + return Cudd_ReadOne(dd); + Abc_ConvertSopToBdd2Count( pSop, nCubes, nStep, iVar, pRes ); + for ( i = 0; i < 3; Start += pRes[i++] ) + bRes[i] = Abc_ConvertSopToBdd2_rec( dd, pSop + Start*nStep, pbVars, pRes[i], nStep, iVar+1 ), Cudd_Ref( bRes[i] ); + bRes[3] = Cudd_bddIte( dd, pbVars[iVar], bRes[2], bRes[1] ); Cudd_Ref( bRes[3] ); + Cudd_RecursiveDeref( dd, bRes[1] ); + Cudd_RecursiveDeref( dd, bRes[2] ); + bRes[4] = Cudd_bddOr( dd, bRes[0], bRes[3] ); Cudd_Ref( bRes[4] ); + Cudd_RecursiveDeref( dd, bRes[3] ); + Cudd_RecursiveDeref( dd, bRes[0] ); + Cudd_Deref( bRes[4] ); + return bRes[4]; +} +DdNode * Abc_ConvertSopToBdd2( DdManager * dd, char * pSop, DdNode ** pbVars ) +{ + int nCubes = Abc_SopGetCubeNum(pSop); + int nStep = Abc_SopGetVarNum(pSop) + 3; + assert( pSop[nCubes*nStep] == '\0' ); + return Abc_ConvertSopToBdd2_rec( dd, pSop, pbVars, nCubes, nStep, 0 ); +} + +/**Function************************************************************* + + Synopsis [Converts the node from SOP to BDD representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_ConvertSopToBdd( DdManager * dd, char * pSop, DdNode ** pbVars ) +{ + DdNode * bSum, * bCube, * bTemp, * bVar; + char * pCube; + int nVars, Value, v; + + // start the cover + nVars = Abc_SopGetVarNum(pSop); + bSum = Cudd_ReadLogicZero(dd); Cudd_Ref( bSum ); + if ( Abc_SopIsExorType(pSop) ) + { + for ( v = 0; v < nVars; v++ ) + { + bSum = Cudd_bddXor( dd, bTemp = bSum, pbVars? pbVars[v] : Cudd_bddIthVar(dd, v) ); Cudd_Ref( bSum ); + Cudd_RecursiveDeref( dd, bTemp ); + } + } + else if ( Abc_SopGetCubeNum(pSop) > ABC_MAX_CUBES2 ) + { + Cudd_Deref( bSum ); + if ( pbVars ) + bSum = Abc_ConvertSopToBdd2( dd, pSop, pbVars ); + else + { + DdNode ** pbVars = ABC_ALLOC( DdNode *, nVars ); + for ( v = 0; v < nVars; v++ ) + pbVars[v] = Cudd_bddIthVar( dd, v ); + bSum = Abc_ConvertSopToBdd2( dd, pSop, pbVars ); + ABC_FREE( pbVars ); + } + Cudd_Ref( bSum ); + } + else + { + // check the logic function of the node + Abc_SopForEachCube( pSop, nVars, pCube ) + { + bCube = Cudd_ReadOne(dd); Cudd_Ref( bCube ); + Abc_CubeForEachVar( pCube, Value, v ) + { + if ( Value == '0' ) + bVar = Cudd_Not( pbVars? pbVars[v] : Cudd_bddIthVar( dd, v ) ); + else if ( Value == '1' ) + bVar = pbVars? pbVars[v] : Cudd_bddIthVar( dd, v ); + else + continue; + bCube = Cudd_bddAnd( dd, bTemp = bCube, bVar ); Cudd_Ref( bCube ); + Cudd_RecursiveDeref( dd, bTemp ); + } + bSum = Cudd_bddOr( dd, bTemp = bSum, bCube ); + Cudd_Ref( bSum ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bCube ); + } + } + // complement the result if necessary + bSum = Cudd_NotCond( bSum, !Abc_SopGetPhase(pSop) ); + Cudd_Deref( bSum ); + return bSum; +} + +/**Function************************************************************* + + Synopsis [Converts the network from SOP to BDD representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkSopToBdd( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + DdManager * dd, * ddTemp = NULL; + Vec_Int_t * vFanins = NULL; + int nFaninsMax, i, k, iVar, nCubesMax = 0; + + assert( Abc_NtkHasSop(pNtk) ); + + // check SOP sizes + Abc_NtkForEachNode( pNtk, pNode, i ) + nCubesMax = Abc_MaxInt( nCubesMax, Abc_SopGetCubeNum((char *)pNode->pData) ); + if ( nCubesMax > ABC_MAX_CUBES2 ) + Abc_NtkSortCubes( pNtk, 0 ); + + // start the functionality manager + nFaninsMax = Abc_NtkGetFaninMax( pNtk ); + if ( nFaninsMax == 0 ) + printf( "Warning: The network has only constant nodes.\n" ); + dd = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + + // start temporary manager for reordered local functions + if ( nFaninsMax > 10 ) + { + ddTemp = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( ddTemp, CUDD_REORDER_SYMM_SIFT ); + vFanins = Vec_IntAlloc( nFaninsMax ); + } + + // convert each node from SOP to BDD + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_ObjIsBarBuf(pNode) ) + continue; + assert( pNode->pData ); + if ( Abc_ObjFaninNum(pNode) > 10 ) + { + DdNode * pFunc = Abc_ConvertSopToBdd( ddTemp, (char *)pNode->pData, NULL ); + if ( pFunc == NULL ) + { + printf( "Abc_NtkSopToBdd: Error while converting SOP into BDD.\n" ); + return 0; + } + Cudd_Ref( pFunc ); + // find variable mapping + Vec_IntFill( vFanins, Abc_ObjFaninNum(pNode), -1 ); + for ( k = iVar = 0; k < nFaninsMax; k++ ) + if ( ddTemp->invperm[k] < Abc_ObjFaninNum(pNode) ) + Vec_IntWriteEntry( vFanins, ddTemp->invperm[k], iVar++ ); + assert( iVar == Abc_ObjFaninNum(pNode) ); + // transfer to the main manager + pNode->pData = Extra_TransferPermute( ddTemp, dd, pFunc, Vec_IntArray(vFanins) ); + Cudd_Ref( (DdNode *)pNode->pData ); + Cudd_RecursiveDeref( ddTemp, pFunc ); + // update variable order + Vec_IntClear( vFanins ); + for ( k = 0; k < nFaninsMax; k++ ) + if ( ddTemp->invperm[k] < Abc_ObjFaninNum(pNode) ) + Vec_IntPush( vFanins, Vec_IntEntry(&pNode->vFanins, ddTemp->invperm[k]) ); + for ( k = 0; k < Abc_ObjFaninNum(pNode); k++ ) + Vec_IntWriteEntry( &pNode->vFanins, k, Vec_IntEntry(vFanins, k) ); + } + else + { + pNode->pData = Abc_ConvertSopToBdd( dd, (char *)pNode->pData, NULL ); + if ( pNode->pData == NULL ) + { + printf( "Abc_NtkSopToBdd: Error while converting SOP into BDD.\n" ); + return 0; + } + Cudd_Ref( (DdNode *)pNode->pData ); + } + } + + if ( ddTemp ) + { +// printf( "Reorderings performed = %d.\n", Cudd_ReadReorderings(ddTemp) ); + Extra_StopManager( ddTemp ); + } + Vec_IntFreeP( &vFanins ); + Mem_FlexStop( (Mem_Flex_t *)pNtk->pManFunc, 0 ); + pNtk->pManFunc = dd; + + // update the network type + pNtk->ntkFunc = ABC_FUNC_BDD; + return 1; +} + + + + +/**Function************************************************************* + + Synopsis [Converts the node from BDD to SOP representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_ConvertBddToSop( Mem_Flex_t * pMan, DdManager * dd, DdNode * bFuncOn, DdNode * bFuncOnDc, int nFanins, int fAllPrimes, Vec_Str_t * vCube, int fMode ) +{ + int fVerify = 0; + char * pSop; + DdNode * bFuncNew, * bCover, * zCover, * zCover0, * zCover1; + int nCubes = 0, nCubes0, nCubes1, fPhase = 0; + + assert( bFuncOn == bFuncOnDc || Cudd_bddLeq( dd, bFuncOn, bFuncOnDc ) ); + if ( Cudd_IsConstant(bFuncOn) || Cudd_IsConstant(bFuncOnDc) ) + { + if ( pMan ) + pSop = Mem_FlexEntryFetch( pMan, nFanins + 4 ); + else + pSop = ABC_ALLOC( char, nFanins + 4 ); + pSop[0] = ' '; + pSop[1] = '0' + (int)(bFuncOn == Cudd_ReadOne(dd)); + pSop[2] = '\n'; + pSop[3] = '\0'; + return pSop; + } + + if ( fMode == -1 ) + { // try both phases + assert( fAllPrimes == 0 ); + + // get the ZDD of the negative polarity + bCover = Cudd_zddIsop( dd, Cudd_Not(bFuncOnDc), Cudd_Not(bFuncOn), &zCover0 ); + Cudd_Ref( zCover0 ); + Cudd_Ref( bCover ); + Cudd_RecursiveDeref( dd, bCover ); + nCubes0 = Abc_CountZddCubes( dd, zCover0 ); + + // get the ZDD of the positive polarity + bCover = Cudd_zddIsop( dd, bFuncOn, bFuncOnDc, &zCover1 ); + Cudd_Ref( zCover1 ); + Cudd_Ref( bCover ); + Cudd_RecursiveDeref( dd, bCover ); + nCubes1 = Abc_CountZddCubes( dd, zCover1 ); + + // compare the number of cubes + if ( nCubes1 <= nCubes0 ) + { // use positive polarity + nCubes = nCubes1; + zCover = zCover1; + Cudd_RecursiveDerefZdd( dd, zCover0 ); + fPhase = 1; + } + else + { // use negative polarity + nCubes = nCubes0; + zCover = zCover0; + Cudd_RecursiveDerefZdd( dd, zCover1 ); + fPhase = 0; + } + } + else if ( fMode == 0 ) + { + // get the ZDD of the negative polarity + if ( fAllPrimes ) + { + zCover = Extra_zddPrimes( dd, Cudd_Not(bFuncOnDc) ); + Cudd_Ref( zCover ); + } + else + { + bCover = Cudd_zddIsop( dd, Cudd_Not(bFuncOnDc), Cudd_Not(bFuncOn), &zCover ); + Cudd_Ref( zCover ); + Cudd_Ref( bCover ); + Cudd_RecursiveDeref( dd, bCover ); + } + nCubes = Abc_CountZddCubes( dd, zCover ); + fPhase = 0; + } + else if ( fMode == 1 ) + { + // get the ZDD of the positive polarity + if ( fAllPrimes ) + { + zCover = Extra_zddPrimes( dd, bFuncOnDc ); + Cudd_Ref( zCover ); + } + else + { + bCover = Cudd_zddIsop( dd, bFuncOn, bFuncOnDc, &zCover ); + Cudd_Ref( zCover ); + Cudd_Ref( bCover ); + Cudd_RecursiveDeref( dd, bCover ); + } + nCubes = Abc_CountZddCubes( dd, zCover ); + fPhase = 1; + } + else + { + assert( 0 ); + } + + if ( nCubes > ABC_MAX_CUBES ) + { + Cudd_RecursiveDerefZdd( dd, zCover ); + printf( "The number of cubes exceeded the predefined limit (%d).\n", ABC_MAX_CUBES ); + return NULL; + } + + // allocate memory for the cover + if ( pMan ) + pSop = Mem_FlexEntryFetch( pMan, (nFanins + 3) * nCubes + 1 ); + else + pSop = ABC_ALLOC( char, (nFanins + 3) * nCubes + 1 ); + pSop[(nFanins + 3) * nCubes] = 0; + // create the SOP + Vec_StrFill( vCube, nFanins, '-' ); + Vec_StrPush( vCube, '\0' ); + Abc_ConvertZddToSop( dd, zCover, pSop, nFanins, vCube, fPhase ); + Cudd_RecursiveDerefZdd( dd, zCover ); + + // verify + if ( fVerify ) + { + bFuncNew = Abc_ConvertSopToBdd( dd, pSop, NULL ); Cudd_Ref( bFuncNew ); + if ( bFuncOn == bFuncOnDc ) + { + if ( bFuncNew != bFuncOn ) + printf( "Verification failed.\n" ); + } + else + { + if ( !Cudd_bddLeq(dd, bFuncOn, bFuncNew) || !Cudd_bddLeq(dd, bFuncNew, bFuncOnDc) ) + printf( "Verification failed.\n" ); + } + Cudd_RecursiveDeref( dd, bFuncNew ); + } + return pSop; +} + +/**Function************************************************************* + + Synopsis [Converts the network from BDD to SOP representation.] + + Description [If the flag is set to 1, forces the direct phase of all covers.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit, int fCubeSort ) +{ + Vec_Int_t * vGuide; + Vec_Str_t * vCube; + Abc_Obj_t * pNode; + Mem_Flex_t * pManNew; + DdManager * dd = (DdManager *)pNtk->pManFunc; + DdNode * bFunc; + int i, nCubes; + + // compute SOP size + vGuide = Vec_IntAlloc( Abc_NtkObjNumMax(pNtk) ); + Vec_IntFill( vGuide, Abc_NtkObjNumMax(pNtk), fMode ); + if ( nCubeLimit < ABC_INFINITY ) + { + // collect all BDDs into one array + Vec_Ptr_t * vFuncs = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); + assert( !Cudd_ReorderingStatus(dd, (Cudd_ReorderingType *)&nCubes) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( !Abc_ObjIsBarBuf(pNode) ) + Vec_PtrWriteEntry( vFuncs, i, pNode->pData ); + // compute the number of cubes in the ISOPs and detemine polarity + nCubes = Extra_bddCountCubes( dd, (DdNode **)Vec_PtrArray(vFuncs), Vec_PtrSize(vFuncs), fMode, nCubeLimit, Vec_IntArray(vGuide) ); + Vec_PtrFree( vFuncs ); + if ( nCubes == -1 ) + { + Vec_IntFree( vGuide ); + return 0; + } + //printf( "The total number of cubes = %d.\n", nCubes ); + } + + assert( Abc_NtkHasBdd(pNtk) ); + if ( dd->size > 0 ) + Cudd_zddVarsFromBddVars( dd, 2 ); + // create the new manager + pManNew = Mem_FlexStart(); + + // go through the objects + vCube = Vec_StrAlloc( 100 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_ObjIsBarBuf(pNode) ) + continue; + assert( pNode->pData ); + bFunc = (DdNode *)pNode->pData; + pNode->pNext = (Abc_Obj_t *)Abc_ConvertBddToSop( pManNew, dd, bFunc, bFunc, Abc_ObjFaninNum(pNode), 0, vCube, Vec_IntEntry(vGuide, i) ); + if ( pNode->pNext == NULL ) + { + Mem_FlexStop( pManNew, 0 ); + Abc_NtkCleanNext( pNtk ); +// printf( "Converting from BDDs to SOPs has failed.\n" ); + Vec_IntFree( vGuide ); + Vec_StrFree( vCube ); + return 0; + } + // it may happen that a constant node was created after structural mapping + if ( Abc_SopGetVarNum((char *)pNode->pNext) == 0 ) + pNode->vFanins.nSize = 0; + // check the support + if ( Abc_ObjFaninNum(pNode) != Abc_SopGetVarNum((char *)pNode->pNext) ) + { + printf( "Node %d with level %d has %d fanins but its SOP has support size %d.\n", + pNode->Id, pNode->Level, Abc_ObjFaninNum(pNode), Abc_SopGetVarNum((char *)pNode->pNext) ); + fflush( stdout ); + } + assert( Abc_ObjFaninNum(pNode) == Abc_SopGetVarNum((char *)pNode->pNext) ); + } + Vec_IntFree( vGuide ); + Vec_StrFree( vCube ); + + // update the network type + pNtk->ntkFunc = ABC_FUNC_SOP; + // set the new manager + pNtk->pManFunc = pManNew; + // transfer from next to data + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_ObjIsBarBuf(pNode) ) + continue; + Cudd_RecursiveDeref( dd, (DdNode *)pNode->pData ); + pNode->pData = pNode->pNext; + pNode->pNext = NULL; + } + + // check for remaining references in the package + Extra_StopManager( dd ); + + // reorder fanins and cubes to make SOPs more human-readable + if ( fCubeSort ) + Abc_NtkSortSops( pNtk ); + return 1; +} + + +/**Function************************************************************* + + Synopsis [Derive the SOP from the ZDD representation of the cubes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ConvertZddToSop_rec( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase, int * pnCubes ) +{ + DdNode * zC0, * zC1, * zC2; + int Index; + + if ( zCover == dd->zero ) + return; + if ( zCover == dd->one ) + { + char * pCube; + pCube = pSop + (*pnCubes) * (nFanins + 3); + sprintf( pCube, "%s %d\n", vCube->pArray, fPhase ); + (*pnCubes)++; + return; + } + Index = zCover->index/2; + assert( Index < nFanins ); + extraDecomposeCover( dd, zCover, &zC0, &zC1, &zC2 ); + vCube->pArray[Index] = '0'; + Abc_ConvertZddToSop_rec( dd, zC0, pSop, nFanins, vCube, fPhase, pnCubes ); + vCube->pArray[Index] = '1'; + Abc_ConvertZddToSop_rec( dd, zC1, pSop, nFanins, vCube, fPhase, pnCubes ); + vCube->pArray[Index] = '-'; + Abc_ConvertZddToSop_rec( dd, zC2, pSop, nFanins, vCube, fPhase, pnCubes ); +} + +/**Function************************************************************* + + Synopsis [Derive the BDD for the function in the cut.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ConvertZddToSop( DdManager * dd, DdNode * zCover, char * pSop, int nFanins, Vec_Str_t * vCube, int fPhase ) +{ + int nCubes = 0; + Abc_ConvertZddToSop_rec( dd, zCover, pSop, nFanins, vCube, fPhase, &nCubes ); + return nCubes; +} + + +/**Function************************************************************* + + Synopsis [Computes the SOPs of the negative and positive phase of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeBddToCnf( Abc_Obj_t * pNode, Mem_Flex_t * pMmMan, Vec_Str_t * vCube, int fAllPrimes, char ** ppSop0, char ** ppSop1 ) +{ + assert( Abc_NtkHasBdd(pNode->pNtk) ); + *ppSop0 = Abc_ConvertBddToSop( pMmMan, (DdManager *)pNode->pNtk->pManFunc, (DdNode *)pNode->pData, (DdNode *)pNode->pData, Abc_ObjFaninNum(pNode), fAllPrimes, vCube, 0 ); + *ppSop1 = Abc_ConvertBddToSop( pMmMan, (DdManager *)pNode->pNtk->pManFunc, (DdNode *)pNode->pData, (DdNode *)pNode->pData, Abc_ObjFaninNum(pNode), fAllPrimes, vCube, 1 ); +} + + +/**Function************************************************************* + + Synopsis [Removes complemented SOP covers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk ) +{ + DdManager * dd; + DdNode * bFunc; + Vec_Str_t * vCube; + Abc_Obj_t * pNode; + int nFaninsMax, fFound, i; + + assert( Abc_NtkHasSop(pNtk) ); + + // check if there are nodes with complemented SOPs + fFound = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( !Abc_ObjIsBarBuf(pNode) && Abc_SopIsComplement((char *)pNode->pData) ) + { + fFound = 1; + break; + } + if ( !fFound ) + return; + + // start the BDD package + nFaninsMax = Abc_NtkGetFaninMax( pNtk ); + if ( nFaninsMax == 0 ) + printf( "Warning: The network has only constant nodes.\n" ); + dd = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + + // change the cover of negated nodes + vCube = Vec_StrAlloc( 100 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + if ( !Abc_ObjIsBarBuf(pNode) && Abc_SopIsComplement((char *)pNode->pData) ) + { + bFunc = Abc_ConvertSopToBdd( dd, (char *)pNode->pData, NULL ); Cudd_Ref( bFunc ); + pNode->pData = Abc_ConvertBddToSop( (Mem_Flex_t *)pNtk->pManFunc, dd, bFunc, bFunc, Abc_ObjFaninNum(pNode), 0, vCube, 1 ); + Cudd_RecursiveDeref( dd, bFunc ); + assert( !Abc_SopIsComplement((char *)pNode->pData) ); + } + Vec_StrFree( vCube ); + Extra_StopManager( dd ); +} + + + + +/**Function************************************************************* + + Synopsis [Count the number of paths in the ZDD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_CountZddCubes_rec( DdManager * dd, DdNode * zCover, int * pnCubes ) +{ + DdNode * zC0, * zC1, * zC2; + if ( zCover == dd->zero ) + return; + if ( zCover == dd->one ) + { + (*pnCubes)++; + return; + } + if ( (*pnCubes) > ABC_MAX_CUBES ) + return; + extraDecomposeCover( dd, zCover, &zC0, &zC1, &zC2 ); + Abc_CountZddCubes_rec( dd, zC0, pnCubes ); + Abc_CountZddCubes_rec( dd, zC1, pnCubes ); + Abc_CountZddCubes_rec( dd, zC2, pnCubes ); +} + +/**Function************************************************************* + + Synopsis [Count the number of paths in the ZDD.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CountZddCubes( DdManager * dd, DdNode * zCover ) +{ + int nCubes = 0; + Abc_CountZddCubes_rec( dd, zCover, &nCubes ); + return nCubes; +} + +/**Function************************************************************* + + Synopsis [Converts the network from AIG to BDD representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkAigToBdd( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + Hop_Man_t * pMan; + DdNode * pFunc; + DdManager * dd, * ddTemp = NULL; + Vec_Int_t * vFanins = NULL; + int nFaninsMax, i, k, iVar; + + assert( Abc_NtkHasAig(pNtk) ); + + // start the functionality manager + nFaninsMax = Abc_NtkGetFaninMax( pNtk ); + if ( nFaninsMax == 0 ) + printf( "Warning: The network has only constant nodes.\n" ); + + dd = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + + // start temporary manager for reordered local functions + ddTemp = Cudd_Init( nFaninsMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); + Cudd_AutodynEnable( ddTemp, CUDD_REORDER_SYMM_SIFT ); + vFanins = Vec_IntAlloc( nFaninsMax ); + + // set the mapping of elementary AIG nodes into the elementary BDD nodes + pMan = (Hop_Man_t *)pNtk->pManFunc; + assert( Hop_ManPiNum(pMan) >= nFaninsMax ); + for ( i = 0; i < nFaninsMax; i++ ) + Hop_ManPi(pMan, i)->pData = Cudd_bddIthVar(ddTemp, i); + + // convert each node from SOP to BDD + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_ObjIsBarBuf(pNode) ) + continue; + pFunc = Abc_ConvertAigToBdd( ddTemp, (Hop_Obj_t *)pNode->pData ); + if ( pFunc == NULL ) + { + printf( "Abc_NtkAigToBdd: Error while converting AIG into BDD.\n" ); + return 0; + } + Cudd_Ref( pFunc ); + // find variable mapping + Vec_IntFill( vFanins, Abc_ObjFaninNum(pNode), -1 ); + for ( k = iVar = 0; k < nFaninsMax; k++ ) + if ( ddTemp->invperm[k] < Abc_ObjFaninNum(pNode) ) + Vec_IntWriteEntry( vFanins, ddTemp->invperm[k], iVar++ ); + assert( iVar == Abc_ObjFaninNum(pNode) ); + // transfer to the main manager + pNode->pData = Extra_TransferPermute( ddTemp, dd, pFunc, Vec_IntArray(vFanins) ); + Cudd_Ref( (DdNode *)pNode->pData ); + Cudd_RecursiveDeref( ddTemp, pFunc ); + // update variable order + Vec_IntClear( vFanins ); + for ( k = 0; k < nFaninsMax; k++ ) + if ( ddTemp->invperm[k] < Abc_ObjFaninNum(pNode) ) + Vec_IntPush( vFanins, Vec_IntEntry(&pNode->vFanins, ddTemp->invperm[k]) ); + for ( k = 0; k < Abc_ObjFaninNum(pNode); k++ ) + Vec_IntWriteEntry( &pNode->vFanins, k, Vec_IntEntry(vFanins, k) ); + } + +// printf( "Reorderings performed = %d.\n", Cudd_ReadReorderings(ddTemp) ); + Extra_StopManager( ddTemp ); + Vec_IntFreeP( &vFanins ); + Hop_ManStop( (Hop_Man_t *)pNtk->pManFunc ); + pNtk->pManFunc = dd; + + // update the network type + pNtk->ntkFunc = ABC_FUNC_BDD; + return 1; +} + +/**Function************************************************************* + + Synopsis [Construct BDDs and mark AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ConvertAigToBdd_rec1( DdManager * dd, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Abc_ConvertAigToBdd_rec1( dd, Hop_ObjFanin0(pObj) ); + Abc_ConvertAigToBdd_rec1( dd, Hop_ObjFanin1(pObj) ); + pObj->pData = Cudd_bddAnd( dd, (DdNode *)Hop_ObjChild0Copy(pObj), (DdNode *)Hop_ObjChild1Copy(pObj) ); + Cudd_Ref( (DdNode *)pObj->pData ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Dereference BDDs and unmark AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ConvertAigToBdd_rec2( DdManager * dd, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) ) + return; + Abc_ConvertAigToBdd_rec2( dd, Hop_ObjFanin0(pObj) ); + Abc_ConvertAigToBdd_rec2( dd, Hop_ObjFanin1(pObj) ); + Cudd_RecursiveDeref( dd, (DdNode *)pObj->pData ); + pObj->pData = NULL; + assert( Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjClearMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Converts the network from AIG to BDD representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_ConvertAigToBdd( DdManager * dd, Hop_Obj_t * pRoot ) +{ + DdNode * bFunc; + // check the case of a constant + if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) + return Cudd_NotCond( Cudd_ReadOne(dd), Hop_IsComplement(pRoot) ); + // construct BDD + Abc_ConvertAigToBdd_rec1( dd, Hop_Regular(pRoot) ); + // hold on to the result + bFunc = Cudd_NotCond( Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); Cudd_Ref( bFunc ); + // dereference BDD + Abc_ConvertAigToBdd_rec2( dd, Hop_Regular(pRoot) ); + // return the result + Cudd_Deref( bFunc ); + return bFunc; +} + +#else + +int Abc_NtkSopToBdd( Abc_Ntk_t * pNtk ) { return 1; } +int Abc_NtkBddToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit, int fCubeSort ) { return 1; } +void Abc_NodeBddToCnf( Abc_Obj_t * pNode, Mem_Flex_t * pMmMan, Vec_Str_t * vCube, int fAllPrimes, char ** ppSop0, char ** ppSop1 ) {} +void Abc_NtkLogicMakeDirectSops( Abc_Ntk_t * pNtk ) {} +int Abc_NtkAigToBdd( Abc_Ntk_t * pNtk ) { return 1; } + +#endif + +/**Function************************************************************* + + Synopsis [Converts the network from SOP to AIG representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkSopToAig( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + Hop_Man_t * pMan; + int i, Max; + + assert( Abc_NtkHasSop(pNtk) ); + + // make dist1-free and SCC-free +// Abc_NtkMakeLegit( pNtk ); + + // start the functionality manager + pMan = Hop_ManStart(); + Max = Abc_NtkGetFaninMax(pNtk); + if ( Max ) Hop_IthVar( pMan, Max-1 ); + + // convert each node from SOP to BDD + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_ObjIsBarBuf(pNode) ) + continue; + assert( pNode->pData ); + pNode->pData = Abc_ConvertSopToAig( pMan, (char *)pNode->pData ); + if ( pNode->pData == NULL ) + { + Hop_ManStop( pMan ); + printf( "Abc_NtkSopToAig: Error while converting SOP into AIG.\n" ); + return 0; + } + } + Mem_FlexStop( (Mem_Flex_t *)pNtk->pManFunc, 0 ); + pNtk->pManFunc = pMan; + + // update the network type + pNtk->ntkFunc = ABC_FUNC_AIG; + return 1; +} + + +/**Function************************************************************* + + Synopsis [Strashes one logic node using its SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Abc_ConvertSopToAigInternal( Hop_Man_t * pMan, char * pSop ) +{ + Hop_Obj_t * pAnd, * pSum; + int i, Value, nFanins; + char * pCube; + // get the number of variables + nFanins = Abc_SopGetVarNum(pSop); + if ( Abc_SopIsExorType(pSop) ) + { + pSum = Hop_ManConst0(pMan); + for ( i = 0; i < nFanins; i++ ) + pSum = Hop_Exor( pMan, pSum, Hop_IthVar(pMan,i) ); + } + else + { + // go through the cubes of the node's SOP + pSum = Hop_ManConst0(pMan); + Abc_SopForEachCube( pSop, nFanins, pCube ) + { + // create the AND of literals + pAnd = Hop_ManConst1(pMan); + Abc_CubeForEachVar( pCube, Value, i ) + { + if ( Value == '1' ) + pAnd = Hop_And( pMan, pAnd, Hop_IthVar(pMan,i) ); + else if ( Value == '0' ) + pAnd = Hop_And( pMan, pAnd, Hop_Not(Hop_IthVar(pMan,i)) ); + } + // add to the sum of cubes + pSum = Hop_Or( pMan, pSum, pAnd ); + } + } + // decide whether to complement the result + if ( Abc_SopIsComplement(pSop) ) + pSum = Hop_Not(pSum); + return pSum; +} + +/**Function************************************************************* + + Synopsis [Converts the network from AIG to BDD representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Abc_ConvertSopToAig( Hop_Man_t * pMan, char * pSop ) +{ + extern Hop_Obj_t * Dec_GraphFactorSop( Hop_Man_t * pMan, char * pSop ); + int fUseFactor = 1; + // consider the constant node + if ( Abc_SopGetVarNum(pSop) == 0 ) + return Hop_NotCond( Hop_ManConst1(pMan), Abc_SopIsConst0(pSop) ); + // decide when to use factoring + if ( fUseFactor && Abc_SopGetVarNum(pSop) > 2 && Abc_SopGetCubeNum(pSop) > 1 && !Abc_SopIsExorType(pSop) ) + return Dec_GraphFactorSop( pMan, pSop ); + return Abc_ConvertSopToAigInternal( pMan, pSop ); +} + + +/**Function************************************************************* + + Synopsis [Converts the network from AIG to GIA representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ConvertAigToGia_rec1( Gia_Man_t * p, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Abc_ConvertAigToGia_rec1( p, Hop_ObjFanin0(pObj) ); + Abc_ConvertAigToGia_rec1( p, Hop_ObjFanin1(pObj) ); + pObj->iData = Gia_ManAppendAnd2( p, Hop_ObjChild0CopyI(pObj), Hop_ObjChild1CopyI(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); +} +void Abc_ConvertAigToGia_rec2( Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || !Hop_ObjIsMarkA(pObj) ) + return; + Abc_ConvertAigToGia_rec2( Hop_ObjFanin0(pObj) ); + Abc_ConvertAigToGia_rec2( Hop_ObjFanin1(pObj) ); + assert( Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjClearMarkA( pObj ); +} +int Abc_ConvertAigToGia( Gia_Man_t * p, Hop_Obj_t * pRoot ) +{ + assert( !Hop_IsComplement(pRoot) ); + if ( Hop_ObjIsConst1( pRoot ) ) + return 1; + Abc_ConvertAigToGia_rec1( p, pRoot ); + Abc_ConvertAigToGia_rec2( pRoot ); + return pRoot->iData; +} + +/**Function************************************************************* + + Synopsis [Converts the network from AIG to BDD representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Abc_NtkAigToGia( Abc_Ntk_t * p, int fGiaSimple ) +{ + Gia_Man_t * pNew; + Hop_Man_t * pHopMan; + Hop_Obj_t * pHopObj; + Vec_Int_t * vMapping = NULL; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode, * pFanin; + int i, k, nObjs, iGiaObj; + assert( Abc_NtkIsAigLogic(p) ); + pHopMan = (Hop_Man_t *)p->pManFunc; + // create new manager + pNew = Gia_ManStart( 10000 ); + pNew->pName = Abc_UtilStrsav( Abc_NtkName(p) ); + pNew->pSpec = Abc_UtilStrsav( Abc_NtkSpec(p) ); + pNew->fGiaSimple = fGiaSimple; + Abc_NtkCleanCopy( p ); + Hop_ManConst1(pHopMan)->iData = 1; + // create primary inputs + Abc_NtkForEachCi( p, pNode, i ) + pNode->iTemp = Gia_ManAppendCi(pNew); + // find the number of objects + nObjs = 1 + Abc_NtkCiNum(p) + Abc_NtkCoNum(p); + Abc_NtkForEachNode( p, pNode, i ) + nObjs += Abc_ObjIsBarBuf(pNode) ? 1 : Hop_DagSize( (Hop_Obj_t *)pNode->pData ); + if ( !fGiaSimple ) + vMapping = Vec_IntStart( nObjs ); + // iterate through nodes used in the mapping + vNodes = Abc_NtkDfs( p, 0 ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) + { + if ( Abc_ObjIsBarBuf(pNode) ) + { + assert( !Abc_ObjFaninC0(pNode) ); + pNode->iTemp = Gia_ManAppendBuf( pNew, Abc_ObjFanin0(pNode)->iTemp ); + continue; + } + Abc_ObjForEachFanin( pNode, pFanin, k ) + Hop_ManPi(pHopMan, k)->iData = pFanin->iTemp; + pHopObj = Hop_Regular( (Hop_Obj_t *)pNode->pData ); + if ( Hop_DagSize(pHopObj) > 0 ) + { + assert( Abc_ObjFaninNum(pNode) <= Hop_ManPiNum(pHopMan) ); + Abc_ConvertAigToGia( pNew, pHopObj ); + iGiaObj = Abc_Lit2Var( pHopObj->iData ); + if ( vMapping && Gia_ObjIsAnd(Gia_ManObj(pNew, iGiaObj)) && !Vec_IntEntry(vMapping, iGiaObj) ) + { + Vec_IntWriteEntry( vMapping, iGiaObj, Vec_IntSize(vMapping) ); + Vec_IntPush( vMapping, Abc_ObjFaninNum(pNode) ); + Abc_ObjForEachFanin( pNode, pFanin, k ) + Vec_IntPush( vMapping, Abc_Lit2Var(pFanin->iTemp) ); + Vec_IntPush( vMapping, iGiaObj ); + } + } + pNode->iTemp = Abc_LitNotCond( pHopObj->iData, Hop_IsComplement( (Hop_Obj_t *)pNode->pData ) ); + } + // create primary outputs + Abc_NtkForEachCo( p, pNode, i ) + Gia_ManAppendCo( pNew, Abc_ObjFanin0(pNode)->iTemp ); + Gia_ManSetRegNum( pNew, Abc_NtkLatchNum(p) ); + // copy original IDs + pNew->vIdsOrig = Vec_IntStart( Gia_ManObjNum(pNew) ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) + Vec_IntWriteEntry( pNew->vIdsOrig, Abc_Lit2Var(pNode->iTemp), Abc_ObjId(pNode) ); + Vec_PtrFree( vNodes ); + // finish mapping + assert( Gia_ManObjNum(pNew) <= nObjs ); + assert( pNew->vMapping == NULL ); + pNew->vMapping = vMapping; + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Construct BDDs and mark AIG nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ConvertAigToAig_rec( Abc_Ntk_t * pNtkAig, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Abc_ConvertAigToAig_rec( pNtkAig, Hop_ObjFanin0(pObj) ); + Abc_ConvertAigToAig_rec( pNtkAig, Hop_ObjFanin1(pObj) ); + pObj->pData = Abc_AigAnd( (Abc_Aig_t *)pNtkAig->pManFunc, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); +} + +/**Function************************************************************* + + Synopsis [Converts the network from AIG to BDD representation.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_ConvertAigToAig( Abc_Ntk_t * pNtkAig, Abc_Obj_t * pObjOld ) +{ + Hop_Man_t * pHopMan; + Hop_Obj_t * pRoot; + Abc_Obj_t * pFanin; + int i; + // get the local AIG + pHopMan = (Hop_Man_t *)pObjOld->pNtk->pManFunc; + pRoot = (Hop_Obj_t *)pObjOld->pData; + // check the case of a constant + if ( Hop_ObjIsConst1( Hop_Regular(pRoot) ) ) + return Abc_ObjNotCond( Abc_AigConst1(pNtkAig), Hop_IsComplement(pRoot) ); + // assign the fanin nodes + Abc_ObjForEachFanin( pObjOld, pFanin, i ) + { + assert( pFanin->pCopy != NULL ); + Hop_ManPi(pHopMan, i)->pData = pFanin->pCopy; + } + // construct the AIG + Abc_ConvertAigToAig_rec( pNtkAig, Hop_Regular(pRoot) ); + Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); + // return the result + return Abc_ObjNotCond( (Abc_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) ); +} + + +/**Function************************************************************* + + Synopsis [Unmaps the network with user provided Mio library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMapToSopUsingLibrary( Abc_Ntk_t * pNtk, void* library) +{ + Abc_Obj_t * pNode; + char * pSop; + int i; + + assert( Abc_NtkHasMapping(pNtk) ); + // update the functionality manager + assert( pNtk->pManFunc == (void*) library ); + pNtk->pManFunc = Mem_FlexStart(); + // update the nodes + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_ObjIsBarBuf(pNode) ) + continue; + pSop = Mio_GateReadSop((Mio_Gate_t *)pNode->pData); + assert( Abc_SopGetVarNum(pSop) == Abc_ObjFaninNum(pNode) ); + pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, pSop ); + } + pNtk->ntkFunc = ABC_FUNC_SOP; + return 1; +} + +/**Function************************************************************* + + Synopsis [Unmaps the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMapToSop( Abc_Ntk_t * pNtk ) +{ + extern void * Abc_FrameReadLibGen(); + return Abc_NtkMapToSopUsingLibrary(pNtk, Abc_FrameReadLibGen()); +} + +/**Function************************************************************* + + Synopsis [Converts SOP functions into BLIF-MV functions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkSopToBlifMv( Abc_Ntk_t * pNtk ) +{ + return 1; +} + +/**Function************************************************************* + + Synopsis [Convers logic network to the SOP form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkToSop( Abc_Ntk_t * pNtk, int fMode, int nCubeLimit ) +{ + assert( !Abc_NtkIsStrash(pNtk) ); + if ( Abc_NtkHasBlackbox(pNtk) ) + return 1; + if ( Abc_NtkHasSop(pNtk) ) + { + if ( fMode == -1 ) + return 1; + if ( !Abc_NtkSopToBdd(pNtk) ) + return 0; + return Abc_NtkBddToSop(pNtk, fMode, nCubeLimit, 1); + } + if ( Abc_NtkHasMapping(pNtk) ) + return Abc_NtkMapToSop(pNtk); + if ( Abc_NtkHasBdd(pNtk) ) + return Abc_NtkBddToSop(pNtk, fMode, nCubeLimit, 1); + if ( Abc_NtkHasAig(pNtk) ) + { + if ( !Abc_NtkAigToBdd(pNtk) ) + return 0; + return Abc_NtkBddToSop(pNtk, fMode, nCubeLimit, 1); + } + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Convers logic network to the SOP form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkToBdd( Abc_Ntk_t * pNtk ) +{ + assert( !Abc_NtkIsStrash(pNtk) ); + if ( Abc_NtkHasBlackbox(pNtk) ) + return 1; + if ( Abc_NtkHasBdd(pNtk) ) + return 1; + if ( Abc_NtkHasMapping(pNtk) ) + { + Abc_NtkMapToSop(pNtk); + return Abc_NtkSopToBdd(pNtk); + } + if ( Abc_NtkHasSop(pNtk) ) + { + Abc_NtkSopToAig(pNtk); + return Abc_NtkAigToBdd(pNtk); + } + if ( Abc_NtkHasAig(pNtk) ) + return Abc_NtkAigToBdd(pNtk); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Convers logic network to the SOP form.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkToAig( Abc_Ntk_t * pNtk ) +{ + assert( !Abc_NtkIsStrash(pNtk) ); + if ( Abc_NtkHasBlackbox(pNtk) ) + return 1; + if ( Abc_NtkHasAig(pNtk) ) + return 1; + if ( Abc_NtkHasMapping(pNtk) ) + { + Abc_NtkMapToSop(pNtk); + return Abc_NtkSopToAig(pNtk); + } + if ( Abc_NtkHasBdd(pNtk) ) + { + if ( !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY, 1) ) + return 0; + return Abc_NtkSopToAig(pNtk); + } + if ( Abc_NtkHasSop(pNtk) ) + return Abc_NtkSopToAig(pNtk); + assert( 0 ); + return 0; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjFaninSort( Abc_Obj_t * pObj ) +{ + Vec_Int_t * vFanins = Abc_ObjFaninVec( pObj ); + char * pCube, * pSop = (char*)pObj->pData; + int i, j, nVars = Abc_SopGetVarNum( pSop ); + assert( nVars == Vec_IntSize(vFanins) ); + for ( i = 0; i < Vec_IntSize(vFanins); i++ ) + for ( j = i+1; j < Vec_IntSize(vFanins); j++ ) + { + if ( Vec_IntEntry(vFanins, i) < Vec_IntEntry(vFanins, j) ) + continue; + ABC_SWAP( int, Vec_IntArray(vFanins)[i], Vec_IntArray(vFanins)[j] ); + for ( pCube = pSop; *pCube; pCube += nVars + 3 ) { + ABC_SWAP( char, pCube[i], pCube[j] ); + } + } +} +void Abc_NtkFaninSort( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; int i; + assert( Abc_NtkIsSopLogic(pNtk) ); + Abc_NtkForEachNode( pNtk, pObj, i ) + Abc_ObjFaninSort( pObj ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/abcHie.c b/yosys/abc/src/base/abc/abcHie.c new file mode 100644 index 00000000000..bd08c35d8d3 --- /dev/null +++ b/yosys/abc/src/base/abc/abcHie.c @@ -0,0 +1,843 @@ +/**CFile**************************************************************** + + FileName [abcHie.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures to handle hierarchy.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcHie.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Recursively flattens logic hierarchy of the netlist.] + + Description [When this procedure is called, the PI/PO nets of the old + netlist point to the corresponding nets of the flattened netlist.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFlattenLogicHierarchy2_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, int * pCounter ) +{ + char Suffix[2000] = {0}; + Abc_Ntk_t * pNtkModel; + Abc_Obj_t * pObj, * pTerm, * pNet, * pFanin; + int i, k; + + // process the blackbox + if ( Abc_NtkHasBlackbox(pNtk) ) + { + // duplicate the blackbox + assert( Abc_NtkBoxNum(pNtk) == 1 ); + pObj = Abc_NtkBox( pNtk, 0 ); + Abc_NtkDupBox( pNtkNew, pObj, 1 ); + pObj->pCopy->pData = pNtk; + + // connect blackbox fanins to the PI nets + assert( Abc_ObjFaninNum(pObj->pCopy) == Abc_NtkPiNum(pNtk) ); + Abc_NtkForEachPi( pNtk, pTerm, i ) + Abc_ObjAddFanin( Abc_ObjFanin(pObj->pCopy,i), Abc_ObjFanout0(pTerm)->pCopy ); + + // connect blackbox fanouts to the PO nets + assert( Abc_ObjFanoutNum(pObj->pCopy) == Abc_NtkPoNum(pNtk) ); + Abc_NtkForEachPo( pNtk, pTerm, i ) + Abc_ObjAddFanin( Abc_ObjFanin0(pTerm)->pCopy, Abc_ObjFanout(pObj->pCopy,i) ); + return; + } + + (*pCounter)++; + + // create the suffix, which will be appended to the internal names + if ( *pCounter ) + sprintf( Suffix, "_%s_%d", Abc_NtkName(pNtk), *pCounter ); + + // duplicate nets of all boxes, including latches + Abc_NtkForEachBox( pNtk, pObj, i ) + { + Abc_ObjForEachFanin( pObj, pTerm, k ) + { + pNet = Abc_ObjFanin0(pTerm); + if ( pNet->pCopy ) + continue; + pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNameSuffix(pNet, Suffix) ); + } + Abc_ObjForEachFanout( pObj, pTerm, k ) + { + pNet = Abc_ObjFanout0(pTerm); + if ( pNet->pCopy ) + continue; + pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNameSuffix(pNet, Suffix) ); + } + } + + // mark objects that will not be used + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachPi( pNtk, pTerm, i ) + Abc_NodeSetTravIdCurrent( pTerm ); + Abc_NtkForEachPo( pNtk, pTerm, i ) + { + Abc_NodeSetTravIdCurrent( pTerm ); + // if the netlist has net names beginning with "abc_property_" + // these names will be addes as primary outputs of the network + pNet = Abc_ObjFanin0(pTerm); + if ( strncmp( Abc_ObjName(pNet), "abc_property", 12 ) ) + continue; + Abc_ObjAddFanin( Abc_NtkCreatePo(pNet->pCopy->pNtk), pNet->pCopy ); + if ( Nm_ManFindNameById(pNet->pCopy->pNtk->pManName, pNet->pCopy->Id) ) + Nm_ManDeleteIdName(pNet->pCopy->pNtk->pManName, pNet->pCopy->Id); + Abc_ObjAssignName( pNet->pCopy, Abc_ObjName(pNet), Suffix ); + } + Abc_NtkForEachBox( pNtk, pObj, i ) + { + if ( Abc_ObjIsLatch(pObj) ) + continue; + Abc_NodeSetTravIdCurrent( pObj ); + Abc_ObjForEachFanin( pObj, pTerm, k ) + Abc_NodeSetTravIdCurrent( pTerm ); + Abc_ObjForEachFanout( pObj, pTerm, k ) + Abc_NodeSetTravIdCurrent( pTerm ); + } + + // duplicate objects that do not have prototypes yet + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( Abc_NodeIsTravIdCurrent(pObj) ) + continue; + if ( pObj->pCopy ) + continue; + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + } + + // connect objects + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + if ( !Abc_NodeIsTravIdCurrent(pFanin) ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + + // call recursively + Abc_NtkForEachBox( pNtk, pObj, i ) + { + if ( Abc_ObjIsLatch(pObj) ) + continue; + pNtkModel = (Abc_Ntk_t *)pObj->pData; + // check the match between the number of actual and formal parameters + assert( Abc_ObjFaninNum(pObj) == Abc_NtkPiNum(pNtkModel) ); + assert( Abc_ObjFanoutNum(pObj) == Abc_NtkPoNum(pNtkModel) ); + // clean the node copy fields + Abc_NtkCleanCopy( pNtkModel ); + // map PIs/POs + Abc_ObjForEachFanin( pObj, pTerm, k ) + Abc_ObjFanout0( Abc_NtkPi(pNtkModel, k) )->pCopy = Abc_ObjFanin0(pTerm)->pCopy; + Abc_ObjForEachFanout( pObj, pTerm, k ) + Abc_ObjFanin0( Abc_NtkPo(pNtkModel, k) )->pCopy = Abc_ObjFanout0(pTerm)->pCopy; + // call recursively + Abc_NtkFlattenLogicHierarchy2_rec( pNtkNew, pNtkModel, pCounter ); + } + + // if it is a BLIF-MV netlist transfer the values of all nets + if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) ) + { + if ( Abc_NtkMvVar( pNtkNew ) == NULL ) + Abc_NtkStartMvVars( pNtkNew ); + Abc_NtkForEachNet( pNtk, pObj, i ) + Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) ); + } +} + +/**Function************************************************************* + + Synopsis [Flattens the logic hierarchy of the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFlattenLogicHierarchy2( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pTerm, * pNet; + int i, Counter; + extern Abc_Des_t * Abc_DesDupBlackboxes( Abc_Des_t * p, Abc_Ntk_t * pNtkSave ); + + assert( Abc_NtkIsNetlist(pNtk) ); + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + // duplicate the name and the spec + pNtkNew->pName = Abc_UtilStrsav(pNtk->pName); + pNtkNew->pSpec = Abc_UtilStrsav(pNtk->pSpec); + + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + + // duplicate PIs/POs and their nets + Abc_NtkForEachPi( pNtk, pTerm, i ) + { + Abc_NtkDupObj( pNtkNew, pTerm, 0 ); + pNet = Abc_ObjFanout0( pTerm ); + pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) ); + Abc_ObjAddFanin( pNet->pCopy, pTerm->pCopy ); + } + Abc_NtkForEachPo( pNtk, pTerm, i ) + { + Abc_NtkDupObj( pNtkNew, pTerm, 0 ); + pNet = Abc_ObjFanin0( pTerm ); + pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) ); + Abc_ObjAddFanin( pTerm->pCopy, pNet->pCopy ); + } + + // recursively flatten hierarchy, create internal logic, add new PI/PO names if there are black boxes + Counter = -1; + Abc_NtkFlattenLogicHierarchy2_rec( pNtkNew, pNtk, &Counter ); + printf( "Hierarchy reader flattened %d instances of logic boxes and left %d black boxes.\n", + Counter, Abc_NtkBlackboxNum(pNtkNew) ); + + if ( pNtk->pDesign ) + { + // pass on the design + assert( Vec_PtrEntry(pNtk->pDesign->vTops, 0) == pNtk ); + pNtkNew->pDesign = Abc_DesDupBlackboxes( pNtk->pDesign, pNtkNew ); + // update the pointers + Abc_NtkForEachBlackbox( pNtkNew, pTerm, i ) + pTerm->pData = ((Abc_Ntk_t *)pTerm->pData)->pCopy; + } + + // we may have added property outputs + Abc_NtkOrderCisCos( pNtkNew ); + + // copy the timing information +// Abc_ManTimeDup( pNtk, pNtkNew ); + // duplicate EXDC + if ( pNtk->pExdc ) + printf( "EXDC is not transformed.\n" ); + if ( !Abc_NtkCheck( pNtkNew ) ) + { + fprintf( stdout, "Abc_NtkFlattenLogicHierarchy2(): Network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + + + +/**Function************************************************************* + + Synopsis [Recursively flattens logic hierarchy of the netlist.] + + Description [When this procedure is called, the PI/PO nets of the old + netlist point to the corresponding nets of the flattened netlist.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFlattenLogicHierarchy_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, int * pCounter, Vec_Str_t * vPref ) +{ + Abc_Ntk_t * pNtkModel; + Abc_Obj_t * pObj, * pTerm, * pNet, * pFanin; + int i, k, Length; + + // process the blackbox + if ( Abc_NtkHasBlackbox(pNtk) ) + { + //printf( "Flatting black box \"%s\".\n", pNtk->pName ); + // duplicate the blackbox + assert( Abc_NtkBoxNum(pNtk) == 1 ); + pObj = Abc_NtkBox( pNtk, 0 ); + Abc_NtkDupBox( pNtkNew, pObj, 1 ); + pObj->pCopy->pData = pNtk; + + // connect blackbox fanins to the PI nets + assert( Abc_ObjFaninNum(pObj->pCopy) == Abc_NtkPiNum(pNtk) ); + Abc_NtkForEachPi( pNtk, pTerm, i ) + Abc_ObjAddFanin( Abc_ObjFanin(pObj->pCopy,i), Abc_ObjFanout0(pTerm)->pCopy ); + + // connect blackbox fanouts to the PO nets + assert( Abc_ObjFanoutNum(pObj->pCopy) == Abc_NtkPoNum(pNtk) ); + Abc_NtkForEachPo( pNtk, pTerm, i ) + Abc_ObjAddFanin( Abc_ObjFanin0(pTerm)->pCopy, Abc_ObjFanout(pObj->pCopy,i) ); + return; + } + + (*pCounter)++; + + // create the suffix, which will be appended to the internal names + if ( *pCounter ) + { + char Buffer[20]; + sprintf( Buffer, "(%d)", *pCounter ); + Vec_StrPrintStr( vPref, Buffer ); + } + Vec_StrPush( vPref, '|' ); + Vec_StrPush( vPref, 0 ); + + // duplicate nets of all boxes, including latches + Abc_NtkForEachBox( pNtk, pObj, i ) + { + Abc_ObjForEachFanin( pObj, pTerm, k ) + { + pNet = Abc_ObjFanin0(pTerm); + if ( pNet->pCopy ) + continue; + pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNamePrefix(pNet, Vec_StrArray(vPref)) ); + } + Abc_ObjForEachFanout( pObj, pTerm, k ) + { + pNet = Abc_ObjFanout0(pTerm); + if ( pNet->pCopy ) + continue; + pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNamePrefix(pNet, Vec_StrArray(vPref)) ); + } + } + + // mark objects that will not be used + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachPi( pNtk, pTerm, i ) + Abc_NodeSetTravIdCurrent( pTerm ); + Abc_NtkForEachPo( pNtk, pTerm, i ) + { + Abc_NodeSetTravIdCurrent( pTerm ); + // if the netlist has net names beginning with "abc_property_" + // these names will be addes as primary outputs of the network + pNet = Abc_ObjFanin0(pTerm); + if ( strncmp( Abc_ObjName(pNet), "abc_property", 12 ) ) + continue; + Abc_ObjAddFanin( Abc_NtkCreatePo(pNet->pCopy->pNtk), pNet->pCopy ); + if ( Nm_ManFindNameById(pNet->pCopy->pNtk->pManName, pNet->pCopy->Id) ) + Nm_ManDeleteIdName(pNet->pCopy->pNtk->pManName, pNet->pCopy->Id); + Abc_ObjAssignName( pNet->pCopy, Vec_StrArray(vPref), Abc_ObjName(pNet) ); + } + Abc_NtkForEachBox( pNtk, pObj, i ) + { + if ( Abc_ObjIsLatch(pObj) ) + continue; + Abc_NodeSetTravIdCurrent( pObj ); + Abc_ObjForEachFanin( pObj, pTerm, k ) + Abc_NodeSetTravIdCurrent( pTerm ); + Abc_ObjForEachFanout( pObj, pTerm, k ) + Abc_NodeSetTravIdCurrent( pTerm ); + } + + // duplicate objects that do not have prototypes yet + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( Abc_NodeIsTravIdCurrent(pObj) ) + continue; + if ( pObj->pCopy ) + continue; + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + } + + // connect objects + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + if ( !Abc_NodeIsTravIdCurrent(pFanin) ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + + // call recursively + Vec_StrPop( vPref ); + Length = Vec_StrSize( vPref ); + Abc_NtkForEachBox( pNtk, pObj, i ) + { + if ( Abc_ObjIsLatch(pObj) ) + continue; + pNtkModel = (Abc_Ntk_t *)pObj->pData; + // check the match between the number of actual and formal parameters + assert( Abc_ObjFaninNum(pObj) == Abc_NtkPiNum(pNtkModel) ); + assert( Abc_ObjFanoutNum(pObj) == Abc_NtkPoNum(pNtkModel) ); + // clean the node copy fields + Abc_NtkCleanCopy( pNtkModel ); + // map PIs/POs + Abc_ObjForEachFanin( pObj, pTerm, k ) + Abc_ObjFanout0( Abc_NtkPi(pNtkModel, k) )->pCopy = Abc_ObjFanin0(pTerm)->pCopy; + Abc_ObjForEachFanout( pObj, pTerm, k ) + Abc_ObjFanin0( Abc_NtkPo(pNtkModel, k) )->pCopy = Abc_ObjFanout0(pTerm)->pCopy; + // create name + Vec_StrShrink( vPref, Length ); + Vec_StrPrintStr( vPref, Abc_NtkName(pNtkModel) ); + // call recursively + Abc_NtkFlattenLogicHierarchy_rec( pNtkNew, pNtkModel, pCounter, vPref ); + } + + // if it is a BLIF-MV netlist transfer the values of all nets + if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) ) + { + if ( Abc_NtkMvVar( pNtkNew ) == NULL ) + Abc_NtkStartMvVars( pNtkNew ); + Abc_NtkForEachNet( pNtk, pObj, i ) + Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) ); + } +} + +/**Function************************************************************* + + Synopsis [Returns 0 if CI names are repeated.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCompareNames( Abc_Ntk_t ** p1, Abc_Ntk_t ** p2 ) +{ + return strcmp( Abc_NtkName(*p1), Abc_NtkName(*p2) ); +} + +/**Function************************************************************* + + Synopsis [Prints information about boxes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintBoxInfo( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vMods; + Abc_Ntk_t * pModel, * pBoxModel; + Abc_Obj_t * pObj; + Vec_Int_t * vCounts; + int i, k, Num; + if ( pNtk->pDesign == NULL || pNtk->pDesign->vModules == NULL ) + { +// printf( "There is no hierarchy information.\n" ); + return; + } + // sort models by name + vMods = pNtk->pDesign->vModules; + Vec_PtrSort( vMods, (int(*)(const void *, const void *))Abc_NtkCompareNames ); +// Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i ) +// printf( "%s\n", Abc_NtkName(pModel) ); + + // swap the first model + Num = Vec_PtrFind( vMods, pNtk ); + assert( Num >= 0 && Num < Vec_PtrSize(vMods) ); + pBoxModel = (Abc_Ntk_t *)Vec_PtrEntry(vMods, 0); + Vec_PtrWriteEntry(vMods, 0, (Abc_Ntk_t *)Vec_PtrEntry(vMods, Num) ); + Vec_PtrWriteEntry(vMods, Num, pBoxModel ); + + // print models + vCounts = Vec_IntStart( Vec_PtrSize(vMods) ); + Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i ) + { + if ( Abc_NtkBoxNum(pModel) == 0 ) + continue; + Vec_IntFill( vCounts, Vec_IntSize(vCounts), 0 ); + Abc_NtkForEachBox( pModel, pObj, k ) + { + pBoxModel = (Abc_Ntk_t *)pObj->pData; + if ( pBoxModel == NULL ) + continue; + Num = Vec_PtrFind( vMods, pBoxModel ); + assert( Num >= 0 && Num < Vec_PtrSize(vMods) ); + Vec_IntAddToEntry( vCounts, Num, 1 ); + } + +// Abc_NtkPrintStats( pModel, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + printf( "MODULE " ); + printf( "%-30s : ", Abc_NtkName(pModel) ); + printf( "PI=%6d ", Abc_NtkPiNum(pModel) ); + printf( "PO=%6d ", Abc_NtkPoNum(pModel) ); + printf( "BB=%6d ", Abc_NtkBoxNum(pModel) ); + printf( "ND=%6d ", Abc_NtkNodeNum(pModel) ); // sans constants + printf( "Lev=%5d ", Abc_NtkLevel(pModel) ); + printf( "\n" ); + + Vec_IntForEachEntry( vCounts, Num, k ) + if ( Num ) + printf( "%15d : %s\n", Num, Abc_NtkName((Abc_Ntk_t *)Vec_PtrEntry(vMods, k)) ); + } + Vec_IntFree( vCounts ); + Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i ) + { + if ( Abc_NtkBoxNum(pModel) != 0 ) + continue; + printf( "MODULE " ); + printf( "%-30s : ", Abc_NtkName(pModel) ); + printf( "PI=%6d ", Abc_NtkPiNum(pModel) ); + printf( "PO=%6d ", Abc_NtkPoNum(pModel) ); + printf( "BB=%6d ", Abc_NtkBoxNum(pModel) ); + printf( "ND=%6d ", Abc_NtkNodeNum(pModel) ); + printf( "Lev=%5d ", Abc_NtkLevel(pModel) ); + printf( "\n" ); + } +} + +/**Function************************************************************* + + Synopsis [Flattens the logic hierarchy of the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFlattenLogicHierarchy( Abc_Ntk_t * pNtk ) +{ + extern Abc_Des_t * Abc_DesDupBlackboxes( Abc_Des_t * p, Abc_Ntk_t * pNtkSave ); + Vec_Str_t * vPref; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pTerm, * pNet; + int i, Counter = -1; + + assert( Abc_NtkIsNetlist(pNtk) ); +// Abc_NtkPrintBoxInfo( pNtk ); + + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); + + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + + // duplicate PIs/POs and their nets + Abc_NtkForEachPi( pNtk, pTerm, i ) + { + Abc_NtkDupObj( pNtkNew, pTerm, 0 ); + pNet = Abc_ObjFanout0( pTerm ); + pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) ); + Abc_ObjAddFanin( pNet->pCopy, pTerm->pCopy ); + } + Abc_NtkForEachPo( pNtk, pTerm, i ) + { + Abc_NtkDupObj( pNtkNew, pTerm, 0 ); + pNet = Abc_ObjFanin0( pTerm ); + pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) ); + Abc_ObjAddFanin( pTerm->pCopy, pNet->pCopy ); + } + + // recursively flatten hierarchy, create internal logic, add new PI/PO names if there are black boxes + vPref = Vec_StrAlloc( 1000 ); + Vec_StrPrintStr( vPref, Abc_NtkName(pNtk) ); + Abc_NtkFlattenLogicHierarchy_rec( pNtkNew, pNtk, &Counter, vPref ); + printf( "Hierarchy reader flattened %d instances of logic boxes and left %d black boxes.\n", + Counter, Abc_NtkBlackboxNum(pNtkNew) ); + Vec_StrFree( vPref ); + + if ( pNtk->pDesign ) + { + // pass on the design + assert( Vec_PtrEntry(pNtk->pDesign->vTops, 0) == pNtk ); + pNtkNew->pDesign = Abc_DesDupBlackboxes( pNtk->pDesign, pNtkNew ); + // update the pointers + Abc_NtkForEachBlackbox( pNtkNew, pTerm, i ) + pTerm->pData = ((Abc_Ntk_t *)pTerm->pData)->pCopy; + } + + // we may have added property outputs + Abc_NtkOrderCisCos( pNtkNew ); + + // copy the timing information +// Abc_ManTimeDup( pNtk, pNtkNew ); + // duplicate EXDC + if ( pNtk->pExdc ) + printf( "EXDC is not transformed.\n" ); + if ( !Abc_NtkCheck( pNtkNew ) ) + { + fprintf( stdout, "Abc_NtkFlattenLogicHierarchy(): Network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + + +/**Function************************************************************* + + Synopsis [Extracts blackboxes by making them into additional PIs/POs.] + + Description [The input netlist has not logic hierarchy. The resulting + netlist has additional PIs/POs for each blackbox input/output.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkConvertBlackboxes( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pNet, * pFanin, * pTerm; + int i, k; + + assert( Abc_NtkIsNetlist(pNtk) ); + assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav( pNtk->pName ); + pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec ); + + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + + // mark the nodes that should not be connected + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachBlackbox( pNtk, pObj, i ) + Abc_NodeSetTravIdCurrent( pObj ); + Abc_NtkForEachCi( pNtk, pTerm, i ) + Abc_NodeSetTravIdCurrent( pTerm ); + Abc_NtkForEachCo( pNtk, pTerm, i ) + Abc_NodeSetTravIdCurrent( pTerm ); + // unmark PIs and LIs/LOs + Abc_NtkForEachPi( pNtk, pTerm, i ) + Abc_NodeSetTravIdPrevious( pTerm ); + Abc_NtkForEachLatchInput( pNtk, pTerm, i ) + Abc_NodeSetTravIdPrevious( pTerm ); + Abc_NtkForEachLatchOutput( pNtk, pTerm, i ) + Abc_NodeSetTravIdPrevious( pTerm ); + // copy the box outputs + Abc_NtkForEachBlackbox( pNtk, pObj, i ) + Abc_ObjForEachFanout( pObj, pTerm, k ) + pTerm->pCopy = Abc_NtkCreatePi( pNtkNew ); + + // duplicate other objects + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + Abc_NtkDupObj( pNtkNew, pObj, Abc_ObjIsNet(pObj) ); + + // connect all objects + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + + // create unique PO for each net feeding into blackboxes or POs + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachCo( pNtk, pTerm, i ) + { + // skip latch inputs + assert( Abc_ObjFanoutNum(pTerm) <= 1 ); + if ( Abc_ObjFanoutNum(pTerm) > 0 && Abc_ObjIsLatch(Abc_ObjFanout0(pTerm)) ) + continue; + // check if the net is visited + pNet = Abc_ObjFanin0(pTerm); + if ( Abc_NodeIsTravIdCurrent(pNet) ) + continue; + // create PO + Abc_NodeSetTravIdCurrent( pNet ); + Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pNet->pCopy ); + } + + // check integrity + if ( !Abc_NtkCheck( pNtkNew ) ) + { + fprintf( stdout, "Abc_NtkConvertBlackboxes(): Network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Inserts blackboxes into the netlist.] + + Description [The first arg is the netlist with blackboxes without logic hierarchy. + The second arg is a non-hierarchical netlist derived from the above netlist after processing. + This procedure create a new netlist, which is comparable to the original netlist with + blackboxes, except that it contains logic nodes from the netlist after processing.] + + SideEffects [This procedure silently assumes that blackboxes appear + only in the top-level model. If they appear in other models as well, + the name of the model and its number were appended to the names of + blackbox inputs/outputs.] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkInsertNewLogic( Abc_Ntk_t * pNtkH, Abc_Ntk_t * pNtkL ) +{ + Abc_Des_t * pDesign; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObjH, * pObjL, * pNetH, * pNetL, * pTermH; + int i, k; + + assert( Abc_NtkIsNetlist(pNtkH) ); + assert( Abc_NtkWhiteboxNum(pNtkH) == 0 ); + assert( Abc_NtkBlackboxNum(pNtkH) > 0 ); + + assert( Abc_NtkIsNetlist(pNtkL) ); + assert( Abc_NtkWhiteboxNum(pNtkL) == 0 ); + assert( Abc_NtkBlackboxNum(pNtkL) == 0 ); + + // prepare the logic network for copying + Abc_NtkCleanCopy( pNtkL ); + + // start the network + pNtkNew = Abc_NtkAlloc( pNtkL->ntkType, pNtkL->ntkFunc, 1 ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav( pNtkH->pName ); + pNtkNew->pSpec = Extra_UtilStrsav( pNtkH->pSpec ); + + // make sure every PI/PO has a PI/PO in the processed network + Abc_NtkForEachPi( pNtkH, pObjH, i ) + { + pNetH = Abc_ObjFanout0(pObjH); + pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) ); + if ( pNetL == NULL || !Abc_ObjIsPi( Abc_ObjFanin0(pNetL) ) ) + { + printf( "Error in Abc_NtkInsertNewLogic(): There is no PI corresponding to the PI %s.\n", Abc_ObjName(pNetH) ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + if ( pNetL->pCopy ) + { + printf( "Error in Abc_NtkInsertNewLogic(): Primary input %s is repeated twice.\n", Abc_ObjName(pNetH) ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + // create the new net + pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) ); + Abc_NtkDupObj( pNtkNew, Abc_ObjFanin0(pNetL), 0 ); + } + + // make sure every BB has a PI/PO in the processed network + Abc_NtkForEachBlackbox( pNtkH, pObjH, i ) + { + // duplicate the box + Abc_NtkDupBox( pNtkNew, pObjH, 0 ); + pObjH->pCopy->pData = pObjH->pData; + // create PIs + Abc_ObjForEachFanout( pObjH, pTermH, k ) + { + pNetH = Abc_ObjFanout0( pTermH ); + pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) ); + if ( pNetL == NULL || !Abc_ObjIsPi( Abc_ObjFanin0(pNetL) ) ) + { + printf( "Error in Abc_NtkInsertNewLogic(): There is no PI corresponding to the inpout %s of blackbox %s.\n", Abc_ObjName(pNetH), Abc_ObjName(pObjH) ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + if ( pNetL->pCopy ) + { + printf( "Error in Abc_NtkInsertNewLogic(): Box output %s is repeated twice.\n", Abc_ObjName(pNetH) ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + // create net and map the PI + pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) ); + Abc_ObjFanin0(pNetL)->pCopy = pTermH->pCopy; + } + } + + Abc_NtkForEachPo( pNtkH, pObjH, i ) + { + pNetH = Abc_ObjFanin0(pObjH); + pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) ); + if ( pNetL == NULL || !Abc_ObjIsPo( Abc_ObjFanout0(pNetL) ) ) + { + printf( "Error in Abc_NtkInsertNewLogic(): There is no PO corresponding to the PO %s.\n", Abc_ObjName(pNetH) ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + if ( pNetL->pCopy ) + continue; + // create the new net + pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) ); + Abc_NtkDupObj( pNtkNew, Abc_ObjFanout0(pNetL), 0 ); + } + Abc_NtkForEachBlackbox( pNtkH, pObjH, i ) + { + Abc_ObjForEachFanin( pObjH, pTermH, k ) + { + char * pName; + pNetH = Abc_ObjFanin0( pTermH ); + pName = Abc_ObjName(pNetH); + pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) ); + if ( pNetL == NULL || !Abc_ObjIsPo( Abc_ObjFanout0(pNetL) ) ) + { + printf( "There is no PO corresponding to the input %s of blackbox %s.\n", Abc_ObjName(pNetH), Abc_ObjName(pObjH) ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + // create net and map the PO + if ( pNetL->pCopy ) + { + if ( Abc_ObjFanout0(pNetL)->pCopy == NULL ) + Abc_ObjFanout0(pNetL)->pCopy = pTermH->pCopy; + else + Abc_ObjAddFanin( pTermH->pCopy, pNetL->pCopy ); + continue; + } + pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) ); + Abc_ObjFanout0(pNetL)->pCopy = pTermH->pCopy; + } + } + + // duplicate other objects of the logic network + Abc_NtkForEachObj( pNtkL, pObjL, i ) + if ( pObjL->pCopy == NULL && !Abc_ObjIsPo(pObjL) ) // skip POs feeding into PIs + Abc_NtkDupObj( pNtkNew, pObjL, Abc_ObjIsNet(pObjL) ); + + // connect objects + Abc_NtkForEachObj( pNtkL, pObjL, i ) + Abc_ObjForEachFanin( pObjL, pNetL, k ) + if ( pObjL->pCopy ) + Abc_ObjAddFanin( pObjL->pCopy, pNetL->pCopy ); + + // transfer the design + pDesign = pNtkH->pDesign; pNtkH->pDesign = NULL; + assert( Vec_PtrEntry( pDesign->vModules, 0 ) == pNtkH ); + Vec_PtrWriteEntry( pDesign->vModules, 0, pNtkNew ); + pNtkNew->pDesign = pDesign; + + // check integrity + if ( !Abc_NtkCheck( pNtkNew ) ) + { + fprintf( stdout, "Abc_NtkInsertNewLogic(): Network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/abcHieCec.c b/yosys/abc/src/base/abc/abcHieCec.c new file mode 100644 index 00000000000..d9f413e8030 --- /dev/null +++ b/yosys/abc/src/base/abc/abcHieCec.c @@ -0,0 +1,764 @@ +/**CFile**************************************************************** + + FileName [abcHieCec.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Hierarchical CEC manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcHieCec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "base/io/ioAbc.h" +#include "aig/gia/gia.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define Abc_ObjForEachFaninReal( pObj, pFanin, i ) \ + for ( i = 0; (i < Abc_ObjFaninNum(pObj)) && (((pFanin) = Abc_ObjFaninReal(pObj, i)), 1); i++ ) + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the real faniin of the object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline Abc_Obj_t * Abc_ObjFaninReal( Abc_Obj_t * pObj, int i ) +{ + Abc_Obj_t * pRes; + if ( Abc_ObjIsBox(pObj) ) + pRes = Abc_ObjFanin0( Abc_ObjFanin0( Abc_ObjFanin(pObj, i) ) ); + else + { + assert( Abc_ObjIsPo(pObj) || Abc_ObjIsNode(pObj) ); + pRes = Abc_ObjFanin0( Abc_ObjFanin(pObj, i) ); + } + if ( Abc_ObjIsBo(pRes) ) + return Abc_ObjFanin0(pRes); + return pRes; +} + +/**Function************************************************************* + + Synopsis [Performs DFS for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDfsBoxes_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanin; + int i; + if ( Abc_ObjIsPi(pNode) ) + return; + assert( Abc_ObjIsNode(pNode) || Abc_ObjIsBox(pNode) ); + // if this node is already visited, skip + if ( Abc_NodeIsTravIdCurrent( pNode ) ) + return; + Abc_NodeSetTravIdCurrent( pNode ); + // visit the transitive fanin of the node + Abc_ObjForEachFaninReal( pNode, pFanin, i ) + Abc_NtkDfsBoxes_rec( pFanin, vNodes ); + // add the node after the fanins have been added + Vec_PtrPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Returns the array of node and boxes reachable from POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkDfsBoxes( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkIsNetlist(pNtk) ); + // set the traversal ID + Abc_NtkIncrementTravId( pNtk ); + // start the array of nodes + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkDfsBoxes_rec( Abc_ObjFaninReal(pObj, 0), vNodes ); + return vNodes; +} + + +/**Function************************************************************* + + Synopsis [Strashes one logic node using its SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkDeriveFlatGiaSop( Gia_Man_t * pGia, int * gFanins, char * pSop ) +{ + char * pCube; + int gAnd, gSum; + int i, Value, nFanins; + // get the number of variables + nFanins = Abc_SopGetVarNum(pSop); + if ( Abc_SopIsExorType(pSop) ) + { + gSum = 0; + for ( i = 0; i < nFanins; i++ ) + gSum = Gia_ManHashXor( pGia, gSum, gFanins[i] ); + } + else + { + // go through the cubes of the node's SOP + gSum = 0; + Abc_SopForEachCube( pSop, nFanins, pCube ) + { + // create the AND of literals + gAnd = 1; + Abc_CubeForEachVar( pCube, Value, i ) + { + if ( Value == '1' ) + gAnd = Gia_ManHashAnd( pGia, gAnd, gFanins[i] ); + else if ( Value == '0' ) + gAnd = Gia_ManHashAnd( pGia, gAnd, Abc_LitNot(gFanins[i]) ); + } + // add to the sum of cubes + gSum = Gia_ManHashAnd( pGia, Abc_LitNot(gSum), Abc_LitNot(gAnd) ); + gSum = Abc_LitNot( gSum ); + } + } + // decide whether to complement the result + if ( Abc_SopIsComplement(pSop) ) + gSum = Abc_LitNot(gSum); + return gSum; +} + +/**Function************************************************************* + + Synopsis [Flattens the logic hierarchy of the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDeriveFlatGia_rec( Gia_Man_t * pGia, Abc_Ntk_t * pNtk ) +{ + int gFanins[16]; + Vec_Ptr_t * vOrder = (Vec_Ptr_t *)pNtk->pData; + Abc_Obj_t * pObj, * pTerm; + Abc_Ntk_t * pNtkModel; + int i, k; + Abc_NtkForEachPi( pNtk, pTerm, i ) + assert( Abc_ObjFanout0(pTerm)->iTemp >= 0 ); + Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i ) + { + if ( Abc_ObjIsNode(pObj) ) + { + char * pSop = (char *)pObj->pData; +/* + int nLength = strlen(pSop); + if ( nLength == 4 ) // buf/inv + { + assert( pSop[2] == '1' ); + assert( pSop[0] == '0' || pSop[0] == '1' ); + assert( Abc_ObjFanin0(pObj)->iTemp >= 0 ); + Abc_ObjFanout0(pObj)->iTemp = Abc_LitNotCond( Abc_ObjFanin0(pObj)->iTemp, pSop[0]=='0' ); + continue; + } + if ( nLength == 5 ) // and2 + { + assert( pSop[3] == '1' ); + assert( pSop[0] == '0' || pSop[0] == '1' ); + assert( pSop[1] == '0' || pSop[1] == '1' ); + assert( Abc_ObjFanin0(pObj)->iTemp >= 0 ); + assert( Abc_ObjFanin1(pObj)->iTemp >= 0 ); + Abc_ObjFanout0(pObj)->iTemp = Gia_ManHashAnd( pGia, + Abc_LitNotCond( Abc_ObjFanin0(pObj)->iTemp, pSop[0]=='0' ), + Abc_LitNotCond( Abc_ObjFanin1(pObj)->iTemp, pSop[1]=='0' ) + ); + continue; + } +*/ + assert( Abc_ObjFaninNum(pObj) <= 16 ); + assert( Abc_ObjFaninNum(pObj) == Abc_SopGetVarNum(pSop) ); + Abc_ObjForEachFanin( pObj, pTerm, k ) + { + gFanins[k] = pTerm->iTemp; + assert( gFanins[k] >= 0 ); + } + Abc_ObjFanout0(pObj)->iTemp = Abc_NtkDeriveFlatGiaSop( pGia, gFanins, pSop ); + continue; + } + assert( Abc_ObjIsBox(pObj) ); + pNtkModel = (Abc_Ntk_t *)pObj->pData; + Abc_NtkFillTemp( pNtkModel ); + // check the match between the number of actual and formal parameters + assert( Abc_ObjFaninNum(pObj) == Abc_NtkPiNum(pNtkModel) ); + assert( Abc_ObjFanoutNum(pObj) == Abc_NtkPoNum(pNtkModel) ); + // assign PIs + Abc_ObjForEachFanin( pObj, pTerm, k ) + Abc_ObjFanout0( Abc_NtkPi(pNtkModel, k) )->iTemp = Abc_ObjFanin0(pTerm)->iTemp; + // call recursively + Abc_NtkDeriveFlatGia_rec( pGia, pNtkModel ); + // assign POs + Abc_ObjForEachFanout( pObj, pTerm, k ) + Abc_ObjFanout0(pTerm)->iTemp = Abc_ObjFanin0( Abc_NtkPo(pNtkModel, k) )->iTemp; + } + Abc_NtkForEachPo( pNtk, pTerm, i ) + assert( Abc_ObjFanin0(pTerm)->iTemp >= 0 ); +} + +/**Function************************************************************* + + Synopsis [Flattens the logic hierarchy of the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Abc_NtkDeriveFlatGia( Abc_Ntk_t * pNtk ) +{ + Gia_Man_t * pTemp, * pGia = NULL; + Abc_Obj_t * pTerm; + int i; + + assert( Abc_NtkIsNetlist(pNtk) ); + assert( !Abc_NtkLatchNum(pNtk) ); + Abc_NtkFillTemp( pNtk ); + // start the network + pGia = Gia_ManStart( (1<<16) ); + pGia->pName = Abc_UtilStrsav( Abc_NtkName(pNtk) ); + pGia->pSpec = Abc_UtilStrsav( Abc_NtkSpec(pNtk) ); + Gia_ManHashAlloc( pGia ); + // create PIs + Abc_NtkForEachPi( pNtk, pTerm, i ) + Abc_ObjFanout0(pTerm)->iTemp = Gia_ManAppendCi( pGia ); + // recursively flatten hierarchy + Abc_NtkDeriveFlatGia_rec( pGia, pNtk ); + // create POs + Abc_NtkForEachPo( pNtk, pTerm, i ) + Gia_ManAppendCo( pGia, Abc_ObjFanin0(pTerm)->iTemp ); + // prepare return value + Gia_ManHashStop( pGia ); + Gia_ManSetRegNum( pGia, 0 ); + pGia = Gia_ManCleanup( pTemp = pGia ); + Gia_ManStop( pTemp ); + return pGia; +} + +/**Function************************************************************* + + Synopsis [Counts the total number of AIG nodes before flattening.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCountAndNodes( Vec_Ptr_t * vOrder ) +{ + Gia_Man_t * pGiaBox; + Abc_Ntk_t * pNtkModel; + Abc_Obj_t * pObj; + int i, Counter = 0; + Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i ) + { + if ( Abc_ObjIsNode(pObj) ) + { + Counter++; + continue; + } + assert( Abc_ObjIsBox(pObj) ); + pNtkModel = (Abc_Ntk_t *)pObj->pData; + pGiaBox = (Gia_Man_t *)pNtkModel->pData; + Counter += Gia_ManAndNum(pGiaBox); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Flattens the logic hierarchy of the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Abc_NtkDeriveFlatGia2Derive( Abc_Ntk_t * pNtk, Vec_Ptr_t * vOrder ) +{ + int gFanins[16]; + Abc_Ntk_t * pNtkModel; + Gia_Man_t * pGiaBox, * pGia = NULL; + Gia_Obj_t * pGiaObj; + Abc_Obj_t * pTerm, * pObj; + int i, k; + + assert( Abc_NtkIsNetlist(pNtk) ); + assert( !Abc_NtkLatchNum(pNtk) ); + Abc_NtkFillTemp( pNtk ); + + // start the network + pGia = Gia_ManStart( (1<<15) ); + pGia->pName = Abc_UtilStrsav( Abc_NtkName(pNtk) ); + pGia->pSpec = Abc_UtilStrsav( Abc_NtkSpec(pNtk) ); + Gia_ManHashAlloc( pGia ); + // create PIs + Abc_NtkForEachPi( pNtk, pTerm, i ) + Abc_ObjFanout0(pTerm)->iTemp = Gia_ManAppendCi( pGia ); + // recursively flatten hierarchy + Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i ) + { + if ( Abc_ObjIsNode(pObj) ) + { + char * pSop = (char *)pObj->pData; + assert( Abc_ObjFaninNum(pObj) <= 16 ); + assert( Abc_ObjFaninNum(pObj) == Abc_SopGetVarNum(pSop) ); + Abc_ObjForEachFanin( pObj, pTerm, k ) + { + gFanins[k] = pTerm->iTemp; + assert( gFanins[k] >= 0 ); + } + Abc_ObjFanout0(pObj)->iTemp = Abc_NtkDeriveFlatGiaSop( pGia, gFanins, pSop ); + continue; + } + assert( Abc_ObjIsBox(pObj) ); + pNtkModel = (Abc_Ntk_t *)pObj->pData; + // check the match between the number of actual and formal parameters + assert( Abc_ObjFaninNum(pObj) == Abc_NtkPiNum(pNtkModel) ); + assert( Abc_ObjFanoutNum(pObj) == Abc_NtkPoNum(pNtkModel) ); +/* + // assign PIs + Abc_ObjForEachFanin( pObj, pTerm, k ) + Abc_ObjFanout0( Abc_NtkPi(pNtkModel, k) )->iTemp = Abc_ObjFanin0(pTerm)->iTemp; + // call recursively + Abc_NtkDeriveFlatGia_rec( pGia, pNtkModel ); + // assign POs + Abc_ObjForEachFanout( pObj, pTerm, k ) + Abc_ObjFanout0(pTerm)->iTemp = Abc_ObjFanin0( Abc_NtkPo(pNtkModel, k) )->iTemp; +*/ + // duplicate the AIG + pGiaBox = (Gia_Man_t *)pNtkModel->pData; + assert( Abc_ObjFaninNum(pObj) == Gia_ManPiNum(pGiaBox) ); + assert( Abc_ObjFanoutNum(pObj) == Gia_ManPoNum(pGiaBox) ); + Gia_ManFillValue( pGiaBox ); + Gia_ManConst0(pGiaBox)->Value = 0; + Abc_ObjForEachFanin( pObj, pTerm, k ) + Gia_ManPi(pGiaBox, k)->Value = Abc_ObjFanin0(pTerm)->iTemp; + Gia_ManForEachAnd( pGiaBox, pGiaObj, k ) + pGiaObj->Value = Gia_ManHashAnd( pGia, Gia_ObjFanin0Copy(pGiaObj), Gia_ObjFanin1Copy(pGiaObj) ); + Abc_ObjForEachFanout( pObj, pTerm, k ) + Abc_ObjFanout0(pTerm)->iTemp = Gia_ObjFanin0Copy(Gia_ManPo(pGiaBox, k)); + } + // create POs + Abc_NtkForEachPo( pNtk, pTerm, i ) + Gia_ManAppendCo( pGia, Abc_ObjFanin0(pTerm)->iTemp ); + // prepare return value + Gia_ManHashStop( pGia ); + Gia_ManSetRegNum( pGia, 0 ); + pGia = Gia_ManCleanup( pGiaBox = pGia ); + Gia_ManStop( pGiaBox ); + + printf( "%8d -> ", Abc_NtkCountAndNodes(vOrder) ); + Gia_ManPrintStats( pGia, NULL ); + return pGia; +} +/* +void Abc_NtkDeriveFlatGia2_rec( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vOrder; + Abc_Obj_t * pObj; + int i; + if ( pNtk->pData != NULL ) + return; + vOrder = Abc_NtkDfsBoxes( pNtk ); + Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i ) + if ( Abc_ObjIsBox(pObj) ) + Abc_NtkDeriveFlatGia2_rec( (Abc_Ntk_t *)pObj->pData ); + pNtk->pData = Abc_NtkDeriveFlatGia2Derive( pNtk, vOrder ); + Vec_PtrFree( vOrder ); +} + +Gia_Man_t * Abc_NtkDeriveFlatGia2( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vMods; + Abc_Ntk_t * pModel; + Gia_Man_t * pGia = NULL; + int i; + + assert( Abc_NtkIsNetlist(pNtk) ); + assert( !Abc_NtkLatchNum(pNtk) ); + + vMods = pNtk->pDesign->vModules; + Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i ) + pModel->pData = NULL; + + Abc_NtkDeriveFlatGia2_rec( pNtk ); + pGia = pNtk->pData; pNtk->pData = NULL; + + Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i ) + Gia_ManStopP( (Gia_Man_t **)&pModel->pData ); + + return pGia; +} +*/ +Gia_Man_t * Abc_NtkDeriveFlatGia2( Abc_Ntk_t * pNtk, Vec_Ptr_t * vModels ) +{ + Vec_Ptr_t * vOrder; + Abc_Ntk_t * pModel = NULL; + Gia_Man_t * pGia = NULL; + int i; + + Vec_PtrForEachEntry( Abc_Ntk_t *, vModels, pModel, i ) + { + vOrder = Abc_NtkDfsBoxes( pModel ); + pModel->pData = Abc_NtkDeriveFlatGia2Derive( pModel, vOrder ); + Vec_PtrFree( vOrder ); + } + + pGia = (Gia_Man_t *)pModel->pData; pModel->pData = NULL; + + Vec_PtrForEachEntry( Abc_Ntk_t *, vModels, pModel, i ) + Gia_ManStopP( (Gia_Man_t **)&pModel->pData ); + + return pGia; +} + + +/**Function************************************************************* + + Synopsis [Collect models in the DFS order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCollectHie_rec( Abc_Ntk_t * pNtk, Vec_Ptr_t * vModels ) +{ + Vec_Ptr_t * vOrder; + Abc_Obj_t * pObj; + int i; + if ( pNtk->iStep >= 0 ) + return; + vOrder = Abc_NtkDfsBoxes( pNtk ); + Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i ) + if ( Abc_ObjIsBox(pObj) && (Abc_Ntk_t *)pObj->pData != pNtk ) + Abc_NtkCollectHie_rec( (Abc_Ntk_t *)pObj->pData, vModels ); + Vec_PtrFree( vOrder ); + pNtk->iStep = Vec_PtrSize(vModels); + Vec_PtrPush( vModels, pNtk ); +} + +Vec_Ptr_t * Abc_NtkCollectHie( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vMods, * vResult; + Abc_Ntk_t * pModel; + int i; + + assert( Abc_NtkIsNetlist(pNtk) ); + assert( !Abc_NtkLatchNum(pNtk) ); + + vResult = Vec_PtrAlloc( 1000 ); + if ( pNtk->pDesign == NULL ) + { + Vec_PtrPush( vResult, pNtk ); + return vResult; + } + + vMods = pNtk->pDesign->vModules; + Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i ) + pModel->iStep = -1; + + Abc_NtkCollectHie_rec( pNtk, vResult ); + return vResult; +} + +/**Function************************************************************* + + Synopsis [Counts the number of intstances.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCountInst_rec( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vOrder; + Abc_Obj_t * pObj; + int i, Counter = 0; + if ( pNtk->iStep >= 0 ) + return pNtk->iStep; + vOrder = Abc_NtkDfsBoxes( pNtk ); + Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i ) + if ( Abc_ObjIsBox(pObj) && (Abc_Ntk_t *)pObj->pData != pNtk ) + Counter += Abc_NtkCountInst_rec( (Abc_Ntk_t *)pObj->pData ); + Vec_PtrFree( vOrder ); + return pNtk->iStep = 1 + Counter; +} + +void Abc_NtkCountInst( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vMods; + Abc_Ntk_t * pModel; + int i, Counter; + + if ( pNtk->pDesign == NULL ) + Counter = Abc_NtkNodeNum(pNtk); + else + { + vMods = pNtk->pDesign->vModules; + Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i ) + pModel->iStep = -1; + Counter = Abc_NtkCountInst_rec( pNtk ); + } + printf( "Instances = %10d.\n", Counter ); +} + +/**Function************************************************************* + + Synopsis [Counts the number of nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +double Abc_NtkCountNodes_rec( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vOrder; + Abc_Obj_t * pObj; + double Counter = 0; + int i; + if ( pNtk->dTemp >= 0 ) + return pNtk->dTemp; + vOrder = Abc_NtkDfsBoxes( pNtk ); + Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i ) + if ( Abc_ObjIsNode(pObj) ) + Counter++; + else if ( Abc_ObjIsBox(pObj) && (Abc_Ntk_t *)pObj->pData != pNtk ) + Counter += Abc_NtkCountNodes_rec( (Abc_Ntk_t *)pObj->pData ); + Vec_PtrFree( vOrder ); + return pNtk->dTemp = Counter; +} + +void Abc_NtkCountNodes( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vMods; + Abc_Ntk_t * pModel; + double Counter; + int i; + + if ( pNtk->pDesign == NULL ) + Counter = Abc_NtkNodeNum(pNtk); + else + { + vMods = pNtk->pDesign->vModules; + Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i ) + pModel->dTemp = -1; + Counter = Abc_NtkCountNodes_rec( pNtk ); + } + printf( "Nodes = %.0f\n", Counter ); +} + +/**Function************************************************************* + + Synopsis [Checks if there is a recursive definition.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCheckRecursive( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vMods; + Abc_Ntk_t * pModel; + Abc_Obj_t * pObj; + int i, k, RetValue = 0; + + assert( Abc_NtkIsNetlist(pNtk) ); + assert( !Abc_NtkLatchNum(pNtk) ); + + if ( pNtk->pDesign == NULL ) + return RetValue; + + vMods = pNtk->pDesign->vModules; + Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i ) + { + Abc_NtkForEachObj( pModel, pObj, k ) + if ( Abc_ObjIsBox(pObj) && pObj->pData == (void *)pModel ) + { + printf( "WARNING: Model \"%s\" contains a recursive definition.\n", Abc_NtkName(pModel) ); + RetValue = 1; + break; + } + } + return RetValue; +} + +/**Function************************************************************* + + Synopsis [Performs hierarchical equivalence checking.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Abc_NtkHieCecTest( char * pFileName, int fVerbose ) +{ + int fUseTest = 1; + int fUseNew = 0; + int fCheck = 1; + Vec_Ptr_t * vMods, * vOrder; + Abc_Ntk_t * pNtk, * pModel; + Gia_Man_t * pGia; + int i; + abctime clk = Abc_Clock(); + + // read hierarchical netlist + pNtk = Io_ReadBlifMv( pFileName, 0, fCheck ); + if ( pNtk == NULL ) + { + printf( "Reading BLIF file has failed.\n" ); + return NULL; + } + if ( pNtk->pDesign == NULL || pNtk->pDesign->vModules == NULL ) + { + printf( "There is no hierarchy information.\n" ); +// Abc_NtkDelete( pNtk ); +// return NULL; + } + Abc_PrintTime( 1, "Reading file", Abc_Clock() - clk ); + + assert( Abc_NtkIsNetlist(pNtk) ); + assert( !Abc_NtkLatchNum(pNtk) ); +/* + if ( pNtk->pDesign != NULL ) + { + clk = Abc_Clock(); + Abc_NtkCountNodes( pNtk ); + Abc_PrintTime( 1, "Count nodes", Abc_Clock() - clk ); + } +*/ + // print stats + if ( fVerbose ) + Abc_NtkPrintBoxInfo( pNtk ); + + // test the new data-structure + if ( fUseTest ) + { + extern Gia_Man_t * Au_ManDeriveTest( Abc_Ntk_t * pRoot ); + Gia_Man_t * pGia; + pGia = Au_ManDeriveTest( pNtk ); + Abc_NtkDelete( pNtk ); + return pGia; + } + + if ( Abc_NtkCheckRecursive(pNtk) ) + return NULL; + + if ( fUseNew ) + { + clk = Abc_Clock(); + vOrder = Abc_NtkCollectHie( pNtk ); + Abc_PrintTime( 1, "Collect DFS ", Abc_Clock() - clk ); + + // derive GIA + clk = Abc_Clock(); + pGia = Abc_NtkDeriveFlatGia2( pNtk, vOrder ); + Abc_PrintTime( 1, "Deriving GIA", Abc_Clock() - clk ); + Gia_ManPrintStats( pGia, NULL ); + // Gia_ManStop( pGia ); + + Vec_PtrFree( vOrder ); + } + else + { + // order nodes/boxes of all models + vMods = pNtk->pDesign->vModules; + Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i ) + pModel->pData = Abc_NtkDfsBoxes( pModel ); + + // derive GIA + clk = Abc_Clock(); + pGia = Abc_NtkDeriveFlatGia( pNtk ); + Abc_PrintTime( 1, "Deriving GIA", Abc_Clock() - clk ); + Gia_ManPrintStats( pGia, NULL ); + + // clean nodes/boxes of all nodes + Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i ) + Vec_PtrFree( (Vec_Ptr_t *)pModel->pData ); + } + + clk = Abc_Clock(); + Abc_NtkCountInst( pNtk ); + Abc_PrintTime( 1, "Gather stats", Abc_Clock() - clk ); + + Abc_NtkDelete( pNtk ); + return pGia; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/abcHieGia.c b/yosys/abc/src/base/abc/abcHieGia.c new file mode 100644 index 00000000000..ca30459dc87 --- /dev/null +++ b/yosys/abc/src/base/abc/abcHieGia.c @@ -0,0 +1,582 @@ +/**CFile**************************************************************** + + FileName [abcHieGia.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures to handle hierarchy.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcHieGia.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Transfers the AIG from one manager into another.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeStrashToGia_rec( Gia_Man_t * pNew, Hop_Obj_t * pObj ) +{ + assert( !Hop_IsComplement(pObj) ); + if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) + return; + Abc_NodeStrashToGia_rec( pNew, Hop_ObjFanin0(pObj) ); + Abc_NodeStrashToGia_rec( pNew, Hop_ObjFanin1(pObj) ); + pObj->iData = Gia_ManHashAnd( pNew, Hop_ObjChild0CopyI(pObj), Hop_ObjChild1CopyI(pObj) ); + assert( !Hop_ObjIsMarkA(pObj) ); // loop detection + Hop_ObjSetMarkA( pObj ); +} +int Abc_NodeStrashToGia( Gia_Man_t * pNew, Abc_Obj_t * pNode ) +{ + Hop_Man_t * pMan = (Hop_Man_t *)pNode->pNtk->pManFunc; + Hop_Obj_t * pRoot = (Hop_Obj_t *)pNode->pData; + Abc_Obj_t * pFanin; int i; + assert( Abc_ObjIsNode(pNode) ); + assert( Abc_NtkHasAig(pNode->pNtk) && !Abc_NtkIsStrash(pNode->pNtk) ); + // check the constant case + if ( Abc_NodeIsConst(pNode) || Hop_Regular(pRoot) == Hop_ManConst1(pMan) ) + return Abc_LitNotCond( 1, Hop_IsComplement(pRoot) ); + // set elementary variables + Abc_ObjForEachFanin( pNode, pFanin, i ) + assert( pFanin->iTemp != -1 ); + Abc_ObjForEachFanin( pNode, pFanin, i ) + Hop_IthVar(pMan, i)->iData = pFanin->iTemp; + // strash the AIG of this node + Abc_NodeStrashToGia_rec( pNew, Hop_Regular(pRoot) ); + Hop_ConeUnmark_rec( Hop_Regular(pRoot) ); + return Abc_LitNotCond( Hop_Regular(pRoot)->iData, Hop_IsComplement(pRoot) ); +} + + +/**Function************************************************************* + + Synopsis [Flattens the logic hierarchy of the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFlattenHierarchyGia2_rec( Gia_Man_t * pNew, Abc_Ntk_t * pNtk, int * pCounter, Vec_Int_t * vBufs ) +{ + Vec_Ptr_t * vDfs = (Vec_Ptr_t *)pNtk->pData; + Abc_Obj_t * pObj, * pTerm; + int i, k; (*pCounter)++; + //printf( "[%d:%d] ", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk) ); + Vec_PtrForEachEntry( Abc_Obj_t *, vDfs, pObj, i ) + { + if ( Abc_ObjIsNode(pObj) ) + Abc_ObjFanout0(pObj)->iTemp = Abc_NodeStrashToGia( pNew, pObj ); + else + { + int iBufStart = Gia_ManBufNum(pNew); + Abc_Ntk_t * pModel = (Abc_Ntk_t *)pObj->pData; + assert( !Abc_ObjIsLatch(pObj) ); + assert( Abc_NtkPiNum(pModel) == Abc_ObjFaninNum(pObj) ); + assert( Abc_NtkPoNum(pModel) == Abc_ObjFanoutNum(pObj) ); + Abc_NtkFillTemp( pModel ); + Abc_ObjForEachFanin( pObj, pTerm, k ) + { + assert( Abc_ObjIsNet(Abc_ObjFanin0(pTerm)) ); + Abc_ObjFanout0(Abc_NtkPi(pModel, k))->iTemp = Abc_ObjFanin0(pTerm)->iTemp; + } + if ( vBufs ) + Abc_ObjForEachFanin( pObj, pTerm, k ) + Abc_ObjFanout0(Abc_NtkPi(pModel, k))->iTemp = Gia_ManAppendBuf( pNew, Abc_ObjFanout0(Abc_NtkPi(pModel, k))->iTemp ); + Abc_NtkFlattenHierarchyGia2_rec( pNew, pModel, pCounter, vBufs ); + if ( vBufs ) + Abc_ObjForEachFanout( pObj, pTerm, k ) + Abc_ObjFanin0(Abc_NtkPo(pModel, k))->iTemp = Gia_ManAppendBuf( pNew, Abc_ObjFanin0(Abc_NtkPo(pModel, k))->iTemp ); + Abc_ObjForEachFanout( pObj, pTerm, k ) + { + assert( Abc_ObjIsNet(Abc_ObjFanout0(pTerm)) ); + Abc_ObjFanout0(pTerm)->iTemp = Abc_ObjFanin0(Abc_NtkPo(pModel, k))->iTemp; + } + // save buffers + if ( vBufs == NULL ) + continue; + Vec_IntPush( vBufs, iBufStart ); + Vec_IntPush( vBufs, Abc_NtkPiNum(pModel) ); + Vec_IntPush( vBufs, Gia_ManBufNum(pNew) - Abc_NtkPoNum(pModel) ); + Vec_IntPush( vBufs, Abc_NtkPoNum(pModel) ); + } + } +} +Gia_Man_t * Abc_NtkFlattenHierarchyGia2( Abc_Ntk_t * pNtk ) +{ + int fUseBufs = 1; + int fUseInter = 0; + Gia_Man_t * pNew, * pTemp; + Abc_Ntk_t * pModel; + Abc_Obj_t * pTerm; + int i, Counter = -1; + assert( Abc_NtkIsNetlist(pNtk) ); +// Abc_NtkPrintBoxInfo( pNtk ); + Abc_NtkFillTemp( pNtk ); + + // start the manager + pNew = Gia_ManStart( Abc_NtkObjNumMax(pNtk) ); + pNew->pName = Abc_UtilStrsav(pNtk->pName); + pNew->pSpec = Abc_UtilStrsav(pNtk->pSpec); + if ( fUseBufs ) + pNew->vBarBufs = Vec_IntAlloc( 1000 ); + + // create PIs and buffers + Abc_NtkForEachPi( pNtk, pTerm, i ) + pTerm->iTemp = Gia_ManAppendCi( pNew ); + Abc_NtkForEachPi( pNtk, pTerm, i ) + Abc_ObjFanout0(pTerm)->iTemp = fUseInter ? Gia_ManAppendBuf(pNew, pTerm->iTemp) : pTerm->iTemp; + + // create DFS order of nets + if ( !pNtk->pDesign ) + pNtk->pData = Abc_NtkDfsWithBoxes( pNtk ); + else + Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pModel, i ) + pModel->pData = Abc_NtkDfsWithBoxes( pModel ); + + // call recursively + Gia_ManHashAlloc( pNew ); + Abc_NtkFlattenHierarchyGia2_rec( pNew, pNtk, &Counter, pNew->vBarBufs ); + Gia_ManHashStop( pNew ); + printf( "Hierarchy reader flattened %d instances of logic boxes.\n", Counter ); + + // delete DFS order of nets + if ( !pNtk->pDesign ) + Vec_PtrFreeP( (Vec_Ptr_t **)&pNtk->pData ); + else + Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pModel, i ) + Vec_PtrFreeP( (Vec_Ptr_t **)&pModel->pData ); + + // create buffers and POs + Abc_NtkForEachPo( pNtk, pTerm, i ) + pTerm->iTemp = fUseInter ? Gia_ManAppendBuf(pNew, Abc_ObjFanin0(pTerm)->iTemp) : Abc_ObjFanin0(pTerm)->iTemp; + Abc_NtkForEachPo( pNtk, pTerm, i ) + Gia_ManAppendCo( pNew, pTerm->iTemp ); + + // save buffers + if ( fUseInter ) + { + Vec_IntPush( pNew->vBarBufs, 0 ); + Vec_IntPush( pNew->vBarBufs, Abc_NtkPiNum(pNtk) ); + Vec_IntPush( pNew->vBarBufs, Gia_ManBufNum(pNew) - Abc_NtkPoNum(pNtk) ); + Vec_IntPush( pNew->vBarBufs, Abc_NtkPoNum(pNtk) ); + } + if ( fUseBufs ) + Vec_IntPrint( pNew->vBarBufs ); + + // cleanup + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Gia_ManPrintBarBufDrivers( Gia_Man_t * p ) +{ + Vec_Int_t * vMap, * vFan, * vCrits; + Gia_Obj_t * pObj; + int i, iFanin, CountCrit[2] = {0}, CountFans[2] = {0}; + // map barbuf drivers into barbuf literals of the first barbuf driven by them + vMap = Vec_IntStart( Gia_ManObjNum(p) ); + vFan = Vec_IntStart( Gia_ManObjNum(p) ); + vCrits = Vec_IntAlloc( 100 ); + Gia_ManForEachObj( p, pObj, i ) + { + // count fanouts + if ( Gia_ObjIsBuf(pObj) || Gia_ObjIsCo(pObj) ) + Vec_IntAddToEntry( vFan, Gia_ObjFaninId0(pObj, i), 1 ); + else if ( Gia_ObjIsAnd(pObj) ) + { + Vec_IntAddToEntry( vFan, Gia_ObjFaninId0(pObj, i), 1 ); + Vec_IntAddToEntry( vFan, Gia_ObjFaninId1(pObj, i), 1 ); + } + // count critical barbufs + if ( Gia_ObjIsBuf(pObj) ) + { + iFanin = Gia_ObjFaninId0( pObj, i ); + if ( iFanin == 0 || Vec_IntEntry(vMap, iFanin) != 0 ) + { + CountCrit[(int)(iFanin != 0)]++; + Vec_IntPush( vCrits, i ); + continue; + } + Vec_IntWriteEntry( vMap, iFanin, Abc_Var2Lit(i, Gia_ObjFaninC0(pObj)) ); + } + } + // check fanouts of the critical barbufs + Gia_ManForEachObjVec( vCrits, p, pObj, i ) + { + assert( Gia_ObjIsBuf(pObj) ); + if ( Vec_IntEntry(vFan, i) == 0 ) + continue; + iFanin = Gia_ObjFaninId0p( p, pObj ); + CountFans[(int)(iFanin != 0)]++; + } + printf( "Detected %d const (out of %d) and %d shared (out of %d) barbufs with fanout.\n", + CountFans[0], CountCrit[0], CountFans[1], CountCrit[1] ); + Vec_IntFree( vMap ); + Vec_IntFree( vFan ); + Vec_IntFree( vCrits ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Gia_ManPatchBufDriver( Gia_Man_t * p, int iBuf, int iLit0 ) +{ + Gia_Obj_t * pObjBuf = Gia_ManObj( p, iBuf ); + assert( Gia_ObjIsBuf(pObjBuf) ); + assert( Gia_ObjId(p, pObjBuf) > Abc_Lit2Var(iLit0) ); + pObjBuf->iDiff1 = pObjBuf->iDiff0 = Gia_ObjId(p, pObjBuf) - Abc_Lit2Var(iLit0); + pObjBuf->fCompl1 = pObjBuf->fCompl0 = Abc_LitIsCompl(iLit0); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Gia_ManSweepHierarchy( Gia_Man_t * p ) +{ + Vec_Int_t * vMap = Vec_IntStart( Gia_ManObjNum(p) ); + Gia_Man_t * pNew, * pTemp; + Gia_Obj_t * pObj, * pObjNew, * pObjNewR; + int i, iFanin, CountReals[2] = {0}; + + // duplicate AIG while propagating constants and equivalences + pNew = Gia_ManStart( Gia_ManObjNum(p) ); + pNew->pName = Abc_UtilStrsav( p->pName ); + pNew->pSpec = Abc_UtilStrsav( p->pSpec ); + Gia_ManConst0(p)->Value = 0; + Gia_ManHashAlloc( pNew ); + Gia_ManForEachObj1( p, pObj, i ) + { + if ( Gia_ObjIsBuf(pObj) ) + { + pObj->Value = Gia_ManAppendBuf( pNew, Gia_ObjFanin0Copy(pObj) ); + pObjNew = Gia_ManObj( pNew, Abc_Lit2Var(pObj->Value) ); + iFanin = Gia_ObjFaninId0p( pNew, pObjNew ); + if ( iFanin == 0 ) + { + pObj->Value = Gia_ObjFaninC0(pObjNew); + CountReals[0]++; + Gia_ManPatchBufDriver( pNew, Gia_ObjId(pNew, pObjNew), 0 ); + } + else if ( Vec_IntEntry(vMap, iFanin) ) + { + pObjNewR = Gia_ManObj( pNew, Vec_IntEntry(vMap, iFanin) ); + pObj->Value = Abc_Var2Lit( Vec_IntEntry(vMap, iFanin), Gia_ObjFaninC0(pObjNewR) ^ Gia_ObjFaninC0(pObjNew) ); + CountReals[1]++; + Gia_ManPatchBufDriver( pNew, Gia_ObjId(pNew, pObjNew), 0 ); + } + else + Vec_IntWriteEntry( vMap, iFanin, Gia_ObjId(pNew, pObjNew) ); + } + else if ( Gia_ObjIsAnd(pObj) ) + pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) ); + else if ( Gia_ObjIsCi(pObj) ) + pObj->Value = Gia_ManAppendCi( pNew ); + else if ( Gia_ObjIsCo(pObj) ) + pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) ); + } + Gia_ManHashStop( pNew ); + Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) ); + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); +// printf( "Updated %d const and %d shared.\n", CountReals[0], CountReals[1] ); + Vec_IntFree( vMap ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Flattens the logic hierarchy of the netlist.] + + Description [This procedure requires that models are uniqified.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Gia_ManFlattenLogicPrepare( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pTerm, * pBox; + int i, k; + Abc_NtkFillTemp( pNtk ); + Abc_NtkForEachPi( pNtk, pTerm, i ) + pTerm->iData = i; + Abc_NtkForEachPo( pNtk, pTerm, i ) + pTerm->iData = i; + Abc_NtkForEachBox( pNtk, pBox, i ) + { + assert( !Abc_ObjIsLatch(pBox) ); + Abc_ObjForEachFanin( pBox, pTerm, k ) + pTerm->iData = k; + Abc_ObjForEachFanout( pBox, pTerm, k ) + pTerm->iData = k; + } + return Abc_NtkPiNum(pNtk) + Abc_NtkPoNum(pNtk); +} +int Abc_NtkFlattenHierarchyGia_rec( Gia_Man_t * pNew, Vec_Ptr_t * vSupers, Abc_Obj_t * pObj, Vec_Ptr_t * vBuffers ) +{ + Abc_Ntk_t * pModel; + Abc_Obj_t * pBox, * pFanin; + int iLit, i; + if ( pObj->iTemp != -1 ) + return pObj->iTemp; + if ( Abc_ObjIsNet(pObj) || Abc_ObjIsPo(pObj) || Abc_ObjIsBi(pObj) ) + return (pObj->iTemp = Abc_NtkFlattenHierarchyGia_rec(pNew, vSupers, Abc_ObjFanin0(pObj), vBuffers)); + if ( Abc_ObjIsPi(pObj) ) + { + pBox = (Abc_Obj_t *)Vec_PtrPop( vSupers ); + pModel = Abc_ObjModel(pBox); + //printf( " Exiting %s\n", Abc_NtkName(pModel) ); + assert( Abc_ObjFaninNum(pBox) == Abc_NtkPiNum(pModel) ); + assert( pObj->iData >= 0 && pObj->iData < Abc_NtkPiNum(pModel) ); + pFanin = Abc_ObjFanin( pBox, pObj->iData ); + iLit = Abc_NtkFlattenHierarchyGia_rec( pNew, vSupers, pFanin, vBuffers ); + Vec_PtrPush( vSupers, pBox ); + //if ( vBuffers ) Vec_PtrPush( vBuffers, pFanin ); // save BI + if ( vBuffers ) Vec_PtrPush( vBuffers, pObj ); // save PI + return (pObj->iTemp = (vBuffers ? Gia_ManAppendBuf(pNew, iLit) : iLit)); + } + if ( Abc_ObjIsBo(pObj) ) + { + pBox = Abc_ObjFanin0(pObj); + assert( Abc_ObjIsBox(pBox) ); + Vec_PtrPush( vSupers, pBox ); + pModel = Abc_ObjModel(pBox); + //printf( "Entering %s\n", Abc_NtkName(pModel) ); + assert( Abc_ObjFanoutNum(pBox) == Abc_NtkPoNum(pModel) ); + assert( pObj->iData >= 0 && pObj->iData < Abc_NtkPoNum(pModel) ); + pFanin = Abc_NtkPo( pModel, pObj->iData ); + iLit = Abc_NtkFlattenHierarchyGia_rec( pNew, vSupers, pFanin, vBuffers ); + Vec_PtrPop( vSupers ); + //if ( vBuffers ) Vec_PtrPush( vBuffers, pObj ); // save BO + if ( vBuffers ) Vec_PtrPush( vBuffers, pFanin ); // save PO + return (pObj->iTemp = (vBuffers ? Gia_ManAppendBuf(pNew, iLit) : iLit)); + } + assert( Abc_ObjIsNode(pObj) ); + Abc_ObjForEachFanin( pObj, pFanin, i ) + Abc_NtkFlattenHierarchyGia_rec( pNew, vSupers, pFanin, vBuffers ); + return (pObj->iTemp = Abc_NodeStrashToGia( pNew, pObj )); +} +Gia_Man_t * Abc_NtkFlattenHierarchyGia( Abc_Ntk_t * pNtk, Vec_Ptr_t ** pvBuffers, int fVerbose ) +{ + int fUseBufs = 1; + Gia_Man_t * pNew, * pTemp; + Abc_Ntk_t * pModel; + Abc_Obj_t * pTerm; + Vec_Ptr_t * vSupers; + Vec_Ptr_t * vBuffers = fUseBufs ? Vec_PtrAlloc(1000) : NULL; + int i, Counter = 0; + assert( Abc_NtkIsNetlist(pNtk) ); +// Abc_NtkPrintBoxInfo( pNtk ); + + // set the PI/PO numbers + Counter -= Abc_NtkPiNum(pNtk) + Abc_NtkPoNum(pNtk); + if ( !pNtk->pDesign ) + Counter += Gia_ManFlattenLogicPrepare( pNtk ); + else + Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pModel, i ) + Counter += Gia_ManFlattenLogicPrepare( pModel ); + + // start the manager + pNew = Gia_ManStart( Abc_NtkObjNumMax(pNtk) ); + pNew->pName = Abc_UtilStrsav(pNtk->pName); + pNew->pSpec = Abc_UtilStrsav(pNtk->pSpec); + + // create PIs and buffers + Abc_NtkForEachPi( pNtk, pTerm, i ) + pTerm->iTemp = Gia_ManAppendCi( pNew ); + + // call recursively + vSupers = Vec_PtrAlloc( 100 ); + Gia_ManHashAlloc( pNew ); + Abc_NtkForEachPo( pNtk, pTerm, i ) + Abc_NtkFlattenHierarchyGia_rec( pNew, vSupers, pTerm, vBuffers ); + Gia_ManHashStop( pNew ); + Vec_PtrFree( vSupers ); + printf( "Hierarchy reader flattened %d instances of boxes and added %d barbufs (out of %d).\n", + pNtk->pDesign ? Vec_PtrSize(pNtk->pDesign->vModules)-1 : 0, Vec_PtrSize(vBuffers), Counter ); + + // create buffers and POs + Abc_NtkForEachPo( pNtk, pTerm, i ) + Gia_ManAppendCo( pNew, pTerm->iTemp ); + + if ( pvBuffers ) + *pvBuffers = vBuffers; + else + Vec_PtrFreeP( &vBuffers ); + + // cleanup + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); +// Gia_ManPrintStats( pNew, NULL ); + pNew = Gia_ManSweepHierarchy( pTemp = pNew ); + Gia_ManStop( pTemp ); +// Gia_ManPrintStats( pNew, NULL ); + return pNew; +} + +/**Function************************************************************* + + Synopsis [Inserts the result of mapping into logic hierarchy.] + + Description [When this procedure is called PIs/POs of pNtk + point to the corresponding nodes in network with barbufs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Gia_ManInsertOne_rec( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNew, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin; int i; + if ( pObj == NULL ) + return Abc_NtkCreateNodeConst0( pNtk ); + assert( Abc_ObjNtk(pObj) == pNew ); + if ( pObj->pCopy ) + return pObj->pCopy; + Abc_ObjForEachFanin( pObj, pFanin, i ) + Gia_ManInsertOne_rec( pNtk, pNew, pFanin ); + pObj->pCopy = Abc_NtkDupObj( pNtk, pObj, 0 ); + Abc_ObjForEachFanin( pObj, pFanin, i ) + Abc_ObjAddFanin( pObj, pFanin ); + return pObj->pCopy; +} +void Gia_ManInsertOne( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNew ) +{ + Abc_Obj_t * pObj, * pBox; int i, k; + assert( !Abc_NtkHasMapping(pNtk) ); + assert( Abc_NtkHasMapping(pNew) ); + // check that PIs point to barbufs + Abc_NtkForEachPi( pNtk, pObj, i ) + assert( !pObj->pCopy || Abc_ObjNtk(pObj->pCopy) == pNew ); + // make barbufs point to box outputs + Abc_NtkForEachBox( pNtk, pBox, i ) + Abc_ObjForEachFanout( pBox, pObj, k ) + { + pObj->pCopy = Abc_NtkPo(Abc_ObjModel(pBox), k)->pCopy; + assert( !pObj->pCopy || Abc_ObjNtk(pObj->pCopy) == pNew ); + } + // remove internal nodes + Abc_NtkForEachNode( pNtk, pObj, i ) + Abc_NtkDeleteObj( pObj ); + // start traversal from box inputs + Abc_NtkForEachBox( pNtk, pBox, i ) + Abc_ObjForEachFanin( pBox, pObj, k ) + if ( Abc_ObjFaninNum(pObj) == 0 ) + Abc_ObjAddFanin( pObj, Gia_ManInsertOne_rec(pNtk, pNew, Abc_NtkPi(Abc_ObjModel(pBox), k)->pCopy) ); + // start traversal from primary outputs + Abc_NtkForEachPo( pNtk, pObj, i ) + if ( Abc_ObjFaninNum(pObj) == 0 ) + Abc_ObjAddFanin( pObj, Gia_ManInsertOne_rec(pNtk, pNew, pObj->pCopy) ); + // update the functionality manager + pNtk->pManFunc = pNew->pManFunc; + pNtk->ntkFunc = pNew->ntkFunc; + assert( Abc_NtkHasMapping(pNtk) ); +} +void Abc_NtkInsertHierarchyGia( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNew, int fVerbose ) +{ + Vec_Ptr_t * vBuffers; + Gia_Man_t * pGia = Abc_NtkFlattenHierarchyGia( pNtk, &vBuffers, 0 ); + Abc_Ntk_t * pModel; + Abc_Obj_t * pObj; + int i, k = 0; + + assert( Gia_ManPiNum(pGia) == Abc_NtkPiNum(pNtk) ); + assert( Gia_ManPiNum(pGia) == Abc_NtkPiNum(pNew) ); + assert( Gia_ManPoNum(pGia) == Abc_NtkPoNum(pNtk) ); + assert( Gia_ManPoNum(pGia) == Abc_NtkPoNum(pNew) ); + assert( Gia_ManBufNum(pGia) == Vec_PtrSize(vBuffers) ); + assert( Gia_ManBufNum(pGia) == pNew->nBarBufs2 ); + Gia_ManStop( pGia ); + + // clean the networks + if ( !pNtk->pDesign ) + Abc_NtkCleanCopy( pNtk ); + else + Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pModel, i ) + Abc_NtkCleanCopy( pModel ); + + // annotate PIs and POs of each network with barbufs + Abc_NtkForEachPi( pNew, pObj, i ) + Abc_NtkPi(pNtk, i)->pCopy = pObj; + Abc_NtkForEachPo( pNew, pObj, i ) + Abc_NtkPo(pNtk, i)->pCopy = pObj; + Abc_NtkForEachBarBuf( pNew, pObj, i ) + ((Abc_Obj_t *)Vec_PtrEntry(vBuffers, k++))->pCopy = pObj; + Vec_PtrFree( vBuffers ); + + // connect each model + Abc_NtkCleanCopy( pNew ); + Gia_ManInsertOne( pNtk, pNew ); + if ( pNtk->pDesign ) + Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pModel, i ) + if ( pModel != pNtk ) + Gia_ManInsertOne( pModel, pNew ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/abcHieNew.c b/yosys/abc/src/base/abc/abcHieNew.c new file mode 100644 index 00000000000..54a61609f89 --- /dev/null +++ b/yosys/abc/src/base/abc/abcHieNew.c @@ -0,0 +1,1635 @@ +/**CFile**************************************************************** + + FileName [abcHieNew.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [New hierarchy manager.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcHieNew.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include +#include +#include +#include + +#include "misc/vec/vec.h" +#include "misc/util/utilNam.h" +#include "misc/extra/extra.h" + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define AU_MAX_FANINS 0x1FFFFFFF + +typedef enum { + AU_OBJ_NONE, // 0: non-existent object + AU_OBJ_CONST0, // 1: constant node + AU_OBJ_PI, // 2: primary input + AU_OBJ_PO, // 3: primary output + AU_OBJ_FAN, // 4: box output + AU_OBJ_FLOP, // 5: flip-flop + AU_OBJ_BOX, // 6: box + AU_OBJ_NODE, // 7: logic node + AU_OBJ_VOID // 8: placeholder +} Au_Type_t; + + +typedef struct Au_Man_t_ Au_Man_t; +typedef struct Au_Ntk_t_ Au_Ntk_t; +typedef struct Au_Obj_t_ Au_Obj_t; + +struct Au_Obj_t_ // 16 bytes +{ + unsigned Func : 30; // functionality + unsigned Value : 2; // node value + unsigned Type : 3; // object type + unsigned nFanins : 29; // fanin count (related to AU_MAX_FANIN_NUM) + int Fanins[2]; // fanin literals +}; + +struct Au_Ntk_t_ +{ + char * pName; // model name + Au_Man_t * pMan; // model manager + int Id; // model ID + // objects + Vec_Int_t vPis; // primary inputs (CI id -> handle) + Vec_Int_t vPos; // primary outputs (CI id -> handle) + Vec_Int_t vObjs; // internal nodes (obj id -> handle) + int nObjs[AU_OBJ_VOID]; // counter of objects of each type + // memory for objects + Vec_Ptr_t * vChunks; // memory pages + Vec_Ptr_t vPages; // memory pages + int iHandle; // currently available ID + int nObjsAlloc; // the total number of objects allocated + int nObjsUsed; // the number of useful entries + // object attributes + int nTravIds; // counter of traversal IDs + Vec_Int_t vTravIds; // trav IDs of the objects + Vec_Int_t vCopies; // object copies + // structural hashing + int nHTable; // hash table size + int * pHTable; // hash table + Au_Obj_t * pConst0; // constant node + // statistics + int fMark; + double nBoxes; + double nNodes; + double nPorts; + double nNodeAnds; + double nNodeXors; + double nNodeMuxs; +}; + +struct Au_Man_t_ +{ + char * pName; // the name of the library + Vec_Ptr_t vNtks; // the array of modules + Abc_Nam_t * pFuncs; // hashing functions into integers + int nRefs; // reference counter + // statistics + int nGiaObjMax; // max number of GIA objects + double nPortsC0; // const ports + double nPortsC1; // const ports + double nPortsNC; // non-const ports +}; + + +static inline int Au_Var2Lit( int Var, int fCompl ) { return Var + Var + fCompl; } +static inline int Au_Lit2Var( int Lit ) { return Lit >> 1; } +static inline int Au_LitIsCompl( int Lit ) { return Lit & 1; } +static inline int Au_LitNot( int Lit ) { return Lit ^ 1; } +static inline int Au_LitNotCond( int Lit, int c ) { return Lit ^ (int)(c > 0); } +static inline int Au_LitRegular( int Lit ) { return Lit & ~01; } + +static inline Au_Obj_t * Au_Regular( Au_Obj_t * p ) { return (Au_Obj_t *)((ABC_PTRUINT_T)(p) & ~01); } +static inline Au_Obj_t * Au_Not( Au_Obj_t * p ) { return (Au_Obj_t *)((ABC_PTRUINT_T)(p) ^ 01); } +static inline Au_Obj_t * Au_NotCond( Au_Obj_t * p, int c ) { return (Au_Obj_t *)((ABC_PTRUINT_T)(p) ^ (c)); } +static inline int Au_IsComplement( Au_Obj_t * p ) { return (int)((ABC_PTRUINT_T)(p) & 01); } + +static inline char * Au_UtilStrsav( char * s ) { return s ? strcpy(ABC_ALLOC(char, strlen(s)+1), s) : NULL; } + +static inline char * Au_ManName( Au_Man_t * p ) { return p->pName; } +static inline int Au_ManNtkNum( Au_Man_t * p ) { return Vec_PtrSize(&p->vNtks) - 1; } +static inline Au_Ntk_t * Au_ManNtk( Au_Man_t * p, int i ) { return (Au_Ntk_t *)Vec_PtrEntry(&p->vNtks, i); } +static inline Au_Ntk_t * Au_ManNtkRoot( Au_Man_t * p ) { return Au_ManNtk( p, 1 ); } + +static inline char * Au_NtkName( Au_Ntk_t * p ) { return p->pName; } +static inline Au_Man_t * Au_NtkMan( Au_Ntk_t * p ) { return p->pMan; } +static inline int Au_NtkPiNum( Au_Ntk_t * p ) { return p->nObjs[AU_OBJ_PI]; } +static inline int Au_NtkPoNum( Au_Ntk_t * p ) { return p->nObjs[AU_OBJ_PO]; } +static inline int Au_NtkFanNum( Au_Ntk_t * p ) { return p->nObjs[AU_OBJ_FAN]; } +static inline int Au_NtkFlopNum( Au_Ntk_t * p ) { return p->nObjs[AU_OBJ_FLOP]; } +static inline int Au_NtkBoxNum( Au_Ntk_t * p ) { return p->nObjs[AU_OBJ_BOX]; } +static inline int Au_NtkNodeNum( Au_Ntk_t * p ) { return p->nObjs[AU_OBJ_NODE]; } +static inline int Au_NtkObjNumMax( Au_Ntk_t * p ) { return (Vec_PtrSize(&p->vPages) - 1) * (1 << 12) + p->iHandle; } +static inline int Au_NtkObjNum( Au_Ntk_t * p ) { return Vec_IntSize(&p->vObjs); } +static inline Au_Obj_t * Au_NtkObj( Au_Ntk_t * p, int h ) { return (Au_Obj_t *)p->vPages.pArray[h >> 12] + (h & 0xFFF); } + +static inline Au_Obj_t * Au_NtkPi( Au_Ntk_t * p, int i ) { return Au_NtkObj(p, Vec_IntEntry(&p->vPis, i)); } +static inline Au_Obj_t * Au_NtkPo( Au_Ntk_t * p, int i ) { return Au_NtkObj(p, Vec_IntEntry(&p->vPos, i)); } +static inline Au_Obj_t * Au_NtkObjI( Au_Ntk_t * p, int i ) { return Au_NtkObj(p, Vec_IntEntry(&p->vObjs, i)); } + +static inline int Au_ObjIsNone( Au_Obj_t * p ) { return p->Type == AU_OBJ_NONE; } +static inline int Au_ObjIsConst0( Au_Obj_t * p ) { return p->Type == AU_OBJ_CONST0; } +static inline int Au_ObjIsPi( Au_Obj_t * p ) { return p->Type == AU_OBJ_PI; } +static inline int Au_ObjIsPo( Au_Obj_t * p ) { return p->Type == AU_OBJ_PO; } +static inline int Au_ObjIsFan( Au_Obj_t * p ) { return p->Type == AU_OBJ_FAN; } +static inline int Au_ObjIsFlop( Au_Obj_t * p ) { return p->Type == AU_OBJ_FLOP; } +static inline int Au_ObjIsBox( Au_Obj_t * p ) { return p->Type == AU_OBJ_BOX; } +static inline int Au_ObjIsNode( Au_Obj_t * p ) { return p->Type == AU_OBJ_NODE; } +static inline int Au_ObjIsTerm( Au_Obj_t * p ) { return p->Type >= AU_OBJ_PI && p->Type <= AU_OBJ_FLOP; } + +static inline char * Au_ObjBase( Au_Obj_t * p ) { return (char *)p - ((ABC_PTRINT_T)p & 0x3FF); } +static inline Au_Ntk_t * Au_ObjNtk( Au_Obj_t * p ) { return ((Au_Ntk_t **)Au_ObjBase(p))[0]; } +static inline int Au_ObjId( Au_Obj_t * p ) { return ((int *)Au_ObjBase(p))[2] | (((ABC_PTRINT_T)p & 0x3FF) >> 4); } +static inline int Au_ObjPioNum( Au_Obj_t * p ) { assert(Au_ObjIsTerm(p)); return p->Fanins[p->nFanins]; } +static inline int Au_ObjFunc( Au_Obj_t * p ) { return p->Func; } +static inline Au_Ntk_t * Au_ObjModel( Au_Obj_t * p ) { assert(Au_ObjIsFan(p)||Au_ObjIsBox(p)); return Au_ManNtk(Au_NtkMan(Au_ObjNtk(p)), p->Func); } + +static inline int Au_ObjFaninNum( Au_Obj_t * p ) { return p->nFanins; } +static inline int Au_ObjFaninId( Au_Obj_t * p, int i ) { assert(i >= 0 && i < (int)p->nFanins && p->Fanins[i]); return Au_Lit2Var(p->Fanins[i]); } +static inline int Au_ObjFaninId0( Au_Obj_t * p ) { return Au_ObjFaninId(p, 0); } +static inline int Au_ObjFaninId1( Au_Obj_t * p ) { return Au_ObjFaninId(p, 1); } +static inline int Au_ObjFaninId2( Au_Obj_t * p ) { return Au_ObjFaninId(p, 2); } +static inline Au_Obj_t * Au_ObjFanin( Au_Obj_t * p, int i ) { return Au_NtkObj(Au_ObjNtk(p), Au_ObjFaninId(p, i)); } +static inline Au_Obj_t * Au_ObjFanin0( Au_Obj_t * p ) { return Au_ObjFanin( p, 0 ); } +static inline Au_Obj_t * Au_ObjFanin1( Au_Obj_t * p ) { return Au_ObjFanin( p, 1 ); } +static inline Au_Obj_t * Au_ObjFanin2( Au_Obj_t * p ) { return Au_ObjFanin( p, 2 ); } +static inline int Au_ObjFaninC( Au_Obj_t * p, int i ) { assert(i >= 0 && i < (int)p->nFanins && p->Fanins[i]); return Au_LitIsCompl(p->Fanins[i]); } +static inline int Au_ObjFaninC0( Au_Obj_t * p ) { return Au_ObjFaninC(p, 0); } +static inline int Au_ObjFaninC1( Au_Obj_t * p ) { return Au_ObjFaninC(p, 1); } +static inline int Au_ObjFaninC2( Au_Obj_t * p ) { return Au_ObjFaninC(p, 2); } +static inline int Au_ObjFaninLit( Au_Obj_t * p, int i ) { assert(i >= 0 && i < (int)p->nFanins && p->Fanins[i]); return p->Fanins[i]; } +static inline void Au_ObjSetFanin( Au_Obj_t * p, int i, int f ) { assert(f > 0 && p->Fanins[i] == 0); p->Fanins[i] = Au_Var2Lit(f,0); } +static inline void Au_ObjSetFaninLit( Au_Obj_t * p, int i, int f){ assert(f >= 0 && p->Fanins[i] == 0); p->Fanins[i] = f; } + +static inline int Au_BoxFanoutNum( Au_Obj_t * p ) { assert(Au_ObjIsBox(p)); return p->Fanins[p->nFanins]; } +static inline int Au_BoxFanoutId( Au_Obj_t * p, int i ) { assert(i >= 0 && i < Au_BoxFanoutNum(p)); return p->Fanins[p->nFanins+1+i]; } +static inline Au_Obj_t * Au_BoxFanout( Au_Obj_t * p, int i ) { return Au_NtkObj(Au_ObjNtk(p), Au_BoxFanoutId(p, i)); } + +static inline int Au_ObjCopy( Au_Obj_t * p ) { return Vec_IntEntry( &Au_ObjNtk(p)->vCopies, Au_ObjId(p) ); } +static inline void Au_ObjSetCopy( Au_Obj_t * p, int c ) { Vec_IntWriteEntry( &Au_ObjNtk(p)->vCopies, Au_ObjId(p), c ); } + +static inline int Au_ObjFanout( Au_Obj_t * p, int i ) { assert(p->Type == AU_OBJ_BOX && i >= 0 && i < p->Fanins[p->nFanins] && p->Fanins[i]); return p->Fanins[p->nFanins + 1 + i]; } +static inline void Au_ObjSetFanout( Au_Obj_t * p, int i, int f ) { assert(p->Type == AU_OBJ_BOX && i >= 0 && i < p->Fanins[p->nFanins] && p->Fanins[i] == 0 && f > 0); p->Fanins[p->nFanins + 1 + i] = f; } + +static inline void Au_NtkIncrementTravId( Au_Ntk_t * p ) { if (p->vTravIds.pArray == NULL) Vec_IntFill(&p->vTravIds, Au_NtkObjNumMax(p)+500, 0); p->nTravIds++; assert(p->nTravIds < (1<<30)); } +static inline void Au_ObjSetTravIdCurrent( Au_Obj_t * p ) { Vec_IntSetEntry(&Au_ObjNtk(p)->vTravIds, Au_ObjId(p), Au_ObjNtk(p)->nTravIds ); } +static inline void Au_ObjSetTravIdPrevious( Au_Obj_t * p ) { Vec_IntSetEntry(&Au_ObjNtk(p)->vTravIds, Au_ObjId(p), Au_ObjNtk(p)->nTravIds-1 ); } +static inline int Au_ObjIsTravIdCurrent( Au_Obj_t * p ) { return (Vec_IntGetEntry(&Au_ObjNtk(p)->vTravIds, Au_ObjId(p)) == Au_ObjNtk(p)->nTravIds); } +static inline int Au_ObjIsTravIdPrevious( Au_Obj_t * p ) { return (Vec_IntGetEntry(&Au_ObjNtk(p)->vTravIds, Au_ObjId(p)) == Au_ObjNtk(p)->nTravIds-1); } +static inline void Au_ObjSetTravIdCurrentId( Au_Ntk_t * p, int Id ) { Vec_IntSetEntry(&p->vTravIds, Id, p->nTravIds ); } +static inline int Au_ObjIsTravIdCurrentId( Au_Ntk_t * p, int Id ) { return (Vec_IntGetEntry(&p->vTravIds, Id) == p->nTravIds); } + +#define Au_ManForEachNtk( p, pNtk, i ) \ + for ( i = 1; (i < Vec_PtrSize(&p->vNtks)) && (((pNtk) = Au_ManNtk(p, i)), 1); i++ ) +#define Au_ManForEachNtkReverse( p, pNtk, i ) \ + for ( i = Vec_PtrSize(&p->vNtks) - 1;(i>=1) && (((pNtk) = Au_ManNtk(p, i)), 1); i-- ) + +#define Au_ObjForEachFaninId( pObj, hFanin, i ) \ + for ( i = 0; (i < Au_ObjFaninNum(pObj)) && (((hFanin) = Au_ObjFaninId(pObj, i)), 1); i++ ) +#define Au_BoxForEachFanoutId( pObj, hFanout, i) \ + for ( i = 0; (i < Au_BoxFanoutNum(pObj)) && (((hFanout) = Au_BoxFanoutId(pObj, i)), 1); i++ ) + +#define Au_ObjForEachFanin( pObj, pFanin, i ) \ + for ( i = 0; (i < Au_ObjFaninNum(pObj)) && (((pFanin) = Au_ObjFanin(pObj, i)), 1); i++ ) +#define Au_BoxForEachFanout( pObj, pFanout, i) \ + for ( i = 0; (i < Au_BoxFanoutNum(pObj)) && (((pFanout) = Au_BoxFanout(pObj, i)), 1); i++ ) + +#define Au_NtkForEachPi( p, pObj, i ) \ + for ( i = 0; (i < Vec_IntSize(&p->vPis)) && (((pObj) = Au_NtkPi(p, i)), 1); i++ ) +#define Au_NtkForEachPo( p, pObj, i ) \ + for ( i = 0; (i < Vec_IntSize(&p->vPos)) && (((pObj) = Au_NtkPo(p, i)), 1); i++ ) +#define Au_NtkForEachObj( p, pObj, i ) \ + for ( i = 0; (i < Vec_IntSize(&p->vObjs)) && (((pObj) = Au_NtkObjI(p, i)), 1); i++ ) +#define Au_NtkForEachNode( p, pObj, i ) \ + for ( i = 0; (i < Vec_IntSize(&p->vObjs)) && (((pObj) = Au_NtkObjI(p, i)), 1); i++ ) if ( !Au_ObjIsNode(pObj) ) {} else +#define Au_NtkForEachBox( p, pObj, i ) \ + for ( i = 0; (i < Vec_IntSize(&p->vObjs)) && (((pObj) = Au_NtkObjI(p, i)), 1); i++ ) if ( !Au_ObjIsBox(pObj) ) {} else + + + +extern void Au_ManAddNtk( Au_Man_t * pMan, Au_Ntk_t * p ); +extern void Au_ManFree( Au_Man_t * p ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Working with models.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Au_Ntk_t * Au_NtkAlloc( Au_Man_t * pMan, char * pName ) +{ + Au_Ntk_t * p; + p = ABC_CALLOC( Au_Ntk_t, 1 ); + p->pName = Au_UtilStrsav( pName ); + p->vChunks = Vec_PtrAlloc( 111 ); + Vec_IntGrow( &p->vPis, 111 ); + Vec_IntGrow( &p->vPos, 111 ); + Vec_IntGrow( &p->vObjs, 1111 ); + Vec_PtrGrow( &p->vPages, 11 ); + Au_ManAddNtk( pMan, p ); + return p; +} +void Au_NtkFree( Au_Ntk_t * p ) +{ + Au_ManFree( p->pMan ); + Vec_PtrFreeFree( p->vChunks ); + ABC_FREE( p->vCopies.pArray ); + ABC_FREE( p->vPages.pArray ); + ABC_FREE( p->vObjs.pArray ); + ABC_FREE( p->vPis.pArray ); + ABC_FREE( p->vPos.pArray ); + ABC_FREE( p->pHTable ); + ABC_FREE( p->pName ); + ABC_FREE( p ); +} +int Au_NtkMemUsage( Au_Ntk_t * p ) +{ + int Mem = sizeof(Au_Ntk_t); + Mem += 4 * p->vPis.nCap; + Mem += 4 * p->vPos.nCap; + Mem += 4 * p->vObjs.nCap; + Mem += 16 * p->nObjsAlloc; + return Mem; +} +void Au_NtkPrintStats( Au_Ntk_t * p ) +{ + printf( "%-30s:", Au_NtkName(p) ); + printf( " i/o =%6d/%6d", Au_NtkPiNum(p), Au_NtkPoNum(p) ); + if ( Au_NtkFlopNum(p) ) + printf( " lat =%5d", Au_NtkFlopNum(p) ); + printf( " nd =%6d", Au_NtkNodeNum(p) ); +// if ( Au_NtkBoxNum(p) ) + printf( " box =%5d", Au_NtkBoxNum(p) ); + printf( " obj =%7d", Au_NtkObjNum(p) ); +// printf( " max =%7d", Au_NtkObjNumMax(p) ); +// printf( " use =%7d", p->nObjsUsed ); + printf( " %5.1f %%", 100.0 * (Au_NtkObjNumMax(p) - Au_NtkObjNum(p)) / Au_NtkObjNumMax(p) ); + printf( " %6.1f MB", 1.0 * Au_NtkMemUsage(p) / (1 << 20) ); + printf( " %5.1f %%", 100.0 * (p->nObjsAlloc - p->nObjsUsed) / p->nObjsAlloc ); + printf( "\n" ); +} +void Au_NtkCleanCopy( Au_Ntk_t * p ) +{ + Vec_IntFill( &p->vCopies, Au_NtkObjNumMax(p), -1 ); +} +int Au_NtkNodeNumFunc( Au_Ntk_t * p, int Func ) +{ + Au_Obj_t * pObj; + int i, Counter = 0; + if ( p->pMan && p->pMan->pFuncs ) + return 0; + Au_NtkForEachNode( p, pObj, i ) + { + Counter += (pObj->Func == (unsigned)Func); +// printf( "%d ", pObj->Func ); + } +// printf( "\n" ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Working with manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Au_Man_t * Au_ManAlloc( char * pName ) +{ + Au_Man_t * p; + p = ABC_CALLOC( Au_Man_t, 1 ); + p->pName = Au_UtilStrsav( pName ); + Vec_PtrGrow( &p->vNtks, 111 ); + Vec_PtrPush( &p->vNtks, NULL ); + return p; +} +void Au_ManFree( Au_Man_t * p ) +{ + assert( p->nRefs > 0 ); + if ( --p->nRefs > 0 ) + return; + if ( p->pFuncs ) + Abc_NamStop( p->pFuncs ); + ABC_FREE( p->vNtks.pArray ); + ABC_FREE( p->pName ); + ABC_FREE( p ); +} +void Au_ManDelete( Au_Man_t * p ) +{ + Au_Ntk_t * pNtk; + int i; + Au_ManForEachNtk( p, pNtk, i ) + Au_NtkFree( pNtk ); +} +int Au_ManFindNtk( Au_Man_t * p, char * pName ) +{ + Au_Ntk_t * pNtk; + int i; + Au_ManForEachNtk( p, pNtk, i ) + if ( !strcmp(Au_NtkName(pNtk), pName) ) + return i; + return -1; +} +Au_Ntk_t * Au_ManFindNtkP( Au_Man_t * p, char * pName ) +{ + int iNtk = Au_ManFindNtk( p, pName ); + if ( iNtk == -1 ) + return NULL; + return Au_ManNtk( p, iNtk ); +} +void Au_ManAddNtk( Au_Man_t * pMan, Au_Ntk_t * p ) +{ + assert( Au_ManFindNtk(pMan, Au_NtkName(p)) == -1 ); + p->pMan = pMan; pMan->nRefs++; + p->Id = Vec_PtrSize( &pMan->vNtks ); + Vec_PtrPush( &pMan->vNtks, p ); +} +int Au_ManMemUsage( Au_Man_t * p ) +{ + Au_Ntk_t * pNtk; + int i, Mem = 0; + Au_ManForEachNtk( p, pNtk, i ) + Mem += 16 * pNtk->nObjsAlloc; + return Mem; +} +int Au_ManMemUsageUseful( Au_Man_t * p ) +{ + Au_Ntk_t * pNtk; + int i, Mem = 0; + Au_ManForEachNtk( p, pNtk, i ) + Mem += 16 * pNtk->nObjsUsed; + return Mem; +} +void Au_ManPrintStats( Au_Man_t * p ) +{ + Au_Ntk_t * pNtk; + int i; + if ( Vec_PtrSize(&p->vNtks) > 2 ) + printf( "Design %-13s\n", Au_ManName(p) ); + Au_ManForEachNtk( p, pNtk, i ) + Au_NtkPrintStats( pNtk ); + printf( "Different functions = %d. ", p->pFuncs ? Abc_NamObjNumMax(p->pFuncs) : 0 ); + printf( "Memory = %.1f MB", 1.0 * Au_ManMemUsage(p) / (1 << 20) ); + printf( " %5.1f %%", 100.0 * (Au_ManMemUsage(p) - Au_ManMemUsageUseful(p)) / Au_ManMemUsage(p) ); + printf( "\n" ); +// if ( p->pFuncs ) +// Abc_NamPrint( p->pFuncs ); +} + +void Au_ManReorderModels_rec( Au_Ntk_t * pNtk, Vec_Int_t * vOrder ) +{ + Au_Ntk_t * pBoxModel; + Au_Obj_t * pObj; + int k; + if ( pNtk->fMark ) + return; + pNtk->fMark = 1; + Au_NtkForEachBox( pNtk, pObj, k ) + { + pBoxModel = Au_ObjModel(pObj); + if ( pBoxModel == NULL || pBoxModel == pNtk ) + continue; + Au_ManReorderModels_rec( pBoxModel, vOrder ); + } + Vec_IntPush( vOrder, pNtk->Id ); +} +void Au_ManReorderModels( Au_Man_t * p, Au_Ntk_t * pRoot ) +{ + Vec_Ptr_t * vNtksNew; + Vec_Int_t * vOrder, * vTemp; + Au_Ntk_t * pNtk, * pBoxModel; + Au_Obj_t * pBox, * pFan; + int i, k, j, Entry; + Au_ManForEachNtk( p, pNtk, i ) + pNtk->fMark = 0; + // collect networks in the DFS order + vOrder = Vec_IntAlloc( Au_ManNtkNum(p)+1 ); + Vec_IntPush( vOrder, 0 ); + Au_ManReorderModels_rec( pRoot, vOrder ); + assert( Vec_IntEntryLast(vOrder) == pRoot->Id ); + // add unconnected ones + Vec_IntPop( vOrder ); + Au_ManForEachNtk( p, pNtk, i ) + if ( pNtk->fMark == 0 ) + Vec_IntPush( vOrder, pNtk->Id ); + Vec_IntPush( vOrder, pRoot->Id ); + assert( Vec_IntSize(vOrder) == Au_ManNtkNum(p)+1 ); + // reverse order + vOrder->nSize--; + vOrder->pArray++; + Vec_IntReverseOrder( vOrder ); + vOrder->pArray--; + vOrder->nSize++; + // compute new order + vNtksNew = Vec_PtrAlloc( Au_ManNtkNum(p)+1 ); + Vec_IntForEachEntry( vOrder, Entry, i ) + Vec_PtrPush( vNtksNew, Au_ManNtk(p, Entry) ); + // invert order + assert( Vec_IntEntry(vOrder, 1) == pRoot->Id ); + vOrder = Vec_IntInvert( vTemp = vOrder, 0 ); + Vec_IntFree( vTemp ); + assert( Vec_IntEntry(vOrder, 1) == pRoot->Id ); + // update model numbers + Au_ManForEachNtk( p, pNtk, i ) + { + pNtk->Id = Vec_IntEntry( vOrder, pNtk->Id ); + Au_NtkForEachBox( pNtk, pBox, k ) + { + pBox->Func = Vec_IntEntry( vOrder, pBox->Func ); + assert( pBox->Func > 0 ); + Au_BoxForEachFanout( pBox, pFan, j ) + pFan->Func = pBox->Func; + } + } + // update + ABC_FREE( p->vNtks.pArray ); + p->vNtks.pArray = vNtksNew->pArray; + vNtksNew->pArray = NULL; + Vec_PtrFree( vNtksNew ); + // verify + Au_ManForEachNtk( p, pNtk, i ) + Au_NtkForEachBox( pNtk, pBox, k ) + { + pBoxModel = Au_ObjModel(pBox); + if ( pBoxModel == NULL || pBoxModel == pNtk ) + continue; + assert( !pBox->Func || pBox->Func >= (unsigned)pNtk->Id ); + assert( Au_ObjFaninNum(pBox) == Au_NtkPiNum(pBoxModel) ); + assert( Au_BoxFanoutNum(pBox) == Au_NtkPoNum(pBoxModel) ); + } + Vec_IntFree( vOrder ); +} +void Au_ManCountThings( Au_Man_t * p ) +{ + Au_Ntk_t * pNtk, * pBoxModel; + Au_Obj_t * pBox; + int i, k;//, clk = Abc_Clock(); + Au_ManForEachNtkReverse( p, pNtk, i ) + { + pNtk->nBoxes = Au_NtkBoxNum(pNtk); + pNtk->nNodes = Au_NtkNodeNum(pNtk); + pNtk->nPorts = Au_NtkPiNum(pNtk) + Au_NtkPoNum(pNtk); + pNtk->nNodeAnds = Au_NtkNodeNumFunc( pNtk, 1 ); + pNtk->nNodeXors = Au_NtkNodeNumFunc( pNtk, 2 ); + pNtk->nNodeMuxs = Au_NtkNodeNumFunc( pNtk, 3 ); +// assert( pNtk->nNodes == pNtk->nNodeAnds + pNtk->nNodeXors + pNtk->nNodeMuxs ); +// printf( "adding %.0f nodes of model %s\n", pNtk->nNodes, Au_NtkName(pNtk) ); + Au_NtkForEachBox( pNtk, pBox, k ) + { + pBoxModel = Au_ObjModel(pBox); + if ( pBoxModel == NULL || pBoxModel == pNtk ) + continue; + assert( Au_ObjFaninNum(pBox) == Au_NtkPiNum(pBoxModel) ); + assert( Au_BoxFanoutNum(pBox) == Au_NtkPoNum(pBoxModel) ); + assert( pBoxModel->Id > pNtk->Id ); + assert( pBoxModel->nPorts > 0 ); + pNtk->nBoxes += pBoxModel->nBoxes; + pNtk->nNodes += pBoxModel->nNodes; + pNtk->nPorts += pBoxModel->nPorts; + pNtk->nNodeAnds += pBoxModel->nNodeAnds; + pNtk->nNodeXors += pBoxModel->nNodeXors; + pNtk->nNodeMuxs += pBoxModel->nNodeMuxs; +// printf( " adding %.0f nodes of model %s\n", pBoxModel->nNodes, Au_NtkName(pBoxModel) ); + } +// printf( "total %.0f nodes in model %s\n", pNtk->nNodes, Au_NtkName(pNtk) ); + } + pNtk = Au_ManNtkRoot(p); + printf( "Total nodes = %15.0f. Total instances = %15.0f. Total ports = %15.0f.\n", +// printf( "Total nodes = %.2e. Total instances = %.2e. Total ports = %.2e.\n", + pNtk->nNodes, pNtk->nBoxes, pNtk->nPorts ); +// printf( "Total ANDs = %15.0f. Total XORs = %15.0f. Total MUXes = %15.0f.\n", +// printf( "Total ANDs = %.2e. Total XORs = %.2e. Total MUXes = %.2e. ", +// pNtk->nNodeAnds, pNtk->nNodeXors, pNtk->nNodeMuxs ); + printf( "Total ANDs = %15.0f.\n", pNtk->nNodeAnds ); + printf( "Total XORs = %15.0f.\n", pNtk->nNodeXors ); + printf( "Total MUXes = %15.0f.\n", pNtk->nNodeMuxs ); +// Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} + +int Au_NtkCompareNames( Au_Ntk_t ** p1, Au_Ntk_t ** p2 ) +{ + return strcmp( Au_NtkName(*p1), Au_NtkName(*p2) ); +} +void Au_ManPrintBoxInfo( Au_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vMods; + Au_Ntk_t * pModel, * pBoxModel; + Au_Obj_t * pObj; + Vec_Int_t * vCounts; + int i, k, Num; + if ( pNtk->pMan == NULL ) + { + printf( "There is no hierarchy information.\n" ); + return; + } + vMods = &pNtk->pMan->vNtks; + +/* + vMods->nSize--; + vMods->pArray++; + // sort models by name + Vec_PtrSort( vMods, (int(*)(const void *, const void *))Au_NtkCompareNames ); + // swap the first model + Num = Vec_PtrFind( vMods, pNtk ); + assert( Num >= 0 && Num < Vec_PtrSize(vMods) ); + pBoxModel = (Au_Ntk_t *)Vec_PtrEntry(vMods, 0); + Vec_PtrWriteEntry(vMods, 0, (Au_Ntk_t *)Vec_PtrEntry(vMods, Num) ); + Vec_PtrWriteEntry(vMods, Num, pBoxModel ); + vMods->pArray--; + vMods->nSize++; +*/ + +// Vec_PtrForEachEntry( Au_Ntk_t *, vMods, pModel, i ) +// printf( "%s\n", Au_NtkName(pModel) ); + + // print models + vCounts = Vec_IntStart( Vec_PtrSize(vMods) ); + Vec_PtrForEachEntryStart( Au_Ntk_t *, vMods, pModel, i, 1 ) + { + if ( Au_NtkBoxNum(pModel) == 0 ) + continue; + Vec_IntFill( vCounts, Vec_IntSize(vCounts), 0 ); + Au_NtkForEachBox( pModel, pObj, k ) + { + pBoxModel = Au_ObjModel(pObj); + if ( pBoxModel == NULL || pBoxModel == pModel ) + continue; + Num = Vec_PtrFind( vMods, pBoxModel ); + assert( Num >= 0 && Num < Vec_PtrSize(vMods) ); + Vec_IntAddToEntry( vCounts, Num, 1 ); + } + +// Au_NtkPrintStats( pModel, 0, 0, 0, 0, 0, 0, 0 ); + printf( "MODULE " ); + printf( "%-30s : ", Au_NtkName(pModel) ); + printf( "PI=%6d ", Au_NtkPiNum(pModel) ); + printf( "PO=%6d ", Au_NtkPoNum(pModel) ); + printf( "BB=%6d ", Au_NtkBoxNum(pModel) ); + printf( "ND=%6d ", Au_NtkNodeNum(pModel) ); // sans constants +// printf( "Lev=%5d ", Au_NtkLevel(pModel) ); + printf( "\n" ); + + Vec_IntForEachEntry( vCounts, Num, k ) + if ( Num ) + printf( "%15d : %s\n", Num, Au_NtkName((Au_Ntk_t *)Vec_PtrEntry(vMods, k)) ); + } + Vec_IntFree( vCounts ); + Vec_PtrForEachEntryStart( Au_Ntk_t *, vMods, pModel, i, 1 ) + { + if ( Au_NtkBoxNum(pModel) != 0 ) + continue; + printf( "MODULE " ); + printf( "%-30s : ", Au_NtkName(pModel) ); + printf( "PI=%6d ", Au_NtkPiNum(pModel) ); + printf( "PO=%6d ", Au_NtkPoNum(pModel) ); + printf( "BB=%6d ", Au_NtkBoxNum(pModel) ); + printf( "ND=%6d ", Au_NtkNodeNum(pModel) ); +// printf( "Lev=%5d ", Au_NtkLevel(pModel) ); + printf( "\n" ); + } +} +int Au_NtkCompareSign( Au_Ntk_t ** p1, Au_Ntk_t ** p2 ) +{ + if ( Au_NtkPiNum(*p1) - Au_NtkPiNum(*p2) != 0 ) + return Au_NtkPiNum(*p1) - Au_NtkPiNum(*p2); + else + return Au_NtkPoNum(*p1) - Au_NtkPoNum(*p2); +} +void Au_ManPrintBoxInfoSorted( Au_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vMods, * vModsNew; + Au_Ntk_t * pModel; + int i; + if ( pNtk->pMan == NULL ) + { + printf( "There is no hierarchy information.\n" ); + return; + } + vMods = &pNtk->pMan->vNtks; + + vMods->nSize--; + vMods->pArray++; + vModsNew = Vec_PtrDup( vMods ); + vMods->pArray--; + vMods->nSize++; + + Vec_PtrSort( vModsNew, (int(*)(const void *, const void *))Au_NtkCompareSign ); + Vec_PtrForEachEntryStart( Au_Ntk_t *, vModsNew, pModel, i, 1 ) + { + printf( "MODULE " ); + printf( "%-30s : ", Au_NtkName(pModel) ); + printf( "PI=%6d ", Au_NtkPiNum(pModel) ); + printf( "PO=%6d ", Au_NtkPoNum(pModel) ); + printf( "BB=%6d ", Au_NtkBoxNum(pModel) ); + printf( "ND=%6d ", Au_NtkNodeNum(pModel) ); + printf( "\n" ); + } + Vec_PtrFree( vModsNew ); +} + +int Au_NtkCheckRecursive( Au_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vMods; + Au_Ntk_t * pModel; + Au_Obj_t * pObj; + int i, k, RetValue = 0; + + if ( pNtk->pMan == NULL ) + { + printf( "There is no hierarchy information.\n" ); + return RetValue; + } + + vMods = &pNtk->pMan->vNtks; + Vec_PtrForEachEntryStart( Au_Ntk_t *, vMods, pModel, i, 1 ) + { + Au_NtkForEachObj( pModel, pObj, k ) + if ( Au_ObjIsBox(pObj) && Au_ObjModel(pObj) == pModel ) + { + printf( "WARNING: Model \"%s\" contains a recursive definition.\n", Au_NtkName(pModel) ); + RetValue = 1; + break; + } + } + return RetValue; +} + +// count the number of support variables +int Au_ObjSuppSize_rec( Au_Ntk_t * p, int Id ) +{ + Au_Obj_t * pObj; + int i, iFanin, Counter = 0; + if ( Au_ObjIsTravIdCurrentId(p, Id) ) + return 0; + Au_ObjSetTravIdCurrentId(p, Id); + pObj = Au_NtkObj( p, Id ); + if ( Au_ObjIsPi(pObj) ) + return 1; + assert( Au_ObjIsNode(pObj) || Au_ObjIsBox(pObj) || Au_ObjIsFan(pObj) ); + Au_ObjForEachFaninId( pObj, iFanin, i ) + Counter += Au_ObjSuppSize_rec( p, iFanin ); + return Counter; +} +int Au_ObjSuppSize( Au_Obj_t * pObj ) +{ + Au_Ntk_t * p = Au_ObjNtk(pObj); + Au_NtkIncrementTravId( p ); + return Au_ObjSuppSize_rec( p, Au_ObjId(pObj) ); +} +/* +// this version is 50% slower than above +int Au_ObjSuppSize_rec( Au_Obj_t * pObj ) +{ + Au_Obj_t * pFanin; + int i, Counter = 0; + if ( Au_ObjIsTravIdCurrent(pObj) ) + return 0; + Au_ObjSetTravIdCurrent(pObj); + if ( Au_ObjIsPi(pObj) ) + return 1; + assert( Au_ObjIsNode(pObj) || Au_ObjIsBox(pObj) || Au_ObjIsFan(pObj) ); + Au_ObjForEachFanin( pObj, pFanin, i ) + Counter += Au_ObjSuppSize_rec( pFanin ); + return Counter; +} +int Au_ObjSuppSize( Au_Obj_t * pObj ) +{ + Au_NtkIncrementTravId( Au_ObjNtk(pObj) ); + return Au_ObjSuppSize_rec( pObj ); +} +*/ +int Au_NtkSuppSizeTest( Au_Ntk_t * p ) +{ + Au_Obj_t * pObj; + int i, Counter = 0; + Au_NtkForEachObj( p, pObj, i ) + if ( Au_ObjIsNode(pObj) ) + Counter += (Au_ObjSuppSize(pObj) <= 16); + printf( "Nodes with small support %d (out of %d)\n", Counter, Au_NtkNodeNum(p) ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns memory for the next object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Au_NtkInsertHeader( Au_Ntk_t * p ) +{ + Au_Obj_t * pMem = (Au_Obj_t *)Vec_PtrEntryLast( &p->vPages ); + assert( (((ABC_PTRINT_T)(pMem + p->iHandle) & 0x3FF) >> 4) == 0 ); + ((Au_Ntk_t **)(pMem + p->iHandle))[0] = p; + ((int *)(pMem + p->iHandle))[2] = ((Vec_PtrSize(&p->vPages) - 1) << 12) | (p->iHandle & 0xFC0); + p->iHandle++; +} +int Au_NtkAllocObj( Au_Ntk_t * p, int nFanins, int Type ) +{ + Au_Obj_t * pMem, * pObj, * pTemp; + int nObjInt = ((2+nFanins) >> 2) + (((2+nFanins) & 3) > 0); + int Id, nObjIntReal = nObjInt; + if ( nObjInt > 63 ) + nObjInt = 63 + 64 * (((nObjInt-63) >> 6) + (((nObjInt-63) & 63) > 0)); + if ( Vec_PtrSize(&p->vPages) == 0 || p->iHandle + nObjInt > (1 << 12) ) + { + if ( nObjInt + 64 > (1 << 12) ) + pMem = ABC_CALLOC( Au_Obj_t, nObjInt + 64 ), p->nObjsAlloc += nObjInt + 64; + else + pMem = ABC_CALLOC( Au_Obj_t, (1 << 12) + 64 ), p->nObjsAlloc += (1 << 12) + 64; + Vec_PtrPush( p->vChunks, pMem ); + if ( ((ABC_PTRINT_T)pMem & 0xF) ) + pMem = (Au_Obj_t *)((char *)pMem + 16 - ((ABC_PTRINT_T)pMem & 0xF)); + assert( ((ABC_PTRINT_T)pMem & 0xF) == 0 ); + p->iHandle = (((ABC_PTRINT_T)pMem & 0x3FF) >> 4); + if ( p->iHandle ) + { + pMem += 64 - (p->iHandle & 63); + p->iHandle = 0; + } + Vec_PtrPush( &p->vPages, pMem ); + Au_NtkInsertHeader( p ); + } + else + { + pMem = (Au_Obj_t *)Vec_PtrEntryLast( &p->vPages ); + if ( (p->iHandle & 63) == 0 || nObjInt > (64 - (p->iHandle & 63)) ) + { + if ( p->iHandle & 63 ) + p->iHandle += 64 - (p->iHandle & 63); + Au_NtkInsertHeader( p ); + } + if ( p->iHandle + nObjInt > (1 << 12) ) + return Au_NtkAllocObj( p, nFanins, Type ); + } + pObj = pMem + p->iHandle; + assert( *((int *)pObj) == 0 ); + pObj->nFanins = nFanins; + p->nObjs[pObj->Type = Type]++; + if ( Type == AU_OBJ_PI ) + { + Au_ObjSetFaninLit( pObj, 0, Vec_IntSize(&p->vPis) ); + Vec_IntPush( &p->vPis, Au_ObjId(pObj) ); + } + else if ( Type == AU_OBJ_PO ) + { + Au_ObjSetFaninLit( pObj, 1, Vec_IntSize(&p->vPos) ); + Vec_IntPush( &p->vPos, Au_ObjId(pObj) ); + } + p->iHandle += nObjInt; + p->nObjsUsed += nObjIntReal; + + Id = Au_ObjId(pObj); + Vec_IntPush( &p->vObjs, Id ); + pTemp = Au_NtkObj( p, Id ); + assert( pTemp == pObj ); + return Id; +} +int Au_NtkCreateConst0( Au_Ntk_t * pNtk ) +{ + return Au_NtkAllocObj( pNtk, 0, AU_OBJ_CONST0 ); +} +int Au_NtkCreatePi( Au_Ntk_t * pNtk ) +{ + return Au_NtkAllocObj( pNtk, 0, AU_OBJ_PI ); +} +int Au_NtkCreatePo( Au_Ntk_t * pNtk, int iFanin ) +{ + int Id = Au_NtkAllocObj( pNtk, 1, AU_OBJ_PO ); + if ( iFanin ) + Au_ObjSetFaninLit( Au_NtkObj(pNtk, Id), 0, iFanin ); + return Id; +} +int Au_NtkCreateFan( Au_Ntk_t * pNtk, int iFanin, int iFanout, int iModel ) +{ + int Id = Au_NtkAllocObj( pNtk, 1, AU_OBJ_FAN ); + Au_Obj_t * p = Au_NtkObj( pNtk, Id ); + if ( iFanin ) + Au_ObjSetFaninLit( p, 0, iFanin ); + Au_ObjSetFaninLit( p, 1, iFanout ); + p->Func = iModel; + return Id; +} +int Au_NtkCreateNode( Au_Ntk_t * pNtk, Vec_Int_t * vFanins, int iFunc ) +{ + int i, iFanin; + int Id = Au_NtkAllocObj( pNtk, Vec_IntSize(vFanins), AU_OBJ_NODE ); + Au_Obj_t * p = Au_NtkObj( pNtk, Id ); + Vec_IntForEachEntry( vFanins, iFanin, i ) + Au_ObjSetFaninLit( p, i, iFanin ); + p->Func = iFunc; + return Id; +} +int Au_NtkCreateBox( Au_Ntk_t * pNtk, Vec_Int_t * vFanins, int nFanouts, int iModel ) +{ + int i, iFanin, nFanins = Vec_IntSize(vFanins); + int Id = Au_NtkAllocObj( pNtk, nFanins + 1 + nFanouts, AU_OBJ_BOX ); + Au_Obj_t * p = Au_NtkObj( pNtk, Id ); + Vec_IntForEachEntry( vFanins, iFanin, i ) + Au_ObjSetFaninLit( p, i, iFanin ); + Au_ObjSetFaninLit( p, nFanins, nFanouts ); + for ( i = 0; i < nFanouts; i++ ) + Au_ObjSetFaninLit( p, nFanins + 1 + i, Au_NtkCreateFan(pNtk, Au_Var2Lit(Id,0), i, iModel) ); + p->nFanins = nFanins; + p->Func = iModel; + assert( iModel > 0 ); + return Id; +} + +/* + * 0/1 would denote false/true respectively. + * Signals would be even numbers, and negation would be handled by xor with 1. + * The output signal for each gate or subckt could be implicitly generated just use the next signal number. + * For ranges, we could use "start:cnt" to denote the sequence "start, start+2, ..., start + 2*(cnt- 1)". + - "cnt" seems more intuitive when signals are restricted to even numbers. + * We'd have subckts and specialized gates .and, .xor, and .mux. + +Here is a small example: + +.model test +.inputs 3 # Inputs 2 4 6 +.subckt and3 3 1 2:3 # 8 is implicit output +.outputs 1 8 +.end + +.model and3 +.inputs 3 # Inputs 2 4 6 +.and 2 4 # 8 output +.and 6 8 # 10 output +.outputs 1 10 +.end +*/ + +/**Function************************************************************* + + Synopsis [Reads one entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Au_NtkRemapNum( Vec_Int_t * vNum2Obj, int Num ) +{ + return Au_Var2Lit(Vec_IntEntry(vNum2Obj, Au_Lit2Var(Num)), Au_LitIsCompl(Num)); +} +/**Function************************************************************* + + Synopsis [Reads one entry.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline void Au_NtkParseCBlifNum( Vec_Int_t * vFanins, char * pToken, Vec_Int_t * vNum2Obj ) +{ + char * pCur; + int Num1, Num2, i; + assert( pToken[0] >= '0' && pToken[0] <= '9' ); + Num1 = atoi( pToken ); + for ( pCur = pToken; *pCur; pCur++ ) + if ( *pCur == ':' ) + { + Num2 = atoi( pCur+1 ); + for ( i = 0; i < Num2; i++ ) + Vec_IntPush( vFanins, Au_NtkRemapNum(vNum2Obj, Num1 + i + i) ); + return; + } + else if ( *pCur == '*' ) + { + Num2 = atoi( pCur+1 ); + for ( i = 0; i < Num2; i++ ) + Vec_IntPush( vFanins, Au_NtkRemapNum(vNum2Obj, Num1) ); + return; + } + assert( *pCur == 0 ); + Vec_IntPush( vFanins, Au_NtkRemapNum(vNum2Obj, Num1) ); +} + +/**Function************************************************************* + + Synopsis [Parses CBLIF file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Au_Ntk_t * Au_NtkParseCBlif( char * pFileName ) +{ + FILE * pFile; + Au_Man_t * pMan; + Au_Ntk_t * pRoot = NULL; + Au_Obj_t * pBox, * pFan; + char * pBuffer, * pCur; + Vec_Int_t * vLines, * vNum2Obj, * vFanins; + int i, k, j, Id, nInputs, nOutputs; + int Line, Num, Func; + // read the file + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\".\n", pFileName ); + return NULL; + } + pBuffer = Extra_FileRead( pFile ); + fclose( pFile ); + // split into lines + vLines = Vec_IntAlloc( 1000 ); + Vec_IntPush( vLines, 0 ); + for ( pCur = pBuffer; *pCur; pCur++ ) + if ( *pCur == '\n' ) + { + *pCur = 0; + Vec_IntPush( vLines, pCur - pBuffer + 1 ); + } + // start the manager + pMan = Au_ManAlloc( pFileName ); + // parse the lines + vNum2Obj = Vec_IntAlloc( 1000 ); + vFanins = Vec_IntAlloc( 1000 ); + Vec_IntForEachEntry( vLines, Line, i ) + { + pCur = strtok( pBuffer + Line, " \t\r" ); + if ( pCur == NULL || *pCur == '#' ) + continue; + if ( *pCur != '.' ) + { + printf( "Cannot read directive in line %d: \"%s\".\n", i, pBuffer + Line ); + continue; + } + Vec_IntClear( vFanins ); + if ( !strcmp(pCur, ".and") ) + { + for ( k = 0; k < 2; k++ ) + { + pCur = strtok( NULL, " \t\r" ); + Num = atoi( pCur ); + Vec_IntPush( vFanins, Au_NtkRemapNum(vNum2Obj, Num) ); + } + Id = Au_NtkCreateNode( pRoot, vFanins, 1 ); + Vec_IntPush( vNum2Obj, Id ); + } + else if ( !strcmp(pCur, ".xor") ) + { + for ( k = 0; k < 2; k++ ) + { + pCur = strtok( NULL, " \t\r" ); + Num = atoi( pCur ); + Vec_IntPush( vFanins, Au_NtkRemapNum(vNum2Obj, Num) ); + } + Id = Au_NtkCreateNode( pRoot, vFanins, 2 ); + Vec_IntPush( vNum2Obj, Id ); + } + else if ( !strcmp(pCur, ".mux") ) + { + for ( k = 0; k < 3; k++ ) + { + pCur = strtok( NULL, " \t\r" ); + Num = atoi( pCur ); + Vec_IntPush( vFanins, Au_NtkRemapNum(vNum2Obj, Num) ); + } + Id = Au_NtkCreateNode( pRoot, vFanins, 3 ); + Vec_IntPush( vNum2Obj, Id ); + } + else if ( !strcmp(pCur, ".subckt") ) + { + pCur = strtok( NULL, " \t\r" ); + Func = pCur - pBuffer; + pCur = strtok( NULL, " \t\r" ); + nInputs = atoi( pCur ); + pCur = strtok( NULL, " \t\r" ); + nOutputs = atoi( pCur ); + while ( 1 ) + { + pCur = strtok( NULL, " \t\r" ); + if ( pCur == NULL || *pCur == '#' ) + break; + Au_NtkParseCBlifNum( vFanins, pCur, vNum2Obj ); + } + assert( Vec_IntSize(vFanins) == nInputs ); + Id = Au_NtkCreateBox( pRoot, vFanins, nOutputs, Func ); + pBox = Au_NtkObj( pRoot, Id ); + Au_BoxForEachFanoutId( pBox, Num, k ) + Vec_IntPush( vNum2Obj, Num ); + } + else if ( !strcmp(pCur, ".model") ) + { + pCur = strtok( NULL, " \t\r" ); + pRoot = Au_NtkAlloc( pMan, pCur ); + Id = Au_NtkCreateConst0( pRoot ); + Vec_IntClear( vNum2Obj ); + Vec_IntPush( vNum2Obj, Id ); + } + else if ( !strcmp(pCur, ".inputs") ) + { + pCur = strtok( NULL, " \t\r" ); + Num = atoi( pCur ); + for ( k = 0; k < Num; k++ ) + Vec_IntPush( vNum2Obj, Au_NtkCreatePi(pRoot) ); + } + else if ( !strcmp(pCur, ".outputs") ) + { + pCur = strtok( NULL, " \t\r" ); + nOutputs = atoi( pCur ); + while ( 1 ) + { + pCur = strtok( NULL, " \t\r" ); + if ( pCur == NULL || *pCur == '#' ) + break; + Au_NtkParseCBlifNum( vFanins, pCur, vNum2Obj ); + } + assert( Vec_IntSize(vFanins) == nOutputs ); + Vec_IntForEachEntry( vFanins, Num, k ) + Au_NtkCreatePo( pRoot, Num ); + } + else if ( strcmp(pCur, ".end") ) + printf( "Unknown directive in line %d: \"%s\".\n", i, pBuffer + Line ); + } + Vec_IntFree( vFanins ); + Vec_IntFree( vNum2Obj ); + Vec_IntFree( vLines ); + // set pointers to models + Au_ManForEachNtk( pMan, pRoot, i ) + Au_NtkForEachBox( pRoot, pBox, k ) + { + pBox->Func = Au_ManFindNtk( pMan, pBuffer + pBox->Func ); + assert( pBox->Func > 0 ); + Au_BoxForEachFanout( pBox, pFan, j ) + pFan->Func = pBox->Func; + } + ABC_FREE( pBuffer ); + // order models in topological order + pRoot = Au_ManNtkRoot( pMan ); + Au_ManReorderModels( pMan, pRoot ); + return pRoot; +} + +ABC_NAMESPACE_IMPL_END + +#include "abc.h" +#include "aig/gia/gia.h" + +ABC_NAMESPACE_IMPL_START + +extern Vec_Ptr_t * Abc_NtkDfsBoxes( Abc_Ntk_t * pNtk ); +extern int Abc_NtkDeriveFlatGiaSop( Gia_Man_t * pGia, int * gFanins, char * pSop ); +extern int Abc_NtkCheckRecursive( Abc_Ntk_t * pNtk ); + +/**Function************************************************************* + + Synopsis [Flattens the logic hierarchy of the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Au_NtkDeriveFlatGia_rec( Gia_Man_t * pGia, Au_Ntk_t * p ) +{ + Au_Obj_t * pObj, * pTerm; + int i, k, Lit = 0; + Au_NtkForEachPi( p, pTerm, i ) + assert( Au_ObjCopy(pTerm) >= 0 ); + if ( strcmp(Au_NtkName(p), "ref_egcd") == 0 ) + { + printf( "Replacing one instance of recursive model \"%s\" by a black box.\n", "ref_egcd" ); + Au_NtkForEachPo( p, pTerm, i ) + Au_ObjSetCopy( pTerm, Gia_ManAppendCi(pGia) ); + return; + } + Au_NtkForEachObj( p, pObj, i ) + { + if ( Au_ObjIsNode(pObj) ) + { + if ( p->pMan->pFuncs ) + { + int gFanins[16]; + char * pSop = Abc_NamStr( p->pMan->pFuncs, pObj->Func ); + assert( Au_ObjFaninNum(pObj) <= 16 ); + assert( Au_ObjFaninNum(pObj) == Abc_SopGetVarNum(pSop) ); + Au_ObjForEachFanin( pObj, pTerm, k ) + { + gFanins[k] = Au_ObjCopy(pTerm); + assert( gFanins[k] >= 0 ); + } + Lit = Abc_NtkDeriveFlatGiaSop( pGia, gFanins, pSop ); + } + else + { + int Lit0, Lit1, Lit2; + assert( pObj->Func >= 1 && pObj->Func <= 3 ); + Lit0 = Abc_LitNotCond( Au_ObjCopy(Au_ObjFanin0(pObj)), Au_ObjFaninC0(pObj) ); + Lit1 = Abc_LitNotCond( Au_ObjCopy(Au_ObjFanin1(pObj)), Au_ObjFaninC1(pObj) ); + if ( pObj->Func == 1 ) + Lit = Gia_ManHashAnd( pGia, Lit0, Lit1 ); + else if ( pObj->Func == 2 ) + Lit = Gia_ManHashXor( pGia, Lit0, Lit1 ); + else if ( pObj->Func == 3 ) + { + Lit2 = Abc_LitNotCond( Au_ObjCopy(Au_ObjFanin2(pObj)), Au_ObjFaninC2(pObj) ); + Lit = Gia_ManHashMux( pGia, Lit0, Lit1, Lit2 ); + } + else assert( 0 ); + } + assert( Lit >= 0 ); + Au_ObjSetCopy( pObj, Lit ); + } + else if ( Au_ObjIsBox(pObj) ) + { + Au_Ntk_t * pModel = Au_ObjModel(pObj); + Au_NtkCleanCopy( pModel ); + // check the match between the number of actual and formal parameters + assert( Au_ObjFaninNum(pObj) == Au_NtkPiNum(pModel) ); + assert( Au_BoxFanoutNum(pObj) == Au_NtkPoNum(pModel) ); + // assign PIs + Au_ObjForEachFanin( pObj, pTerm, k ) + Au_ObjSetCopy( Au_NtkPi(pModel, k), Au_ObjCopy(pTerm) ); + // call recursively + Au_NtkDeriveFlatGia_rec( pGia, pModel ); + // assign POs + Au_BoxForEachFanout( pObj, pTerm, k ) + Au_ObjSetCopy( pTerm, Au_ObjCopy(Au_NtkPo(pModel, k)) ); + } + else if ( Au_ObjIsConst0(pObj) ) + Au_ObjSetCopy( pObj, 0 ); + + } + Au_NtkForEachPo( p, pTerm, i ) + { + Lit = Abc_LitNotCond( Au_ObjCopy(Au_ObjFanin0(pTerm)), Au_ObjFaninC0(pTerm) ); + Au_ObjSetCopy( pTerm, Lit ); + } + Au_NtkForEachPo( p, pTerm, i ) + assert( Au_ObjCopy(pTerm) >= 0 ); +// p->pMan->nGiaObjMax = Abc_MaxInt( p->pMan->nGiaObjMax, Gia_ManObjNum(pGia) ); +} + +/**Function************************************************************* + + Synopsis [Flattens the logic hierarchy of the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Au_NtkDeriveFlatGia( Au_Ntk_t * p ) +{ + Gia_Man_t * pTemp, * pGia = NULL; + Au_Obj_t * pTerm; + int i; + printf( "Collapsing model \"%s\"...\n", Au_NtkName(p) ); + Au_NtkCleanCopy( p ); + // start the network + pGia = Gia_ManStart( (1<<16) ); + pGia->pName = Abc_UtilStrsav( Au_NtkName(p) ); +// pGia->pSpec = Abc_UtilStrsav( Au_NtkSpec(p) ); + Gia_ManHashAlloc( pGia ); + Gia_ManFlipVerbose( pGia ); + // create PIs + Au_NtkForEachPi( p, pTerm, i ) + Au_ObjSetCopy( pTerm, Gia_ManAppendCi(pGia) ); + // recursively flatten hierarchy + Au_NtkDeriveFlatGia_rec( pGia, p ); + // create POs + Au_NtkForEachPo( p, pTerm, i ) + Gia_ManAppendCo( pGia, Au_ObjCopy(pTerm) ); + // prepare return value +// Gia_ManHashProfile( pGia ); + Gia_ManHashStop( pGia ); + Gia_ManSetRegNum( pGia, 0 ); + pGia = Gia_ManCleanup( pTemp = pGia ); + Gia_ManStop( pTemp ); + return pGia; +} + + +// ternary simulation +#define AU_VAL0 1 +#define AU_VAL1 2 +#define AU_VALX 3 + +static inline void Au_ObjSetXsim( Au_Obj_t * pObj, int Value ) { pObj->Value = Value; } +static inline int Au_ObjGetXsim( Au_Obj_t * pObj ) { return pObj->Value; } +static inline int Au_XsimInv( int Value ) +{ + if ( Value == AU_VAL0 ) + return AU_VAL1; + if ( Value == AU_VAL1 ) + return AU_VAL0; + assert( Value == AU_VALX ); + return AU_VALX; +} +static inline int Au_XsimAnd( int Value0, int Value1 ) +{ + if ( Value0 == AU_VAL0 || Value1 == AU_VAL0 ) + return AU_VAL0; + if ( Value0 == AU_VALX || Value1 == AU_VALX ) + return AU_VALX; + assert( Value0 == AU_VAL1 && Value1 == AU_VAL1 ); + return AU_VAL1; +} +static inline int Au_XsimXor( int Value0, int Value1 ) +{ + if ( Value0 == AU_VALX || Value1 == AU_VALX ) + return AU_VALX; + if ( (Value0 == AU_VAL0) == (Value1 == AU_VAL0) ) + return AU_VAL0; + return AU_VAL1; +} +static inline int Au_XsimMux( int ValueC, int Value1, int Value0 ) +{ + if ( ValueC == AU_VAL0 ) + return Value0; + if ( ValueC == AU_VAL1 ) + return Value1; + if ( Value0 == AU_VAL0 && Value1 == AU_VAL0 ) + return AU_VAL0; + if ( Value0 == AU_VAL1 && Value1 == AU_VAL1 ) + return AU_VAL1; + return AU_VALX; +} +static inline int Au_ObjGetXsimFan0( Au_Obj_t * pObj ) +{ + int Value = Au_ObjGetXsim( Au_ObjFanin0(pObj) ); + return Au_ObjFaninC0(pObj) ? Au_XsimInv(Value) : Value; +} +static inline int Au_ObjGetXsimFan1( Au_Obj_t * pObj ) +{ + int Value = Au_ObjGetXsim( Au_ObjFanin1(pObj) ); + return Au_ObjFaninC1(pObj) ? Au_XsimInv(Value) : Value; +} +static inline int Au_ObjGetXsimFan2( Au_Obj_t * pObj ) +{ + int Value = Au_ObjGetXsim( Au_ObjFanin2(pObj) ); + return Au_ObjFaninC2(pObj) ? Au_XsimInv(Value) : Value; +} + +/**Function************************************************************* + + Synopsis [Flattens the logic hierarchy of the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Au_NtkTerSimulate_rec( Au_Ntk_t * p ) +{ + Au_Obj_t * pObj = NULL, * pTerm; + int i, k; + Au_NtkForEachPi( p, pTerm, i ) + { + assert( Au_ObjGetXsim(pTerm) > 0 ); + if ( Au_ObjGetXsim(pTerm) == AU_VALX ) + p->pMan->nPortsNC++; + else if ( Au_ObjGetXsim(pTerm) == AU_VAL0 ) + p->pMan->nPortsC0++; + else + p->pMan->nPortsC1++; + } + if ( strcmp(Au_NtkName(p), "ref_egcd") == 0 ) + { + printf( "Replacing one instance of recursive model \"%s\" by a black box.\n", "ref_egcd" ); + Au_NtkForEachPo( p, pTerm, i ) + Au_ObjSetXsim( pTerm, AU_VALX ); + return; + } + Au_NtkForEachObj( p, pObj, i ) + { + if ( Au_ObjIsNode(pObj) ) + { + if ( pObj->Func == 1 ) + Au_ObjSetXsim( pObj, Au_XsimAnd(Au_ObjGetXsimFan0(pObj), Au_ObjGetXsimFan1(pObj)) ); + else if ( pObj->Func == 2 ) + Au_ObjSetXsim( pObj, Au_XsimXor(Au_ObjGetXsimFan0(pObj), Au_ObjGetXsimFan1(pObj)) ); + else if ( pObj->Func == 3 ) + Au_ObjSetXsim( pObj, Au_XsimMux(Au_ObjGetXsimFan0(pObj), Au_ObjGetXsimFan1(pObj), Au_ObjGetXsimFan2(pObj)) ); + else assert( 0 ); + } + else if ( Au_ObjIsBox(pObj) ) + { + Au_Ntk_t * pModel = Au_ObjModel(pObj); + // check the match between the number of actual and formal parameters + assert( Au_ObjFaninNum(pObj) == Au_NtkPiNum(pModel) ); + assert( Au_BoxFanoutNum(pObj) == Au_NtkPoNum(pModel) ); + // assign PIs + Au_ObjForEachFanin( pObj, pTerm, k ) + Au_ObjSetXsim( Au_NtkPi(pModel, k), Au_ObjGetXsim(pTerm) ); + // call recursively + Au_NtkTerSimulate_rec( pModel ); + // assign POs + Au_BoxForEachFanout( pObj, pTerm, k ) + Au_ObjSetXsim( pTerm, Au_ObjGetXsim(Au_NtkPo(pModel, k)) ); + } + else if ( Au_ObjIsConst0(pObj) ) + Au_ObjSetXsim( pObj, AU_VAL0 ); + + } + Au_NtkForEachPo( p, pTerm, i ) + Au_ObjSetXsim( pTerm, Au_ObjGetXsimFan0(pObj) ); + Au_NtkForEachPo( p, pTerm, i ) + { + assert( Au_ObjGetXsim(pTerm) > 0 ); + if ( Au_ObjGetXsim(pTerm) == AU_VALX ) + p->pMan->nPortsNC++; + else if ( Au_ObjGetXsim(pTerm) == AU_VAL0 ) + p->pMan->nPortsC0++; + else + p->pMan->nPortsC1++; + } +} + +/**Function************************************************************* + + Synopsis [Flattens the logic hierarchy of the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Au_NtkTerSimulate( Au_Ntk_t * p ) +{ + Au_Obj_t * pTerm; + int i, Counter[2] = {0}; + assert( p->pMan->pFuncs == NULL ); + printf( "Collapsing model \"%s\"...\n", Au_NtkName(p) ); + // create PIs + Au_NtkForEachPi( p, pTerm, i ) + Au_ObjSetXsim( pTerm, AU_VALX ); + // recursively flatten hierarchy + p->pMan->nPortsC0 = 0; + p->pMan->nPortsC1 = 0; + p->pMan->nPortsNC = 0; + Au_NtkTerSimulate_rec( p ); + // analyze outputs + Au_NtkForEachPo( p, pTerm, i ) + if ( Au_ObjGetXsim(pTerm) == AU_VAL0 ) + Counter[0]++; + else if ( Au_ObjGetXsim(pTerm) == AU_VAL1 ) + Counter[1]++; + // print results + printf( "Const0 outputs =%15d. Const1 outputs =%15d. Total outputs =%15d.\n", + Counter[0], Counter[1], Au_NtkPoNum(p) ); + printf( "Const0 ports = %.0f. Const1 ports = %.0f. Non-const ports= %.0f. Total ports = %.0f.\n", + p->pMan->nPortsC0, p->pMan->nPortsC1, p->pMan->nPortsNC, p->pMan->nPortsC0 + p->pMan->nPortsC1 + p->pMan->nPortsNC ); +} + + +/**Function************************************************************* + + Synopsis [Duplicates ABC network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Au_Ntk_t * Au_NtkDerive( Au_Man_t * pMan, Abc_Ntk_t * pNtk, Vec_Ptr_t * vOrder ) +{ + Au_Ntk_t * p; + Au_Obj_t * pAuObj; + Abc_Obj_t * pObj, * pTerm; +// Vec_Ptr_t * vOrder; + Vec_Int_t * vFanins; + int i, k, iFunc; + assert( Abc_NtkIsNetlist(pNtk) ); + Abc_NtkCleanCopy( pNtk ); + p = Au_NtkAlloc( pMan, Abc_NtkName(pNtk) ); + // copy PIs + Abc_NtkForEachPi( pNtk, pTerm, i ) + Abc_ObjFanout0(pTerm)->iTemp = Au_NtkCreatePi(p); + // copy nodes and boxes + vFanins = Vec_IntAlloc( 100 ); +// vOrder = Abc_NtkDfsBoxes( pNtk ); + Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i ) + { + Vec_IntClear( vFanins ); + if ( Abc_ObjIsNode(pObj) ) + { + Abc_ObjForEachFanin( pObj, pTerm, k ) + Vec_IntPush( vFanins, Au_Var2Lit(pTerm->iTemp, 0) ); + iFunc = Abc_NamStrFindOrAdd( pMan->pFuncs, (char *)pObj->pData, NULL ); + Abc_ObjFanout0(pObj)->iTemp = Au_NtkCreateNode(p, vFanins, iFunc); + continue; + } + assert( Abc_ObjIsBox(pObj) ); + Abc_ObjForEachFanin( pObj, pTerm, k ) + Vec_IntPush( vFanins, Au_Var2Lit(Abc_ObjFanin0(pTerm)->iTemp, 0) ); + pObj->iTemp = Au_NtkCreateBox(p, vFanins, Abc_ObjFanoutNum(pObj), ((Abc_Ntk_t *)pObj->pData)->iStep ); + pAuObj = Au_NtkObj(p, pObj->iTemp); + Abc_ObjForEachFanout( pObj, pTerm, k ) + Abc_ObjFanout0(pTerm)->iTemp = Au_ObjFanout(pAuObj, k); + } +// Vec_PtrFree( vOrder ); + Vec_IntFree( vFanins ); + // copy POs + Abc_NtkForEachPo( pNtk, pTerm, i ) + Au_NtkCreatePo( p, Au_Var2Lit(Abc_ObjFanin0(pTerm)->iTemp, 0) ); +// Au_NtkPrintStats( p ); + return p; +} + +Gia_Man_t * Au_ManDeriveTest( Abc_Ntk_t * pRoot ) +{ + extern Vec_Ptr_t * Abc_NtkCollectHie( Abc_Ntk_t * pNtk ); + +// char * pModelName = NULL; + char * pModelName = "path_0_r_x_lhs"; + Gia_Man_t * pGia = NULL; + Vec_Ptr_t * vOrder, * vModels; + Abc_Ntk_t * pMod; + Au_Man_t * pMan; + Au_Ntk_t * pNtk = NULL; + abctime clk1, clk2 = 0, clk3 = 0, clk = Abc_Clock(); + int i; + + clk1 = Abc_Clock(); + pMan = Au_ManAlloc( pRoot->pDesign ? pRoot->pDesign->pName : pRoot->pName ); + pMan->pFuncs = Abc_NamStart( 100, 16 ); + clk2 += Abc_Clock() - clk1; + + vModels = Abc_NtkCollectHie( pRoot ); + Vec_PtrForEachEntry( Abc_Ntk_t *, vModels, pMod, i ) + { + vOrder = Abc_NtkDfsBoxes( pMod ); + + clk1 = Abc_Clock(); + pNtk = Au_NtkDerive( pMan, pMod, vOrder ); + pMod->iStep = pNtk->Id; + pMod->pData = pNtk; + clk2 += Abc_Clock() - clk1; + + Vec_PtrFree( vOrder ); + } + Vec_PtrFree( vModels ); + // order models in topological order + Au_ManReorderModels( pMan, pNtk ); + + // print statistics + Au_ManPrintStats( pMan ); + Au_ManCountThings( pNtk->pMan ); + + // select network + if ( pModelName ) + { + pNtk = Au_ManFindNtkP( pMan, pModelName ); + if ( pNtk == NULL ) + printf( "Could not find module \"%s\".\n", pModelName ); + } + if ( pNtk == NULL ) + pNtk = (Au_Ntk_t *)pRoot->pData; + + +// if ( !Abc_NtkCheckRecursive(pRoot) ) + { + clk1 = Abc_Clock(); + pGia = Au_NtkDeriveFlatGia( pNtk ); + clk3 = Abc_Clock() - clk1; +// printf( "GIA objects max = %d.\n", pMan->nGiaObjMax ); + } + +// clk1 = Abc_Clock(); +// Au_NtkSuppSizeTest( (Au_Ntk_t *)pRoot->pData ); +// clk4 = Abc_Clock() - clk1; + + clk1 = Abc_Clock(); + Au_ManDelete( pMan ); + clk2 += Abc_Clock() - clk1; + + Abc_PrintTime( 1, "Time all ", Abc_Clock() - clk ); + Abc_PrintTime( 1, "Time new ", clk2 ); + Abc_PrintTime( 1, "Time GIA ", clk3 ); +// Abc_PrintTime( 1, "Time supp", clk4 ); + return pGia; +} + +/**Function************************************************************* + + Synopsis [Performs hierarchical equivalence checking.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Abc_NtkHieCecTest2( char * pFileName, char * pModelName, int fVerbose ) +{ + int fSimulation = 0; + Gia_Man_t * pGia = NULL; + Au_Ntk_t * pNtk, * pNtkClp = NULL; + abctime clk1 = 0, clk = Abc_Clock(); + + // read hierarchical netlist + pNtk = Au_NtkParseCBlif( pFileName ); + if ( pNtk == NULL ) + { + printf( "Reading CBLIF file has failed.\n" ); + return NULL; + } + if ( pNtk->pMan == NULL || pNtk->pMan->vNtks.pArray == NULL ) + { + printf( "There is no hierarchy information.\n" ); + Au_NtkFree( pNtk ); + return NULL; + } + Abc_PrintTime( 1, "Reading file", Abc_Clock() - clk ); + + if ( fVerbose ) + { + Au_ManPrintBoxInfo( pNtk ); +// Au_ManPrintBoxInfoSorted( pNtk ); + Au_ManPrintStats( pNtk->pMan ); + } + Au_ManCountThings( pNtk->pMan ); + + // select network + if ( pModelName ) + pNtkClp = Au_ManFindNtkP( pNtk->pMan, pModelName ); + if ( pNtkClp == NULL ) + pNtkClp = pNtk; + + // check if the model is recursive + Au_NtkCheckRecursive( pNtkClp ); + + // collapse + clk1 = Abc_Clock(); + if ( fSimulation ) + { + Au_NtkTerSimulate( pNtkClp ); + Abc_PrintTime( 1, "Time sim ", Abc_Clock() - clk1 ); + } + else + { + pGia = Au_NtkDeriveFlatGia( pNtkClp ); + Abc_PrintTime( 1, "Time GIA ", Abc_Clock() - clk1 ); + } + + // delete + Au_ManDelete( pNtk->pMan ); + Abc_PrintTime( 1, "Time all ", Abc_Clock() - clk ); + return pGia; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/abcInt.h b/yosys/abc/src/base/abc/abcInt.h new file mode 100644 index 00000000000..0bcddcfb3ad --- /dev/null +++ b/yosys/abc/src/base/abc/abcInt.h @@ -0,0 +1,60 @@ +/**CFile**************************************************************** + + FileName [abcInt.h] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Internal declarations.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcInt.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifndef ABC__base__abc__abcInt_h +#define ABC__base__abc__abcInt_h + + +ABC_NAMESPACE_HEADER_START + + +//////////////////////////////////////////////////////////////////////// +/// INCLUDES /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// PARAMETERS /// +//////////////////////////////////////////////////////////////////////// + +#define ABC_NUM_STEPS 10 + +//////////////////////////////////////////////////////////////////////// +/// STRUCTURE DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// MACRO DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + + + +ABC_NAMESPACE_HEADER_END + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + diff --git a/yosys/abc/src/base/abc/abcLatch.c b/yosys/abc/src/base/abc/abcLatch.c new file mode 100644 index 00000000000..653d855fe48 --- /dev/null +++ b/yosys/abc/src/base/abc/abcLatch.c @@ -0,0 +1,769 @@ +/**CFile**************************************************************** + + FileName [abcLatch.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures working with latches.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcLatch.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +#ifdef ABC_USE_CUDD +#include "bdd/extrab/extraBdd.h" +#endif + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Checks if latches form self-loop.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkLatchIsSelfFeed_rec( Abc_Obj_t * pLatch, Abc_Obj_t * pLatchRoot ) +{ + Abc_Obj_t * pFanin; + assert( Abc_ObjIsLatch(pLatch) ); + if ( pLatch == pLatchRoot ) + return 1; + pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); + if ( !Abc_ObjIsBo(pFanin) || !Abc_ObjIsLatch(Abc_ObjFanin0(pFanin)) ) + return 0; + return Abc_NtkLatchIsSelfFeed_rec( Abc_ObjFanin0(pFanin), pLatch ); +} + +/**Function************************************************************* + + Synopsis [Checks if latches form self-loop.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkLatchIsSelfFeed( Abc_Obj_t * pLatch ) +{ + Abc_Obj_t * pFanin; + assert( Abc_ObjIsLatch(pLatch) ); + pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); + if ( !Abc_ObjIsBo(pFanin) || !Abc_ObjIsLatch(Abc_ObjFanin0(pFanin)) ) + return 0; + return Abc_NtkLatchIsSelfFeed_rec( Abc_ObjFanin0(pFanin), pLatch ); +} + +/**Function************************************************************* + + Synopsis [Checks if latches form self-loop.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCountSelfFeedLatches( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pLatch; + int i, Counter; + Counter = 0; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { +// if ( Abc_NtkLatchIsSelfFeed(pLatch) && Abc_ObjFanoutNum(pLatch) > 1 ) +// printf( "Fanouts = %d.\n", Abc_ObjFanoutNum(pLatch) ); + Counter += Abc_NtkLatchIsSelfFeed( pLatch ); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Replaces self-feeding latches by latches with constant inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRemoveSelfFeedLatches( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pLatch, * pConst1; + int i, Counter; + Counter = 0; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + if ( Abc_NtkLatchIsSelfFeed( pLatch ) ) + { + if ( Abc_NtkIsStrash(pNtk) ) + pConst1 = Abc_AigConst1(pNtk); + else + pConst1 = Abc_NtkCreateNodeConst1(pNtk); + Abc_ObjPatchFanin( Abc_ObjFanin0(pLatch), Abc_ObjFanin0(Abc_ObjFanin0(pLatch)), pConst1 ); + Counter++; + } + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Pipelines the network with latches.] + + Description [] + + SideEffects [Does not check the names of the added latches!!!] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkLatchPipe( Abc_Ntk_t * pNtk, int nLatches ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pFanin, * pFanout; + int i, k, nTotal, nDigits; + if ( nLatches < 1 ) + return; + nTotal = nLatches * Abc_NtkPiNum(pNtk); + nDigits = Abc_Base10Log( nTotal ); + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachPi( pNtk, pObj, i ) + { + Abc_NodeCollectFanouts( pObj, vNodes ); + for ( pFanin = pObj, k = 0; k < nLatches; k++ ) + pFanin = Abc_NtkAddLatch( pNtk, pFanin, ABC_INIT_ZERO ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pFanout, k ) + Abc_ObjPatchFanin( pFanout, pObj, pFanin ); + } + Vec_PtrFree( vNodes ); + Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); +} + +/**Function************************************************************* + + Synopsis [Strashes one logic node using its SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkCollectLatchValues( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vValues; + Abc_Obj_t * pLatch; + int i; + vValues = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) ); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + Vec_IntPush( vValues, Abc_LatchIsInit1(pLatch) ); + return vValues; +} + +/**Function************************************************************* + + Synopsis [Derives latch init string.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_NtkCollectLatchValuesStr( Abc_Ntk_t * pNtk ) +{ + char * pInits; + Abc_Obj_t * pLatch; + int i; + pInits = ABC_ALLOC( char, Abc_NtkLatchNum(pNtk) + 1 ); + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + if ( Abc_LatchIsInit0(pLatch) ) + pInits[i] = '0'; + else if ( Abc_LatchIsInit1(pLatch) ) + pInits[i] = '1'; + else if ( Abc_LatchIsInitDc(pLatch) ) + pInits[i] = 'x'; + else + assert( 0 ); + } + pInits[i] = 0; + return pInits; +} + +/**Function************************************************************* + + Synopsis [Strashes one logic node using its SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues ) +{ + Abc_Obj_t * pLatch; + int i; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + pLatch->pData = (void *)(ABC_PTRINT_T)(vValues? (Vec_IntEntry(vValues,i)? ABC_INIT_ONE : ABC_INIT_ZERO) : ABC_INIT_DC); +} + +/**Function************************************************************* + + Synopsis [Creates latch with the given initial value.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkAddLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pDriver, Abc_InitType_t Init ) +{ + Abc_Obj_t * pLatchOut, * pLatch, * pLatchIn; + pLatchOut = Abc_NtkCreateBo(pNtk); + pLatch = Abc_NtkCreateLatch(pNtk); + pLatchIn = Abc_NtkCreateBi(pNtk); + Abc_ObjAssignName( pLatchOut, Abc_ObjName(pLatch), "_lo" ); + Abc_ObjAssignName( pLatchIn, Abc_ObjName(pLatch), "_li" ); + Abc_ObjAddFanin( pLatchOut, pLatch ); + Abc_ObjAddFanin( pLatch, pLatchIn ); + if ( pDriver ) + Abc_ObjAddFanin( pLatchIn, pDriver ); + pLatch->pData = (void *)Init; + return pLatchOut; +} + +/**Function************************************************************* + + Synopsis [Creates MUX.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkNodeConvertToMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0, Abc_Obj_t * pMux ) +{ + assert( Abc_NtkIsLogic(pNtk) ); + Abc_ObjAddFanin( pMux, pNodeC ); + Abc_ObjAddFanin( pMux, pNode1 ); + Abc_ObjAddFanin( pMux, pNode0 ); + if ( Abc_NtkHasSop(pNtk) ) + pMux->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, "11- 1\n0-1 1\n" ); +#ifdef ABC_USE_CUDD + else if ( Abc_NtkHasBdd(pNtk) ) + pMux->pData = Cudd_bddIte((DdManager *)pNtk->pManFunc,Cudd_bddIthVar((DdManager *)pNtk->pManFunc,0),Cudd_bddIthVar((DdManager *)pNtk->pManFunc,1),Cudd_bddIthVar((DdManager *)pNtk->pManFunc,2)), Cudd_Ref( (DdNode *)pMux->pData ); +#endif + else if ( Abc_NtkHasAig(pNtk) ) + pMux->pData = Hop_Mux((Hop_Man_t *)pNtk->pManFunc,Hop_IthVar((Hop_Man_t *)pNtk->pManFunc,0),Hop_IthVar((Hop_Man_t *)pNtk->pManFunc,1),Hop_IthVar((Hop_Man_t *)pNtk->pManFunc,2)); + else + assert( 0 ); +} + +/**Function************************************************************* + + Synopsis [Converts registers with DC values into additional PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkConvertDcLatches( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pCtrl, * pLatch, * pMux, * pPi; + Abc_InitType_t Init = ABC_INIT_ZERO; + int i, fFound = 0, Counter; + // check if there are latches with DC values + Abc_NtkForEachLatch( pNtk, pLatch, i ) + if ( Abc_LatchIsInitDc(pLatch) ) + { + fFound = 1; + break; + } + if ( !fFound ) + return; + // add control latch + pCtrl = Abc_NtkAddLatch( pNtk, Abc_NtkCreateNodeConst1(pNtk), Init ); + // add fanouts for each latch with DC values + Counter = 0; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + if ( !Abc_LatchIsInitDc(pLatch) ) + continue; + // change latch value + pLatch->pData = (void *)Init; + // if the latch output has the same name as a PO, rename it + if ( Abc_NodeFindCoFanout( Abc_ObjFanout0(pLatch) ) ) + { + Nm_ManDeleteIdName( pLatch->pNtk->pManName, Abc_ObjFanout0(pLatch)->Id ); + Abc_ObjAssignName( Abc_ObjFanout0(pLatch), Abc_ObjName(pLatch), "_lo" ); + } + // create new PIs + pPi = Abc_NtkCreatePi( pNtk ); + Abc_ObjAssignName( pPi, Abc_ObjName(pLatch), "_pi" ); + // create a new node and transfer fanout from latch output to the new node + pMux = Abc_NtkCreateNode( pNtk ); + Abc_ObjTransferFanout( Abc_ObjFanout0(pLatch), pMux ); + // convert the node into a mux + Abc_NtkNodeConvertToMux( pNtk, pCtrl, Abc_ObjFanout0(pLatch), pPi, pMux ); + Counter++; + } + printf( "The number of converted latches with DC values = %d.\n", Counter ); +} + +/**Function************************************************************* + + Synopsis [Transfors the array of latch names into that of latch numbers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkConverLatchNamesIntoNumbers( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vResult, * vNames; + Vec_Int_t * vNumbers; + Abc_Obj_t * pObj; + char * pName; + int i, k, Num; + if ( pNtk->vOnehots == NULL ) + return NULL; + // set register numbers + Abc_NtkForEachLatch( pNtk, pObj, i ) + pObj->pNext = (Abc_Obj_t *)(ABC_PTRINT_T)i; + // add the numbers + vResult = Vec_PtrAlloc( Vec_PtrSize(pNtk->vOnehots) ); + Vec_PtrForEachEntry( Vec_Ptr_t *, pNtk->vOnehots, vNames, i ) + { + vNumbers = Vec_IntAlloc( Vec_PtrSize(vNames) ); + Vec_PtrForEachEntry( char *, vNames, pName, k ) + { + Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_BO ); + if ( Num < 0 ) + continue; + pObj = Abc_NtkObj( pNtk, Num ); + if ( Abc_ObjFaninNum(pObj) != 1 || !Abc_ObjIsLatch(Abc_ObjFanin0(pObj)) ) + continue; + Vec_IntPush( vNumbers, (int)(ABC_PTRINT_T)pObj->pNext ); + } + if ( Vec_IntSize( vNumbers ) > 1 ) + { + Vec_PtrPush( vResult, vNumbers ); +printf( "Converted %d one-hot registers.\n", Vec_IntSize(vNumbers) ); + } + else + Vec_IntFree( vNumbers ); + } + // clean the numbers + Abc_NtkForEachLatch( pNtk, pObj, i ) + pObj->pNext = NULL; + return vResult; +} + + +/**Function************************************************************* + + Synopsis [Converts registers with DC values into additional PIs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkConvertOnehot( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin, * pObjNew, * pObjLiNew, * pObjLoNew; + int i, k, nFlops, nStates, iState, pfCompl[32]; + assert( Abc_NtkIsLogic(pNtk) ); + nFlops = Abc_NtkLatchNum(pNtk); + if ( nFlops == 0 ) + return Abc_NtkDup( pNtk ); + if ( nFlops > 16 ) + { + printf( "Cannot re-encode %d flops because it will lead to 2^%d states.\n", nFlops, nFlops ); + return NULL; + } + // check if there are latches with DC values + iState = 0; + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + if ( Abc_LatchIsInitDc(pObj) ) + { + printf( "Cannot process logic network with don't-care init values. Run \"zero\".\n" ); + return NULL; + } + if ( Abc_LatchIsInit1(pObj) ) + iState |= (1 << i); + } + // transfer logic to SOPs + Abc_NtkToSop( pNtk, -1, ABC_INFINITY ); + // create new network + pNtkNew = Abc_NtkStartFromNoLatches( pNtk, pNtk->ntkType, pNtk->ntkFunc ); + nStates = (1 << nFlops); + for ( i = 0; i < nStates; i++ ) + { + pObjNew = Abc_NtkCreateLatch( pNtkNew ); + pObjLiNew = Abc_NtkCreateBi( pNtkNew ); + pObjLoNew = Abc_NtkCreateBo( pNtkNew ); + Abc_ObjAddFanin( pObjNew, pObjLiNew ); + Abc_ObjAddFanin( pObjLoNew, pObjNew ); + if ( i == iState ) + Abc_LatchSetInit1( pObjNew ); + else + Abc_LatchSetInit0( pObjNew ); + } + Abc_NtkAddDummyBoxNames( pNtkNew ); + assert( Abc_NtkLatchNum(pNtkNew) == nStates ); + assert( Abc_NtkPiNum(pNtkNew) == Abc_NtkPiNum(pNtk) ); + assert( Abc_NtkPoNum(pNtkNew) == Abc_NtkPoNum(pNtk) ); + assert( Abc_NtkCiNum(pNtkNew) == Abc_NtkPiNum(pNtkNew) + nStates ); + assert( Abc_NtkCoNum(pNtkNew) == Abc_NtkPoNum(pNtkNew) + nStates ); + assert( Abc_NtkCiNum(pNtk) == Abc_NtkPiNum(pNtk) + nFlops ); + assert( Abc_NtkCoNum(pNtk) == Abc_NtkPoNum(pNtk) + nFlops ); + // create hot-to-log transformers + for ( i = 0; i < nFlops; i++ ) + { + pObjNew = Abc_NtkCreateNode( pNtkNew ); + for ( k = 0; k < nStates; k++ ) + if ( (k >> i) & 1 ) + Abc_ObjAddFanin( pObjNew, Abc_NtkCi(pNtkNew, Abc_NtkPiNum(pNtkNew)+k) ); + assert( Abc_ObjFaninNum(pObjNew) == nStates/2 ); + pObjNew->pData = Abc_SopCreateOr( (Mem_Flex_t *)pNtkNew->pManFunc, nStates/2, NULL ); + // save the new flop + pObj = Abc_NtkCi( pNtk, Abc_NtkPiNum(pNtk) + i ); + pObj->pCopy = pObjNew; + } + // duplicate the nodes + vNodes = Abc_NtkDfs( pNtk, 0 ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + { + pObj->pCopy = Abc_NtkDupObj( pNtkNew, pObj, 1 ); + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + Vec_PtrFree( vNodes ); + // connect the POs + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjNotCond(Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj)) ); + // write entries into the nodes + Abc_NtkForEachCo( pNtk, pObj, i ) + pObj->pCopy = Abc_ObjNotCond(Abc_ObjFanin0(pObj)->pCopy, Abc_ObjFaninC0(pObj)); + // create log-to-hot transformers + for ( k = 0; k < nStates; k++ ) + { + pObjNew = Abc_NtkCreateNode( pNtkNew ); + for ( i = 0; i < nFlops; i++ ) + { + pObj = Abc_NtkCo( pNtk, Abc_NtkPoNum(pNtk) + i ); + Abc_ObjAddFanin( pObjNew, Abc_ObjRegular(pObj->pCopy) ); + pfCompl[i] = Abc_ObjIsComplement(pObj->pCopy) ^ !((k >> i) & 1); + } + pObjNew->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, nFlops, pfCompl ); + // connect it to the flop input + Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, Abc_NtkPoNum(pNtkNew)+k), pObjNew ); + } + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkConvertOnehot(): Network check has failed.\n" ); + return pNtkNew; +} + +ABC_NAMESPACE_IMPL_END + +#include "aig/gia/giaAig.h" + +ABC_NAMESPACE_IMPL_START + + +/**Function************************************************************* + + Synopsis [Performs retiming with classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Aig_Man_t * Abc_NtkRetimeWithClassesAig( Aig_Man_t * pMan, Vec_Int_t * vClasses, Vec_Int_t ** pvClasses, int fVerbose ) +{ + Aig_Man_t * pManNew; + Gia_Man_t * pGia, * pGiaNew; + pGia = Gia_ManFromAigSimple( pMan ); + assert( Gia_ManRegNum(pGia) == Vec_IntSize(vClasses) ); + pGia->vFlopClasses = vClasses; + pGiaNew = Gia_ManRetimeForward( pGia, 10, fVerbose ); + *pvClasses = pGiaNew->vFlopClasses; + pGiaNew->vFlopClasses = NULL; + pManNew = Gia_ManToAig( pGiaNew, 0 ); + Gia_ManStop( pGiaNew ); + Gia_ManStop( pGia ); + return pManNew; +} + +/**Function************************************************************* + + Synopsis [Performs retiming with classes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkRetimeWithClassesNtk( Abc_Ntk_t * pNtk, Vec_Int_t * vClasses, Vec_Int_t ** pvClasses, int fVerbose ) +{ + extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); + extern Abc_Ntk_t * Abc_NtkFromDarSeqSweep( Abc_Ntk_t * pNtkOld, Aig_Man_t * pMan ); + Abc_Ntk_t * pNtkAig, * pNtkAigRet, * pNtkRes; + Aig_Man_t * pMan, * pManNew; + pNtkAig = Abc_NtkStrash( pNtk, 0, 1, 0 ); + pMan = Abc_NtkToDar( pNtkAig, 0, 1 ); + pManNew = Abc_NtkRetimeWithClassesAig( pMan, vClasses, pvClasses, fVerbose ); + pNtkAigRet = Abc_NtkFromDarSeqSweep( pNtkAig, pManNew ); + pNtkRes = Abc_NtkToLogic( pNtkAigRet ); + Abc_NtkDelete( pNtkAigRet ); + Abc_NtkDelete( pNtkAig ); + Aig_ManStop( pManNew ); + Aig_ManStop( pMan ); + return pNtkRes; +} + +/**Function************************************************************* + + Synopsis [Returns self-loops back into the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTransformBack( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew, Vec_Ptr_t * vControls, Vec_Int_t * vClasses ) +{ + Abc_Obj_t * pObj, * pNodeNew, * pCtrl, * pDriver; + int i, Class; + assert( Abc_NtkPoNum(pNtkOld) == Abc_NtkPoNum(pNtkNew) ); + // match the POs of the old into new + Abc_NtkForEachPo( pNtkOld, pObj, i ) + pObj->pCopy = Abc_NtkPo( pNtkNew, i ); + // remap the flops + Vec_PtrForEachEntry( Abc_Obj_t *, vControls, pObj, i ) + { + assert( Abc_ObjIsPo(pObj) && pObj->pNtk == pNtkOld ); + Vec_PtrWriteEntry( vControls, i, pObj->pCopy ); + } + // create self-loops + assert( Abc_NtkLatchNum(pNtkNew) == Vec_IntSize(vClasses) ); + Abc_NtkForEachLatch( pNtkNew, pObj, i ) + { + Class = Vec_IntEntry( vClasses, i ); + if ( Class == -1 ) + continue; + pDriver = Abc_ObjFanin0(Abc_ObjFanin0(pObj)); + pCtrl = (Abc_Obj_t *)Vec_PtrEntry( vControls, Class ); + pCtrl = Abc_ObjFanin0( pCtrl ); + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + Abc_ObjAddFanin( pNodeNew, pCtrl ); + Abc_ObjAddFanin( pNodeNew, pDriver ); + Abc_ObjAddFanin( pNodeNew, Abc_ObjFanout0(pObj) ); + Abc_ObjSetData( pNodeNew, Abc_SopRegister((Mem_Flex_t *)pNtkNew->pManFunc, "0-1 1\n11- 1\n") ); + Abc_ObjPatchFanin( Abc_ObjFanin0(pObj), pDriver, pNodeNew ); + } + // remove the useless POs + Vec_PtrForEachEntry( Abc_Obj_t *, vControls, pObj, i ) + Abc_NtkDeleteObj( pObj ); +} + +/**Function************************************************************* + + Synopsis [Classify flops.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCRetime( Abc_Ntk_t * pNtk, int fVerbose ) +{ + Abc_Ntk_t * pNtkNew; + Vec_Ptr_t * vControls; + Vec_Int_t * vFlopClasses, * vFlopClassesNew; + Abc_Obj_t * pObj, * pDriver, * pFlopOut, * pObjPo; + int i, iFlop, CountN = 0, Count2 = 0, Count1 = 0, Count0 = 0; + + // duplicate the AIG + pNtk = Abc_NtkDup( pNtk ); + + // update registers + vControls = Vec_PtrAlloc( 100 ); + vFlopClasses = Vec_IntAlloc( 100 ); + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + pFlopOut = Abc_ObjFanout0(pObj); + pDriver = Abc_ObjFanin0( Abc_ObjFanin0(pObj) ); + if ( Abc_ObjFaninNum(pDriver) != 3 ) + { + Vec_IntPush( vFlopClasses, -1 ); + CountN++; + continue; + } + if ( Abc_ObjFanin(pDriver, 1) != pFlopOut && Abc_ObjFanin(pDriver, 2) != pFlopOut ) + { + Vec_IntPush( vFlopClasses, -1 ); + Count2++; + continue; + } + if ( Abc_ObjFanin(pDriver, 1) == pFlopOut ) + { + Vec_IntPush( vFlopClasses, -1 ); + Count1++; + continue; + } + assert( Abc_ObjFanin(pDriver, 2) == pFlopOut ); + Count0++; + Vec_PtrPushUnique( vControls, Abc_ObjFanin0(pDriver) ); + // set the flop class + iFlop = Vec_PtrFind( vControls, Abc_ObjFanin0(pDriver) ); + Vec_IntPush( vFlopClasses, iFlop ); + // update + Abc_ObjPatchFanin( Abc_ObjFanin0(pObj), pDriver, Abc_ObjFanin(pDriver, 1) ); + } + if ( Count1 ) + printf( "Opposite phase enable is present in %d flops (out of %d).\n", Count1, Abc_NtkLatchNum(pNtk) ); + if ( fVerbose ) + printf( "CountN = %4d. Count2 = %4d. Count1 = %4d. Count0 = %4d. Ctrls = %d.\n", + CountN, Count2, Count1, Count0, Vec_PtrSize(vControls) ); + + // add the controls to the list of POs + Vec_PtrForEachEntry( Abc_Obj_t *, vControls, pObj, i ) + { + pObjPo = Abc_NtkCreatePo( pNtk ); + Abc_ObjAddFanin( pObjPo, pObj ); + Abc_ObjAssignName( pObjPo, Abc_ObjName(pObjPo), NULL ); + Vec_PtrWriteEntry( vControls, i, pObjPo ); + } + Abc_NtkOrderCisCos( pNtk ); + Abc_NtkCleanup( pNtk, fVerbose ); + + // performs retiming with classes + pNtkNew = Abc_NtkRetimeWithClassesNtk( pNtk, vFlopClasses, &vFlopClassesNew, fVerbose ); + Abc_NtkTransformBack( pNtk, pNtkNew, vControls, vFlopClassesNew ); +// assert( Abc_NtkPoNum(pNtkNew) == Abc_NtkPoNum(pNtk) ); + Abc_NtkDelete( pNtk ); + + Vec_PtrFree( vControls ); +// Vec_IntFree( vFlopClasses ); + Vec_IntFree( vFlopClassesNew ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Resimulates CEX and return the ID of the PO that failed.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkVerifyCex( Abc_Ntk_t * pNtk, Abc_Cex_t * p ) +{ + Abc_Obj_t * pObj; + int RetValue, i, k, iBit = 0; + assert( Abc_NtkIsStrash(pNtk) ); + assert( p->nPis == Abc_NtkPiNum(pNtk) ); +// assert( p->nRegs == Abc_NtkLatchNum(pNtk) ); + Abc_NtkCleanMarkC( pNtk ); + Abc_AigConst1(pNtk)->fMarkC = 1; + // initialize flops + Abc_NtkForEachLatch( pNtk, pObj, i ) + Abc_ObjFanout0(pObj)->fMarkC = Abc_InfoHasBit(p->pData, iBit++); + // simulate timeframes + iBit = p->nRegs; + for ( i = 0; i <= p->iFrame; i++ ) + { + Abc_NtkForEachPi( pNtk, pObj, k ) + pObj->fMarkC = Abc_InfoHasBit(p->pData, iBit++); + Abc_NtkForEachNode( pNtk, pObj, k ) + pObj->fMarkC = (Abc_ObjFanin0(pObj)->fMarkC ^ Abc_ObjFaninC0(pObj)) & + (Abc_ObjFanin1(pObj)->fMarkC ^ Abc_ObjFaninC1(pObj)); + Abc_NtkForEachCo( pNtk, pObj, k ) + pObj->fMarkC = Abc_ObjFanin0(pObj)->fMarkC ^ Abc_ObjFaninC0(pObj); + Abc_NtkForEachLatch( pNtk, pObj, k ) + Abc_ObjFanout0(pObj)->fMarkC = Abc_ObjFanin0(pObj)->fMarkC; + } + assert( iBit == p->nBits ); + // figure out the number of failed output + RetValue = -1; + Abc_NtkForEachPo( pNtk, pObj, i ) + { + if ( pObj->fMarkC ) + { + RetValue = i; + break; + } + } + Abc_NtkCleanMarkC( pNtk ); + return RetValue; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/abcLib.c b/yosys/abc/src/base/abc/abcLib.c new file mode 100644 index 00000000000..6623b872989 --- /dev/null +++ b/yosys/abc/src/base/abc/abcLib.c @@ -0,0 +1,400 @@ +/**CFile**************************************************************** + + FileName [abcLib.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Functions to manipulate verilog libraries.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcLib.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Create the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Des_t * Abc_DesCreate( char * pName ) +{ + Abc_Des_t * p; + p = ABC_ALLOC( Abc_Des_t, 1 ); + memset( p, 0, sizeof(Abc_Des_t) ); + p->pName = Abc_UtilStrsav( pName ); + p->tModules = st__init_table( strcmp, st__strhash ); + p->vTops = Vec_PtrAlloc( 100 ); + p->vModules = Vec_PtrAlloc( 100 ); + p->pManFunc = Hop_ManStart(); + p->pLibrary = NULL; + return p; +} + +/**Function************************************************************* + + Synopsis [Removes all pointers to the manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_DesCleanManPointer( Abc_Des_t * p, void * pMan ) +{ + Abc_Ntk_t * pTemp; + int i; + if ( p == NULL ) + return; + if ( p->pManFunc == pMan ) + p->pManFunc = NULL; + Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pTemp, i ) + if ( pTemp->pManFunc == pMan ) + pTemp->pManFunc = NULL; +} + +/**Function************************************************************* + + Synopsis [Frees the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_DesFree( Abc_Des_t * p, Abc_Ntk_t * pNtkSave ) +{ + Abc_Ntk_t * pNtk; + int i; + if ( p->pName ) + ABC_FREE( p->pName ); + if ( p->pManFunc ) + Hop_ManStop( (Hop_Man_t *)p->pManFunc ); + if ( p->tModules ) + st__free_table( p->tModules ); + if ( p->vModules ) + { + Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pNtk, i ) + { + if ( pNtk == pNtkSave ) + continue; + pNtk->pDesign = NULL; + if ( (pNtkSave && pNtk->pManFunc == pNtkSave->pManFunc) || (pNtk->pManFunc == p->pManFunc) ) + pNtk->pManFunc = NULL; + Abc_NtkDelete( pNtk ); + } + Vec_PtrFree( p->vModules ); + } + if ( p->vTops ) + Vec_PtrFree( p->vTops ); + ABC_FREE( p ); +} + +/**Function************************************************************* + + Synopsis [Duplicated the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Des_t * Abc_DesDup( Abc_Des_t * p ) +{ + Abc_Des_t * pNew; + Abc_Ntk_t * pTemp; + Abc_Obj_t * pObj; + int i, k; + pNew = Abc_DesCreate( p->pName ); + Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pTemp, i ) + Abc_DesAddModel( pNew, Abc_NtkDup(pTemp) ); + Vec_PtrForEachEntry( Abc_Ntk_t *, p->vTops, pTemp, i ) + Vec_PtrPush( pNew->vTops, pTemp->pCopy ); + Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pTemp, i ) + pTemp->pCopy->pAltView = pTemp->pAltView ? pTemp->pAltView->pCopy : NULL; + // update box models + Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pTemp, i ) + Abc_NtkForEachBox( pTemp, pObj, k ) + if ( Abc_ObjIsWhitebox(pObj) || Abc_ObjIsBlackbox(pObj) ) + pObj->pCopy->pData = Abc_ObjModel(pObj)->pCopy; + return pNew; +} + +/**Function************************************************************* + + Synopsis [Frees the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Des_t * Abc_DesDupBlackboxes( Abc_Des_t * p, Abc_Ntk_t * pNtkSave ) +{ + Abc_Des_t * pNew; + Abc_Ntk_t * pNtkTemp; + int i; + assert( Vec_PtrSize(p->vTops) > 0 ); + assert( Vec_PtrSize(p->vModules) > 1 ); + pNew = Abc_DesCreate( p->pName ); +// pNew->pManFunc = pNtkSave->pManFunc; + Vec_PtrPush( pNew->vTops, pNtkSave ); + Vec_PtrPush( pNew->vModules, pNtkSave ); + Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pNtkTemp, i ) + if ( Abc_NtkHasBlackbox( pNtkTemp ) ) + Vec_PtrPush( pNew->vModules, Abc_NtkDup(pNtkTemp) ); + return pNew; +} + + +/**Function************************************************************* + + Synopsis [Prints the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_DesPrint( Abc_Des_t * p ) +{ + Abc_Ntk_t * pNtk; + Abc_Obj_t * pObj; + int i, k; + printf( "Models of design %s:\n", p->pName ); + Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pNtk, i ) + { + printf( "%2d : %20s ", i+1, pNtk->pName ); + printf( "nd = %6d lat = %6d whitebox = %3d blackbox = %3d\n", + Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk), + Abc_NtkWhiteboxNum(pNtk), Abc_NtkBlackboxNum(pNtk) ); + if ( Abc_NtkBlackboxNum(pNtk) == 0 ) + continue; + Abc_NtkForEachWhitebox( pNtk, pObj, k ) + printf( " %20s (whitebox)\n", Abc_NtkName((Abc_Ntk_t *)pObj->pData) ); + Abc_NtkForEachBlackbox( pNtk, pObj, k ) + printf( " %20s (blackbox)\n", Abc_NtkName((Abc_Ntk_t *)pObj->pData) ); + } +} + +/**Function************************************************************* + + Synopsis [Create the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_DesAddModel( Abc_Des_t * p, Abc_Ntk_t * pNtk ) +{ + if ( st__is_member( p->tModules, (char *)pNtk->pName ) ) + return 0; + st__insert( p->tModules, (char *)pNtk->pName, (char *)pNtk ); + assert( pNtk->Id == 0 ); + pNtk->Id = Vec_PtrSize(p->vModules); + Vec_PtrPush( p->vModules, pNtk ); + pNtk->pDesign = p; + return 1; +} + +/**Function************************************************************* + + Synopsis [Create the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_DesFindModelByName( Abc_Des_t * p, char * pName ) +{ + Abc_Ntk_t * pNtk; + if ( ! st__is_member( p->tModules, (char *)pName ) ) + return NULL; + st__lookup( p->tModules, (char *)pName, (char **)&pNtk ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Frees the library.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_DesDeriveRoot( Abc_Des_t * p ) +{ + Abc_Ntk_t * pNtk; + if ( Vec_PtrSize(p->vModules) > 1 ) + { + printf( "The design includes more than one module and is currently not used.\n" ); + return NULL; + } + pNtk = (Abc_Ntk_t *)Vec_PtrEntry( p->vModules, 0 ); Vec_PtrClear( p->vModules ); + pNtk->pManFunc = p->pManFunc; p->pManFunc = NULL; + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Detects the top-level models.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_DesFindTopLevelModels( Abc_Des_t * p ) +{ + Abc_Ntk_t * pNtk, * pNtkBox; + Abc_Obj_t * pObj; + int i, k; + assert( Vec_PtrSize( p->vModules ) > 0 ); + // clear the models + Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pNtk, i ) + pNtk->fHieVisited = 0; + // mark all the models reachable from other models + Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pNtk, i ) + { + Abc_NtkForEachBox( pNtk, pObj, k ) + { + if ( Abc_ObjIsLatch(pObj) ) + continue; + if ( pObj->pData == NULL ) + continue; + pNtkBox = (Abc_Ntk_t *)pObj->pData; + pNtkBox->fHieVisited = 1; + } + } + // collect the models that are not marked + Vec_PtrClear( p->vTops ); + Vec_PtrForEachEntry( Abc_Ntk_t *, p->vModules, pNtk, i ) + { + if ( pNtk->fHieVisited == 0 ) + Vec_PtrPush( p->vTops, pNtk ); + else + pNtk->fHieVisited = 0; + } + return Vec_PtrSize( p->vTops ); +} + + +/**Function************************************************************* + + Synopsis [Derive the AIG of the logic in the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeStrashUsingNetwork_rec( Abc_Ntk_t * pNtkAig, Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pFanin; + int i; + assert( !Abc_ObjIsNet(pObj) ); + if ( pObj->pCopy ) + return; + // call for the fanins + Abc_ObjForEachFanin( pObj, pFanin, i ) + Abc_NodeStrashUsingNetwork_rec( pNtkAig, Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)) ); + // compute for the node + pObj->pCopy = Abc_NodeStrash( pNtkAig, pObj, 0 ); + // set for the fanout net + Abc_ObjFanout0(pObj)->pCopy = pObj->pCopy; +} + +/**Function************************************************************* + + Synopsis [Derive the AIG of the logic in the netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeStrashUsingNetwork( Abc_Ntk_t * pNtkAig, Abc_Obj_t * pBox ) +{ + Abc_Ntk_t * pNtkGate; + Abc_Obj_t * pObj; + unsigned * pPolarity; + int i, fCompl; + assert( Abc_ObjIsBox(pBox) ); + pNtkGate = (Abc_Ntk_t *)pBox->pData; + pPolarity = (unsigned *)pBox->pNext; + assert( Abc_NtkIsNetlist(pNtkGate) ); + assert( Abc_NtkLatchNum(pNtkGate) == 0 ); + Abc_NtkCleanCopy( pNtkGate ); + // set the PI values + Abc_NtkForEachPi( pNtkGate, pObj, i ) + { + fCompl = (pPolarity && Abc_InfoHasBit(pPolarity, i)); + pObj->pCopy = Abc_ObjNotCond( Abc_ObjFanin(pBox,i)->pCopy, fCompl ); + Abc_ObjFanout0(pObj)->pCopy = pObj->pCopy; + } + // build recursively and set the PO values + Abc_NtkForEachPo( pNtkGate, pObj, i ) + { + Abc_NodeStrashUsingNetwork_rec( pNtkAig, Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)) ); + Abc_ObjFanout(pBox,i)->pCopy = Abc_ObjFanin0(pObj)->pCopy; + } +//printf( "processing %d\n", pBox->Id ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/abcMinBase.c b/yosys/abc/src/base/abc/abcMinBase.c new file mode 100644 index 00000000000..92dbd0c9813 --- /dev/null +++ b/yosys/abc/src/base/abc/abcMinBase.c @@ -0,0 +1,907 @@ +/**CFile**************************************************************** + + FileName [abcMinBase.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Makes nodes of the network minimum base.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcMinBase.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +#ifdef ABC_USE_CUDD +#include "bdd/extrab/extraBdd.h" +#endif + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#ifdef ABC_USE_CUDD + +extern int Abc_NodeSupport( DdNode * bFunc, Vec_Str_t * vSupport, int nVars ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Makes nodes minimum base.] + + Description [Returns the number of changed nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkMinimumBase( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, Counter; + assert( Abc_NtkIsBddLogic(pNtk) ); + Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + Counter += Abc_NodeMinimumBase( pNode ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Makes one node minimum base.] + + Description [Returns 1 if the node is changed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeMinimumBase_buggy( Abc_Obj_t * pNode ) +{ + Vec_Str_t * vSupport; + Vec_Ptr_t * vFanins; + DdNode * bTemp; + int i, nVars; + + assert( Abc_NtkIsBddLogic(pNode->pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + + // compute support + vSupport = Vec_StrAlloc( 10 ); + nVars = Abc_NodeSupport( Cudd_Regular(pNode->pData), vSupport, Abc_ObjFaninNum(pNode) ); + if ( nVars == Abc_ObjFaninNum(pNode) ) + { + Vec_StrFree( vSupport ); + return 0; + } + + // remove unused fanins + vFanins = Vec_PtrAlloc( Abc_ObjFaninNum(pNode) ); + Abc_NodeCollectFanins( pNode, vFanins ); + for ( i = 0; i < vFanins->nSize; i++ ) + if ( vSupport->pArray[i] == 0 ) + Abc_ObjDeleteFanin( pNode, (Abc_Obj_t *)vFanins->pArray[i] ); + assert( nVars == Abc_ObjFaninNum(pNode) ); + + // update the function of the node + pNode->pData = Extra_bddRemapUp( (DdManager *)pNode->pNtk->pManFunc, bTemp = (DdNode *)pNode->pData ); Cudd_Ref( (DdNode *)pNode->pData ); + Cudd_RecursiveDeref( (DdManager *)pNode->pNtk->pManFunc, bTemp ); + Vec_PtrFree( vFanins ); + Vec_StrFree( vSupport ); + return 1; +} + +int Abc_NodeMinimumBase( Abc_Obj_t * pNode ) +{ + DdManager * dd = (DdManager *)pNode->pNtk->pManFunc; + DdNode * bTemp, ** pbVars; + Vec_Str_t * vSupport; + int i, nVars, j, iFanin, iFanin2, k = 0; + int ddSize, fDupFanins = 0; + + assert( Abc_NtkIsBddLogic(pNode->pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + + // compute support + vSupport = Vec_StrAlloc( 10 ); + nVars = Abc_NodeSupport( Cudd_Regular(pNode->pData), vSupport, Abc_ObjFaninNum(pNode) ); + if ( nVars == Abc_ObjFaninNum(pNode) ) + { + Vec_StrFree( vSupport ); + return 0; + } + + // remove unused fanins. + + // By default, every BDD variable stays equivalent to itself. + ddSize = Cudd_ReadSize( dd ); + pbVars = ABC_CALLOC( DdNode *, ddSize ); + for (i = 0; i < ddSize; i += 1 ) { + pbVars[i] = Cudd_bddIthVar( dd, i ); + } + Vec_IntForEachEntry( &pNode->vFanins, iFanin, i ) + { + Abc_Obj_t * pFanin = Abc_NtkObj( pNode->pNtk, iFanin ); + if ( !Vec_StrEntry(vSupport, i) ) + { + if ( !Vec_IntRemove( &pFanin->vFanouts, pNode->Id ) ) + printf( "The obj %d is not found among the fanouts of obj %d ...\n", pNode->Id, iFanin ); + continue; + } + Vec_IntForEachEntryStop( &pNode->vFanins, iFanin2, j, k ) + if ( iFanin == iFanin2 ) + break; + fDupFanins |= (int)(j < k); + if ( j == k ) + Vec_IntWriteEntry( &pNode->vFanins, k++, iFanin ); + else if ( !Vec_IntRemove( &pFanin->vFanouts, pNode->Id ) ) + printf( "The obj %d is not found among the fanouts of obj %d ...\n", pNode->Id, iFanin ); + + // i-th variable becomes equivalent to j-th variable (can be itself) + pbVars[i] = Cudd_bddIthVar( dd, j ); + } + Vec_IntShrink( &pNode->vFanins, k ); + + // update the function of the node + if ( ! Cudd_IsConstant((DdNode *) pNode->pData ) ) { + pNode->pData = Cudd_bddVectorCompose( dd, bTemp = (DdNode *)pNode->pData, pbVars ); + Cudd_Ref( (DdNode *)pNode->pData ); + Cudd_RecursiveDeref( dd, bTemp ); + } + Vec_StrFree( vSupport ); + ABC_FREE( pbVars ); + + // try again if node had duplicated fanins + if ( fDupFanins ) + Abc_NodeMinimumBase( pNode ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Makes nodes of the network fanin-dup-free.] + + Description [Returns the number of pairs of duplicated fanins.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkRemoveDupFanins( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, Counter; + assert( Abc_NtkIsBddLogic(pNtk) ); + Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + Counter += Abc_NodeRemoveDupFanins( pNode ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Removes one pair of duplicated fanins if present.] + + Description [Returns 1 if the node is changed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeRemoveDupFanins_int( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin1, * pFanin2; + int i, k; + assert( Abc_NtkIsBddLogic(pNode->pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + // make sure fanins are not duplicated + Abc_ObjForEachFanin( pNode, pFanin2, i ) + { + Abc_ObjForEachFanin( pNode, pFanin1, k ) + { + if ( k >= i ) + break; + if ( pFanin1 == pFanin2 ) + { + DdManager * dd = (DdManager *)pNode->pNtk->pManFunc; + DdNode * bVar1 = Cudd_bddIthVar( dd, i ); + DdNode * bVar2 = Cudd_bddIthVar( dd, k ); + DdNode * bTrans, * bTemp; + bTrans = Cudd_bddXnor( dd, bVar1, bVar2 ); Cudd_Ref( bTrans ); + pNode->pData = Cudd_bddAndAbstract( dd, bTemp = (DdNode *)pNode->pData, bTrans, bVar2 ); Cudd_Ref( (DdNode *)pNode->pData ); + Cudd_RecursiveDeref( dd, bTemp ); + Cudd_RecursiveDeref( dd, bTrans ); + Abc_NodeMinimumBase( pNode ); + return 1; + } + } + } + return 0; +} + +/**Function************************************************************* + + Synopsis [Removes duplicated fanins if present.] + + Description [Returns the number of fanins removed.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeRemoveDupFanins( Abc_Obj_t * pNode ) +{ + int Counter = 0; + while ( Abc_NodeRemoveDupFanins_int(pNode) ) + Counter++; + return Counter; +} +/**Function************************************************************* + + Synopsis [Computes support of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeSupport_rec( DdNode * bFunc, Vec_Str_t * vSupport ) +{ + if ( cuddIsConstant(bFunc) || Cudd_IsComplement(bFunc->next) ) + return; + vSupport->pArray[ bFunc->index ] = 1; + Abc_NodeSupport_rec( cuddT(bFunc), vSupport ); + Abc_NodeSupport_rec( Cudd_Regular(cuddE(bFunc)), vSupport ); + bFunc->next = Cudd_Not(bFunc->next); +} + +/**Function************************************************************* + + Synopsis [Computes support of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeSupportClear_rec( DdNode * bFunc ) +{ + if ( !Cudd_IsComplement(bFunc->next) ) + return; + bFunc->next = Cudd_Regular(bFunc->next); + if ( cuddIsConstant(bFunc) ) + return; + Abc_NodeSupportClear_rec( cuddT(bFunc) ); + Abc_NodeSupportClear_rec( Cudd_Regular(cuddE(bFunc)) ); +} + +/**Function************************************************************* + + Synopsis [Computes support of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeSupport( DdNode * bFunc, Vec_Str_t * vSupport, int nVars ) +{ + int Counter, i; + // compute the support by marking the BDD + Vec_StrFill( vSupport, nVars, 0 ); + Abc_NodeSupport_rec( bFunc, vSupport ); + // clear the marak + Abc_NodeSupportClear_rec( bFunc ); + // get the number of support variables + Counter = 0; + for ( i = 0; i < nVars; i++ ) + Counter += vSupport->pArray[i]; + return Counter; +} + + + +/**Function************************************************************* + + Synopsis [Find the number of unique variables after collapsing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeCheckDupFanin( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, int * piFanin ) +{ + Abc_Obj_t * pObj; + int i, Counter = 0; + Abc_ObjForEachFanin( pFanout, pObj, i ) + if ( pObj == pFanin ) + { + if ( piFanin ) + *piFanin = i; + Counter++; + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Find the number of unique variables after collapsing.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeCollapseSuppSize( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, Vec_Ptr_t * vFanins ) +{ + Abc_Obj_t * pObj; + int i; + Vec_PtrClear( vFanins ); + Abc_ObjForEachFanin( pFanout, pObj, i ) + if ( pObj != pFanin ) + Vec_PtrPushUnique( vFanins, pObj ); + Abc_ObjForEachFanin( pFanin, pObj, i ) + Vec_PtrPushUnique( vFanins, pObj ); + return Vec_PtrSize( vFanins ); +} + +/**Function************************************************************* + + Synopsis [Returns the index of the new fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjFaninNumberNew( Vec_Ptr_t * vFanins, Abc_Obj_t * pFanin ) +{ + Abc_Obj_t * pObj; + int i; + Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pObj, i ) + if ( pObj == pFanin ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Find the permutation map for the given node into the new order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeCollapsePermMap( Abc_Obj_t * pNode, Abc_Obj_t * pSkip, Vec_Ptr_t * vFanins, int * pPerm ) +{ + Abc_Obj_t * pFanin; + int i; + for ( i = 0; i < Vec_PtrSize(vFanins); i++ ) + pPerm[i] = i; + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( pFanin == pSkip ) + continue; + pPerm[i] = Abc_ObjFaninNumberNew( vFanins, pFanin ); + if ( pPerm[i] == -1 ) + return 0; + } + return 1; +} + + + +/**Function************************************************************* + + Synopsis [Eliminates the nodes into their fanouts if the node size does not exceed this number.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +DdNode * Abc_NodeCollapseFunc( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, Vec_Ptr_t * vFanins, int * pPermFanin, int * pPermFanout ) +{ + DdManager * dd = (DdManager *)pFanin->pNtk->pManFunc; + DdNode * bVar, * bFunc0, * bFunc1, * bTemp, * bFanin, * bFanout; + int RetValue, nSize, iFanin; + // can only eliminate if fanin occurs in the fanin list of the fanout exactly once + if ( Abc_NodeCheckDupFanin( pFanin, pFanout, &iFanin ) != 1 ) + return NULL; + // find the new number of fanins after collapsing + nSize = Abc_NodeCollapseSuppSize( pFanin, pFanout, vFanins ); + bVar = Cudd_bddIthVar( dd, nSize - 1 ); + assert( nSize <= dd->size ); + // find the permutation after collapsing + RetValue = Abc_NodeCollapsePermMap( pFanin, NULL, vFanins, pPermFanin ); + assert( RetValue ); + RetValue = Abc_NodeCollapsePermMap( pFanout, pFanin, vFanins, pPermFanout ); + assert( RetValue ); + // cofactor the local function of the node + bVar = Cudd_bddIthVar( dd, iFanin ); + bFunc0 = Cudd_Cofactor( dd, (DdNode *)pFanout->pData, Cudd_Not(bVar) ); Cudd_Ref( bFunc0 ); + bFunc1 = Cudd_Cofactor( dd, (DdNode *)pFanout->pData, bVar ); Cudd_Ref( bFunc1 ); + // find the permutation after collapsing + bFunc0 = Cudd_bddPermute( dd, bTemp = bFunc0, pPermFanout ); Cudd_Ref( bFunc0 ); + Cudd_RecursiveDeref( dd, bTemp ); + bFunc1 = Cudd_bddPermute( dd, bTemp = bFunc1, pPermFanout ); Cudd_Ref( bFunc1 ); + Cudd_RecursiveDeref( dd, bTemp ); + bFanin = Cudd_bddPermute( dd, (DdNode *)pFanin->pData, pPermFanin ); Cudd_Ref( bFanin ); + // create the new function + bFanout = Cudd_bddIte( dd, bFanin, bFunc1, bFunc0 ); Cudd_Ref( bFanout ); + Cudd_RecursiveDeref( dd, bFanin ); + Cudd_RecursiveDeref( dd, bFunc1 ); + Cudd_RecursiveDeref( dd, bFunc0 ); + Cudd_Deref( bFanout ); + return bFanout; +} +int Abc_NodeCollapse( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, Vec_Ptr_t * vFanins, int * pPermFanin, int * pPermFanout ) +{ + Abc_Obj_t * pFanoutNew, * pObj; + DdNode * bFanoutNew; + int i; + assert( Abc_NtkIsBddLogic(pFanin->pNtk) ); + assert( Abc_ObjIsNode(pFanin) ); + assert( Abc_ObjIsNode(pFanout) ); + bFanoutNew = Abc_NodeCollapseFunc( pFanin, pFanout, vFanins, pPermFanin, pPermFanout ); + if ( bFanoutNew == NULL ) + return 0; + Cudd_Ref( bFanoutNew ); + // create the new node + pFanoutNew = Abc_NtkCreateNode( pFanin->pNtk ); + Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pObj, i ) + Abc_ObjAddFanin( pFanoutNew, pObj ); + pFanoutNew->pData = bFanoutNew; + // minimize the node + Abc_NodeMinimumBase( pFanoutNew ); + // transfer the fanout + Abc_ObjTransferFanout( pFanout, pFanoutNew ); + assert( Abc_ObjFanoutNum( pFanout ) == 0 ); + Abc_NtkDeleteObj_rec( pFanout, 1 ); + return 1; +} +int Abc_NtkEliminate( Abc_Ntk_t * pNtk, int nMaxSize, int fReverse, int fVerbose ) +{ + extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose ); + Vec_Ptr_t * vFanouts, * vFanins, * vNodes; + Abc_Obj_t * pNode, * pFanout; + int * pPermFanin, * pPermFanout; + int RetValue, i, k; + assert( nMaxSize > 0 ); + assert( Abc_NtkIsLogic(pNtk) ); + // convert network to BDD representation + if ( !Abc_NtkToBdd(pNtk) ) + { + fprintf( stdout, "Converting to BDD has failed.\n" ); + return 0; + } + // prepare nodes for sweeping + //Abc_NtkRemoveDupFanins( pNtk ); + Abc_NtkMinimumBase( pNtk ); + Abc_NtkCleanup( pNtk, 0 ); + // get the nodes in the given order + vNodes = fReverse? Abc_NtkDfsReverse( pNtk ) : Abc_NtkDfs( pNtk, 0 ); + // go through the nodes and decide is they can be eliminated + pPermFanin = ABC_ALLOC( int, nMaxSize + 1000 ); + pPermFanout = ABC_ALLOC( int, nMaxSize + 1000 ); + vFanins = Vec_PtrAlloc( 1000 ); + vFanouts = Vec_PtrAlloc( 1000 ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) + { + if ( !Abc_ObjIsNode(pNode) ) // skip deleted nodes + continue; + if ( Abc_NodeFindCoFanout(pNode) != NULL ) + continue; + if ( Abc_ObjFaninNum(pNode) > nMaxSize ) + continue; + Abc_ObjForEachFanout( pNode, pFanout, k ) + if ( Abc_NodeCollapseSuppSize(pNode, pFanout, vFanins) > nMaxSize ) + break; + if ( k < Abc_ObjFanoutNum(pNode) ) + continue; + // perform elimination + Abc_NodeCollectFanouts( pNode, vFanouts ); + Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, k ) + { + if ( fVerbose ) + printf( "Collapsing fanin %5d (supp =%2d) into fanout %5d (supp =%2d) ", + Abc_ObjId(pNode), Abc_ObjFaninNum(pNode), Abc_ObjId(pFanout), Abc_ObjFaninNum(pFanout) ); + RetValue = Abc_NodeCollapse( pNode, pFanout, vFanins, pPermFanin, pPermFanout ); + assert( RetValue ); + if ( fVerbose ) + { + Abc_Obj_t * pNodeNew = Abc_NtkObj( pNtk, Abc_NtkObjNumMax(pNtk) - 1 ); + if ( pNodeNew ) + printf( "resulting in node %5d (supp =%2d).\n", Abc_ObjId(pNodeNew), Abc_ObjFaninNum(pNodeNew) ); + } + } + } + Abc_NtkBddReorder( pNtk, 0 ); + Vec_PtrFree( vFanins ); + Vec_PtrFree( vFanouts ); + Vec_PtrFree( vNodes ); + ABC_FREE( pPermFanin ); + ABC_FREE( pPermFanout ); + return 1; +} + + + +/**Function************************************************************* + + Synopsis [Check how many times fanin appears in the FF of the fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeCountAppearances( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout ) +{ + Hop_Man_t * pMan = (Hop_Man_t *)pFanin->pNtk->pManFunc; + int iFanin = Abc_NodeFindFanin( pFanout, pFanin ); + assert( iFanin >= 0 && iFanin < Hop_ManPiNum(pMan) ); + return Hop_ObjFanoutCount( (Hop_Obj_t *)pFanout->pData, Hop_IthVar(pMan, iFanin) ); +} +int Abc_NodeCountAppearancesAll( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanout; + int i, Count = 0; + Abc_ObjForEachFanout( pNode, pFanout, i ) + Count += Abc_NodeCountAppearances( pNode, pFanout ); + return Count; +} + +/**Function************************************************************* + + Synopsis [Performs traditional eliminate -1.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Hop_Obj_t * Abc_NodeCollapseFunc1( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, Vec_Ptr_t * vFanins, int * pPermFanin, int * pPermFanout ) +{ + Hop_Man_t * pMan = (Hop_Man_t *)pFanin->pNtk->pManFunc; + Hop_Obj_t * bFanin, * bFanout; + int RetValue, nSize, iFanin; + // can only eliminate if fanin occurs in the fanin list of the fanout exactly once + if ( Abc_NodeCheckDupFanin( pFanin, pFanout, &iFanin ) != 1 ) + return NULL; + // find the new number of fanins after collapsing + nSize = Abc_NodeCollapseSuppSize( pFanin, pFanout, vFanins ); + Hop_IthVar( pMan, nSize ); // use additional var for fanin variable + assert( nSize + 1 <= Hop_ManPiNum(pMan) ); + // find the permutation after collapsing + RetValue = Abc_NodeCollapsePermMap( pFanin, NULL, vFanins, pPermFanin ); + assert( RetValue ); + RetValue = Abc_NodeCollapsePermMap( pFanout, pFanin, vFanins, pPermFanout ); + assert( RetValue ); + // include fanin's variable + pPermFanout[iFanin] = nSize; + // create new function of fanin and fanout + bFanin = Hop_Permute( pMan, (Hop_Obj_t *)pFanin->pData, Abc_ObjFaninNum(pFanin), pPermFanin ); + bFanout = Hop_Permute( pMan, (Hop_Obj_t *)pFanout->pData, Abc_ObjFaninNum(pFanout), pPermFanout ); + // compose fanin into fanout + return Hop_Compose( pMan, bFanout, bFanin, nSize ); +} +int Abc_NodeCollapse1( Abc_Obj_t * pFanin, Abc_Obj_t * pFanout, Vec_Ptr_t * vFanins, int * pPermFanin, int * pPermFanout ) +{ + Abc_Obj_t * pFanoutNew, * pObj; + Hop_Obj_t * bFanoutNew; + int i; + assert( Abc_NtkIsAigLogic(pFanin->pNtk) ); + assert( Abc_ObjIsNode(pFanin) ); + assert( Abc_ObjIsNode(pFanout) ); + bFanoutNew = Abc_NodeCollapseFunc1( pFanin, pFanout, vFanins, pPermFanin, pPermFanout ); + if ( bFanoutNew == NULL ) + return 0; + // create the new node + pFanoutNew = Abc_NtkCreateNode( pFanin->pNtk ); + Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pObj, i ) + Abc_ObjAddFanin( pFanoutNew, pObj ); + pFanoutNew->pData = bFanoutNew; + // transfer the fanout + Abc_ObjTransferFanout( pFanout, pFanoutNew ); + assert( Abc_ObjFanoutNum( pFanout ) == 0 ); + Abc_NtkDeleteObj_rec( pFanout, 1 ); + return 1; +} +int Abc_NodeIsExor( Abc_Obj_t * pNode ) +{ + Hop_Man_t * pMan; + word Truth; + if ( Abc_ObjFaninNum(pNode) < 3 || Abc_ObjFaninNum(pNode) > 6 ) + return 0; + pMan = (Hop_Man_t *)pNode->pNtk->pManFunc; + Truth = Hop_ManComputeTruth6( pMan, (Hop_Obj_t *)pNode->pData, Abc_ObjFaninNum(pNode) ); + if ( Truth == 0x6666666666666666 || Truth == 0x9999999999999999 || + Truth == 0x9696969696969696 || Truth == 0x6969696969696969 || + Truth == 0x6996699669966996 || Truth == 0x9669966996699669 || + Truth == 0x9669699696696996 || Truth == 0x6996966969969669 || + Truth == 0x6996966996696996 || Truth == 0x9669699669969669 ) + return 1; + return 0; +} +int Abc_NtkEliminate1One( Abc_Ntk_t * pNtk, int ElimValue, int nMaxSize, int fReverse, int fVerbose ) +{ + Vec_Ptr_t * vFanouts, * vFanins, * vNodes; + Abc_Obj_t * pNode, * pFanout; + int * pPermFanin, * pPermFanout; + int RetValue, i, k; + assert( nMaxSize > 0 ); + assert( Abc_NtkIsLogic(pNtk) ); + // convert network to BDD representation + if ( !Abc_NtkToAig(pNtk) ) + { + fprintf( stdout, "Converting to AIG has failed.\n" ); + return 0; + } + // get the nodes in the given order + vNodes = fReverse? Abc_NtkDfsReverse( pNtk ) : Abc_NtkDfs( pNtk, 0 ); + // go through the nodes and decide is they can be eliminated + pPermFanin = ABC_ALLOC( int, nMaxSize + 1000 ); + pPermFanout = ABC_ALLOC( int, nMaxSize + 1000 ); + vFanins = Vec_PtrAlloc( 1000 ); + vFanouts = Vec_PtrAlloc( 1000 ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) + { + if ( !Abc_ObjIsNode(pNode) ) // skip deleted nodes + continue; + if ( Abc_NodeFindCoFanout(pNode) != NULL ) + continue; + if ( Abc_ObjFaninNum(pNode) > nMaxSize ) + continue; + if ( Abc_NodeIsExor(pNode) ) + continue; + // skip nodes with more than one fanout +// if ( Abc_ObjFanoutNum(pNode) != 1 ) +// continue; + // skip nodes that appear in the FF of their fanout more than once + if ( Abc_NodeCountAppearancesAll( pNode ) > ElimValue + 2 ) + continue; + Abc_ObjForEachFanout( pNode, pFanout, k ) + if ( Abc_NodeCollapseSuppSize(pNode, pFanout, vFanins) > nMaxSize ) + break; + if ( k < Abc_ObjFanoutNum(pNode) ) + continue; + // perform elimination + Abc_NodeCollectFanouts( pNode, vFanouts ); + Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, k ) + { + if ( fVerbose ) + printf( "Collapsing fanin %5d (supp =%2d) into fanout %5d (supp =%2d) ", + Abc_ObjId(pNode), Abc_ObjFaninNum(pNode), Abc_ObjId(pFanout), Abc_ObjFaninNum(pFanout) ); + RetValue = Abc_NodeCollapse1( pNode, pFanout, vFanins, pPermFanin, pPermFanout ); + assert( RetValue ); + if ( fVerbose ) + { + Abc_Obj_t * pNodeNew = Abc_NtkObj( pNtk, Abc_NtkObjNumMax(pNtk) - 1 ); + if ( pNodeNew ) + printf( "resulting in node %5d (supp =%2d).\n", Abc_ObjId(pNodeNew), Abc_ObjFaninNum(pNodeNew) ); + } + } + } + Vec_PtrFree( vFanins ); + Vec_PtrFree( vFanouts ); + Vec_PtrFree( vNodes ); + ABC_FREE( pPermFanin ); + ABC_FREE( pPermFanout ); + return 1; +} +int Abc_NtkEliminate1( Abc_Ntk_t * pNtk, int ElimValue, int nMaxSize, int nIterMax, int fReverse, int fVerbose ) +{ + int i; + for ( i = 0; i < nIterMax; i++ ) + { + int nNodes = Abc_NtkNodeNum(pNtk); +// printf( "%d ", nNodes ); + if ( !Abc_NtkEliminate1One(pNtk, ElimValue, nMaxSize, fReverse, fVerbose) ) + return 0; + if ( nNodes == Abc_NtkNodeNum(pNtk) ) + break; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Sort nodes in the reverse topo order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjCompareByNumber( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) +{ + return Abc_ObjRegular(*pp1)->iTemp - Abc_ObjRegular(*pp2)->iTemp; +} +void Abc_ObjSortInReverseOrder( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes ) +{ + Vec_Ptr_t * vOrder; + Abc_Obj_t * pNode; + int i; + vOrder = Abc_NtkDfsReverse( pNtk ); + Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pNode, i ) + pNode->iTemp = i; + Vec_PtrSort( vNodes, (int (*)(const void *, const void *))Abc_ObjCompareByNumber ); + Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pNode, i ) + pNode->iTemp = 0; + Vec_PtrFree( vOrder ); +} + + +/**Function************************************************************* + + Synopsis [Performs traditional eliminate -1.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkEliminateSpecial( Abc_Ntk_t * pNtk, int nMaxSize, int fVerbose ) +{ + extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose ); + Vec_Ptr_t * vFanouts, * vFanins, * vNodes; + Abc_Obj_t * pNode, * pFanout; + int * pPermFanin, * pPermFanout; + int RetValue, i, k; + assert( nMaxSize > 0 ); + assert( Abc_NtkIsLogic(pNtk) ); + + + // convert network to BDD representation + if ( !Abc_NtkToBdd(pNtk) ) + { + fprintf( stdout, "Converting to BDD has failed.\n" ); + return 0; + } + + // prepare nodes for sweeping + //Abc_NtkRemoveDupFanins( pNtk ); + Abc_NtkMinimumBase( pNtk ); + Abc_NtkCleanup( pNtk, 0 ); + + // convert network to SOPs + if ( !Abc_NtkToSop(pNtk, -1, ABC_INFINITY) ) + { + fprintf( stdout, "Converting to SOP has failed.\n" ); + return 0; + } + + // collect info about the nodes to be eliminated + vNodes = Vec_PtrAlloc( 1000 ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_ObjFanoutNum(pNode) != 1 ) + continue; + pFanout = Abc_ObjFanout0(pNode); + if ( !Abc_ObjIsNode(pFanout) ) + continue; + if ( Abc_SopGetCubeNum((char *)pNode->pData) != 1 ) + continue; + if ( Abc_SopGetCubeNum((char *)pFanout->pData) != 1 ) + continue; + // find the fanout's fanin + RetValue = Abc_NodeFindFanin( pFanout, pNode ); + assert( RetValue >= 0 && RetValue < Abc_ObjFaninNum(pFanout) ); + // both pNode and pFanout are AND/OR type nodes + if ( Abc_SopIsComplement((char *)pNode->pData) == Abc_SopGetIthCareLit((char *)pFanout->pData, RetValue) ) + continue; + Vec_PtrPush( vNodes, pNode ); + } + if ( Vec_PtrSize(vNodes) == 0 ) + { + Vec_PtrFree( vNodes ); + return 1; + } + Abc_ObjSortInReverseOrder( pNtk, vNodes ); + + // convert network to BDD representation + if ( !Abc_NtkToBdd(pNtk) ) + { + fprintf( stdout, "Converting to BDD has failed.\n" ); + return 0; + } + + // go through the nodes and decide is they can be eliminated + pPermFanin = ABC_ALLOC( int, nMaxSize + 1000 ); + pPermFanout = ABC_ALLOC( int, nMaxSize + 1000 ); + vFanins = Vec_PtrAlloc( 1000 ); + vFanouts = Vec_PtrAlloc( 1000 ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) + { + assert( Abc_ObjIsNode(pNode) ); + assert( Abc_NodeFindCoFanout(pNode) == NULL ); + // perform elimination + Abc_NodeCollectFanouts( pNode, vFanouts ); + Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, k ) + { + if ( fVerbose ) + printf( "Collapsing fanin %5d (supp =%2d) into fanout %5d (supp =%2d) ", + Abc_ObjId(pNode), Abc_ObjFaninNum(pNode), Abc_ObjId(pFanout), Abc_ObjFaninNum(pFanout) ); + RetValue = Abc_NodeCollapse( pNode, pFanout, vFanins, pPermFanin, pPermFanout ); + assert( RetValue ); + if ( fVerbose ) + { + Abc_Obj_t * pNodeNew = Abc_NtkObj( pNtk, Abc_NtkObjNumMax(pNtk) - 1 ); + if ( pNodeNew ) + printf( "resulting in node %5d (supp =%2d).\n", Abc_ObjId(pNodeNew), Abc_ObjFaninNum(pNodeNew) ); + } + } + } + Abc_NtkBddReorder( pNtk, 0 ); + Vec_PtrFree( vFanins ); + Vec_PtrFree( vFanouts ); + Vec_PtrFree( vNodes ); + ABC_FREE( pPermFanin ); + ABC_FREE( pPermFanout ); + return 1; +} + +#else + +int Abc_NtkMinimumBase( Abc_Ntk_t * pNtk ) { return 0; } +int Abc_NodeMinimumBase( Abc_Obj_t * pNode ) { return 0; } +int Abc_NtkRemoveDupFanins( Abc_Ntk_t * pNtk ) { return 0; } +int Abc_NtkEliminateSpecial( Abc_Ntk_t * pNtk, int nMaxSize, int fVerbose ) { return 0; } +int Abc_NtkEliminate( Abc_Ntk_t * pNtk, int nMaxSize, int fReverse, int fVerbose ) { return 0; } +int Abc_NtkEliminate1( Abc_Ntk_t * pNtk, int ElimValue, int nMaxSize, int nIterMax, int fReverse, int fVerbose ) { return 0; } + +#endif + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/abcNames.c b/yosys/abc/src/base/abc/abcNames.c new file mode 100644 index 00000000000..dec5f01e0b0 --- /dev/null +++ b/yosys/abc/src/base/abc/abcNames.c @@ -0,0 +1,813 @@ +/**CFile**************************************************************** + + FileName [abcNames.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures working with net and node names.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcNames.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "misc/util/utilNam.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the unique name for the object.] + + Description [If the name previously did not exist, creates a new unique + name but does not assign this name to the object. The temporary unique + name is stored in a static buffer inside this procedure. It is important + that the name is used before the function is called again!] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_ObjName( Abc_Obj_t * pObj ) +{ + return Nm_ManCreateUniqueName( pObj->pNtk->pManName, pObj->Id ); +} + +/**Function************************************************************* + + Synopsis [Assigns the given name to the object.] + + Description [The object should not have a name assigned. The same + name may be used for several objects, which they share the same net + in the original netlist. (For example, latch output and primary output + may have the same name.) This procedure returns the pointer to the + internally stored representation of the given name.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_ObjAssignName( Abc_Obj_t * pObj, char * pName, char * pSuffix ) +{ + assert( pName != NULL ); + return Nm_ManStoreIdName( pObj->pNtk->pManName, pObj->Id, pObj->Type, pName, pSuffix ); +} + +/**Function************************************************************* + + Synopsis [Appends name to the prefix] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_ObjNamePrefix( Abc_Obj_t * pObj, char * pPrefix ) +{ + static char Buffer[2000]; + sprintf( Buffer, "%s%s", pPrefix, Abc_ObjName(pObj) ); + return Buffer; +} + +/**Function************************************************************* + + Synopsis [Appends suffic to the name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_ObjNameSuffix( Abc_Obj_t * pObj, char * pSuffix ) +{ + static char Buffer[2000]; + sprintf( Buffer, "%s%s", Abc_ObjName(pObj), pSuffix ); + return Buffer; +} + +/**Function************************************************************* + + Synopsis [Returns the dummy PI name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_ObjNameDummy( char * pPrefix, int Num, int nDigits ) +{ + static char Buffer[2000]; + sprintf( Buffer, "%s%0*d", pPrefix, nDigits, Num ); + return Buffer; +} + +/**Function************************************************************* + + Synopsis [Tranfers names to the old network.] + + Description [Assumes that the new nodes are attached using pObj->pCopy.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTrasferNames( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) +{ + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) ); + assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkNew) ); + assert( Abc_NtkBoxNum(pNtk) == Abc_NtkBoxNum(pNtkNew) ); + assert( Nm_ManNumEntries(pNtk->pManName) > 0 ); + assert( Nm_ManNumEntries(pNtkNew->pManName) == 0 ); + // copy the CI/CO/box names + Abc_NtkForEachCi( pNtk, pObj, i ) + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanout0Ntk(pObj)), NULL ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanin0Ntk(pObj)), NULL ); + Abc_NtkForEachBox( pNtk, pObj, i ) + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); +} + +/**Function************************************************************* + + Synopsis [Tranfers names to the old network.] + + Description [Assumes that the new nodes are attached using pObj->pCopy.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTrasferNamesNoLatches( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) +{ + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) ); + assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkNew) ); + assert( Nm_ManNumEntries(pNtk->pManName) > 0 ); + assert( Nm_ManNumEntries(pNtkNew->pManName) == 0 ); + // copy the CI/CO/box name and skip latches and theirs inputs/outputs + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_ObjFaninNum(pObj) == 0 || !Abc_ObjIsLatch(Abc_ObjFanin0(pObj)) ) + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanout0Ntk(pObj)), NULL ); + Abc_NtkForEachCo( pNtk, pObj, i ) + if ( Abc_ObjFanoutNum(pObj) == 0 || !Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) ) + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanin0Ntk(pObj)), NULL ); + Abc_NtkForEachBox( pNtk, pObj, i ) + if ( !Abc_ObjIsLatch(pObj) ) + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); +} + +/**Function************************************************************* + + Synopsis [Gets fanin node names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NodeGetFaninNames( Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pFanin; + int i; + vNodes = Vec_PtrAlloc( 100 ); + Abc_ObjForEachFanin( pNode, pFanin, i ) + Vec_PtrPush( vNodes, Abc_UtilStrsav(Abc_ObjName(pFanin)) ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Gets fanin node names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NodeGetFakeNames( int nNames ) +{ + Vec_Ptr_t * vNames; + char Buffer[5]; + int i; + + vNames = Vec_PtrAlloc( nNames ); + for ( i = 0; i < nNames; i++ ) + { + if ( nNames < 26 ) + { + Buffer[0] = 'a' + i; + Buffer[1] = 0; + } + else + { + Buffer[0] = 'a' + i%26; + Buffer[1] = '0' + i/26; + Buffer[2] = 0; + } + Vec_PtrPush( vNames, Extra_UtilStrsav(Buffer) ); + } + return vNames; +} + +/**Function************************************************************* + + Synopsis [Gets fanin node names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeFreeNames( Vec_Ptr_t * vNames ) +{ + int i; + if ( vNames == NULL ) + return; + for ( i = 0; i < vNames->nSize; i++ ) + ABC_FREE( vNames->pArray[i] ); + Vec_PtrFree( vNames ); +} + +/**Function************************************************************* + + Synopsis [Collects the CI or CO names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char ** Abc_NtkCollectCioNames( Abc_Ntk_t * pNtk, int fCollectCos ) +{ + Abc_Obj_t * pObj; + char ** ppNames; + int i; + if ( fCollectCos ) + { + ppNames = ABC_ALLOC( char *, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + ppNames[i] = Abc_ObjName(pObj); + } + else + { + ppNames = ABC_ALLOC( char *, Abc_NtkCiNum(pNtk) ); + Abc_NtkForEachCi( pNtk, pObj, i ) + ppNames[i] = Abc_ObjName(pObj); + } + return ppNames; +} + +/**Function************************************************************* + + Synopsis [Orders PIs/POs/latches alphabetically.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeCompareNames( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) +{ + int Diff = strcmp( (char *)(*pp1)->pCopy, (char *)(*pp2)->pCopy ); + if ( Diff < 0 ) + return -1; + if ( Diff > 0 ) + return 1; + Diff = (*pp1)->Id - (*pp2)->Id; + if ( Diff < 0 ) + return -1; + if ( Diff > 0 ) + return 1; + return 0; +} +void Abc_NtkOrderObjsByName( Abc_Ntk_t * pNtk, int fComb ) +{ + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); + // temporarily store the names in the copy field + Abc_NtkForEachPi( pNtk, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(pObj); + Abc_NtkForEachPo( pNtk, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(pObj); + Abc_NtkForEachBox( pNtk, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)Abc_ObjName(Abc_ObjFanout0(pObj)); + // order objects alphabetically + qsort( (void *)Vec_PtrArray(pNtk->vPis), (size_t)Vec_PtrSize(pNtk->vPis), sizeof(Abc_Obj_t *), + (int (*)(const void *, const void *)) Abc_NodeCompareNames ); + qsort( (void *)Vec_PtrArray(pNtk->vPos), (size_t)Vec_PtrSize(pNtk->vPos), sizeof(Abc_Obj_t *), + (int (*)(const void *, const void *)) Abc_NodeCompareNames ); + // if the comparison if combinational (latches as PIs/POs), order them too + if ( fComb ) + qsort( (void *)Vec_PtrArray(pNtk->vBoxes), (size_t)Vec_PtrSize(pNtk->vBoxes), sizeof(Abc_Obj_t *), + (int (*)(const void *, const void *)) Abc_NodeCompareNames ); + // order CIs/COs first PIs/POs(Asserts) then latches + Abc_NtkOrderCisCos( pNtk ); + // clean the copy fields + Abc_NtkForEachPi( pNtk, pObj, i ) + pObj->pCopy = NULL; + Abc_NtkForEachPo( pNtk, pObj, i ) + pObj->pCopy = NULL; + Abc_NtkForEachBox( pNtk, pObj, i ) + pObj->pCopy = NULL; +} + +/**Function************************************************************* + + Synopsis [Creates name manager storing input/output names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Nam_t * Abc_NtkNameMan( Abc_Ntk_t * p, int fOuts ) +{ + if ( fOuts ) + { + Abc_Obj_t * pObj; int i; + Abc_Nam_t * pStrsCo = Abc_NamStart( Abc_NtkCoNum(p), 24 ); + Abc_NtkForEachCo( p, pObj, i ) + Abc_NamStrFindOrAdd( pStrsCo, Abc_ObjName(pObj), NULL ); + assert( Abc_NamObjNumMax(pStrsCo) == i + 1 ); + return pStrsCo; + } + else + { + Abc_Obj_t * pObj; int i; + Abc_Nam_t * pStrsCi = Abc_NamStart( Abc_NtkCiNum(p), 24 ); + Abc_NtkForEachCi( p, pObj, i ) + Abc_NamStrFindOrAdd( pStrsCi, Abc_ObjName(pObj), NULL ); + assert( Abc_NamObjNumMax(pStrsCi) == i + 1 ); + return pStrsCi; + } +} + +/**Function************************************************************* + + Synopsis [Orders PIs/POs/latches alphabetically.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeCompareIndexes( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) +{ + int Diff = (*pp1)->iTemp - (*pp2)->iTemp; + if ( Diff < 0 ) + return -1; + if ( Diff > 0 ) + return 1; + return 0; +} +void Abc_NtkTransferOrder( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ) +{ + Abc_Obj_t * pObj; int i; + Abc_Nam_t * pStrsCi = Abc_NtkNameMan( pNtkOld, 0 ); + Abc_Nam_t * pStrsCo = Abc_NtkNameMan( pNtkOld, 1 ); + assert( Abc_NtkPiNum(pNtkOld) == Abc_NtkPiNum(pNtkNew) ); + assert( Abc_NtkPoNum(pNtkOld) == Abc_NtkPoNum(pNtkNew) ); + assert( Abc_NtkLatchNum(pNtkOld) == Abc_NtkLatchNum(pNtkNew) ); + // transfer to the new network + Abc_NtkForEachCi( pNtkNew, pObj, i ) + { + pObj->iTemp = Abc_NamStrFind(pStrsCi, Abc_ObjName(pObj)); + assert( pObj->iTemp > 0 && pObj->iTemp <= Abc_NtkCiNum(pNtkNew) ); + } + Abc_NtkForEachCo( pNtkNew, pObj, i ) + { + pObj->iTemp = Abc_NamStrFind(pStrsCo, Abc_ObjName(pObj)); + assert( pObj->iTemp > 0 && pObj->iTemp <= Abc_NtkCoNum(pNtkNew) ); + } + Abc_NamDeref( pStrsCi ); + Abc_NamDeref( pStrsCo ); + // order PI/PO + qsort( (void *)Vec_PtrArray(pNtkNew->vPis), (size_t)Vec_PtrSize(pNtkNew->vPis), sizeof(Abc_Obj_t *), + (int (*)(const void *, const void *)) Abc_NodeCompareIndexes ); + qsort( (void *)Vec_PtrArray(pNtkNew->vPos), (size_t)Vec_PtrSize(pNtkNew->vPos), sizeof(Abc_Obj_t *), + (int (*)(const void *, const void *)) Abc_NodeCompareIndexes ); + // order CI/CO + qsort( (void *)Vec_PtrArray(pNtkNew->vCis), (size_t)Vec_PtrSize(pNtkNew->vCis), sizeof(Abc_Obj_t *), + (int (*)(const void *, const void *)) Abc_NodeCompareIndexes ); + qsort( (void *)Vec_PtrArray(pNtkNew->vCos), (size_t)Vec_PtrSize(pNtkNew->vCos), sizeof(Abc_Obj_t *), + (int (*)(const void *, const void *)) Abc_NodeCompareIndexes ); + // order CIs/COs first PIs/POs(Asserts) then latches + //Abc_NtkOrderCisCos( pNtk ); + // clean the copy fields + Abc_NtkForEachCi( pNtkNew, pObj, i ) + pObj->iTemp = 0; + Abc_NtkForEachCo( pNtkNew, pObj, i ) + pObj->iTemp = 0; +} + +/**Function************************************************************* + + Synopsis [Checks that the order and number of CI/CO is the same.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeCompareCiCo( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew ) +{ + int i; + if ( Abc_NtkPiNum(pNtkOld) != Abc_NtkPiNum(pNtkNew) ) + return 0; + if ( Abc_NtkPoNum(pNtkOld) != Abc_NtkPoNum(pNtkNew) ) + return 0; + if ( Abc_NtkLatchNum(pNtkOld) != Abc_NtkLatchNum(pNtkNew) ) + return 0; + for ( i = 0; i < Abc_NtkCiNum(pNtkOld); i++ ) + if ( strcmp(Abc_ObjName(Abc_NtkCi(pNtkOld, i)), Abc_ObjName(Abc_NtkCi(pNtkNew, i))) ) + return 0; + for ( i = 0; i < Abc_NtkCoNum(pNtkOld); i++ ) + if ( strcmp(Abc_ObjName(Abc_NtkCo(pNtkOld, i)), Abc_ObjName(Abc_NtkCo(pNtkNew, i))) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Adds dummy names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAddDummyPiNames( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int nDigits, i; + nDigits = Abc_Base10Log( Abc_NtkPiNum(pNtk) ); + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_ObjAssignName( pObj, Abc_ObjNameDummy("pi", i, nDigits), NULL ); +} + +/**Function************************************************************* + + Synopsis [Adds dummy names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAddDummyPoNames( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int nDigits, i; + nDigits = Abc_Base10Log( Abc_NtkPoNum(pNtk) ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_ObjAssignName( pObj, Abc_ObjNameDummy("po", i, nDigits), NULL ); +} + +/**Function************************************************************* + + Synopsis [Adds dummy names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAddDummyBoxNames( Abc_Ntk_t * pNtk ) +{ + char * pName, PrefLi[100], PrefLo[100]; + Abc_Obj_t * pObj; + int nDigits, i, k, CountCur, CountMax = 0; + // if PIs/POs already have nodes with what looks like latch names + // we need to add different prefix for the new latches + Abc_NtkForEachPi( pNtk, pObj, i ) + { + CountCur = 0; + pName = Abc_ObjName(pObj); + for ( k = 0; pName[k]; k++ ) + if ( pName[k] == 'l' ) + CountCur++; + else + break; + CountMax = Abc_MaxInt( CountMax, CountCur ); + } + Abc_NtkForEachPo( pNtk, pObj, i ) + { + CountCur = 0; + pName = Abc_ObjName(pObj); + for ( k = 0; pName[k]; k++ ) + if ( pName[k] == 'l' ) + CountCur++; + else + break; + CountMax = Abc_MaxInt( CountMax, CountCur ); + } +//printf( "CountMax = %d\n", CountMax ); + assert( CountMax < 100-2 ); + for ( i = 0; i <= CountMax; i++ ) + PrefLi[i] = PrefLo[i] = 'l'; + PrefLi[i] = 'i'; + PrefLo[i] = 'o'; + PrefLi[i+1] = 0; + PrefLo[i+1] = 0; + // create latch names + assert( !Abc_NtkIsNetlist(pNtk) ); + nDigits = Abc_Base10Log( Abc_NtkLatchNum(pNtk) ); + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + Abc_ObjAssignName( pObj, Abc_ObjNameDummy("l", i, nDigits), NULL ); + Abc_ObjAssignName( Abc_ObjFanin0(pObj), Abc_ObjNameDummy(PrefLi, i, nDigits), NULL ); + Abc_ObjAssignName( Abc_ObjFanout0(pObj), Abc_ObjNameDummy(PrefLo, i, nDigits), NULL ); + } +/* + nDigits = Abc_Base10Log( Abc_NtkBlackboxNum(pNtk) ); + Abc_NtkForEachBlackbox( pNtk, pObj, i ) + { + pName = Abc_ObjAssignName( pObj, Abc_ObjNameDummy("B", i, nDigits), NULL ); + nDigitsF = Abc_Base10Log( Abc_ObjFaninNum(pObj) ); + Abc_ObjForEachFanin( pObj, pTerm, k ) + Abc_ObjAssignName( Abc_ObjFanin0(pObj), pName, Abc_ObjNameDummy("i", k, nDigitsF) ); + nDigitsF = Abc_Base10Log( Abc_ObjFanoutNum(pObj) ); + Abc_ObjForEachFanout( pObj, pTerm, k ) + Abc_ObjAssignName( Abc_ObjFanin0(pObj), pName, Abc_ObjNameDummy("o", k, nDigitsF) ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Replaces names by short names.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkShortNames( Abc_Ntk_t * pNtk ) +{ + Nm_ManFree( pNtk->pManName ); + pNtk->pManName = Nm_ManCreate( Abc_NtkCiNum(pNtk) + Abc_NtkCoNum(pNtk) + Abc_NtkBoxNum(pNtk) ); + Abc_NtkAddDummyPiNames( pNtk ); + Abc_NtkAddDummyPoNames( pNtk ); + Abc_NtkAddDummyBoxNames( pNtk ); +} +void Abc_NtkCleanNames( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; int i; + Nm_Man_t * pManName = Nm_ManCreate( Abc_NtkCiNum(pNtk) + Abc_NtkCoNum(pNtk) + Abc_NtkBoxNum(pNtk) ); + Abc_NtkForEachCi( pNtk, pObj, i ) + Nm_ManStoreIdName( pManName, pObj->Id, pObj->Type, Abc_ObjName(pObj), NULL ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Nm_ManStoreIdName( pManName, pObj->Id, pObj->Type, Abc_ObjName(pObj), NULL ); + Nm_ManFree( pNtk->pManName ); + pNtk->pManName = pManName; +} + +/**Function************************************************************* + + Synopsis [Moves names from the other network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRedirectCiCo( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj, * pObjCi, * pFanin; + int i, Count = 0; + // if CO points to CI with the same name, remove buffer between them + Abc_NtkForEachCo( pNtk, pObj, i ) + { + int nCiId = Nm_ManFindIdByNameTwoTypes( pNtk->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO ); + if ( nCiId == -1 ) + continue; + pObjCi = Abc_NtkObj( pNtk, nCiId ); + assert( !strcmp( Abc_ObjName(pObj), Abc_ObjName(pObjCi) ) ); + pFanin = Abc_ObjFanin0(pObj); + if ( pFanin == pObjCi ) + continue; + assert( Abc_NodeIsBuf(pFanin) ); + Abc_ObjPatchFanin( pObj, pFanin, pObjCi ); + if ( Abc_ObjFanoutNum(pFanin) == 0 ) + Abc_NtkDeleteObj( pFanin ); + Count++; + } + if ( Count ) + printf( "Redirected %d POs from buffers to PIs with the same name.\n", Count ); +} +void Abc_NtkMoveNames( Abc_Ntk_t * pNtk, Abc_Ntk_t * pOld ) +{ + Abc_Obj_t * pObj; int i; + Nm_ManFree( pNtk->pManName ); + pNtk->pManName = Nm_ManCreate( Abc_NtkCiNum(pNtk) + Abc_NtkCoNum(pNtk) + Abc_NtkBoxNum(pNtk) ); + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_ObjAssignName( pObj, Abc_ObjName(Abc_NtkPi(pOld, i)), NULL ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_ObjAssignName( pObj, Abc_ObjName(Abc_NtkPo(pOld, i)), NULL ); + Abc_NtkForEachLatch( pNtk, pObj, i ) + { + Abc_ObjAssignName( Abc_ObjFanin0(pObj), Abc_ObjName(Abc_ObjFanin0(Abc_NtkBox(pOld, i))), NULL ); + Abc_ObjAssignName( Abc_ObjFanout0(pObj), Abc_ObjName(Abc_ObjFanout0(Abc_NtkBox(pOld, i))), NULL ); + } + Abc_NtkRedirectCiCo( pNtk ); +} + + +/**Function************************************************************* + + Synopsis [Saves name IDs into a file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkStartNameIds( Abc_Ntk_t * p ) +{ + char pFileName[1000]; + FILE * pFile; + Abc_Obj_t * pObj, * pFanin; + Vec_Ptr_t * vNodes; + int i, Counter = 1; + assert( Abc_NtkIsNetlist(p) ); + assert( p->vNameIds == NULL ); + assert( strlen(p->pSpec) < 1000 ); + sprintf( pFileName, "%s_%s_names.txt", Extra_FileNameGenericAppend(p->pSpec,""), Extra_FileNameExtension(p->pSpec) ); + pFile = fopen( pFileName, "wb" ); + p->vNameIds = Vec_IntStart( Abc_NtkObjNumMax(p) ); + // add inputs + Abc_NtkForEachCi( p, pObj, i ) + fprintf( pFile, "%s \n", Abc_ObjName(Abc_ObjFanout0(pObj)) ), Vec_IntWriteEntry(p->vNameIds, Abc_ObjId(pObj), 2*Counter++); + // add outputs + Abc_NtkForEachCo( p, pObj, i ) + { + pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pObj)); + if ( !Vec_IntEntry(p->vNameIds, Abc_ObjId(pFanin)) ) + fprintf( pFile, "%s \n", Abc_ObjName(Abc_ObjFanout0(pFanin)) ), Vec_IntWriteEntry(p->vNameIds, Abc_ObjId(pFanin), 2*Counter++); + } + // add nodes in a topo order + vNodes = Abc_NtkDfs( p, 1 ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + if ( !Vec_IntEntry(p->vNameIds, Abc_ObjId(pObj)) ) + fprintf( pFile, "%s \n", Abc_ObjName(Abc_ObjFanout0(pObj)) ), Vec_IntWriteEntry(p->vNameIds, Abc_ObjId(pObj), 2*Counter++); + Vec_PtrFree( vNodes ); + fclose( pFile ); + // transfer driver node names to COs + Abc_NtkForEachCo( p, pObj, i ) + { + pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pObj)); + Vec_IntWriteEntry( p->vNameIds, Abc_ObjId(pObj), Vec_IntEntry(p->vNameIds, Abc_ObjId(pFanin)) ); + Vec_IntWriteEntry( p->vNameIds, Abc_ObjId(pFanin), 0 ); + } +} + +/**Function************************************************************* + + Synopsis [Remaps the AIG from the old manager into the new manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTransferNameIds( Abc_Ntk_t * p, Abc_Ntk_t * pNew ) +{ + Abc_Obj_t * pObj, * pObjNew; + int i; + assert( p->vNameIds != NULL ); + assert( pNew->vNameIds == NULL ); + pNew->vNameIds = Vec_IntStart( Abc_NtkObjNumMax(pNew) ); +// Abc_NtkForEachCi( p, pObj, i ) +// printf( "%d ", Vec_IntEntry(p->vNameIds, Abc_ObjId(pObj)) ); +// printf( "\n" ); + Abc_NtkForEachObj( p, pObj, i ) + if ( pObj->pCopy && i < Vec_IntSize(p->vNameIds) && Vec_IntEntry(p->vNameIds, i) ) + { + pObjNew = Abc_ObjRegular(pObj->pCopy); + assert( Abc_ObjNtk(pObjNew) == pNew ); + if ( Abc_ObjIsCi(pObjNew) && !Abc_ObjIsCi(pObj) ) // do not overwrite CI name by internal node name + continue; + Vec_IntWriteEntry( pNew->vNameIds, Abc_ObjId(pObjNew), Vec_IntEntry(p->vNameIds, i) ^ Abc_ObjIsComplement(pObj->pCopy) ); + } +} + +/**Function************************************************************* + + Synopsis [Updates file with name IDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkUpdateNameIds( Abc_Ntk_t * p ) +{ + char pFileName[1000]; + Vec_Int_t * vStarts; + Abc_Obj_t * pObj; + FILE * pFile; + int i, c, iVar, fCompl, fSeenSpace, Counter = 0; + assert( !Abc_NtkIsNetlist(p) ); + assert( strlen(p->pSpec) < 1000 ); + assert( p->vNameIds != NULL ); + sprintf( pFileName, "%s_%s_names.txt", Extra_FileNameGenericAppend(p->pSpec,""), Extra_FileNameExtension(p->pSpec) ); + pFile = fopen( pFileName, "r+" ); + // collect info about lines + fSeenSpace = 0; + vStarts = Vec_IntAlloc( 1000 ); + Vec_IntPush( vStarts, -1 ); + while ( (c = fgetc(pFile)) != EOF && ++Counter ) + if ( c == ' ' && !fSeenSpace ) + Vec_IntPush(vStarts, Counter), fSeenSpace = 1; + else if ( c == '\n' ) + fSeenSpace = 0; + // add info about names + Abc_NtkForEachObj( p, pObj, i ) + { + if ( i == 0 || i >= Vec_IntSize(p->vNameIds) || !Vec_IntEntry(p->vNameIds, i) ) + continue; + iVar = Abc_Lit2Var( Vec_IntEntry(p->vNameIds, i) ); + fCompl = Abc_LitIsCompl( Vec_IntEntry(p->vNameIds, i) ); + assert( iVar < Vec_IntSize(vStarts) ); + fseek( pFile, Vec_IntEntry(vStarts, iVar), SEEK_SET ); + fprintf( pFile, "%s%d", fCompl? "-":"", i ); + } + printf( "Saved %d names into file \"%s\".\n", Vec_IntSize(vStarts)-1, pFileName ); + fclose( pFile ); + Vec_IntFree( vStarts ); + Vec_IntFreeP( &p->vNameIds ); +// Abc_NtkForEachObj( p, pObj, i ) +// Abc_ObjPrint( stdout, pObj ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/abcNetlist.c b/yosys/abc/src/base/abc/abcNetlist.c new file mode 100644 index 00000000000..8a2e9f184ed --- /dev/null +++ b/yosys/abc/src/base/abc/abcNetlist.c @@ -0,0 +1,514 @@ +/**CFile**************************************************************** + + FileName [abcNetlist.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Transforms netlist into a logic network and vice versa.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcNetlist.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "base/main/main.h" +//#include "seq.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static void Abc_NtkAddPoBuffers( Abc_Ntk_t * pNtk ); +static Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk ); +static Abc_Ntk_t * Abc_NtkAigToLogicSop( Abc_Ntk_t * pNtk ); +static Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Transform the netlist into a logic network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkToLogic( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin; + int i, k; + // consider the case of the AIG + if ( Abc_NtkIsStrash(pNtk) ) + return Abc_NtkAigToLogicSop( pNtk ); + assert( Abc_NtkIsNetlist(pNtk) ); + // consider simple case when there is hierarchy +// assert( pNtk->pDesign == NULL ); + assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); + assert( Abc_NtkBlackboxNum(pNtk) == 0 ); + // start the network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, pNtk->ntkFunc ); + // duplicate the nodes + Abc_NtkForEachNode( pNtk, pObj, i ) + { + Abc_NtkDupObj(pNtkNew, pObj, 0); + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanout0(pObj)), NULL ); + } + // reconnect the internal nodes in the new network + Abc_NtkForEachNode( pNtk, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pFanin)->pCopy ); + // collect the CO nodes + Abc_NtkFinalize( pNtk, pNtkNew ); + // fix the problem with CO pointing directly to CIs + Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); + // duplicate EXDC + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkToLogic( pNtk->pExdc ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkToLogic(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Transform the logic network into a netlist.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkToNetlist( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew, * pNtkTemp; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); + if ( Abc_NtkIsStrash(pNtk) ) + { + pNtkTemp = Abc_NtkAigToLogicSop(pNtk); + pNtkNew = Abc_NtkLogicToNetlist( pNtkTemp ); + Abc_NtkDelete( pNtkTemp ); + return pNtkNew; + } + return Abc_NtkLogicToNetlist( pNtk ); +} + +/**Function************************************************************* + + Synopsis [Converts the AIG into the netlist.] + + Description [This procedure does not copy the choices.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkToNetlistBench( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew, * pNtkTemp; + assert( Abc_NtkIsStrash(pNtk) ); + pNtkTemp = Abc_NtkAigToLogicSopBench( pNtk ); + pNtkNew = Abc_NtkLogicToNetlist( pNtkTemp ); + Abc_NtkDelete( pNtkTemp ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Transform the logic network into a netlist.] + + Description [The logic network given to this procedure should + have exactly the same structure as the resulting netlist. The COs + can only point to CIs if they have identical names. Otherwise, + they should have a node between them, even if this node is + inverter or buffer.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pNet, * pDriver, * pFanin; + int i, k; + + assert( Abc_NtkIsLogic(pNtk) ); + + // remove dangling nodes + Abc_NtkCleanup( pNtk, 0 ); + + // make sure the CO names are unique + Abc_NtkCheckUniqueCiNames( pNtk ); + Abc_NtkCheckUniqueCoNames( pNtk ); + Abc_NtkCheckUniqueCioNames( pNtk ); + +// assert( Abc_NtkLogicHasSimpleCos(pNtk) ); + if ( !Abc_NtkLogicHasSimpleCos(pNtk) ) + { + if ( !Abc_FrameReadFlag("silentmode") ) + printf( "Abc_NtkLogicToNetlist() warning: The network is converted to have simple COs.\n" ); + Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); + } + + // start the netlist by creating PI/PO/Latch objects + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_NETLIST, pNtk->ntkFunc ); + // create the CI nets and remember them in the new CI nodes + Abc_NtkForEachCi( pNtk, pObj, i ) + { + pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); + Abc_ObjAddFanin( pNet, pObj->pCopy ); + pObj->pCopy->pCopy = pNet; + } + // duplicate all nodes + Abc_NtkForEachNode( pNtk, pObj, i ) + Abc_NtkDupObj(pNtkNew, pObj, 0); + // first add the nets to the CO drivers + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pDriver = Abc_ObjFanin0(pObj); + if ( Abc_ObjIsCi(pDriver) ) + { + assert( !strcmp( Abc_ObjName(pDriver), Abc_ObjName(pObj) ) ); + Abc_ObjAddFanin( pObj->pCopy, pDriver->pCopy->pCopy ); + continue; + } + assert( Abc_ObjIsNode(pDriver) ); + // if the CO driver has no net, create it + if ( pDriver->pCopy->pCopy == NULL ) + { + // create the CO net and connect it to CO + //if ( Abc_NtkFindNet(pNtkNew, Abc_ObjName(pDriver)) == NULL ) + // pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pDriver) ); + //else + pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); + Abc_ObjAddFanin( pObj->pCopy, pNet ); + // connect the CO net to the new driver and remember it in the new driver + Abc_ObjAddFanin( pNet, pDriver->pCopy ); + pDriver->pCopy->pCopy = pNet; + } + else + { + assert( !strcmp( Abc_ObjName(pDriver->pCopy->pCopy), Abc_ObjName(pObj) ) ); + Abc_ObjAddFanin( pObj->pCopy, pDriver->pCopy->pCopy ); + } + } + // create the missing nets + Abc_NtkForEachNode( pNtk, pObj, i ) + { + char Buffer[1000]; + if ( pObj->pCopy->pCopy ) // the net of the new object is already created + continue; + // create the new net + sprintf( Buffer, "new_%s", Abc_ObjName(pObj) ); + //pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); // here we create net names such as "n48", where 48 is the ID of the node + pNet = Abc_NtkFindOrCreateNet( pNtkNew, Buffer ); + Abc_ObjAddFanin( pNet, pObj->pCopy ); + pObj->pCopy->pCopy = pNet; + } + // connect nodes to the fanins nets + Abc_NtkForEachNode( pNtk, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); + // duplicate EXDC + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkToNetlist( pNtk->pExdc ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkLogicToNetlist(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Converts the AIG into the logic network with SOPs.] + + Description [Correctly handles the case of choice nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkAigToLogicSop( Abc_Ntk_t * pNtk ) +{ + extern int Abc_NtkLogicMakeSimpleCos2( Abc_Ntk_t * pNtk, int fDuplicate ); + + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin, * pNodeNew; + Vec_Int_t * vInts; + int i, k, fChoices = 0; + assert( Abc_NtkIsStrash(pNtk) ); + // start the network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); + // if the constant node is used, duplicate it + pObj = Abc_AigConst1(pNtk); + if ( Abc_ObjFanoutNum(pObj) > 0 ) + pObj->pCopy = Abc_NtkCreateNodeConst1(pNtkNew); + // duplicate the nodes and create node functions + Abc_NtkForEachNode( pNtk, pObj, i ) + { + Abc_NtkDupObj(pNtkNew, pObj, 0); + pObj->pCopy->pData = Abc_SopCreateAnd2( (Mem_Flex_t *)pNtkNew->pManFunc, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) ); + } + // create the choice nodes + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( !Abc_AigNodeIsChoice(pObj) ) + continue; + // create an OR gate + pNodeNew = Abc_NtkCreateNode(pNtkNew); + // add fanins + vInts = Vec_IntAlloc( 10 ); + for ( pFanin = pObj; pFanin; pFanin = (Abc_Obj_t *)pFanin->pData ) + { + Vec_IntPush( vInts, (int)(pObj->fPhase != pFanin->fPhase) ); + Abc_ObjAddFanin( pNodeNew, pFanin->pCopy ); + } + // create the logic function + pNodeNew->pData = Abc_SopCreateOrMultiCube( (Mem_Flex_t *)pNtkNew->pManFunc, Vec_IntSize(vInts), Vec_IntArray(vInts) ); + // set the new node + pObj->pCopy->pCopy = pNodeNew; + Vec_IntFree( vInts ); + fChoices = 1; + } + // connect the internal nodes + Abc_NtkForEachNode( pNtk, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + if ( pFanin->pCopy->pCopy ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); + else + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + // connect the COs +// Abc_NtkFinalize( pNtk, pNtkNew ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pFanin = Abc_ObjFanin0(pObj); + if ( pFanin->pCopy->pCopy ) + pNodeNew = Abc_ObjNotCond(pFanin->pCopy->pCopy, Abc_ObjFaninC0(pObj)); + else + pNodeNew = Abc_ObjNotCond(pFanin->pCopy, Abc_ObjFaninC0(pObj)); + Abc_ObjAddFanin( pObj->pCopy, pNodeNew ); + } + + // fix the problem with complemented and duplicated CO edges + if ( fChoices ) + Abc_NtkLogicMakeSimpleCos2( pNtkNew, 0 ); + else + Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); + // duplicate the EXDC Ntk + if ( pNtk->pExdc ) + { + if ( Abc_NtkIsStrash(pNtk->pExdc) ) + pNtkNew->pExdc = Abc_NtkAigToLogicSop( pNtk->pExdc ); + else + pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + } + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkAigToLogicSop(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Converts the AIG into the logic network with SOPs for bench writing.] + + Description [This procedure does not copy the choices.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin; + Vec_Ptr_t * vNodes; + int i, k; + assert( Abc_NtkIsStrash(pNtk) ); + if ( Abc_NtkGetChoiceNum(pNtk) ) + printf( "Warning: Choice nodes are skipped.\n" ); + // start the network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); + // collect the nodes to be used (marks all nodes with current TravId) + vNodes = Abc_NtkDfs( pNtk, 0 ); + // create inverters for the constant node + pObj = Abc_AigConst1(pNtk); + if ( Abc_ObjFanoutNum(pObj) > 0 ) + pObj->pCopy = Abc_NtkCreateNodeConst1(pNtkNew); + if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) ) + pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy ); + // create inverters for the CIs + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) ) + pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy ); + // duplicate the nodes, create node functions, and inverters + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + { + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + pObj->pCopy->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, 2, NULL ); + if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) ) + pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy ); + } + // connect the objects + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + if ( Abc_ObjFaninC( pObj, k ) ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); + else + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + Vec_PtrFree( vNodes ); + // connect the COs + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pFanin = Abc_ObjFanin0(pObj); + if ( Abc_ObjFaninC0( pObj ) ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); + else + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + // fix the problem with complemented and duplicated CO edges + Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); + // duplicate the EXDC Ntk + if ( pNtk->pExdc ) + printf( "Warning: The EXDc network is skipped.\n" ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkAigToLogicSopBench(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Converts the AIG into the logic network with SOPs for bench writing.] + + Description [This procedure does not copy the choices.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkAigToLogicSopNand( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin; + Vec_Ptr_t * vNodes; + int i, k; + assert( Abc_NtkIsStrash(pNtk) ); + if ( Abc_NtkGetChoiceNum(pNtk) ) + printf( "Warning: Choice nodes are skipped.\n" ); + // convert complemented edges + Abc_NtkForEachObj( pNtk, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + if ( Abc_ObjIsNode(pFanin) ) + Abc_ObjXorFaninC( pObj, k ); + // start the network + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); + // collect the nodes to be used (marks all nodes with current TravId) + vNodes = Abc_NtkDfs( pNtk, 0 ); + // create inverters for the constant node + pObj = Abc_AigConst1(pNtk); + if ( Abc_ObjFanoutNum(pObj) > 0 ) + pObj->pCopy = Abc_NtkCreateNodeConst1(pNtkNew); + if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) ) + pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy ); + // create inverters for the CIs + Abc_NtkForEachCi( pNtk, pObj, i ) + if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) ) + pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy ); + // duplicate the nodes, create node functions, and inverters + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + { + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + pObj->pCopy->pData = Abc_SopCreateNand( (Mem_Flex_t *)pNtkNew->pManFunc, 2 ); + if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) ) + pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy ); + } + // connect the objects + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + if ( Abc_ObjFaninC( pObj, k ) ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); + else + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + Vec_PtrFree( vNodes ); + // connect the COs + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pFanin = Abc_ObjFanin0(pObj); + if ( Abc_ObjFaninC0( pObj ) ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy ); + else + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + // fix the problem with complemented and duplicated CO edges + Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); + // convert complemented edges + Abc_NtkForEachObj( pNtk, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + if ( Abc_ObjIsNode(pFanin) ) + Abc_ObjXorFaninC( pObj, k ); + // duplicate the EXDC Ntk + if ( pNtk->pExdc ) + printf( "Warning: The EXDc network is skipped.\n" ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkAigToLogicSopBench(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Adds buffers for each PO.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAddPoBuffers( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj, * pFanin, * pFaninNew; + int i; + assert( Abc_NtkIsStrash(pNtk) ); + Abc_NtkForEachPo( pNtk, pObj, i ) + { + pFanin = Abc_ObjChild0(pObj); + pFaninNew = Abc_NtkCreateNode(pNtk); + Abc_ObjAddFanin( pFaninNew, pFanin ); + Abc_ObjPatchFanin( pObj, pFanin, pFaninNew ); + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/abcNtk.c b/yosys/abc/src/base/abc/abcNtk.c new file mode 100644 index 00000000000..c4dbb36ee6f --- /dev/null +++ b/yosys/abc/src/base/abc/abcNtk.c @@ -0,0 +1,2560 @@ +/**CFile**************************************************************** + + FileName [abcNtk.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Network creation/duplication/deletion procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcNtk.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "abcInt.h" +#include "base/main/main.h" +#include "map/mio/mio.h" +#include "aig/gia/gia.h" + +#ifdef ABC_USE_CUDD +#include "bdd/extrab/extraBdd.h" +#endif + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates a new Ntk.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func, int fUseMemMan ) +{ + Abc_Ntk_t * pNtk; + pNtk = ABC_ALLOC( Abc_Ntk_t, 1 ); + memset( pNtk, 0, sizeof(Abc_Ntk_t) ); + pNtk->ntkType = Type; + pNtk->ntkFunc = Func; + // start the object storage + pNtk->vObjs = Vec_PtrAlloc( 100 ); + pNtk->vPios = Vec_PtrAlloc( 100 ); + pNtk->vPis = Vec_PtrAlloc( 100 ); + pNtk->vPos = Vec_PtrAlloc( 100 ); + pNtk->vCis = Vec_PtrAlloc( 100 ); + pNtk->vCos = Vec_PtrAlloc( 100 ); + pNtk->vBoxes = Vec_PtrAlloc( 100 ); + pNtk->vLtlProperties = Vec_PtrAlloc( 100 ); + // start the memory managers + pNtk->pMmObj = fUseMemMan? Mem_FixedStart( sizeof(Abc_Obj_t) ) : NULL; + pNtk->pMmStep = fUseMemMan? Mem_StepStart( ABC_NUM_STEPS ) : NULL; + // get ready to assign the first Obj ID + pNtk->nTravIds = 1; + // start the functionality manager + if ( !Abc_NtkIsStrash(pNtk) ) + Vec_PtrPush( pNtk->vObjs, NULL ); + if ( Abc_NtkIsStrash(pNtk) ) + pNtk->pManFunc = Abc_AigAlloc( pNtk ); + else if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) ) + pNtk->pManFunc = Mem_FlexStart(); +#ifdef ABC_USE_CUDD + else if ( Abc_NtkHasBdd(pNtk) ) + pNtk->pManFunc = Cudd_Init( 20, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); +#endif + else if ( Abc_NtkHasAig(pNtk) ) + pNtk->pManFunc = Hop_ManStart(); + else if ( Abc_NtkHasMapping(pNtk) ) + pNtk->pManFunc = Abc_FrameReadLibGen(); + else if ( !Abc_NtkHasBlackbox(pNtk) ) + assert( 0 ); + // name manager + pNtk->pManName = Nm_ManCreate( 200 ); + // attribute manager + pNtk->vAttrs = Vec_PtrStart( VEC_ATTR_TOTAL_NUM ); + // estimated AndGateDelay + pNtk->AndGateDelay = 0.0; + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Starts a new network using existing network as a model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj; + int fCopyNames, i; + if ( pNtk == NULL ) + return NULL; + // decide whether to copy the names + fCopyNames = ( Type != ABC_NTK_NETLIST ); + // start the network + pNtkNew = Abc_NtkAlloc( Type, Func, 1 ); + pNtkNew->nConstrs = pNtk->nConstrs; + pNtkNew->nBarBufs = pNtk->nBarBufs; + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + // map the constant nodes + if ( Abc_NtkIsStrash(pNtk) && Abc_NtkIsStrash(pNtkNew) ) + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + // clone CIs/CIs/boxes + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, fCopyNames ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, fCopyNames ); + Abc_NtkForEachBox( pNtk, pObj, i ) + Abc_NtkDupBox( pNtkNew, pObj, fCopyNames ); + // transfer logic level + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pCopy->Level = pObj->Level; + // transfer the names +// Abc_NtkTrasferNames( pNtk, pNtkNew ); + Abc_ManTimeDup( pNtk, pNtkNew ); + if ( pNtk->vOnehots ) + pNtkNew->vOnehots = (Vec_Ptr_t *)Vec_VecDupInt( (Vec_Vec_t *)pNtk->vOnehots ); + if ( pNtk->pSeqModel ) + pNtkNew->pSeqModel = Abc_CexDup( pNtk->pSeqModel, Abc_NtkLatchNum(pNtk) ); + if ( pNtk->vObjPerm ) + pNtkNew->vObjPerm = Vec_IntDup( pNtk->vObjPerm ); + pNtkNew->AndGateDelay = pNtk->AndGateDelay; + if ( pNtkNew->pManTime && Abc_FrameReadLibGen() && pNtkNew->AndGateDelay == 0.0 ) + pNtkNew->AndGateDelay = Mio_LibraryReadDelayAigNode((Mio_Library_t *)Abc_FrameReadLibGen()); + // initialize logic level of the CIs + if ( pNtk->AndGateDelay != 0.0 && pNtk->pManTime != NULL && pNtk->ntkType != ABC_NTK_STRASH && Type == ABC_NTK_STRASH ) + { + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pCopy->Level = (int)(Abc_MaxFloat(0, Abc_NodeReadArrivalWorst(pObj)) / pNtk->AndGateDelay); + } + // check that the CI/CO/latches are copied correctly + assert( Abc_NtkCiNum(pNtk) == Abc_NtkCiNum(pNtkNew) ); + assert( Abc_NtkCoNum(pNtk) == Abc_NtkCoNum(pNtkNew) ); + assert( Abc_NtkLatchNum(pNtk) == Abc_NtkLatchNum(pNtkNew) ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Starts a new network using existing network as a model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkStartFromWithLatches( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func, int nLatches ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pNode0, * pNode1; + int fCopyNames, i; + if ( pNtk == NULL ) + return NULL; + assert( Abc_NtkLatchNum(pNtk) == 0 ); + // decide whether to copy the names + fCopyNames = ( Type != ABC_NTK_NETLIST ); + // start the network + pNtkNew = Abc_NtkAlloc( Type, Func, 1 ); + pNtkNew->nConstrs = pNtk->nConstrs; + pNtkNew->nBarBufs = pNtk->nBarBufs; + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + // map the constant nodes + if ( Abc_NtkIsStrash(pNtk) && Abc_NtkIsStrash(pNtkNew) ) + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + // clone CIs/CIs/boxes + for ( i = 0; i < Abc_NtkPiNum(pNtk)-nLatches; i++ ) + Abc_NtkDupObj( pNtkNew, Abc_NtkPi(pNtk, i), fCopyNames ); + for ( i = 0; i < Abc_NtkPoNum(pNtk)-nLatches; i++ ) + Abc_NtkDupObj( pNtkNew, Abc_NtkPo(pNtk, i), fCopyNames ); + for ( i = 0; i < nLatches; i++ ) + { + pObj = Abc_NtkCreateLatch(pNtkNew); + Abc_LatchSetInit0( pObj ); + pNode0 = Abc_NtkCreateBi(pNtkNew); + Abc_NtkPo(pNtk, Abc_NtkPoNum(pNtk)-nLatches+i)->pCopy = pNode0; + pNode1 = Abc_NtkCreateBo(pNtkNew); + Abc_NtkPi(pNtk, Abc_NtkPiNum(pNtk)-nLatches+i)->pCopy = pNode1; + Abc_ObjAddFanin( pObj, pNode0 ); + Abc_ObjAddFanin( pNode1, pObj ); + Abc_ObjAssignName( pNode0, Abc_ObjName(pNode0), NULL ); + Abc_ObjAssignName( pNode1, Abc_ObjName(pNode1), NULL ); + } + // transfer logic level +// Abc_NtkForEachCi( pNtk, pObj, i ) +// pObj->pCopy->Level = pObj->Level; + // transfer the names +// Abc_NtkTrasferNames( pNtk, pNtkNew ); + Abc_ManTimeDup( pNtk, pNtkNew ); + if ( pNtk->vOnehots ) + pNtkNew->vOnehots = (Vec_Ptr_t *)Vec_VecDupInt( (Vec_Vec_t *)pNtk->vOnehots ); + if ( pNtk->pSeqModel ) + pNtkNew->pSeqModel = Abc_CexDup( pNtk->pSeqModel, Abc_NtkLatchNum(pNtk) ); + if ( pNtk->vObjPerm ) + pNtkNew->vObjPerm = Vec_IntDup( pNtk->vObjPerm ); + pNtkNew->AndGateDelay = pNtk->AndGateDelay; + // initialize logic level of the CIs + if ( pNtk->AndGateDelay != 0.0 && pNtk->pManTime != NULL && pNtk->ntkType != ABC_NTK_STRASH && Type == ABC_NTK_STRASH ) + { + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->pCopy->Level = (int)(Abc_MaxFloat(0, Abc_NodeReadArrivalWorst(pObj)) / pNtk->AndGateDelay); + } + // check that the CI/CO/latches are copied correctly + assert( Abc_NtkCiNum(pNtk) == Abc_NtkCiNum(pNtkNew) ); + assert( Abc_NtkCoNum(pNtk) == Abc_NtkCoNum(pNtkNew) ); + assert( nLatches == Abc_NtkLatchNum(pNtkNew) ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Starts a new network using existing network as a model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkStartFromNoLatches( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj; + int i; + if ( pNtk == NULL ) + return NULL; + assert( Type != ABC_NTK_NETLIST ); + // start the network + pNtkNew = Abc_NtkAlloc( Type, Func, 1 ); + pNtkNew->nConstrs = pNtk->nConstrs; + pNtkNew->nBarBufs = pNtk->nBarBufs; + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + // map the constant nodes + if ( Abc_NtkIsStrash(pNtk) && Abc_NtkIsStrash(pNtkNew) ) + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + // clone CIs/CIs/boxes + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 1 ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 1 ); + Abc_NtkForEachBox( pNtk, pObj, i ) + { + if ( Abc_ObjIsLatch(pObj) ) + continue; + Abc_NtkDupBox(pNtkNew, pObj, 1); + } + if ( pNtk->vObjPerm ) + pNtkNew->vObjPerm = Vec_IntDup( pNtk->vObjPerm ); + pNtkNew->AndGateDelay = pNtk->AndGateDelay; + // transfer the names +// Abc_NtkTrasferNamesNoLatches( pNtk, pNtkNew ); + Abc_ManTimeDup( pNtk, pNtkNew ); + // check that the CI/CO/latches are copied correctly + assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) ); + assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkNew) ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Finalizes the network using the existing network as a model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFinalize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) +{ + Abc_Obj_t * pObj, * pDriver, * pDriverNew; + int i; + // set the COs of the strashed network + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pObj) ); + pDriverNew = Abc_ObjNotCond(pDriver->pCopy, Abc_ObjFaninC0(pObj)); + Abc_ObjAddFanin( pObj->pCopy, pDriverNew ); + } + // duplicate timing manager + if ( pNtk->pManTime ) + Abc_NtkTimeInitialize( pNtkNew, pNtk ); + if ( pNtk->vPhases ) + Abc_NtkTransferPhases( pNtkNew, pNtk ); + if ( pNtk->pWLoadUsed ) + pNtkNew->pWLoadUsed = Abc_UtilStrsav( pNtk->pWLoadUsed ); +} + +/**Function************************************************************* + + Synopsis [Starts a new network using existing network as a model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkStartRead( char * pName ) +{ + Abc_Ntk_t * pNtkNew; + // allocate the empty network + pNtkNew = Abc_NtkAlloc( ABC_NTK_NETLIST, ABC_FUNC_SOP, 1 ); + // set the specs + pNtkNew->pName = Extra_FileNameGeneric(pName); + pNtkNew->pSpec = Extra_UtilStrsav(pName); + if ( pNtkNew->pName == NULL || strlen(pNtkNew->pName) == 0 ) + { + ABC_FREE( pNtkNew->pName ); + pNtkNew->pName = Extra_UtilStrsav("unknown"); + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Finalizes the network using the existing network as a model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFinalizeRead( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pBox, * pObj, * pTerm, * pNet; + int i; + if ( Abc_NtkHasBlackbox(pNtk) && Abc_NtkBoxNum(pNtk) == 0 ) + { + pBox = Abc_NtkCreateBlackbox(pNtk); + Abc_NtkForEachPi( pNtk, pObj, i ) + { + pTerm = Abc_NtkCreateBi(pNtk); + Abc_ObjAddFanin( pTerm, Abc_ObjFanout0(pObj) ); + Abc_ObjAddFanin( pBox, pTerm ); + } + Abc_NtkForEachPo( pNtk, pObj, i ) + { + pTerm = Abc_NtkCreateBo(pNtk); + Abc_ObjAddFanin( pTerm, pBox ); + Abc_ObjAddFanin( Abc_ObjFanin0(pObj), pTerm ); + } + return; + } + assert( Abc_NtkIsNetlist(pNtk) ); + + // check if constant 0 net is used + pNet = Abc_NtkFindNet( pNtk, "1\'b0" ); + if ( pNet ) + { + if ( Abc_ObjFanoutNum(pNet) == 0 ) + Abc_NtkDeleteObj(pNet); + else if ( Abc_ObjFaninNum(pNet) == 0 ) + Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst0(pNtk) ); + } + // check if constant 1 net is used + pNet = Abc_NtkFindNet( pNtk, "1\'b1" ); + if ( pNet ) + { + if ( Abc_ObjFanoutNum(pNet) == 0 ) + Abc_NtkDeleteObj(pNet); + else if ( Abc_ObjFaninNum(pNet) == 0 ) + Abc_ObjAddFanin( pNet, Abc_NtkCreateNodeConst1(pNtk) ); + } + // fix the net drivers + Abc_NtkFixNonDrivenNets( pNtk ); + + // reorder the CI/COs to PI/POs first + Abc_NtkOrderCisCos( pNtk ); +} + +/**Function************************************************************* + + Synopsis [Duplicate the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin; + int i, k; + if ( pNtk == NULL ) + return NULL; + // start the network + pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc ); + // copy the internal nodes + if ( Abc_NtkIsStrash(pNtk) ) + { + // copy the AND gates + Abc_AigForEachAnd( pNtk, pObj, i ) + pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + // relink the choice nodes + Abc_AigForEachAnd( pNtk, pObj, i ) + if ( pObj->pData ) + pObj->pCopy->pData = ((Abc_Obj_t *)pObj->pData)->pCopy; + // relink the CO nodes + Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); + // get the number of nodes before and after + if ( Abc_NtkNodeNum(pNtk) != Abc_NtkNodeNum(pNtkNew) ) + printf( "Warning: Structural hashing during duplication reduced %d nodes (this is a minor bug).\n", + Abc_NtkNodeNum(pNtk) - Abc_NtkNodeNum(pNtkNew) ); + } + else + { + // duplicate the nets and nodes (CIs/COs/latches already dupped) + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( pObj->pCopy == NULL ) + Abc_NtkDupObj(pNtkNew, pObj, Abc_NtkHasBlackbox(pNtk) && Abc_ObjIsNet(pObj)); + // reconnect all objects (no need to transfer attributes on edges) + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + // move object IDs + if ( pNtk->vOrigNodeIds ) + { + pNtkNew->vOrigNodeIds = Vec_IntStartFull( Abc_NtkObjNumMax(pNtkNew) ); + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( pObj->pCopy && Vec_IntEntry(pNtk->vOrigNodeIds, pObj->Id) > 0 ) + Vec_IntWriteEntry( pNtkNew->vOrigNodeIds, pObj->pCopy->Id, Vec_IntEntry(pNtk->vOrigNodeIds, pObj->Id) ); + } + + } + // duplicate the EXDC Ntk + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + if ( pNtk->pExcare ) + pNtkNew->pExcare = Abc_NtkDup( (Abc_Ntk_t *)pNtk->pExcare ); + // duplicate timing manager + if ( pNtk->pManTime ) + Abc_NtkTimeInitialize( pNtkNew, pNtk ); + if ( pNtk->vPhases ) + Abc_NtkTransferPhases( pNtkNew, pNtk ); + if ( pNtk->pWLoadUsed ) + pNtkNew->pWLoadUsed = Abc_UtilStrsav( pNtk->pWLoadUsed ); + // check correctness + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" ); + pNtk->pCopy = pNtkNew; + return pNtkNew; +} +Abc_Ntk_t * Abc_NtkDupDfs( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin; + int i, k; + if ( pNtk == NULL ) + return NULL; + assert( !Abc_NtkIsStrash(pNtk) && !Abc_NtkIsNetlist(pNtk) ); + // start the network + pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc ); + // copy the internal nodes + vNodes = Abc_NtkDfs( pNtk, 0 ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Vec_PtrFree( vNodes ); + // reconnect all objects (no need to transfer attributes on edges) + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + if ( pObj->pCopy && pFanin->pCopy ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + // duplicate the EXDC Ntk + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + if ( pNtk->pExcare ) + pNtkNew->pExcare = Abc_NtkDup( (Abc_Ntk_t *)pNtk->pExcare ); + // duplicate timing manager + if ( pNtk->pManTime ) + Abc_NtkTimeInitialize( pNtkNew, pNtk ); + if ( pNtk->vPhases ) + Abc_NtkTransferPhases( pNtkNew, pNtk ); + if ( pNtk->pWLoadUsed ) + pNtkNew->pWLoadUsed = Abc_UtilStrsav( pNtk->pWLoadUsed ); + // check correctness + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" ); + pNtk->pCopy = pNtkNew; + return pNtkNew; +} +Abc_Ntk_t * Abc_NtkDupDfsNoBarBufs( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin; + int i, k; + if ( pNtk == NULL ) + return NULL; + assert( Abc_NtkIsLogic(pNtk) ); + assert( pNtk->nBarBufs2 > 0 ); + // start the network + pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc ); + // copy the internal nodes + vNodes = Abc_NtkDfs2( pNtk ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + if ( Abc_ObjIsBarBuf(pObj) ) + pObj->pCopy = Abc_ObjFanin0(pObj)->pCopy; + else + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Vec_PtrFree( vNodes ); + // reconnect all objects (no need to transfer attributes on edges) + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) && !Abc_ObjIsBarBuf(pObj) ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + if ( pObj->pCopy && pFanin->pCopy ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + // duplicate the EXDC Ntk + if ( pNtk->pExdc ) + pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc ); + if ( pNtk->pExcare ) + pNtkNew->pExcare = Abc_NtkDup( (Abc_Ntk_t *)pNtk->pExcare ); + // duplicate timing manager + if ( pNtk->pManTime ) + Abc_NtkTimeInitialize( pNtkNew, pNtk ); + if ( pNtk->vPhases ) + Abc_NtkTransferPhases( pNtkNew, pNtk ); + if ( pNtk->pWLoadUsed ) + pNtkNew->pWLoadUsed = Abc_UtilStrsav( pNtk->pWLoadUsed ); + // check correctness + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" ); + pNtk->pCopy = pNtkNew; + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Duplicate the AIG while adding latches.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkRestrashWithLatches( Abc_Ntk_t * pNtk, int nLatches ) +{ + Abc_Ntk_t * pNtkAig; + Abc_Obj_t * pObj; + int i; + assert( Abc_NtkIsStrash(pNtk) ); + // start the new network (constants and CIs of the old network will point to the their counterparts in the new network) + pNtkAig = Abc_NtkStartFromWithLatches( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG, nLatches ); + // restrash the nodes (assuming a topological order of the old network) + Abc_NtkForEachNode( pNtk, pObj, i ) + pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + // finalize the network + Abc_NtkFinalize( pNtk, pNtkAig ); + // make sure everything is okay + if ( !Abc_NtkCheck( pNtkAig ) ) + { + printf( "Abc_NtkStrash: The network check has failed.\n" ); + Abc_NtkDelete( pNtkAig ); + return NULL; + } + return pNtkAig; + +} + +/**Function************************************************************* + + Synopsis [Duplicate the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDupTransformMiter( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pObj2, * pMiter; + int i; + assert( Abc_NtkIsStrash(pNtk) ); + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + pNtkNew->nConstrs = pNtk->nConstrs; + pNtkNew->nBarBufs = pNtk->nBarBufs; + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + // map the constant nodes + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + // clone CIs/CIs/boxes + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 1 ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 1 ), i++; + Abc_NtkForEachBox( pNtk, pObj, i ) + Abc_NtkDupBox( pNtkNew, pObj, 1 ); + // copy the AND gates + Abc_AigForEachAnd( pNtk, pObj, i ) + pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + // create new miters + Abc_NtkForEachPo( pNtk, pObj, i ) + { + pObj2 = Abc_NtkPo( pNtk, ++i ); + pMiter = Abc_AigXor( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild0Copy(pObj2) ); + Abc_ObjAddFanin( pObj->pCopy, pMiter ); + } + Abc_NtkForEachLatchInput( pNtk, pObj, i ) + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) ); + // cleanup + Abc_AigCleanup( (Abc_Aig_t *)pNtkNew->pManFunc ); + // check that the CI/CO/latches are copied correctly + assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) ); + assert( Abc_NtkPoNum(pNtk) == 2*Abc_NtkPoNum(pNtkNew) ); + assert( Abc_NtkLatchNum(pNtk) == Abc_NtkLatchNum(pNtkNew) ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Duplicate the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDouble( Abc_Ntk_t * pNtk ) +{ + char Buffer[500]; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin; + int i, k; + assert( Abc_NtkIsLogic(pNtk) ); + + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + sprintf( Buffer, "%s%s", pNtk->pName, "_2x" ); + pNtkNew->pName = Extra_UtilStrsav(Buffer); + + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + // clone CIs/CIs/boxes + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_NtkForEachBox( pNtk, pObj, i ) + Abc_NtkDupBox( pNtkNew, pObj, 0 ); + // copy the internal nodes + // duplicate the nets and nodes (CIs/COs/latches already dupped) + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( pObj->pCopy == NULL ) + Abc_NtkDupObj(pNtkNew, pObj, 0); + // reconnect all objects (no need to transfer attributes on edges) + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + // clone CIs/CIs/boxes + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_NtkForEachBox( pNtk, pObj, i ) + Abc_NtkDupBox( pNtkNew, pObj, 0 ); + // copy the internal nodes + // duplicate the nets and nodes (CIs/COs/latches already dupped) + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( pObj->pCopy == NULL ) + Abc_NtkDupObj(pNtkNew, pObj, 0); + // reconnect all objects (no need to transfer attributes on edges) + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + + // assign names + Abc_NtkForEachCi( pNtk, pObj, i ) + { + Abc_ObjAssignName( Abc_NtkCi(pNtkNew, i), "1_", Abc_ObjName(pObj) ); + Abc_ObjAssignName( Abc_NtkCi(pNtkNew, Abc_NtkCiNum(pNtk) + i), "2_", Abc_ObjName(pObj) ); + } + Abc_NtkForEachCo( pNtk, pObj, i ) + { + Abc_ObjAssignName( Abc_NtkCo(pNtkNew, i), "1_", Abc_ObjName(pObj) ); + Abc_ObjAssignName( Abc_NtkCo(pNtkNew, Abc_NtkCoNum(pNtk) + i), "2_", Abc_ObjName(pObj) ); + } + Abc_NtkOrderCisCos( pNtkNew ); + + // perform the final check + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Duplicate the bottom levels of the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkBottom( Abc_Ntk_t * pNtk, int Level ) +{ + char Buffer[500]; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin; + int i, k; + assert( Abc_NtkIsLogic(pNtk) ); + assert( Abc_NtkLatchNum(pNtk) == 0 ); + + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + sprintf( Buffer, "%s%s", pNtk->pName, "_bot" ); + pNtkNew->pName = Extra_UtilStrsav(Buffer); + + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + // clone CIs/CIs/boxes + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, 1 ); + + // copy the internal nodes + // duplicate the nets and nodes (CIs/COs/latches already dupped) + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( pObj->pCopy == NULL && Abc_ObjIsNode(pObj) && Abc_ObjLevel(pObj) <= Level ) + Abc_NtkDupObj(pNtkNew, pObj, 0); + // reconnect all objects (no need to transfer attributes on edges) + Abc_NtkForEachObj( pNtk, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + if ( pObj->pCopy && pFanin->pCopy ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + + // create new primary outputs + Abc_NtkForEachObj( pNtk, pObj, i ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + if ( !pObj->pCopy && pFanin->pCopy && Abc_ObjIsNode(pFanin) ) + { + Abc_Obj_t * pNodeNew = Abc_NtkCreatePo(pNtkNew); + Abc_ObjAddFanin( pNodeNew, pFanin->pCopy ); + Abc_ObjAssignName( pNodeNew, Abc_ObjName(pNodeNew), NULL ); + } + + // perform the final check + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkBottom(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Attaches the second network at the bottom of the first.] + + Description [Returns the first network. Deletes the second network.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkAttachBottom( Abc_Ntk_t * pNtkTop, Abc_Ntk_t * pNtkBottom ) +{ + Abc_Obj_t * pObj, * pFanin, * pBuffer; + Vec_Ptr_t * vNodes; + int i, k; + assert( pNtkBottom != NULL ); + if ( pNtkTop == NULL ) + return pNtkBottom; + // make sure the networks are combinational + assert( Abc_NtkPiNum(pNtkTop) == Abc_NtkCiNum(pNtkTop) ); + assert( Abc_NtkPiNum(pNtkBottom) == Abc_NtkCiNum(pNtkBottom) ); + // make sure the POs of the bottom correspond to the PIs of the top + assert( Abc_NtkPoNum(pNtkBottom) == Abc_NtkPiNum(pNtkTop) ); + assert( Abc_NtkPiNum(pNtkBottom) < Abc_NtkPiNum(pNtkTop) ); + // add buffers for the PIs of the top - save results in the POs of the bottom + Abc_NtkForEachPi( pNtkTop, pObj, i ) + { + pBuffer = Abc_NtkCreateNodeBuf( pNtkTop, NULL ); + Abc_ObjTransferFanout( pObj, pBuffer ); + Abc_NtkPo(pNtkBottom, i)->pCopy = pBuffer; + } + // remove useless PIs of the top + for ( i = Abc_NtkPiNum(pNtkTop) - 1; i >= Abc_NtkPiNum(pNtkBottom); i-- ) + Abc_NtkDeleteObj( Abc_NtkPi(pNtkTop, i) ); + assert( Abc_NtkPiNum(pNtkBottom) == Abc_NtkPiNum(pNtkTop) ); + // copy the bottom network + Abc_NtkForEachPi( pNtkBottom, pObj, i ) + Abc_NtkPi(pNtkBottom, i)->pCopy = Abc_NtkPi(pNtkTop, i); + // construct all nodes + vNodes = Abc_NtkDfs( pNtkBottom, 0 ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + { + Abc_NtkDupObj(pNtkTop, pObj, 0); + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + Vec_PtrFree( vNodes ); + // connect the POs + Abc_NtkForEachPo( pNtkBottom, pObj, i ) + Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pObj)->pCopy ); + // delete old network + Abc_NtkDelete( pNtkBottom ); + // return the network + if ( !Abc_NtkCheck( pNtkTop ) ) + fprintf( stdout, "Abc_NtkAttachBottom(): Network check has failed.\n" ); + return pNtkTop; +} + +/**Function************************************************************* + + Synopsis [Creates the network composed of one logic cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateCone( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName, int fUseAllCis ) +{ + Abc_Ntk_t * pNtkNew; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pFanin, * pNodeCoNew; + char Buffer[1000]; + int i, k; + + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); + assert( Abc_ObjIsNode(pNode) || (Abc_NtkIsStrash(pNtk) && (Abc_AigNodeIsConst(pNode) || Abc_ObjIsCi(pNode))) ); + + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + // set the name + sprintf( Buffer, "%s_%s", pNtk->pName, pNodeName ); + pNtkNew->pName = Extra_UtilStrsav(Buffer); + + // establish connection between the constant nodes + if ( Abc_NtkIsStrash(pNtk) ) + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + + // collect the nodes in the TFI of the output (mark the TFI) + vNodes = Abc_NtkDfsNodes( pNtk, &pNode, 1 ); + // create the PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + { + if ( fUseAllCis || Abc_NodeIsTravIdCurrent(pObj) ) // TravId is set by DFS + { + pObj->pCopy = Abc_NtkCreatePi(pNtkNew); + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); + } + } + // add the PO corresponding to this output + pNodeCoNew = Abc_NtkCreatePo( pNtkNew ); + Abc_ObjAssignName( pNodeCoNew, pNodeName, NULL ); + // copy the nodes + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + { + // if it is an AIG, add to the hash table + if ( Abc_NtkIsStrash(pNtk) ) + { + pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + } + else + { + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + } + // connect the internal nodes to the new CO + Abc_ObjAddFanin( pNodeCoNew, pNode->pCopy ); + Vec_PtrFree( vNodes ); + + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateCone(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Creates the network composed of several logic cones.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateConeArray( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, int fUseAllCis ) +{ + Abc_Ntk_t * pNtkNew; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pFanin, * pNodeCoNew; + char Buffer[1000]; + int i, k; + + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); + + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + // set the name + sprintf( Buffer, "%s_part", pNtk->pName ); + pNtkNew->pName = Extra_UtilStrsav(Buffer); + + // establish connection between the constant nodes + if ( Abc_NtkIsStrash(pNtk) ) + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + + // collect the nodes in the TFI of the output (mark the TFI) + vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)Vec_PtrArray(vRoots), Vec_PtrSize(vRoots) ); + + // create the PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + { + if ( fUseAllCis || Abc_NodeIsTravIdCurrent(pObj) ) // TravId is set by DFS + { + pObj->pCopy = Abc_NtkCreatePi(pNtkNew); + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); + } + } + + // copy the nodes + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + { + // if it is an AIG, add to the hash table + if ( Abc_NtkIsStrash(pNtk) ) + { + pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + } + else + { + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + } + Vec_PtrFree( vNodes ); + + // add the POs corresponding to the root nodes + Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) + { + // create the PO node + pNodeCoNew = Abc_NtkCreatePo( pNtkNew ); + // connect the internal nodes to the new CO + if ( Abc_ObjIsCo(pObj) ) + Abc_ObjAddFanin( pNodeCoNew, Abc_ObjChild0Copy(pObj) ); + else + Abc_ObjAddFanin( pNodeCoNew, pObj->pCopy ); + // assign the name + Abc_ObjAssignName( pNodeCoNew, Abc_ObjName(pObj), NULL ); + } + + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateConeArray(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Adds new nodes to the cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkAppendToCone( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj; + int i, iNodeId; + + assert( Abc_NtkIsStrash(pNtkNew) ); + assert( Abc_NtkIsStrash(pNtk) ); + + // collect the nodes in the TFI of the output (mark the TFI) + vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)Vec_PtrArray(vRoots), Vec_PtrSize(vRoots) ); + + // establish connection between the constant nodes + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + + // create the PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + { + // skip CIs that are not used + if ( !Abc_NodeIsTravIdCurrent(pObj) ) + continue; + // find the corresponding CI in the new network + iNodeId = Nm_ManFindIdByNameTwoTypes( pNtkNew->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO ); + if ( iNodeId == -1 ) + { + pObj->pCopy = Abc_NtkCreatePi(pNtkNew); + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); + } + else + pObj->pCopy = Abc_NtkObj( pNtkNew, iNodeId ); + } + + // copy the nodes + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + Vec_PtrFree( vNodes ); + + // do not add the COs + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkAppendToCone(): Network check has failed.\n" ); +} + +/**Function************************************************************* + + Synopsis [Creates the network composed of MFFC of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateMffc( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode, char * pNodeName ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin, * pNodeCoNew; + Vec_Ptr_t * vCone, * vSupp; + char Buffer[1000]; + int i, k; + + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + // set the name + sprintf( Buffer, "%s_%s", pNtk->pName, pNodeName ); + pNtkNew->pName = Extra_UtilStrsav(Buffer); + + // establish connection between the constant nodes + if ( Abc_NtkIsStrash(pNtk) ) + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + + // collect the nodes in MFFC + vCone = Vec_PtrAlloc( 100 ); + vSupp = Vec_PtrAlloc( 100 ); + Abc_NodeDeref_rec( pNode ); + Abc_NodeMffcConeSupp( pNode, vCone, vSupp ); + Abc_NodeRef_rec( pNode ); + // create the PIs + Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pObj, i ) + { + pObj->pCopy = Abc_NtkCreatePi(pNtkNew); + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); + } + // create the PO + pNodeCoNew = Abc_NtkCreatePo( pNtkNew ); + Abc_ObjAssignName( pNodeCoNew, pNodeName, NULL ); + // copy the nodes + Vec_PtrForEachEntry( Abc_Obj_t *, vCone, pObj, i ) + { + // if it is an AIG, add to the hash table + if ( Abc_NtkIsStrash(pNtk) ) + { + pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) ); + } + else + { + Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + } + } + // connect the topmost node + Abc_ObjAddFanin( pNodeCoNew, pNode->pCopy ); + Vec_PtrFree( vCone ); + Vec_PtrFree( vSupp ); + + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateMffc(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Creates the miter composed of one multi-output cone.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateTarget( Abc_Ntk_t * pNtk, Vec_Ptr_t * vRoots, Vec_Int_t * vValues ) +{ + Vec_Ptr_t * vNodes; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFinal, * pOther, * pNodePo; + int i; + + assert( Abc_NtkIsLogic(pNtk) ); + + // start the network + Abc_NtkCleanCopy( pNtk ); + pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + + // collect the nodes in the TFI of the output + vNodes = Abc_NtkDfsNodes( pNtk, (Abc_Obj_t **)vRoots->pArray, vRoots->nSize ); + // create the PIs + Abc_NtkForEachCi( pNtk, pObj, i ) + { + pObj->pCopy = Abc_NtkCreatePi(pNtkNew); + Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); + } + // copy the nodes + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + pObj->pCopy = Abc_NodeStrash( pNtkNew, pObj, 0 ); + Vec_PtrFree( vNodes ); + + // add the PO + pFinal = Abc_AigConst1( pNtkNew ); + Vec_PtrForEachEntry( Abc_Obj_t *, vRoots, pObj, i ) + { + if ( Abc_ObjIsCo(pObj) ) + pOther = Abc_ObjFanin0(pObj)->pCopy; + else + pOther = pObj->pCopy; + if ( Vec_IntEntry(vValues, i) == 0 ) + pOther = Abc_ObjNot(pOther); + pFinal = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, pFinal, pOther ); + } + + // add the PO corresponding to this output + pNodePo = Abc_NtkCreatePo( pNtkNew ); + Abc_ObjAddFanin( pNodePo, pFinal ); + Abc_ObjAssignName( pNodePo, "miter", NULL ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateTarget(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Creates the network composed of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateFromNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pFanin, * pNodePo; + int i; + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + pNtkNew->pName = Extra_UtilStrsav(Abc_ObjName(pNode)); + // add the PIs corresponding to the fanins of the node + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + pFanin->pCopy = Abc_NtkCreatePi( pNtkNew ); + Abc_ObjAssignName( pFanin->pCopy, Abc_ObjName(pFanin), NULL ); + } + // duplicate and connect the node + pNode->pCopy = Abc_NtkDupObj( pNtkNew, pNode, 0 ); + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_ObjAddFanin( pNode->pCopy, pFanin->pCopy ); + // create the only PO + pNodePo = Abc_NtkCreatePo( pNtkNew ); + Abc_ObjAddFanin( pNodePo, pNode->pCopy ); + Abc_ObjAssignName( pNodePo, Abc_ObjName(pNode), NULL ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateFromNode(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Creates the network composed of one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateFromRange( Abc_Ntk_t * pNtk ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pNodeNew, * pNodePo; + Gia_Man_t * p = Abc_NtkClpGia( pNtk ); int i; + Vec_Str_t * vStr = Gia_ManComputeRange( p ); + Gia_ManStop( p ); + pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); + pNtkNew->pName = Extra_UtilStrsav("range"); + Abc_NtkForEachCo( pNtk, pObj, i ) + Abc_ObjAssignName( Abc_NtkCreatePi(pNtkNew), Abc_ObjName(pObj), NULL ); + pNodeNew = Abc_NtkCreateObj( pNtkNew, ABC_OBJ_NODE ); + pNodeNew->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkNew->pManFunc, Vec_StrArray(vStr) ); + Vec_StrFree( vStr ); + Abc_NtkForEachCi( pNtkNew, pObj, i ) + Abc_ObjAddFanin( pNodeNew, pObj ); + pNodePo = Abc_NtkCreatePo( pNtkNew ); + Abc_ObjAddFanin( pNodePo, pNodeNew ); + Abc_ObjAssignName( pNodePo, "range", NULL ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateFromNode(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Creates the network composed of one node with the given SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateWithNode( char * pSop ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pFanin, * pNode, * pNodePo; + Vec_Ptr_t * vNames; + int i, nVars; + // start the network + pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); + pNtkNew->pName = Extra_UtilStrsav("ex"); + // create PIs + Vec_PtrPush( pNtkNew->vObjs, NULL ); + nVars = Abc_SopGetVarNum( pSop ); + vNames = Abc_NodeGetFakeNames( nVars ); + for ( i = 0; i < nVars; i++ ) + Abc_ObjAssignName( Abc_NtkCreatePi(pNtkNew), (char *)Vec_PtrEntry(vNames, i), NULL ); + Abc_NodeFreeNames( vNames ); + // create the node, add PIs as fanins, set the function + pNode = Abc_NtkCreateNode( pNtkNew ); + Abc_NtkForEachPi( pNtkNew, pFanin, i ) + Abc_ObjAddFanin( pNode, pFanin ); + pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkNew->pManFunc, pSop ); + // create the only PO + pNodePo = Abc_NtkCreatePo(pNtkNew); + Abc_ObjAddFanin( pNodePo, pNode ); + Abc_ObjAssignName( pNodePo, "F", NULL ); + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateWithNode(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Creates the network composed of one node with the given SOP.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateWithNodes( Vec_Ptr_t * vSop ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pFanin, * pNode, * pNodePo; + Vec_Ptr_t * vNames; + int i, k, nVars; char Buffer[100]; + char * pSop = (char *)Vec_PtrEntry(vSop, 0); + // start the network + pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); + pNtkNew->pName = Extra_UtilStrsav("ex"); + // create PIs + Vec_PtrPush( pNtkNew->vObjs, NULL ); + nVars = Abc_SopGetVarNum( pSop ); + vNames = Abc_NodeGetFakeNames( nVars ); + for ( i = 0; i < nVars; i++ ) + Abc_ObjAssignName( Abc_NtkCreatePi(pNtkNew), (char *)Vec_PtrEntry(vNames, i), NULL ); + Abc_NodeFreeNames( vNames ); + // create the node, add PIs as fanins, set the function + Vec_PtrForEachEntry( char *, vSop, pSop, i ) + { + pNode = Abc_NtkCreateNode( pNtkNew ); + if ( Abc_SopGetVarNum(pSop) > 0 ) + Abc_NtkForEachPi( pNtkNew, pFanin, k ) + Abc_ObjAddFanin( pNode, pFanin ); + pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkNew->pManFunc, pSop ); + // create the only PO + pNodePo = Abc_NtkCreatePo(pNtkNew); + Abc_ObjAddFanin( pNodePo, pNode ); + sprintf( Buffer, "F%d", i ); + Abc_ObjAssignName( pNodePo, Buffer, NULL ); + } + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkCreateWithNode(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Deletes the Ntk.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDelete( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + void * pAttrMan; + int TotalMemory, i; + int fWarning = 0; +// int LargePiece = (4 << ABC_NUM_STEPS); + if ( pNtk == NULL ) + return; + // free EXDC Ntk + if ( pNtk->pExdc ) + Abc_NtkDelete( pNtk->pExdc ); + if ( pNtk->pExcare ) + Abc_NtkDelete( (Abc_Ntk_t *)pNtk->pExcare ); + // dereference the BDDs + if ( Abc_NtkHasBdd(pNtk) ) + { +#ifdef ABC_USE_CUDD + Abc_NtkForEachNode( pNtk, pObj, i ) + Cudd_RecursiveDeref( (DdManager *)pNtk->pManFunc, (DdNode *)pObj->pData ); +#endif + } + // make sure all the marks are clean + Abc_NtkForEachObj( pNtk, pObj, i ) + { + // free large fanout arrays +// if ( pNtk->pMmObj && pObj->vFanouts.nCap * 4 > LargePiece ) +// ABC_FREE( pObj->vFanouts.pArray ); + // these flags should be always zero + // if this is not true, something is wrong somewhere +// assert( pObj->fMarkA == 0 ); +// assert( pObj->fMarkB == 0 ); +// assert( pObj->fMarkC == 0 ); + if ( !fWarning && (pObj->fMarkA || pObj->fMarkB || pObj->fMarkC) ) + { printf( "Flags A, B, or C are not zero.\n" ), fWarning = 1; } + } + // free the nodes + if ( pNtk->pMmStep == NULL ) + { + Abc_NtkForEachObj( pNtk, pObj, i ) + { + ABC_FREE( pObj->vFanouts.pArray ); + ABC_FREE( pObj->vFanins.pArray ); + } + } + if ( pNtk->pMmObj == NULL ) + { + Abc_NtkForEachObj( pNtk, pObj, i ) + ABC_FREE( pObj ); + } + + // free the arrays + Vec_PtrFree( pNtk->vPios ); + Vec_PtrFree( pNtk->vPis ); + Vec_PtrFree( pNtk->vPos ); + Vec_PtrFree( pNtk->vCis ); + Vec_PtrFree( pNtk->vCos ); + Vec_PtrFree( pNtk->vObjs ); + Vec_PtrFree( pNtk->vBoxes ); + ABC_FREE( pNtk->vTravIds.pArray ); + if ( pNtk->vLevelsR ) Vec_IntFree( pNtk->vLevelsR ); + ABC_FREE( pNtk->pModel ); + ABC_FREE( pNtk->pSeqModel ); + if ( pNtk->vSeqModelVec ) + Vec_PtrFreeFree( pNtk->vSeqModelVec ); + TotalMemory = 0; + TotalMemory += pNtk->pMmObj? Mem_FixedReadMemUsage(pNtk->pMmObj) : 0; + TotalMemory += pNtk->pMmStep? Mem_StepReadMemUsage(pNtk->pMmStep) : 0; +// fprintf( stdout, "The total memory allocated internally by the network = %0.2f MB.\n", ((double)TotalMemory)/(1<<20) ); + // free the storage + if ( pNtk->pMmObj ) + Mem_FixedStop( pNtk->pMmObj, 0 ); + if ( pNtk->pMmStep ) + Mem_StepStop ( pNtk->pMmStep, 0 ); + // name manager + Nm_ManFree( pNtk->pManName ); + // free the timing manager + if ( pNtk->pManTime ) + Abc_ManTimeStop( pNtk->pManTime ); + Vec_IntFreeP( &pNtk->vPhases ); + // start the functionality manager + if ( Abc_NtkIsStrash(pNtk) ) + Abc_AigFree( (Abc_Aig_t *)pNtk->pManFunc ); + else if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) ) + Mem_FlexStop( (Mem_Flex_t *)pNtk->pManFunc, 0 ); +#ifdef ABC_USE_CUDD + else if ( Abc_NtkHasBdd(pNtk) ) + Extra_StopManager( (DdManager *)pNtk->pManFunc ); +#endif + else if ( Abc_NtkHasAig(pNtk) ) + { if ( pNtk->pManFunc ) Hop_ManStop( (Hop_Man_t *)pNtk->pManFunc ); } + else if ( Abc_NtkHasMapping(pNtk) ) + pNtk->pManFunc = NULL; + else if ( !Abc_NtkHasBlackbox(pNtk) ) + assert( 0 ); + // free the hierarchy + if ( pNtk->pDesign ) + { + Abc_DesFree( pNtk->pDesign, pNtk ); + pNtk->pDesign = NULL; + } +// if ( pNtk->pBlackBoxes ) +// Vec_IntFree( pNtk->pBlackBoxes ); + // free node attributes + Vec_PtrForEachEntry( Abc_Obj_t *, pNtk->vAttrs, pAttrMan, i ) + if ( pAttrMan ) + Vec_AttFree( (Vec_Att_t *)pAttrMan, 1 ); + assert( pNtk->pSCLib == NULL ); + Vec_IntFreeP( &pNtk->vGates ); + Vec_PtrFree( pNtk->vAttrs ); + Vec_IntFreeP( &pNtk->vNameIds ); + ABC_FREE( pNtk->pWLoadUsed ); + ABC_FREE( pNtk->pName ); + ABC_FREE( pNtk->pSpec ); + ABC_FREE( pNtk->pLutTimes ); + if ( pNtk->vOnehots ) + Vec_VecFree( (Vec_Vec_t *)pNtk->vOnehots ); + Vec_PtrFreeP( &pNtk->vLtlProperties ); + Vec_IntFreeP( &pNtk->vObjPerm ); + Vec_IntFreeP( &pNtk->vTopo ); + Vec_IntFreeP( &pNtk->vFins ); + Vec_IntFreeP( &pNtk->vOrigNodeIds ); + ABC_FREE( pNtk ); +} + +/**Function************************************************************* + + Synopsis [Reads the verilog file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNets; + Abc_Obj_t * pNet, * pNode; + int i; + + if ( Abc_NtkNodeNum(pNtk) == 0 && Abc_NtkBoxNum(pNtk) == 0 ) + return; + + // special case + pNet = Abc_NtkFindNet( pNtk, "[_c1_]" ); + if ( pNet != NULL ) + { + pNode = Abc_NtkCreateNodeConst1( pNtk ); + Abc_ObjAddFanin( pNet, pNode ); + } + + // check for non-driven nets + vNets = Vec_PtrAlloc( 100 ); + Abc_NtkForEachNet( pNtk, pNet, i ) + { + if ( Abc_ObjFaninNum(pNet) > 0 ) + continue; + // add the constant 0 driver + pNode = Abc_NtkCreateNodeConst0( pNtk ); + // add the fanout net + Abc_ObjAddFanin( pNet, pNode ); + // add the net to those for which the warning will be printed + Vec_PtrPush( vNets, pNet ); + } + + // print the warning + if ( vNets->nSize > 0 ) + { + printf( "Warning: Constant-0 drivers added to %d non-driven nets in network \"%s\":\n", Vec_PtrSize(vNets), pNtk->pName ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNets, pNet, i ) + { + printf( "%s%s", (i? ", ": ""), Abc_ObjName(pNet) ); + if ( i == 3 ) + { + if ( Vec_PtrSize(vNets) > 3 ) + printf( " ..." ); + break; + } + } + printf( "\n" ); + } + Vec_PtrFree( vNets ); +} + + +/**Function************************************************************* + + Synopsis [Converts the network to combinational.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMakeComb( Abc_Ntk_t * pNtk, int fRemoveLatches ) +{ + Abc_Obj_t * pObj; + int i; + + if ( Abc_NtkIsComb(pNtk) ) + return; + + assert( !Abc_NtkIsNetlist(pNtk) ); + assert( Abc_NtkHasOnlyLatchBoxes(pNtk) ); + + // detach the latches +// Abc_NtkForEachLatch( pNtk, pObj, i ) + Vec_PtrForEachEntryReverse( Abc_Obj_t *, pNtk->vBoxes, pObj, i ) + Abc_NtkDeleteObj( pObj ); + assert( Abc_NtkLatchNum(pNtk) == 0 ); + assert( Abc_NtkBoxNum(pNtk) == 0 ); + + // move CIs to become PIs + Vec_PtrClear( pNtk->vPis ); + Abc_NtkForEachCi( pNtk, pObj, i ) + { + if ( Abc_ObjIsBo(pObj) ) + { + pObj->Type = ABC_OBJ_PI; + pNtk->nObjCounts[ABC_OBJ_PI]++; + pNtk->nObjCounts[ABC_OBJ_BO]--; + } + Vec_PtrPush( pNtk->vPis, pObj ); + } + assert( Abc_NtkBoNum(pNtk) == 0 ); + + if ( fRemoveLatches ) + { + // remove registers + Vec_Ptr_t * vBos; + vBos = Vec_PtrAlloc( 100 ); + Vec_PtrClear( pNtk->vPos ); + Abc_NtkForEachCo( pNtk, pObj, i ) + if ( Abc_ObjIsBi(pObj) ) + Vec_PtrPush( vBos, pObj ); + else + Vec_PtrPush( pNtk->vPos, pObj ); + // remove COs + Vec_PtrFree( pNtk->vCos ); + pNtk->vCos = NULL; + // remove the BOs + Vec_PtrForEachEntry( Abc_Obj_t *, vBos, pObj, i ) + Abc_NtkDeleteObj( pObj ); + Vec_PtrFree( vBos ); + // create COs + pNtk->vCos = Vec_PtrDup( pNtk->vPos ); + // cleanup + if ( Abc_NtkIsLogic(pNtk) ) + Abc_NtkCleanup( pNtk, 0 ); + else if ( Abc_NtkIsStrash(pNtk) ) + Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc ); + else + assert( 0 ); + } + else + { + // move COs to become POs + Vec_PtrClear( pNtk->vPos ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + if ( Abc_ObjIsBi(pObj) ) + { + pObj->Type = ABC_OBJ_PO; + pNtk->nObjCounts[ABC_OBJ_PO]++; + pNtk->nObjCounts[ABC_OBJ_BI]--; + } + Vec_PtrPush( pNtk->vPos, pObj ); + } + } + assert( Abc_NtkBiNum(pNtk) == 0 ); + + if ( !Abc_NtkCheck( pNtk ) ) + fprintf( stdout, "Abc_NtkMakeComb(): Network check has failed.\n" ); +} + +/**Function************************************************************* + + Synopsis [Converts the network to sequential.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkMakeSeq( Abc_Ntk_t * pNtk, int nLatchesToAdd ) +{ + Abc_Obj_t * pObjLi, * pObjLo, * pObj; + int i; + assert( Abc_NtkBoxNum(pNtk) == 0 ); + if ( !Abc_NtkIsComb(pNtk) ) + { + printf( "The network is a not a combinational one.\n" ); + return; + } + if ( nLatchesToAdd >= Abc_NtkPiNum(pNtk) ) + { + printf( "The number of latches is more or equal than the number of PIs.\n" ); + return; + } + if ( nLatchesToAdd >= Abc_NtkPoNum(pNtk) ) + { + printf( "The number of latches is more or equal than the number of POs.\n" ); + return; + } + + // move the last PIs to become CIs + Vec_PtrClear( pNtk->vPis ); + Abc_NtkForEachCi( pNtk, pObj, i ) + { + if ( i < Abc_NtkCiNum(pNtk) - nLatchesToAdd ) + { + Vec_PtrPush( pNtk->vPis, pObj ); + continue; + } + pObj->Type = ABC_OBJ_BO; + pNtk->nObjCounts[ABC_OBJ_PI]--; + pNtk->nObjCounts[ABC_OBJ_BO]++; + } + + // move the last POs to become COs + Vec_PtrClear( pNtk->vPos ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + if ( i < Abc_NtkCoNum(pNtk) - nLatchesToAdd ) + { + Vec_PtrPush( pNtk->vPos, pObj ); + continue; + } + pObj->Type = ABC_OBJ_BI; + pNtk->nObjCounts[ABC_OBJ_PO]--; + pNtk->nObjCounts[ABC_OBJ_BI]++; + } + + // create latches + for ( i = 0; i < nLatchesToAdd; i++ ) + { + pObjLo = Abc_NtkCi( pNtk, Abc_NtkCiNum(pNtk) - nLatchesToAdd + i ); + pObjLi = Abc_NtkCo( pNtk, Abc_NtkCoNum(pNtk) - nLatchesToAdd + i ); + pObj = Abc_NtkCreateLatch( pNtk ); + Abc_ObjAddFanin( pObj, pObjLi ); + Abc_ObjAddFanin( pObjLo, pObj ); + Abc_LatchSetInit0( pObj ); + } + + if ( !Abc_NtkCheck( pNtk ) ) + fprintf( stdout, "Abc_NtkMakeSeq(): Network check has failed.\n" ); +} + + +/**Function************************************************************* + + Synopsis [Keeps POs in the array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkSelectPos( Abc_Ntk_t * pNtkInit, Vec_Int_t * vPoIds ) +{ + Abc_Ntk_t * pNtk; + Vec_Ptr_t * vPosLeft; + Vec_Ptr_t * vCosLeft; + Abc_Obj_t * pNodePo; + int i, Index; + assert( !Abc_NtkIsNetlist(pNtkInit) ); + assert( Abc_NtkHasOnlyLatchBoxes(pNtkInit) ); + pNtk = Abc_NtkDup( pNtkInit ); + if ( Abc_NtkPoNum(pNtk) == 1 ) + return pNtk; + vPosLeft = Vec_PtrAlloc( Vec_IntSize(vPoIds) ); + Vec_IntForEachEntry( vPoIds, Index, i ) { + Vec_PtrPush( vPosLeft, Abc_NtkPo(pNtk, Index) ); + Vec_PtrWriteEntry( pNtk->vPos, Index, NULL ); + } + // filter COs + vCosLeft = Vec_PtrDup( vPosLeft ); + for ( i = Abc_NtkPoNum(pNtk); i < Abc_NtkCoNum(pNtk); i++ ) + Vec_PtrPush( vCosLeft, Abc_NtkCo(pNtk, i) ); + // remove remaiing POs + Abc_NtkForEachPo( pNtk, pNodePo, i ) + if ( pNodePo ) + Abc_NtkDeleteObjPo( pNodePo ); + // update arrays + Vec_PtrFree( pNtk->vPos ); pNtk->vPos = vPosLeft; + Vec_PtrFree( pNtk->vCos ); pNtk->vCos = vCosLeft; + // clean the network + if ( Abc_NtkIsStrash(pNtk) ) { + Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc ); + if ( Abc_NtkLatchNum(pNtk) ) printf( "Run sequential cleanup (\"scl\") to get rid of dangling logic.\n" ); + } + else { + if ( Abc_NtkLatchNum(pNtk) ) printf( "Run sequential cleanup (\"st; scl\") to get rid of dangling logic.\n" ); + } + if ( !Abc_NtkCheck( pNtk ) ) + fprintf( stdout, "Abc_NtkMakeComb(): Network check has failed.\n" ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Removes all POs, except one.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkMakeOnePo( Abc_Ntk_t * pNtkInit, int Output, int nRange ) +{ + Abc_Ntk_t * pNtk; + Vec_Ptr_t * vPosLeft; + Vec_Ptr_t * vCosLeft; + Abc_Obj_t * pNodePo; + int i; + assert( !Abc_NtkIsNetlist(pNtkInit) ); + assert( Abc_NtkHasOnlyLatchBoxes(pNtkInit) ); + if ( Output < 0 || Output >= Abc_NtkPoNum(pNtkInit) ) + { + printf( "PO index is incorrect.\n" ); + return NULL; + } + + pNtk = Abc_NtkDup( pNtkInit ); + if ( Abc_NtkPoNum(pNtk) == 1 ) + return pNtk; + + if ( nRange < 1 ) + nRange = 1; + + // filter POs + vPosLeft = Vec_PtrAlloc( nRange ); + Abc_NtkForEachPo( pNtk, pNodePo, i ) + if ( i < Output || i >= Output + nRange ) + Abc_NtkDeleteObjPo( pNodePo ); + else + Vec_PtrPush( vPosLeft, pNodePo ); + // filter COs + vCosLeft = Vec_PtrDup( vPosLeft ); + for ( i = Abc_NtkPoNum(pNtk); i < Abc_NtkCoNum(pNtk); i++ ) + Vec_PtrPush( vCosLeft, Abc_NtkCo(pNtk, i) ); + // update arrays + Vec_PtrFree( pNtk->vPos ); pNtk->vPos = vPosLeft; + Vec_PtrFree( pNtk->vCos ); pNtk->vCos = vCosLeft; + + // clean the network + if ( Abc_NtkIsStrash(pNtk) ) + { + Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc ); + if ( Abc_NtkLatchNum(pNtk) ) printf( "Run sequential cleanup (\"scl\") to get rid of dangling logic.\n" ); + } + else + { + if ( Abc_NtkLatchNum(pNtk) ) printf( "Run sequential cleanup (\"st; scl\") to get rid of dangling logic.\n" ); + } + + if ( !Abc_NtkCheck( pNtk ) ) + fprintf( stdout, "Abc_NtkMakeComb(): Network check has failed.\n" ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [Removes POs with suppsize less than 2 and PIs without fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkTrim( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i, k, m; + + // filter POs + k = m = 0; + Abc_NtkForEachCo( pNtk, pObj, i ) + { + if ( Abc_ObjIsPo(pObj) ) + { + // remove constant nodes and PI pointers + if ( Abc_ObjFaninNum(Abc_ObjFanin0(pObj)) == 0 ) + { + Abc_ObjDeleteFanin( pObj, Abc_ObjFanin0(pObj) ); + if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) == 0 && !Abc_ObjIsPi(Abc_ObjFanin0(pObj)) ) + Abc_NtkDeleteObj_rec( Abc_ObjFanin0(pObj), 1 ); + pNtk->vObjs->pArray[pObj->Id] = NULL; + pObj->Id = (1<<26)-1; + pNtk->nObjCounts[pObj->Type]--; + pNtk->nObjs--; + Abc_ObjRecycle( pObj ); + continue; + } + // remove buffers/inverters of PIs + if ( Abc_ObjFaninNum(Abc_ObjFanin0(pObj)) == 1 ) + { + if ( Abc_ObjIsPi(Abc_ObjFanin0(Abc_ObjFanin0(pObj))) ) + { + Abc_ObjDeleteFanin( pObj, Abc_ObjFanin0(pObj) ); + if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pObj)) == 0 ) + Abc_NtkDeleteObj_rec( Abc_ObjFanin0(pObj), 1 ); + pNtk->vObjs->pArray[pObj->Id] = NULL; + pObj->Id = (1<<26)-1; + pNtk->nObjCounts[pObj->Type]--; + pNtk->nObjs--; + Abc_ObjRecycle( pObj ); + continue; + } + } + Vec_PtrWriteEntry( pNtk->vPos, m++, pObj ); + } + Vec_PtrWriteEntry( pNtk->vCos, k++, pObj ); + } + Vec_PtrShrink( pNtk->vPos, m ); + Vec_PtrShrink( pNtk->vCos, k ); + + // filter PIs + k = m = 0; + Abc_NtkForEachCi( pNtk, pObj, i ) + { + if ( Abc_ObjIsPi(pObj) ) + { + if ( Abc_ObjFanoutNum(pObj) == 0 ) + { + pNtk->vObjs->pArray[pObj->Id] = NULL; + pObj->Id = (1<<26)-1; + pNtk->nObjCounts[pObj->Type]--; + pNtk->nObjs--; + Abc_ObjRecycle( pObj ); + continue; + } + Vec_PtrWriteEntry( pNtk->vPis, m++, pObj ); + } + Vec_PtrWriteEntry( pNtk->vCis, k++, pObj ); + } + Vec_PtrShrink( pNtk->vPis, m ); + Vec_PtrShrink( pNtk->vCis, k ); + + return Abc_NtkDup( pNtk ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDropSatOutputs( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCexes, int fVerbose ) +{ + Abc_Obj_t * pObj, * pConst0, * pFaninNew; + int i, Counter = 0; + assert( Vec_PtrSize(vCexes) == Abc_NtkPoNum(pNtk) ); + pConst0 = Abc_ObjNot( Abc_AigConst1(pNtk) ); + Abc_NtkForEachPo( pNtk, pObj, i ) + { + if ( Vec_PtrEntry( vCexes, i ) == NULL ) + continue; + Counter++; + pFaninNew = Abc_ObjNotCond( pConst0, Abc_ObjFaninC0(pObj) ); + Abc_ObjPatchFanin( pObj, Abc_ObjFanin0(pObj), pFaninNew ); + assert( Abc_ObjChild0(pObj) == pConst0 ); + // if a PO is driven by a latch, they have the same name... +// if ( Abc_ObjIsBo(pObj) ) +// Nm_ManDeleteIdName( pNtk->pManName, Abc_ObjId(pObj) ); + } + if ( fVerbose ) + printf( "Logic cones of %d POs have been replaced by constant 0.\n", Counter ); + Counter = Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc ); +// printf( "Cleanup removed %d nodes.\n", Counter ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDropOneOutput( Abc_Ntk_t * pNtk, int iOutput, int fSkipSweep, int fUseConst1 ) +{ + Abc_Obj_t * pObj, * pConst0, * pFaninNew; + pObj = Abc_NtkPo( pNtk, iOutput ); + if ( Abc_ObjFanin0(pObj) == Abc_AigConst1(pNtk) ) + { + if ( !Abc_ObjFaninC0(pObj) ^ fUseConst1 ) + Abc_ObjXorFaninC( pObj, 0 ); + return; + } + pConst0 = Abc_ObjNotCond( Abc_AigConst1(pNtk), !fUseConst1 ); + pFaninNew = Abc_ObjNotCond( pConst0, Abc_ObjFaninC0(pObj) ); + Abc_ObjPatchFanin( pObj, Abc_ObjFanin0(pObj), pFaninNew ); + assert( Abc_ObjChild0(pObj) == pConst0 ); + if ( fSkipSweep ) + return; + Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkSwapOneOutput( Abc_Ntk_t * pNtk, int iOutput ) +{ + Abc_Obj_t * pObj1, * pObj2; + Abc_Obj_t * pChild1Old, * pChild2Old; + Abc_Obj_t * pChild1, * pChild2; + if ( iOutput == 0 ) + return; + pObj1 = Abc_NtkPo( pNtk, 0 ); + pObj2 = Abc_NtkPo( pNtk, iOutput ); + if ( Abc_ObjFanin0(pObj1) == Abc_ObjFanin0(pObj2) ) + { + if ( Abc_ObjFaninC0(pObj1) ^ Abc_ObjFaninC0(pObj2) ) + { + Abc_ObjXorFaninC( pObj1, 0 ); + Abc_ObjXorFaninC( pObj2, 0 ); + } + return; + } + pChild1Old = Abc_ObjChild0( pObj1 ); + pChild2Old = Abc_ObjChild0( pObj2 ); + pChild1 = Abc_ObjNotCond( pChild1Old, Abc_ObjFaninC0(pObj2) ); + pChild2 = Abc_ObjNotCond( pChild2Old, Abc_ObjFaninC0(pObj1) ); + Abc_ObjPatchFanin( pObj1, Abc_ObjFanin0(pObj1), pChild2 ); + Abc_ObjPatchFanin( pObj2, Abc_ObjFanin0(pObj2), pChild1 ); + assert( Abc_ObjChild0(pObj1) == pChild2Old ); + assert( Abc_ObjChild0(pObj2) == pChild1Old ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkRemovePo( Abc_Ntk_t * pNtk, int iOutput, int fRemoveConst0 ) +{ + Abc_Obj_t * pObj = Abc_NtkPo(pNtk, iOutput); + if ( Abc_ObjFanin0(pObj) == Abc_AigConst1(pNtk) && Abc_ObjFaninC0(pObj) == fRemoveConst0 ) + Abc_NtkDeleteObj( pObj ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkReadSignalPerm2( char * pFileName, int nSignals ) +{ + char Buffer[1000]; + FILE * pFile; + Vec_Int_t * vSignals; + int iFlop = -1; + pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open input file \"%s\".\n", pFileName ); + return NULL; + } + vSignals = Vec_IntAlloc( nSignals ); + while ( fgets( Buffer, 1000, pFile ) != NULL ) + { + if ( Buffer[0] == ' ' || Buffer[0] == '\r' || Buffer[0] == '\n' ) + continue; + iFlop = atoi( Buffer ); + if ( iFlop < 0 || iFlop >= nSignals ) + { + printf( "The zero-based signal ID (%d) is out of range.\n", iFlop ); + fclose( pFile ); + Vec_IntFree( vSignals ); + return NULL; + } + Vec_IntPush( vSignals, iFlop ); + } + fclose( pFile ); + if ( Vec_IntSize(vSignals) != nSignals ) + { + printf( "The number of indexes read in from file (%d) is different from the number of signals in the circuit (%d).\n", Vec_IntSize(vSignals), nSignals ); + Vec_IntFree( vSignals ); + return NULL; + } + return vSignals; +} + +Vec_Int_t * Abc_NtkReadSignalPerm( char * pFileName, int nSignals ) +{ + int Num = -1; + Vec_Int_t * vSignals; + FILE * pFile = fopen( pFileName, "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open input file \"%s\".\n", pFileName ); + return NULL; + } + vSignals = Vec_IntAlloc( nSignals ); + while ( fscanf( pFile, "%d", &Num ) == 1 ) + { + if ( Num <= 0 || Num > nSignals ) + { + printf( "The one-based signal ID (%d) is out of range (%d).\n", Num, nSignals ); + fclose( pFile ); + Vec_IntFree( vSignals ); + return NULL; + } + Vec_IntPush( vSignals, Num-1 ); + } + fclose( pFile ); + if ( Vec_IntSize(vSignals) != nSignals ) + { + printf( "The number of indexes read in from file (%d) is different from the number of signals in the circuit (%d).\n", Vec_IntSize(vSignals), nSignals ); + Vec_IntFree( vSignals ); + return NULL; + } + return vSignals; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPermute( Abc_Ntk_t * pNtk, int fInputs, int fOutputs, int fFlops, char * pInPermFile, char * pOutPermFile, char * pFlopPermFile ) +{ + Abc_Obj_t * pTemp; + Vec_Int_t * vInputs, * vOutputs, * vFlops, * vTemp; + int i, k, Entry; + // start permutation arrays + if ( pInPermFile ) + { + vInputs = Abc_NtkReadSignalPerm( pInPermFile, Abc_NtkPiNum(pNtk) ); + if ( vInputs == NULL ) + return; + fInputs = 1; + } + else + vInputs = Vec_IntStartNatural( Abc_NtkPiNum(pNtk) ); + if ( pOutPermFile ) + { + vOutputs = Abc_NtkReadSignalPerm( pOutPermFile, Abc_NtkPoNum(pNtk) ); + if ( vOutputs == NULL ) + return; + fOutputs = 1; + } + else + vOutputs = Vec_IntStartNatural( Abc_NtkPoNum(pNtk) ); + if ( pFlopPermFile ) + { + vFlops = Abc_NtkReadSignalPerm( pFlopPermFile, Abc_NtkLatchNum(pNtk) ); + if ( vFlops == NULL ) + return; + fFlops = 1; + } + else + vFlops = Vec_IntStartNatural( Abc_NtkLatchNum(pNtk) ); + // permute inputs + Vec_Ptr_t * vCis = Vec_PtrDup(pNtk->vCis); + Vec_Ptr_t * vCos = Vec_PtrDup(pNtk->vCos); + Vec_Ptr_t * vFfs = Vec_PtrDup(pNtk->vBoxes); + if ( fInputs ) + for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ ) + { + if ( pInPermFile ) + { + k = Vec_IntEntry( vInputs, i ); + pTemp = (Abc_Obj_t *)Vec_PtrEntry( vCis, k ); + Vec_PtrWriteEntry( pNtk->vPis, i, pTemp ); + Vec_PtrWriteEntry( pNtk->vCis, i, pTemp ); + } + else + { + k = rand() % Abc_NtkPiNum(pNtk); + // swap indexes + Entry = Vec_IntEntry( vInputs, i ); + Vec_IntWriteEntry( vInputs, i, Vec_IntEntry(vInputs, k) ); + Vec_IntWriteEntry( vInputs, k, Entry ); + // swap PIs + pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPis, i ); + Vec_PtrWriteEntry( pNtk->vPis, i, Vec_PtrEntry(pNtk->vPis, k) ); + Vec_PtrWriteEntry( pNtk->vPis, k, pTemp ); + // swap CIs + pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCis, i ); + Vec_PtrWriteEntry( pNtk->vCis, i, Vec_PtrEntry(pNtk->vCis, k) ); + Vec_PtrWriteEntry( pNtk->vCis, k, pTemp ); + } +//printf( "Swapping PIs %d and %d.\n", i, k ); + } + // permute outputs + if ( fOutputs ) + for ( i = 0; i < Abc_NtkPoNum(pNtk); i++ ) + { + if ( pOutPermFile ) + { + k = Vec_IntEntry( vOutputs, i ); + pTemp = (Abc_Obj_t *)Vec_PtrEntry( vCos, k ); + Vec_PtrWriteEntry( pNtk->vPos, i, pTemp ); + Vec_PtrWriteEntry( pNtk->vCos, i, pTemp ); + } + else + { + k = rand() % Abc_NtkPoNum(pNtk); + // swap indexes + Entry = Vec_IntEntry( vOutputs, i ); + Vec_IntWriteEntry( vOutputs, i, Vec_IntEntry(vOutputs, k) ); + Vec_IntWriteEntry( vOutputs, k, Entry ); + // swap POs + pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPos, i ); + Vec_PtrWriteEntry( pNtk->vPos, i, Vec_PtrEntry(pNtk->vPos, k) ); + Vec_PtrWriteEntry( pNtk->vPos, k, pTemp ); + // swap COs + pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCos, i ); + Vec_PtrWriteEntry( pNtk->vCos, i, Vec_PtrEntry(pNtk->vCos, k) ); + Vec_PtrWriteEntry( pNtk->vCos, k, pTemp ); + } +//printf( "Swapping POs %d and %d.\n", i, k ); + } + // permute flops + assert( Abc_NtkBoxNum(pNtk) == Abc_NtkLatchNum(pNtk) ); + if ( fFlops ) + for ( i = 0; i < Abc_NtkLatchNum(pNtk); i++ ) + { + if ( pFlopPermFile ) + { + k = Vec_IntEntry( vFlops, i ); + pTemp = (Abc_Obj_t *)Vec_PtrEntry( vFfs, k ); + Vec_PtrWriteEntry( pNtk->vBoxes, i, pTemp ); + pTemp = (Abc_Obj_t *)Vec_PtrEntry( vCis, Abc_NtkPiNum(pNtk)+k ); + Vec_PtrWriteEntry( pNtk->vCis, Abc_NtkPiNum(pNtk)+i, pTemp ); + pTemp = (Abc_Obj_t *)Vec_PtrEntry( vCos, Abc_NtkPoNum(pNtk)+k ); + Vec_PtrWriteEntry( pNtk->vCos, Abc_NtkPoNum(pNtk)+i, pTemp ); + } + else + { + k = rand() % Abc_NtkLatchNum(pNtk); + // swap indexes + Entry = Vec_IntEntry( vFlops, i ); + Vec_IntWriteEntry( vFlops, i, Vec_IntEntry(vFlops, k) ); + Vec_IntWriteEntry( vFlops, k, Entry ); + // swap flops + pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vBoxes, i ); + Vec_PtrWriteEntry( pNtk->vBoxes, i, Vec_PtrEntry(pNtk->vBoxes, k) ); + Vec_PtrWriteEntry( pNtk->vBoxes, k, pTemp ); + // swap CIs + pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCis, Abc_NtkPiNum(pNtk)+i ); + Vec_PtrWriteEntry( pNtk->vCis, Abc_NtkPiNum(pNtk)+i, Vec_PtrEntry(pNtk->vCis, Abc_NtkPiNum(pNtk)+k) ); + Vec_PtrWriteEntry( pNtk->vCis, Abc_NtkPiNum(pNtk)+k, pTemp ); + // swap COs + pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCos, Abc_NtkPoNum(pNtk)+i ); + Vec_PtrWriteEntry( pNtk->vCos, Abc_NtkPoNum(pNtk)+i, Vec_PtrEntry(pNtk->vCos, Abc_NtkPoNum(pNtk)+k) ); + Vec_PtrWriteEntry( pNtk->vCos, Abc_NtkPoNum(pNtk)+k, pTemp ); + } + +//printf( "Swapping flops %d and %d.\n", i, k ); + } + Vec_PtrFree(vCis); + Vec_PtrFree(vCos); + Vec_PtrFree(vFfs); + // invert arrays + vInputs = Vec_IntInvert( vTemp = vInputs, -1 ); + Vec_IntFree( vTemp ); + vOutputs = Vec_IntInvert( vTemp = vOutputs, -1 ); + Vec_IntFree( vTemp ); + vFlops = Vec_IntInvert( vTemp = vFlops, -1 ); + Vec_IntFree( vTemp ); + // pack the results into the output array + Vec_IntFreeP( &pNtk->vObjPerm ); + pNtk->vObjPerm = Vec_IntAlloc( Abc_NtkPiNum(pNtk) + Abc_NtkPoNum(pNtk) + Abc_NtkLatchNum(pNtk) ); + Vec_IntForEachEntry( vInputs, Entry, i ) + Vec_IntPush( pNtk->vObjPerm, Entry ); + Vec_IntForEachEntry( vOutputs, Entry, i ) + Vec_IntPush( pNtk->vObjPerm, Entry ); + Vec_IntForEachEntry( vFlops, Entry, i ) + Vec_IntPush( pNtk->vObjPerm, Entry ); + // cleanup + Vec_IntFree( vInputs ); + Vec_IntFree( vOutputs ); + Vec_IntFree( vFlops ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeCompareByFanoutCount( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) +{ + int Diff = Abc_ObjFanoutNum(*pp2) - Abc_ObjFanoutNum(*pp1); + if ( Diff < 0 ) + return -1; + if ( Diff > 0 ) + return 1; + Diff = strcmp( Abc_ObjName(*pp1), Abc_ObjName(*pp2) ); + if ( Diff < 0 ) + return -1; + if ( Diff > 0 ) + return 1; + return 0; +} +void Abc_NtkPermutePiUsingFanout( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; int i; + qsort( (void *)Vec_PtrArray(pNtk->vPis), (size_t)Vec_PtrSize(pNtk->vPis), sizeof(Abc_Obj_t *), + (int (*)(const void *, const void *)) Abc_NodeCompareByFanoutCount ); + Vec_PtrClear( pNtk->vCis ); + Vec_PtrForEachEntry( Abc_Obj_t *, pNtk->vPis, pNode, i ) + Vec_PtrPush( pNtk->vCis, pNode ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkUnpermute( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vTemp, * vTemp2, * vLatch; + int i, * pInputs, * pOutputs, * pFlops; + if ( pNtk->vObjPerm == NULL ) + { + printf( "Abc_NtkUnpermute(): Initial permutation is not available.\n" ); + return; + } + assert( Abc_NtkBoxNum(pNtk) == Abc_NtkLatchNum(pNtk) ); + // get reverve permutation + pInputs = Vec_IntArray( pNtk->vObjPerm ); + pOutputs = pInputs + Abc_NtkPiNum(pNtk); + pFlops = pOutputs + Abc_NtkPoNum(pNtk); + // create new PI array + vTemp = Vec_PtrAlloc( Abc_NtkPiNum(pNtk) ); + for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ ) + Vec_PtrPush( vTemp, Abc_NtkPi(pNtk, pInputs[i]) ); + Vec_PtrFreeP( &pNtk->vPis ); + pNtk->vPis = vTemp; + // create new PO array + vTemp = Vec_PtrAlloc( Abc_NtkPoNum(pNtk) ); + for ( i = 0; i < Abc_NtkPoNum(pNtk); i++ ) + Vec_PtrPush( vTemp, Abc_NtkPo(pNtk, pOutputs[i]) ); + Vec_PtrFreeP( &pNtk->vPos ); + pNtk->vPos = vTemp; + // create new CI/CO arrays + vTemp = Vec_PtrDup( pNtk->vPis ); + vTemp2 = Vec_PtrDup( pNtk->vPos ); + vLatch = Vec_PtrAlloc( Abc_NtkLatchNum(pNtk) ); + for ( i = 0; i < Abc_NtkLatchNum(pNtk); i++ ) + { +//printf( "Setting flop %d to be %d.\n", i, pFlops[i] ); + Vec_PtrPush( vTemp, Abc_NtkCi(pNtk, Abc_NtkPiNum(pNtk) + pFlops[i]) ); + Vec_PtrPush( vTemp2, Abc_NtkCo(pNtk, Abc_NtkPoNum(pNtk) + pFlops[i]) ); + Vec_PtrPush( vLatch, Abc_NtkBox(pNtk, pFlops[i]) ); + } + Vec_PtrFreeP( &pNtk->vCis ); + Vec_PtrFreeP( &pNtk->vCos ); + Vec_PtrFreeP( &pNtk->vBoxes ); + pNtk->vCis = vTemp; + pNtk->vCos = vTemp2; + pNtk->vBoxes = vLatch; + // cleanup + Vec_IntFreeP( &pNtk->vObjPerm ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkNodeDup( Abc_Ntk_t * pNtkInit, int nLimit, int fVerbose ) +{ + Vec_Ptr_t * vNodes, * vFanouts; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pObj, * pObjNew, * pFanin, * pFanout; + int i, k; + pNtk = Abc_NtkDup( pNtkInit ); + vNodes = Vec_PtrAlloc( 100 ); + vFanouts = Vec_PtrAlloc( 100 ); + do + { + Vec_PtrClear( vNodes ); + Abc_NtkForEachNode( pNtk, pObj, i ) + if ( Abc_ObjFanoutNum(pObj) >= nLimit ) + Vec_PtrPush( vNodes, pObj ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + { + pObjNew = Abc_NtkDupObj( pNtk, pObj, 0 ); + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObjNew, pFanin ); + Abc_NodeCollectFanouts( pObj, vFanouts ); + Vec_PtrShrink( vFanouts, nLimit / 2 ); + Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pFanout, k ) + Abc_ObjPatchFanin( pFanout, pObj, pObjNew ); + } + if ( fVerbose ) + printf( "Duplicated %d nodes.\n", Vec_PtrSize(vNodes) ); + } + while ( Vec_PtrSize(vNodes) > 0 ); + Vec_PtrFree( vFanouts ); + Vec_PtrFree( vNodes ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateFromSops( char * pName, Vec_Ptr_t * vSops ) +{ + int i, k, nObjBeg; + char * pSop = (char *)Vec_PtrEntry(vSops, 0); + Abc_Ntk_t * pNtk = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); + pNtk->pName = Extra_UtilStrsav( pName ); + for ( k = 0; pSop[k] != ' '; k++ ) + Abc_NtkCreatePi( pNtk ); + nObjBeg = Abc_NtkObjNumMax(pNtk); + Vec_PtrForEachEntry( char *, vSops, pSop, i ) + { + Abc_Obj_t * pObj = Abc_NtkCreateNode( pNtk ); + pObj->pData = Abc_SopRegister( (Mem_Flex_t*)pNtk->pManFunc, pSop ); + for ( k = 0; pSop[k] != ' '; k++ ) + Abc_ObjAddFanin( pObj, Abc_NtkCi(pNtk, k) ); + } + for ( i = 0; i < Vec_PtrSize(vSops); i++ ) + { + Abc_Obj_t * pObj = Abc_NtkObj( pNtk, nObjBeg + i ); + Abc_Obj_t * pObjPo = Abc_NtkCreatePo( pNtk ); + Abc_ObjAddFanin( pObjPo, pObj ); + } + Abc_NtkAddDummyPiNames( pNtk ); + Abc_NtkAddDummyPoNames( pNtk ); + return pNtk; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreateFromGias( char * pName, Vec_Ptr_t * vGias, Gia_Man_t * pMulti ) +{ + Gia_Man_t * pGia = pMulti ? pMulti : (Gia_Man_t *)Vec_PtrEntry(vGias, 0); + Abc_Ntk_t * pNtk = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); + Abc_Obj_t * pAbcObj, * pAbcObjPo; + Gia_Obj_t * pObj; int i, k; + pNtk->pName = Extra_UtilStrsav( pName ); + for ( k = 0; k < Gia_ManCiNum(pGia); k++ ) + Abc_NtkCreatePi( pNtk ); + if ( pMulti ) + { + Gia_ManCleanValue(pGia); + Gia_ManForEachCi( pGia, pObj, k ) + pObj->Value = Abc_ObjId( Abc_NtkCi(pNtk, k) ); + Gia_ManForEachAnd( pGia, pObj, k ) + { + Abc_Obj_t * pAbcObj0 = Abc_NtkObj( pNtk, Gia_ObjFanin0(pObj)->Value ); + Abc_Obj_t * pAbcObj1 = Abc_NtkObj( pNtk, Gia_ObjFanin1(pObj)->Value ); + pAbcObj0 = Abc_ObjNotCond( pAbcObj0, Gia_ObjFaninC0(pObj) ); + pAbcObj1 = Abc_ObjNotCond( pAbcObj1, Gia_ObjFaninC1(pObj) ); + pAbcObj = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, pAbcObj0, pAbcObj1 ); + pObj->Value = Abc_ObjId( pAbcObj ); + } + Gia_ManForEachCo( pGia, pObj, k ) + { + //pObj = Gia_ManCo(pGia, 0); + if ( Gia_ObjFaninId0p(pGia, pObj) == 0 ) + pAbcObj = Abc_ObjNot( Abc_AigConst1(pNtk) ); + else + pAbcObj = Abc_NtkObj( pNtk, Gia_ObjFanin0(pObj)->Value ); + pAbcObj = Abc_ObjNotCond( pAbcObj, Gia_ObjFaninC0(pObj) ); + pAbcObjPo = Abc_NtkCreatePo( pNtk ); + Abc_ObjAddFanin( pAbcObjPo, pAbcObj ); + } + } + else + { + Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) + { + assert( Gia_ManCoNum(pGia) == 1 ); + Gia_ManCleanValue(pGia); + Gia_ManForEachCi( pGia, pObj, k ) + pObj->Value = Abc_ObjId( Abc_NtkCi(pNtk, k) ); + Gia_ManForEachAnd( pGia, pObj, k ) + { + Abc_Obj_t * pAbcObj0 = Abc_NtkObj( pNtk, Gia_ObjFanin0(pObj)->Value ); + Abc_Obj_t * pAbcObj1 = Abc_NtkObj( pNtk, Gia_ObjFanin1(pObj)->Value ); + pAbcObj0 = Abc_ObjNotCond( pAbcObj0, Gia_ObjFaninC0(pObj) ); + pAbcObj1 = Abc_ObjNotCond( pAbcObj1, Gia_ObjFaninC1(pObj) ); + pAbcObj = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, pAbcObj0, pAbcObj1 ); + pObj->Value = Abc_ObjId( pAbcObj ); + } + pObj = Gia_ManCo(pGia, 0); + if ( Gia_ObjFaninId0p(pGia, pObj) == 0 ) + pAbcObj = Abc_ObjNot( Abc_AigConst1(pNtk) ); + else + pAbcObj = Abc_NtkObj( pNtk, Gia_ObjFanin0(pObj)->Value ); + pAbcObj = Abc_ObjNotCond( pAbcObj, Gia_ObjFaninC0(pObj) ); + pAbcObjPo = Abc_NtkCreatePo( pNtk ); + Abc_ObjAddFanin( pAbcObjPo, pAbcObj ); + } + } + Abc_NtkAddDummyPiNames( pNtk ); + Abc_NtkAddDummyPoNames( pNtk ); + return pNtk; +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/abcObj.c b/yosys/abc/src/base/abc/abcObj.c new file mode 100644 index 00000000000..65ea91dc562 --- /dev/null +++ b/yosys/abc/src/base/abc/abcObj.c @@ -0,0 +1,1076 @@ +/**CFile**************************************************************** + + FileName [abcObj.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Object creation/duplication/deletion procedures.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcObj.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "abcInt.h" +#include "base/main/main.h" +#include "map/mio/mio.h" + +#ifdef ABC_USE_CUDD +#include "bdd/extrab/extraBdd.h" +#endif + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Creates a new object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_ObjAlloc( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ) +{ + Abc_Obj_t * pObj; + if ( pNtk->pMmObj ) + pObj = (Abc_Obj_t *)Mem_FixedEntryFetch( pNtk->pMmObj ); + else + pObj = (Abc_Obj_t *)ABC_ALLOC( Abc_Obj_t, 1 ); + memset( pObj, 0, sizeof(Abc_Obj_t) ); + pObj->pNtk = pNtk; + pObj->Type = Type; + pObj->Id = -1; + return pObj; +} + +/**Function************************************************************* + + Synopsis [Recycles the object.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ObjRecycle( Abc_Obj_t * pObj ) +{ + Abc_Ntk_t * pNtk = pObj->pNtk; +// int LargePiece = (4 << ABC_NUM_STEPS); + // free large fanout arrays +// if ( pNtk->pMmStep && pObj->vFanouts.nCap * 4 > LargePiece ) +// free( pObj->vFanouts.pArray ); + if ( pNtk->pMmStep == NULL ) + { + ABC_FREE( pObj->vFanouts.pArray ); + ABC_FREE( pObj->vFanins.pArray ); + } + // clean the memory to make deleted object distinct from the live one + memset( pObj, 0, sizeof(Abc_Obj_t) ); + // recycle the object + if ( pNtk->pMmObj ) + Mem_FixedEntryRecycle( pNtk->pMmObj, (char *)pObj ); + else + ABC_FREE( pObj ); +} + +/**Function************************************************************* + + Synopsis [Adds the node to the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateObj( Abc_Ntk_t * pNtk, Abc_ObjType_t Type ) +{ + Abc_Obj_t * pObj; + // create new object, assign ID, and add to the array + pObj = Abc_ObjAlloc( pNtk, Type ); + pObj->Id = pNtk->vObjs->nSize; + Vec_PtrPush( pNtk->vObjs, pObj ); + pNtk->nObjCounts[Type]++; + pNtk->nObjs++; + // perform specialized operations depending on the object type + switch (Type) + { + case ABC_OBJ_NONE: + assert(0); + break; + case ABC_OBJ_CONST1: + assert(0); + break; + case ABC_OBJ_PI: +// pObj->iTemp = Vec_PtrSize(pNtk->vCis); + Vec_PtrPush( pNtk->vPis, pObj ); + Vec_PtrPush( pNtk->vCis, pObj ); + break; + case ABC_OBJ_PO: +// pObj->iTemp = Vec_PtrSize(pNtk->vCos); + Vec_PtrPush( pNtk->vPos, pObj ); + Vec_PtrPush( pNtk->vCos, pObj ); + break; + case ABC_OBJ_BI: + if ( pNtk->vCos ) Vec_PtrPush( pNtk->vCos, pObj ); + break; + case ABC_OBJ_BO: + if ( pNtk->vCis ) Vec_PtrPush( pNtk->vCis, pObj ); + break; + case ABC_OBJ_NET: + case ABC_OBJ_NODE: + break; + case ABC_OBJ_LATCH: + pObj->pData = (void *)ABC_INIT_NONE; + case ABC_OBJ_WHITEBOX: + case ABC_OBJ_BLACKBOX: + if ( pNtk->vBoxes ) Vec_PtrPush( pNtk->vBoxes, pObj ); + break; + default: + assert(0); + break; + } + return pObj; +} + +/**Function************************************************************* + + Synopsis [Deletes the object from the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDeleteObj( Abc_Obj_t * pObj ) +{ + Abc_Ntk_t * pNtk = pObj->pNtk; + Vec_Ptr_t * vNodes; + int i; + assert( !Abc_ObjIsComplement(pObj) ); + // remove from the table of names + if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) ) + Nm_ManDeleteIdName(pObj->pNtk->pManName, pObj->Id); + // delete fanins and fanouts + vNodes = Vec_PtrAlloc( 100 ); + Abc_NodeCollectFanouts( pObj, vNodes ); + for ( i = 0; i < vNodes->nSize; i++ ) + Abc_ObjDeleteFanin( (Abc_Obj_t *)vNodes->pArray[i], pObj ); + Abc_NodeCollectFanins( pObj, vNodes ); + for ( i = 0; i < vNodes->nSize; i++ ) + Abc_ObjDeleteFanin( pObj, (Abc_Obj_t *)vNodes->pArray[i] ); + Vec_PtrFree( vNodes ); + // remove from the list of objects + Vec_PtrWriteEntry( pNtk->vObjs, pObj->Id, NULL ); + pObj->Id = (1<<26)-1; + pNtk->nObjCounts[pObj->Type]--; + pNtk->nObjs--; + // perform specialized operations depending on the object type + switch (pObj->Type) + { + case ABC_OBJ_NONE: + assert(0); + break; + case ABC_OBJ_CONST1: + assert(0); + break; + case ABC_OBJ_PI: + Vec_PtrRemove( pNtk->vPis, pObj ); + Vec_PtrRemove( pNtk->vCis, pObj ); + break; + case ABC_OBJ_PO: + Vec_PtrRemove( pNtk->vPos, pObj ); + Vec_PtrRemove( pNtk->vCos, pObj ); + break; + case ABC_OBJ_BI: + if ( pNtk->vCos ) Vec_PtrRemove( pNtk->vCos, pObj ); + break; + case ABC_OBJ_BO: + if ( pNtk->vCis ) Vec_PtrRemove( pNtk->vCis, pObj ); + break; + case ABC_OBJ_NET: + break; + case ABC_OBJ_NODE: +#ifdef ABC_USE_CUDD + if ( Abc_NtkHasBdd(pNtk) ) + Cudd_RecursiveDeref( (DdManager *)pNtk->pManFunc, (DdNode *)pObj->pData ); +#endif + pObj->pData = NULL; + break; + case ABC_OBJ_LATCH: + case ABC_OBJ_WHITEBOX: + case ABC_OBJ_BLACKBOX: + if ( pNtk->vBoxes ) Vec_PtrRemove( pNtk->vBoxes, pObj ); + break; + default: + assert(0); + break; + } + // recycle the object memory + Abc_ObjRecycle( pObj ); +} + +/**Function************************************************************* + + Synopsis [Deletes the PO from the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDeleteObjPo( Abc_Obj_t * pObj ) +{ + assert( Abc_ObjIsPo(pObj) ); + // remove from the table of names + if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) ) + Nm_ManDeleteIdName(pObj->pNtk->pManName, pObj->Id); + // delete fanins + Abc_ObjDeleteFanin( pObj, Abc_ObjFanin0(pObj) ); + // remove from the list of objects + Vec_PtrWriteEntry( pObj->pNtk->vObjs, pObj->Id, NULL ); + pObj->Id = (1<<26)-1; + pObj->pNtk->nObjCounts[pObj->Type]--; + pObj->pNtk->nObjs--; + // recycle the object memory + Abc_ObjRecycle( pObj ); +} + + +/**Function************************************************************* + + Synopsis [Deletes the node and MFFC of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDeleteObj_rec( Abc_Obj_t * pObj, int fOnlyNodes ) +{ + Vec_Ptr_t * vNodes; + int i; + assert( !Abc_ObjIsComplement(pObj) ); + assert( !Abc_ObjIsPi(pObj) ); + assert( Abc_ObjFanoutNum(pObj) == 0 ); + // delete fanins and fanouts + vNodes = Vec_PtrAlloc( 100 ); + Abc_NodeCollectFanins( pObj, vNodes ); + Abc_NtkDeleteObj( pObj ); + if ( fOnlyNodes ) + { + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + if ( Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) == 0 ) + Abc_NtkDeleteObj_rec( pObj, fOnlyNodes ); + } + else + { + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + if ( !Abc_ObjIsPi(pObj) && Abc_ObjFanoutNum(pObj) == 0 ) + Abc_NtkDeleteObj_rec( pObj, fOnlyNodes ); + } + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Deletes the node and MFFC of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDeleteAll_rec( Abc_Obj_t * pObj ) +{ + Vec_Ptr_t * vNodes; + int i; + assert( !Abc_ObjIsComplement(pObj) ); + assert( Abc_ObjFanoutNum(pObj) == 0 ); + // delete fanins and fanouts + vNodes = Vec_PtrAlloc( 100 ); + Abc_NodeCollectFanins( pObj, vNodes ); + Abc_NtkDeleteObj( pObj ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + if ( !Abc_ObjIsNode(pObj) && Abc_ObjFanoutNum(pObj) == 0 ) + Abc_NtkDeleteAll_rec( pObj ); + Vec_PtrFree( vNodes ); +} + +/**Function************************************************************* + + Synopsis [Duplicate the Obj.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, int fCopyName ) +{ + Abc_Obj_t * pObjNew; + // create the new object + pObjNew = Abc_NtkCreateObj( pNtkNew, (Abc_ObjType_t)pObj->Type ); + // transfer names of the terminal objects + if ( fCopyName ) + { + if ( Abc_ObjIsCi(pObj) ) + { + if ( !Abc_NtkIsNetlist(pNtkNew) ) + Abc_ObjAssignName( pObjNew, Abc_ObjName(Abc_ObjFanout0Ntk(pObj)), NULL ); + } + else if ( Abc_ObjIsCo(pObj) ) + { + if ( !Abc_NtkIsNetlist(pNtkNew) ) + { + if ( Abc_ObjIsPo(pObj) ) + Abc_ObjAssignName( pObjNew, Abc_ObjName(Abc_ObjFanin0Ntk(pObj)), NULL ); + else + { + assert( Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) ); + Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); + } + } + } + else if ( Abc_ObjIsBox(pObj) || Abc_ObjIsNet(pObj) ) + Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); + } + // copy functionality/names + if ( Abc_ObjIsNode(pObj) ) // copy the function if functionality is compatible + { + if ( pNtkNew->ntkFunc == pObj->pNtk->ntkFunc ) + { + if ( Abc_NtkIsStrash(pNtkNew) ) + {} + else if ( Abc_NtkHasSop(pNtkNew) || Abc_NtkHasBlifMv(pNtkNew) ) + pObjNew->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkNew->pManFunc, (char *)pObj->pData ); +#ifdef ABC_USE_CUDD + else if ( Abc_NtkHasBdd(pNtkNew) ) + pObjNew->pData = Cudd_bddTransfer((DdManager *)pObj->pNtk->pManFunc, (DdManager *)pNtkNew->pManFunc, (DdNode *)pObj->pData), Cudd_Ref((DdNode *)pObjNew->pData); +#endif + else if ( Abc_NtkHasAig(pNtkNew) ) + pObjNew->pData = Hop_Transfer((Hop_Man_t *)pObj->pNtk->pManFunc, (Hop_Man_t *)pNtkNew->pManFunc, (Hop_Obj_t *)pObj->pData, Abc_ObjFaninNum(pObj)); + else if ( Abc_NtkHasMapping(pNtkNew) ) + pObjNew->pData = pObj->pData, pNtkNew->nBarBufs2 += !pObj->pData; + else assert( 0 ); + } + } + else if ( Abc_ObjIsNet(pObj) ) // copy the name + { + } + else if ( Abc_ObjIsLatch(pObj) ) // copy the reset value + pObjNew->pData = pObj->pData; + pObjNew->fPersist = pObj->fPersist; + // transfer HAIG +// pObjNew->pEquiv = pObj->pEquiv; + // remember the new node in the old node + pObj->pCopy = pObjNew; + return pObjNew; +} + +/**Function************************************************************* + + Synopsis [Duplicates the latch with its input/output terminals.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkDupBox( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pBox, int fCopyName ) +{ + Abc_Obj_t * pTerm, * pBoxNew; + int i; + assert( Abc_ObjIsBox(pBox) ); + // duplicate the box + pBoxNew = Abc_NtkDupObj( pNtkNew, pBox, fCopyName ); + // duplicate the fanins and connect them + Abc_ObjForEachFanin( pBox, pTerm, i ) + Abc_ObjAddFanin( pBoxNew, Abc_NtkDupObj(pNtkNew, pTerm, fCopyName) ); + // duplicate the fanouts and connect them + Abc_ObjForEachFanout( pBox, pTerm, i ) + Abc_ObjAddFanin( Abc_NtkDupObj(pNtkNew, pTerm, fCopyName), pBoxNew ); + return pBoxNew; +} + +/**Function************************************************************* + + Synopsis [Clones the objects in the same network but does not assign its function.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCloneObj( Abc_Obj_t * pObj ) +{ + Abc_Obj_t * pClone, * pFanin; + int i; + pClone = Abc_NtkCreateObj( pObj->pNtk, (Abc_ObjType_t)pObj->Type ); + Abc_ObjForEachFanin( pObj, pFanin, i ) + Abc_ObjAddFanin( pClone, pFanin ); + return pClone; +} + + +/**Function************************************************************* + + Synopsis [Returns the net with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkFindNode( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pObj; + int Num; + // try to find the terminal + Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_PO ); + if ( Num >= 0 ) + return Abc_ObjFanin0( Abc_NtkObj( pNtk, Num ) ); + Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_BI ); + if ( Num >= 0 ) + return Abc_ObjFanin0( Abc_NtkObj( pNtk, Num ) ); + Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_NODE ); + if ( Num >= 0 ) + return Abc_NtkObj( pNtk, Num ); + // find the internal node + if ( pName[0] != 'n' ) + { + printf( "Name \"%s\" is not found among CO or node names (internal names often look as \"n\").\n", pName ); + return NULL; + } + Num = atoi( pName + 1 ); + if ( Num < 0 || Num >= Abc_NtkObjNumMax(pNtk) ) + { + printf( "The node \"%s\" with ID %d is not in the current network.\n", pName, Num ); + return NULL; + } + pObj = Abc_NtkObj( pNtk, Num ); + if ( pObj == NULL ) + { + printf( "The node \"%s\" with ID %d has been removed from the current network.\n", pName, Num ); + return NULL; + } + if ( !Abc_ObjIsNode(pObj) ) + { + printf( "Object with ID %d is not a node.\n", Num ); + return NULL; + } + return pObj; +} + +/**Function************************************************************* + + Synopsis [Returns the net with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkFindNet( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pNet; + int ObjId; + assert( Abc_NtkIsNetlist(pNtk) ); + ObjId = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_NET ); + if ( ObjId == -1 ) + return NULL; + pNet = Abc_NtkObj( pNtk, ObjId ); + return pNet; +} + +/**Function************************************************************* + + Synopsis [Returns CI with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkFindCi( Abc_Ntk_t * pNtk, char * pName ) +{ + int Num; + assert( !Abc_NtkIsNetlist(pNtk) ); + Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_PI ); + if ( Num >= 0 ) + return Abc_NtkObj( pNtk, Num ); + Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_BO ); + if ( Num >= 0 ) + return Abc_NtkObj( pNtk, Num ); + return NULL; +} + +/**Function************************************************************* + + Synopsis [Returns CO with the given name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkFindCo( Abc_Ntk_t * pNtk, char * pName ) +{ + int Num; + assert( !Abc_NtkIsNetlist(pNtk) ); + Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_PO ); + if ( Num >= 0 ) + return Abc_NtkObj( pNtk, Num ); + Num = Nm_ManFindIdByName( pNtk->pManName, pName, ABC_OBJ_BI ); + if ( Num >= 0 ) + return Abc_NtkObj( pNtk, Num ); + return NULL; +} + + +/**Function************************************************************* + + Synopsis [Finds or creates the net.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkFindOrCreateNet( Abc_Ntk_t * pNtk, char * pName ) +{ + Abc_Obj_t * pNet; + assert( Abc_NtkIsNetlist(pNtk) ); + if ( pName && (pNet = Abc_NtkFindNet( pNtk, pName )) ) + return pNet; +//printf( "Creating net %s.\n", pName ); + // create a new net + pNet = Abc_NtkCreateNet( pNtk ); + if ( pName ) + Nm_ManStoreIdName( pNtk->pManName, pNet->Id, pNet->Type, pName, NULL ); + return pNet; +} + +/**Function************************************************************* + + Synopsis [Creates constant 0 node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateNodeConst0( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + pNode = Abc_NtkCreateNode( pNtk ); + if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) ) + pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, " 0\n" ); +#ifdef ABC_USE_CUDD + else if ( Abc_NtkHasBdd(pNtk) ) + pNode->pData = Cudd_ReadLogicZero((DdManager *)pNtk->pManFunc), Cudd_Ref( (DdNode *)pNode->pData ); +#endif + else if ( Abc_NtkHasAig(pNtk) ) + pNode->pData = Hop_ManConst0((Hop_Man_t *)pNtk->pManFunc); + else if ( Abc_NtkHasMapping(pNtk) ) + pNode->pData = Mio_LibraryReadConst0((Mio_Library_t *)Abc_FrameReadLibGen()); + else if ( !Abc_NtkHasBlackbox(pNtk) ) + assert( 0 ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates constant 1 node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateNodeConst1( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + pNode = Abc_NtkCreateNode( pNtk ); + if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) ) + pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, " 1\n" ); +#ifdef ABC_USE_CUDD + else if ( Abc_NtkHasBdd(pNtk) ) + pNode->pData = Cudd_ReadOne((DdManager *)pNtk->pManFunc), Cudd_Ref( (DdNode *)pNode->pData ); +#endif + else if ( Abc_NtkHasAig(pNtk) ) + pNode->pData = Hop_ManConst1((Hop_Man_t *)pNtk->pManFunc); + else if ( Abc_NtkHasMapping(pNtk) ) + pNode->pData = Mio_LibraryReadConst1((Mio_Library_t *)Abc_FrameReadLibGen()); + else if ( !Abc_NtkHasBlackbox(pNtk) ) + assert( 0 ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates inverter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateNodeInv( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ) +{ + Abc_Obj_t * pNode; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + pNode = Abc_NtkCreateNode( pNtk ); + if ( pFanin ) Abc_ObjAddFanin( pNode, pFanin ); + if ( Abc_NtkHasSop(pNtk) ) + pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, "0 1\n" ); +#ifdef ABC_USE_CUDD + else if ( Abc_NtkHasBdd(pNtk) ) + pNode->pData = Cudd_Not(Cudd_bddIthVar((DdManager *)pNtk->pManFunc,0)), Cudd_Ref( (DdNode *)pNode->pData ); +#endif + else if ( Abc_NtkHasAig(pNtk) ) + pNode->pData = Hop_Not(Hop_IthVar((Hop_Man_t *)pNtk->pManFunc,0)); + else if ( Abc_NtkHasMapping(pNtk) ) + pNode->pData = Mio_LibraryReadInv((Mio_Library_t *)Abc_FrameReadLibGen()); + else + assert( 0 ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates buffer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateNodeBuf( Abc_Ntk_t * pNtk, Abc_Obj_t * pFanin ) +{ + Abc_Obj_t * pNode; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + pNode = Abc_NtkCreateNode( pNtk ); + if ( pFanin ) Abc_ObjAddFanin( pNode, pFanin ); + if ( Abc_NtkHasSop(pNtk) ) + pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, "1 1\n" ); +#ifdef ABC_USE_CUDD + else if ( Abc_NtkHasBdd(pNtk) ) + pNode->pData = Cudd_bddIthVar((DdManager *)pNtk->pManFunc,0), Cudd_Ref( (DdNode *)pNode->pData ); +#endif + else if ( Abc_NtkHasAig(pNtk) ) + pNode->pData = Hop_IthVar((Hop_Man_t *)pNtk->pManFunc,0); + else if ( Abc_NtkHasMapping(pNtk) ) + pNode->pData = Mio_LibraryReadBuf((Mio_Library_t *)Abc_FrameReadLibGen()); + else + assert( 0 ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates AND.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateNodeAnd( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) +{ + Abc_Obj_t * pNode; + int i; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + pNode = Abc_NtkCreateNode( pNtk ); + for ( i = 0; i < vFanins->nSize; i++ ) + Abc_ObjAddFanin( pNode, (Abc_Obj_t *)vFanins->pArray[i] ); + if ( Abc_NtkHasSop(pNtk) ) + pNode->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtk->pManFunc, Vec_PtrSize(vFanins), NULL ); +#ifdef ABC_USE_CUDD + else if ( Abc_NtkHasBdd(pNtk) ) + pNode->pData = Extra_bddCreateAnd( (DdManager *)pNtk->pManFunc, Vec_PtrSize(vFanins) ), Cudd_Ref((DdNode *)pNode->pData); +#endif + else if ( Abc_NtkHasAig(pNtk) ) + pNode->pData = Hop_CreateAnd( (Hop_Man_t *)pNtk->pManFunc, Vec_PtrSize(vFanins) ); + else + assert( 0 ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates OR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateNodeOr( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) +{ + Abc_Obj_t * pNode; + int i; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + pNode = Abc_NtkCreateNode( pNtk ); + for ( i = 0; i < vFanins->nSize; i++ ) + Abc_ObjAddFanin( pNode, (Abc_Obj_t *)vFanins->pArray[i] ); + if ( Abc_NtkHasSop(pNtk) ) + pNode->pData = Abc_SopCreateOr( (Mem_Flex_t *)pNtk->pManFunc, Vec_PtrSize(vFanins), NULL ); +#ifdef ABC_USE_CUDD + else if ( Abc_NtkHasBdd(pNtk) ) + pNode->pData = Extra_bddCreateOr( (DdManager *)pNtk->pManFunc, Vec_PtrSize(vFanins) ), Cudd_Ref((DdNode *)pNode->pData); +#endif + else if ( Abc_NtkHasAig(pNtk) ) + pNode->pData = Hop_CreateOr( (Hop_Man_t *)pNtk->pManFunc, Vec_PtrSize(vFanins) ); + else + assert( 0 ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates EXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateNodeExor( Abc_Ntk_t * pNtk, Vec_Ptr_t * vFanins ) +{ + Abc_Obj_t * pNode; + int i; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + pNode = Abc_NtkCreateNode( pNtk ); + for ( i = 0; i < vFanins->nSize; i++ ) + Abc_ObjAddFanin( pNode, (Abc_Obj_t *)vFanins->pArray[i] ); + if ( Abc_NtkHasSop(pNtk) ) + pNode->pData = Abc_SopCreateXorSpecial( (Mem_Flex_t *)pNtk->pManFunc, Vec_PtrSize(vFanins) ); +#ifdef ABC_USE_CUDD + else if ( Abc_NtkHasBdd(pNtk) ) + pNode->pData = Extra_bddCreateExor( (DdManager *)pNtk->pManFunc, Vec_PtrSize(vFanins) ), Cudd_Ref((DdNode *)pNode->pData); +#endif + else if ( Abc_NtkHasAig(pNtk) ) + pNode->pData = Hop_CreateExor( (Hop_Man_t *)pNtk->pManFunc, Vec_PtrSize(vFanins) ); + else + assert( 0 ); + return pNode; +} + +/**Function************************************************************* + + Synopsis [Creates MUX.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkCreateNodeMux( Abc_Ntk_t * pNtk, Abc_Obj_t * pNodeC, Abc_Obj_t * pNode1, Abc_Obj_t * pNode0 ) +{ + Abc_Obj_t * pNode; + assert( Abc_NtkIsLogic(pNtk) ); + pNode = Abc_NtkCreateNode( pNtk ); + Abc_ObjAddFanin( pNode, pNodeC ); + Abc_ObjAddFanin( pNode, pNode1 ); + Abc_ObjAddFanin( pNode, pNode0 ); + if ( Abc_NtkHasSop(pNtk) ) + pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtk->pManFunc, "11- 1\n0-1 1\n" ); +#ifdef ABC_USE_CUDD + else if ( Abc_NtkHasBdd(pNtk) ) + pNode->pData = Cudd_bddIte((DdManager *)pNtk->pManFunc,Cudd_bddIthVar((DdManager *)pNtk->pManFunc,0),Cudd_bddIthVar((DdManager *)pNtk->pManFunc,1),Cudd_bddIthVar((DdManager *)pNtk->pManFunc,2)), Cudd_Ref( (DdNode *)pNode->pData ); +#endif + else if ( Abc_NtkHasAig(pNtk) ) + pNode->pData = Hop_Mux((Hop_Man_t *)pNtk->pManFunc,Hop_IthVar((Hop_Man_t *)pNtk->pManFunc,0),Hop_IthVar((Hop_Man_t *)pNtk->pManFunc,1),Hop_IthVar((Hop_Man_t *)pNtk->pManFunc,2)); + else + assert( 0 ); + return pNode; +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is a constant 0 node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeIsConst( Abc_Obj_t * pNode ) +{ + assert( Abc_NtkIsLogic(pNode->pNtk) || Abc_NtkIsNetlist(pNode->pNtk) ); + return Abc_ObjIsNode(pNode) && Abc_ObjFaninNum(pNode) == 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is a constant 0 node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeIsConst0( Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtk = pNode->pNtk; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + if ( !Abc_NodeIsConst(pNode) ) + return 0; + if ( Abc_NtkHasSop(pNtk) ) + return Abc_SopIsConst0((char *)pNode->pData); +#ifdef ABC_USE_CUDD + if ( Abc_NtkHasBdd(pNtk) ) + return Cudd_IsComplement(pNode->pData); +#endif + if ( Abc_NtkHasAig(pNtk) ) + return Hop_IsComplement((Hop_Obj_t *)pNode->pData)? 1:0; + if ( Abc_NtkHasMapping(pNtk) ) + return pNode->pData == Mio_LibraryReadConst0((Mio_Library_t *)Abc_FrameReadLibGen()); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is a constant 1 node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeIsConst1( Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtk = pNode->pNtk; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + if ( !Abc_NodeIsConst(pNode) ) + return 0; + if ( Abc_NtkHasSop(pNtk) ) + return Abc_SopIsConst1((char *)pNode->pData); +#ifdef ABC_USE_CUDD + if ( Abc_NtkHasBdd(pNtk) ) + return !Cudd_IsComplement(pNode->pData); +#endif + if ( Abc_NtkHasAig(pNtk) ) + return !Hop_IsComplement((Hop_Obj_t *)pNode->pData); + if ( Abc_NtkHasMapping(pNtk) ) + return pNode->pData == Mio_LibraryReadConst1((Mio_Library_t *)Abc_FrameReadLibGen()); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is a buffer.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeIsBuf( Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtk = pNode->pNtk; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + if ( Abc_ObjFaninNum(pNode) != 1 ) + return 0; + if ( Abc_NtkHasSop(pNtk) ) + return Abc_SopIsBuf((char *)pNode->pData); +#ifdef ABC_USE_CUDD + if ( Abc_NtkHasBdd(pNtk) ) + return !Cudd_IsComplement(pNode->pData); +#endif + if ( Abc_NtkHasAig(pNtk) ) + return !Hop_IsComplement((Hop_Obj_t *)pNode->pData); + if ( Abc_NtkHasMapping(pNtk) ) + return pNode->pData == Mio_LibraryReadBuf((Mio_Library_t *)Abc_FrameReadLibGen()); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is an inverter.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeIsInv( Abc_Obj_t * pNode ) +{ + Abc_Ntk_t * pNtk = pNode->pNtk; + assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsNetlist(pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + if ( Abc_ObjFaninNum(pNode) != 1 ) + return 0; + if ( Abc_NtkHasSop(pNtk) ) + return Abc_SopIsInv((char *)pNode->pData); +#ifdef ABC_USE_CUDD + if ( Abc_NtkHasBdd(pNtk) ) + return Cudd_IsComplement(pNode->pData); +#endif + if ( Abc_NtkHasAig(pNtk) ) + return Hop_IsComplement((Hop_Obj_t *)pNode->pData)? 1:0; + if ( Abc_NtkHasMapping(pNtk) ) + return pNode->pData == Mio_LibraryReadInv((Mio_Library_t *)Abc_FrameReadLibGen()); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Complements the local functions of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeComplement( Abc_Obj_t * pNode ) +{ + assert( Abc_NtkIsLogic(pNode->pNtk) || Abc_NtkIsNetlist(pNode->pNtk) ); + assert( Abc_ObjIsNode(pNode) ); + if ( Abc_NtkHasSop(pNode->pNtk) ) + Abc_SopComplement( (char *)pNode->pData ); + else if ( Abc_NtkHasAig(pNode->pNtk) ) + pNode->pData = Hop_Not( (Hop_Obj_t *)pNode->pData ); +#ifdef ABC_USE_CUDD + else if ( Abc_NtkHasBdd(pNode->pNtk) ) + pNode->pData = Cudd_Not( pNode->pData ); +#endif + else + assert( 0 ); +} + +/**Function************************************************************* + + Synopsis [Changes the polarity of one fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin ) +{ + int iFanin; + if ( (iFanin = Vec_IntFind( &pNode->vFanins, pFanin->Id )) == -1 ) + { + printf( "Node %s should be among", Abc_ObjName(pFanin) ); + printf( " the fanins of node %s...\n", Abc_ObjName(pNode) ); + return; + } + if ( Abc_NtkHasSop(pNode->pNtk) ) + Abc_SopComplementVar( (char *)pNode->pData, iFanin ); + else if ( Abc_NtkHasAig(pNode->pNtk) ) + pNode->pData = Hop_Complement( (Hop_Man_t *)pNode->pNtk->pManFunc, (Hop_Obj_t *)pNode->pData, iFanin ); +#ifdef ABC_USE_CUDD + else if ( Abc_NtkHasBdd(pNode->pNtk) ) + { + DdManager * dd = (DdManager *)pNode->pNtk->pManFunc; + DdNode * bVar, * bCof0, * bCof1; + bVar = Cudd_bddIthVar( dd, iFanin ); + bCof0 = Cudd_Cofactor( dd, (DdNode *)pNode->pData, Cudd_Not(bVar) ); Cudd_Ref( bCof0 ); + bCof1 = Cudd_Cofactor( dd, (DdNode *)pNode->pData, bVar ); Cudd_Ref( bCof1 ); + Cudd_RecursiveDeref( dd, (DdNode *)pNode->pData ); + pNode->pData = Cudd_bddIte( dd, bVar, bCof0, bCof1 ); Cudd_Ref( (DdNode *)pNode->pData ); + Cudd_RecursiveDeref( dd, bCof0 ); + Cudd_RecursiveDeref( dd, bCof1 ); + } +#endif + else + assert( 0 ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/abcRefs.c b/yosys/abc/src/base/abc/abcRefs.c new file mode 100644 index 00000000000..4c5600c636c --- /dev/null +++ b/yosys/abc/src/base/abc/abcRefs.c @@ -0,0 +1,459 @@ +/**CFile**************************************************************** + + FileName [abcRefs.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Procedures using reference counting of the AIG nodes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcRefs.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +static int Abc_NodeRefDeref( Abc_Obj_t * pNode, int fReference, int fLabel ); +static int Abc_NodeRefDerefStop( Abc_Obj_t * pNode, int fReference ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Returns the MFFC size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeMffcSize( Abc_Obj_t * pNode ) +{ + int nConeSize1, nConeSize2; +// assert( Abc_NtkIsStrash(pNode->pNtk) ); +// assert( !Abc_ObjIsComplement( pNode ) ); + assert( Abc_ObjIsNode( pNode ) ); + if ( Abc_ObjFaninNum(pNode) == 0 ) + return 0; + nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0 ); // dereference + nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0 ); // reference + assert( nConeSize1 == nConeSize2 ); + assert( nConeSize1 > 0 ); + return nConeSize1; +} + +/**Function************************************************************* + + Synopsis [Returns the MFFC size while stopping at the complemented edges.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeMffcSizeStop( Abc_Obj_t * pNode ) +{ + int nConeSize1, nConeSize2; + assert( Abc_NtkIsStrash(pNode->pNtk) ); + assert( !Abc_ObjIsComplement( pNode ) ); + assert( Abc_ObjIsNode( pNode ) ); + if ( Abc_ObjFaninNum(pNode) == 0 ) + return 0; + nConeSize1 = Abc_NodeRefDerefStop( pNode, 0 ); // dereference + nConeSize2 = Abc_NodeRefDerefStop( pNode, 1 ); // reference + assert( nConeSize1 == nConeSize2 ); + assert( nConeSize1 > 0 ); + return nConeSize1; +} + +/**Function************************************************************* + + Synopsis [Labels MFFC with the current traversal ID.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeMffcLabelAig( Abc_Obj_t * pNode ) +{ + int nConeSize1, nConeSize2; + assert( Abc_NtkIsStrash(pNode->pNtk) ); + assert( !Abc_ObjIsComplement( pNode ) ); + assert( Abc_ObjIsNode( pNode ) ); + if ( Abc_ObjFaninNum(pNode) == 0 ) + return 0; + nConeSize1 = Abc_NodeRefDeref( pNode, 0, 1 ); // dereference + nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0 ); // reference + assert( nConeSize1 == nConeSize2 ); + assert( nConeSize1 > 0 ); + return nConeSize1; +} + +/**Function************************************************************* + + Synopsis [References/references the node and returns MFFC size.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeRefDeref( Abc_Obj_t * pNode, int fReference, int fLabel ) +{ + Abc_Obj_t * pNode0, * pNode1; + int Counter; + // label visited nodes + if ( fLabel ) + Abc_NodeSetTravIdCurrent( pNode ); + // skip the CI + if ( Abc_ObjIsCi(pNode) ) + return 0; + // process the internal node + pNode0 = Abc_ObjFanin0(pNode); + pNode1 = Abc_ObjFanin1(pNode); + Counter = 1; + if ( fReference ) + { + if ( pNode0->vFanouts.nSize++ == 0 ) + Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel ); + if ( pNode1->vFanouts.nSize++ == 0 ) + Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel ); + } + else + { + assert( pNode0->vFanouts.nSize > 0 ); + assert( pNode1->vFanouts.nSize > 0 ); + if ( --pNode0->vFanouts.nSize == 0 ) + Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel ); + if ( --pNode1->vFanouts.nSize == 0 ) + Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel ); + } + return Counter; +} + + +/**Function************************************************************* + + Synopsis [References/references the node and returns MFFC size.] + + Description [Stops at the complemented edges.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeRefDerefStop( Abc_Obj_t * pNode, int fReference ) +{ + Abc_Obj_t * pNode0, * pNode1; + int Counter; + // skip the CI + if ( Abc_ObjIsCi(pNode) ) + return 0; + // process the internal node + pNode0 = Abc_ObjFanin0(pNode); + pNode1 = Abc_ObjFanin1(pNode); + Counter = 1; + if ( fReference ) + { + if ( !Abc_ObjFaninC0(pNode) && pNode0->vFanouts.nSize++ == 0 ) + Counter += Abc_NodeRefDerefStop( pNode0, fReference ); + if ( !Abc_ObjFaninC1(pNode) && pNode1->vFanouts.nSize++ == 0 ) + Counter += Abc_NodeRefDerefStop( pNode1, fReference ); + } + else + { + assert( pNode0->vFanouts.nSize > 0 ); + assert( pNode1->vFanouts.nSize > 0 ); + if ( !Abc_ObjFaninC0(pNode) && --pNode0->vFanouts.nSize == 0 ) + Counter += Abc_NodeRefDerefStop( pNode0, fReference ); + if ( !Abc_ObjFaninC1(pNode) && --pNode1->vFanouts.nSize == 0 ) + Counter += Abc_NodeRefDerefStop( pNode1, fReference ); + } + return Counter; +} + + + + +/**Function************************************************************* + + Synopsis [Dereferences the node's MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeDeref_rec( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + int i, Counter = 1; + if ( Abc_ObjIsCi(pNode) ) + return 0; + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + assert( pFanin->vFanouts.nSize > 0 ); + if ( --pFanin->vFanouts.nSize == 0 ) + Counter += Abc_NodeDeref_rec( pFanin ); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [References the node's MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeRef_rec( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanin; + int i, Counter = 1; + if ( Abc_ObjIsCi(pNode) ) + return 0; + Abc_ObjForEachFanin( pNode, pFanin, i ) + { + if ( pFanin->vFanouts.nSize++ == 0 ) + Counter += Abc_NodeRef_rec( pFanin ); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Collects the internal and boundary nodes in the derefed MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeMffcConeSupp_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp, int fTopmost ) +{ + Abc_Obj_t * pFanin; + int i; + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pNode) ) + return; + Abc_NodeSetTravIdCurrent(pNode); + // add to the new support nodes + if ( !fTopmost && (Abc_ObjIsCi(pNode) || pNode->vFanouts.nSize > 0) ) + { + if ( vSupp ) Vec_PtrPush( vSupp, pNode ); + return; + } + // recur on the children + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_NodeMffcConeSupp_rec( pFanin, vCone, vSupp, 0 ); + // collect the internal node + if ( vCone ) Vec_PtrPush( vCone, pNode ); +// printf( "%d ", pNode->Id ); +} + +/**Function************************************************************* + + Synopsis [Collects the support of the derefed MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeMffcConeSupp( Abc_Obj_t * pNode, Vec_Ptr_t * vCone, Vec_Ptr_t * vSupp ) +{ + assert( Abc_ObjIsNode(pNode) ); + assert( !Abc_ObjIsComplement(pNode) ); + if ( vCone ) Vec_PtrClear( vCone ); + if ( vSupp ) Vec_PtrClear( vSupp ); + Abc_NtkIncrementTravId( pNode->pNtk ); + Abc_NodeMffcConeSupp_rec( pNode, vCone, vSupp, 1 ); +// printf( "\n" ); +} + +/**Function************************************************************* + + Synopsis [Collects the support of the derefed MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeMffcConeSuppPrint( Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vCone, * vSupp; + Abc_Obj_t * pObj; + int i; + vCone = Vec_PtrAlloc( 100 ); + vSupp = Vec_PtrAlloc( 100 ); + Abc_NodeDeref_rec( pNode ); + Abc_NodeMffcConeSupp( pNode, vCone, vSupp ); + Abc_NodeRef_rec( pNode ); + printf( "Node = %6s : Supp = %3d Cone = %3d (", + Abc_ObjName(pNode), Vec_PtrSize(vSupp), Vec_PtrSize(vCone) ); + Vec_PtrForEachEntry( Abc_Obj_t *, vCone, pObj, i ) + printf( " %s", Abc_ObjName(pObj) ); + printf( " )\n" ); + Vec_PtrFree( vCone ); + Vec_PtrFree( vSupp ); +} + +/**Function************************************************************* + + Synopsis [Collects the internal nodes of the MFFC limited by cut.] + + Description [] + + SideEffects [Increments the trav ID and marks visited nodes.] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeMffcInside( Abc_Obj_t * pNode, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vInside ) +{ + Abc_Obj_t * pObj; + int i, Count1, Count2; + // increment the fanout counters for the leaves + Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i ) + pObj->vFanouts.nSize++; + // dereference the node + Count1 = Abc_NodeDeref_rec( pNode ); + // collect the nodes inside the MFFC + Abc_NodeMffcConeSupp( pNode, vInside, NULL ); + // reference it back + Count2 = Abc_NodeRef_rec( pNode ); + assert( Count1 == Count2 ); + // remove the extra counters + Vec_PtrForEachEntry( Abc_Obj_t *, vLeaves, pObj, i ) + pObj->vFanouts.nSize--; + return Count1; +} + +/**Function************************************************************* + + Synopsis [Collects the internal nodes of the MFFC limited by cut.] + + Description [] + + SideEffects [Increments the trav ID and marks visited nodes.] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NodeMffcInsideCollect( Abc_Obj_t * pNode ) +{ + Vec_Ptr_t * vInside; + int Count1, Count2; + // dereference the node + Count1 = Abc_NodeDeref_rec( pNode ); + // collect the nodes inside the MFFC + vInside = Vec_PtrAlloc( 10 ); + Abc_NodeMffcConeSupp( pNode, vInside, NULL ); + // reference it back + Count2 = Abc_NodeRef_rec( pNode ); + assert( Count1 == Count2 ); + return vInside; +} + +/**Function************************************************************* + + Synopsis [Collects the internal and boundary nodes in the derefed MFFC.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeMffcLabel_rec( Abc_Obj_t * pNode, int fTopmost, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanin; + int i; + // add to the new support nodes + if ( !fTopmost && (Abc_ObjIsCi(pNode) || pNode->vFanouts.nSize > 0) ) + return; + // skip visited nodes + if ( Abc_NodeIsTravIdCurrent(pNode) ) + return; + Abc_NodeSetTravIdCurrent(pNode); + // recur on the children + Abc_ObjForEachFanin( pNode, pFanin, i ) + Abc_NodeMffcLabel_rec( pFanin, 0, vNodes ); + // collect the internal node +// printf( "%d ", pNode->Id ); + if ( vNodes ) + Vec_PtrPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Collects the internal nodes of the MFFC limited by cut.] + + Description [] + + SideEffects [Increments the trav ID and marks visited nodes.] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeMffcLabel( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + int Count1, Count2; + // dereference the node + Count1 = Abc_NodeDeref_rec( pNode ); + // collect the nodes inside the MFFC + Abc_NtkIncrementTravId( pNode->pNtk ); + Abc_NodeMffcLabel_rec( pNode, 1, vNodes ); + // reference it back + Count2 = Abc_NodeRef_rec( pNode ); + assert( Count1 == Count2 ); + return Count1; +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/abcShow.c b/yosys/abc/src/base/abc/abcShow.c new file mode 100644 index 00000000000..cdd53fc20c3 --- /dev/null +++ b/yosys/abc/src/base/abc/abcShow.c @@ -0,0 +1,537 @@ +/**CFile**************************************************************** + + FileName [abcShow.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Visualization procedures using DOT software and GSView.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcShow.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#ifdef WIN32 +#include +#else +#include +#endif + + +#include "abc.h" +#include "base/main/main.h" +#include "base/io/ioAbc.h" + +#ifdef ABC_USE_CUDD +#include "bdd/extrab/extraBdd.h" +#endif + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +extern void Abc_ShowFile( char * FileNameDot, int fKeepDot ); +static void Abc_ShowGetFileName( char * pName, char * pBuffer ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +#ifdef ABC_USE_CUDD + +/**Function************************************************************* + + Synopsis [Visualizes BDD of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeShowBddOne( DdManager * dd, DdNode * bFunc ) +{ + char * FileNameDot = "temp.dot"; + FILE * pFile; + if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); + return; + } + Cudd_DumpDot( dd, 1, (DdNode **)&bFunc, NULL, NULL, pFile ); + fclose( pFile ); + Abc_ShowFile( FileNameDot, 0 ); +} + +/**Function************************************************************* + + Synopsis [Visualizes BDD of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeShowBdd( Abc_Obj_t * pNode, int fCompl ) +{ + FILE * pFile; + Vec_Ptr_t * vNamesIn; + char FileNameDot[200]; + char * pNameOut; + DdManager * dd = (DdManager *)pNode->pNtk->pManFunc; + + assert( Abc_NtkIsBddLogic(pNode->pNtk) ); + // create the file name + Abc_ShowGetFileName( Abc_ObjName(pNode), FileNameDot ); + // check that the file can be opened + if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); + return; + } + + // set the node names + vNamesIn = Abc_NodeGetFaninNames( pNode ); + pNameOut = Abc_ObjName(pNode); + if ( fCompl ) + Cudd_DumpDot( dd, 1, (DdNode **)&pNode->pData, (char **)vNamesIn->pArray, &pNameOut, pFile ); + else + { + DdNode * bAdd = Cudd_BddToAdd( dd, (DdNode *)pNode->pData ); Cudd_Ref( bAdd ); + Cudd_DumpDot( dd, 1, (DdNode **)&bAdd, (char **)vNamesIn->pArray, &pNameOut, pFile ); + Cudd_RecursiveDeref( dd, bAdd ); + } + Abc_NodeFreeNames( vNamesIn ); + Abc_NtkCleanCopy( pNode->pNtk ); + fclose( pFile ); + + // visualize the file + Abc_ShowFile( FileNameDot, 0 ); +} +void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl, int fReorder ) +{ + char FileNameDot[200]; + char ** ppNamesIn, ** ppNamesOut; + DdManager * dd; DdNode * bFunc; + Vec_Ptr_t * vFuncsGlob; + Abc_Obj_t * pObj; int i; + FILE * pFile; + + assert( Abc_NtkIsStrash(pNtk) ); + dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, fReorder, 0, 0 ); + if ( dd == NULL ) + { + printf( "Construction of global BDDs has failed.\n" ); + return; + } + //printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) ); + + // complement the global functions + vFuncsGlob = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + Vec_PtrPush( vFuncsGlob, Abc_ObjGlobalBdd(pObj) ); + + // create the file name + Abc_ShowGetFileName( pNtk->pName, FileNameDot ); + // check that the file can be opened + if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); + return; + } + + // set the node names + ppNamesIn = Abc_NtkCollectCioNames( pNtk, 0 ); + ppNamesOut = Abc_NtkCollectCioNames( pNtk, 1 ); + if ( fCompl ) + Cudd_DumpDot( dd, Abc_NtkCoNum(pNtk), (DdNode **)Vec_PtrArray(vFuncsGlob), ppNamesIn, ppNamesOut, pFile ); + else + { + DdNode ** pbAdds = ABC_ALLOC( DdNode *, Vec_PtrSize(vFuncsGlob) ); + Vec_PtrForEachEntry( DdNode *, vFuncsGlob, bFunc, i ) + { pbAdds[i] = Cudd_BddToAdd( dd, bFunc ); Cudd_Ref( pbAdds[i] ); } + Cudd_DumpDot( dd, Abc_NtkCoNum(pNtk), pbAdds, ppNamesIn, ppNamesOut, pFile ); + Vec_PtrForEachEntry( DdNode *, vFuncsGlob, bFunc, i ) + Cudd_RecursiveDeref( dd, pbAdds[i] ); + ABC_FREE( pbAdds ); + } + ABC_FREE( ppNamesIn ); + ABC_FREE( ppNamesOut ); + fclose( pFile ); + + // cleanup + Abc_NtkFreeGlobalBdds( pNtk, 0 ); + Vec_PtrForEachEntry( DdNode *, vFuncsGlob, bFunc, i ) + Cudd_RecursiveDeref( dd, bFunc ); + Vec_PtrFree( vFuncsGlob ); + Extra_StopManager( dd ); + Abc_NtkCleanCopy( pNtk ); + + // visualize the file + Abc_ShowFile( FileNameDot, 0 ); +} + +#else +void Abc_NodeShowBdd( Abc_Obj_t * pNode, int fCompl ) {} +void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl, int fReorder ) {} +#endif + +/**Function************************************************************* + + Synopsis [Visualizes a reconvergence driven cut at the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax ) +{ + FILE * pFile; + char FileNameDot[200]; + Abc_ManCut_t * p; + Vec_Ptr_t * vCutSmall; + Vec_Ptr_t * vCutLarge; + Vec_Ptr_t * vInside; + Vec_Ptr_t * vNodesTfo; + Abc_Obj_t * pTemp; + int i; + + assert( Abc_NtkIsStrash(pNode->pNtk) ); + + // start the cut computation manager + p = Abc_NtkManCutStart( nNodeSizeMax, nConeSizeMax, 2, ABC_INFINITY ); + // get the recovergence driven cut + vCutSmall = Abc_NodeFindCut( p, pNode, 1 ); + // get the containing cut + vCutLarge = Abc_NtkManCutReadCutLarge( p ); + // get the array for the inside nodes + vInside = Abc_NtkManCutReadVisited( p ); + // get the inside nodes of the containing cone + Abc_NodeConeCollect( &pNode, 1, vCutLarge, vInside, 1 ); + + // add the nodes in the TFO + vNodesTfo = Abc_NodeCollectTfoCands( p, pNode, vCutSmall, ABC_INFINITY ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodesTfo, pTemp, i ) + Vec_PtrPushUnique( vInside, pTemp ); + + // create the file name + Abc_ShowGetFileName( Abc_ObjName(pNode), FileNameDot ); + // check that the file can be opened + if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); + return; + } + // add the root node to the cone (for visualization) + Vec_PtrPush( vCutSmall, pNode ); + // write the DOT file + Io_WriteDotNtk( pNode->pNtk, vInside, vCutSmall, FileNameDot, 0, 0, 0 ); + // stop the cut computation manager + Abc_NtkManCutStop( p ); + + // visualize the file + Abc_ShowFile( FileNameDot, 0 ); +} + +/**Function************************************************************* + + Synopsis [Visualizes AIG with choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkShow( Abc_Ntk_t * pNtk0, int fGateNames, int fSeq, int fUseReverse, int fKeepDot, int fAigIds ) +{ + FILE * pFile; + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + Vec_Ptr_t * vNodes; + int nBarBufs; + char FileNameDot[200]; + int i; + + assert( Abc_NtkIsStrash(pNtk0) || Abc_NtkIsLogic(pNtk0) ); + if ( Abc_NtkIsStrash(pNtk0) && Abc_NtkGetChoiceNum(pNtk0) ) + { + printf( "Temporarily visualization of AIGs with choice nodes is disabled.\n" ); + return; + } + // create the file name + Abc_ShowGetFileName( pNtk0->pName, FileNameDot ); + // check that the file can be opened + if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); + return; + } + fclose( pFile ); + + + // convert to logic SOP + pNtk = Abc_NtkDup( pNtk0 ); + if ( Abc_NtkIsLogic(pNtk) && !Abc_NtkHasMapping(pNtk) ) + Abc_NtkToSop( pNtk, -1, ABC_INFINITY ); + + // collect all nodes in the network + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachObj( pNtk, pNode, i ) + Vec_PtrPush( vNodes, pNode ); + // write the DOT file + nBarBufs = pNtk->nBarBufs; + pNtk->nBarBufs = 0; + if ( fSeq ) + Io_WriteDotSeq( pNtk, vNodes, NULL, FileNameDot, fGateNames, fUseReverse ); + else + Io_WriteDotNtk( pNtk, vNodes, NULL, FileNameDot, fGateNames, fUseReverse, fAigIds ); + pNtk->nBarBufs = nBarBufs; + Vec_PtrFree( vNodes ); + + // visualize the file + Abc_ShowFile( FileNameDot, fKeepDot ); + Abc_NtkDelete( pNtk ); +} + + +/**Function************************************************************* + + Synopsis [Shows the given DOT file.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ShowFile( char * FileNameDot, int fKeepDot ) +{ + FILE * pFile; + char * FileGeneric; + char FileNamePs[200]; + char CommandDot[1000]; + char * pDotName; + char * pDotNameWin = "dot.exe"; + char * pDotNameUnix = "dot"; + char * pGsNameWin = "gsview32.exe"; + char * pGsNameUnix = "gv"; + int RetValue; + + // get DOT names from the resource file + if ( Abc_FrameReadFlag("dotwin") ) + pDotNameWin = Abc_FrameReadFlag("dotwin"); + if ( Abc_FrameReadFlag("dotunix") ) + pDotNameUnix = Abc_FrameReadFlag("dotunix"); + +#ifdef WIN32 + pDotName = pDotNameWin; +#else + pDotName = pDotNameUnix; +#endif + + // check if the input DOT file is okay + if ( (pFile = fopen( FileNameDot, "r" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); + return; + } + fclose( pFile ); + + // create the PostScript file name + FileGeneric = Extra_FileNameGeneric( FileNameDot ); + sprintf( FileNamePs, "%s.ps", FileGeneric ); + ABC_FREE( FileGeneric ); + + // generate the PostScript file using DOT + sprintf( CommandDot, "%s -Tps -o %s %s", pDotName, FileNamePs, FileNameDot ); +#if defined(__wasm) + RetValue = -1; +#else + RetValue = system( CommandDot ); +#endif + if ( RetValue == -1 ) + { + fprintf( stdout, "Command \"%s\" did not succeed.\n", CommandDot ); + return; + } + // check that the input PostScript file is okay + if ( (pFile = fopen( FileNamePs, "r" )) == NULL ) + { + fprintf( stdout, "Cannot open intermediate file \"%s\".\n", FileNamePs ); + return; + } + fclose( pFile ); + + + // get GSVIEW names from the resource file + if ( Abc_FrameReadFlag("gsviewwin") ) + pGsNameWin = Abc_FrameReadFlag("gsviewwin"); + if ( Abc_FrameReadFlag("gsviewunix") ) + pGsNameUnix = Abc_FrameReadFlag("gsviewunix"); + + // spawn the viewer +#ifdef WIN32 + if ( !fKeepDot ) _unlink( FileNameDot ); + if ( _spawnl( _P_NOWAIT, pGsNameWin, pGsNameWin, FileNamePs, NULL ) == -1 ) + if ( _spawnl( _P_NOWAIT, "C:\\Program Files\\Ghostgum\\gsview\\gsview32.exe", + "C:\\Program Files\\Ghostgum\\gsview\\gsview32.exe", FileNamePs, NULL ) == -1 ) + if ( _spawnl( _P_NOWAIT, "C:\\Program Files\\Ghostgum\\gsview\\gsview64.exe", + "C:\\Program Files\\Ghostgum\\gsview\\gsview64.exe", FileNamePs, NULL ) == -1 ) + { + fprintf( stdout, "Cannot find \"%s\".\n", pGsNameWin ); + return; + } +#else + { + char CommandPs[1000]; + if ( !fKeepDot ) unlink( FileNameDot ); + sprintf( CommandPs, "%s %s &", pGsNameUnix, FileNamePs ); +#if defined(__wasm) + if ( 1 ) +#else + if ( system( CommandPs ) == -1 ) +#endif + { + fprintf( stdout, "Cannot execute \"%s\".\n", CommandPs ); + return; + } + } +#endif +} + +/**Function************************************************************* + + Synopsis [Derives the DOT file name.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_ShowGetFileName( char * pName, char * pBuffer ) +{ + char * pCur; + // creat the file name + sprintf( pBuffer, "%s.dot", pName ); + // get rid of not-alpha-numeric characters + for ( pCur = pBuffer; *pCur; pCur++ ) + if ( !((*pCur >= '0' && *pCur <= '9') || (*pCur >= 'a' && *pCur <= 'z') || + (*pCur >= 'A' && *pCur <= 'Z') || (*pCur == '.')) ) + *pCur = '_'; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkWriteFlopDependency( Abc_Ntk_t * pNtk, char * pFileName ) +{ + FILE * pFile; + Vec_Ptr_t * vSupp; + Abc_Obj_t * pObj, * pTemp; + int i, k, Count; + pFile = fopen( pFileName, "w" ); + if ( pFile == NULL ) + { + printf( "Cannot open input file %s.\n", pFileName ); + return; + } + fprintf( pFile, "# Flop dependency for \"%s\" generated by ABC on %s\n", Abc_NtkName(pNtk), Extra_TimeStamp() ); + fprintf( pFile, "digraph G {\n" ); + fprintf( pFile, " graph [splines=true overlap=false];\n" ); + fprintf( pFile, " size = \"7.5,10\";\n" ); + fprintf( pFile, " center = true;\n" ); +// fprintf( pFile, " edge [len=3,dir=forward];\n" ); + fprintf( pFile, " edge [dir=forward];\n" ); + Abc_NtkForEachLatchInput( pNtk, pObj, i ) + { + Abc_ObjFanout0( Abc_ObjFanout0(pObj) )->iTemp = i; + vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); + Count = 0; + Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pTemp, k ) + Count += Abc_ObjIsPi(pTemp); + Vec_PtrFree( vSupp ); + fprintf( pFile, " { rank = same; %d [label=\"%d(%d)\"]; }\n", i, i, Count ); + } + Abc_NtkForEachLatchInput( pNtk, pObj, i ) + { + vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); + Count = 0; + Vec_PtrForEachEntry( Abc_Obj_t *, vSupp, pTemp, k ) + if ( !Abc_ObjIsPi(pTemp) ) + fprintf( pFile, " %4d -> %4d\n", pTemp->iTemp, i ); + Vec_PtrFree( vSupp ); + } + fprintf( pFile, "}\n" ); + fclose( pFile ); +} + + +/**Function************************************************************* + + Synopsis [Visualizes AIG with choices.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkShowFlopDependency( Abc_Ntk_t * pNtk ) +{ + FILE * pFile; + char FileNameDot[200]; + assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); + // create the file name + Abc_ShowGetFileName( pNtk->pName, FileNameDot ); + // check that the file can be opened + if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) + { + fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); + return; + } + fclose( pFile ); + // write the DOT file + Abc_NtkWriteFlopDependency( pNtk, FileNameDot ); + // visualize the file + Abc_ShowFile( FileNameDot, 0 ); +} + + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/abcSop.c b/yosys/abc/src/base/abc/abcSop.c new file mode 100644 index 00000000000..adc1639a6e2 --- /dev/null +++ b/yosys/abc/src/base/abc/abcSop.c @@ -0,0 +1,1471 @@ +/**CFile**************************************************************** + + FileName [abcSop.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Implementation of a simple SOP representation of nodes.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcSop.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "bool/kit/kit.h" + +#ifdef _MSC_VER +# include +# define __builtin_popcount __popcnt +#endif + +ABC_NAMESPACE_IMPL_START + + +/* + The SOPs in this package are represented using char * strings. + For example, the SOP of the node: + + .names c d0 d1 MUX + 01- 1 + 1-1 1 + + is the string: "01- 1\n1-1 1\n" where '\n' is a single char. +*/ + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Registers the cube string with the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopRegister( Mem_Flex_t * pMan, const char * pName ) +{ + char * pRegName; + if ( pName == NULL ) return NULL; + pRegName = Mem_FlexEntryFetch( pMan, strlen(pName) + 1 ); + strcpy( pRegName, pName ); + return pRegName; +} + +/**Function************************************************************* + + Synopsis [Creates the constant 1 cover with the given number of variables and cubes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopStart( Mem_Flex_t * pMan, int nCubes, int nVars ) +{ + char * pSopCover, * pCube; + int i, Length; + + Length = nCubes * (nVars + 3); + pSopCover = Mem_FlexEntryFetch( pMan, Length + 1 ); + memset( pSopCover, '-', (size_t)Length ); + pSopCover[Length] = 0; + + for ( i = 0; i < nCubes; i++ ) + { + pCube = pSopCover + i * (nVars + 3); + pCube[nVars + 0] = ' '; + pCube[nVars + 1] = '1'; + pCube[nVars + 2] = '\n'; + } + return pSopCover; +} + +/**Function************************************************************* + + Synopsis [Creates the constant 1 cover with 0 variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateConst1( Mem_Flex_t * pMan ) +{ + return Abc_SopRegister( pMan, " 1\n" ); +} + +/**Function************************************************************* + + Synopsis [Creates the constant 1 cover with 0 variables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateConst0( Mem_Flex_t * pMan ) +{ + return Abc_SopRegister( pMan, " 0\n" ); +} + +/**Function************************************************************* + + Synopsis [Creates the AND2 cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateAnd2( Mem_Flex_t * pMan, int fCompl0, int fCompl1 ) +{ + char Buffer[6]; + Buffer[0] = '1' - fCompl0; + Buffer[1] = '1' - fCompl1; + Buffer[2] = ' '; + Buffer[3] = '1'; + Buffer[4] = '\n'; + Buffer[5] = 0; + return Abc_SopRegister( pMan, Buffer ); +} + +/**Function************************************************************* + + Synopsis [Creates the multi-input AND cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateAnd( Mem_Flex_t * pMan, int nVars, int * pfCompl ) +{ + char * pSop; + int i; + pSop = Abc_SopStart( pMan, 1, nVars ); + for ( i = 0; i < nVars; i++ ) + pSop[i] = '1' - (pfCompl? pfCompl[i] : 0); + pSop[nVars + 1] = '1'; + return pSop; +} + +/**Function************************************************************* + + Synopsis [Creates the multi-input NAND cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateNand( Mem_Flex_t * pMan, int nVars ) +{ + char * pSop; + int i; + pSop = Abc_SopStart( pMan, 1, nVars ); + for ( i = 0; i < nVars; i++ ) + pSop[i] = '1'; + pSop[nVars + 1] = '0'; + return pSop; +} + +/**Function************************************************************* + + Synopsis [Creates the multi-input OR cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateOr( Mem_Flex_t * pMan, int nVars, int * pfCompl ) +{ + char * pSop; + int i; + pSop = Abc_SopStart( pMan, 1, nVars ); + for ( i = 0; i < nVars; i++ ) + pSop[i] = '0' + (pfCompl? pfCompl[i] : 0); + pSop[nVars + 1] = '0'; + return pSop; +} + +/**Function************************************************************* + + Synopsis [Creates the multi-input OR cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateOrMultiCube( Mem_Flex_t * pMan, int nVars, int * pfCompl ) +{ + char * pSop, * pCube; + int i; + pSop = Abc_SopStart( pMan, nVars, nVars ); + i = 0; + Abc_SopForEachCube( pSop, nVars, pCube ) + { + pCube[i] = '1' - (pfCompl? pfCompl[i] : 0); + i++; + } + return pSop; +} + +/**Function************************************************************* + + Synopsis [Creates the multi-input NOR cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateNor( Mem_Flex_t * pMan, int nVars ) +{ + char * pSop; + int i; + pSop = Abc_SopStart( pMan, 1, nVars ); + for ( i = 0; i < nVars; i++ ) + pSop[i] = '0'; + return pSop; +} + +/**Function************************************************************* + + Synopsis [Creates the multi-input XOR cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateXor( Mem_Flex_t * pMan, int nVars ) +{ + assert( nVars == 2 ); + return Abc_SopRegister(pMan, "01 1\n10 1\n"); +} + +/**Function************************************************************* + + Synopsis [Creates the multi-input XOR cover (special case).] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateXorSpecial( Mem_Flex_t * pMan, int nVars ) +{ + char * pSop; + pSop = Abc_SopCreateAnd( pMan, nVars, NULL ); + pSop[nVars+1] = 'x'; + assert( pSop[nVars+2] == '\n' ); + return pSop; +} + +/**Function************************************************************* + + Synopsis [Creates the multi-input XNOR cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateNxor( Mem_Flex_t * pMan, int nVars ) +{ + assert( nVars == 2 ); + return Abc_SopRegister(pMan, "11 1\n00 1\n"); +} + +/**Function************************************************************* + + Synopsis [Creates the MUX cover.] + + Description [The first input of MUX is the control. The second input + is DATA1. The third input is DATA0.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateMux( Mem_Flex_t * pMan ) +{ + return Abc_SopRegister(pMan, "11- 1\n0-1 1\n"); +} + +/**Function************************************************************* + + Synopsis [Creates the inv cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateInv( Mem_Flex_t * pMan ) +{ + return Abc_SopRegister(pMan, "0 1\n"); +} + +/**Function************************************************************* + + Synopsis [Creates the buf cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateBuf( Mem_Flex_t * pMan ) +{ + return Abc_SopRegister(pMan, "1 1\n"); +} + +/**Function************************************************************* + + Synopsis [Creates the arbitrary cover from the truth table.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateFromTruth( Mem_Flex_t * pMan, int nVars, unsigned * pTruth ) +{ + char * pSop, * pCube; + int nMints, Counter, i, k; + if ( nVars == 0 ) + return pTruth[0] ? Abc_SopCreateConst1(pMan) : Abc_SopCreateConst0(pMan); + // count the number of true minterms + Counter = 0; + nMints = (1 << nVars); + for ( i = 0; i < nMints; i++ ) + Counter += ((pTruth[i>>5] & (1 << (i&31))) > 0); + // SOP is not well-defined if the truth table is constant 0 + assert( Counter > 0 ); + if ( Counter == 0 ) + return NULL; + // start the cover + pSop = Abc_SopStart( pMan, Counter, nVars ); + // create true minterms + Counter = 0; + for ( i = 0; i < nMints; i++ ) + if ( (pTruth[i>>5] & (1 << (i&31))) > 0 ) + { + pCube = pSop + Counter * (nVars + 3); + for ( k = 0; k < nVars; k++ ) + pCube[k] = '0' + ((i & (1 << k)) > 0); + Counter++; + } + return pSop; +} + +/**Function************************************************************* + + Synopsis [Creates the cover from the ISOP computed from TT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateFromIsop( Mem_Flex_t * pMan, int nVars, Vec_Int_t * vCover ) +{ + char * pSop, * pCube; + int i, k, Entry, Literal; + assert( Vec_IntSize(vCover) > 0 ); + if ( Vec_IntSize(vCover) == 0 ) + return NULL; + // start the cover + pSop = Abc_SopStart( pMan, Vec_IntSize(vCover), nVars ); + // create cubes + Vec_IntForEachEntry( vCover, Entry, i ) + { + pCube = pSop + i * (nVars + 3); + for ( k = 0; k < nVars; k++ ) + { + Literal = 3 & (Entry >> (k << 1)); + if ( Literal == 1 ) + pCube[k] = '0'; + else if ( Literal == 2 ) + pCube[k] = '1'; + else if ( Literal != 0 ) + assert( 0 ); + } + } + return pSop; +} + +/**Function************************************************************* + + Synopsis [Creates the cover from the ISOP computed from TT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopCreateFromTruthIsop( Mem_Flex_t * pMan, int nVars, word * pTruth, Vec_Int_t * vCover ) +{ + char * pSop = NULL; + int w, nWords = Abc_Truth6WordNum( nVars ); + assert( nVars < 16 ); + + for ( w = 0; w < nWords; w++ ) + if ( pTruth[w] ) + break; + if ( w == nWords ) + return Abc_SopRegister( pMan, " 0\n" ); + + for ( w = 0; w < nWords; w++ ) + if ( ~pTruth[w] ) + break; + if ( w == nWords ) + return Abc_SopRegister( pMan, " 1\n" ); + + { + int RetValue = Kit_TruthIsop( (unsigned *)pTruth, nVars, vCover, 1 ); + assert( nVars > 0 ); + assert( RetValue == 0 || RetValue == 1 ); + pSop = Abc_SopCreateFromIsop( pMan, nVars, vCover ); + if ( RetValue ) + Abc_SopComplement( pSop ); + } + return pSop; +} + +/**Function************************************************************* + + Synopsis [Creates the cover from the ISOP computed from TT.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_SopToIsop( char * pSop, Vec_Int_t * vCover ) +{ + char * pCube; + int k, nVars, Entry; + nVars = Abc_SopGetVarNum( pSop ); + assert( nVars > 0 ); + // create cubes + Vec_IntClear( vCover ); + for ( pCube = pSop; *pCube; pCube += nVars + 3 ) + { + Entry = 0; + for ( k = nVars - 1; k >= 0; k-- ) + if ( pCube[k] == '0' ) + Entry = (Entry << 2) | 1; + else if ( pCube[k] == '1' ) + Entry = (Entry << 2) | 2; + else if ( pCube[k] == '-' ) + Entry = (Entry << 2); + else + assert( 0 ); + Vec_IntPush( vCover, Entry ); + } +} + +/**Function************************************************************* + + Synopsis [Reads the number of cubes in the cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopGetCubeNum( char * pSop ) +{ + char * pCur; + int nCubes = 0; + if ( pSop == NULL ) + return 0; + for ( pCur = pSop; *pCur; pCur++ ) + nCubes += (*pCur == '\n'); + return nCubes; +} + +/**Function************************************************************* + + Synopsis [Reads the number of SOP literals in the cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopGetLitNum( char * pSop ) +{ + char * pCur; + int nLits = 0; + if ( pSop == NULL ) + return 0; + for ( pCur = pSop; *pCur; pCur++ ) + { + nLits -= (*pCur == '\n'); + nLits += (*pCur == '0' || *pCur == '1'); + } + return nLits; +} + +/**Function************************************************************* + + Synopsis [Reads the number of variables in the cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopGetVarNum( char * pSop ) +{ + char * pCur; + for ( pCur = pSop; *pCur != '\n'; pCur++ ) + if ( *pCur == 0 ) + return -1; + return pCur - pSop - 2; +} + +/**Function************************************************************* + + Synopsis [Reads the phase of the cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopGetPhase( char * pSop ) +{ + int nVars = Abc_SopGetVarNum( pSop ); + if ( pSop[nVars+1] == '0' || pSop[nVars+1] == 'n' ) + return 0; + if ( pSop[nVars+1] == '1' || pSop[nVars+1] == 'x' ) + return 1; + assert( 0 ); + return -1; +} + +/**Function************************************************************* + + Synopsis [Returns the i-th literal of the cover.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopGetIthCareLit( char * pSop, int i ) +{ + char * pCube; + int nVars; + nVars = Abc_SopGetVarNum( pSop ); + Abc_SopForEachCube( pSop, nVars, pCube ) + if ( pCube[i] != '-' ) + return pCube[i] - '0'; + return -1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_SopComplement( char * pSop ) +{ + char * pCur; + for ( pCur = pSop; *pCur; pCur++ ) + if ( *pCur == '\n' ) + { + if ( *(pCur - 1) == '0' ) + *(pCur - 1) = '1'; + else if ( *(pCur - 1) == '1' ) + *(pCur - 1) = '0'; + else if ( *(pCur - 1) == 'x' ) + *(pCur - 1) = 'n'; + else if ( *(pCur - 1) == 'n' ) + *(pCur - 1) = 'x'; + else + assert( 0 ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_SopComplementVar( char * pSop, int iVar ) +{ + char * pCube; + int nVars = Abc_SopGetVarNum(pSop); + assert( iVar < nVars ); + Abc_SopForEachCube( pSop, nVars, pCube ) + { + if ( pCube[iVar] == '0' ) + pCube[iVar] = '1'; + else if ( pCube[iVar] == '1' ) + pCube[iVar] = '0'; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopIsComplement( char * pSop ) +{ + char * pCur; + for ( pCur = pSop; *pCur; pCur++ ) + if ( *pCur == '\n' ) + return (int)(*(pCur - 1) == '0' || *(pCur - 1) == 'n'); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [Checks if the cover is constant 0.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopIsConst0( char * pSop ) +{ + return pSop[0] == ' ' && pSop[1] == '0'; +} + +/**Function************************************************************* + + Synopsis [Checks if the cover is constant 1.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopIsConst1( char * pSop ) +{ + return pSop[0] == ' ' && pSop[1] == '1'; +} + +/**Function************************************************************* + + Synopsis [Checks if the cover is constant 1.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopIsBuf( char * pSop ) +{ + if ( pSop[4] != 0 ) + return 0; + if ( (pSop[0] == '1' && pSop[2] == '1') || (pSop[0] == '0' && pSop[2] == '0') ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Checks if the cover is constant 1.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopIsInv( char * pSop ) +{ + if ( pSop[4] != 0 ) + return 0; + if ( (pSop[0] == '0' && pSop[2] == '1') || (pSop[0] == '1' && pSop[2] == '0') ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Checks if the cover is AND with possibly complemented inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopIsAndType( char * pSop ) +{ + char * pCur; + if ( Abc_SopGetCubeNum(pSop) != 1 ) + return 0; + for ( pCur = pSop; *pCur != ' '; pCur++ ) + if ( *pCur == '-' ) + return 0; + if ( pCur[1] != '1' ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Checks if the cover is OR with possibly complemented inputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopIsOrType( char * pSop ) +{ + char * pCube, * pCur; + int nVars, nLits; + nVars = Abc_SopGetVarNum( pSop ); + if ( nVars != Abc_SopGetCubeNum(pSop) ) + return 0; + Abc_SopForEachCube( pSop, nVars, pCube ) + { + // count the number of literals in the cube + nLits = 0; + for ( pCur = pCube; *pCur != ' '; pCur++ ) + nLits += ( *pCur != '-' ); + if ( nLits != 1 ) + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopIsExorType( char * pSop ) +{ + char * pCur; + for ( pCur = pSop; *pCur; pCur++ ) + if ( *pCur == '\n' ) + return (int)(*(pCur - 1) == 'x' || *(pCur - 1) == 'n'); + assert( 0 ); + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopCheck( char * pSop, int nFanins ) +{ + char * pCubes, * pCubesOld; + int fFound0 = 0, fFound1 = 0; + + // check the logic function of the node + for ( pCubes = pSop; *pCubes; pCubes++ ) + { + // get the end of the next cube + for ( pCubesOld = pCubes; *pCubes != ' '; pCubes++ ); + // compare the distance + if ( pCubes - pCubesOld != nFanins ) + { + fprintf( stdout, "Abc_SopCheck: SOP has a mismatch between its cover size (%d) and its fanin number (%d).\n", + (int)(ABC_PTRDIFF_T)(pCubes - pCubesOld), nFanins ); + return 0; + } + // check the output values for this cube + pCubes++; + if ( *pCubes == '0' ) + fFound0 = 1; + else if ( *pCubes == '1' ) + fFound1 = 1; + else if ( *pCubes != 'x' && *pCubes != 'n' ) + { + fprintf( stdout, "Abc_SopCheck: SOP has a strange character (%c) in the output part of its cube.\n", *pCubes ); + return 0; + } + // check the last symbol (new line) + pCubes++; + if ( *pCubes != '\n' ) + { + fprintf( stdout, "Abc_SopCheck: SOP has a cube without new line in the end.\n" ); + return 0; + } + } + if ( fFound0 && fFound1 ) + { + fprintf( stdout, "Abc_SopCheck: SOP has cubes in both phases.\n" ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_SopCheckReadTruth( Vec_Ptr_t * vRes, char * pToken, int fHex ) +{ + char * pBase; int nVars; + int Log2 = Abc_Base2Log( strlen(pToken) ); + if ( fHex && strlen(pToken) == 1 ) + Log2 = 0; + if ( (1 << Log2) != (int)strlen(pToken) ) + { + printf( "The truth table length (%d) is not power-of-2.\n", (int)strlen(pToken) ); + Vec_PtrFreeData( vRes ); + Vec_PtrShrink( vRes, 0 ); + return 0; + } + if ( Vec_PtrSize(vRes) == 0 ) + return 1; + pBase = (char *)Vec_PtrEntry( vRes, 0 ); + nVars = Abc_SopGetVarNum( pBase ); + if ( nVars != Log2+2*fHex ) + { + printf( "Truth table #1 has %d vars while truth table #%d has %d vars.\n", nVars, Vec_PtrSize(vRes)+1, Log2+2*fHex ); + Vec_PtrFreeData( vRes ); + Vec_PtrShrink( vRes, 0 ); + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Derives SOP from the truth table representation.] + + Description [Truth table is expected to be in the hexadecimal notation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopFromTruthBin( char * pTruth ) +{ + char * pSopCover, * pCube; + int nTruthSize, nVars, Digit, Length, Mint, i, b; + Vec_Int_t * vMints; + + // get the number of variables + nTruthSize = strlen(pTruth); + nVars = Abc_Base2Log( nTruthSize ); + if ( nTruthSize != (1 << (nVars)) ) + { + printf( "String %s does not look like a truth table of a %d-variable function.\n", pTruth, nVars ); + return NULL; + } + + // collect the on-set minterms + vMints = Vec_IntAlloc( 100 ); + for ( i = 0; i < nTruthSize; i++ ) + { + if ( pTruth[i] >= '0' && pTruth[i] <= '1' ) + Digit = pTruth[i] - '0'; + else + { + Vec_IntFree( vMints ); + printf( "String %s does not look like a binary representation of the truth table.\n", pTruth ); + return NULL; + } + if ( Digit == 1 ) + Vec_IntPush( vMints, nTruthSize - 1 - i ); + } +/* + if ( Vec_IntSize( vMints ) == 0 || Vec_IntSize( vMints ) == nTruthSize ) + { + Vec_IntFree( vMints ); + printf( "Cannot create constant function.\n" ); + return NULL; + } +*/ + if ( Vec_IntSize(vMints) == 0 || Vec_IntSize(vMints) == (1 << nVars) ) + { + pSopCover = ABC_ALLOC( char, 4 ); + pSopCover[0] = ' '; + pSopCover[1] = '0' + (Vec_IntSize(vMints) > 0); + pSopCover[2] = '\n'; + pSopCover[3] = 0; + } + else + { + // create the SOP representation of the minterms + Length = Vec_IntSize(vMints) * (nVars + 3); + pSopCover = ABC_ALLOC( char, Length + 1 ); + pSopCover[Length] = 0; + Vec_IntForEachEntry( vMints, Mint, i ) + { + pCube = pSopCover + i * (nVars + 3); + for ( b = 0; b < nVars; b++ ) + // if ( Mint & (1 << (nVars-1-b)) ) + if ( Mint & (1 << b) ) + pCube[b] = '1'; + else + pCube[b] = '0'; + pCube[nVars + 0] = ' '; + pCube[nVars + 1] = '1'; + pCube[nVars + 2] = '\n'; + } + } + Vec_IntFree( vMints ); + return pSopCover; +} +Vec_Ptr_t * Abc_SopFromTruthsBin( char * pTruth ) +{ + Vec_Ptr_t * vRes = Vec_PtrAlloc( 10 ); + char * pCopy = Abc_UtilStrsav(pTruth); + char * pToken = strtok( pCopy, " \r\n\t|" ); + while ( pToken ) + { + if ( !Abc_SopCheckReadTruth( vRes, pToken, 0 ) ) + break; + Vec_PtrPush( vRes, Abc_SopFromTruthBin(pToken) ); + pToken = strtok( NULL, " \r\n\t|" ); + } + ABC_FREE( pCopy ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [Derives SOP from the truth table representation.] + + Description [Truth table is expected to be in the hexadecimal notation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopFromTruthHex( char * pTruth ) +{ + char * pSopCover, * pCube; + int nTruthSize, nVars, Digit, Length, Mint, i, b; + Vec_Int_t * vMints; + + // get the number of variables + nTruthSize = strlen(pTruth); + nVars = (nTruthSize < 2) ? 2 : Abc_Base2Log(nTruthSize) + 2; + if ( nTruthSize != (1 << (nVars-2)) ) + { + printf( "String %s does not look like a truth table of a %d-variable function.\n", pTruth, nVars ); + return NULL; + } + + // collect the on-set minterms + vMints = Vec_IntAlloc( 100 ); + for ( i = 0; i < nTruthSize; i++ ) + { + if ( pTruth[i] >= '0' && pTruth[i] <= '9' ) + Digit = pTruth[i] - '0'; + else if ( pTruth[i] >= 'a' && pTruth[i] <= 'f' ) + Digit = 10 + pTruth[i] - 'a'; + else if ( pTruth[i] >= 'A' && pTruth[i] <= 'F' ) + Digit = 10 + pTruth[i] - 'A'; + else + { + printf( "String %s does not look like a hexadecimal representation of the truth table.\n", pTruth ); + return NULL; + } + for ( b = 0; b < 4; b++ ) + if ( Digit & (1 << b) ) + Vec_IntPush( vMints, 4*(nTruthSize-1-i)+b ); + } + + // create the SOP representation of the minterms + if ( Vec_IntSize(vMints) == 0 || Vec_IntSize(vMints) == (1 << nVars) ) + { + pSopCover = ABC_ALLOC( char, 4 ); + pSopCover[0] = ' '; + pSopCover[1] = '0' + (Vec_IntSize(vMints) > 0); + pSopCover[2] = '\n'; + pSopCover[3] = 0; + } + else + { + Length = Vec_IntSize(vMints) * (nVars + 3); + pSopCover = ABC_ALLOC( char, Length + 1 ); + pSopCover[Length] = 0; + Vec_IntForEachEntry( vMints, Mint, i ) + { + pCube = pSopCover + i * (nVars + 3); + for ( b = 0; b < nVars; b++ ) + // if ( Mint & (1 << (nVars-1-b)) ) + if ( Mint & (1 << b) ) + pCube[b] = '1'; + else + pCube[b] = '0'; + pCube[nVars + 0] = ' '; + pCube[nVars + 1] = '1'; + pCube[nVars + 2] = '\n'; + } + } + + Vec_IntFree( vMints ); + return pSopCover; +} +Vec_Ptr_t * Abc_SopFromTruthsHex( char * pTruth ) +{ + Vec_Ptr_t * vRes = Vec_PtrAlloc( 10 ); + char * pCopy = Abc_UtilStrsav(pTruth); + char * pToken = strtok( pCopy, " \r\n\t|" ); + while ( pToken ) + { + if ( !Abc_SopCheckReadTruth( vRes, pToken, 1 ) ) + break; + Vec_PtrPush( vRes, Abc_SopFromTruthHex(pToken) ); + pToken = strtok( NULL, " \r\n\t|" ); + } + ABC_FREE( pCopy ); + return vRes; +} + +Vec_Ptr_t * Abc_SopGenerateCounters( int nVars ) +{ + int m, i, o, nOuts = Abc_Base2Log( nVars + 1 ); + Vec_Ptr_t * vRes = Vec_PtrAlloc( nOuts ); + for ( o = 0; o < nOuts; o++ ) + { + Vec_Str_t * vStr = Vec_StrAlloc( 1000 ); + for ( m = 0; m < (1 << nVars); m++ ) { + int nOnes = __builtin_popcount(m); + if ( !((nOnes >> o) & 1) ) + continue; + for ( i = 0; i < nVars; i++ ) + Vec_StrPush( vStr, ((m >> i) & 1) ? '1' : '0' ); + Vec_StrPush( vStr, ' ' ); + Vec_StrPush( vStr, '1' ); + Vec_StrPush( vStr, '\n' ); + } + Vec_StrPush( vStr, '\0' ); + //printf( "%s\n", Vec_StrArray(vStr) ); + Vec_PtrPush( vRes, Vec_StrReleaseArray(vStr) ); + Vec_StrFree( vStr ); + } + return vRes; +} + +/**Function************************************************************* + + Synopsis [Creates one encoder node.] + + Description [Produces MV-SOP for BLIF-MV representation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopEncoderPos( Mem_Flex_t * pMan, int iValue, int nValues ) +{ + char Buffer[32]; + assert( iValue < nValues ); + sprintf( Buffer, "d0\n%d 1\n", iValue ); + return Abc_SopRegister( pMan, Buffer ); +} + +/**Function************************************************************* + + Synopsis [Creates one encoder node.] + + Description [Produces MV-SOP for BLIF-MV representation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopEncoderLog( Mem_Flex_t * pMan, int iBit, int nValues ) +{ + char * pResult; + Vec_Str_t * vSop; + int v, Counter, fFirst = 1, nBits = Abc_Base2Log(nValues); + assert( iBit < nBits ); + // count the number of literals + Counter = 0; + for ( v = 0; v < nValues; v++ ) + Counter += ( (v & (1 << iBit)) > 0 ); + // create the cover + vSop = Vec_StrAlloc( 100 ); + Vec_StrPrintStr( vSop, "d0\n" ); + if ( Counter > 1 ) + Vec_StrPrintStr( vSop, "(" ); + for ( v = 0; v < nValues; v++ ) + if ( v & (1 << iBit) ) + { + if ( fFirst ) + fFirst = 0; + else + Vec_StrPush( vSop, ',' ); + Vec_StrPrintNum( vSop, v ); + } + if ( Counter > 1 ) + Vec_StrPrintStr( vSop, ")" ); + Vec_StrPrintStr( vSop, " 1\n" ); + Vec_StrPush( vSop, 0 ); + pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) ); + Vec_StrFree( vSop ); + return pResult; +} + +/**Function************************************************************* + + Synopsis [Creates the decoder node.] + + Description [Produces MV-SOP for BLIF-MV representation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopDecoderPos( Mem_Flex_t * pMan, int nValues ) +{ + char * pResult; + Vec_Str_t * vSop; + int i, k; + assert( nValues > 1 ); + vSop = Vec_StrAlloc( 100 ); + for ( i = 0; i < nValues; i++ ) + { + for ( k = 0; k < nValues; k++ ) + { + if ( k == i ) + Vec_StrPrintStr( vSop, "1 " ); + else + Vec_StrPrintStr( vSop, "- " ); + } + Vec_StrPrintNum( vSop, i ); + Vec_StrPush( vSop, '\n' ); + } + Vec_StrPush( vSop, 0 ); + pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) ); + Vec_StrFree( vSop ); + return pResult; +} + +/**Function************************************************************* + + Synopsis [Creates the decover node.] + + Description [Produces MV-SOP for BLIF-MV representation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +char * Abc_SopDecoderLog( Mem_Flex_t * pMan, int nValues ) +{ + char * pResult; + Vec_Str_t * vSop; + int i, b, nBits = Abc_Base2Log(nValues); + assert( nValues > 1 && nValues <= (1< 0) ); + Vec_StrPush( vSop, ' ' ); + } + Vec_StrPrintNum( vSop, i ); + Vec_StrPush( vSop, '\n' ); + } + Vec_StrPush( vSop, 0 ); + pResult = Abc_SopRegister( pMan, Vec_StrArray(vSop) ); + Vec_StrFree( vSop ); + return pResult; +} + +/**Function************************************************************* + + Synopsis [Computes truth table of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +word Abc_SopToTruth( char * pSop, int nInputs ) +{ + static word Truth[8] = { + ABC_CONST(0xAAAAAAAAAAAAAAAA), + ABC_CONST(0xCCCCCCCCCCCCCCCC), + ABC_CONST(0xF0F0F0F0F0F0F0F0), + ABC_CONST(0xFF00FF00FF00FF00), + ABC_CONST(0xFFFF0000FFFF0000), + ABC_CONST(0xFFFFFFFF00000000), + ABC_CONST(0x0000000000000000), + ABC_CONST(0xFFFFFFFFFFFFFFFF) + }; + word Cube, Result = 0; + int v, lit = 0; + int nVars = Abc_SopGetVarNum(pSop); + assert( nVars >= 0 && nVars <= 6 ); + assert( nVars == nInputs ); + do { + Cube = Truth[7]; + for ( v = 0; v < nVars; v++, lit++ ) + { + if ( pSop[lit] == '1' ) + Cube &= Truth[v]; + else if ( pSop[lit] == '0' ) + Cube &= ~Truth[v]; + else if ( pSop[lit] != '-' ) + assert( 0 ); + } + Result |= Cube; + assert( pSop[lit] == ' ' ); + lit++; + lit++; + assert( pSop[lit] == '\n' ); + lit++; + } while ( pSop[lit] ); + if ( Abc_SopIsComplement(pSop) ) + Result = ~Result; + return Result; +} + +/**Function************************************************************* + + Synopsis [Computes truth table of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_SopToTruth7( char * pSop, int nInputs, word r[2] ) +{ + static word Truth[7][2] = { + {ABC_CONST(0xAAAAAAAAAAAAAAAA),ABC_CONST(0xAAAAAAAAAAAAAAAA)}, + {ABC_CONST(0xCCCCCCCCCCCCCCCC),ABC_CONST(0xCCCCCCCCCCCCCCCC)}, + {ABC_CONST(0xF0F0F0F0F0F0F0F0),ABC_CONST(0xF0F0F0F0F0F0F0F0)}, + {ABC_CONST(0xFF00FF00FF00FF00),ABC_CONST(0xFF00FF00FF00FF00)}, + {ABC_CONST(0xFFFF0000FFFF0000),ABC_CONST(0xFFFF0000FFFF0000)}, + {ABC_CONST(0xFFFFFFFF00000000),ABC_CONST(0xFFFFFFFF00000000)}, + {ABC_CONST(0x0000000000000000),ABC_CONST(0xFFFFFFFFFFFFFFFF)}, + }; + word Cube[2]; + int v, lit = 0; + int nVars = Abc_SopGetVarNum(pSop); + assert( nVars >= 0 && nVars <= 7 ); + assert( nVars == nInputs ); + r[0] = r[1] = 0; + do { + Cube[0] = Cube[1] = ~(word)0; + for ( v = 0; v < nVars; v++, lit++ ) + { + if ( pSop[lit] == '1' ) + { + Cube[0] &= Truth[v][0]; + Cube[1] &= Truth[v][1]; + } + else if ( pSop[lit] == '0' ) + { + Cube[0] &= ~Truth[v][0]; + Cube[1] &= ~Truth[v][1]; + } + else if ( pSop[lit] != '-' ) + assert( 0 ); + } + r[0] |= Cube[0]; + r[1] |= Cube[1]; + assert( pSop[lit] == ' ' ); + lit++; + lit++; + assert( pSop[lit] == '\n' ); + lit++; + } while ( pSop[lit] ); + if ( Abc_SopIsComplement(pSop) ) + { + r[0] = ~r[0]; + r[1] = ~r[1]; + } +} + +/**Function************************************************************* + + Synopsis [Computes truth table of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_SopToTruthBig( char * pSop, int nInputs, word ** pVars, word * pCube, word * pRes ) +{ + int nVars = Abc_SopGetVarNum(pSop); + int nWords = nVars <= 6 ? 1 : 1 << (nVars-6); + int v, i, lit = 0; + assert( nVars >= 0 && nVars <= 16 ); + assert( nVars == nInputs ); + for ( i = 0; i < nWords; i++ ) + pRes[i] = 0; + do { + for ( i = 0; i < nWords; i++ ) + pCube[i] = ~(word)0; + for ( v = 0; v < nVars; v++, lit++ ) + { + if ( pSop[lit] == '1' ) + { + for ( i = 0; i < nWords; i++ ) + pCube[i] &= pVars[v][i]; + } + else if ( pSop[lit] == '0' ) + { + for ( i = 0; i < nWords; i++ ) + pCube[i] &= ~pVars[v][i]; + } + else if ( pSop[lit] != '-' ) + assert( 0 ); + } + for ( i = 0; i < nWords; i++ ) + pRes[i] |= pCube[i]; + assert( pSop[lit] == ' ' ); + lit++; + lit++; + assert( pSop[lit] == '\n' ); + lit++; + } while ( pSop[lit] ); + if ( Abc_SopIsComplement(pSop) ) + { + for ( i = 0; i < nWords; i++ ) + pRes[i] = ~pRes[i]; + } +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/abcUtil.c b/yosys/abc/src/base/abc/abcUtil.c new file mode 100644 index 00000000000..fddc04bebe1 --- /dev/null +++ b/yosys/abc/src/base/abc/abcUtil.c @@ -0,0 +1,3567 @@ +/**CFile**************************************************************** + + FileName [abcUtil.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Various utilities.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abcUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" +#include "base/main/main.h" +#include "map/mio/mio.h" +#include "bool/dec/dec.h" +#include "opt/fxu/fxu.h" +#include "aig/miniaig/ndr.h" +#include "misc/util/utilTruth.h" + +#ifdef ABC_USE_CUDD +#include "bdd/extrab/extraBdd.h" +#endif + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [Frees one attribute manager.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void * Abc_NtkAttrFree( Abc_Ntk_t * pNtk, int Attr, int fFreeMan ) +{ + void * pUserMan; + Vec_Att_t * pAttrMan; + pAttrMan = (Vec_Att_t *)Vec_PtrEntry( pNtk->vAttrs, Attr ); + Vec_PtrWriteEntry( pNtk->vAttrs, Attr, NULL ); + pUserMan = Vec_AttFree( pAttrMan, fFreeMan ); + return pUserMan; +} + +/**Function************************************************************* + + Synopsis [Order CI/COs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkOrderCisCos( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj, * pTerm; + int i, k; + Vec_PtrClear( pNtk->vCis ); + Vec_PtrClear( pNtk->vCos ); + Abc_NtkForEachPi( pNtk, pObj, i ) + Vec_PtrPush( pNtk->vCis, pObj ); + Abc_NtkForEachPo( pNtk, pObj, i ) + Vec_PtrPush( pNtk->vCos, pObj ); + Abc_NtkForEachBox( pNtk, pObj, i ) + { + if ( Abc_ObjIsLatch(pObj) ) + continue; + Abc_ObjForEachFanin( pObj, pTerm, k ) + Vec_PtrPush( pNtk->vCos, pTerm ); + Abc_ObjForEachFanout( pObj, pTerm, k ) + Vec_PtrPush( pNtk->vCis, pTerm ); + } + Abc_NtkForEachBox( pNtk, pObj, i ) + { + if ( !Abc_ObjIsLatch(pObj) ) + continue; + Abc_ObjForEachFanin( pObj, pTerm, k ) + Vec_PtrPush( pNtk->vCos, pTerm ); + Abc_ObjForEachFanout( pObj, pTerm, k ) + Vec_PtrPush( pNtk->vCis, pTerm ); + } +} + +/**Function************************************************************* + + Synopsis [Reads the number of cubes of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetCubeNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, nCubes = 0; + assert( Abc_NtkHasSop(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_NodeIsConst(pNode) ) + continue; + assert( pNode->pData ); + nCubes += Abc_SopGetCubeNum( (char *)pNode->pData ); + } + return nCubes; +} + +/**Function************************************************************* + + Synopsis [Reads the number of cubes of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetCubePairNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i; + word nCubes, nCubePairs = 0; + assert( Abc_NtkHasSop(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_NodeIsConst(pNode) ) + continue; + assert( pNode->pData ); + nCubes = (word)Abc_SopGetCubeNum( (char *)pNode->pData ); + if ( nCubes > 1 ) + nCubePairs += nCubes * (nCubes - 1) / 2; + } + return (int)(nCubePairs > (1<<30) ? (1<<30) : nCubePairs); +} + +/**Function************************************************************* + + Synopsis [Reads the number of literals in the SOPs of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetLitNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, nLits = 0; + assert( Abc_NtkHasSop(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + assert( pNode->pData ); + nLits += Abc_SopGetLitNum( (char *)pNode->pData ); + } + return nLits; +} + +/**Function************************************************************* + + Synopsis [Counts the number of literals in the factored forms.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetLitFactNum( Abc_Ntk_t * pNtk ) +{ + Dec_Graph_t * pFactor; + Abc_Obj_t * pNode; + int nNodes, i; + assert( Abc_NtkHasSop(pNtk) ); + nNodes = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( Abc_NodeIsConst(pNode) ) + continue; + pFactor = Dec_Factor( (char *)pNode->pData ); + nNodes += 1 + Dec_GraphNodeNum(pFactor); + Dec_GraphFree( pFactor ); + } + return nNodes; +} + +/**Function************************************************************* + + Synopsis [Counts the number of nodes with more than 1 reference.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetMultiRefNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int nNodes, i; + assert( Abc_NtkIsStrash(pNtk) ); + nNodes = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + nNodes += (int)(Abc_ObjFanoutNum(pNode) > 1); + return nNodes; +} + +/**Function************************************************************* + + Synopsis [Reads the number of BDD nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetBddNodeNum( Abc_Ntk_t * pNtk ) +{ + int nNodes = 0; +#ifdef ABC_USE_CUDD + Abc_Obj_t * pNode; + int i; + assert( Abc_NtkIsBddLogic(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + assert( pNode->pData ); + if ( Abc_ObjFaninNum(pNode) < 2 ) + continue; + nNodes += pNode->pData? -1 + Cudd_DagSize( (DdNode *)pNode->pData ) : 0; + } +#endif + return nNodes; +} + +/**Function************************************************************* + + Synopsis [Reads the number of BDD nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetAigNodeNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, nNodes = 0; + assert( Abc_NtkIsAigLogic(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + assert( pNode->pData ); + if ( Abc_ObjFaninNum(pNode) < 2 ) + continue; +//printf( "%d ", Hop_DagSize( pNode->pData ) ); + nNodes += pNode->pData? Hop_DagSize( (Hop_Obj_t *)pNode->pData ) : 0; + } + return nNodes; +} + +/**Function************************************************************* + + Synopsis [Reads the number of BDD nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetClauseNum( Abc_Ntk_t * pNtk ) +{ + int nClauses = 0; +#ifdef ABC_USE_CUDD + extern int Abc_CountZddCubes( DdManager * dd, DdNode * zCover ); + Abc_Obj_t * pNode; + DdNode * bCover, * zCover, * bFunc; + DdManager * dd = (DdManager *)pNtk->pManFunc; + int i; + assert( Abc_NtkIsBddLogic(pNtk) ); + Abc_NtkForEachNode( pNtk, pNode, i ) + { + assert( pNode->pData ); + bFunc = (DdNode *)pNode->pData; + + bCover = Cudd_zddIsop( dd, bFunc, bFunc, &zCover ); + Cudd_Ref( bCover ); + Cudd_Ref( zCover ); + nClauses += Abc_CountZddCubes( dd, zCover ); + Cudd_RecursiveDeref( dd, bCover ); + Cudd_RecursiveDerefZdd( dd, zCover ); + + bCover = Cudd_zddIsop( dd, Cudd_Not(bFunc), Cudd_Not(bFunc), &zCover ); + Cudd_Ref( bCover ); + Cudd_Ref( zCover ); + nClauses += Abc_CountZddCubes( dd, zCover ); + Cudd_RecursiveDeref( dd, bCover ); + Cudd_RecursiveDerefZdd( dd, zCover ); + } +#endif + return nClauses; +} + +/**Function************************************************************* + + Synopsis [Computes the area of the mapped circuit.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +double Abc_NtkGetMappedArea( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + double TotalArea; + int i; + assert( Abc_NtkHasMapping(pNtk) ); + TotalArea = 0.0; + Abc_NtkForEachNode( pNtk, pObj, i ) + { + if ( Abc_ObjIsBarBuf(pObj) ) + continue; +// assert( pObj->pData ); + if ( pObj->pData == NULL ) + { + printf( "Node without mapping is encountered.\n" ); + continue; + } + TotalArea += Mio_GateReadArea( (Mio_Gate_t *)pObj->pData ); + // assuming that twin gates follow each other + if ( Abc_NtkFetchTwinNode(pObj) ) + i++; + } + return TotalArea; +} + +/**Function************************************************************* + + Synopsis [Counts the number of exors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetExorNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + Counter += pNode->fExor; + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of exors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetMuxNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + Counter += Abc_NodeIsMuxType(pNode); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of exors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetBufNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + Counter += (Abc_ObjFaninNum(pNode) == 1); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Counts the number of exors.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetLargeNodeNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + Counter += (Abc_ObjFaninNum(pNode) > 1); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if it is an AIG with choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetChoiceNum( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, Counter; + if ( !Abc_NtkIsStrash(pNtk) ) + return 0; + Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + Counter += Abc_AigNodeIsChoice( pNode ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Reads the maximum number of fanins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetFaninMax( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, nFaninsMax = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( nFaninsMax < Abc_ObjFaninNum(pNode) ) + nFaninsMax = Abc_ObjFaninNum(pNode); + } + return nFaninsMax; +} +int Abc_NtkGetFanoutMax( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, nFaninsMax = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + { + if ( nFaninsMax < Abc_ObjFanoutNum(pNode) ) + nFaninsMax = Abc_ObjFanoutNum(pNode); + } + return nFaninsMax; +} + +/**Function************************************************************* + + Synopsis [Reads the total number of all fanins.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkGetTotalFanins( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i, nFanins = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + nFanins += Abc_ObjFaninNum(pNode); + return nFanins; +} + +/**Function************************************************************* + + Synopsis [Cleans the copy field of all objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCleanCopy( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pCopy = NULL; +} +void Abc_NtkCleanCopy_rec( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkCleanCopy( pNtk ); + Abc_NtkForEachBox( pNtk, pObj, i ) + Abc_NtkCleanCopy_rec( Abc_ObjModel(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Cleans the copy field of all objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCleanData( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pData = NULL; +} + +/**Function************************************************************* + + Synopsis [Cleans the copy field of all objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFillTemp( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->iTemp = -1; +} + +/**Function************************************************************* + + Synopsis [Counts the number of nodes having non-trivial copies.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCountCopy( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i, Counter = 0; + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( Abc_ObjIsNode(pObj) ) + Counter += (pObj->pCopy != NULL); + } + return Counter; +} + +/**Function************************************************************* + + Synopsis [Saves copy field of the objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkSaveCopy( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vCopies; + Abc_Obj_t * pObj; + int i; + vCopies = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); + Abc_NtkForEachObj( pNtk, pObj, i ) + Vec_PtrWriteEntry( vCopies, i, pObj->pCopy ); + return vCopies; +} + +/**Function************************************************************* + + Synopsis [Loads copy field of the objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkLoadCopy( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCopies ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pCopy = (Abc_Obj_t *)Vec_PtrEntry( vCopies, i ); +} + +/**Function************************************************************* + + Synopsis [Cleans the copy field of all objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCleanNext( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->pNext = NULL; +} +void Abc_NtkCleanNext_rec( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkCleanNext( pNtk ); + Abc_NtkForEachBox( pNtk, pObj, i ) + Abc_NtkCleanNext_rec( Abc_ObjModel(pObj) ); +} + +/**Function************************************************************* + + Synopsis [Cleans the copy field of all objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCleanMarkA( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->fMarkA = 0; +} + +/**Function************************************************************* + + Synopsis [Cleans the copy field of all objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCleanMarkB( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->fMarkB = 0; +} + +/**Function************************************************************* + + Synopsis [Cleans the copy field of all objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCleanMarkC( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->fMarkC = 0; +} + +/**Function************************************************************* + + Synopsis [Cleans the copy field of all objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCleanMarkAB( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->fMarkA = pObj->fMarkB = 0; +} + +/**Function************************************************************* + + Synopsis [Cleans the copy field of all objects.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCleanMarkABC( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + pObj->fMarkA = pObj->fMarkB = pObj->fMarkC = 0; +} + +/**Function************************************************************* + + Synopsis [Returns the index of the given fanin.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeFindFanin( Abc_Obj_t * pNode, Abc_Obj_t * pFanin ) +{ + Abc_Obj_t * pThis; + int i; + Abc_ObjForEachFanin( pNode, pThis, i ) + if ( pThis == pFanin ) + return i; + return -1; +} + +/**Function************************************************************* + + Synopsis [Checks if the internal node has CO fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFindCoFanout( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanout; + int i; + Abc_ObjForEachFanout( pNode, pFanout, i ) + if ( Abc_ObjIsCo(pFanout) ) + return pFanout; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Checks if the internal node has CO fanout.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeFindNonCoFanout( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanout; + int i; + Abc_ObjForEachFanout( pNode, pFanout, i ) + if ( !Abc_ObjIsCo(pFanout) ) + return pFanout; + return NULL; +} + +/**Function************************************************************* + + Synopsis [Checks if the internal node has CO drivers with the same name.] + + Description [Checks if the internal node can borrow its name from CO fanouts. + This is possible if all COs with non-complemented fanin edge pointing to this + node have the same name.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeHasUniqueCoFanout( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pFanout, * pFanoutCo; + int i; + pFanoutCo = NULL; + Abc_ObjForEachFanout( pNode, pFanout, i ) + { + if ( !Abc_ObjIsCo(pFanout) ) + continue; + if ( Abc_ObjFaninC0(pFanout) ) + continue; + if ( pFanoutCo == NULL ) + { + assert( Abc_ObjFaninNum(pFanout) == 1 ); + assert( Abc_ObjFanin0(pFanout) == pNode ); + pFanoutCo = pFanout; + continue; + } + if ( strcmp( Abc_ObjName(pFanoutCo), Abc_ObjName(pFanout) ) ) // they have diff names + return NULL; + } + return pFanoutCo; +} + +/**Function************************************************************* + + Synopsis [Fixes the CO driver problem.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkFixCoDriverProblem( Abc_Obj_t * pDriver, Abc_Obj_t * pNodeCo, int fDuplicate ) +{ + Abc_Ntk_t * pNtk = pDriver->pNtk; + Abc_Obj_t * pDriverNew, * pFanin; + int k; + if ( fDuplicate && !Abc_ObjIsCi(pDriver) ) + { + pDriverNew = Abc_NtkDupObj( pNtk, pDriver, 0 ); + Abc_ObjForEachFanin( pDriver, pFanin, k ) + Abc_ObjAddFanin( pDriverNew, pFanin ); + if ( Abc_ObjFaninC0(pNodeCo) ) + { + // change polarity of the duplicated driver + Abc_NodeComplement( pDriverNew ); + Abc_ObjXorFaninC( pNodeCo, 0 ); + } + } + else + { + // add inverters and buffers when necessary + if ( Abc_ObjFaninC0(pNodeCo) ) + { + pDriverNew = Abc_NtkCreateNodeInv( pNtk, pDriver ); + Abc_ObjXorFaninC( pNodeCo, 0 ); + } + else + pDriverNew = Abc_NtkCreateNodeBuf( pNtk, pDriver ); + } + // update the fanin of the PO node + Abc_ObjPatchFanin( pNodeCo, pDriver, pDriverNew ); + assert( Abc_ObjFanoutNum(pDriverNew) == 1 ); + // remove the old driver if it dangles + // (this happens when the duplicated driver had only one complemented fanout) + if ( Abc_ObjFanoutNum(pDriver) == 0 ) + Abc_NtkDeleteObj( pDriver ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if COs of a logic network are simple.] + + Description [The COs of a logic network are simple under three conditions: + (1) The edge from CO to its driver is not complemented. + (2) If CI is a driver of a CO, they have the same name.] + (3) If two COs share the same driver, they have the same name.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode, * pDriver; + int i; + assert( Abc_NtkIsLogic(pNtk) ); + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + // if the driver is complemented, this is an error + pDriver = Abc_ObjFanin0(pNode); + if ( Abc_ObjFaninC0(pNode) ) + return 0; + // if the driver is a CI and has different name, this is an error + if ( Abc_ObjIsCi(pDriver) && strcmp(Abc_ObjName(pDriver), Abc_ObjName(pNode)) ) + return 0; + // if the driver is visited for the first time, remember the CO name + if ( !Abc_NodeIsTravIdCurrent(pDriver) ) + { + pDriver->pNext = (Abc_Obj_t *)Abc_ObjName(pNode); + Abc_NodeSetTravIdCurrent(pDriver); + continue; + } + // the driver has second CO - if they have different name, this is an error + if ( strcmp((char *)pDriver->pNext, Abc_ObjName(pNode)) ) // diff names + return 0; + } + return 1; +} + +/**Function************************************************************* + + Synopsis [Transforms the network to have simple COs.] + + Description [The COs of a logic network are simple under three conditions: + (1) The edge from CO to its driver is not complemented. + (2) If CI is a driver of a CO, they have the same name.] + (3) If two COs share the same driver, they have the same name. + In some cases, such as FPGA mapping, we prevent the increase in delay + by duplicating the driver nodes, rather than adding invs/bufs.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkLogicMakeSimpleCos2( Abc_Ntk_t * pNtk, int fDuplicate ) +{ + Abc_Obj_t * pNode, * pDriver; + int i, nDupGates = 0; + assert( Abc_NtkIsLogic(pNtk) ); + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + // if the driver is complemented, this is an error + pDriver = Abc_ObjFanin0(pNode); + if ( Abc_ObjFaninC0(pNode) ) + { + Abc_NtkFixCoDriverProblem( pDriver, pNode, fDuplicate ); + nDupGates++; + continue; + } + // if the driver is a CI and has different name, this is an error + if ( Abc_ObjIsCi(pDriver) && strcmp(Abc_ObjName(pDriver), Abc_ObjName(pNode)) ) + { + Abc_NtkFixCoDriverProblem( pDriver, pNode, fDuplicate ); + nDupGates++; + continue; + } + // if the driver is visited for the first time, remember the CO name + if ( !Abc_NodeIsTravIdCurrent(pDriver) ) + { + pDriver->pNext = (Abc_Obj_t *)Abc_ObjName(pNode); + Abc_NodeSetTravIdCurrent(pDriver); + continue; + } + // the driver has second CO - if they have different name, this is an error + if ( strcmp((char *)pDriver->pNext, Abc_ObjName(pNode)) ) // diff names + { + Abc_NtkFixCoDriverProblem( pDriver, pNode, fDuplicate ); + nDupGates++; + continue; + } + } + assert( Abc_NtkLogicHasSimpleCos(pNtk) ); + return nDupGates; +} + + +/**Function************************************************************* + + Synopsis [Transforms the network to have simple COs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkLogicMakeSimpleCosTest( Abc_Ntk_t * pNtk, int fDuplicate ) +{ + int nObjs = Abc_NtkObjNumMax(pNtk); + unsigned * pType = ABC_CALLOC( unsigned, nObjs ); + Abc_Obj_t * pNode; + int i, Counts[4] = {0}, Consts[2] = {0}, Inputs[2] = {0}; + // collect info + Abc_NtkForEachCo( pNtk, pNode, i ) + { + if ( Abc_ObjFaninId0(pNode) == 0 ) + Consts[Abc_ObjFaninC0(pNode)]++; + if ( Abc_ObjIsCi(Abc_ObjFanin0(pNode)) ) + Inputs[Abc_ObjFaninC0(pNode)]++; + pType[Abc_ObjFaninId0(pNode)] |= (1 << Abc_ObjFaninC0(pNode)); + } + // count the numbers + for ( i = 0; i < nObjs; i++ ) + Counts[pType[i]]++; + for ( i = 0; i < 4; i++ ) + printf( "%d = %d ", i, Counts[i] ); + for ( i = 0; i < 2; i++ ) + printf( "c%d = %d ", i, Consts[i] ); + for ( i = 0; i < 2; i++ ) + printf( "i%d = %d ", i, Inputs[i] ); + printf( "\n" ); + ABC_FREE( pType ); +} + +/**Function************************************************************* + + Synopsis [Transforms the network to have simple COs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkLogicMakeSimpleCos( Abc_Ntk_t * pNtk, int fDuplicate ) +{ + int fAddBuffers = 1; + Vec_Ptr_t * vDrivers, * vCoTerms; + Abc_Obj_t * pNode, * pDriver, * pDriverNew, * pFanin; + int i, k, LevelMax, nTotal = 0; + assert( Abc_NtkIsLogic(pNtk) ); + LevelMax = Abc_NtkLevel(pNtk); +// Abc_NtkLogicMakeSimpleCosTest( pNtk, fDuplicate ); + + // fix constant drivers + Abc_NtkForEachCo( pNtk, pNode, i ) + { + pDriver = Abc_ObjFanin0(pNode); + if ( !Abc_NodeIsConst(pDriver) ) + continue; + pDriverNew = (Abc_ObjFaninC0(pNode) == Abc_NodeIsConst0(pDriver)) ? Abc_NtkCreateNodeConst1(pNtk) : Abc_NtkCreateNodeConst0(pNtk); + if ( Abc_ObjFaninC0(pNode) ) + Abc_ObjXorFaninC( pNode, 0 ); + Abc_ObjPatchFanin( pNode, pDriver, pDriverNew ); + if ( Abc_ObjFanoutNum(pDriver) == 0 ) + Abc_NtkDeleteObj( pDriver ); + } + + // collect drivers pointed by complemented edges + vDrivers = Vec_PtrAlloc( 100 ); + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + if ( !Abc_ObjFaninC0(pNode) ) + continue; + pDriver = Abc_ObjFanin0(pNode); + if ( Abc_NodeIsTravIdCurrent(pDriver) ) + continue; + Abc_NodeSetTravIdCurrent(pDriver); + Vec_PtrPush( vDrivers, pDriver ); + } + // fix complemented drivers + if ( Vec_PtrSize(vDrivers) > 0 ) + { + int nDupGates = 0, nDupInvs = 0, nDupChange = 0; + Vec_Ptr_t * vFanouts = Vec_PtrAlloc( 100 ); + Vec_PtrForEachEntry( Abc_Obj_t *, vDrivers, pDriver, i ) + { + int fHasDir = 0, fHasInv = 0, fHasOther = 0; + Abc_ObjForEachFanout( pDriver, pNode, k ) + { + if ( !Abc_ObjIsCo(pNode) ) + { + assert( !Abc_ObjFaninC0(pNode) ); + fHasOther = 1; + continue; + } + if ( Abc_ObjFaninC0(pNode) ) + fHasInv = 1; + else //if ( Abc_ObjFaninC0(pNode) ) + fHasDir = 1; + } + assert( fHasInv ); + if ( Abc_ObjIsCi(pDriver) || fHasDir || (fHasOther && Abc_NtkHasMapping(pNtk)) ) // cannot change + { + // duplicate if critical + if ( fDuplicate && Abc_ObjIsNode(pDriver) && Abc_ObjLevel(pDriver) == LevelMax ) + { + pDriverNew = Abc_NtkDupObj( pNtk, pDriver, 0 ); + Abc_ObjForEachFanin( pDriver, pFanin, k ) + Abc_ObjAddFanin( pDriverNew, pFanin ); + Abc_NodeComplement( pDriverNew ); + nDupGates++; + } + else // add inverter + { + pDriverNew = Abc_NtkCreateNodeInv( pNtk, pDriver ); + nDupInvs++; + } + // collect CO fanouts to be redirected to the new node + Vec_PtrClear( vFanouts ); + Abc_ObjForEachFanout( pDriver, pNode, k ) + if ( Abc_ObjIsCo(pNode) && Abc_ObjFaninC0(pNode) ) + Vec_PtrPush( vFanouts, pNode ); + assert( Vec_PtrSize(vFanouts) > 0 ); + Vec_PtrForEachEntry( Abc_Obj_t *, vFanouts, pNode, k ) + { + Abc_ObjXorFaninC( pNode, 0 ); + Abc_ObjPatchFanin( pNode, pDriver, pDriverNew ); + assert( Abc_ObjIsCi(pDriver) || Abc_ObjFanoutNum(pDriver) > 0 ); + } + } + else // can change + { + // change polarity of the driver + assert( Abc_ObjIsNode(pDriver) ); + Abc_NodeComplement( pDriver ); + Abc_ObjForEachFanout( pDriver, pNode, k ) + { + if ( Abc_ObjIsCo(pNode) ) + { + assert( Abc_ObjFaninC0(pNode) ); + Abc_ObjXorFaninC( pNode, 0 ); + } + else if ( Abc_ObjIsNode(pNode) ) + Abc_NodeComplementInput( pNode, pDriver ); + else assert( 0 ); + } + nDupChange++; + } + } + Vec_PtrFree( vFanouts ); +// printf( "Resolving inverted CO drivers: Invs = %d. Dups = %d. Changes = %d.\n", +// nDupInvs, nDupGates, nDupChange ); + nTotal += nDupInvs + nDupGates; + } + Vec_PtrFree( vDrivers ); + + // collect COs that needs fixing by adding buffers or duplicating + vCoTerms = Vec_PtrAlloc( 100 ); + Abc_NtkIncrementTravId( pNtk ); + + // The following cases should be addressed only if the network is written + // into a BLIF file. Otherwise, it is possible to skip them: + // (1) if a CO points to a CI with a different name + // (2) if an internal node drives more than one CO + if ( fAddBuffers ) + Abc_NtkForEachCo( pNtk, pNode, i ) + { + // if the driver is a CI and has different name, this is an error + pDriver = Abc_ObjFanin0(pNode); + if ( Abc_ObjIsCi(pDriver) && strcmp(Abc_ObjName(pDriver), Abc_ObjName(pNode)) ) + { + Vec_PtrPush( vCoTerms, pNode ); + continue; + } + // if the driver is visited for the first time, remember the CO name + if ( !Abc_NodeIsTravIdCurrent(pDriver) ) + { + pDriver->pNext = (Abc_Obj_t *)Abc_ObjName(pNode); + Abc_NodeSetTravIdCurrent(pDriver); + continue; + } + // the driver has second CO - if they have different name, this is an error + if ( strcmp((char *)pDriver->pNext, Abc_ObjName(pNode)) ) // diff names + { + Vec_PtrPush( vCoTerms, pNode ); + continue; + } + } + // fix duplication problem + if ( Vec_PtrSize(vCoTerms) > 0 ) + { + int nDupBufs = 0, nDupGates = 0; + Vec_PtrForEachEntry( Abc_Obj_t *, vCoTerms, pNode, i ) + { + pDriver = Abc_ObjFanin0(pNode); + // duplicate if critical + if ( fDuplicate && Abc_ObjIsNode(pDriver) && (Abc_NtkHasMapping(pNtk) || Abc_ObjLevel(pDriver) == LevelMax) ) + { + pDriverNew = Abc_NtkDupObj( pNtk, pDriver, 0 ); + Abc_ObjForEachFanin( pDriver, pFanin, k ) + Abc_ObjAddFanin( pDriverNew, pFanin ); + nDupGates++; + } + else // add buffer + { + pDriverNew = Abc_NtkCreateNodeBuf( pNtk, pDriver ); + Abc_ObjAssignName( pDriverNew, Abc_ObjName(pDriver), "_buf" ); + nDupBufs++; + } + // swing the PO + Abc_ObjPatchFanin( pNode, pDriver, pDriverNew ); + assert( Abc_ObjIsCi(pDriver) || Abc_ObjFanoutNum(pDriver) > 0 ); + } +// printf( "Resolving shared CO drivers: Bufs = %d. Dups = %d.\n", nDupBufs, nDupGates ); + nTotal += nDupBufs + nDupGates; + } + Vec_PtrFree( vCoTerms ); + return nTotal; +} + +/**Function************************************************************* + + Synopsis [Inserts a new node in the order by levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_VecObjPushUniqueOrderByLevel( Vec_Ptr_t * p, Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNode1, * pNode2; + int i; + if ( Vec_PtrPushUnique(p, pNode) ) + return; + // find the p of the node + for ( i = p->nSize-1; i > 0; i-- ) + { + pNode1 = (Abc_Obj_t *)p->pArray[i ]; + pNode2 = (Abc_Obj_t *)p->pArray[i-1]; + if ( Abc_ObjRegular(pNode1)->Level <= Abc_ObjRegular(pNode2)->Level ) + break; + p->pArray[i ] = pNode2; + p->pArray[i-1] = pNode1; + } +} + + + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is the root of EXOR/NEXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeIsExorType( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNode0, * pNode1; + // check that the node is regular + assert( !Abc_ObjIsComplement(pNode) ); + // if the node is not AND, this is not EXOR + if ( !Abc_AigNodeIsAnd(pNode) ) + return 0; + // if the children are not complemented, this is not EXOR + if ( !Abc_ObjFaninC0(pNode) || !Abc_ObjFaninC1(pNode) ) + return 0; + // get children + pNode0 = Abc_ObjFanin0(pNode); + pNode1 = Abc_ObjFanin1(pNode); + // if the children are not ANDs, this is not EXOR + if ( Abc_ObjFaninNum(pNode0) != 2 || Abc_ObjFaninNum(pNode1) != 2 ) + return 0; + // this is AIG, which means the fanins should be ordered + assert( Abc_ObjFaninId0(pNode0) != Abc_ObjFaninId1(pNode1) || + Abc_ObjFaninId0(pNode1) != Abc_ObjFaninId1(pNode0) ); + // if grand children are not the same, this is not EXOR + if ( Abc_ObjFaninId0(pNode0) != Abc_ObjFaninId0(pNode1) || + Abc_ObjFaninId1(pNode0) != Abc_ObjFaninId1(pNode1) ) + return 0; + // finally, if the complemented edges are matched, this is not EXOR + if ( Abc_ObjFaninC0(pNode0) == Abc_ObjFaninC0(pNode1) || + Abc_ObjFaninC1(pNode0) == Abc_ObjFaninC1(pNode1) ) + return 0; + return 1; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeIsMuxType( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNode0, * pNode1; + // check that the node is regular + assert( !Abc_ObjIsComplement(pNode) ); + // if the node is not AND, this is not MUX + if ( !Abc_AigNodeIsAnd(pNode) ) + return 0; + // if the children are not complemented, this is not MUX + if ( !Abc_ObjFaninC0(pNode) || !Abc_ObjFaninC1(pNode) ) + return 0; + // get children + pNode0 = Abc_ObjFanin0(pNode); + pNode1 = Abc_ObjFanin1(pNode); + // if the children are not ANDs, this is not MUX + if ( !Abc_AigNodeIsAnd(pNode0) || !Abc_AigNodeIsAnd(pNode1) ) + return 0; + // otherwise the node is MUX iff it has a pair of equal grandchildren with opposite polarity + return (Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId0(pNode1) && (Abc_ObjFaninC0(pNode0) ^ Abc_ObjFaninC0(pNode1))) || + (Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId1(pNode1) && (Abc_ObjFaninC0(pNode0) ^ Abc_ObjFaninC1(pNode1))) || + (Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId0(pNode1) && (Abc_ObjFaninC1(pNode0) ^ Abc_ObjFaninC0(pNode1))) || + (Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId1(pNode1) && (Abc_ObjFaninC1(pNode0) ^ Abc_ObjFaninC1(pNode1))); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCountMuxes( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pNode; + int i; + int Counter = 0; + Abc_NtkForEachNode( pNtk, pNode, i ) + Counter += Abc_NodeIsMuxType( pNode ); + return Counter; +} + +/**Function************************************************************* + + Synopsis [Returns 1 if the node is the control type of the MUX.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeIsMuxControlType( Abc_Obj_t * pNode ) +{ + Abc_Obj_t * pNode0, * pNode1; + // check that the node is regular + assert( !Abc_ObjIsComplement(pNode) ); + // skip the node that do not have two fanouts + if ( Abc_ObjFanoutNum(pNode) != 2 ) + return 0; + // get the fanouts + pNode0 = Abc_ObjFanout( pNode, 0 ); + pNode1 = Abc_ObjFanout( pNode, 1 ); + // if they have more than one fanout, we are not interested + if ( Abc_ObjFanoutNum(pNode0) != 1 || Abc_ObjFanoutNum(pNode1) != 1 ) + return 0; + // if the fanouts have the same fanout, this is MUX or EXOR (or a redundant gate (CA)(CB)) + return Abc_ObjFanout0(pNode0) == Abc_ObjFanout0(pNode1); +} + +/**Function************************************************************* + + Synopsis [Recognizes what nodes are control and data inputs of a MUX.] + + Description [If the node is a MUX, returns the control variable C. + Assigns nodes T and E to be the then and else variables of the MUX. + Node C is never complemented. Nodes T and E can be complemented. + This function also recognizes EXOR/NEXOR gates as MUXes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NodeRecognizeMux( Abc_Obj_t * pNode, Abc_Obj_t ** ppNodeT, Abc_Obj_t ** ppNodeE ) +{ + Abc_Obj_t * pNode0, * pNode1; + assert( !Abc_ObjIsComplement(pNode) ); + assert( Abc_NodeIsMuxType(pNode) ); + // get children + pNode0 = Abc_ObjFanin0(pNode); + pNode1 = Abc_ObjFanin1(pNode); + // find the control variable +// if ( pNode1->p1 == Fraig_Not(pNode2->p1) ) + if ( Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId0(pNode1) && (Abc_ObjFaninC0(pNode0) ^ Abc_ObjFaninC0(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p1) ) + if ( Abc_ObjFaninC0(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Abc_ObjNot(Abc_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Abc_ObjNot(Abc_ObjChild1(pNode0));//pNode1->p2); + return Abc_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Abc_ObjNot(Abc_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Abc_ObjNot(Abc_ObjChild1(pNode1));//pNode2->p2); + return Abc_ObjChild0(pNode0);//pNode1->p1; + } + } +// else if ( pNode1->p1 == Fraig_Not(pNode2->p2) ) + else if ( Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId1(pNode1) && (Abc_ObjFaninC0(pNode0) ^ Abc_ObjFaninC1(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p1) ) + if ( Abc_ObjFaninC0(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Abc_ObjNot(Abc_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Abc_ObjNot(Abc_ObjChild1(pNode0));//pNode1->p2); + return Abc_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p1 is positive phase of C + *ppNodeT = Abc_ObjNot(Abc_ObjChild1(pNode0));//pNode1->p2); + *ppNodeE = Abc_ObjNot(Abc_ObjChild0(pNode1));//pNode2->p1); + return Abc_ObjChild0(pNode0);//pNode1->p1; + } + } +// else if ( pNode1->p2 == Fraig_Not(pNode2->p1) ) + else if ( Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId0(pNode1) && (Abc_ObjFaninC1(pNode0) ^ Abc_ObjFaninC0(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p2) ) + if ( Abc_ObjFaninC1(pNode0) ) + { // pNode2->p1 is positive phase of C + *ppNodeT = Abc_ObjNot(Abc_ObjChild1(pNode1));//pNode2->p2); + *ppNodeE = Abc_ObjNot(Abc_ObjChild0(pNode0));//pNode1->p1); + return Abc_ObjChild0(pNode1);//pNode2->p1; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Abc_ObjNot(Abc_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Abc_ObjNot(Abc_ObjChild1(pNode1));//pNode2->p2); + return Abc_ObjChild1(pNode0);//pNode1->p2; + } + } +// else if ( pNode1->p2 == Fraig_Not(pNode2->p2) ) + else if ( Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId1(pNode1) && (Abc_ObjFaninC1(pNode0) ^ Abc_ObjFaninC1(pNode1)) ) + { +// if ( Fraig_IsComplement(pNode1->p2) ) + if ( Abc_ObjFaninC1(pNode0) ) + { // pNode2->p2 is positive phase of C + *ppNodeT = Abc_ObjNot(Abc_ObjChild0(pNode1));//pNode2->p1); + *ppNodeE = Abc_ObjNot(Abc_ObjChild0(pNode0));//pNode1->p1); + return Abc_ObjChild1(pNode1);//pNode2->p2; + } + else + { // pNode1->p2 is positive phase of C + *ppNodeT = Abc_ObjNot(Abc_ObjChild0(pNode0));//pNode1->p1); + *ppNodeE = Abc_ObjNot(Abc_ObjChild0(pNode1));//pNode2->p1); + return Abc_ObjChild1(pNode0);//pNode1->p2; + } + } + assert( 0 ); // this is not MUX + return NULL; +} + +/**Function************************************************************* + + Synopsis [Prepares two network for a two-argument command similar to "verify".] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkPrepareTwoNtks( FILE * pErr, Abc_Ntk_t * pNtk, char ** argv, int argc, + Abc_Ntk_t ** ppNtk1, Abc_Ntk_t ** ppNtk2, int * pfDelete1, int * pfDelete2, int fCheck ) +{ + FILE * pFile; + Abc_Ntk_t * pNtk1, * pNtk2, * pNtkTemp; + int util_optind = 0; + + *pfDelete1 = 0; + *pfDelete2 = 0; + if ( argc == util_optind ) + { // use the spec + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty current network.\n" ); + return 0; + } + if ( pNtk->pSpec == NULL ) + { + fprintf( pErr, "The external spec is not given.\n" ); + return 0; + } + pFile = fopen( pNtk->pSpec, "r" ); + if ( pFile == NULL ) + { + fprintf( pErr, "Cannot open the external spec file \"%s\".\n", pNtk->pSpec ); + return 0; + } + else + fclose( pFile ); + pNtk1 = Abc_NtkDup(pNtk); + pNtk2 = Io_Read( pNtk->pSpec, Io_ReadFileType(pNtk->pSpec), fCheck, 0 ); + if ( pNtk2 == NULL ) + return 0; + *pfDelete1 = 1; + *pfDelete2 = 1; + } + else if ( argc == util_optind + 1 ) + { + if ( pNtk == NULL ) + { + fprintf( pErr, "Empty current network.\n" ); + return 0; + } + pNtk1 = Abc_NtkDup(pNtk); + pNtk2 = Io_Read( argv[util_optind], Io_ReadFileType(argv[util_optind]), fCheck, 0 ); + if ( pNtk2 == NULL ) + return 0; + *pfDelete1 = 1; + *pfDelete2 = 1; + } + else if ( argc == util_optind + 2 ) + { + pNtk1 = Io_Read( argv[util_optind], Io_ReadFileType(argv[util_optind]), fCheck, 0 ); + if ( pNtk1 == NULL ) + return 0; + pNtk2 = Io_Read( argv[util_optind+1], Io_ReadFileType(argv[util_optind+1]), fCheck, 0 ); + if ( pNtk2 == NULL ) + { + Abc_NtkDelete( pNtk1 ); + return 0; + } + *pfDelete1 = 1; + *pfDelete2 = 1; + } + else + { + fprintf( pErr, "Wrong number of arguments.\n" ); + return 0; + } + + // make sure the networks are strashed + if ( !Abc_NtkIsStrash(pNtk1) ) + { + pNtkTemp = Abc_NtkStrash( pNtk1, 0, 1, 0 ); + if ( *pfDelete1 ) + Abc_NtkDelete( pNtk1 ); + pNtk1 = pNtkTemp; + *pfDelete1 = 1; + } + if ( !Abc_NtkIsStrash(pNtk2) ) + { + pNtkTemp = Abc_NtkStrash( pNtk2, 0, 1, 0 ); + if ( *pfDelete2 ) + Abc_NtkDelete( pNtk2 ); + pNtk2 = pNtkTemp; + *pfDelete2 = 1; + } + + *ppNtk1 = pNtk1; + *ppNtk2 = pNtk2; + return 1; +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if it is an AIG with choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeCollectFanins( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanin; + int i; + Vec_PtrClear(vNodes); + Abc_ObjForEachFanin( pNode, pFanin, i ) + Vec_PtrPush( vNodes, pFanin ); +} + +/**Function************************************************************* + + Synopsis [Returns 1 if it is an AIG with choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeCollectFanouts( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes ) +{ + Abc_Obj_t * pFanout; + int i; + Vec_PtrClear(vNodes); + Abc_ObjForEachFanout( pNode, pFanout, i ) + Vec_PtrPush( vNodes, pFanout ); +} + +/**Function************************************************************* + + Synopsis [Collects all latches in the network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkCollectLatches( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vLatches; + Abc_Obj_t * pObj; + int i; + vLatches = Vec_PtrAlloc( 10 ); + Abc_NtkForEachObj( pNtk, pObj, i ) + Vec_PtrPush( vLatches, pObj ); + return vLatches; +} + +/**Function************************************************************* + + Synopsis [Procedure used for sorting the nodes in increasing order of levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeCompareLevelsIncrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) +{ + int Diff = Abc_ObjRegular(*pp1)->Level - Abc_ObjRegular(*pp2)->Level; + if ( Diff < 0 ) + return -1; + if ( Diff > 0 ) + return 1; + Diff = Abc_ObjRegular(*pp1)->Id - Abc_ObjRegular(*pp2)->Id; + if ( Diff < 0 ) + return -1; + if ( Diff > 0 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Procedure used for sorting the nodes in decreasing order of levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NodeCompareLevelsDecrease( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 ) +{ + int Diff = Abc_ObjRegular(*pp1)->Level - Abc_ObjRegular(*pp2)->Level; + if ( Diff > 0 ) + return -1; + if ( Diff < 0 ) + return 1; + Diff = Abc_ObjRegular(*pp1)->Id - Abc_ObjRegular(*pp2)->Id; + if ( Diff > 0 ) + return -1; + if ( Diff < 0 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Creates the array of fanout counters.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkFanoutCounts( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vFanNums; + Abc_Obj_t * pObj; + int i; + vFanNums = Vec_IntAlloc( 0 ); + Vec_IntFill( vFanNums, Abc_NtkObjNumMax(pNtk), -1 ); + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( Abc_ObjIsCi(pObj) || Abc_ObjIsNode(pObj) ) + Vec_IntWriteEntry( vFanNums, i, Abc_ObjFanoutNum(pObj) ); + return vFanNums; +} + +/**Function************************************************************* + + Synopsis [Collects all objects into one array.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Ptr_t * Abc_NtkCollectObjects( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Abc_Obj_t * pNode; + int i; + vNodes = Vec_PtrAlloc( 100 ); + Abc_NtkForEachObj( pNtk, pNode, i ) + Vec_PtrPush( vNodes, pNode ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Returns the array of CI IDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_NtkGetCiIds( Abc_Ntk_t * pNtk ) +{ + Vec_Int_t * vCiIds; + Abc_Obj_t * pObj; + int i; + vCiIds = Vec_IntAlloc( Abc_NtkCiNum(pNtk) ); + Abc_NtkForEachCi( pNtk, pObj, i ) + Vec_IntPush( vCiIds, pObj->Id ); + return vCiIds; +} + +/**Function************************************************************* + + Synopsis [Puts the nodes into the DFS order and reassign their IDs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkReassignIds( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vNodes; + Vec_Ptr_t * vObjsNew; + Abc_Obj_t * pNode, * pTemp, * pConst1; + int i, k; + assert( Abc_NtkIsStrash(pNtk) ); +//printf( "Total = %d. Current = %d.\n", Abc_NtkObjNumMax(pNtk), Abc_NtkObjNum(pNtk) ); + // start the array of objects with new IDs + vObjsNew = Vec_PtrAlloc( pNtk->nObjs ); + // put constant node first + pConst1 = Abc_AigConst1(pNtk); + assert( pConst1->Id == 0 ); + Vec_PtrPush( vObjsNew, pConst1 ); + // put PI nodes next + Abc_NtkForEachPi( pNtk, pNode, i ) + { + pNode->Id = Vec_PtrSize( vObjsNew ); + Vec_PtrPush( vObjsNew, pNode ); + } + // put PO nodes next + Abc_NtkForEachPo( pNtk, pNode, i ) + { + pNode->Id = Vec_PtrSize( vObjsNew ); + Vec_PtrPush( vObjsNew, pNode ); + } + // put latches and their inputs/outputs next + Abc_NtkForEachBox( pNtk, pNode, i ) + { + pNode->Id = Vec_PtrSize( vObjsNew ); + Vec_PtrPush( vObjsNew, pNode ); + Abc_ObjForEachFanin( pNode, pTemp, k ) + { + pTemp->Id = Vec_PtrSize( vObjsNew ); + Vec_PtrPush( vObjsNew, pTemp ); + } + Abc_ObjForEachFanout( pNode, pTemp, k ) + { + pTemp->Id = Vec_PtrSize( vObjsNew ); + Vec_PtrPush( vObjsNew, pTemp ); + } + } + // finally, internal nodes in the DFS order + vNodes = Abc_AigDfs( pNtk, 1, 0 ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) + { + if ( pNode == pConst1 ) + continue; + pNode->Id = Vec_PtrSize( vObjsNew ); + Vec_PtrPush( vObjsNew, pNode ); + } + Vec_PtrFree( vNodes ); + assert( Vec_PtrSize(vObjsNew) == pNtk->nObjs ); + + // update the fanin/fanout arrays + Abc_NtkForEachObj( pNtk, pNode, i ) + { + Abc_ObjForEachFanin( pNode, pTemp, k ) + pNode->vFanins.pArray[k] = pTemp->Id; + Abc_ObjForEachFanout( pNode, pTemp, k ) + pNode->vFanouts.pArray[k] = pTemp->Id; + } + + // replace the array of objs + Vec_PtrFree( pNtk->vObjs ); + pNtk->vObjs = vObjsNew; + + // rehash the AIG + Abc_AigRehash( (Abc_Aig_t *)pNtk->pManFunc ); + + // update the name manager!!! +} + +/**Function************************************************************* + + Synopsis [Detect cases when non-trivial FF matching is possible.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkDetectMatching( Abc_Ntk_t * pNtk ) +{ +/* + Abc_Obj_t * pLatch, * pFanin; + int i, nTFFs, nJKFFs; + nTFFs = nJKFFs = 0; + Abc_NtkForEachLatch( pNtk, pLatch, i ) + { + pFanin = Abc_ObjFanin0(pLatch); + if ( Abc_ObjFaninNum(pFanin) != 2 ) + continue; + if ( Abc_NodeIsExorType(pLatch) ) + { + if ( Abc_ObjFanin0(Abc_ObjFanin0(pFanin)) == pLatch || + Abc_ObjFanin1(Abc_ObjFanin0(pFanin)) == pLatch ) + nTFFs++; + } + if ( Abc_ObjFaninNum( Abc_ObjFanin0(pFanin) ) != 2 || + Abc_ObjFaninNum( Abc_ObjFanin1(pFanin) ) != 2 ) + continue; + + if ( (Abc_ObjFanin0(Abc_ObjFanin0(pFanin)) == pLatch || + Abc_ObjFanin1(Abc_ObjFanin0(pFanin)) == pLatch) && + (Abc_ObjFanin0(Abc_ObjFanin1(pFanin)) == pLatch || + Abc_ObjFanin1(Abc_ObjFanin1(pFanin)) == pLatch) ) + { + nJKFFs++; + } + } + printf( "D = %6d. T = %6d. JK = %6d. (%6.2f %%)\n", + Abc_NtkLatchNum(pNtk), nTFFs, nJKFFs, 100.0 * nJKFFs / Abc_NtkLatchNum(pNtk) ); +*/ +} + + +/**Function************************************************************* + + Synopsis [Compares the pointers.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_ObjPointerCompare( void ** pp1, void ** pp2 ) +{ + if ( *pp1 < *pp2 ) + return -1; + if ( *pp1 > *pp2 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Adjusts the copy pointers.] + + Description [This procedure assumes that the network was transformed + into another network, which was in turn transformed into yet another + network. It makes the pCopy pointers of the original network point to + the objects of the yet another network.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTransferCopy( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_ObjIsNet(pObj) ) + pObj->pCopy = pObj->pCopy? Abc_ObjCopyCond(pObj->pCopy) : NULL; +} + + +/**Function************************************************************* + + Synopsis [Increaments the cut counter.] + + Description [Returns 1 if it becomes equal to the ref counter.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Abc_ObjCrossCutInc( Abc_Obj_t * pObj ) +{ +// pObj->pCopy = (void *)(((int)pObj->pCopy)++); + int Value = (int)(ABC_PTRINT_T)pObj->pCopy; + pObj->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)(Value + 1); + return (int)(ABC_PTRINT_T)pObj->pCopy == Abc_ObjFanoutNum(pObj); +} + +/**Function************************************************************* + + Synopsis [Computes cross-cut of the circuit.] + + Description [Returns 1 if it is the last visit to the node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCrossCut_rec( Abc_Obj_t * pObj, int * pnCutSize, int * pnCutSizeMax ) +{ + Abc_Obj_t * pFanin; + int i, nDecrem = 0; + int fReverse = 0; + if ( Abc_ObjIsCi(pObj) ) + return 0; + // if visited, increment visit counter + if ( Abc_NodeIsTravIdCurrent( pObj ) ) + return Abc_ObjCrossCutInc( pObj ); + Abc_NodeSetTravIdCurrent( pObj ); + // visit the fanins + if ( !Abc_ObjIsCi(pObj) ) + { + if ( fReverse ) + { + Abc_ObjForEachFanin( pObj, pFanin, i ) + { + pFanin = Abc_ObjFanin( pObj, Abc_ObjFaninNum(pObj) - 1 - i ); + nDecrem += Abc_NtkCrossCut_rec( pFanin, pnCutSize, pnCutSizeMax ); + } + } + else + { + Abc_ObjForEachFanin( pObj, pFanin, i ) + nDecrem += Abc_NtkCrossCut_rec( pFanin, pnCutSize, pnCutSizeMax ); + } + } + // count the node + (*pnCutSize)++; + if ( *pnCutSizeMax < *pnCutSize ) + *pnCutSizeMax = *pnCutSize; + (*pnCutSize) -= nDecrem; + return Abc_ObjCrossCutInc( pObj ); +} + +/**Function************************************************************* + + Synopsis [Computes cross-cut of the circuit.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCrossCut( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int nCutSize = 0, nCutSizeMax = 0; + int i; + Abc_NtkCleanCopy( pNtk ); + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + Abc_NtkCrossCut_rec( pObj, &nCutSize, &nCutSizeMax ); + nCutSize--; + } + assert( nCutSize == 0 ); + printf( "Max cross cut size = %6d. Ratio = %6.2f %%\n", nCutSizeMax, 100.0 * nCutSizeMax/Abc_NtkObjNum(pNtk) ); + return nCutSizeMax; +} + + +/**Function************************************************************* + + Synopsis [Prints all 3-var functions.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrint256() +{ + FILE * pFile; + unsigned i; + pFile = fopen( "4varfs.txt", "w" ); + for ( i = 1; i < (1<<16)-1; i++ ) + { + fprintf( pFile, "read_truth " ); + Extra_PrintBinary( pFile, &i, 16 ); + fprintf( pFile, "; clp; st; w 1.blif; map; cec 1.blif\n" ); + } + fclose( pFile ); +} + + +static int * pSupps; + +/**Function************************************************************* + + Synopsis [Compares the supergates by their level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkCompareConesCompare( int * pNum1, int * pNum2 ) +{ + if ( pSupps[*pNum1] > pSupps[*pNum2] ) + return -1; + if ( pSupps[*pNum1] < pSupps[*pNum2] ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Analyze choice node support.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCompareCones( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vSupp, * vNodes, * vReverse; + Abc_Obj_t * pObj, * pTemp; + int Iter, i, k, Counter, CounterCos, CounterCosNew; + int * pPerms; + + // sort COs by support size + pPerms = ABC_ALLOC( int, Abc_NtkCoNum(pNtk) ); + pSupps = ABC_ALLOC( int, Abc_NtkCoNum(pNtk) ); + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pPerms[i] = i; + vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); + pSupps[i] = Vec_PtrSize(vSupp); + Vec_PtrFree( vSupp ); + } + qsort( (void *)pPerms, (size_t)Abc_NtkCoNum(pNtk), sizeof(int), (int (*)(const void *, const void *)) Abc_NtkCompareConesCompare ); + + // consider COs in this order + Iter = 0; + Abc_NtkForEachCo( pNtk, pObj, i ) + { + pObj = Abc_NtkCo( pNtk, pPerms[i] ); + if ( pObj->fMarkA ) + continue; + Iter++; + + vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); + vNodes = Abc_NtkDfsNodes( pNtk, &pObj, 1 ); + vReverse = Abc_NtkDfsReverseNodesContained( pNtk, (Abc_Obj_t **)Vec_PtrArray(vSupp), Vec_PtrSize(vSupp) ); + // count the number of nodes in the reverse cone + Counter = 0; + for ( k = 1; k < Vec_PtrSize(vReverse) - 1; k++ ) + for ( pTemp = (Abc_Obj_t *)Vec_PtrEntry(vReverse, k); pTemp; pTemp = (Abc_Obj_t *)pTemp->pCopy ) + Counter++; + CounterCos = CounterCosNew = 0; + for ( pTemp = (Abc_Obj_t *)Vec_PtrEntryLast(vReverse); pTemp; pTemp = (Abc_Obj_t *)pTemp->pCopy ) + { + assert( Abc_ObjIsCo(pTemp) ); + CounterCos++; + if ( pTemp->fMarkA == 0 ) + CounterCosNew++; + pTemp->fMarkA = 1; + } + // print statistics + printf( "%4d CO %5d : Supp = %5d. Lev = %3d. Cone = %5d. Rev = %5d. COs = %3d (%3d).\n", + Iter, pPerms[i], Vec_PtrSize(vSupp), Abc_ObjLevel(Abc_ObjFanin0(pObj)), Vec_PtrSize(vNodes), Counter, CounterCos, CounterCosNew ); + + if ( Vec_PtrSize(vSupp) < 10 ) + { + // free arrays + Vec_PtrFree( vSupp ); + Vec_PtrFree( vNodes ); + Vec_PtrFree( vReverse ); + break; + } + + // free arrays + Vec_PtrFree( vSupp ); + Vec_PtrFree( vNodes ); + Vec_PtrFree( vReverse ); + + } + Abc_NtkForEachCo( pNtk, pObj, i ) + pObj->fMarkA = 0; + + ABC_FREE( pPerms ); + ABC_FREE( pSupps ); +} + +/**Function************************************************************* + + Synopsis [Analyze choice node support.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkCompareSupports( Abc_Ntk_t * pNtk ) +{ + Vec_Ptr_t * vSupp; + Abc_Obj_t * pObj, * pTemp; + int i, nNodesOld; + assert( Abc_NtkIsStrash(pNtk) ); + Abc_AigForEachAnd( pNtk, pObj, i ) + { + if ( !Abc_AigNodeIsChoice(pObj) ) + continue; + + vSupp = Abc_NtkNodeSupport( pNtk, &pObj, 1 ); + nNodesOld = Vec_PtrSize(vSupp); + Vec_PtrFree( vSupp ); + + for ( pTemp = (Abc_Obj_t *)pObj->pData; pTemp; pTemp = (Abc_Obj_t *)pTemp->pData ) + { + vSupp = Abc_NtkNodeSupport( pNtk, &pTemp, 1 ); + if ( nNodesOld != Vec_PtrSize(vSupp) ) + printf( "Choice orig = %3d Choice new = %3d\n", nNodesOld, Vec_PtrSize(vSupp) ); + Vec_PtrFree( vSupp ); + } + } +} + +/**Function************************************************************* + + Synopsis [Complements the constraint outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkInvertConstraints( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + if ( Abc_NtkConstrNum(pNtk) == 0 ) + return; + Abc_NtkForEachPo( pNtk, pObj, i ) + { + if ( i >= Abc_NtkPoNum(pNtk) - Abc_NtkConstrNum(pNtk) ) + Abc_ObjXorFaninC( pObj, 0 ); + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkPrintCiLevels( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + Abc_NtkForEachCi( pNtk, pObj, i ) + printf( "%c=%d ", 'a'+i, pObj->Level ); + printf( "\n" ); +} + + +/**Function************************************************************* + + Synopsis [Returns 1 if all other fanouts of pFanin are below pNode.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkAddBuffsEval( Abc_Obj_t * pNode, Abc_Obj_t * pFanin ) +{ + Abc_Obj_t * pFanout; + int i; + Abc_ObjForEachFanout( pFanin, pFanout, i ) + if ( pFanout != pNode && pFanout->Level >= pNode->Level ) + return 0; + return 1; +} +/**Function************************************************************* + + Synopsis [Returns 1 if there exist a fanout of pFanin higher than pNode.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkAddBuffsEval2( Abc_Obj_t * pNode, Abc_Obj_t * pFanin ) +{ + Abc_Obj_t * pFanout; + int i; + Abc_ObjForEachFanout( pFanin, pFanout, i ) + if ( pFanout != pNode && pFanout->Level > pNode->Level ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Obj_t * Abc_NtkAddBuffsOne( Vec_Ptr_t * vBuffs, Abc_Obj_t * pFanin, int Level, int nLevelMax ) +{ + Abc_Obj_t * pBuffer; + assert( Level - 1 >= Abc_ObjLevel(pFanin) ); + pBuffer = (Abc_Obj_t *)Vec_PtrEntry( vBuffs, Abc_ObjId(pFanin) * nLevelMax + Level ); + if ( pBuffer == NULL ) + { + if ( Level - 1 == Abc_ObjLevel(pFanin) ) + pBuffer = pFanin; + else + pBuffer = Abc_NtkAddBuffsOne( vBuffs, pFanin, Level - 1, nLevelMax ); + pBuffer = Abc_NtkCreateNodeBuf( Abc_ObjNtk(pFanin), pBuffer ); + Vec_PtrWriteEntry( vBuffs, Abc_ObjId(pFanin) * nLevelMax + Level, pBuffer ); + } + return pBuffer; +} +Abc_Ntk_t * Abc_NtkAddBuffsInt( Abc_Ntk_t * pNtkInit, int fReverse, int nImprove, int fVerbose ) +{ + Vec_Ptr_t * vBuffs; + Abc_Ntk_t * pNtk = Abc_NtkDup( pNtkInit ); + Abc_Obj_t * pObj, * pFanin, * pBuffer; + int i, k, Iter, nLevelMax = Abc_NtkLevel( pNtk ); + Abc_NtkForEachCo( pNtk, pObj, i ) + pObj->Level = nLevelMax + 1; + if ( fReverse ) + { + Vec_Ptr_t * vNodes = Abc_NtkDfs( pNtk, 1 ); + assert( nLevelMax < (1<<18) ); + Vec_PtrForEachEntryReverse( Abc_Obj_t *, vNodes, pObj, i ) + { + pObj->Level = (1<<18); + Abc_ObjForEachFanout( pObj, pFanin, k ) + pObj->Level = Abc_MinInt( pFanin->Level - 1, pObj->Level ); + assert( pObj->Level > 0 ); + } + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->Level = 0; + + // move the nodes down one step at a time + for ( Iter = 0; Iter < nImprove; Iter++ ) + { + int Counter = 0, TotalGain = 0; + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + { + int CountGain = -1; + assert( pObj->Level > 0 ); + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + assert( pFanin->Level < pObj->Level ); + if ( pFanin->Level + 1 == pObj->Level ) + break; + } + if ( k < Abc_ObjFaninNum(pObj) ) // cannot move + continue; + Abc_ObjForEachFanin( pObj, pFanin, k ) + CountGain += Abc_NtkAddBuffsEval( pObj, pFanin ); + if ( CountGain >= 0 ) // can move + { + pObj->Level--; + Counter++; + TotalGain += CountGain; + } + } + if ( fVerbose ) + printf( "Shifted %5d nodes down with total gain %5d.\n", Counter, TotalGain ); + if ( Counter == 0 ) + break; + } + Vec_PtrFree( vNodes ); + } + else + { + // move the nodes up one step at a time + Vec_Ptr_t * vNodes = Abc_NtkDfs( pNtk, 1 ); + for ( Iter = 0; Iter < nImprove; Iter++ ) + { + int Counter = 0, TotalGain = 0; + Vec_PtrForEachEntryReverse( Abc_Obj_t *, vNodes, pObj, i ) + { + int CountGain = 1; + assert( pObj->Level <= (unsigned)nLevelMax ); + Abc_ObjForEachFanout( pObj, pFanin, k ) + { + assert( pFanin->Level > pObj->Level ); + if ( pFanin->Level == pObj->Level + 1 ) + break; + } + if ( k < Abc_ObjFanoutNum(pObj) ) // cannot move + continue; + Abc_ObjForEachFanin( pObj, pFanin, k ) + CountGain -= !Abc_NtkAddBuffsEval2( pObj, pFanin ); + if ( CountGain >= 0 ) // can move + { + pObj->Level++; + Counter++; + TotalGain += CountGain; + } + } + if ( fVerbose ) + printf( "Shifted %5d nodes up with total gain %5d.\n", Counter, TotalGain ); + if ( Counter == 0 ) + break; + } + Vec_PtrFree( vNodes ); + } + vBuffs = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) * (nLevelMax + 1) ); + Abc_NtkForEachObj( pNtk, pObj, i ) + { + if ( i == Vec_PtrSize(vBuffs) / (nLevelMax + 1) ) + break; + if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsCo(pObj) ) + continue; + Abc_ObjForEachFanin( pObj, pFanin, k ) + { + assert( Abc_ObjLevel(pObj) - 1 >= Abc_ObjLevel(pFanin) ); + if ( Abc_ObjLevel(pObj) - 1 == Abc_ObjLevel(pFanin) ) + continue; + pBuffer = Abc_NtkAddBuffsOne( vBuffs, pFanin, Abc_ObjLevel(pObj) - 1, nLevelMax ); + Abc_ObjPatchFanin( pObj, pFanin, pBuffer ); + } + } + Vec_PtrFree( vBuffs ); + Abc_NtkForEachCo( pNtk, pObj, i ) + pObj->Level = 0; + return pNtk; +} +Abc_Ntk_t * Abc_NtkAddBuffs( Abc_Ntk_t * pNtkInit, int fDirect, int fReverse, int nImprove, int fVerbose ) +{ + Abc_Ntk_t * pNtkD, * pNtkR; + if ( fDirect ) + return Abc_NtkAddBuffsInt( pNtkInit, 0, nImprove, fVerbose ); + if ( fReverse ) + return Abc_NtkAddBuffsInt( pNtkInit, 1, nImprove, fVerbose ); + pNtkD = Abc_NtkAddBuffsInt( pNtkInit, 0, nImprove, fVerbose ); + pNtkR = Abc_NtkAddBuffsInt( pNtkInit, 1, nImprove, fVerbose ); + if ( Abc_NtkNodeNum(pNtkD) < Abc_NtkNodeNum(pNtkR) ) + { + Abc_NtkDelete( pNtkR ); + return pNtkD; + } + else + { + Abc_NtkDelete( pNtkD ); + return pNtkR; + } +} + +/**Function************************************************************* + + Synopsis [Computes max delay using log(n) delay model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Abc_NtkComputeDelay( Abc_Ntk_t * pNtk ) +{ + static double GateDelays[20] = { 1.00, 1.00, 2.00, 2.58, 3.00, 3.32, 3.58, 3.81, 4.00, 4.17, 4.32, 4.46, 4.58, 4.70, 4.81, 4.91, 5.00, 5.09, 5.17, 5.25 }; + Vec_Ptr_t * vNodes; + Abc_Obj_t * pObj, * pFanin; + float DelayMax, Delays[15] = {0}; + int nFaninMax, i, k; + // calculate relative gate delays + nFaninMax = Abc_NtkGetFaninMax( pNtk ); + assert( nFaninMax > 1 && nFaninMax < 15 ); + for ( i = 0; i <= nFaninMax; i++ ) + Delays[i] = GateDelays[i]/GateDelays[nFaninMax]; + // set max CI delay + Abc_NtkForEachCi( pNtk, pObj, i ) + pObj->dTemp = 0.0; + // compute delays for each node + vNodes = Abc_NtkDfs( pNtk, 1 ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + { + pObj->dTemp = 0.0; + Abc_ObjForEachFanin( pObj, pFanin, k ) + pObj->dTemp = Abc_MaxFloat( pObj->dTemp, pFanin->dTemp ); + pObj->dTemp += Delays[Abc_ObjFaninNum(pObj)]; + } + Vec_PtrFree( vNodes ); + DelayMax = 0.0; + // find max CO delay + Abc_NtkForEachCo( pNtk, pObj, i ) + DelayMax = Abc_MaxFloat( DelayMax, Abc_ObjFanin0(pObj)->dTemp ); + return DelayMax; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NodeSopToCubes( Abc_Obj_t * pNodeOld, Abc_Ntk_t * pNtkNew, int fXor ) +{ + Abc_Obj_t * pNodeOr, * pNodeNew, * pFanin; + char * pCube, * pSop = (char *)pNodeOld->pData; + int v, Value, nVars = Abc_ObjFaninNum(pNodeOld), nFanins; + // create the root node + if ( Abc_SopGetCubeNum(pSop) < 2 ) + { + pNodeNew = Abc_NtkDupObj( pNtkNew, pNodeOld, 0 ); + Abc_ObjForEachFanin( pNodeOld, pFanin, v ) + Abc_ObjAddFanin( pNodeNew, pFanin->pCopy ); + assert( pNodeOld->pCopy == pNodeNew ); + return; + } + // add the OR gate + pNodeOr = Abc_NtkCreateNode( pNtkNew ); + if ( fXor ) + pNodeOr->pData = Abc_SopCreateXorSpecial( (Mem_Flex_t *)pNtkNew->pManFunc, Abc_SopGetCubeNum(pSop) ); + else + pNodeOr->pData = Abc_SopCreateOr( (Mem_Flex_t *)pNtkNew->pManFunc, Abc_SopGetCubeNum(pSop), NULL ); + // check the logic function of the node + Abc_SopForEachCube( pSop, nVars, pCube ) + { + nFanins = 0; + Abc_CubeForEachVar( pCube, Value, v ) + if ( Value == '0' || Value == '1' ) + nFanins++; + if ( nFanins == 0 ) // const1 cube in ESOP + { + pNodeNew = Abc_NtkCreateNodeConst1( pNtkNew ); + Abc_ObjAddFanin( pNodeOr, pNodeNew ); + continue; + } + assert( nFanins > 0 ); + // create node + pNodeNew = Abc_NtkCreateNode( pNtkNew ); + pNodeNew->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, nFanins, NULL ); + nFanins = 0; + Abc_CubeForEachVar( pCube, Value, v ) + { + if ( Value != '0' && Value != '1' ) + continue; + Abc_ObjAddFanin( pNodeNew, Abc_ObjFanin(pNodeOld, v)->pCopy ); + if ( Value == '0' ) + Abc_SopComplementVar( (char *)pNodeNew->pData, nFanins ); + nFanins++; + } + Abc_ObjAddFanin( pNodeOr, pNodeNew ); + } + // check the complement + if ( Abc_SopIsComplement(pSop) ) + Abc_SopComplement( (char *)pNodeOr->pData ); + // mark the old node with the new one + assert( pNodeOld->pCopy == NULL ); + pNodeOld->pCopy = pNodeOr; +} +Abc_Ntk_t * Abc_NtkSopToCubes( Abc_Ntk_t * pNtk, int fXor ) +{ + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pNode; + Vec_Ptr_t * vNodes; + int i; + assert( Abc_NtkIsSopLogic(pNtk) ); + Abc_NtkCleanCopy( pNtk ); + pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP ); + // perform conversion in the topological order + vNodes = Abc_NtkDfs( pNtk, 0 ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) + Abc_NodeSopToCubes( pNode, pNtkNew, fXor ); + Vec_PtrFree( vNodes ); + // make sure everything is okay + Abc_NtkFinalize( pNtk, pNtkNew ); + if ( !Abc_NtkCheck( pNtkNew ) ) + { + printf( "Abc_NtkSopToCubes: The network check has failed.\n" ); + Abc_NtkDelete( pNtkNew ); + return NULL; + } + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Creates precomputed reverse topological order for each node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static inline int Abc_NtkTopoHasBeg( Abc_Obj_t * p ) { return Vec_IntEntry(p->pNtk->vTopo, 2*Abc_ObjId(p) ); } +static inline int Abc_NtkTopoHasEnd( Abc_Obj_t * p ) { return Vec_IntEntry(p->pNtk->vTopo, 2*Abc_ObjId(p)+1); } + +static inline void Abc_NtkTopoSetBeg( Abc_Obj_t * p ) { Vec_IntWriteEntry(p->pNtk->vTopo, 2*Abc_ObjId(p) , Vec_IntSize(p->pNtk->vTopo)); } +static inline void Abc_NtkTopoSetEnd( Abc_Obj_t * p ) { Vec_IntWriteEntry(p->pNtk->vTopo, 2*Abc_ObjId(p)+1, Vec_IntSize(p->pNtk->vTopo)); } + +void Abc_NtkReverseTopoOrder_rec( Abc_Obj_t * pObj, int fThisIsPivot ) +{ + Abc_Obj_t * pNext, * pPivot = NULL; + int i; + if ( Abc_NodeIsTravIdCurrent( pObj ) ) + return; + Abc_NodeSetTravIdCurrent( pObj ); + if ( Abc_ObjIsPo(pObj) ) + { + Vec_IntPush( pObj->pNtk->vTopo, Abc_ObjId(pObj) ); + return; + } + assert( Abc_ObjIsNode(pObj) ); + // mark begining + if ( fThisIsPivot ) + Abc_NtkTopoSetBeg( pObj ); + // find fanout without topo + Abc_ObjForEachFanout( pObj, pNext, i ) + if ( !Abc_NtkTopoHasBeg(pNext) ) + { + assert( !Abc_NtkTopoHasEnd(pNext) ); + Abc_NtkReverseTopoOrder_rec( pNext, 1 ); + pPivot = pNext; + break; + } + Abc_ObjForEachFanout( pObj, pNext, i ) + if ( pNext != pPivot ) + Abc_NtkReverseTopoOrder_rec( pNext, 0 ); + // mark end + if ( fThisIsPivot ) + Abc_NtkTopoSetEnd( pObj ); + // save current node + Vec_IntPush( pObj->pNtk->vTopo, Abc_ObjId(pObj) ); +} +void Abc_NtkReverseTopoOrder( Abc_Ntk_t * p ) +{ + Abc_Obj_t * pObj; + int i; + assert( p->vTopo == NULL ); + p->vTopo = Vec_IntAlloc( 10 * Abc_NtkObjNumMax(p) ); + Vec_IntFill( p->vTopo, 2 * Abc_NtkObjNumMax(p), 0 ); + Abc_NtkForEachNode( p, pObj, i ) + { + if ( Abc_NtkTopoHasBeg(pObj) ) + continue; + Abc_NtkIncrementTravId( p ); + Abc_NtkReverseTopoOrder_rec( pObj, 1 ); + } + printf( "Nodes = %d. Size = %d. Ratio = %f.\n", + Abc_NtkNodeNum(p), Vec_IntSize(p->vTopo), 1.0*Vec_IntSize(p->vTopo)/Abc_NtkNodeNum(p) ); +} + +void Abc_NtkReverse_rec( Abc_Obj_t * pObj, Vec_Int_t * vVisited ) +{ + Abc_Obj_t * pNext; + int i; + if ( Abc_NodeIsTravIdCurrent( pObj ) ) + return; + Abc_NodeSetTravIdCurrent( pObj ); + Abc_ObjForEachFanout( pObj, pNext, i ) + Abc_NtkReverse_rec( pNext, vVisited ); + Vec_IntPush( vVisited, Abc_ObjId(pObj) ); +} +void Abc_NtkReverseTopoOrderTest( Abc_Ntk_t * p ) +{ + Vec_Int_t * vVisited; + Abc_Obj_t * pObj; + int i;//, k, iBeg, iEnd; + abctime clk = Abc_Clock(); + Abc_NtkReverseTopoOrder( p ); +/* + printf( "Reverse topological order for nodes:\n" ); + Abc_NtkForEachNode( p, pObj, i ) + { + iBeg = Abc_NtkTopoHasBeg( pObj ); + iEnd = Abc_NtkTopoHasEnd( pObj ); + printf( "Node %4d : ", Abc_ObjId(pObj) ); + for ( k = iEnd - 1; k >= iBeg; k-- ) + printf( "%d ", Vec_IntEntry(p->vTopo, k) ); + printf( "\n" ); + } +*/ + Vec_IntFreeP( &p->vTopo ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + // compute regular fanout orders + clk = Abc_Clock(); + vVisited = Vec_IntAlloc( 1000 ); + Abc_NtkForEachNode( p, pObj, i ) + { + Vec_IntClear( vVisited ); + Abc_NtkIncrementTravId( p ); + Abc_NtkReverse_rec( pObj, vVisited ); + } + Vec_IntFree( vVisited ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); +} + +/**Function************************************************************* + + Synopsis [Converts multi-output PLA into an AIG with logic sharing.] + + Description [The first argument is an array of char*-strings representing + individual output of a multi-output PLA. The number of inputs (nInputs) + and the number of outputs (nOutputs) are the second and third arguments. + This procedure returns the AIG manager with the given number of inputs + and outputs representing the PLA as a logic network with sharing. + + For example, if the original PLA is + 1000 10 + 0110 01 + 0011 01 + the individual PLA for each the two outputs should be + 1000 1 + and + 0110 1 + 0011 1 + + Reprsentation in terms of two char*-strings will be: + char * pPlas[2] = { "1000 1\n", "0110 1\n0011 1\n" }; + The call to the procedure may look as follows: + Abc_Ntk_t * pNtkAig = Abc_NtkFromPla( pPlas, 4, 2 );] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkFromPla( char ** pPlas, int nInputs, int nOutputs ) +{ + Fxu_Data_t Params, * p = &Params; + Abc_Ntk_t * pNtkSop, * pNtkAig; + Abc_Obj_t * pNode, * pFanin; + int i, k; + // allocate logic network with SOP local functions + pNtkSop = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); + pNtkSop->pName = Extra_FileNameGeneric("pla"); + // create primary inputs/outputs + for ( i = 0; i < nInputs; i++ ) + Abc_NtkCreatePi( pNtkSop ); + for ( i = 0; i < nOutputs; i++ ) + Abc_NtkCreatePo( pNtkSop ); + Abc_NtkAddDummyPiNames( pNtkSop ); + Abc_NtkAddDummyPoNames( pNtkSop ); + // create internal nodes + for ( i = 0; i < nOutputs; i++ ) + { + pNode = Abc_NtkCreateNode( pNtkSop ); + Abc_NtkForEachPi( pNtkSop, pFanin, k ) + Abc_ObjAddFanin( pNode, pFanin ); + pNode->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkSop->pManFunc, pPlas[i] ); + Abc_ObjAddFanin( Abc_NtkPo(pNtkSop, i), pNode ); + // check that the number of inputs is the same + assert( Abc_SopGetVarNum((char*)pNode->pData) == nInputs ); + } + if ( !Abc_NtkCheck( pNtkSop ) ) + fprintf( stdout, "Abc_NtkFromPla(): Network check has failed.\n" ); + // perform fast_extract + Abc_NtkSetDefaultFxParams( p ); + Abc_NtkFastExtract( pNtkSop, p ); + Abc_NtkFxuFreeInfo( p ); + // convert to an AIG + pNtkAig = Abc_NtkStrash( pNtkSop, 0, 1, 0 ); + Abc_NtkDelete( pNtkSop ); + return pNtkAig; +} +void Abc_NtkFromPlaTest() +{ + char * pPlas[2] = { "1000 1\n", "0110 1\n0011 1\n" }; + Abc_Ntk_t * pNtkAig = Abc_NtkFromPla( pPlas, 4, 2 ); + Io_WriteBlifLogic( pNtkAig, "temp.blif", 0 ); + Abc_NtkDelete( pNtkAig ); +} + +/**Function************************************************************* + + Synopsis [Checks if the logic network is in the topological order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkSplitSop( Abc_Ntk_t * pNtk, int nCubesMax, int fVerbose ) +{ + Vec_Ptr_t * vNodes; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin, * pObjNew, * pObjNewRoot; + int i, k, j, nCubes, nCubesThis, nSplits; + char * pSopStr, * pSopStr2, * pTempSop, Symb; + if ( pNtk == NULL ) + return NULL; + assert( !Abc_NtkIsStrash(pNtk) && !Abc_NtkIsNetlist(pNtk) ); + // start the network + pNtkNew = Abc_NtkStartFrom( pNtk, pNtk->ntkType, pNtk->ntkFunc ); + // copy the internal nodes + vNodes = Abc_NtkDfs( pNtk, 0 ); + Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) + { + assert( Abc_ObjIsNode(pObj) ); + pObjNewRoot = Abc_NtkDupObj( pNtkNew, pObj, 0 ); + nCubes = Abc_SopGetCubeNum( (char *)pObj->pData ); + if ( nCubes <= nCubesMax ) + { + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + continue; + } + nSplits = (nCubes / nCubesMax) + (int)(nCubes % nCubesMax > 0); + pSopStr = (char *)pObjNewRoot->pData; + pObjNewRoot->pData = Abc_SopCreateOr((Mem_Flex_t *)pNtkNew->pManFunc, nSplits, NULL); + if ( Abc_SopIsComplement(pSopStr) ) + { + Abc_SopComplement( pSopStr ); + Abc_SopComplement( (char *)pObjNewRoot->pData ); + } + pTempSop = (char *)pObj->pData; pObj->pData = (char *)"?"; + for ( j = 0; j < nSplits; j++ ) + { + // clone the node + pObjNew = Abc_NtkDupObj( pNtkNew, pObj, 0 ); + Abc_ObjAddFanin( pObjNewRoot, pObjNew ); + // get its cubes + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + // create SOP for this node + nCubesThis = (j < nCubes / nCubesMax) ? nCubesMax : nCubes % nCubesMax; + pSopStr2 = pSopStr + (Abc_ObjFaninNum(pObj) + 3) * nCubesThis; + Symb = *pSopStr2; *pSopStr2 = 0; + pObjNew->pData = Abc_SopRegister( (Mem_Flex_t *)pNtkNew->pManFunc, pSopStr ); + *pSopStr2 = Symb; + pSopStr = pSopStr2; + } + // update + pObj->pData = pTempSop; + pObj->pCopy = pObjNewRoot; + } + Vec_PtrFree( vNodes ); + Abc_NtkFinalize( pNtk, pNtkNew ); + // check correctness + if ( !Abc_NtkCheck( pNtkNew ) ) + fprintf( stdout, "Abc_NtkDup(): Network check has failed.\n" ); + pNtk->pCopy = pNtkNew; + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Checks if the logic network is in the topological order.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkIsTopo( Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj, * pFanin; + int i, k, Counter = 0; + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachCi( pNtk, pObj, i ) + Abc_NodeSetTravIdCurrent(pObj); + Abc_NtkForEachNode( pNtk, pObj, i ) + { + // check if fanins are in the topo order + Abc_ObjForEachFanin( pObj, pFanin, k ) + if ( !Abc_NodeIsTravIdCurrent(pFanin) ) + break; + if ( k != Abc_ObjFaninNum(pObj) ) + { + if ( Counter++ == 0 ) + printf( "Node %d is out of topo order.\n", Abc_ObjId(pObj) ); + } + Abc_NodeSetTravIdCurrent(pObj); + } + if ( Counter ) + printf( "Topological order does not hold for %d internal nodes.\n", Counter ); + return (int)(Counter == 0); +} + +/**Function************************************************************* + + Synopsis [Transfers phase information to the new network.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_NtkTransferPhases( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk ) +{ + Abc_Obj_t * pObj; + int i; + assert( pNtk->vPhases != NULL ); + assert( Vec_IntSize(pNtk->vPhases) == Abc_NtkObjNumMax(pNtk) ); + assert( pNtkNew->vPhases == NULL ); + pNtkNew->vPhases = Vec_IntStart( Abc_NtkObjNumMax(pNtkNew) ); + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( pObj->pCopy && !Abc_ObjIsNone( (Abc_Obj_t *)pObj->pCopy ) ) + Vec_IntWriteEntry( pNtkNew->vPhases, Abc_ObjId( (Abc_Obj_t *)pObj->pCopy ), Vec_IntEntry(pNtk->vPhases, i) ); +} + +/**Function************************************************************* + + Synopsis [Starts a new network using existing network as a model.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkDeriveWithOnePo( Abc_Ntk_t * pNtk, Vec_Int_t * vNodeIds, Vec_Int_t * vNodeValues ) +{ + int fCopyNames = 1; + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin, * pObjNew, * pOutputNew; + Vec_Ptr_t * vFanins = Vec_PtrAlloc( 100 ); + int i, k, Id, Value; + // start the network + pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 ); + // duplicate the name and the spec + pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); + pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); + // clean the node copy fields + Abc_NtkCleanCopy( pNtk ); + // map the constant nodes + if ( Abc_NtkIsStrash(pNtk) && Abc_NtkIsStrash(pNtkNew) ) + Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); + // clone CIs/CIs/boxes + Abc_NtkForEachPi( pNtk, pObj, i ) + Abc_NtkDupObj( pNtkNew, pObj, fCopyNames ); + //Abc_NtkForEachPo( pNtk, pObj, i ) + // Abc_NtkDupObj( pNtkNew, pObj, fCopyNames ); + // create one PO + pObjNew = Abc_NtkCreateObj( pNtkNew, ABC_OBJ_PO ); + Abc_ObjAssignName( pObjNew, "monitor", NULL ); + // create boxes + Abc_NtkForEachBox( pNtk, pObj, i ) + Abc_NtkDupBox( pNtkNew, pObj, fCopyNames ); + + // duplicate nodes (CIs/COs/latches are already duplicated) + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( pObj->pCopy == NULL && !Abc_ObjIsPo(pObj) ) + Abc_NtkDupObj(pNtkNew, pObj, 0); + // reconnect all objects except boxes (they are already connected) and POs (they will be connected later) + Abc_NtkForEachObj( pNtk, pObj, i ) + if ( !Abc_ObjIsPo(pObj) && !Abc_ObjIsBox(pObj) && !Abc_ObjIsBo(pObj) ) + Abc_ObjForEachFanin( pObj, pFanin, k ) + Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy ); + + // AND nodes (with interters if needed) + pOutputNew = NULL; + Vec_IntForEachEntryTwo( vNodeIds, vNodeValues, Id, Value, i ) + { + pObjNew = Abc_NtkObj( pNtk, Id )->pCopy; + if ( Value == 0 ) // negative polarity - add inverter + pObjNew = Abc_NtkCreateNodeInv( pNtkNew, pObjNew ); + if ( pOutputNew == NULL ) + pOutputNew = pObjNew; + else + { + Vec_PtrFillTwo( vFanins, 2, pOutputNew, pObjNew ); + pOutputNew = Abc_NtkCreateNodeAnd( pNtkNew, vFanins ); + } + } + Vec_PtrFree( vFanins ); + // create the only POs, which is the AND of the corresponding nodes + Abc_ObjAddFanin( Abc_NtkPo(pNtkNew, 0), pOutputNew ); + + // check that the CI/CO/latches are copied correctly + assert( Abc_NtkPoNum(pNtkNew) == 1 ); + assert( Abc_NtkCiNum(pNtkNew) == Abc_NtkCiNum(pNtk) ); + assert( Abc_NtkLatchNum(pNtkNew) == Abc_NtkLatchNum(pNtk) ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [Derives the AIG representing a property.] + + Description [Given is a sequential logic network (Abc_Ntk_t) and + an array of nodes (vector of object IDs) and their values (vector of 0s or 1s). + This procedure creates a sequential AIG (Abc_Ntk_t), which can be given to a + sequential model checker (in particular "pdr") to prove that the given + combination of values never appears at the intenal nodes of the network, + or produce a counter-example showing that it can appear.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreatePropertyMonitor( Abc_Ntk_t * p, Vec_Int_t * vNodeIds, Vec_Int_t * vNodeValues ) +{ + Abc_Ntk_t * pMonitor, * pStrashed, * pResult; + // sequential cleanup parameters + int fLatchConst = 1; + int fLatchEqual = 1; + int fSaveNames = 1; + int fUseMvSweep = 0; + int nFramesSymb = 1; + int nFramesSatur = 512; + int fVerbose = 0; + int fVeryVerbose = 0; + // expecting sequential logic network + assert( Abc_NtkIsLogic(p) ); + assert( Abc_NtkLatchNum(p) > 0 ); + assert( Vec_IntSize(vNodeIds) > 0 ); + assert( Vec_IntSize(vNodeIds) == Vec_IntSize(vNodeValues) ); + // derive ABC network whose only output is 1 iff the given nodes have the given values + pMonitor = Abc_NtkDeriveWithOnePo( p, vNodeIds, vNodeValues ); + // perform structural hashing + pStrashed = Abc_NtkStrash( pMonitor, 0, 1, 0 ); + Abc_NtkDelete( pMonitor ); + // it is a good idea to run sequential cleanup before giving the network to PDR + pResult = Abc_NtkDarLatchSweep( pStrashed, fLatchConst, fLatchEqual, fSaveNames, fUseMvSweep, nFramesSymb, nFramesSatur, fVerbose, fVeryVerbose ); + Abc_NtkDelete( pStrashed ); + return pResult; +} + +/**Function************************************************************* + + Synopsis [Testbench.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Abc_Ntk_t * Abc_NtkCreatePropertyMonitorTest( Abc_Ntk_t * p ) +{ + Abc_Ntk_t * pNtk; + Vec_Int_t * vNodeIds = Vec_IntAlloc( 100 ); + Vec_Int_t * vNodeValues = Vec_IntAlloc( 100 ); + + // this test will only work for the network, which has nodes with internal IDs such as these + Vec_IntPush( vNodeIds, 90 ); + Vec_IntPush( vNodeIds, 80 ); + Vec_IntPush( vNodeIds, 100 ); + + Vec_IntPush( vNodeValues, 1 ); + Vec_IntPush( vNodeValues, 0 ); + Vec_IntPush( vNodeValues, 1 ); + + pNtk = Abc_NtkCreatePropertyMonitor( p, vNodeIds, vNodeValues ); + + Vec_IntFree( vNodeIds ); + Vec_IntFree( vNodeValues ); + + return pNtk; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_GateToType( Abc_Obj_t * pObj ) +{ + char * pGateName = Mio_GateReadName((Mio_Gate_t *)pObj->pData); + if ( !strncmp(pGateName, "buf", 3) ) return ABC_OPER_BIT_BUF; + if ( !strncmp(pGateName, "inv", 3) ) return ABC_OPER_BIT_INV; + if ( !strncmp(pGateName, "and", 3) ) return ABC_OPER_BIT_AND; + if ( !strncmp(pGateName, "nand", 4) ) return ABC_OPER_BIT_NAND; + if ( !strncmp(pGateName, "or", 2) ) return ABC_OPER_BIT_OR; + if ( !strncmp(pGateName, "nor", 3) ) return ABC_OPER_BIT_NOR; + if ( !strncmp(pGateName, "xor", 3) ) return ABC_OPER_BIT_XOR; + if ( !strncmp(pGateName, "xnor", 4) ) return ABC_OPER_BIT_NXOR; + if ( !strncmp(pGateName, "zero", 4) ) return ABC_OPER_CONST_F; + if ( !strncmp(pGateName, "one", 3) ) return ABC_OPER_CONST_T; + assert( 0 ); + return -1; +} +Vec_Wec_t * Abc_SopSynthesize( Vec_Ptr_t * vSops ) +{ + Vec_Wec_t * vRes = NULL; + Abc_Ntk_t * pNtk = Abc_NtkCreateFromSops( "top", vSops ); + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin; + int i, k, iNode = 0; + Abc_FrameReplaceCurrentNetwork( Abc_FrameReadGlobalFrame(), pNtk ); + //Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "fx; strash; balance; dc2; map -a" ); + Abc_FrameSetBatchMode( 1 ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "st; collapse; sop; fx; strash; &get; &ps; &deepsyn -I 4 -J 50 -T 5 -S 111 -t; &ps; &put; map -a" ); + Abc_FrameSetBatchMode( 0 ); + pNtkNew = Abc_FrameReadNtk( Abc_FrameReadGlobalFrame() ); + vRes = Vec_WecStart( Abc_NtkPiNum(pNtkNew) + Abc_NtkNodeNum(pNtkNew) + Abc_NtkPoNum(pNtkNew) ); + Abc_NtkForEachPi( pNtkNew, pObj, i ) + pObj->iTemp = iNode++; + Abc_NtkForEachNode( pNtkNew, pObj, i ) + { + Vec_Int_t * vNode = Vec_WecEntry(vRes, iNode); + Vec_IntPush( vNode, Abc_GateToType(pObj) ); + Vec_IntPush( vNode, iNode ); + Abc_ObjForEachFanin( pObj, pFanin, k ) + Vec_IntPush( vNode, pFanin->iTemp ); + pObj->iTemp = iNode++; + } + Abc_NtkForEachPo( pNtkNew, pObj, i ) + Vec_IntPushTwo( Vec_WecEntry(vRes, iNode++), ABC_OPER_BIT_BUF, Abc_ObjFanin0(pObj)->iTemp ); + assert( Vec_WecSize(vRes) == iNode ); + return vRes; +} +Vec_Wec_t * Abc_GiaSynthesize( Vec_Ptr_t * vGias, Gia_Man_t * pMulti ) +{ + Vec_Wec_t * vRes = NULL; + Abc_Ntk_t * pNtk = Abc_NtkCreateFromGias( "top", vGias, pMulti ); + Abc_Ntk_t * pNtkNew; + Abc_Obj_t * pObj, * pFanin; + int i, k, iNode = 0; + Abc_FrameReplaceCurrentNetwork( Abc_FrameReadGlobalFrame(), pNtk ); + Abc_FrameSetBatchMode( 1 ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "clp; sop; fx; strash; compress2rs; dch; map -a; strash; compress2rs; dch; map -a" ); + Abc_FrameSetBatchMode( 0 ); + pNtkNew = Abc_FrameReadNtk( Abc_FrameReadGlobalFrame() ); + vRes = Vec_WecStart( Abc_NtkPiNum(pNtkNew) + Abc_NtkNodeNum(pNtkNew) + Abc_NtkPoNum(pNtkNew) ); + Abc_NtkForEachPi( pNtkNew, pObj, i ) + pObj->iTemp = iNode++; + Abc_NtkForEachNode( pNtkNew, pObj, i ) + { + Vec_Int_t * vNode = Vec_WecEntry(vRes, iNode); + Vec_IntPush( vNode, Abc_GateToType(pObj) ); + Vec_IntPush( vNode, iNode ); + Abc_ObjForEachFanin( pObj, pFanin, k ) + Vec_IntPush( vNode, pFanin->iTemp ); + pObj->iTemp = iNode++; + } + Abc_NtkForEachPo( pNtkNew, pObj, i ) + Vec_IntPushTwo( Vec_WecEntry(vRes, iNode++), ABC_OPER_BIT_BUF, Abc_ObjFanin0(pObj)->iTemp ); + assert( Vec_WecSize(vRes) == iNode ); + return vRes; +} +Gia_Man_t * Abc_GiaSynthesizeInter( Gia_Man_t * p ) +{ + Abc_Ntk_t * pNtkNew, * pNtk; + Vec_Ptr_t * vGias = Vec_PtrAlloc( 1 ); + Vec_PtrPush( vGias, p ); + pNtk = Abc_NtkCreateFromGias( "top", vGias, NULL ); + Vec_PtrFree( vGias ); + Abc_FrameReplaceCurrentNetwork( Abc_FrameReadGlobalFrame(), pNtk ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "balance; collapse; muxes; strash; dc2" ); + pNtkNew = Abc_FrameReadNtk( Abc_FrameReadGlobalFrame() ); + return Abc_NtkClpGia( pNtkNew ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_NtkClpOneGia_rec( Gia_Man_t * pNew, Abc_Obj_t * pNode ) +{ + int iLit0, iLit1; + if ( Abc_NodeIsTravIdCurrent(pNode) || Abc_ObjFaninNum(pNode) == 0 || Abc_ObjIsCi(pNode) ) + return pNode->iTemp; + assert( Abc_ObjIsNode( pNode ) ); + Abc_NodeSetTravIdCurrent( pNode ); + iLit0 = Abc_NtkClpOneGia_rec( pNew, Abc_ObjFanin0(pNode) ); + iLit1 = Abc_NtkClpOneGia_rec( pNew, Abc_ObjFanin1(pNode) ); + iLit0 = Abc_LitNotCond( iLit0, Abc_ObjFaninC0(pNode) ); + iLit1 = Abc_LitNotCond( iLit1, Abc_ObjFaninC1(pNode) ); + return (pNode->iTemp = Gia_ManHashAnd(pNew, iLit0, iLit1)); +} +Gia_Man_t * Abc_NtkStrashToGia( Abc_Ntk_t * pNtk ) +{ + int i, iLit; + Abc_Obj_t * pNode; + Gia_Man_t * pNew, * pTemp; + assert( Abc_NtkIsStrash(pNtk) ); + Abc_NtkForEachObj( pNtk, pNode, i ) + pNode->iTemp = -1; + // start new manager + pNew = Gia_ManStart( Abc_NtkObjNum(pNtk) ); + pNew->pName = Abc_UtilStrsav( pNtk->pName ); + pNew->pSpec = Abc_UtilStrsav( pNtk->pSpec ); + Gia_ManHashStart( pNew ); + // primary inputs + Abc_AigConst1(pNtk)->iTemp = 1; + Abc_NtkForEachCi( pNtk, pNode, i ) + pNode->iTemp = Gia_ManAppendCi(pNew); + // create the first cone + Abc_NtkIncrementTravId( pNtk ); + Abc_NtkForEachCo( pNtk, pNode, i ) + { + iLit = Abc_NtkClpOneGia_rec( pNew, Abc_ObjFanin0(pNode) ); + iLit = Abc_LitNotCond( iLit, Abc_ObjFaninC0(pNode) ); + Gia_ManAppendCo( pNew, iLit ); + } + // perform cleanup + pNew = Gia_ManCleanup( pTemp = pNew ); + Gia_ManStop( pTemp ); + return pNew; +} +Gia_Man_t * Abc_SopSynthesizeOne( char * pSop, int fClp ) +{ + Abc_Ntk_t * pNtkNew, * pNtk; + Vec_Ptr_t * vSops; + if ( strlen(pSop) == 3 ) + { + Gia_Man_t * pNew = Gia_ManStart( 1 ); + pNew->pName = Abc_UtilStrsav( "top" ); + //Gia_ManAppendCi( pNew ); + assert( pSop[1] == '0' || pSop[1] == '1' ); + Gia_ManAppendCo( pNew, pSop[1] == '1' ); + return pNew; + } + vSops = Vec_PtrAlloc( 1 ); + Vec_PtrPush( vSops, pSop ); + pNtk = Abc_NtkCreateFromSops( "top", vSops ); + Vec_PtrFree( vSops ); + Abc_FrameReplaceCurrentNetwork( Abc_FrameReadGlobalFrame(), pNtk ); + Abc_FrameSetBatchMode( 1 ); + if ( fClp ) + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "clp; sop" ); + Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "fx; strash; balance; dc2" ); + Abc_FrameSetBatchMode( 0 ); + pNtkNew = Abc_FrameReadNtk( Abc_FrameReadGlobalFrame() ); + return Abc_NtkStrashToGia( pNtkNew ); +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int s_ArraySize = 145; +static int s_ArrayData[290] = { + 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 6, 14, 12, 10, 2, 22, 20, 2, 24, 16, 4, 28, 18, 16, 10, 8, 4, 34, 32, 30, 36, 38, 26, 16, 6, 36, 20, 44, 42, 46, 40, 42, 44, 14, 6, 52, 34, 32, 54, 56, 50, 58, 48, 32, 24, 20, 2, 12, 6, 66, 34, 68, 64, 62, 70, 28, 68, 74, 72, 76, 58, 70, 62, 80, 78, 68, 28, 84, 74, 4, 2, 88, 20, 64, 90, 92, 86, 66, 32, 18, 96, 98, 56, 100, 94, 52, 36, 104, 38, 90, 42, 36, 2, 108, 110, 112, 106, 114, 100, 102, 116, 118, 82, 116, 60, 120, 122, 124, 60, 118, 60, 102, 82, 128, 130, 132, 82, 134, 126, 82, 116, 122, 138, 122, 118, 142, 140, 60, 102, 130, 146, 130, 118, 150, 148, 152, 144, 154, 136, 18, 156, 144, 126, 68, 160, 32, 136, 164, 162, 166, 158, 28, 160, 70, 126, 90, 144, 174, 172, 176, 170, 152, 134, 36, 180, 2, 134, 184, 182, 186, 178, 188, 168, 64, 144, 164, 158, 194, 192, 96, 156, 44, 154, 200, 170, 202, 198, 204, 176, 206, 196, 204, 168, 62, 126, 212, 186, 24, 134, 108, 152, 218, 192, 220, 216, 222, 214, 224, 210, 220, 194, 110, 152, 30, 180, 232, 230, 184, 172, 236, 234, 238, 228, 234, 182, 242, 220, 244, 168, 42, 154, 248, 202, 54, 136, 252, 164, 254, 214, 256, 250, 218, 194, 252, 198, 262, 242, 264, 260, 232, 220, 268, 262, 270, 168, + 191, 191, 209, 209, 226, 226, 240, 240, 246, 246, 259, 259, 267, 267, 272, 272, +}; +int Abc_NtkHasConstNode() +{ + int i; + for ( i = 1; i < s_ArraySize; i++ ) + if ( s_ArrayData[2*i] || s_ArrayData[2*i+1] ) + break; + for ( ; i < s_ArraySize; i++ ) + if ( s_ArrayData[2*i] < 2 && s_ArrayData[2*i+1] < 2 ) + return 1; + return 0; +} +Abc_Ntk_t * Abc_NtkFromArray() +{ + Vec_Ptr_t * vNodes = Vec_PtrAlloc( s_ArraySize ); int i, nPos = 0; + Abc_Ntk_t * pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); + Abc_Obj_t * pObjNew = Abc_NtkHasConstNode() ? Abc_NtkCreateNode(pNtkNew) : NULL; + if ( pObjNew ) pObjNew->pData = Abc_SopCreateConst0((Mem_Flex_t *)pNtkNew->pManFunc); + Vec_PtrPush( vNodes, pObjNew ); + for ( i = 1; i < s_ArraySize; i++ ) + if ( !s_ArrayData[2*i] && !s_ArrayData[2*i+1] ) + Vec_PtrPush( vNodes, Abc_NtkCreatePi(pNtkNew) ); + else + break; + for ( ; i < s_ArraySize; i++ ) + { + char * pSop = NULL; + if ( s_ArrayData[2*i] > s_ArrayData[2*i+1] ) + pSop = Abc_SopCreateXor( (Mem_Flex_t *)pNtkNew->pManFunc, 2 ); + else if ( s_ArrayData[2*i] < s_ArrayData[2*i+1] ) + pSop = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, 2, NULL ); + else + break; + pObjNew = Abc_NtkCreateNode( pNtkNew ); + Abc_ObjAddFanin( pObjNew, (Abc_Obj_t *)Vec_PtrEntry(vNodes, Abc_Lit2Var(s_ArrayData[2*i])) ); + Abc_ObjAddFanin( pObjNew, (Abc_Obj_t *)Vec_PtrEntry(vNodes, Abc_Lit2Var(s_ArrayData[2*i+1])) ); + if ( Abc_LitIsCompl(s_ArrayData[2*i]) ) Abc_SopComplementVar( pSop, 0 ); + if ( Abc_LitIsCompl(s_ArrayData[2*i+1]) ) Abc_SopComplementVar( pSop, 1 ); + pObjNew->pData = pSop; + Vec_PtrPush( vNodes, pObjNew ); + } + for ( ; i < s_ArraySize; i++ ) + { + char * pSop = NULL; + assert( s_ArrayData[2*i] == s_ArrayData[2*i+1] ); + pObjNew = Abc_NtkCreateNode( pNtkNew ); + Abc_ObjAddFanin( pObjNew, (Abc_Obj_t *)Vec_PtrEntry(vNodes, Abc_Lit2Var(s_ArrayData[2*i])) ); + if ( Abc_LitIsCompl(s_ArrayData[2*i]) ) + pSop = Abc_SopCreateInv( (Mem_Flex_t *)pNtkNew->pManFunc ); + else + pSop = Abc_SopCreateBuf( (Mem_Flex_t *)pNtkNew->pManFunc ); + pObjNew->pData = pSop; + Vec_PtrPush( vNodes, pObjNew ); + nPos++; + } + for ( i = 0; i < nPos; i++ ) + Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), (Abc_Obj_t *)Vec_PtrEntry(vNodes, s_ArraySize-nPos+i) ); + Vec_PtrFree( vNodes ); + pNtkNew->pName = Extra_UtilStrsav("test"); + Abc_NtkAddDummyPiNames( pNtkNew ); + Abc_NtkAddDummyPoNames( pNtkNew ); + Abc_NtkAddDummyBoxNames( pNtkNew ); + if ( !Abc_NtkCheck( pNtkNew ) ) + Abc_Print( 1, "Abc_NtkFromArray(): Network check has failed.\n" ); + return pNtkNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_PrintAT( Vec_Int_t * vRanks ) +{ + int i, Entry; + Vec_IntForEachEntryReverse( vRanks, Entry, i ) + if ( Entry == 0 ) + printf( " " ); + else + printf( "%4d", Entry ); + //printf( "\n" ); +} +int Abc_NtkMatchGpcPattern( Vec_Int_t * vRanks, int i, char * pGPC ) +{ + int k, Cur, Min = ABC_INFINITY; + for ( k = 0; pGPC[k] != ':' && i+k < Vec_IntSize(vRanks); k++ ) { + if ( Abc_TtReadHexDigit(pGPC[k]) == 0 ) + continue; + Cur = Vec_IntEntry(vRanks, i+k) / Abc_TtReadHexDigit(pGPC[k]); + if ( Min > Cur ) + Min = Cur; + } + return Min; +} +void Abc_NtkUpdateGpcPattern( Vec_Int_t * vRank, int i, char * pGPC, int nGpcs, Vec_Int_t * vRank2, Vec_Int_t * vLevel ) +{ + int k; char * pOut = strstr(pGPC, ":"); + assert( pOut && pOut[0] == ':' ); + pOut++; + Vec_IntAddToEntry( vLevel, i, nGpcs ); + for ( k = 0; pGPC[k] != ':'; k++ ) + Vec_IntAddToEntry( vRank, i+k, -nGpcs * Abc_TtReadHexDigit(pGPC[k]) ); + for ( k = 0; pOut[k] != ':'; k++ ) + Vec_IntAddToEntry( vRank2, i+k, nGpcs * Abc_TtReadHexDigit(pOut[k]) ); +} +int Abc_NtkGetGpcLutCount( char * pGPC ) +{ + char * pOut = strstr(pGPC, ":"); + char * pLut = strstr(pOut+1, ":"); + return atoi(pLut+1); +} +static inline int Vec_WecSum( Vec_Wec_t * p ) +{ + Vec_Int_t * vVec; + int i, Counter = 0; + Vec_WecForEachLevel( p, vVec, i ) + Counter += Vec_IntSum(vVec); + return Counter; +} +char ** Abc_NtkTransformGPCs( char ** pGPCs, int nGPCs ) +{ + char * pOut, * pLut, ** pRes = ABC_ALLOC( char *, nGPCs ); + int i, k, nLength; + for ( i = 0; i < nGPCs; i++ ) { + pRes[i] = Abc_UtilStrsav(pGPCs[i]); + pOut = strstr(pRes[i], ":"); + nLength = (int)(pOut-pRes[i]); + for ( k = 0; k < nLength/2; k++ ) + ABC_SWAP( char, pRes[i][k], pRes[i][nLength-1-k] ) + pLut = strstr(pOut+1, ":"); + nLength = (int)(pLut-pOut-1); + for ( k = 0; k < nLength/2; k++ ) + ABC_SWAP( char, pOut[1+k], pOut[1+nLength-1-k] ) + } + return pRes; +} +int Abc_NtkCheckGpc( char * pGPC, char * pGPC0 ) +{ + int RetValue = 0, k, Sum[2] = {0}; + char * pOut = strstr(pGPC, ":"); + for ( k = 0; pGPC[k] != ':'; k++ ) + Sum[0] += (1 << k) * Abc_TtReadHexDigit(pGPC[k]); + for ( k = 0; pOut[1+k] != ':'; k++ ) + Sum[1] += (1 << k) * Abc_TtReadHexDigit(pOut[1+k]); + //printf( "GPC %s has input sum %d and output sum %d\n", pGPC0, Sum[0], Sum[1] ); + if ( Sum[0]+1 > (1 << Abc_Base2Log(Sum[1]+1)) ) + printf( "The largest value of GPC inputs (%d) exceeds the capacity of outputs (%d) for GPC %s.\n", Sum[0], Sum[1], pGPC0 ); + else if ( Sum[1]+1 > (1 << Abc_Base2Log(Sum[0]+1)) ) + printf( "The largest value of GPC outputs (%d) exceeds the capacity of inputs (%d) for GPC %s.\n", Sum[1], Sum[0], pGPC0 ); + else + RetValue = 1; + return RetValue; +} +void Abc_NtkATMap( int nXVars, int nYVars, int nAdder, char ** pGPCs0, int nGPCs, int fReturn, int fVerbose ) +{ + abctime clkStart = Abc_Clock(); + char ** pGPCs = Abc_NtkTransformGPCs(pGPCs0, nGPCs); + int i, nGPCluts[100] = {0}; + for ( i = 0; i < nGPCs; i++ ) + if ( !Abc_NtkCheckGpc(pGPCs[i], pGPCs0[i]) ) + return; + for ( i = 0; i < nGPCs; i++ ) + nGPCluts[i] = Abc_NtkGetGpcLutCount(pGPCs[i]); + int x, n, Entry, iLevel = 0, Sum = 0, nGpcs = 0, nBits, fFinished, nRcaLuts = 0, nLuts = 0; + for ( x = 0; x < nXVars; x++ ) + Sum += (1 << x) * nYVars; + nBits = Abc_Base2Log( Sum+1 ); + printf( "Rectangular adder tree (X=%d Y=%d Sum=%d Out=%d) mapped with", nXVars, nYVars, Sum, nBits ); + for ( i = 0; i < nGPCs; i++ ) + printf( " GPC%d=%s", i, pGPCs0[i] ); + printf( "\n" ); + Vec_Int_t * vLevel; + Vec_Int_t * vRank[3] = { Vec_IntAlloc(100), Vec_IntAlloc(100), Vec_IntAlloc(100) }; + Vec_Wec_t ** vGPCs = ABC_ALLOC( Vec_Wec_t *, nGPCs ); + for ( i = 0; i < nGPCs; i++ ) + vGPCs[i] = Vec_WecAlloc(100); + Vec_IntFill( vRank[0], nBits, 0 ); + for ( x = 0; x < nXVars; x++ ) + Vec_IntAddToEntry( vRank[0], x, nYVars ); + if ( fVerbose ) { + printf( "Ranks: " ); + for ( i = nBits-1; i >= 0; i-- ) + printf( "%4d", i ); + printf( " : " ); + for ( i = nBits-1; i >= 0; i-- ) + printf( "%4d", i ); + printf( " LUT6\n" ); + } + for ( n = 0; n < nGPCs; n++ ) + for ( i = 0, fFinished = 0; !fFinished; i++ ) + { + int fAdded = 0; + vLevel = Vec_WecPushLevel( vGPCs[n] ); + Vec_IntFill( vLevel, nBits, 0 ); + Vec_IntFill( vRank[1], nBits, 0 ); + Vec_IntClear( vRank[2] ); + Vec_IntAppend( vRank[2], vRank[0] ); + fFinished = 1; + if ( Vec_IntFindMax(vRank[0]) > nAdder ) { + for ( x = 0; x < nBits; x++ ) + if ( (nGpcs = Abc_NtkMatchGpcPattern(vRank[0], x, pGPCs[n])) ) + Abc_NtkUpdateGpcPattern(vRank[0], x, pGPCs[n], nGpcs, vRank[1], vLevel), fFinished = 0, fAdded = 1; + nLuts += Vec_IntSum(vLevel) * nGPCluts[n]; + Vec_IntForEachEntry( vRank[1], Entry, x ) + Vec_IntAddToEntry( vRank[0], x, Entry ); + } + if ( fVerbose && (fAdded || Vec_IntFindMax(vRank[2]) <= nAdder ) ) { + printf( "Lev%02d: ", iLevel++ ); + Abc_PrintAT( vRank[2] ); + if ( fAdded ) { + printf( " GPC%d: ", n ); + Abc_PrintAT( vLevel ); + printf( " %4d", Vec_IntSum(vLevel) * nGPCluts[n] ); + } + else if ( Vec_IntFindMax(vRank[2]) <= nAdder ) { + printf( " ADD%d: ", nAdder ); + for ( x = 0; x < nBits; x++ ) + if ( Vec_IntEntry(vRank[2], x) > 1 ) + break; + for ( i = nBits-1; i >= x; i-- ) + printf( "%4d", 1 ); + for ( ; i >= 0; i-- ) + printf( " " ); + printf( " %4d", (nBits-x)*(nAdder == 4 ? 2 : 1) ); + } + printf( "\n" ); + } + if ( fAdded ) { + if ( fReturn ) { + fFinished = 1; + n = -1; + } + } + else if ( Vec_IntFindMax(vRank[2]) <= nAdder ) { + fFinished = 1; + n = nGPCs; + } + } + if ( Vec_IntFindMax(vRank[0]) > nAdder ) + printf( "Synthesis of the adder tree is incomplete. Try using the full adder \"3:11:1\" as the last GPC.\n" ); + else if ( fVerbose && Vec_IntFindMax(vRank[0]) <= nAdder ) { + printf( "Lev%02d: ", iLevel++ ); + for ( i = nBits-1; i >= 0; i-- ) + printf( "%4d", 1 ); + printf( "\n" ); + } + printf( "Statistics: " ); + for ( n = 0; n < nGPCs; n++ ) + printf( "GPC%d = %d. ", n, Vec_WecSum(vGPCs[n]) ); + for ( x = 0; x < nBits; x++ ) + if ( Vec_IntEntry(vRank[0], x) > 1 ) + break; + nRcaLuts = (nBits-x)*(nAdder == 4 ? 2 : 1); + printf( "ADD%d = %d. ", nAdder, nRcaLuts ); + printf( "Total LUT count = %d. ", nLuts+nRcaLuts ); + for ( i = 0; i < 3; i++ ) + Vec_IntFree( vRank[i] ); + for ( i = 0; i < nGPCs; i++ ) + Vec_WecFree( vGPCs[i] ); + ABC_FREE( vGPCs ); + for ( i = 0; i < nGPCs; i++ ) + ABC_FREE( pGPCs[i] ); + ABC_FREE( pGPCs ); + Abc_PrintTime( 0, "Total time", Abc_Clock() - clkStart ); +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/abc_.c b/yosys/abc/src/base/abc/abc_.c new file mode 100644 index 00000000000..d9302303093 --- /dev/null +++ b/yosys/abc/src/base/abc/abc_.c @@ -0,0 +1,52 @@ +/**CFile**************************************************************** + + FileName [abc_.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abc_.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "abc.h" + +ABC_NAMESPACE_IMPL_START + + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + +ABC_NAMESPACE_IMPL_END + diff --git a/yosys/abc/src/base/abc/module.make b/yosys/abc/src/base/abc/module.make new file mode 100644 index 00000000000..34517b04da4 --- /dev/null +++ b/yosys/abc/src/base/abc/module.make @@ -0,0 +1,23 @@ +SRC += src/base/abc/abcAig.c \ + src/base/abc/abcBarBuf.c \ + src/base/abc/abcBlifMv.c \ + src/base/abc/abcCheck.c \ + src/base/abc/abcDfs.c \ + src/base/abc/abcFanio.c \ + src/base/abc/abcFanOrder.c \ + src/base/abc/abcFunc.c \ + src/base/abc/abcHie.c \ + src/base/abc/abcHieCec.c \ + src/base/abc/abcHieGia.c \ + src/base/abc/abcHieNew.c \ + src/base/abc/abcLatch.c \ + src/base/abc/abcLib.c \ + src/base/abc/abcMinBase.c \ + src/base/abc/abcNames.c \ + src/base/abc/abcNetlist.c \ + src/base/abc/abcNtk.c \ + src/base/abc/abcObj.c \ + src/base/abc/abcRefs.c \ + src/base/abc/abcShow.c \ + src/base/abc/abcSop.c \ + src/base/abc/abcUtil.c diff --git a/yosys/abc/src/base/abci/abc.c b/yosys/abc/src/base/abci/abc.c new file mode 100644 index 00000000000..6db456e5c7b --- /dev/null +++ b/yosys/abc/src/base/abci/abc.c @@ -0,0 +1,57063 @@ +/**CFile**************************************************************** + + FileName [abc.c] + + SystemName [ABC: Logic synthesis and verification system.] + + PackageName [Network and node package.] + + Synopsis [Command file.] + + Author [Alan Mishchenko] + + Affiliation [UC Berkeley] + + Date [Ver. 1.0. Started - June 20, 2005.] + + Revision [$Id: abc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] + +***********************************************************************/ + +#include "base/abc/abc.h" +#include "base/main/main.h" +#include "base/main/mainInt.h" +#include "proof/fraig/fraig.h" +#include "opt/fxu/fxu.h" +#include "opt/fxch/Fxch.h" +#include "opt/cut/cut.h" +#include "map/fpga/fpga.h" +#include "map/if/if.h" +#include "opt/sim/sim.h" +#include "opt/res/res.h" +#include "opt/lpk/lpk.h" +#include "aig/gia/giaAig.h" +#include "opt/dar/dar.h" +#include "opt/mfs/mfs.h" +#include "proof/fra/fra.h" +#include "aig/saig/saig.h" +#include "proof/int/int.h" +#include "proof/dch/dch.h" +#include "proof/ssw/ssw.h" +#include "opt/cgt/cgt.h" +#include "bool/kit/kit.h" +#include "map/amap/amap.h" +#include "opt/ret/retInt.h" +#include "sat/xsat/xsat.h" +#include "sat/satoko/satoko.h" +#include "sat/cnf/cnf.h" +#include "proof/cec/cec.h" +#include "proof/acec/acec.h" +#include "proof/pdr/pdr.h" +#include "misc/tim/tim.h" +#include "bdd/llb/llb.h" +#include "bdd/bbr/bbr.h" +#include "map/cov/cov.h" +#include "base/cmd/cmd.h" +#include "proof/abs/abs.h" +#include "sat/bmc/bmc.h" +#include "proof/ssc/ssc.h" +#include "opt/sfm/sfm.h" +#include "opt/sbd/sbd.h" +#include "bool/rpo/rpo.h" +#include "map/mpm/mpm.h" +#include "map/mio/mio.h" +#include "opt/fret/fretime.h" +#include "opt/nwk/nwkMerge.h" +#include "base/acb/acbPar.h" +#include "misc/extra/extra.h" +#include "opt/eslim/eSLIM.h" + + +#ifndef _WIN32 +#include +#endif + +ABC_NAMESPACE_IMPL_START + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +//#define USE_MINISAT22 + +static int Abc_CommandPrintStats ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintExdc ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintIo ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintLatch ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintFanio ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintMffc ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintFactor ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintLevel ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintSupport ( Abc_Frame_t * pAbc, int argc, char ** argv ); +#ifdef ABC_USE_CUDD +static int Abc_CommandPrintMint ( Abc_Frame_t * pAbc, int argc, char ** argv ); +#endif +static int Abc_CommandPrintSymms ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintUnate ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintAuto ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintKMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintGates ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintSharing ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintXCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintDsd ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintCone ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintMiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintStatus ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPrintDelay ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandShow ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandShowBdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandShowCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandCollapse ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSatClp ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandStrash ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBalance ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMuxStruct ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMulti ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRenode ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCleanup ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFastExtract ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFxch ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandEliminate ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDisjoint ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSparsify ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandLutpack ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandLutmin ( Abc_Frame_t * pAbc, int argc, char ** argv ); +//static int Abc_CommandImfs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMfs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMfs2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMfs3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMfse ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandLogicPush ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTrace ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandGlitch ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSpeedup ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPowerdown ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAddBuffs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMerge ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTestDec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTestNpn ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTestRPO ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTestTruth ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTestSupp ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTestRand ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRunSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRunEco ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRunGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRunTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRefactor ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRestructure ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandResubstitute ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandResubUnate ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandResubCore ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandResubCheck ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRr ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCascade ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandLutCasDec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandLutCas ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBsEval ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandExtract ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandVarMin ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFaultClasses ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandExact ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBmsStart ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBmsStop ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBmsPs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMajExact ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTwoExact ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandLutExact ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAllExact ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTestExact ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMajGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandOrchestrate ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAIGAugmentation ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandLogic ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandComb ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMiter2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDemiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandOrPos ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAndPos ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandZeroPo ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSwapPos ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRemovePo ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDropSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAddPi ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAddFlop ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAppend ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPutOnTop ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFrames ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDFrames ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSop ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAig ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandReorder ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBidec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandOrder ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMuxes ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCubes ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandExpand ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSplitSop ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandExtSeqDcs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandReach ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCone ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandNode ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRange ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCof ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTopmost ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBottommost ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTopAnd ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTrim ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandShortNames ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMoveNames ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandExdcFree ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandExdcGet ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandExdcSet ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCareSet ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandEspresso ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandGenTF ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandGenAT ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandGenFsm ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCover ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDouble ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandInter ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBb2Wb ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandOutdec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandNodeDup ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandWrap ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTestColor ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandQuaVar ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandQuaRel ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandQuaReach ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSenseInput ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandNpnLoad ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandNpnSave ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandSendAig ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSendStatus ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandBackup ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRestore ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandMinisat ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMinisimp ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandIStrash ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandICut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandIRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDRefactor ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDc2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDChoice ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDch ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDrwsat ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandIRewriteSeq ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandIResyn ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandISat ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandIFraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDFraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbSec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSimSec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandMatch ( Abc_Frame_t * pAbc, int argc, char ** argv ); +//static int Abc_CommandHaig ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandQbf ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandFraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFraigTrust ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFraigStore ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFraigRestore ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFraigClean ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFraigSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFraigDress ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDumpEquiv ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandRecStart3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecStop3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecPs3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecAdd3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecDump3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRecMerge3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAmap ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPhaseMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandStochMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandUnmap ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAttach ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSuperChoice ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSuperChoiceLut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTimeScale ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRewire ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +//static int Abc_CommandFpga ( Abc_Frame_t * pAbc, int argc, char ** argv ); +//static int Abc_CommandFpgaFast ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandIf ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandIfif ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandDsdSave ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDsdLoad ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDsdFree ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDsdPs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDsdMatch ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDsdMerge ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDsdFilter ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandScut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandInit ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandZero ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandUndc ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandOneHot ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPipe ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSeq ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandUnseq ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandRetime ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDRetime ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFlowRetime ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCRetime ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSeqFpga ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSeqMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSeqSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSeqSweep2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTestSeqSweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTestScorr ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandLcorr ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSeqCleanup ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCycle ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandXsim ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSim ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSim3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDarPhase ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSynch ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandClockGate ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandExtWin ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandInsWin ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSymFun ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandATMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPermute ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandUnpermute ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCubeEnum ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPathEnum ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFunEnum ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDCec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDSec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandXSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSatoko ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Satoko ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Sat3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Kissat ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandIProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDebug ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandEco ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBmc ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBmc2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBmc3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBmcInter ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandIndcut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandEnlarge ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTempor ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandInduction ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandConstr ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandUnfold ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFold ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandUnfold2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandFold2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBm ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBm2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandSaucy ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTestCex ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandPdr ( Abc_Frame_t * pAbc, int argc, char ** argv ); +#ifdef ABC_USE_CUDD +static int Abc_CommandReconcile ( Abc_Frame_t * pAbc, int argc, char ** argv ); +#endif +static int Abc_CommandCexSave ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCexLoad ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCexCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandCexMerge ( Abc_Frame_t * pAbc, int argc, char ** argv ); +//static int Abc_CommandCexMin ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandDualRail ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandBlockPo ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandIso ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandTraceStart ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandTraceCheck ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandAbcSave ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbcLoad ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandAbc9Get ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Put ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9MoveNames ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Save ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Save2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9SaveAig ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Load ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Load2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9LoadAig ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Read ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9ReadBlif ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9ReadCBlif ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9ReadStg ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9ReadVer ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9WriteVer ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Write ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9WriteLut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Ps ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9PFan ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Pms ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9PSig ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Status ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9MuxProfile ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9MuxPos ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9MuxStr ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9MuxDec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9PrintTruth ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Unate ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Rex2Gia ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9RexWalk ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Show ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9SetRegNum ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Strash ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Topand ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Add1Hot ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Cof ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Cofs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Trim ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Dfs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Sim ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Sim2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Sim3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9MLGen ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9MLTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Iwls21Test ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9ReadSim ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9WriteSim ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9PrintSim ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9GenSim ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9SimRsb ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Resim ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9SpecI ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Equiv ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Equiv2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Equiv3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Semi ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Times ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Frames ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Retime ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Enable ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Dc2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Dsd ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Bidec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Shrink ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Fx ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Extract ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Balance ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9BalanceLut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Resub ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Reshape ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Syn2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Syn3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Syn4 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Synch2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9False ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Miter ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Miter2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Append ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Scl ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Lcorr ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Scorr ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Choice ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Sat ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9SatEnum ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9AdvGenSim ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Fraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9CFraig ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Srm ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Srm2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Filter ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Reduce ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9EquivMark ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9EquivFilter ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Cec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9ICec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Verify ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Sweep ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Force ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Embed ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Sopb ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Dsdb ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Flow ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Flow2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Flow3 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9If ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Iff ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Iiff ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9If2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Sif ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Jf ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Kf ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Lf ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Mf ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Nf ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Of ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Simap ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Exmap ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Pack ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Edge ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9SatLut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9LNetRead ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9LNetSim ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9LNetEval ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9LNetOpt ( Abc_Frame_t * pAbc, int argc, char ** argv ); +//#ifndef _WIN32 +static int Abc_CommandAbc9Ttopt ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Transduction ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9TranStoch ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Rrr ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Rewire ( Abc_Frame_t * pAbc, int argc, char ** argv ); +//#endif +static int Abc_CommandAbc9LNetMap ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Unmap ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Struct ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Trace ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Speedup ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Era ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Dch ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Rpm ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9BackReach ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Posplit ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Permute ( Abc_Frame_t * pAbc, int argc, char ** argv ); +#ifdef ABC_USE_CUDD +static int Abc_CommandAbc9ReachM ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9ReachP ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9ReachN ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9ReachY ( Abc_Frame_t * pAbc, int argc, char ** argv ); +#endif +static int Abc_CommandAbc9Undo ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Mesh ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Iso ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9IsoNpn ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9IsoSt ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Store ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Compare ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9RevEng ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Uif ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9CexInfo ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Cycle ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Cone ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Slice ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9PoPart ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9GroupProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9MultiProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9SplitProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9SProve ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9SplitSat ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Bmc ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9SBmc ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9ChainBmc ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9BCore ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9ICheck ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9SatTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9FFTest ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Qbf ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9QVar ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9GenQbf ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9HomoQbf ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9SatFx ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9SatClp ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Inse ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Maxi ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Bmci ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9PoXsim ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Demiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Fadds ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9ATree ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Polyn ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Acec ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Anorm ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Decla ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Esop ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Exorcism ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Mfs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Mfsd ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9DeepSyn ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9RandSyn ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9SatSyn ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9StochSyn ( Abc_Frame_t * pAbc, int argc, char ** argv ); +//static int Abc_CommandAbc9PoPart2 ( Abc_Frame_t * pAbc, int argc, char ** argv ); +//static int Abc_CommandAbc9CexCut ( Abc_Frame_t * pAbc, int argc, char ** argv ); +//static int Abc_CommandAbc9CexMerge ( Abc_Frame_t * pAbc, int argc, char ** argv ); +//static int Abc_CommandAbc9CexMin ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandAbc9AbsCreate ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9AbsDerive ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9AbsRefine ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9GlaDerive ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9GlaRefine ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9GlaShrink ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Gla ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Vta ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Vta2Gla ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Gla2Vta ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Fla2Gla ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Gla2Fla ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandAbc9Gen ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Cfs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9ProdAdd ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9AddFlop ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9BMiter ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9GenHie ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9PutOnTop ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9BRecover ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9StrEco ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9GenCex ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Odc ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9GenRel ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9GenMux ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9GenComp ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9GenSorter ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9GenNeuron ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9Window ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9FunAbs ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9DsdInfo ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9FunTrace ( Abc_Frame_t * pAbc, int argc, char ** argv ); +static int Abc_CommandAbc9MulFind ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandAbc9Test ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +static int Abc_CommandAbc9eSLIM ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +extern int Abc_CommandAbcLivenessToSafety ( Abc_Frame_t * pAbc, int argc, char ** argv ); +extern int Abc_CommandAbcLivenessToSafetySim ( Abc_Frame_t * pAbc, int argc, char ** argv ); +extern int Abc_CommandAbcLivenessToSafetyWithLTL( Abc_Frame_t * pAbc, int argc, char ** argv ); +extern int Abc_CommandCS_kLiveness ( Abc_Frame_t * pAbc, int argc, char ** argv ); +extern int Abc_CommandNChooseK ( Abc_Frame_t * pAbc, int argc, char ** argv ); + +extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); +extern Abc_Ntk_t * Abc_NtkFromAigPhase( Aig_Man_t * pMan ); + +extern Vec_Ptr_t * Abc_NtkCollectCiNames( Abc_Ntk_t * pNtk ); +extern Vec_Ptr_t * Abc_NtkCollectCoNames( Abc_Ntk_t * pNtk ); + +extern void Extra_BitMatrixTransposeP( Vec_Wrd_t * vSimsIn, int nWordsIn, Vec_Wrd_t * vSimsOut, int nWordsOut ); + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameReplaceCex( Abc_Frame_t * pAbc, Abc_Cex_t ** ppCex ) +{ + // update CEX + ABC_FREE( pAbc->pCex ); + pAbc->pCex = *ppCex; + *ppCex = NULL; + // remove CEX vector + if ( pAbc->vCexVec ) + { + Vec_PtrFreeFree( pAbc->vCexVec ); + pAbc->vCexVec = NULL; + } +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameReplaceCexVec( Abc_Frame_t * pAbc, Vec_Ptr_t ** pvCexVec ) +{ + // update CEX vector + if ( pAbc->vCexVec ) + Vec_PtrFreeFree( pAbc->vCexVec ); + pAbc->vCexVec = *pvCexVec; + *pvCexVec = NULL; + // remove CEX + ABC_FREE( pAbc->pCex ); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameReplacePoEquivs( Abc_Frame_t * pAbc, Vec_Ptr_t ** pvPoEquivs ) +{ + if ( pAbc->vPoEquivs ) + Vec_VecFree( (Vec_Vec_t *)pAbc->vPoEquivs ); + pAbc->vPoEquivs = *pvPoEquivs; + *pvPoEquivs = NULL; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameReplacePoStatuses( Abc_Frame_t * pAbc, Vec_Int_t ** pvStatuses ) +{ + if ( pAbc->vStatuses ) + Vec_IntFree( pAbc->vStatuses ); + pAbc->vStatuses = *pvStatuses; + *pvStatuses = NULL; +} + +/**Function************************************************************* + + Synopsis [Derives array of statuses from the array of CEXes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Vec_Int_t * Abc_FrameDeriveStatusArray( Vec_Ptr_t * vCexes ) +{ + Vec_Int_t * vStatuses; + Abc_Cex_t * pCex; + int i; + if ( vCexes == NULL ) + return NULL; + vStatuses = Vec_IntAlloc( Vec_PtrSize(vCexes) ); + Vec_IntFill( vStatuses, Vec_PtrSize(vCexes), -1 ); // assume UNDEC + Vec_PtrForEachEntry( Abc_Cex_t *, vCexes, pCex, i ) + if ( pCex != NULL ) + Vec_IntWriteEntry( vStatuses, i, 0 ); // set this output as SAT + return vStatuses; +} +Vec_Int_t * Abc_FrameDeriveStatusArray2( Vec_Ptr_t * vCexes ) +{ + Vec_Int_t * vStatuses; + Abc_Cex_t * pCex; + int i; + if ( vCexes == NULL ) + return NULL; + vStatuses = Vec_IntAlloc( Vec_PtrSize(vCexes) ); + Vec_IntFill( vStatuses, Vec_PtrSize(vCexes), -1 ); // assume UNDEC + Vec_PtrForEachEntry( Abc_Cex_t *, vCexes, pCex, i ) + if ( pCex == (Abc_Cex_t *)(ABC_PTRINT_T)1 ) + { + Vec_IntWriteEntry( vStatuses, i, 1 ); // set this output as UNSAT + Vec_PtrWriteEntry( vCexes, i, NULL ); + } + else if ( pCex != NULL ) + Vec_IntWriteEntry( vStatuses, i, 0 ); // set this output as SAT + return vStatuses; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameClearDesign() +{ +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_FrameUpdateGia( Abc_Frame_t * pAbc, Gia_Man_t * pNew ) +{ + if ( pNew == NULL ) + { + Abc_Print( -1, "Abc_FrameUpdateGia(): Transformation has failed.\n" ); + return; + } + if ( Gia_ManPoNum(pNew) == 0 ) + Abc_Print( 0, "The current GIA has no primary outputs. Some commands may not work correctly.\n" ); + if ( pNew == pAbc->pGia ) + return; + // transfer names + if (!pNew->vNamesIn && pAbc->pGia && pAbc->pGia->vNamesIn && Gia_ManCiNum(pNew) == Vec_PtrSize(pAbc->pGia->vNamesIn)) + { + pNew->vNamesIn = pAbc->pGia->vNamesIn; + pAbc->pGia->vNamesIn = NULL; + } + if (!pNew->vNamesOut && pAbc->pGia && pAbc->pGia->vNamesOut && Gia_ManCoNum(pNew) == Vec_PtrSize(pAbc->pGia->vNamesOut)) + { + pNew->vNamesOut = pAbc->pGia->vNamesOut; + pAbc->pGia->vNamesOut = NULL; + } + if (!pNew->vNamesNode && pAbc->pGia && pAbc->pGia->vNamesNode && Gia_ManObjNum(pNew) == Vec_PtrSize(pAbc->pGia->vNamesNode)) + { + pNew->vNamesNode = pAbc->pGia->vNamesNode; + pAbc->pGia->vNamesNode = NULL; + } + // update + if ( pAbc->pGia2 ) + Gia_ManStop( pAbc->pGia2 ); + pAbc->pGia2 = pAbc->pGia; + pAbc->pGia = pNew; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Gia_Man_t * Abc_FrameGetGia( Abc_Frame_t * pAbc ) +{ + Gia_Man_t * pGia; + if ( pAbc->pGia2 ) + Gia_ManStop( pAbc->pGia2 ); + pAbc->pGia2 = NULL; + pGia = pAbc->pGia; + pAbc->pGia = NULL; + return pGia; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_Init( Abc_Frame_t * pAbc ) +{ + Cmd_CommandAdd( pAbc, "Printing", "ps", Abc_CommandPrintStats, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_stats", Abc_CommandPrintStats, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_exdc", Abc_CommandPrintExdc, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_io", Abc_CommandPrintIo, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_latch", Abc_CommandPrintLatch, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "pfan", Abc_CommandPrintFanio, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_fanio", Abc_CommandPrintFanio, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_mffc", Abc_CommandPrintMffc, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "pf", Abc_CommandPrintFactor, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_factor", Abc_CommandPrintFactor, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_level", Abc_CommandPrintLevel, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "psu", Abc_CommandPrintSupport, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_supp", Abc_CommandPrintSupport, 0 ); +#ifdef ABC_USE_CUDD + Cmd_CommandAdd( pAbc, "Printing", "print_mint", Abc_CommandPrintMint, 0 ); +#endif + Cmd_CommandAdd( pAbc, "Printing", "print_symm", Abc_CommandPrintSymms, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_unate", Abc_CommandPrintUnate, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_auto", Abc_CommandPrintAuto, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_kmap", Abc_CommandPrintKMap, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "pg", Abc_CommandPrintGates, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_gates", Abc_CommandPrintGates, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_sharing", Abc_CommandPrintSharing, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_xcut", Abc_CommandPrintXCut, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_dsd", Abc_CommandPrintDsd, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_cone", Abc_CommandPrintCone, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_miter", Abc_CommandPrintMiter, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_status", Abc_CommandPrintStatus, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "print_delay", Abc_CommandPrintDelay, 0 ); + + Cmd_CommandAdd( pAbc, "Printing", "show", Abc_CommandShow, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "show_bdd", Abc_CommandShowBdd, 0 ); + Cmd_CommandAdd( pAbc, "Printing", "show_cut", Abc_CommandShowCut, 0 ); + + Cmd_CommandAdd( pAbc, "Synthesis", "clp", Abc_CommandCollapse, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "collapse", Abc_CommandCollapse, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "satclp", Abc_CommandSatClp, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "st", Abc_CommandStrash, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "strash", Abc_CommandStrash, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "b", Abc_CommandBalance, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "balance", Abc_CommandBalance, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "mux_struct", Abc_CommandMuxStruct, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "multi", Abc_CommandMulti, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "renode", Abc_CommandRenode, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "cleanup", Abc_CommandCleanup, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "sweep", Abc_CommandSweep, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "fx", Abc_CommandFastExtract, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "fxch", Abc_CommandFxch, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "eliminate", Abc_CommandEliminate, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "dsd", Abc_CommandDisjoint, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "sparsify", Abc_CommandSparsify, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "lutpack", Abc_CommandLutpack, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "lutmin", Abc_CommandLutmin, 1 ); +// Cmd_CommandAdd( pAbc, "Synthesis", "imfs", Abc_CommandImfs, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "mfs", Abc_CommandMfs, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "mfs2", Abc_CommandMfs2, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "mfs3", Abc_CommandMfs3, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "mfse", Abc_CommandMfse, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "logicpush", Abc_CommandLogicPush, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "trace", Abc_CommandTrace, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "glitch", Abc_CommandGlitch, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "speedup", Abc_CommandSpeedup, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "powerdown", Abc_CommandPowerdown, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "addbuffs", Abc_CommandAddBuffs, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "merge", Abc_CommandMerge, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "testdec", Abc_CommandTestDec, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "testnpn", Abc_CommandTestNpn, 0 ); + Cmd_CommandAdd( pAbc, "LogiCS", "testrpo", Abc_CommandTestRPO, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "testtruth", Abc_CommandTestTruth, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "testsupp", Abc_CommandTestSupp, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "testrand", Abc_CommandTestRand, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "runsat", Abc_CommandRunSat, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "runeco", Abc_CommandRunEco, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "rungen", Abc_CommandRunGen, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "xec", Abc_CommandRunTest, 0 ); + + Cmd_CommandAdd( pAbc, "Synthesis", "rewrite", Abc_CommandRewrite, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "refactor", Abc_CommandRefactor, 1 ); +// Cmd_CommandAdd( pAbc, "Synthesis", "restructure", Abc_CommandRestructure, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "resub", Abc_CommandResubstitute, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "resub_unate", Abc_CommandResubUnate, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "resub_core", Abc_CommandResubCore, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "resub_check", Abc_CommandResubCheck, 0 ); +// Cmd_CommandAdd( pAbc, "Synthesis", "rr", Abc_CommandRr, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "cascade", Abc_CommandCascade, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "lutcasdec", Abc_CommandLutCasDec, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "lutcas", Abc_CommandLutCas, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "bseval", Abc_CommandBsEval, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "extract", Abc_CommandExtract, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "varmin", Abc_CommandVarMin, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "faultclasses", Abc_CommandFaultClasses, 0 ); + Cmd_CommandAdd( pAbc, "Synthesis", "exact", Abc_CommandExact, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "orchestrate", Abc_CommandOrchestrate, 1 ); + Cmd_CommandAdd( pAbc, "Synthesis", "aigaug", Abc_CommandAIGAugmentation, 1 ); + + Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_start", Abc_CommandBmsStart, 0 ); + Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_stop", Abc_CommandBmsStop, 0 ); + Cmd_CommandAdd( pAbc, "Exact synthesis", "bms_ps", Abc_CommandBmsPs, 0 ); + Cmd_CommandAdd( pAbc, "Exact synthesis", "majexact", Abc_CommandMajExact, 0 ); + Cmd_CommandAdd( pAbc, "Exact synthesis", "twoexact", Abc_CommandTwoExact, 0 ); + Cmd_CommandAdd( pAbc, "Exact synthesis", "lutexact", Abc_CommandLutExact, 0 ); + Cmd_CommandAdd( pAbc, "Exact synthesis", "allexact", Abc_CommandAllExact, 0 ); + Cmd_CommandAdd( pAbc, "Exact synthesis", "testexact", Abc_CommandTestExact, 0 ); + Cmd_CommandAdd( pAbc, "Exact synthesis", "majgen", Abc_CommandMajGen, 0 ); + + Cmd_CommandAdd( pAbc, "Various", "logic", Abc_CommandLogic, 1 ); + Cmd_CommandAdd( pAbc, "Various", "comb", Abc_CommandComb, 1 ); + Cmd_CommandAdd( pAbc, "Various", "miter", Abc_CommandMiter, 1 ); + Cmd_CommandAdd( pAbc, "Various", "miter2", Abc_CommandMiter2, 1 ); + Cmd_CommandAdd( pAbc, "Various", "demiter", Abc_CommandDemiter, 1 ); + Cmd_CommandAdd( pAbc, "Various", "orpos", Abc_CommandOrPos, 1 ); + Cmd_CommandAdd( pAbc, "Various", "andpos", Abc_CommandAndPos, 1 ); + Cmd_CommandAdd( pAbc, "Various", "zeropo", Abc_CommandZeroPo, 1 ); + Cmd_CommandAdd( pAbc, "Various", "swappos", Abc_CommandSwapPos, 1 ); + Cmd_CommandAdd( pAbc, "Various", "removepo", Abc_CommandRemovePo, 1 ); + Cmd_CommandAdd( pAbc, "Various", "dropsat", Abc_CommandDropSat, 1 ); + Cmd_CommandAdd( pAbc, "Various", "addpi", Abc_CommandAddPi, 1 ); + Cmd_CommandAdd( pAbc, "Various", "addflop", Abc_CommandAddFlop, 1 ); + Cmd_CommandAdd( pAbc, "Various", "append", Abc_CommandAppend, 1 ); + Cmd_CommandAdd( pAbc, "Various", "putontop", Abc_CommandPutOnTop, 1 ); + Cmd_CommandAdd( pAbc, "Various", "frames", Abc_CommandFrames, 1 ); + Cmd_CommandAdd( pAbc, "Various", "dframes", Abc_CommandDFrames, 1 ); + Cmd_CommandAdd( pAbc, "Various", "sop", Abc_CommandSop, 0 ); + Cmd_CommandAdd( pAbc, "Various", "bdd", Abc_CommandBdd, 0 ); + Cmd_CommandAdd( pAbc, "Various", "aig", Abc_CommandAig, 0 ); + Cmd_CommandAdd( pAbc, "Various", "reorder", Abc_CommandReorder, 0 ); + Cmd_CommandAdd( pAbc, "Various", "bidec", Abc_CommandBidec, 1 ); + Cmd_CommandAdd( pAbc, "Various", "order", Abc_CommandOrder, 0 ); + Cmd_CommandAdd( pAbc, "Various", "muxes", Abc_CommandMuxes, 1 ); + Cmd_CommandAdd( pAbc, "Various", "cubes", Abc_CommandCubes, 1 ); + Cmd_CommandAdd( pAbc, "Various", "expand", Abc_CommandExpand, 1 ); + Cmd_CommandAdd( pAbc, "Various", "splitsop", Abc_CommandSplitSop, 1 ); + Cmd_CommandAdd( pAbc, "Various", "ext_seq_dcs", Abc_CommandExtSeqDcs, 0 ); + Cmd_CommandAdd( pAbc, "Various", "reach", Abc_CommandReach, 0 ); + Cmd_CommandAdd( pAbc, "Various", "cone", Abc_CommandCone, 1 ); + Cmd_CommandAdd( pAbc, "Various", "node", Abc_CommandNode, 1 ); + Cmd_CommandAdd( pAbc, "Various", "range", Abc_CommandRange, 1 ); + Cmd_CommandAdd( pAbc, "Various", "cof", Abc_CommandCof, 1 ); + Cmd_CommandAdd( pAbc, "Various", "topmost", Abc_CommandTopmost, 1 ); + Cmd_CommandAdd( pAbc, "Various", "bottommost", Abc_CommandBottommost, 1 ); + Cmd_CommandAdd( pAbc, "Various", "topand", Abc_CommandTopAnd, 1 ); + Cmd_CommandAdd( pAbc, "Various", "trim", Abc_CommandTrim, 1 ); + Cmd_CommandAdd( pAbc, "Various", "short_names", Abc_CommandShortNames, 0 ); + Cmd_CommandAdd( pAbc, "Various", "move_names", Abc_CommandMoveNames, 0 ); + Cmd_CommandAdd( pAbc, "Various", "exdc_free", Abc_CommandExdcFree, 1 ); + Cmd_CommandAdd( pAbc, "Various", "exdc_get", Abc_CommandExdcGet, 1 ); + Cmd_CommandAdd( pAbc, "Various", "exdc_set", Abc_CommandExdcSet, 1 ); + Cmd_CommandAdd( pAbc, "Various", "care_set", Abc_CommandCareSet, 1 ); + Cmd_CommandAdd( pAbc, "Various", "cut", Abc_CommandCut, 0 ); + Cmd_CommandAdd( pAbc, "Various", "espresso", Abc_CommandEspresso, 1 ); + Cmd_CommandAdd( pAbc, "Various", "gen", Abc_CommandGen, 0 ); + Cmd_CommandAdd( pAbc, "Various", "gentf", Abc_CommandGenTF, 0 ); + Cmd_CommandAdd( pAbc, "Various", "genat", Abc_CommandGenAT, 0 ); + Cmd_CommandAdd( pAbc, "Various", "genfsm", Abc_CommandGenFsm, 0 ); + Cmd_CommandAdd( pAbc, "Various", "cover", Abc_CommandCover, 1 ); + Cmd_CommandAdd( pAbc, "Various", "double", Abc_CommandDouble, 1 ); + Cmd_CommandAdd( pAbc, "Various", "inter", Abc_CommandInter, 1 ); + Cmd_CommandAdd( pAbc, "Various", "bb2wb", Abc_CommandBb2Wb, 0 ); + Cmd_CommandAdd( pAbc, "Various", "outdec", Abc_CommandOutdec, 1 ); + Cmd_CommandAdd( pAbc, "Various", "nodedup", Abc_CommandNodeDup, 1 ); + Cmd_CommandAdd( pAbc, "Various", "wrap", Abc_CommandWrap, 0 ); + Cmd_CommandAdd( pAbc, "Various", "testcolor", Abc_CommandTestColor, 0 ); + Cmd_CommandAdd( pAbc, "Various", "test", Abc_CommandTest, 0 ); +// Cmd_CommandAdd( pAbc, "Various", "qbf_solve", Abc_CommandTest, 0 ); + + Cmd_CommandAdd( pAbc, "Various", "qvar", Abc_CommandQuaVar, 1 ); + Cmd_CommandAdd( pAbc, "Various", "qrel", Abc_CommandQuaRel, 1 ); + Cmd_CommandAdd( pAbc, "Various", "qreach", Abc_CommandQuaReach, 1 ); + Cmd_CommandAdd( pAbc, "Various", "senseinput", Abc_CommandSenseInput, 1 ); + Cmd_CommandAdd( pAbc, "Various", "npnload", Abc_CommandNpnLoad, 0 ); + Cmd_CommandAdd( pAbc, "Various", "npnsave", Abc_CommandNpnSave, 0 ); + + Cmd_CommandAdd( pAbc, "Various", "send_aig", Abc_CommandSendAig, 0 ); + Cmd_CommandAdd( pAbc, "Various", "send_status", Abc_CommandSendStatus, 0 ); + + Cmd_CommandAdd( pAbc, "Various", "backup", Abc_CommandBackup, 0 ); + Cmd_CommandAdd( pAbc, "Various", "restore", Abc_CommandRestore, 0 ); + + Cmd_CommandAdd( pAbc, "Various", "minisat", Abc_CommandMinisat, 0 ); + Cmd_CommandAdd( pAbc, "Various", "minisimp", Abc_CommandMinisimp, 0 ); + + Cmd_CommandAdd( pAbc, "New AIG", "istrash", Abc_CommandIStrash, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "icut", Abc_CommandICut, 0 ); + Cmd_CommandAdd( pAbc, "New AIG", "irw", Abc_CommandIRewrite, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "drw", Abc_CommandDRewrite, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "drf", Abc_CommandDRefactor, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "dc2", Abc_CommandDc2, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "dchoice", Abc_CommandDChoice, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "dch", Abc_CommandDch, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "drwsat", Abc_CommandDrwsat, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "irws", Abc_CommandIRewriteSeq, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "iresyn", Abc_CommandIResyn, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "isat", Abc_CommandISat, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "ifraig", Abc_CommandIFraig, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "dfraig", Abc_CommandDFraig, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "csweep", Abc_CommandCSweep, 1 ); +// Cmd_CommandAdd( pAbc, "New AIG", "haig", Abc_CommandHaig, 1 ); + Cmd_CommandAdd( pAbc, "New AIG", "qbf", Abc_CommandQbf, 0 ); + + Cmd_CommandAdd( pAbc, "Fraiging", "fraig", Abc_CommandFraig, 1 ); + Cmd_CommandAdd( pAbc, "Fraiging", "fraig_trust", Abc_CommandFraigTrust, 1 ); + Cmd_CommandAdd( pAbc, "Fraiging", "fraig_store", Abc_CommandFraigStore, 0 ); + Cmd_CommandAdd( pAbc, "Fraiging", "fraig_restore", Abc_CommandFraigRestore, 1 ); + Cmd_CommandAdd( pAbc, "Fraiging", "fraig_clean", Abc_CommandFraigClean, 0 ); + Cmd_CommandAdd( pAbc, "Fraiging", "fraig_sweep", Abc_CommandFraigSweep, 1 ); + Cmd_CommandAdd( pAbc, "Fraiging", "dress", Abc_CommandFraigDress, 1 ); + Cmd_CommandAdd( pAbc, "Fraiging", "dump_equiv", Abc_CommandDumpEquiv, 0 ); + + Cmd_CommandAdd( pAbc, "Choicing", "rec_start3", Abc_CommandRecStart3, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_stop3", Abc_CommandRecStop3, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_ps3", Abc_CommandRecPs3, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_add3", Abc_CommandRecAdd3, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_dump3", Abc_CommandRecDump3, 0 ); + Cmd_CommandAdd( pAbc, "Choicing", "rec_merge3", Abc_CommandRecMerge3, 0 ); + + Cmd_CommandAdd( pAbc, "SC mapping", "map", Abc_CommandMap, 1 ); + Cmd_CommandAdd( pAbc, "SC mapping", "amap", Abc_CommandAmap, 1 ); + Cmd_CommandAdd( pAbc, "SC mapping", "phase_map", Abc_CommandPhaseMap, 1 ); + Cmd_CommandAdd( pAbc, "SC mapping", "stochmap", Abc_CommandStochMap, 1 ); + Cmd_CommandAdd( pAbc, "SC mapping", "unmap", Abc_CommandUnmap, 1 ); + Cmd_CommandAdd( pAbc, "SC mapping", "attach", Abc_CommandAttach, 1 ); + Cmd_CommandAdd( pAbc, "SC mapping", "superc", Abc_CommandSuperChoice, 1 ); + Cmd_CommandAdd( pAbc, "SC mapping", "supercl", Abc_CommandSuperChoiceLut, 1 ); + Cmd_CommandAdd( pAbc, "SC mapping", "timescale", Abc_CommandTimeScale, 0 ); + Cmd_CommandAdd( pAbc, "SC mapping", "rewire", Abc_CommandRewire, 1 ); + +// Cmd_CommandAdd( pAbc, "FPGA mapping", "fpga", Abc_CommandFpga, 1 ); +// Cmd_CommandAdd( pAbc, "FPGA mapping", "ffpga", Abc_CommandFpgaFast, 1 ); + Cmd_CommandAdd( pAbc, "FPGA mapping", "if", Abc_CommandIf, 1 ); + Cmd_CommandAdd( pAbc, "FPGA mapping", "ifif", Abc_CommandIfif, 1 ); + + Cmd_CommandAdd( pAbc, "DSD manager", "dsd_save", Abc_CommandDsdSave, 0 ); + Cmd_CommandAdd( pAbc, "DSD manager", "dsd_load", Abc_CommandDsdLoad, 0 ); + Cmd_CommandAdd( pAbc, "DSD manager", "dsd_free", Abc_CommandDsdFree, 0 ); + Cmd_CommandAdd( pAbc, "DSD manager", "dsd_ps", Abc_CommandDsdPs, 0 ); + Cmd_CommandAdd( pAbc, "DSD manager", "dsd_match", Abc_CommandDsdMatch, 0 ); + Cmd_CommandAdd( pAbc, "DSD manager", "dsd_merge", Abc_CommandDsdMerge, 0 ); + Cmd_CommandAdd( pAbc, "DSD manager", "dsd_filter", Abc_CommandDsdFilter, 0 ); + +// Cmd_CommandAdd( pAbc, "Sequential", "scut", Abc_CommandScut, 0 ); + Cmd_CommandAdd( pAbc, "Sequential", "init", Abc_CommandInit, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "zero", Abc_CommandZero, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "undc", Abc_CommandUndc, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "onehot", Abc_CommandOneHot, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "pipe", Abc_CommandPipe, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "retime", Abc_CommandRetime, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "dretime", Abc_CommandDRetime, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "fretime", Abc_CommandFlowRetime, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "cretime", Abc_CommandCRetime, 1 ); +// Cmd_CommandAdd( pAbc, "Sequential", "sfpga", Abc_CommandSeqFpga, 1 ); +// Cmd_CommandAdd( pAbc, "Sequential", "smap", Abc_CommandSeqMap, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "ssweep", Abc_CommandSeqSweep, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "scorr", Abc_CommandSeqSweep2, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "testssw", Abc_CommandTestSeqSweep, 0 ); + Cmd_CommandAdd( pAbc, "Sequential", "testscorr", Abc_CommandTestScorr, 0 ); + Cmd_CommandAdd( pAbc, "Sequential", "lcorr", Abc_CommandLcorr, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "scleanup", Abc_CommandSeqCleanup, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "cycle", Abc_CommandCycle, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "xsim", Abc_CommandXsim, 0 ); + Cmd_CommandAdd( pAbc, "Sequential", "sim", Abc_CommandSim, 0 ); + Cmd_CommandAdd( pAbc, "Sequential", "sim3", Abc_CommandSim3, 0 ); + Cmd_CommandAdd( pAbc, "Sequential", "phase", Abc_CommandDarPhase, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "synch", Abc_CommandSynch, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "clockgate", Abc_CommandClockGate, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "extwin", Abc_CommandExtWin, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "inswin", Abc_CommandInsWin, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "symfun", Abc_CommandSymFun, 0 ); + Cmd_CommandAdd( pAbc, "Sequential", "atmap", Abc_CommandATMap, 0 ); + Cmd_CommandAdd( pAbc, "Sequential", "permute", Abc_CommandPermute, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "unpermute", Abc_CommandUnpermute, 1 ); + Cmd_CommandAdd( pAbc, "Sequential", "cubeenum", Abc_CommandCubeEnum, 0 ); + Cmd_CommandAdd( pAbc, "Sequential", "pathenum", Abc_CommandPathEnum, 0 ); + Cmd_CommandAdd( pAbc, "Sequential", "funenum", Abc_CommandFunEnum, 0 ); + + Cmd_CommandAdd( pAbc, "Verification", "cec", Abc_CommandCec, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "dcec", Abc_CommandDCec, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "dsec", Abc_CommandDSec, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "dprove", Abc_CommandDProve, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "absec", Abc_CommandAbSec, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "simsec", Abc_CommandSimSec, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "match", Abc_CommandMatch, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "sat", Abc_CommandSat, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "dsat", Abc_CommandDSat, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "xsat", Abc_CommandXSat, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "satoko", Abc_CommandSatoko, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "&satoko", Abc_CommandAbc9Satoko, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "&sat3", Abc_CommandAbc9Sat3, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "&kissat", Abc_CommandAbc9Kissat, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "psat", Abc_CommandPSat, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "prove", Abc_CommandProve, 1 ); + Cmd_CommandAdd( pAbc, "Verification", "iprove", Abc_CommandIProve, 1 ); + Cmd_CommandAdd( pAbc, "Verification", "debug", Abc_CommandDebug, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "eco", Abc_CommandEco, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "bmc", Abc_CommandBmc, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "bmc2", Abc_CommandBmc2, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "bmc3", Abc_CommandBmc3, 1 ); + Cmd_CommandAdd( pAbc, "Verification", "int", Abc_CommandBmcInter, 1 ); + Cmd_CommandAdd( pAbc, "Verification", "indcut", Abc_CommandIndcut, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "enlarge", Abc_CommandEnlarge, 1 ); + Cmd_CommandAdd( pAbc, "Verification", "tempor", Abc_CommandTempor, 1 ); + Cmd_CommandAdd( pAbc, "Verification", "ind", Abc_CommandInduction, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "constr", Abc_CommandConstr, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "unfold", Abc_CommandUnfold, 1 ); + Cmd_CommandAdd( pAbc, "Verification", "fold", Abc_CommandFold, 1 ); + Cmd_CommandAdd( pAbc, "Verification", "unfold2", Abc_CommandUnfold2, 1 ); // jlong + Cmd_CommandAdd( pAbc, "Verification", "fold2", Abc_CommandFold2, 1 ); // jlong + Cmd_CommandAdd( pAbc, "Verification", "bm", Abc_CommandBm, 1 ); + Cmd_CommandAdd( pAbc, "Verification", "bm2", Abc_CommandBm2, 1 ); + Cmd_CommandAdd( pAbc, "Verification", "saucy3", Abc_CommandSaucy, 1 ); + Cmd_CommandAdd( pAbc, "Verification", "testcex", Abc_CommandTestCex, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "pdr", Abc_CommandPdr, 0 ); +#ifdef ABC_USE_CUDD + Cmd_CommandAdd( pAbc, "Verification", "reconcile", Abc_CommandReconcile, 1 ); +#endif + Cmd_CommandAdd( pAbc, "Verification", "cexsave", Abc_CommandCexSave, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "cexload", Abc_CommandCexLoad, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "cexcut", Abc_CommandCexCut, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "cexmerge", Abc_CommandCexMerge, 0 ); +// Cmd_CommandAdd( pAbc, "Verification", "cexmin", Abc_CommandCexMin, 0 ); + Cmd_CommandAdd( pAbc, "Verification", "dualrail", Abc_CommandDualRail, 1 ); + Cmd_CommandAdd( pAbc, "Verification", "blockpo", Abc_CommandBlockPo, 1 ); + Cmd_CommandAdd( pAbc, "Verification", "iso", Abc_CommandIso, 1 ); + + Cmd_CommandAdd( pAbc, "Various", "save", Abc_CommandAbcSave, 0 ); + Cmd_CommandAdd( pAbc, "Various", "load", Abc_CommandAbcLoad, 0 ); + + Cmd_CommandAdd( pAbc, "ABC9", "&get", Abc_CommandAbc9Get, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&put", Abc_CommandAbc9Put, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&move_names", Abc_CommandAbc9MoveNames, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&save", Abc_CommandAbc9Save, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&save2", Abc_CommandAbc9Save2, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&saveaig", Abc_CommandAbc9SaveAig, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&load", Abc_CommandAbc9Load, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&load2", Abc_CommandAbc9Load2, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&loadaig", Abc_CommandAbc9LoadAig, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&r", Abc_CommandAbc9Read, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&read", Abc_CommandAbc9Read, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&read_blif", Abc_CommandAbc9ReadBlif, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&read_cblif", Abc_CommandAbc9ReadCBlif, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&read_stg", Abc_CommandAbc9ReadStg, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&read_ver", Abc_CommandAbc9ReadVer, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&write_ver", Abc_CommandAbc9WriteVer, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&w", Abc_CommandAbc9Write, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&write", Abc_CommandAbc9Write, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&wlut", Abc_CommandAbc9WriteLut, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&ps", Abc_CommandAbc9Ps, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&pfan", Abc_CommandAbc9PFan, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&pms", Abc_CommandAbc9Pms, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&psig", Abc_CommandAbc9PSig, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&status", Abc_CommandAbc9Status, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&profile", Abc_CommandAbc9MuxProfile, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&muxpos", Abc_CommandAbc9MuxPos, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&muxstr", Abc_CommandAbc9MuxStr, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&muxdec", Abc_CommandAbc9MuxDec, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&print_truth", Abc_CommandAbc9PrintTruth, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&unate", Abc_CommandAbc9Unate, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&rex2gia", Abc_CommandAbc9Rex2Gia, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&rexwalk", Abc_CommandAbc9RexWalk, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&show", Abc_CommandAbc9Show, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&setregnum", Abc_CommandAbc9SetRegNum, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&st", Abc_CommandAbc9Strash, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&topand", Abc_CommandAbc9Topand, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&add1hot", Abc_CommandAbc9Add1Hot, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&cof", Abc_CommandAbc9Cof, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&cofs", Abc_CommandAbc9Cofs, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&trim", Abc_CommandAbc9Trim, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&dfs", Abc_CommandAbc9Dfs, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&sim", Abc_CommandAbc9Sim, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&sim2", Abc_CommandAbc9Sim2, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&sim3", Abc_CommandAbc9Sim3, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&mlgen", Abc_CommandAbc9MLGen, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&mltest", Abc_CommandAbc9MLTest, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&iwls21test", Abc_CommandAbc9Iwls21Test, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&sim_read", Abc_CommandAbc9ReadSim, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&sim_write", Abc_CommandAbc9WriteSim, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&sim_print", Abc_CommandAbc9PrintSim, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&sim_gen", Abc_CommandAbc9GenSim, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&simrsb", Abc_CommandAbc9SimRsb, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&resim", Abc_CommandAbc9Resim, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&speci", Abc_CommandAbc9SpecI, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&equiv", Abc_CommandAbc9Equiv, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&equiv2", Abc_CommandAbc9Equiv2, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&equiv3", Abc_CommandAbc9Equiv3, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&semi", Abc_CommandAbc9Semi, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "×", Abc_CommandAbc9Times, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&frames", Abc_CommandAbc9Frames, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&retime", Abc_CommandAbc9Retime, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&enable", Abc_CommandAbc9Enable, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&dc2", Abc_CommandAbc9Dc2, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&dsd", Abc_CommandAbc9Dsd, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&bidec", Abc_CommandAbc9Bidec, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&shrink", Abc_CommandAbc9Shrink, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&fx", Abc_CommandAbc9Fx, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&extract", Abc_CommandAbc9Extract, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&b", Abc_CommandAbc9Balance, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&blut", Abc_CommandAbc9BalanceLut, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&resub", Abc_CommandAbc9Resub, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&reshape", Abc_CommandAbc9Reshape, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&syn2", Abc_CommandAbc9Syn2, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&syn3", Abc_CommandAbc9Syn3, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&syn4", Abc_CommandAbc9Syn4, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&synch2", Abc_CommandAbc9Synch2, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&false", Abc_CommandAbc9False, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&miter", Abc_CommandAbc9Miter, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&miter2", Abc_CommandAbc9Miter2, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&append", Abc_CommandAbc9Append, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&scl", Abc_CommandAbc9Scl, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&lcorr", Abc_CommandAbc9Lcorr, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&scorr", Abc_CommandAbc9Scorr, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&choice", Abc_CommandAbc9Choice, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&sat", Abc_CommandAbc9Sat, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&satenum", Abc_CommandAbc9SatEnum, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&adv_sim_gen", Abc_CommandAbc9AdvGenSim, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&fraig", Abc_CommandAbc9Fraig, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&cfraig", Abc_CommandAbc9CFraig, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&srm", Abc_CommandAbc9Srm, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&srm2", Abc_CommandAbc9Srm2, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&filter", Abc_CommandAbc9Filter, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&reduce", Abc_CommandAbc9Reduce, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&equiv_mark", Abc_CommandAbc9EquivMark, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&equiv_filter", Abc_CommandAbc9EquivFilter, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&cec", Abc_CommandAbc9Cec, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&icec", Abc_CommandAbc9ICec, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&verify", Abc_CommandAbc9Verify, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&sweep", Abc_CommandAbc9Sweep, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&force", Abc_CommandAbc9Force, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&embed", Abc_CommandAbc9Embed, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&sopb", Abc_CommandAbc9Sopb, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&dsdb", Abc_CommandAbc9Dsdb, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&flow", Abc_CommandAbc9Flow, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&flow2", Abc_CommandAbc9Flow2, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&flow3", Abc_CommandAbc9Flow3, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&if", Abc_CommandAbc9If, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&iff", Abc_CommandAbc9Iff, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&iiff", Abc_CommandAbc9Iiff, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&if2", Abc_CommandAbc9If2, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&sif", Abc_CommandAbc9Sif, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&jf", Abc_CommandAbc9Jf, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&kf", Abc_CommandAbc9Kf, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&lf", Abc_CommandAbc9Lf, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&mf", Abc_CommandAbc9Mf, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&nf", Abc_CommandAbc9Nf, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&of", Abc_CommandAbc9Of, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&simap", Abc_CommandAbc9Simap, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&exmap", Abc_CommandAbc9Exmap, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&pack", Abc_CommandAbc9Pack, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&edge", Abc_CommandAbc9Edge, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&satlut", Abc_CommandAbc9SatLut, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&lnetread", Abc_CommandAbc9LNetRead, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&lnetsim", Abc_CommandAbc9LNetSim, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&lneteval", Abc_CommandAbc9LNetEval, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&lnetopt", Abc_CommandAbc9LNetOpt, 0 ); +//#ifndef _WIN32 + Cmd_CommandAdd( pAbc, "ABC9", "&ttopt", Abc_CommandAbc9Ttopt, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&transduction", Abc_CommandAbc9Transduction, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&transtoch" , Abc_CommandAbc9TranStoch, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&rrr", Abc_CommandAbc9Rrr, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&rewire" , Abc_CommandAbc9Rewire, 0 ); +//#endif + Cmd_CommandAdd( pAbc, "ABC9", "&lnetmap", Abc_CommandAbc9LNetMap, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&unmap", Abc_CommandAbc9Unmap, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&struct", Abc_CommandAbc9Struct, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&trace", Abc_CommandAbc9Trace, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&speedup", Abc_CommandAbc9Speedup, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&era", Abc_CommandAbc9Era, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&dch", Abc_CommandAbc9Dch, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&rpm", Abc_CommandAbc9Rpm, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&back_reach", Abc_CommandAbc9BackReach, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&posplit", Abc_CommandAbc9Posplit, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&permute", Abc_CommandAbc9Permute, 0 ); +#ifdef ABC_USE_CUDD + Cmd_CommandAdd( pAbc, "ABC9", "&reachm", Abc_CommandAbc9ReachM, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&reachp", Abc_CommandAbc9ReachP, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&reachn", Abc_CommandAbc9ReachN, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&reachy", Abc_CommandAbc9ReachY, 0 ); +#endif + Cmd_CommandAdd( pAbc, "ABC9", "&undo", Abc_CommandAbc9Undo, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&mesh", Abc_CommandAbc9Mesh, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&iso", Abc_CommandAbc9Iso, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&isonpn", Abc_CommandAbc9IsoNpn, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&isost", Abc_CommandAbc9IsoSt, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&store", Abc_CommandAbc9Store, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&compare", Abc_CommandAbc9Compare, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&reveng", Abc_CommandAbc9RevEng, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&uif", Abc_CommandAbc9Uif, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&cexinfo", Abc_CommandAbc9CexInfo, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&cycle", Abc_CommandAbc9Cycle, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&cone", Abc_CommandAbc9Cone, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&slice", Abc_CommandAbc9Slice, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&popart", Abc_CommandAbc9PoPart, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&gprove", Abc_CommandAbc9GroupProve, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&mprove", Abc_CommandAbc9MultiProve, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&splitprove", Abc_CommandAbc9SplitProve, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&sprove", Abc_CommandAbc9SProve, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&splitsat", Abc_CommandAbc9SplitSat, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&bmc", Abc_CommandAbc9Bmc, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&bmcs", Abc_CommandAbc9SBmc, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&chainbmc", Abc_CommandAbc9ChainBmc, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&bcore", Abc_CommandAbc9BCore, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&icheck", Abc_CommandAbc9ICheck, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&sattest", Abc_CommandAbc9SatTest, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&fftest", Abc_CommandAbc9FFTest, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&qbf", Abc_CommandAbc9Qbf, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&qvar", Abc_CommandAbc9QVar, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&genqbf", Abc_CommandAbc9GenQbf, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&homoqbf", Abc_CommandAbc9HomoQbf, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&satfx", Abc_CommandAbc9SatFx, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&satclp", Abc_CommandAbc9SatClp, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&inse", Abc_CommandAbc9Inse, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&maxi", Abc_CommandAbc9Maxi, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&bmci", Abc_CommandAbc9Bmci, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&poxsim", Abc_CommandAbc9PoXsim, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&demiter", Abc_CommandAbc9Demiter, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&fadds", Abc_CommandAbc9Fadds, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&atree", Abc_CommandAbc9ATree, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&polyn", Abc_CommandAbc9Polyn, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&acec", Abc_CommandAbc9Acec, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&anorm", Abc_CommandAbc9Anorm, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&decla", Abc_CommandAbc9Decla, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&esop", Abc_CommandAbc9Esop, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&exorcism", Abc_CommandAbc9Exorcism, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&mfs", Abc_CommandAbc9Mfs, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&mfsd", Abc_CommandAbc9Mfsd, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&deepsyn", Abc_CommandAbc9DeepSyn, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&randsyn", Abc_CommandAbc9RandSyn, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&satsyn", Abc_CommandAbc9SatSyn, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&stochsyn", Abc_CommandAbc9StochSyn, 0 ); +// Cmd_CommandAdd( pAbc, "ABC9", "&popart2", Abc_CommandAbc9PoPart2, 0 ); +// Cmd_CommandAdd( pAbc, "ABC9", "&cexcut", Abc_CommandAbc9CexCut, 0 ); +// Cmd_CommandAdd( pAbc, "ABC9", "&cexmerge", Abc_CommandAbc9CexMerge, 0 ); +// Cmd_CommandAdd( pAbc, "ABC9", "&cexmin", Abc_CommandAbc9CexMin, 0 ); + + Cmd_CommandAdd( pAbc, "Abstraction", "&abs_create", Abc_CommandAbc9AbsCreate, 0 ); + Cmd_CommandAdd( pAbc, "Abstraction", "&abs_derive", Abc_CommandAbc9AbsDerive, 0 ); + Cmd_CommandAdd( pAbc, "Abstraction", "&abs_refine", Abc_CommandAbc9AbsRefine, 0 ); + Cmd_CommandAdd( pAbc, "Abstraction", "&gla_derive", Abc_CommandAbc9GlaDerive, 0 ); + Cmd_CommandAdd( pAbc, "Abstraction", "&gla_refine", Abc_CommandAbc9GlaRefine, 0 ); + Cmd_CommandAdd( pAbc, "Abstraction", "&gla_shrink", Abc_CommandAbc9GlaShrink, 0 ); + Cmd_CommandAdd( pAbc, "Abstraction", "&gla", Abc_CommandAbc9Gla, 0 ); + Cmd_CommandAdd( pAbc, "Abstraction", "&vta", Abc_CommandAbc9Vta, 0 ); + Cmd_CommandAdd( pAbc, "Abstraction", "&vta_gla", Abc_CommandAbc9Vta2Gla, 0 ); + Cmd_CommandAdd( pAbc, "Abstraction", "&gla_vta", Abc_CommandAbc9Gla2Vta, 0 ); + Cmd_CommandAdd( pAbc, "Abstraction", "&fla_gla", Abc_CommandAbc9Fla2Gla, 0 ); + Cmd_CommandAdd( pAbc, "Abstraction", "&gla_fla", Abc_CommandAbc9Gla2Fla, 0 ); + + Cmd_CommandAdd( pAbc, "Liveness", "l2s", Abc_CommandAbcLivenessToSafety, 0 ); + Cmd_CommandAdd( pAbc, "Liveness", "l2ssim", Abc_CommandAbcLivenessToSafetySim, 0 ); + Cmd_CommandAdd( pAbc, "Liveness", "l3s", Abc_CommandAbcLivenessToSafetyWithLTL, 0 ); + Cmd_CommandAdd( pAbc, "Liveness", "kcs", Abc_CommandCS_kLiveness, 0 ); + Cmd_CommandAdd( pAbc, "Liveness", "nck", Abc_CommandNChooseK, 0 ); + + Cmd_CommandAdd( pAbc, "ABC9", "&gen", Abc_CommandAbc9Gen, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&cfs", Abc_CommandAbc9Cfs, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&prodadd", Abc_CommandAbc9ProdAdd, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&addflop", Abc_CommandAbc9AddFlop, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&bmiter", Abc_CommandAbc9BMiter, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&gen_hie", Abc_CommandAbc9GenHie, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&putontop", Abc_CommandAbc9PutOnTop, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&brecover", Abc_CommandAbc9BRecover, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&str_eco", Abc_CommandAbc9StrEco, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&gencex", Abc_CommandAbc9GenCex, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&odc", Abc_CommandAbc9Odc, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&genrel", Abc_CommandAbc9GenRel, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&genmux", Abc_CommandAbc9GenMux, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&gencomp", Abc_CommandAbc9GenComp, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&gensorter", Abc_CommandAbc9GenSorter, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&genneuron", Abc_CommandAbc9GenNeuron, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&window", Abc_CommandAbc9Window, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&funabs", Abc_CommandAbc9FunAbs, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&dsdinfo", Abc_CommandAbc9DsdInfo, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&funtrace", Abc_CommandAbc9FunTrace, 0 ); + Cmd_CommandAdd( pAbc, "ABC9", "&mulfind", Abc_CommandAbc9MulFind, 0 ); + + Cmd_CommandAdd( pAbc, "ABC9", "&test", Abc_CommandAbc9Test, 0 ); + + Cmd_CommandAdd( pAbc, "ABC9", "&eslim", Abc_CommandAbc9eSLIM, 0 ); + { +// extern Mf_ManTruthCount(); +// Mf_ManTruthCount(); + } + + { + extern void Dar_LibStart(); + Dar_LibStart(); + } + { +// extern void Dau_DsdTest(); +// Dau_DsdTest(); +// extern void If_ManSatTest(); +// If_ManSatTest(); + } + +// if ( Sdm_ManCanRead() ) +// Sdm_ManRead(); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Abc_End( Abc_Frame_t * pAbc ) +{ + extern Abc_Frame_t * Abc_FrameGetGlobalFrame(); + Abc_FrameClearDesign(); + Cnf_ManFree(); + { + extern int Abc_NtkCompareAndSaveBest( Abc_Ntk_t * pNtk ); + Abc_NtkCompareAndSaveBest( NULL ); + } + { + extern void Dar_LibStop(); + Dar_LibStop(); + } + { + extern void Aig_RManQuit(); + Aig_RManQuit(); + } + { + extern void Npn_ManClean(); + Npn_ManClean(); + } + { + extern void Sdm_ManQuit(); + Sdm_ManQuit(); + } + Abc_NtkFraigStoreClean(); + Gia_ManStopP( &pAbc->pGia ); + Gia_ManStopP( &pAbc->pGia2 ); + Gia_ManStopP( &pAbc->pGiaBest ); + Gia_ManStopP( &pAbc->pGiaBest2 ); + Gia_ManStopP( &pAbc->pGiaSaved ); + if ( Abc_NtkRecIsRunning3() ) + Abc_NtkRecStop3(); +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int fFactor; + int fSaveBest; + int fDumpResult; + int fUseLutLib; + int fPrintTime; + int fPrintMuxes; + int fPower; + int fGlitch; + int fSkipBuf; + int fSkipSmall; + int fPrintMem; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + + // set the defaults + fFactor = 0; + fSaveBest = 0; + fDumpResult = 0; + fUseLutLib = 0; + fPrintTime = 0; + fPrintMuxes = 0; + fPower = 0; + fGlitch = 0; + fSkipBuf = 0; + fSkipSmall = 0; + fPrintMem = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "fbdltmpgscuh" ) ) != EOF ) + { + switch ( c ) + { + case 'f': + fFactor ^= 1; + break; + case 'b': + fSaveBest ^= 1; + break; + case 'd': + fDumpResult ^= 1; + break; + case 'l': + fUseLutLib ^= 1; + break; + case 't': + fPrintTime ^= 1; + break; + case 'm': + fPrintMuxes ^= 1; + break; + case 'p': + fPower ^= 1; + break; + case 'g': + fGlitch ^= 1; + break; + case 's': + fSkipBuf ^= 1; + break; + case 'c': + fSkipSmall ^= 1; + break; + case 'u': + fPrintMem ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) && fUseLutLib ) + { + Abc_Print( -1, "Cannot print LUT delay for a non-logic network.\n" ); + return 1; + } + Abc_NtkPrintStats( pNtk, fFactor, fSaveBest, fDumpResult, fUseLutLib, fPrintMuxes, fPower, fGlitch, fSkipBuf, fSkipSmall, fPrintMem ); + if ( fPrintTime ) + { + pAbc->TimeTotal += pAbc->TimeCommand; + Abc_Print( 1, "elapse: %3.2f seconds, total: %3.2f seconds\n", pAbc->TimeCommand, pAbc->TimeTotal ); + pAbc->TimeCommand = 0.0; + } + return 0; + +usage: + Abc_Print( -2, "usage: print_stats [-fbdltmpgscuh]\n" ); + Abc_Print( -2, "\t prints the network statistics\n" ); + Abc_Print( -2, "\t-f : toggles printing the literal count in the factored forms [default = %s]\n", fFactor? "yes": "no" ); + Abc_Print( -2, "\t-b : toggles saving the best logic network in \"best.blif\" [default = %s]\n", fSaveBest? "yes": "no" ); + Abc_Print( -2, "\t-d : toggles dumping statistics about the network into file [default = %s]\n", fDumpResult? "yes": "no" ); + Abc_Print( -2, "\t-l : toggles printing delay of LUT mapping using LUT library [default = %s]\n", fUseLutLib? "yes": "no" ); + Abc_Print( -2, "\t-t : toggles printing runtime statistics [default = %s]\n", fPrintTime? "yes": "no" ); + Abc_Print( -2, "\t-m : toggles printing MUX statistics [default = %s]\n", fPrintMuxes? "yes": "no" ); + Abc_Print( -2, "\t-p : toggles printing power dissipation due to switching [default = %s]\n", fPower? "yes": "no" ); + Abc_Print( -2, "\t-g : toggles printing percentage of increased power due to glitching [default = %s]\n", fGlitch? "yes": "no" ); + Abc_Print( -2, "\t-s : toggles not counting single-output nodes as nodes [default = %s]\n", fSkipBuf? "yes": "no" ); + Abc_Print( -2, "\t-c : toggles not counting constants and single-output nodes as nodes [default = %s]\n", fSkipSmall? "yes": "no" ); + Abc_Print( -2, "\t-u : toggles printing memory usage [default = %s]\n", fPrintMem? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintExdc( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkTemp; + double Percentage; + int fShort; + int c; + int fPrintDc; + extern double Abc_NtkSpacePercentage( Abc_Obj_t * pNode ); + pNtk = Abc_FrameReadNtk(pAbc); + + // set the defaults + fShort = 1; + fPrintDc = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "sdh" ) ) != EOF ) + { + switch ( c ) + { + case 's': + fShort ^= 1; + break; + case 'd': + fPrintDc ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( pNtk->pExdc == NULL ) + { + Abc_Print( -1, "Network has no EXDC.\n" ); + return 1; + } + + if ( fPrintDc ) + { + if ( !Abc_NtkIsStrash(pNtk->pExdc) ) + { + pNtkTemp = Abc_NtkStrash(pNtk->pExdc, 0, 0, 0); + Percentage = Abc_NtkSpacePercentage( Abc_ObjChild0( Abc_NtkPo(pNtkTemp, 0) ) ); + Abc_NtkDelete( pNtkTemp ); + } + else + Percentage = Abc_NtkSpacePercentage( Abc_ObjChild0( Abc_NtkPo(pNtk->pExdc, 0) ) ); + + Abc_Print( 1, "EXDC network statistics: " ); + Abc_Print( 1, "(" ); + if ( Percentage > 0.05 && Percentage < 99.95 ) + Abc_Print( 1, "%.2f", Percentage ); + else if ( Percentage > 0.000005 && Percentage < 99.999995 ) + Abc_Print( 1, "%.6f", Percentage ); + else + Abc_Print( 1, "%f", Percentage ); + Abc_Print( 1, " %% don't-cares)\n" ); + } + else + Abc_Print( 1, "EXDC network statistics: \n" ); + Abc_NtkPrintStats( pNtk->pExdc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + return 0; + +usage: + Abc_Print( -2, "usage: print_exdc [-dh]\n" ); + Abc_Print( -2, "\t prints the EXDC network statistics\n" ); + Abc_Print( -2, "\t-d : toggles printing don't-care percentage [default = %s]\n", fPrintDc? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintIo( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Abc_Obj_t * pNode; + int c, fPrintFlops = 1; + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "fh" ) ) != EOF ) + { + switch ( c ) + { + case 'f': + fPrintFlops ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( argc > globalUtilOptind + 1 ) + { + Abc_Print( -1, "Wrong number of auguments.\n" ); + goto usage; + } + + if ( argc == globalUtilOptind + 1 ) + { + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + Abc_NodePrintFanio( stdout, pNode ); + return 0; + } + // print the nodes + Abc_NtkPrintIo( stdout, pNtk, fPrintFlops ); + return 0; + +usage: + Abc_Print( -2, "usage: print_io [-fh] \n" ); + Abc_Print( -2, "\t prints the PIs/POs/flops or fanins/fanouts of a node\n" ); + Abc_Print( -2, "\t-f : toggles printing flops [default = %s]\n", fPrintFlops? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\tnode : the node to print fanins/fanouts\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintLatch( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fPrintSccs; + extern void Abc_NtkPrintSccs( Abc_Ntk_t * pNtk, int fVerbose ); + + // set defaults + fPrintSccs = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "sh" ) ) != EOF ) + { + switch ( c ) + { + case 's': + fPrintSccs ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + // print the nodes + Abc_NtkPrintLatch( stdout, pNtk ); + if ( fPrintSccs ) + Abc_NtkPrintSccs( pNtk, 0 ); + return 0; + +usage: + Abc_Print( -2, "usage: print_latch [-sh]\n" ); + Abc_Print( -2, "\t prints information about latches\n" ); + Abc_Print( -2, "\t-s : toggles printing SCCs of registers [default = %s]\n", fPrintSccs? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintFanio( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fUseFanio = 0; + int fUsePio = 0; + int fUseSupp = 0; + int fUseCone = 0; + int fMffc = 0; + int fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "fiscmvh" ) ) != EOF ) + { + switch ( c ) + { + case 'f': + fUseFanio ^= 1; + break; + case 'i': + fUsePio ^= 1; + break; + case 's': + fUseSupp ^= 1; + break; + case 'c': + fUseCone ^= 1; + break; + case 'm': + fMffc ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + // print the nodes + if ( fMffc || !fVerbose ) + Abc_NtkPrintFanioNew( stdout, pNtk, fMffc ); + else + { + if ( fUseFanio + fUsePio + fUseSupp + fUseCone == 1 ) + Abc_NtkPrintFanio( stdout, pNtk, fUseFanio, fUsePio, fUseSupp, fUseCone ); + else + printf( "Exactly one of the switches \"-f\", \"-i\", \"-s\", \"-c\" should be enabled.\n" ); + } + return 0; + +usage: + Abc_Print( -2, "usage: print_fanio [-fiscmvh]\n" ); + Abc_Print( -2, "\t prints the statistics about different objects in the network\n" ); + Abc_Print( -2, "\t-f : toggles considering fanins/fanouts of all nodes [default = %s]\n", fUseFanio? "yes": "no" ); + Abc_Print( -2, "\t-i : toggles considering fanins/fanouts of CI/CO [default = %s]\n", fUsePio? "yes": "no" ); + Abc_Print( -2, "\t-s : toggles considering TFO/TFI support sizes of CI/CO [default = %s]\n", fUseSupp? "yes": "no" ); + Abc_Print( -2, "\t-c : toggles considering TFO/TFI cone sizes of CI/CO [default = %s]\n", fUseCone? "yes": "no" ); + Abc_Print( -2, "\t-m : toggles printing MFFC sizes instead of fanouts [default = %s]\n", fMffc? "yes": "no" ); + Abc_Print( -2, "\t-v : toggles verbose way of printing the stats [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintMffc( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + extern void Abc_NtkPrintMffc( FILE * pFile, Abc_Ntk_t * pNtk ); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + // print the nodes + Abc_NtkPrintMffc( stdout, pNtk ); + return 0; + +usage: + Abc_Print( -2, "usage: print_mffc [-h]\n" ); + Abc_Print( -2, "\t prints the MFFC of each node in the network\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintFactor( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_NodePrintSop( FILE * pFile, Abc_Obj_t * pNode, int fUseRealNames ); + extern void Abc_NtkPrintSop( FILE * pFile, Abc_Ntk_t * pNtk, int fUseRealNames ); + + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Abc_Obj_t * pNode; + int c, fSop = 0; + int fUseRealNames; + + // set defaults + fUseRealNames = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "snh" ) ) != EOF ) + { + switch ( c ) + { + case 's': + fSop ^= 1; + break; + case 'n': + fUseRealNames ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsSopLogic(pNtk) ) + { + Abc_Print( -1, "Printing factored forms can be done for SOP networks.\n" ); + return 1; + } + + if ( argc > globalUtilOptind + 1 ) + { + Abc_Print( -1, "Wrong number of auguments.\n" ); + goto usage; + } + + if ( argc == globalUtilOptind + 1 ) + { + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + if ( fSop ) + Abc_NodePrintSop( stdout, pNode, fUseRealNames ); + else + Abc_NodePrintFactor( stdout, pNode, fUseRealNames ); + return 0; + } + // print the nodes + if ( fSop ) + Abc_NtkPrintSop( stdout, pNtk, fUseRealNames ); + else + Abc_NtkPrintFactor( stdout, pNtk, fUseRealNames ); + return 0; + +usage: + Abc_Print( -2, "usage: print_factor [-snh] \n" ); + Abc_Print( -2, "\t prints the factored forms (FFs) of nodes\n" ); + Abc_Print( -2, "\t-s : toggles printing SOP instead of FF [default = %s]\n", fSop? "SOP": "FF" ); + Abc_Print( -2, "\t-n : toggles real/dummy fanin names [default = %s]\n", fUseRealNames? "real": "dummy" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\tnode : (optional) one node to consider\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintLevel( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Abc_Obj_t * pNode; + int c; + int fListNodes; + int fProfile; + int fOutputs; + int fVerbose; + + // set defaults + fListNodes = 0; + fProfile = 1; + fOutputs = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "npovh" ) ) != EOF ) + { + switch ( c ) + { + case 'n': + fListNodes ^= 1; + break; + case 'p': + fProfile ^= 1; + break; + case 'o': + fOutputs ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !fProfile && !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for AIGs (run \"strash\").\n" ); + return 1; + } + + if ( argc > globalUtilOptind + 1 ) + { + Abc_Print( -1, "Wrong number of auguments.\n" ); + goto usage; + } + + if ( argc == globalUtilOptind + 1 ) + { + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + Abc_NodePrintLevel( stdout, pNode ); + return 0; + } + // process all COs + Abc_NtkPrintLevel( stdout, pNtk, fProfile, fListNodes, fOutputs, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: print_level [-npovh] \n" ); + Abc_Print( -2, "\t prints information about node level and cone size\n" ); + Abc_Print( -2, "\t-n : toggles printing nodes by levels [default = %s]\n", fListNodes? "yes": "no" ); + Abc_Print( -2, "\t-p : toggles printing level profile [default = %s]\n", fProfile? "yes": "no" ); + Abc_Print( -2, "\t-o : toggles printing output levels [default = %s]\n", fOutputs? "yes": "no" ); + Abc_Print( -2, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\tnode : (optional) one node to consider\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintSupport( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Vec_Ptr_t * vSuppFun; + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fStruct; + int fVerbose; + int fVeryVerbose; + extern Vec_Ptr_t * Sim_ComputeFunSupp( Abc_Ntk_t * pNtk, int fVerbose ); + extern void Abc_NtkPrintStrSupports( Abc_Ntk_t * pNtk, int fMatrix ); + + // set defaults + fStruct = 1; + fVerbose = 0; + fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "svwh" ) ) != EOF ) + { + switch ( c ) + { + case 's': + fStruct ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + // print support information + if ( fStruct ) + { + Abc_NtkPrintStrSupports( pNtk, fVeryVerbose ); + return 0; + } + + if ( !Abc_NtkIsComb(pNtk) ) + { + Abc_Print( -1, "This command works only for combinational networks (run \"comb\").\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for AIGs (run \"strash\").\n" ); + return 1; + } + vSuppFun = Sim_ComputeFunSupp( pNtk, fVerbose ); + ABC_FREE( vSuppFun->pArray[0] ); + Vec_PtrFree( vSuppFun ); + return 0; + +usage: + Abc_Print( -2, "usage: print_supp [-svwh]\n" ); + Abc_Print( -2, "\t prints the supports of the CO nodes\n" ); + Abc_Print( -2, "\t-s : toggle printing structural support only [default = %s].\n", fStruct? "yes": "no" ); + Abc_Print( -2, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : enable printing CI/CO dependency matrix [default = %s].\n", fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +#ifdef ABC_USE_CUDD +int Abc_CommandPrintMint( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Abc_Obj_t * pObj; + int c; + int fVerbose; + + // set defaults + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "svwh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for logic networks (run \"clp\").\n" ); + return 1; + } + if ( !Abc_NtkHasBdd(pNtk) ) + { + Abc_Print( -1, "This command works only for logic networks with local functions represented by BDDs.\n" ); + return 1; + } + + Abc_NtkForEachNode( pNtk, pObj, c ) + printf( "ObjId %3d : SuppSize = %5d MintCount = %32.0f\n", c, Abc_ObjFaninNum(pObj), + Cudd_CountMinterm((DdManager *)pNtk->pManFunc, (DdNode *)pObj->pData, Abc_ObjFaninNum(pObj)) ); + return 0; + +usage: + Abc_Print( -2, "usage: print_mint [-svwh]\n" ); + Abc_Print( -2, "\t prints the number of on-set minterms in the PO functions\n" ); + Abc_Print( -2, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} +#endif + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintSymms( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fUseBdds; + int fNaive; + int fReorder; + int fVerbose; + extern void Abc_NtkSymmetries( Abc_Ntk_t * pNtk, int fUseBdds, int fNaive, int fReorder, int fVerbose ); + + // set defaults + fUseBdds = 0; + fNaive = 0; + fReorder = 1; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "bnrvh" ) ) != EOF ) + { + switch ( c ) + { + case 'b': + fUseBdds ^= 1; + break; + case 'n': + fNaive ^= 1; + break; + case 'r': + fReorder ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsComb(pNtk) ) + { + Abc_Print( -1, "This command works only for combinational networks (run \"comb\").\n" ); + return 1; + } + if ( Abc_NtkIsStrash(pNtk) ) + Abc_NtkSymmetries( pNtk, fUseBdds, fNaive, fReorder, fVerbose ); + else + { + pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); + Abc_NtkSymmetries( pNtk, fUseBdds, fNaive, fReorder, fVerbose ); + Abc_NtkDelete( pNtk ); + } + return 0; + +usage: + Abc_Print( -2, "usage: print_symm [-bnrvh]\n" ); + Abc_Print( -2, "\t computes symmetries of the PO functions\n" ); + Abc_Print( -2, "\t-b : toggle BDD-based or SAT-based computations [default = %s].\n", fUseBdds? "BDD": "SAT" ); + Abc_Print( -2, "\t-n : enable naive BDD-based computation [default = %s].\n", fNaive? "yes": "no" ); + Abc_Print( -2, "\t-r : enable dynamic BDD variable reordering [default = %s].\n", fReorder? "yes": "no" ); + Abc_Print( -2, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintUnate( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fUseBdds; + int fUseNaive; + int fVerbose; + extern void Abc_NtkPrintUnate( Abc_Ntk_t * pNtk, int fUseBdds, int fUseNaive, int fVerbose ); + + // set defaults + fUseBdds = 1; + fUseNaive = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "bnvh" ) ) != EOF ) + { + switch ( c ) + { + case 'b': + fUseBdds ^= 1; + break; + case 'n': + fUseNaive ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for AIGs (run \"strash\").\n" ); + return 1; + } + Abc_NtkPrintUnate( pNtk, fUseBdds, fUseNaive, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: print_unate [-bnvh]\n" ); + Abc_Print( -2, "\t computes unate variables of the PO functions\n" ); + Abc_Print( -2, "\t-b : toggle BDD-based or SAT-based computations [default = %s].\n", fUseBdds? "BDD": "SAT" ); + Abc_Print( -2, "\t-n : toggle naive BDD-based computation [default = %s].\n", fUseNaive? "yes": "no" ); + Abc_Print( -2, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintAuto( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int Output; + int fNaive; + int fVerbose; + extern void Abc_NtkAutoPrint( Abc_Ntk_t * pNtk, int Output, int fNaive, int fVerbose ); + + // set defaults + Output = -1; + fNaive = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Onvh" ) ) != EOF ) + { + switch ( c ) + { + case 'O': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" ); + goto usage; + } + Output = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Output < 0 ) + goto usage; + break; + case 'n': + fNaive ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for AIGs (run \"strash\").\n" ); + return 1; + } + + + Abc_NtkAutoPrint( pNtk, Output, fNaive, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: print_auto [-O ] [-nvh]\n" ); + Abc_Print( -2, "\t computes autosymmetries of the PO functions\n" ); + Abc_Print( -2, "\t-O : (optional) the 0-based number of the output [default = all]\n"); + Abc_Print( -2, "\t-n : enable naive BDD-based computation [default = %s].\n", fNaive? "yes": "no" ); + Abc_Print( -2, "\t-v : enable verbose output [default = %s].\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintKMap( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Abc_Obj_t * pNode; + int c; + int fUseRealNames; + + extern void Abc_NodePrintKMap( Abc_Obj_t * pNode, int fUseRealNames ); + + // set defaults + fUseRealNames = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "nh" ) ) != EOF ) + { + switch ( c ) + { + case 'n': + fUseRealNames ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc == globalUtilOptind + 2 ) + { + Abc_NtkShow6VarFunc( argv[globalUtilOptind], argv[globalUtilOptind+1] ); + return 0; + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "Visualization of Karnaugh maps works for logic networks.\n" ); + return 1; + } + if ( argc > globalUtilOptind + 1 ) + { + Abc_Print( -1, "Wrong number of auguments.\n" ); + goto usage; + } + if ( argc == globalUtilOptind ) + { + pNode = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) ); + if ( !Abc_ObjIsNode(pNode) ) + { + Abc_Print( -1, "The driver \"%s\" of the first PO is not an internal node.\n", Abc_ObjName(pNode) ); + return 1; + } + } + else + { + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + } + Abc_NtkToBdd(pNtk); + Abc_NodePrintKMap( pNode, fUseRealNames ); + return 0; + +usage: + Abc_Print( -2, "usage: print_kmap [-nh] \n" ); + Abc_Print( -2, "\t shows the truth table of the node\n" ); + Abc_Print( -2, "\t-n : toggles real/dummy fanin names [default = %s]\n", fUseRealNames? "real": "dummy" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t: the node to consider (default = the driver of the first PO)\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintGates( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fUseLibrary; + int fUpdateProfile; + + extern void Abc_NtkPrintGates( Abc_Ntk_t * pNtk, int fUseLibrary, int fUpdateProfile ); + + // set defaults + fUseLibrary = 1; + fUpdateProfile = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "luh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUseLibrary ^= 1; + break; + case 'u': + fUpdateProfile ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkHasAig(pNtk) ) + { + Abc_Print( -1, "Printing gates does not work for AIGs and sequential AIGs.\n" ); + return 1; + } + + Abc_NtkPrintGates( pNtk, fUseLibrary, fUpdateProfile ); + return 0; + +usage: + Abc_Print( -2, "usage: print_gates [-luh]\n" ); + Abc_Print( -2, "\t prints statistics about gates used in the network\n" ); + Abc_Print( -2, "\t-l : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" ); + Abc_Print( -2, "\t-u : update profile before printing it[default = %s]\n", fUpdateProfile? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintSharing( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fUseLibrary; + + extern void Abc_NtkPrintSharing( Abc_Ntk_t * pNtk ); + + // set defaults + fUseLibrary = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUseLibrary ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + Abc_NtkPrintSharing( pNtk ); + return 0; + +usage: + Abc_Print( -2, "usage: print_sharing [-h]\n" ); + Abc_Print( -2, "\t prints the number of shared nodes in the TFI cones of the COs\n" ); +// Abc_Print( -2, "\t-l : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintXCut( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fUseLibrary; + + extern int Abc_NtkCrossCut( Abc_Ntk_t * pNtk ); + + // set defaults + fUseLibrary = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUseLibrary ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + Abc_NtkCrossCut( pNtk ); + return 0; + +usage: + Abc_Print( -2, "usage: print_xcut [-h]\n" ); + Abc_Print( -2, "\t prints the size of the cross cut of the current network\n" ); +// Abc_Print( -2, "\t-l : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintDsd( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fCofactor; + int nCofLevel; + int fProfile; + int fPrintDec; + + extern void Kit_DsdTest( unsigned * pTruth, int nVars ); + extern void Kit_DsdPrintCofactors( unsigned * pTruth, int nVars, int nCofLevel, int fVerbose ); + extern void Dau_DecTrySets( word * p, int nVars, int fVerbose ); + + // set defaults + nCofLevel = 1; + fCofactor = 0; + fProfile = 0; + fPrintDec = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Npcdh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nCofLevel = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCofLevel < 0 ) + goto usage; + break; + case 'p': + fProfile ^= 1; + break; + case 'c': + fCofactor ^= 1; + break; + case 'd': + fPrintDec ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + // get the truth table of the first output + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "Currently works only for logic networks.\n" ); + return 1; + } + Abc_NtkToAig( pNtk ); + // convert it to truth table + { + Abc_Obj_t * pObj = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) ); + Vec_Int_t * vMemory; + unsigned * pTruth; + if ( !Abc_ObjIsNode(pObj) ) + { + Abc_Print( -1, "The fanin of the first PO node does not have a logic function.\n" ); + return 1; + } + if ( Abc_ObjFaninNum(pObj) > 16 ) + { + Abc_Print( -1, "Currently works only for up to 16 inputs.\n" ); + return 1; + } + vMemory = Vec_IntAlloc(0); + pTruth = Hop_ManConvertAigToTruth( (Hop_Man_t *)pNtk->pManFunc, Hop_Regular((Hop_Obj_t *)pObj->pData), Abc_ObjFaninNum(pObj), vMemory, 0 ); + if ( Hop_IsComplement((Hop_Obj_t *)pObj->pData) ) + Extra_TruthNot( pTruth, pTruth, Abc_ObjFaninNum(pObj) ); +// Extra_PrintBinary( stdout, pTruth, 1 << Abc_ObjFaninNum(pObj) ); +// Abc_Print( -1, "\n" ); + if ( fPrintDec )//&&Abc_ObjFaninNum(pObj) <= 6 ) + { + word * pTruthW = (word *)pTruth; + if ( Abc_ObjFaninNum(pObj) < 6 ) + pTruthW[0] = Abc_Tt6Stretch( pTruthW[0], Abc_ObjFaninNum(pObj) ); + Dau_DecTrySets( (word *)pTruth, Abc_ObjFaninNum(pObj), 1 ); + } + if ( fProfile ) + Kit_TruthPrintProfile( pTruth, Abc_ObjFaninNum(pObj) ); + else if ( fCofactor ) + Kit_DsdPrintCofactors( pTruth, Abc_ObjFaninNum(pObj), nCofLevel, 1 ); + else + Kit_DsdTest( pTruth, Abc_ObjFaninNum(pObj) ); + Vec_IntFree( vMemory ); + } + return 0; + +usage: + Abc_Print( -2, "usage: print_dsd [-pcdh] [-N ]\n" ); + Abc_Print( -2, "\t print DSD formula for a single-output function with less than 16 variables\n" ); + Abc_Print( -2, "\t-p : toggle printing profile [default = %s]\n", fProfile? "yes": "no" ); + Abc_Print( -2, "\t-c : toggle recursive cofactoring [default = %s]\n", fCofactor? "yes": "no" ); + Abc_Print( -2, "\t-d : toggle printing decompositions [default = %s]\n", fPrintDec? "yes": "no" ); + Abc_Print( -2, "\t-N : the number of levels to cofactor [default = %d]\n", nCofLevel ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintCone( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fUseLibrary; + + // set defaults + fUseLibrary = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUseLibrary ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkLatchNum(pNtk) == 0 ) + { + Abc_Print( -1, "The network is combinational.\n" ); + return 1; + } + Abc_NtkDarPrintCone( pNtk ); + return 0; + +usage: + Abc_Print( -2, "usage: print_cone [-h]\n" ); + Abc_Print( -2, "\t prints cones of influence info for each primary output\n" ); +// Abc_Print( -2, "\t-l : used library gate names (if mapped) [default = %s]\n", fUseLibrary? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintMiter( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fUseLibrary; + + extern void Abc_NtkPrintMiter( Abc_Ntk_t * pNtk ); + + // set defaults + fUseLibrary = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUseLibrary ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "The network is should be structurally hashed.\n" ); + return 1; + } + Abc_NtkPrintMiter( pNtk ); + return 0; + +usage: + Abc_Print( -2, "usage: print_miter [-h]\n" ); + Abc_Print( -2, "\t prints the status of the miter\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintStatus( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_NtkDumpOneCexSpecial( FILE * pFile, Abc_Ntk_t * pNtk, Abc_Cex_t * pCex ); + extern void Abc_NtkPrintPoEquivs( Abc_Ntk_t * pNtk ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c, fOutStatus = 0, fShort = 1; + char * pLogFileName = NULL; + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Losh" ) ) != EOF ) + { + switch ( c ) + { + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" ); + goto usage; + } + pLogFileName = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'o': + fOutStatus ^= 1; + break; + case 's': + fShort ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( fOutStatus ) + { + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + Abc_NtkPrintPoEquivs( pNtk ); + return 0; + } + if ( !pAbc->vStatuses ) + Abc_Print( 1,"Status = %d Frames = %d ", pAbc->Status, pAbc->nFrames ); + if ( pAbc->pCex == NULL && pAbc->vCexVec == NULL ) + Abc_Print( 1,"Cex is not defined.\n" ); + else + { + if ( pAbc->pCex ) + Abc_CexPrintStats( pAbc->pCex ); + if ( pAbc->vCexVec ) + { + Abc_Cex_t * pTemp; + int nCexes = 0; + int Counter = 0; + //printf( "\n" ); + Vec_PtrForEachEntry( Abc_Cex_t *, pAbc->vCexVec, pTemp, c ) + { + if ( pTemp == (void *)(ABC_PTRINT_T)1 ) + { + Counter++; + continue; + } + if ( pTemp ) + { + printf( "%4d : ", ++nCexes ); + Abc_CexPrintStats( pTemp ); + } + } +// if ( Counter ) +// printf( "In total, %d (out of %d) outputs are \"sat\" but CEXes are not recorded.\n", Counter, Vec_PtrSize(pAbc->vCexVec) ); + } + } + if ( pAbc->vStatuses ) + { + if ( pLogFileName ) + { + Abc_Cex_t * pTemp = NULL; + FILE * pFile = fopen( pLogFileName, "wb" ); + if ( pFile == NULL ) + { + printf( "Cannot open file \"%s\" for writing.\n", pLogFileName ); + return 0; + } + Vec_PtrForEachEntry( Abc_Cex_t *, pAbc->vCexVec, pTemp, c ) + { + int Status = Vec_IntEntry( pAbc->vStatuses, c ); + if ( Status == -1 ) // undec + fprintf( pFile, "STATUS: ABORTED " ); + else if ( Status == 0 ) + fprintf( pFile, "STATUS: SAT " ); + else if ( Status == 1 ) + fprintf( pFile, "STATUS: UNSAT " ); + fprintf( pFile, "%s\n", Abc_ObjName(Abc_NtkPo(pNtk, c)) ); + if ( Status != 0 ) + continue; + Abc_NtkDumpOneCexSpecial( pFile, pNtk, pTemp ); + } + fclose( pFile ); + } + else if ( fShort ) + { + printf( "Status array contains %d SAT, %d UNSAT, and %d UNDEC entries (out of %d).", + Vec_IntCountEntry(pAbc->vStatuses, 0), Vec_IntCountEntry(pAbc->vStatuses, 1), + Vec_IntCountEntry(pAbc->vStatuses, -1), Vec_IntSize(pAbc->vStatuses) ); + } + else + { + int i, Entry; + Vec_IntForEachEntry( pAbc->vStatuses, Entry, i ) + printf( "%d=%d ", i, Entry ); + } + printf( "\n" ); + } + return 0; + +usage: + Abc_Print( -2, "usage: print_status [-L file] [-osh]\n" ); + Abc_Print( -2, "\t prints verification status\n" ); + Abc_Print( -2, "\t-L file : the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" ); + Abc_Print( -2, "\t-o : toggle printing output status [default = %s]\n", fOutStatus? "yes": "no" ); + Abc_Print( -2, "\t-s : toggle using short print-out [default = %s]\n", fShort? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPrintDelay( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Abc_Obj_t * pObjIn = NULL, * pObjOut = NULL; + int c; + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsMappedLogic(pNtk) ) + { + Abc_Print( -1, "Delay trace works only for network mapped into standard cells.\n" ); + return 1; + } + if ( argc > globalUtilOptind + 2 ) + { + Abc_Print( -1, "Wrong number of auguments.\n" ); + goto usage; + } + // collect the first name (PO name) + if ( argc >= globalUtilOptind + 1 ) + { + int Num = Nm_ManFindIdByName( pNtk->pManName, argv[globalUtilOptind], ABC_OBJ_PO ); + if ( Num < 0 ) + Num = Nm_ManFindIdByName( pNtk->pManName, argv[globalUtilOptind], ABC_OBJ_BI ); + if ( Num >= 0 ) + pObjOut = Abc_NtkObj( pNtk, Num ); + if ( pObjOut == NULL ) + { + Abc_Print( 1, "Cannot find combinational output \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + } + // collect the second name (PI name) + if ( argc == globalUtilOptind + 2 ) + { + int Num = Nm_ManFindIdByName( pNtk->pManName, argv[globalUtilOptind+1], ABC_OBJ_PI ); + if ( Num < 0 ) + Num = Nm_ManFindIdByName( pNtk->pManName, argv[globalUtilOptind+1], ABC_OBJ_BO ); + if ( Num >= 0 ) + pObjIn = Abc_NtkObj( pNtk, Num ); + if ( pObjIn == NULL ) + { + Abc_Print( 1, "Cannot find combinational input \"%s\".\n", argv[globalUtilOptind+1] ); + return 1; + } + } + Abc_NtkDelayTrace( pNtk, pObjOut, pObjIn, 1 ); + return 0; + +usage: + Abc_Print( -2, "usage: print_delay [-h] \n" ); + Abc_Print( -2, "\t prints one critical path of the mapped network\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : (optional) the sink of the critical path (primary output or flop input)\n"); + Abc_Print( -2, "\t : (optional) the source of the critical path (primary input or flop output)\n"); + Abc_Print( -2, "\t (if CO and/or CI are not given, uses the most critical ones)\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandShow( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fSeq; + int fGateNames; + int fUseReverse; + int fFlopDep; + int fKeepDot; + int fAigIds; + extern void Abc_NtkShow( Abc_Ntk_t * pNtk, int fGateNames, int fSeq, int fUseReverse, int fKeepDot, int fAigIds ); + extern void Abc_NtkShowFlopDependency( Abc_Ntk_t * pNtk ); + + // set defaults + fSeq = 0; + fGateNames = 0; + fUseReverse = 1; + fFlopDep = 0; + fKeepDot = 0; + fAigIds = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "rsgfdih" ) ) != EOF ) + { + switch ( c ) + { + case 'r': + fUseReverse ^= 1; + break; + case 's': + fSeq ^= 1; + break; + case 'g': + fGateNames ^= 1; + break; + case 'f': + fFlopDep ^= 1; + break; + case 'd': + fKeepDot ^= 1; + break; + case 'i': + fAigIds ^= 1; + break; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( fFlopDep ) + Abc_NtkShowFlopDependency( pNtk ); + else + Abc_NtkShow( pNtk, fGateNames, fSeq, fUseReverse, fKeepDot, fAigIds ); + return 0; + +usage: + Abc_Print( -2, "usage: show [-srgfdih]\n" ); + Abc_Print( -2, " visualizes the network structure using DOT and GSVIEW\n" ); +#ifdef WIN32 + Abc_Print( -2, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" ); + Abc_Print( -2, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" ); +#endif + Abc_Print( -2, "\t-s : toggles visualization of sequential networks [default = %s].\n", fSeq? "yes": "no" ); + Abc_Print( -2, "\t-r : toggles ordering nodes in reverse order [default = %s].\n", fUseReverse? "yes": "no" ); + Abc_Print( -2, "\t-g : toggles printing gate names for mapped network [default = %s].\n", fGateNames? "yes": "no" ); + Abc_Print( -2, "\t-f : toggles visualizing flop dependency graph [default = %s].\n", fFlopDep? "yes": "no" ); + Abc_Print( -2, "\t-d : toggles keeping the .dot file used to produce the .ps file [default = %s].\n", fKeepDot? "yes": "no" ); + Abc_Print( -2, "\t-i : toggles using original AIG object IDs as node labels [default = %s].\n", fAigIds? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandShowBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); Abc_Obj_t * pNode; + int c, fCompl = 0, fGlobal = 0, fReorder = 1, fWidth = 0; + extern void Abc_NodeShowBdd( Abc_Obj_t * pNode, int fCompl ); + extern void Abc_NtkShowBdd( Abc_Ntk_t * pNtk, int fCompl, int fReorder ); + extern void Abc_NtkBddDecExplore( Abc_Obj_t * pNode ); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "cgrwh" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fCompl ^= 1; + break; + case 'g': + fGlobal ^= 1; + break; + case 'r': + fReorder ^= 1; + break; + case 'w': + fWidth ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( fGlobal ) + { + Abc_Ntk_t * pTemp = Abc_NtkIsStrash(pNtk) ? pNtk : Abc_NtkStrash(pNtk, 0, 0, 0); + Abc_NtkShowBdd( pTemp, fCompl, fReorder ); + if ( pTemp != pNtk ) + Abc_NtkDelete( pTemp ); + return 0; + } + + if ( !Abc_NtkIsBddLogic(pNtk) ) + { + Abc_Print( -1, "Visualizing BDDs can only be done for logic BDD networks (run \"bdd\").\n" ); + return 1; + } + if ( argc > globalUtilOptind + 1 ) + { + Abc_Print( -1, "Wrong number of auguments.\n" ); + goto usage; + } + if ( argc == globalUtilOptind ) + { + pNode = Abc_ObjFanin0( Abc_NtkPo(pNtk, 0) ); + if ( !Abc_ObjIsNode(pNode) ) + { + Abc_Print( -1, "The driver \"%s\" of the first PO is not an internal node.\n", Abc_ObjName(pNode) ); + return 1; + } + } + else + { + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + } + if ( fWidth ) + Abc_NtkBddDecExplore( pNode ); + else + Abc_NodeShowBdd( pNode, fCompl ); + return 0; + +usage: + Abc_Print( -2, "usage: show_bdd [-cgrwh] \n" ); + Abc_Print( -2, " uses DOT and GSVIEW to visualize the global BDDs of primary outputs\n" ); + Abc_Print( -2, " in terms of primary inputs or the local BDD of a node in terms of its fanins\n" ); +#ifdef WIN32 + Abc_Print( -2, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" ); + Abc_Print( -2, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" ); +#endif + Abc_Print( -2, "\t: (optional) the node to consider [default = the driver of the first PO]\n"); + Abc_Print( -2, "\t-c : toggle visualizing BDD with complemented edges [default = %s].\n", fCompl? "yes": "no" ); + Abc_Print( -2, "\t-g : toggle visualizing the global BDDs of primary outputs [default = %s].\n", fGlobal? "yes": "no" ); + Abc_Print( -2, "\t-r : toggles dynamic variable reordering [default = %s]\n", fReorder? "yes": "no" ); + Abc_Print( -2, "\t-w : toggles printing width profile of the node's BDD [default = %s]\n", fWidth? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandShowCut( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Abc_Obj_t * pNode; + int c; + int nNodeSizeMax; + int nConeSizeMax; + extern void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax ); + + // set defaults + nNodeSizeMax = 10; + nConeSizeMax = ABC_INFINITY; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NCh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nNodeSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nNodeSizeMax < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConeSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConeSizeMax < 0 ) + goto usage; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Visualizing cuts only works for AIGs (run \"strash\").\n" ); + return 1; + } + if ( argc != globalUtilOptind + 1 ) + { + Abc_Print( -1, "Wrong number of auguments.\n" ); + goto usage; + } + + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + Abc_NodeShowCut( pNode, nNodeSizeMax, nConeSizeMax ); + return 0; + +usage: + Abc_Print( -2, "usage: show_cut [-N ] [-C ] [-h] \n" ); + Abc_Print( -2, " visualizes the cut of a node using DOT and GSVIEW\n" ); +#ifdef WIN32 + Abc_Print( -2, " \"dot.exe\" and \"gsview32.exe\" should be set in the paths\n" ); + Abc_Print( -2, " (\"gsview32.exe\" may be in \"C:\\Program Files\\Ghostgum\\gsview\\\")\n" ); +#endif + Abc_Print( -2, "\t-N : the max size of the cut to be computed [default = %d]\n", nNodeSizeMax ); + Abc_Print( -2, "\t-C : the max support of the containing cone [default = %d]\n", nConeSizeMax ); + Abc_Print( -2, "\t : the node to consider\n"); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCollapse( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int fVerbose; + int fBddSizeMax; + int fDualRail; + int fReorder; + int fReverse; + int fDumpOrder; + int c; + char * pLogFileName = NULL; + pNtk = Abc_FrameReadNtk(pAbc); + + // set defaults + fVerbose = 0; + fReorder = 1; + fReverse = 0; + fDualRail = 0; + fDumpOrder = 0; + fBddSizeMax = ABC_INFINITY; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "BLrodxvh" ) ) != EOF ) + { + switch ( c ) + { + case 'B': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" ); + goto usage; + } + fBddSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( fBddSizeMax < 0 ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" ); + goto usage; + } + pLogFileName = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'r': + fReorder ^= 1; + break; + case 'o': + fReverse ^= 1; + break; + case 'd': + fDualRail ^= 1; + break; + case 'x': + fDumpOrder ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Can only collapse a logic network or an AIG.\n" ); + return 1; + } + + // get the new network + if ( Abc_NtkIsStrash(pNtk) ) + pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fReverse, fDumpOrder, fVerbose ); + else + { + pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); + pNtkRes = Abc_NtkCollapse( pNtk, fBddSizeMax, fDualRail, fReorder, fReverse, fDumpOrder, fVerbose ); + Abc_NtkDelete( pNtk ); + } + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Collapsing has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + if ( pLogFileName ) + { + pAbc->pCex = NULL; + pAbc->nFrames = -1; + if ( Abc_NtkNodeNum(pNtkRes) == 0 ) + pAbc->Status = 1; // UNSAT + else + pAbc->Status = -1; // UNDEC + Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "collapse" ); + } + return 0; + +usage: + Abc_Print( -2, "usage: collapse [-B ] [-L file] [-rodxvh]\n" ); + Abc_Print( -2, "\t collapses the network by constructing global BDDs\n" ); + Abc_Print( -2, "\t-B : limit on live BDD nodes during collapsing [default = %d]\n", fBddSizeMax ); + Abc_Print( -2, "\t-L file : the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" ); + Abc_Print( -2, "\t-r : toggles dynamic variable reordering [default = %s]\n", fReorder? "yes": "no" ); + Abc_Print( -2, "\t-o : toggles reverse variable ordering [default = %s]\n", fReverse? "yes": "no" ); + Abc_Print( -2, "\t-d : toggles dual-rail collapsing mode [default = %s]\n", fDualRail? "yes": "no" ); + Abc_Print( -2, "\t-x : toggles dumping file \"order.txt\" with variable order [default = %s]\n", fDumpOrder? "yes": "no" ); + Abc_Print( -2, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSatClp( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; + int nCubeLim = 0; + int nBTLimit = 1000000; + int nCostMax = 20000000; + int fCanon = 0; + int fReverse = 0; + int fCnfShared = 0; + int fVerbose = 0; + int c; + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "CLZcrsvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nCubeLim = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCubeLim < 0 ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + nBTLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nBTLimit < 0 ) + goto usage; + break; + case 'Z': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-Z\" should be followed by an integer.\n" ); + goto usage; + } + nCostMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCostMax < 0 ) + goto usage; + break; + case 'c': + fCanon ^= 1; + break; + case 'r': + fReverse ^= 1; + break; + case 's': + fCnfShared ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Can only collapse a logic network or an AIG.\n" ); + return 1; + } + + // get the new network + if ( Abc_NtkIsStrash(pNtk) ) + pNtkRes = Abc_NtkCollapseSat( pNtk, nCubeLim, nBTLimit, nCostMax, fCanon, fReverse, fCnfShared, fVerbose ); + else + { + pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); + pNtkRes = Abc_NtkCollapseSat( pNtk, nCubeLim, nBTLimit, nCostMax, fCanon, fReverse, fCnfShared, fVerbose ); + Abc_NtkDelete( pNtk ); + } + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Collapsing has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: satclp [-CLZ num] [-crsvh]\n" ); + Abc_Print( -2, "\t performs SAT based collapsing\n" ); + Abc_Print( -2, "\t-C num : the limit on the SOP size of one output [default = %d]\n", nCubeLim ); + Abc_Print( -2, "\t-L num : the limit on the number of conflicts in one SAT call [default = %d]\n", nBTLimit ); + Abc_Print( -2, "\t-Z num : the limit on the cost of the largest output [default = %d]\n", nCostMax ); + Abc_Print( -2, "\t-c : toggles using canonical ISOP computation [default = %s]\n", fCanon? "yes": "no" ); + Abc_Print( -2, "\t-r : toggles using reverse veriable ordering [default = %s]\n", fReverse? "yes": "no" ); + Abc_Print( -2, "\t-s : toggles shared CNF computation (non-canonical only) [default = %s]\n", fCnfShared? "yes": "no" ); + Abc_Print( -2, "\t-v : toggles printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandStrash( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + Abc_Obj_t * pObj; + int c; + int fAllNodes; + int fRecord; + int fCleanup; + int fComplOuts; + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + fAllNodes = 0; + fCleanup = 1; + fRecord = 0; + fComplOuts= 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "acrih" ) ) != EOF ) + { + switch ( c ) + { + case 'a': + fAllNodes ^= 1; + break; + case 'c': + fCleanup ^= 1; + break; + case 'r': + fRecord ^= 1; + break; + case 'i': + fComplOuts ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkStrash( pNtk, fAllNodes, fCleanup, fRecord ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Strashing has failed.\n" ); + return 1; + } + if ( fComplOuts ) + Abc_NtkForEachPo( pNtkRes, pObj, c ) + Abc_ObjXorFaninC( pObj, 0 ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: strash [-acrih]\n" ); + Abc_Print( -2, "\t transforms combinational logic into an AIG\n" ); + Abc_Print( -2, "\t-a : toggles between using all nodes and DFS nodes [default = %s]\n", fAllNodes? "all": "DFS" ); + Abc_Print( -2, "\t-c : toggles cleanup to remove the dangling AIG nodes [default = %s]\n", fCleanup? "all": "DFS" ); + Abc_Print( -2, "\t-r : toggles using the record of AIG subgraphs [default = %s]\n", fRecord? "yes": "no" ); + Abc_Print( -2, "\t-i : toggles complementing the POs of the AIG [default = %s]\n", fComplOuts? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandBalance( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes, * pNtkTemp; + int c; + int fDuplicate; + int fSelective; + int fUpdateLevel; + int fExor; + int fVerbose; + pNtk = Abc_FrameReadNtk(pAbc); + + // set defaults + fDuplicate = 0; + fSelective = 0; + fUpdateLevel = 1; + fExor = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ldsxvh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUpdateLevel ^= 1; + break; + case 'd': + fDuplicate ^= 1; + break; + case 's': + fSelective ^= 1; + break; + case 'x': + fExor ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + // get the new network + if ( Abc_NtkIsStrash(pNtk) ) + { + if ( fExor ) + pNtkRes = Abc_NtkBalanceExor( pNtk, fUpdateLevel, fVerbose ); + else + pNtkRes = Abc_NtkBalance( pNtk, fDuplicate, fSelective, fUpdateLevel ); + } + else + { + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); + if ( pNtkTemp == NULL ) + { + Abc_Print( -1, "Strashing before balancing has failed.\n" ); + return 1; + } + if ( fExor ) + pNtkRes = Abc_NtkBalanceExor( pNtkTemp, fUpdateLevel, fVerbose ); + else + pNtkRes = Abc_NtkBalance( pNtkTemp, fDuplicate, fSelective, fUpdateLevel ); + Abc_NtkDelete( pNtkTemp ); + } + + // check if balancing worked + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Balancing has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: balance [-ldsxvh]\n" ); + Abc_Print( -2, "\t transforms the current network into a well-balanced AIG\n" ); + Abc_Print( -2, "\t-l : toggle minimizing the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + Abc_Print( -2, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" ); + Abc_Print( -2, "\t-s : toggle duplication on the critical paths [default = %s]\n", fSelective? "yes": "no" ); + Abc_Print( -2, "\t-x : toggle balancing multi-input EXORs [default = %s]\n", fExor? "yes": "no" ); + Abc_Print( -2, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMuxStruct( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int fVerbose; + + extern Abc_Ntk_t * Abc_NtkMuxRestructure( Abc_Ntk_t * pNtk, int fVerbose ); + pNtk = Abc_FrameReadNtk(pAbc); + + // set defaults + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + // get the new network + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Does not work for a logic network.\n" ); + return 1; + } + // check if balancing worked +// pNtkRes = Abc_NtkMuxRestructure( pNtk, fVerbose ); + pNtkRes = NULL; + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "MUX restructuring has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: mux_struct [-vh]\n" ); + Abc_Print( -2, "\t performs MUX restructuring of the current network\n" ); + Abc_Print( -2, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMulti( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int nThresh, nFaninMax, c; + int fCnf; + int fMulti; + int fSimple; + int fFactor; + extern Abc_Ntk_t * Abc_NtkMulti( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple, int fFactor ); + + pNtk = Abc_FrameReadNtk(pAbc); + + // set defaults + nThresh = 1; + nFaninMax = 20; + fCnf = 0; + fMulti = 1; + fSimple = 0; + fFactor = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "TFmcsfh" ) ) != EOF ) + { + switch ( c ) + { + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + nThresh = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nThresh < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nFaninMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFaninMax < 0 ) + goto usage; + break; + case 'c': + fCnf ^= 1; + break; + case 'm': + fMulti ^= 1; + break; + case 's': + fSimple ^= 1; + break; + case 'f': + fFactor ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Cannot renode a network that is not an AIG (run \"strash\").\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkMulti( pNtk, nThresh, nFaninMax, fCnf, fMulti, fSimple, fFactor ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Renoding has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: multi [-TF ] [-msfch]\n" ); + Abc_Print( -2, "\t transforms an AIG into a logic network by creating larger nodes\n" ); + Abc_Print( -2, "\t-F : the maximum fanin size after renoding [default = %d]\n", nFaninMax ); + Abc_Print( -2, "\t-T : the threshold for AIG node duplication [default = %d]\n", nThresh ); + Abc_Print( -2, "\t (an AIG node is the root of a new node after renoding\n" ); + Abc_Print( -2, "\t if this leads to duplication of no more than %d AIG nodes,\n", nThresh ); + Abc_Print( -2, "\t that is, if [(numFanouts(Node)-1) * size(MFFC(Node))] <= %d)\n", nThresh ); + Abc_Print( -2, "\t-m : creates multi-input AND graph [default = %s]\n", fMulti? "yes": "no" ); + Abc_Print( -2, "\t-s : creates a simple AIG (no renoding) [default = %s]\n", fSimple? "yes": "no" ); + Abc_Print( -2, "\t-f : creates a factor-cut network [default = %s]\n", fFactor? "yes": "no" ); + Abc_Print( -2, "\t-c : performs renoding to derive the CNF [default = %s]\n", fCnf? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRenode( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int nLutSize, nCutsMax, c; + int nFlowIters, nAreaIters; + int fArea; + int fUseBdds; + int fUseSops; + int fUseCnfs; + int fUseMv; + int fVerbose; + extern Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nLutSize, int nCutsMax, int nFlowIters, int nAreaIters, int fArea, int fUseBdds, int fUseSops, int fUseCnfs, int fUseMv, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + + // set defaults + nLutSize = 8; + nCutsMax = 4; + nFlowIters = 1; + nAreaIters = 1; + fArea = 0; + fUseBdds = 0; + fUseSops = 0; + fUseCnfs = 0; + fUseMv = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KCFAabscivh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutSize < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nCutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCutsMax < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by a positive integer.\n" ); + goto usage; + } + nFlowIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFlowIters < 0 ) + goto usage; + break; + case 'A': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-A\" should be followed by a positive integer.\n" ); + goto usage; + } + nAreaIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nAreaIters < 0 ) + goto usage; + break; + case 'a': + fArea ^= 1; + break; + case 'b': + fUseBdds ^= 1; + break; + case 's': + fUseSops ^= 1; + break; + case 'c': + fUseCnfs ^= 1; + break; + case 'i': + fUseMv ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( fUseBdds + fUseSops + fUseCnfs + fUseMv > 1 ) + { + Abc_Print( -1, "Cannot optimize two parameters at the same time.\n" ); + return 1; + } + + if ( nLutSize < 2 || nLutSize > IF_MAX_FUNC_LUTSIZE ) + { + Abc_Print( -1, "Incorrect LUT size (%d).\n", nLutSize ); + return 1; + } + + if ( nCutsMax < 1 || nCutsMax >= (1<<12) ) + { + Abc_Print( -1, "Incorrect number of cuts.\n" ); + return 1; + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Cannot renode a network that is not an AIG (run \"strash\").\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkRenode( pNtk, nLutSize, nCutsMax, nFlowIters, nAreaIters, fArea, fUseBdds, fUseSops, fUseCnfs, fUseMv, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Renoding has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: renode [-KCFA ] [-sbciav]\n" ); + Abc_Print( -2, "\t transforms the AIG into a logic network with larger nodes\n" ); + Abc_Print( -2, "\t while minimizing the number of FF literals of the node SOPs\n" ); + Abc_Print( -2, "\t-K : the max cut size for renoding (2 < num < %d) [default = %d]\n", IF_MAX_FUNC_LUTSIZE+1, nLutSize ); + Abc_Print( -2, "\t-C : the max number of cuts used at a node (0 < num < 2^12) [default = %d]\n", nCutsMax ); + Abc_Print( -2, "\t-F : the number of area flow recovery iterations (num >= 0) [default = %d]\n", nFlowIters ); + Abc_Print( -2, "\t-A : the number of exact area recovery iterations (num >= 0) [default = %d]\n", nAreaIters ); + Abc_Print( -2, "\t-s : toggles minimizing SOP cubes instead of FF lits [default = %s]\n", fUseSops? "yes": "no" ); + Abc_Print( -2, "\t-b : toggles minimizing BDD nodes instead of FF lits [default = %s]\n", fUseBdds? "yes": "no" ); + Abc_Print( -2, "\t-c : toggles minimizing CNF clauses instead of FF lits [default = %s]\n", fUseCnfs? "yes": "no" ); + Abc_Print( -2, "\t-i : toggles minimizing MV-SOP instead of FF lits [default = %s]\n", fUseMv? "yes": "no" ); + Abc_Print( -2, "\t-a : toggles area-oriented mapping [default = %s]\n", fArea? "yes": "no" ); + Abc_Print( -2, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCleanup( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int fCleanupPis; + int fCleanupPos; + int fVerbose; + + extern Abc_Ntk_t * Abc_NtkDarCleanupAig( Abc_Ntk_t * pNtk, int fCleanupPis, int fCleanupPos, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + + // set defaults + fCleanupPis = 1; + fCleanupPos = 1; + fVerbose = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "iovh" ) ) != EOF ) + { + switch ( c ) + { + case 'i': + fCleanupPis ^= 1; + break; + case 'o': + fCleanupPos ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkIsStrash(pNtk) ) + { + if ( !fCleanupPis && !fCleanupPos ) + { + Abc_Print( -1, "Cleanup for PIs and POs is not enabled.\n" ); + pNtkRes = Abc_NtkDup( pNtk ); + } + else + pNtkRes = Abc_NtkDarCleanupAig( pNtk, fCleanupPis, fCleanupPos, fVerbose ); + } + else + { + Abc_NtkCleanup( pNtk, fVerbose ); + pNtkRes = Abc_NtkDup( pNtk ); + } + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Cleanup has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: cleanup [-iovh]\n" ); + Abc_Print( -2, "\t for logic networks, removes dangling combinatinal logic\n" ); + Abc_Print( -2, "\t for AIGs, removes PIs w/o fanout and POs driven by const-0\n" ); + Abc_Print( -2, "\t-i : toggles removing PIs without fanout [default = %s]\n", fCleanupPis? "yes": "no" ); + Abc_Print( -2, "\t-o : toggles removing POs with const-0 drivers [default = %s]\n", fCleanupPos? "yes": "no" ); + Abc_Print( -2, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fSingle = 0; + int fVerbose = 0; + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF ) + { + switch ( c ) + { + case 's': + fSingle ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "The classical (SIS-like) sweep can only be performed on a logic network.\n" ); + return 1; + } + // modify the current network + if ( fSingle ) + Abc_NtkSweepBufsInvs( pNtk, fVerbose ); + else + Abc_NtkSweep( pNtk, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: sweep [-svh]\n" ); + Abc_Print( -2, "\t removes dangling nodes; propagates constant, buffers, inverters\n" ); + Abc_Print( -2, "\t-s : toggle sweeping buffers/inverters only [default = %s]\n", fSingle? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFastExtract( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int Abc_NtkFxPerform( Abc_Ntk_t * pNtk, int nNewNodesMax, int nLitCountMax, int fCanonDivs, int fVerbose, int fVeryVerbose ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Fxu_Data_t Params, * p = &Params; + int c, fNewAlgo = 1; + int nPairsLimit = 1000000000; + // set the defaults + Abc_NtkSetDefaultFxParams( p ); + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "SDNWMPsdzcnxvwh")) != EOF ) + { + switch (c) + { + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + p->nSingleMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( p->nSingleMax < 0 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + p->nPairsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( p->nPairsMax < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + p->nNodesExt = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( p->nNodesExt < 0 ) + goto usage; + break; + case 'W': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + p->WeightMin = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( p->WeightMin < 0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + p->LitCountMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( p->LitCountMax < 0 ) + goto usage; + break; + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + nPairsLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nPairsLimit < 0 ) + goto usage; + break; + case 's': + p->fOnlyS ^= 1; + break; + case 'd': + p->fOnlyD ^= 1; + break; + case 'z': + p->fUse0 ^= 1; + break; + case 'c': + p->fUseCompl ^= 1; + break; + case 'n': + fNewAlgo ^= 1; + break; + case 'x': + p->fCanonDivs ^= 1; + break; + case 'v': + p->fVerbose ^= 1; + break; + case 'w': + p->fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + break; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkNodeNum(pNtk) == 0 || Abc_NtkPiNum(pNtk) == 0 ) + { + Abc_Print( 0, "The network does not have internal nodes.\n" ); + return 0; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "Fast extract can only be applied to a logic network (run \"renode\" or \"if\").\n" ); + return 1; + } + if ( !Abc_NtkIsSopLogic(pNtk) ) + { + Abc_Print( -1, "Fast extract can only be applied to a logic network with SOP local functions (run \"bdd; sop\").\n" ); + return 1; + } + if ( Abc_NtkGetCubePairNum(pNtk) > nPairsLimit ) + { + Abc_Print( -1, "Cannot perform \"fx\" because the number cube pairs exceeds the limit (%d).\n", nPairsLimit ); + return 1; + } + + // the nodes to be merged are linked into the special linked list + if ( fNewAlgo ) + Abc_NtkFxPerform( pNtk, p->nNodesExt, p->LitCountMax, p->fCanonDivs, p->fVerbose, p->fVeryVerbose ); + else + Abc_NtkFastExtract( pNtk, p ); + Abc_NtkFxuFreeInfo( p ); + return 0; + +usage: + Abc_Print( -2, "usage: fx [-SDNWMP ] [-sdzcnxvwh]\n"); + Abc_Print( -2, "\t performs unate fast extract on the current network\n"); + Abc_Print( -2, "\t-S : max number of single-cube divisors to consider [default = %d]\n", p->nSingleMax ); + Abc_Print( -2, "\t-D : max number of double-cube divisors to consider [default = %d]\n", p->nPairsMax ); + Abc_Print( -2, "\t-N : max number of divisors to extract during this run [default = %d]\n", p->nNodesExt ); + Abc_Print( -2, "\t-W : lower bound on the weight of divisors to extract [default = %d]\n", p->WeightMin ); + Abc_Print( -2, "\t-M : upper bound on literal count of divisors to extract [default = %d]\n", p->LitCountMax ); + Abc_Print( -2, "\t-P : skip \"fx\" if cube pair count exceeds this limit [default = %d]\n", nPairsLimit ); + Abc_Print( -2, "\t-s : use only single-cube divisors [default = %s]\n", p->fOnlyS? "yes": "no" ); + Abc_Print( -2, "\t-d : use only double-cube divisors [default = %s]\n", p->fOnlyD? "yes": "no" ); + Abc_Print( -2, "\t-z : use zero-weight divisors [default = %s]\n", p->fUse0? "yes": "no" ); + Abc_Print( -2, "\t-c : use complement in the binary case [default = %s]\n", p->fUseCompl? "yes": "no" ); + Abc_Print( -2, "\t-n : use new implementation of fast extract [default = %s]\n", fNewAlgo? "yes": "no" ); + Abc_Print( -2, "\t-x : use only canonical divisors (AND, XOR, MUX) [default = %s]\n", p->fCanonDivs? "yes": "no" ); + Abc_Print( -2, "\t-v : print verbose information [default = %s]\n", p->fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : print additional information [default = %s]\n", p->fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +static int Abc_CommandFxch( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int Abc_NtkFxchPerform( Abc_Ntk_t * pNtk, int nMaxDivExt, int fVerbose, int fVeryVerbose ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + + int c, + nMaxDivExt = 0, + fVerbose = 0, + fVeryVerbose = 0; + + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "Nvwh")) != EOF ) + { + switch (c) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nMaxDivExt = atoi( argv[globalUtilOptind] ); + globalUtilOptind++; + + if ( nMaxDivExt < 0 ) + goto usage; + break; + + case 'v': + fVerbose ^= 1; + break; + + case 'w': + fVeryVerbose ^= 1; + break; + + case 'h': + goto usage; + break; + + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkNodeNum( pNtk ) == 0 ) + { + Abc_Print( -1, "The network does not have internal nodes.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic( pNtk ) ) + { + Abc_Print( -1, "Fast extract can only be applied to a logic network (run \"renode\" or \"if\").\n" ); + return 1; + } + if ( !Abc_NtkIsSopLogic( pNtk ) ) + { + Abc_Print( -1, "Fast extract can only be applied to a logic network with SOP local functions (run \"bdd; sop\").\n" ); + return 1; + } + + Abc_NtkFxchPerform( pNtk, nMaxDivExt, fVerbose, fVeryVerbose ); + + return 0; + +usage: + Abc_Print( -2, "usage: fxch [-N ] [-svwh]\n"); + Abc_Print( -2, "\t performs fast extract with cube hashing on the current network\n"); + Abc_Print( -2, "\t-N : max number of divisors to extract during this run [default = unused]\n" ); + Abc_Print( -2, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : print additional information [default = %s]\n", fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t\n" ); + Abc_Print( -2, "\t This command was contributed by Bruno Schmitt from UFRGS in May 2016.\n" ); + Abc_Print( -2, "\t The author can be contacted as boschmitt at inf.ufrgs.br\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandEliminate( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int ElimValue; + int nMaxSize; + int nIterMax; + int fGreedy; + int fReverse; + int fSpecial; + int fVerbose; + int c; + extern int Abc_NtkEliminate( Abc_Ntk_t * pNtk, int nMaxSize, int fReverse, int fVerbose ); + extern int Abc_NtkEliminate1( Abc_Ntk_t * pNtk, int ElimValue, int nMaxSize, int nIterMax, int fReverse, int fVerbose ); + extern int Abc_NtkEliminateSpecial( Abc_Ntk_t * pNtk, int nMaxSize, int fVerbose ); + + // set the defaults + ElimValue = -1; + nMaxSize = 12; + nIterMax = 1; + fGreedy = 0; + fReverse = 0; + fSpecial = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( (c = Extra_UtilGetopt(argc, argv, "VNIgrsvh")) != EOF ) + { + switch (c) + { + case 'V': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-V\" should be followed by an integer that is -1 or larger.\n" ); + goto usage; + } + ElimValue = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( ElimValue < -1 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by a positive integer.\n" ); + goto usage; + } + nMaxSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMaxSize <= 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by a positive integer.\n" ); + goto usage; + } + nIterMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIterMax <= 0 ) + goto usage; + break; + case 'g': + fGreedy ^= 1; + break; + case 'r': + fReverse ^= 1; + break; + case 's': + fSpecial ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( Abc_NtkNodeNum(pNtk) == 0 ) + { + Abc_Print( -1, "The network does not have internal nodes.\n" ); + return 1; + } + + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to a logic network (run \"renode\" or \"if\").\n" ); + return 1; + } + + if ( fSpecial ) + Abc_NtkEliminateSpecial( pNtk, 1000, fVerbose ); + else if ( fGreedy ) + Abc_NtkEliminate( pNtk, nMaxSize, fReverse, fVerbose ); + else + Abc_NtkEliminate1( pNtk, ElimValue, nMaxSize, nIterMax, fReverse, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: eliminate [-VNI ] [-grsvh]\n"); + Abc_Print( -2, "\t traditional \"eliminate -1\", which collapses the node into its fanout\n"); + Abc_Print( -2, "\t if the node's variable appears in the fanout's factored form only once\n"); + Abc_Print( -2, "\t-V : the \"value\" parameter used by \"eliminate\" in SIS [default = %d]\n", ElimValue ); + Abc_Print( -2, "\t-N : the maximum node support after collapsing [default = %d]\n", nMaxSize ); + Abc_Print( -2, "\t-I : the maximum number of iterations [default = %d]\n", nIterMax ); + Abc_Print( -2, "\t-g : toggle using greedy eliminate (without \"value\") [default = %s]\n", fGreedy? "yes": "no" ); + Abc_Print( -2, "\t-r : use the reverse topological order [default = %s]\n", fReverse? "yes": "no" ); + Abc_Print( -2, "\t-s : toggle eliminating similar nodes [default = %s]\n", fSpecial? "yes": "no" ); + Abc_Print( -2, "\t-v : print verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDisjoint( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes, * pNtkNew; + int fGlobal, fRecursive, fVerbose, fPrint, fShort, c; + + extern Abc_Ntk_t * Abc_NtkDsdGlobal( Abc_Ntk_t * pNtk, int fVerbose, int fPrint, int fShort ); + extern int Abc_NtkDsdLocal( Abc_Ntk_t * pNtk, int fVerbose, int fRecursive ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + fGlobal = 1; + fRecursive = 0; + fVerbose = 0; + fPrint = 0; + fShort = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "grvpsh" ) ) != EOF ) + { + switch ( c ) + { + case 'g': + fGlobal ^= 1; + break; + case 'r': + fRecursive ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'p': + fPrint ^= 1; + break; + case 's': + fShort ^= 1; + break; + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( fGlobal ) + { +// Abc_Print( 0, "Performing DSD of global functions of the network.\n" ); + // get the new network + if ( !Abc_NtkIsStrash(pNtk) ) + { + pNtkNew = Abc_NtkStrash( pNtk, 0, 0, 0 ); + pNtkRes = Abc_NtkDsdGlobal( pNtkNew, fVerbose, fPrint, fShort ); + Abc_NtkDelete( pNtkNew ); + } + else + { + pNtkRes = Abc_NtkDsdGlobal( pNtk, fVerbose, fPrint, fShort ); + } + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Global DSD has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + } + else if ( fRecursive ) + { + if ( !Abc_NtkIsBddLogic( pNtk ) ) + { + Abc_Print( -1, "This command is only applicable to logic BDD networks.\n" ); + return 1; + } + if ( fVerbose ) + Abc_Print( 1, "Performing recursive DSD and MUX decomposition of local functions.\n" ); + if ( !Abc_NtkDsdLocal( pNtk, fVerbose, fRecursive ) ) + Abc_Print( -1, "Recursive DSD has failed.\n" ); + } + else + { + if ( !Abc_NtkIsBddLogic( pNtk ) ) + { + Abc_Print( -1, "This command is only applicable to logic BDD networks (run \"bdd\").\n" ); + return 1; + } + if ( fVerbose ) + Abc_Print( 1, "Performing simple non-recursive DSD of local functions.\n" ); + if ( !Abc_NtkDsdLocal( pNtk, fVerbose, fRecursive ) ) + Abc_Print( -1, "Simple DSD of local functions has failed.\n" ); + } + return 0; + +usage: + Abc_Print( -2, "usage: dsd [-grvpsh]\n" ); + Abc_Print( -2, "\t decomposes the network using disjoint-support decomposition\n" ); + Abc_Print( -2, "\t-g : toggle DSD of global and local functions [default = %s]\n", fGlobal? "global": "local" ); + Abc_Print( -2, "\t-r : toggle recursive DSD/MUX and simple DSD [default = %s]\n", fRecursive? "recursive DSD/MUX": "simple DSD" ); + Abc_Print( -2, "\t-v : prints DSD statistics and runtime [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-p : prints DSD structure to the standard output [default = %s]\n", fPrint? "yes": "no" ); + Abc_Print( -2, "\t-s : use short PI names when printing DSD structure [default = %s]\n", fShort? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSparsify( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Abc_Ntk_t * Abc_NtkSparsify( Abc_Ntk_t * pNtk, int nPerc, int fVerbose ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkNew; + int nPerc, fVerbose, c; + // set defaults + nPerc = 10; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nPerc = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nPerc < 1 || nPerc > 100 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + break; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsBddLogic( pNtk ) ) + { + Abc_Print( -1, "This command is only applicable to logic BDD networks (run \"bdd\").\n" ); + return 1; + } + if ( Abc_NtkCiNum(pNtk) > 16 ) + { + Abc_Print( -1, "The number of primary inputs is more than 16.\n" ); + return 1; + } + pNtkNew = Abc_NtkSparsify( pNtk, nPerc, fVerbose ); + if ( pNtkNew == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew ); + return 0; + +usage: + Abc_Print( -2, "usage: sparsify [-N num] [-vh]\n" ); + Abc_Print( -2, "\t creates incompletely-specified function\n" ); + Abc_Print( -2, "\t-N : the percentage of on-set and off-set minterms (1 <= num <= 100) [default = %d]\n", nPerc ); + Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandLutpack( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Lpk_Par_t Pars, * pPars = &Pars; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + memset( pPars, 0, sizeof(Lpk_Par_t) ); + pPars->nLutsMax = 4; // (N) the maximum number of LUTs in the structure + pPars->nLutsOver = 3; // (Q) the maximum number of LUTs not in the MFFC + pPars->nVarsShared = 0; // (S) the maximum number of shared variables (crossbars) + pPars->nGrowthLevel = 0; // (L) the maximum number of increased levels + pPars->fSatur = 1; + pPars->fZeroCost = 0; + pPars->fFirst = 0; + pPars->fOldAlgo = 0; + pPars->fVerbose = 0; + pPars->fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NQSLszfovwh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nLutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nLutsMax < 2 || pPars->nLutsMax > 16 ) + goto usage; + break; + case 'Q': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-Q\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nLutsOver = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nLutsOver < 0 || pPars->nLutsOver > 8 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nVarsShared = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nVarsShared < 0 || pPars->nVarsShared > 4 ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nGrowthLevel = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nGrowthLevel < 0 || pPars->nGrowthLevel > ABC_INFINITY ) + goto usage; + break; + case 's': + pPars->fSatur ^= 1; + break; + case 'z': + pPars->fZeroCost ^= 1; + break; + case 'f': + pPars->fFirst ^= 1; + break; + case 'o': + pPars->fOldAlgo ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'w': + pPars->fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to a logic network.\n" ); + return 1; + } + if ( pPars->nVarsShared < 0 || pPars->nVarsShared > 3 ) + { + Abc_Print( -1, "The number of shared variables (%d) is not in the range 0 <= S <= 3.\n", pPars->nVarsShared ); + return 1; + } + + // modify the current network + if ( !Lpk_Resynthesize( pNtk, pPars ) ) + { + Abc_Print( -1, "Resynthesis has failed.\n" ); + return 1; + } + return 0; + +usage: + Abc_Print( -2, "usage: lutpack [-NQSL ] [-szfovwh]\n" ); + Abc_Print( -2, "\t performs \"rewriting\" for LUT network;\n" ); + Abc_Print( -2, "\t determines LUT size as the max fanin count of a node;\n" ); + Abc_Print( -2, "\t if the network is not LUT-mapped, packs it into 6-LUTs\n" ); + Abc_Print( -2, "\t (there is another command for resynthesis after LUT mapping, \"mfs2\")\n" ); + Abc_Print( -2, "\t-N : the max number of LUTs in the structure (2 <= num) [default = %d]\n", pPars->nLutsMax ); + Abc_Print( -2, "\t-Q : the max number of LUTs not in MFFC (0 <= num) [default = %d]\n", pPars->nLutsOver ); + Abc_Print( -2, "\t-S : the max number of LUT inputs shared (0 <= num <= 3) [default = %d]\n", pPars->nVarsShared ); + Abc_Print( -2, "\t-L : max level increase after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel ); + Abc_Print( -2, "\t-s : toggle iteration till saturation [default = %s]\n", pPars->fSatur? "yes": "no" ); + Abc_Print( -2, "\t-z : toggle zero-cost replacements [default = %s]\n", pPars->fZeroCost? "yes": "no" ); + Abc_Print( -2, "\t-f : toggle using only first node and first cut [default = %s]\n", pPars->fFirst? "yes": "no" ); + Abc_Print( -2, "\t-o : toggle using old implementation [default = %s]\n", pPars->fOldAlgo? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle detailed printout of decomposed functions [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandLutmin( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Abc_Ntk_t * Abc_NtkLutmin( Abc_Ntk_t * pNtk, int nLutSize, int fReorder, int fVerbose ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; + int c; + int nLutSize = 4; + int fReorder = 1; + int fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Krvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'r': + fReorder ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + // modify the current network + pNtkRes = Abc_NtkLutmin( pNtk, nLutSize, fReorder, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "The command has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: lutmin [-K ] [-rvh]\n" ); + Abc_Print( -2, "\t perform FPGA mapping while minimizing the LUT count\n" ); + Abc_Print( -2, "\t as described in the paper T. Sasao and A. Mishchenko:\n" ); + Abc_Print( -2, "\t \"On the number of LUTs to implement logic functions\".\n" ); + Abc_Print( -2, "\t-K : the LUT size to use for the mapping (2 <= num) [default = %d]\n", nLutSize ); + Abc_Print( -2, "\t-r : toggle using BDD variable reordering [default = %s]\n", fReorder? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +#if 0 + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandImfs( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Res_Par_t Pars, * pPars = &Pars; + int c; + + // set defaults + pPars->nWindow = 62; + pPars->nCands = 5; + pPars->nSimWords = 4; + pPars->nGrowthLevel = 0; + pPars->fArea = 0; + pPars->fVerbose = 0; + pPars->fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "WSCLavwh" ) ) != EOF ) + { + switch ( c ) + { + case 'W': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nWindow = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nWindow < 1 || pPars->nWindow > 99 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nSimWords = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nSimWords < 1 || pPars->nSimWords > 256 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nCands = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nCands < 0 || pPars->nCands > ABC_INFINITY ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nGrowthLevel = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nGrowthLevel < 0 || pPars->nGrowthLevel > ABC_INFINITY ) + goto usage; + break; + case 'a': + pPars->fArea ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'w': + pPars->fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to a logic network.\n" ); + return 1; + } + + // modify the current network + if ( !Abc_NtkResynthesize( pNtk, pPars ) ) + { + Abc_Print( -1, "Resynthesis has failed.\n" ); + return 1; + } + return 0; + +usage: + Abc_Print( -2, "usage: imfs [-W ] [-LCS ] [-avwh]\n" ); + Abc_Print( -2, "\t performs resubstitution-based resynthesis with interpolation\n" ); + Abc_Print( -2, "\t (there is another command for resynthesis after LUT mapping, \"lutpack\")\n" ); + Abc_Print( -2, "\t-W : fanin/fanout levels (NxM) of the window (00 <= NM <= 99) [default = %d%d]\n", pPars->nWindow/10, pPars->nWindow%10 ); + Abc_Print( -2, "\t-C : the max number of resub candidates (1 <= n) [default = %d]\n", pPars->nCands ); + Abc_Print( -2, "\t-S : the number of simulation words (1 <= n <= 256) [default = %d]\n", pPars->nSimWords ); + Abc_Print( -2, "\t-L : the max increase in node level after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel ); + Abc_Print( -2, "\t-a : toggle optimization for area only [default = %s]\n", pPars->fArea? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle printout subgraph statistics [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +#endif + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMfs( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Mfs_Par_t Pars, * pPars = &Pars; + int c; + // set defaults + Abc_NtkMfsParsDefault( pPars ); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "WFDMLCdraestpgvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'W': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nWinTfoLevs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nWinTfoLevs < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nFanoutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nFanoutsMax < 0 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nDepthMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nDepthMax < 0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nWinMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nWinMax < 0 ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nGrowthLevel = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nGrowthLevel < 0 || pPars->nGrowthLevel > ABC_INFINITY ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nBTLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nBTLimit < 0 ) + goto usage; + break; + case 'd': + pPars->fRrOnly ^= 1; + break; + case 'r': + pPars->fResub ^= 1; + break; + case 'a': + pPars->fArea ^= 1; + break; + case 'e': + pPars->fMoreEffort ^= 1; + break; + case 's': + pPars->fSwapEdge ^= 1; + break; + case 't': + pPars->fOneHotness ^= 1; + break; + case 'p': + pPars->fPower ^= 1; + break; + case 'g': + pPars->fGiaSat ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'w': + pPars->fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to a logic network.\n" ); + return 1; + } + + // modify the current network + if ( !Abc_NtkMfs( pNtk, pPars ) ) + { + Abc_Print( -1, "Resynthesis has failed.\n" ); + return 1; + } + return 0; + +usage: + Abc_Print( -2, "usage: mfs [-WFDMLC ] [-draestpgvh]\n" ); + Abc_Print( -2, "\t performs don't-care-based optimization of logic networks\n" ); + Abc_Print( -2, "\t-W : the number of levels in the TFO cone (0 <= num) [default = %d]\n", pPars->nWinTfoLevs ); + Abc_Print( -2, "\t-F : the max number of fanouts to skip (1 <= num) [default = %d]\n", pPars->nFanoutsMax ); + Abc_Print( -2, "\t-D : the max depth nodes to try (0 = no limit) [default = %d]\n", pPars->nDepthMax ); + Abc_Print( -2, "\t-M : the max node count of windows to consider (0 = no limit) [default = %d]\n", pPars->nWinMax ); + Abc_Print( -2, "\t-L : the max increase in node level after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel ); + Abc_Print( -2, "\t-C : the max number of conflicts in one SAT run (0 = no limit) [default = %d]\n", pPars->nBTLimit ); + Abc_Print( -2, "\t-d : toggle performing redundancy removal [default = %s]\n", pPars->fRrOnly? "yes": "no" ); + Abc_Print( -2, "\t-r : toggle resubstitution and dc-minimization [default = %s]\n", pPars->fResub? "resub": "dc-min" ); + Abc_Print( -2, "\t-a : toggle minimizing area or area+edges [default = %s]\n", pPars->fArea? "area": "area+edges" ); + Abc_Print( -2, "\t-e : toggle high-effort resubstitution [default = %s]\n", pPars->fMoreEffort? "yes": "no" ); + Abc_Print( -2, "\t-s : toggle evaluation of edge swapping [default = %s]\n", pPars->fSwapEdge? "yes": "no" ); + Abc_Print( -2, "\t-t : toggle using artificial one-hotness conditions [default = %s]\n", pPars->fOneHotness? "yes": "no" ); + Abc_Print( -2, "\t-p : toggle power-aware optimization [default = %s]\n", pPars->fPower? "yes": "no" ); + Abc_Print( -2, "\t-g : toggle using new SAT solver [default = %s]\n", pPars->fGiaSat? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMfs2( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int Abc_NtkPerformMfs( Abc_Ntk_t * pNtk, Sfm_Par_t * pPars ); + extern int Abc_NtkMfsAfterICheck( Abc_Ntk_t * p, int nFrames, int nFramesAdd, Vec_Int_t * vFlops, Sfm_Par_t * pPars ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Sfm_Par_t Pars, * pPars = &Pars; + int c, fIndDCs = 0, fUseAllFfs = 0, nFramesAdd = 0; + // set defaults + Sfm_ParSetDefault( pPars ); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "WFDMLCZNIdaeijlvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'W': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nTfoLevMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nTfoLevMax < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nFanoutMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nFanoutMax < 0 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nDepthMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nDepthMax < 0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nWinSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nWinSizeMax < 0 ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nGrowthLevel = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nGrowthLevel < -ABC_INFINITY || pPars->nGrowthLevel > ABC_INFINITY ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nBTLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nBTLimit < 0 ) + goto usage; + break; + case 'Z': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-Z\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nFirstFixed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nFirstFixed < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nNodesMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nNodesMax < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nFramesAdd = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFramesAdd < 0 ) + goto usage; + break; + case 'd': + pPars->fRrOnly ^= 1; + break; + case 'a': + pPars->fArea ^= 1; + break; + case 'e': + pPars->fMoreEffort ^= 1; + break; + case 'i': + fIndDCs ^= 1; + break; + case 'j': + fUseAllFfs ^= 1; + break; + case 'l': + pPars->fUseDcs ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'w': + pPars->fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to a logic network.\n" ); + return 1; + } + if ( fIndDCs ) + { + if ( fUseAllFfs ) + { + pAbc->nIndFrames = 1; + Vec_IntFreeP( &pAbc->vIndFlops ); + pAbc->vIndFlops = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) ); + Vec_IntFill( pAbc->vIndFlops, Abc_NtkLatchNum(pNtk), 1 ); + } + if ( pAbc->nIndFrames <= 0 ) + { + Abc_Print( -1, "The number of k-inductive frames is not specified.\n" ); + return 0; + } + if ( pAbc->vIndFlops == NULL ) + { + Abc_Print( -1, "The set of k-inductive flops is not specified.\n" ); + return 0; + } + if ( Vec_IntSize(pAbc->vIndFlops) != Abc_NtkLatchNum(pNtk) ) + { + Abc_Print( -1, "The saved flop count (%d) does not match that of the current network (%d).\n", + Vec_IntSize(pAbc->vIndFlops), Abc_NtkLatchNum(pNtk) ); + return 0; + } + // modify the current network + if ( !Abc_NtkMfsAfterICheck( pNtk, pAbc->nIndFrames, nFramesAdd, pAbc->vIndFlops, pPars ) ) + { + Abc_Print( -1, "Resynthesis has failed.\n" ); + return 1; + } + if ( fUseAllFfs ) + { + pAbc->nIndFrames = 0; + Vec_IntFreeP( &pAbc->vIndFlops ); + } + } + else + { + // modify the current network + if ( !Abc_NtkPerformMfs( pNtk, pPars ) ) + { + Abc_Print( -1, "Resynthesis has failed.\n" ); + return 1; + } + } + return 0; + +usage: + Abc_Print( -2, "usage: mfs2 [-WFDMLCZNI ] [-daeijlvwh]\n" ); + Abc_Print( -2, "\t performs don't-care-based optimization of logic networks\n" ); + Abc_Print( -2, "\t-W : the number of levels in the TFO cone (0 <= num) [default = %d]\n", pPars->nTfoLevMax ); + Abc_Print( -2, "\t-F : the max number of fanouts to skip (1 <= num) [default = %d]\n", pPars->nFanoutMax ); + Abc_Print( -2, "\t-D : the max depth nodes to try (0 = no limit) [default = %d]\n", pPars->nDepthMax ); + Abc_Print( -2, "\t-M : the max node count of windows to consider (0 = no limit) [default = %d]\n", pPars->nWinSizeMax ); + Abc_Print( -2, "\t-L : the max increase in node level after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel ); + Abc_Print( -2, "\t-C : the max number of conflicts in one SAT run (0 = no limit) [default = %d]\n", pPars->nBTLimit ); + Abc_Print( -2, "\t-Z : treat the first logic nodes as fixed (0 = none) [default = %d]\n", pPars->nFirstFixed ); + Abc_Print( -2, "\t-N : the max number of nodes to try (0 = all) [default = %d]\n", pPars->nNodesMax ); + Abc_Print( -2, "\t-d : toggle performing redundancy removal [default = %s]\n", pPars->fRrOnly? "yes": "no" ); + Abc_Print( -2, "\t-a : toggle minimizing area or area+edges [default = %s]\n", pPars->fArea? "area": "area+edges" ); + Abc_Print( -2, "\t-e : toggle high-effort resubstitution [default = %s]\n", pPars->fMoreEffort? "yes": "no" ); + Abc_Print( -2, "\t-i : toggle using inductive don't-cares [default = %s]\n", fIndDCs? "yes": "no" ); + Abc_Print( -2, "\t-j : toggle using all flops when \"-i\" is enabled [default = %s]\n", fUseAllFfs? "yes": "no" ); + Abc_Print( -2, "\t-I : the number of additional frames inserted [default = %d]\n", nFramesAdd ); + Abc_Print( -2, "\t-l : toggle deriving don't-cares [default = %s]\n", pPars->fUseDcs? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMfs3( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_NtkPerformMfs3( Abc_Ntk_t * pNtk, Sfm_Par_t * pPars ); + extern void Sfm_ParSetDefault3( Sfm_Par_t * pPars ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Sfm_Par_t Pars, * pPars = &Pars; int c; + // set defaults + Sfm_ParSetDefault3( pPars ); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "IOVFKLHRMCNPWDEarmzoespdlvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nTfiLevMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nTfiLevMax < 1 ) + { + Abc_Print( -1, "The number of TFI levels (switch \"-I\") should be at least 1.\n" ); + goto usage; + } + break; + case 'O': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nTfoLevMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nTfoLevMax < 0 ) + goto usage; + break; + case 'V': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-V\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nTfiLevMax = pPars->nTfoLevMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nTfiLevMax < 1 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nFanoutMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nFanoutMax < 0 ) + goto usage; + break; + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nVarMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nVarMax < 2 || pPars->nVarMax > 8 ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nMffcMin = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nMffcMin < 0 ) + goto usage; + break; + case 'H': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-H\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nMffcMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nMffcMax < 0 ) + goto usage; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nDecMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nDecMax < 0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nWinSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nWinSizeMax < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nBTLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nBTLimit < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nNodesMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nNodesMax < 0 ) + goto usage; + break; + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + pPars->iNodeOne = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->iNodeOne < 0 ) + goto usage; + break; + case 'W': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nTimeWin = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nTimeWin < 0 || pPars->nTimeWin > 100 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + pPars->DeltaCrit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->DeltaCrit < 0 ) + goto usage; + break; + case 'E': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-E\" should be followed by an integer.\n" ); + goto usage; + } + pPars->DelAreaRatio = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->DelAreaRatio < 0 ) + goto usage; + break; + case 'a': + pPars->fArea ^= 1; + break; + case 'r': + pPars->fAreaRev ^= 1; + break; + case 'm': + pPars->fUseAndOr ^= 1; + break; + case 'z': + pPars->fZeroCost ^= 1; + break; + case 'o': + pPars->fRrOnly ^= 1; + break; + case 'e': + pPars->fMoreEffort ^= 1; + break; + case 's': + pPars->fUseSim ^= 1; + break; + case 'p': + pPars->fPrintDecs ^= 1; + break; + case 'd': + pPars->fDelayVerbose ^= 1; + break; + case 'l': + pPars->fLibVerbose ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'w': + pPars->fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsMappedLogic(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to a mapped logic network.\n" ); + return 1; + } + // modify the current network + Abc_NtkPerformMfs3( pNtk, pPars ); + return 0; + +usage: + Abc_Print( -2, "usage: mfs3 [-IOVFKLHRMCNPWDE ] [-armzespdlvwh]\n" ); + Abc_Print( -2, "\t performs don't-care-based optimization of mapped networks\n" ); + Abc_Print( -2, "\t-I : the number of levels in the TFI cone (1 <= num) [default = %d]\n", pPars->nTfiLevMax ); + Abc_Print( -2, "\t-O : the number of levels in the TFO cone (0 <= num) [default = %d]\n", pPars->nTfoLevMax ); + Abc_Print( -2, "\t-V : the number of levels in the TFI/TFO cone (1 <= num) [default = %d]\n", pPars->nTfiLevMax ); + Abc_Print( -2, "\t-F : the max number of fanouts to skip (1 <= num) [default = %d]\n", pPars->nFanoutMax ); + Abc_Print( -2, "\t-K : the max number of variables (2 <= num <= 8 ) [default = %d]\n", pPars->nVarMax ); + Abc_Print( -2, "\t-L : the min size of max fanout-free cone (MFFC) (area-only) [default = %d]\n", pPars->nMffcMin ); + Abc_Print( -2, "\t-H : the max size of max fanout-free cone (MFFC) (area-only) [default = %d]\n", pPars->nMffcMax ); + Abc_Print( -2, "\t-R : the max number of decomposition rounds (1 <= num <= 4) [default = %d]\n", pPars->nDecMax ); + Abc_Print( -2, "\t-M : the max node count of windows to consider (0 = no limit) [default = %d]\n", pPars->nWinSizeMax ); + Abc_Print( -2, "\t-C : the max number of conflicts in one SAT run (0 = no limit) [default = %d]\n", pPars->nBTLimit ); + Abc_Print( -2, "\t-N : the max number of nodes to try (0 = all) [default = %d]\n", pPars->nNodesMax ); + Abc_Print( -2, "\t-P : one particular node to try (0 = none) [default = %d]\n", pPars->iNodeOne ); + Abc_Print( -2, "\t-W : size of timing window in percents (0 <= num <= 100) [default = %d]\n", pPars->nTimeWin ); + Abc_Print( -2, "\t-D : size of critical-timing delay-delta (in picoseconds) [default = %d]\n", pPars->DeltaCrit ); + Abc_Print( -2, "\t-E : delay-area tradeoff (in picoseconds per area-unit) [default = %d]\n", pPars->DelAreaRatio ); + Abc_Print( -2, "\t-a : toggle area minimization [default = %s]\n", pPars->fArea? "yes": "no" ); + Abc_Print( -2, "\t-r : toggle using reverse topo order for area minimization [default = %s]\n", pPars->fAreaRev? "yes": "no" ); + Abc_Print( -2, "\t-m : toggle detecting multi-input AND/OR gates [default = %s]\n", pPars->fUseAndOr? "yes": "no" ); + Abc_Print( -2, "\t-z : toggle zero-cost replacements [default = %s]\n", pPars->fZeroCost? "yes": "no" ); + Abc_Print( -2, "\t-e : toggle using more effort [default = %s]\n", pPars->fMoreEffort? "yes": "no" ); + Abc_Print( -2, "\t-s : toggle using simulation [default = %s]\n", pPars->fUseSim? "yes": "no" ); + Abc_Print( -2, "\t-p : toggle printing decompositions [default = %s]\n", pPars->fPrintDecs? "yes": "no" ); + Abc_Print( -2, "\t-d : toggle printing delay profile statistics [default = %s]\n", pPars->fDelayVerbose? "yes": "no" ); + Abc_Print( -2, "\t-l : toggle printing library usage statistics [default = %s]\n", pPars->fLibVerbose? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMfse( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Abc_Ntk_t * Abc_NtkOptMfse( Abc_Ntk_t * pNtk, Acb_Par_t * pPars ); + Abc_Ntk_t * pNtkNew, * pNtk = Abc_FrameReadNtk(pAbc); + Acb_Par_t Pars, * pPars = &Pars; int c; + Acb_ParSetDefault( pPars ); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "IOWFLCadvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nTfiLevMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nTfiLevMax < 0 ) + goto usage; + break; + case 'O': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nTfoLevMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nTfoLevMax < 0 ) + goto usage; + break; + case 'W': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nWinNodeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nWinNodeMax < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nFanoutMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nFanoutMax < 0 ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nGrowthLevel = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nGrowthLevel < -ABC_INFINITY || pPars->nGrowthLevel > ABC_INFINITY ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nBTLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nBTLimit < 0 ) + goto usage; + break; + case 'a': + pPars->fArea ^= 1; + break; + case 'd': + pPars->fUseAshen ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'w': + pPars->fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to a logic network.\n" ); + return 1; + } + pPars->nLutSize = Abc_NtkGetFaninMax( pNtk ); + if ( pPars->nLutSize > 6 ) + { + Abc_Print( -1, "Command is only applicable to LUT size no more than 6.\n" ); + return 1; + } + Abc_NtkToSop( pNtk, -1, ABC_INFINITY ); + pNtkNew = Abc_NtkOptMfse( pNtk, pPars ); + if ( pNtkNew == NULL ) + { + Abc_Print( -1, "Command \"mfse\" has failed.\n" ); + return 1; + } + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkNew ); + return 0; + +usage: + Abc_Print( -2, "usage: mfse [-IOWFLC ] [-advwh]\n" ); + Abc_Print( -2, "\t performs don't-care-based optimization of logic networks\n" ); + Abc_Print( -2, "\t-I : the number of levels in the TFI cone (2 <= num) [default = %d]\n", pPars->nTfiLevMax ); + Abc_Print( -2, "\t-O : the number of levels in the TFO cone (0 <= num) [default = %d]\n", pPars->nTfoLevMax ); + Abc_Print( -2, "\t-W : the max number of nodes in the window (1 <= num) [default = %d]\n", pPars->nWinNodeMax ); + Abc_Print( -2, "\t-F : the max number of fanouts to skip (1 <= num) [default = %d]\n", pPars->nFanoutMax ); + Abc_Print( -2, "\t-L : the max increase in node level after resynthesis (0 <= num) [default = %d]\n", pPars->nGrowthLevel ); + Abc_Print( -2, "\t-C : the max number of conflicts in one SAT run (0 = no limit) [default = %d]\n", pPars->nBTLimit ); + Abc_Print( -2, "\t-a : toggle minimizing area [default = %s]\n", pPars->fArea? "area": "delay" ); + Abc_Print( -2, "\t-d : toggle using Ashenhurst decomposition [default = %s]\n", pPars->fUseAshen? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandLogicPush( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Abc_Ntk_t * Abc_NtkOptPush( Abc_Ntk_t * pNtk, int nLutSize, int fVerbose ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Abc_Ntk_t * pNtkRes; + int nLutSize = 4; + int fVerbose = 0; + int c; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Kvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by a positive integer.\n" ); + goto usage; + } + nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutSize < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to a logic network.\n" ); + return 1; + } + nLutSize = Abc_MaxInt( nLutSize, Abc_NtkGetFaninMax(pNtk) ); + Abc_NtkToSop( pNtk, -1, ABC_INFINITY ); + pNtkRes = Abc_NtkOptPush( pNtk, nLutSize, fVerbose ); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; +usage: + Abc_Print( -2, "usage: logicpush [-K num] [-vh]\n" ); + Abc_Print( -2, "\t performs logic pushing to reduce structural bias\n" ); + Abc_Print( -2, "\t-K : the LUT size used in the mapping [default = %d]\n", nLutSize ); + Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTrace( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fUseLutLib; + int fVerbose; + extern void Abc_NtkDelayTracePrint( Abc_Ntk_t * pNtk, int fUseLutLib, int fVerbose ); + + // set defaults + fUseLutLib = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lvh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUseLutLib ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to a logic network.\n" ); + return 1; + } + + // modify the current network + Abc_NtkDelayTracePrint( pNtk, fUseLutLib, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: trace [-lvh]\n" ); + Abc_Print( -2, "\t performs delay trace of LUT-mapped network\n" ); + Abc_Print( -2, "\t-l : toggle using unit- or LUT-library-delay model [default = %s]\n", fUseLutLib? "lib": "unit" ); + Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandGlitch( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int nPats = 4000; + int Prob = 8; + int fVerbose = 1; + int c; + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NPvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nPats = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nPats < 1 ) + goto usage; + break; + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + Prob = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Prob < 1 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to a mapped logic network.\n" ); + return 1; + } + if ( Abc_NtkIsMappedLogic(pNtk) || Abc_NtkGetFaninMax(pNtk) <= 6 ) + Abc_Print( 1, "Glitching adds %7.2f %% of signal transitions, compared to switching.\n", Abc_NtkMfsTotalGlitching(pNtk, nPats, Prob, fVerbose) ); + else + printf( "Currently computes glitching only for K-LUT networks with K <= 6.\n" ); + return 0; + +usage: + Abc_Print( -2, "usage: glitch [-NP ] [-vh]\n" ); + Abc_Print( -2, "\t comparing glitching activity to switching activity\n" ); + Abc_Print( -2, "\t-N : the number of random patterns to use (0 < num < 1000000) [default = %d]\n", nPats ); + Abc_Print( -2, "\t-P : once in how many cycles an input changes its value [default = %d]\n", Prob ); + Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSpeedup( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int fUseLutLib; + int Percentage; + int Degree; + int fVerbose; + int fVeryVerbose; + extern Abc_Ntk_t * Abc_NtkSpeedup( Abc_Ntk_t * pNtk, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose ); + pNtk = Abc_FrameReadNtk(pAbc); + + // set defaults + fUseLutLib = 0; + Percentage = 5; + Degree = 2; + fVerbose = 0; + fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "PNlvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + Percentage = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Percentage < 1 || Percentage > 100 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + Degree = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Degree < 1 || Degree > 5 ) + goto usage; + break; + case 'l': + fUseLutLib ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to a logic network.\n" ); + return 1; + } + + // modify the current network + pNtkRes = Abc_NtkSpeedup( pNtk, fUseLutLib, Percentage, Degree, fVerbose, fVeryVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "The command has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: speedup [-PN ] [-lvwh]\n" ); + Abc_Print( -2, "\t transforms LUT-mapped network into an AIG with choices;\n" ); + Abc_Print( -2, "\t the choices are added to speedup the next round of mapping\n" ); + Abc_Print( -2, "\t-P : delay delta defining critical path for library model [default = %d%%]\n", Percentage ); + Abc_Print( -2, "\t-N : the max critical path degree for resynthesis (0 < num < 6) [default = %d]\n", Degree ); + Abc_Print( -2, "\t-l : toggle using unit- or LUT-library-delay model [default = %s]\n", fUseLutLib? "lib" : "unit" ); + Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle printing detailed stats for each node [default = %s]\n", fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPowerdown( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int fUseLutLib; + int Percentage; + int Degree; + int fVerbose; + int fVeryVerbose; + extern Abc_Ntk_t * Abc_NtkPowerdown( Abc_Ntk_t * pNtk, int fUseLutLib, int Percentage, int Degree, int fVerbose, int fVeryVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + fUseLutLib = 0; + Percentage =10; + Degree = 2; + fVerbose = 0; + fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "PNlvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + Percentage = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Percentage < 1 || Percentage > 100 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + Degree = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Degree < 1 || Degree > 5 ) + goto usage; + break; + case 'l': + fUseLutLib ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to a logic network.\n" ); + return 1; + } + + // modify the current network + pNtkRes = Abc_NtkPowerdown( pNtk, fUseLutLib, Percentage, Degree, fVerbose, fVeryVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "The command has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: powerdown [-PN ] [-vwh]\n" ); + Abc_Print( -2, "\t transforms LUT-mapped network into an AIG with choices;\n" ); + Abc_Print( -2, "\t the choices are added to power down the next round of mapping\n" ); + Abc_Print( -2, "\t-P : switching propability delta defining power critical edges [default = %d%%]\n", Percentage ); + Abc_Print( -2, "\t (e.g. 5% means hot wires switch with probability: 0.45 <= p <= 0.50 (max)\n" ); + Abc_Print( -2, "\t-N : the max critical path degree for resynthesis (0 < num < 6) [default = %d]\n", Degree ); +// Abc_Print( -2, "\t-l : toggle using unit- or LUT-library-delay model [default = %s]\n", fUseLutLib? "lib" : "unit" ); + Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle printing detailed stats for each node [default = %s]\n", fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAddBuffs( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Abc_Ntk_t * Abc_NtkAddBuffs( Abc_Ntk_t * pNtk, int fDirect, int fReverse, int nImprove, int fVerbose ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Abc_Ntk_t * pNtkRes; + int fDirect; + int fReverse; + int nImprove; + int c, fVerbose; + + fDirect = 0; + fReverse = 0; + nImprove = 1000; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Idrvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by a positive integer.\n" ); + goto usage; + } + nImprove = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nImprove < 0 ) + goto usage; + break; + case 'd': + fDirect ^= 1; + break; + case 'r': + fReverse ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to a logic network.\n" ); + return 1; + } + + // modify the current network + pNtkRes = Abc_NtkAddBuffs( pNtk, fDirect, fReverse, nImprove, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "The command has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: addbuffs [-I num] [-drvh]\n" ); + Abc_Print( -2, "\t adds buffers to create balanced CI/CO paths\n" ); + Abc_Print( -2, "\t-I : the number of refinement iterations [default = %d]\n", nImprove ); + Abc_Print( -2, "\t-d : toggle using only CI-to-CO levelized order [default = %s]\n", fDirect? "yes": "no" ); + Abc_Print( -2, "\t-r : toggle using only CO-to-C1 levelized order [default = %s]\n", fReverse? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +//#if 0 +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMerge( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Nwk_LMPars_t Pars, * pPars = &Pars; + Vec_Int_t * vResult; + int c; + extern Vec_Int_t * Abc_NtkLutMerge( Abc_Ntk_t * pNtk, Nwk_LMPars_t * pPars ); + // set defaults + memset( pPars, 0, sizeof(Nwk_LMPars_t) ); + pPars->nMaxLutSize = 5; // the max LUT size for merging (N=5) + pPars->nMaxSuppSize = 5; // the max total support size after merging (S=5) + pPars->nMaxDistance = 3; // the max number of nodes separating LUTs + pPars->nMaxLevelDiff = 2; // the max difference in levels + pPars->nMaxFanout = 100; // the max number of fanouts to traverse + pPars->fUseDiffSupp = 0; // enables the use of nodes with different support + pPars->fUseTfiTfo = 0; // enables the use of TFO/TFO nodes as candidates + pPars->fVeryVerbose = 0; // enables additional verbose output + pPars->fVerbose = 1; // enables verbose output + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NSDLFscvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nMaxLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nMaxLutSize < 2 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nMaxSuppSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nMaxSuppSize < 2 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nMaxDistance = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nMaxDistance < 2 ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nMaxLevelDiff = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nMaxLevelDiff < 2 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nMaxFanout = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nMaxFanout < 2 ) + goto usage; + break; + case 's': + pPars->fUseDiffSupp ^= 1; + break; + case 'c': + pPars->fUseTfiTfo ^= 1; + break; + case 'w': + pPars->fVeryVerbose ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL || !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "Abc_CommandMerge(): There is no mapped network to merge LUTs.\n" ); + return 1; + } + + vResult = Abc_NtkLutMerge( pNtk, pPars ); + Vec_IntFree( vResult ); + return 0; + +usage: + Abc_Print( -2, "usage: merge [-NSDLF ] [-scwvh]\n" ); + Abc_Print( -2, "\t creates pairs of topologically-related LUTs\n" ); + Abc_Print( -2, "\t-N : the max LUT size for merging (1 < num) [default = %d]\n", pPars->nMaxLutSize ); + Abc_Print( -2, "\t-S : the max total support size after merging (1 < num) [default = %d]\n", pPars->nMaxSuppSize ); + Abc_Print( -2, "\t-D : the max distance in terms of LUTs (0 < num) [default = %d]\n", pPars->nMaxDistance ); + Abc_Print( -2, "\t-L : the max difference in levels (0 <= num) [default = %d]\n", pPars->nMaxLevelDiff ); + Abc_Print( -2, "\t-F : the max number of fanouts to stop traversal (0 < num) [default = %d]\n", pPars->nMaxFanout ); + Abc_Print( -2, "\t-s : toggle the use of nodes without support overlap [default = %s]\n", pPars->fUseDiffSupp? "yes" : "no" ); + Abc_Print( -2, "\t-c : toggle the use of TFI/TFO nodes as candidates [default = %s]\n", pPars->fUseTfiTfo? "yes" : "no" ); + Abc_Print( -2, "\t-w : toggle printing detailed stats for each node [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing optimization summary [default = %s]\n", pPars->fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} +//#endif + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTestDec( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int Abc_DecTest( char * pFileName, int DecType, int nVarNum, int fVerbose ); + char * pFileName; + int c; + int fVerbose = 0; + int DecType = 0; + int nVarNum = -1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ANvh" ) ) != EOF ) + { + switch ( c ) + { + case 'A': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-A\" should be followed by an integer.\n" ); + goto usage; + } + DecType = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( DecType < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nVarNum = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVarNum < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + { + Abc_Print( 1,"Input file is not given.\n" ); + return 0; + } + if ( nVarNum >= 0 && nVarNum < 6 ) + { + Abc_Print( 1,"The number of variables cannot be less than 6.\n" ); + return 0; + } + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the testbench + Abc_DecTest( pFileName, DecType, nVarNum, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: testdec [-AN ] [-vh] \n" ); + Abc_Print( -2, "\t testbench for Boolean decomposition algorithms\n" ); + Abc_Print( -2, "\t-A : decomposition algorithm [default = %d]\n", DecType ); + Abc_Print( -2, "\t 0: none (reading and writing the file)\n" ); + Abc_Print( -2, "\t 1: algebraic factoring applied to ISOP\n" ); + Abc_Print( -2, "\t 2: bi-decomposition with cofactoring\n" ); + Abc_Print( -2, "\t 3: disjoint-support decomposition with cofactoring\n" ); + Abc_Print( -2, "\t 4: updated disjoint-support decomposition with cofactoring\n" ); + Abc_Print( -2, "\t 5: enumerating decomposable variable sets\n" ); + Abc_Print( -2, "\t 6: disjoint-support decomposition with cofactoring and boolean difference analysis\n" ); + Abc_Print( -2, "\t from V. Callegaro, F. S. Marranghello, M. G. A. Martins, R. P. Ribas and A. I. Reis,\n"); + Abc_Print( -2, "\t \"Bottom-up disjoint-support decomposition based on cofactor and boolean difference analysis,\" ICCD'15.\n" ); + Abc_Print( -2, "\t-N : the number of support variables (binary files only) [default = unused]\n" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : a text file with truth tables in hexadecimal, listed one per line,\n"); + Abc_Print( -2, "\t or a binary file with an array of truth tables (in this case,\n"); + Abc_Print( -2, "\t -N is required to determine how many functions are stored)\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTestNpn( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int Abc_NpnTest( char * pFileName, int NpnType, int nVarNum, int fDumpRes, int fBinary, int fVerbose ); + char * pFileName; + int c; + int fVerbose = 0; + int NpnType = 0; + int nVarNum = -1; + int fDumpRes = 0; + int fBinary = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ANdbvh" ) ) != EOF ) + { + switch ( c ) + { + case 'A': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-A\" should be followed by an integer.\n" ); + goto usage; + } + NpnType = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( NpnType < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nVarNum = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVarNum < 0 ) + goto usage; + break; + case 'd': + fDumpRes ^= 1; + break; + case 'b': + fBinary ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + { + Abc_Print( 1,"Input file is not given.\n" ); + return 0; + } + if ( nVarNum >= 0 && nVarNum < 6 ) + { + Abc_Print( 1,"The number of variables cannot be less than 6.\n" ); + return 0; + } + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the testbench + Abc_NpnTest( pFileName, NpnType, nVarNum, fDumpRes, fBinary, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: testnpn [-AN ] [-dbvh] \n" ); + Abc_Print( -2, "\t testbench for computing (semi-)canonical forms\n" ); + Abc_Print( -2, "\t of completely-specified Boolean functions up to 16 variables\n" ); + Abc_Print( -2, "\t-A : semi-caninical form computation algorithm [default = %d]\n", NpnType ); + Abc_Print( -2, "\t 0: uniqifying truth tables\n" ); + Abc_Print( -2, "\t 1: exact NPN canonical form by brute-force enumeration\n" ); + Abc_Print( -2, "\t 2: semi-canonical form by counting 1s in cofactors\n" ); + Abc_Print( -2, "\t 3: Jake's hybrid semi-canonical form (fast)\n" ); + Abc_Print( -2, "\t 4: Jake's hybrid semi-canonical form (high-effort)\n" ); + Abc_Print( -2, "\t 5: new fast hybrid semi-canonical form\n" ); + Abc_Print( -2, "\t 6: new phase canonical form\n" ); + Abc_Print( -2, "\t 7: new hierarchical matching\n" ); + Abc_Print( -2, "\t 8: hierarchical matching by XueGong Zhou at Fudan University, Shanghai\n" ); + Abc_Print( -2, "\t 9: adjustable algorithm (heuristic) by XueGong Zhou at Fudan University, Shanghai\n" ); + Abc_Print( -2, "\t 10: adjustable algorithm (exact) by XueGong Zhou at Fudan University, Shanghai\n" ); + Abc_Print( -2, "\t 11: new cost-aware exact algorithm by XueGong Zhou at Fudan University, Shanghai\n" ); + Abc_Print( -2, "\t 12: new fast hybrid semi-canonical form (permutation only)\n" ); + Abc_Print( -2, "\t-N : the number of support variables (binary files only) [default = unused]\n" ); + Abc_Print( -2, "\t-d : toggle dumping resulting functions into a file [default = %s]\n", fDumpRes? "yes": "no" ); + Abc_Print( -2, "\t-b : toggle dumping in binary format [default = %s]\n", fBinary? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : a text file with truth tables in hexadecimal, listed one per line,\n"); + Abc_Print( -2, "\t or a binary file with an array of truth tables (in this case,\n"); + Abc_Print( -2, "\t -N is required to determine how many functions are stored)\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTestRPO(Abc_Frame_t * pAbc, int argc, char ** argv) { + extern int Abc_RpoTest(char * pFileName, int nVarNum, int nThreshold, int fVerbose); + char * pFileName; + int c; + int nVarNum = -1; + int fVerbose = 0; + int nThreshold = -1; + Extra_UtilGetoptReset(); + while ((c = Extra_UtilGetopt(argc, argv, "TNvh")) != EOF) { + switch (c) { + case 'N': + if (globalUtilOptind >= argc) { + Abc_Print(-1, "Command line switch \"-N\" should be followed by an integer.\n"); + goto usage; + } + nVarNum = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if (nVarNum < 0) + goto usage; + break; + case 'T': + if (globalUtilOptind >= argc) { + Abc_Print(-1, "Command line switch \"-T\" should be followed by an integer.\n"); + goto usage; + } + nThreshold = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if (nThreshold < 0) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if (argc != globalUtilOptind + 1) + { + Abc_Print(1, "Input file is not given.\n"); + goto usage; + } + // get the output file name + pFileName = argv[globalUtilOptind]; + // call the testbench + Abc_RpoTest( pFileName, nVarNum, nThreshold, fVerbose ); + return 0; + +usage: + Abc_Print(-2, "usage: testrpo [-NT ] [-vh] \n"); + Abc_Print(-2, "\t RPO algorithm developed and implemented by Mayler G. A. Martins,\n"); + Abc_Print(-2, "\t Vinicius Callegaro, Renato P. Ribas and Andre' I. Reis\n"); + Abc_Print(-2, "\t at Federal University of Rio Grande do Sul, Porto Alegre, Brazil\n"); + Abc_Print(-2, "\t-N : the number of support variables (binary files only) [default = unused]\n"); + Abc_Print(-2, "\t-T : the number of recursions accepted before abort [default = INFINITE]\n"); + Abc_Print(-2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose ? "yes" : "no"); + Abc_Print(-2, "\t-h : print the command usage\n"); + Abc_Print(-2, "\t : a text file with truth tables in hexadecimal, listed one per line,\n"); + Abc_Print(-2, "\t or a binary file with an array of truth tables (in this case,\n"); + Abc_Print(-2, "\t -N is required to determine how many functions are stored)\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTestTruth( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int * Kit_TruthTest( char * pFileName ); + int * pResult = NULL; + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + { + Abc_Print( 1,"Input file is not given.\n" ); + return 0; + } + pResult = Kit_TruthTest( argv[globalUtilOptind] ); + ABC_FREE( pResult ); + return 0; + +usage: + Abc_Print( -2, "usage: testtruth [-vh] \n" ); + Abc_Print( -2, "\t printing truth table stats\n" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTestSupp( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_NtkSuppMinFile( char * pFileName ); + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + { + Abc_Print( 1,"Input file is not given.\n" ); + return 0; + } + Abc_NtkSuppMinFile( argv[globalUtilOptind] ); + return 0; + +usage: + Abc_Print( -2, "usage: testsupp [-vh] \n" ); + Abc_Print( -2, "\t reads truth tables from file and support-minimizes them\n" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : file to read the truth tables from\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTestRand( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_NtkRandFile( char * pFileName, int nVars, int nFuncs, int nMints ); + int c, nVars = 0, nFuncs = 0, nMints = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NFMvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVars < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nFuncs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + nMints = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + { + Abc_Print( 1,"Input file is not given.\n" ); + return 0; + } + Abc_NtkRandFile( argv[globalUtilOptind], nVars, nFuncs, nMints ); + return 0; + +usage: + Abc_Print( -2, "usage: testrand [-NFMvh] \n" ); + Abc_Print( -2, "\t generates truth tables and writes them into a file\n" ); + Abc_Print( -2, "\t-N : the number of input variables [default = %d]\n", nVars ); + Abc_Print( -2, "\t-F : the number of random functions to generate [default = %d]\n", nFuncs ); + Abc_Print( -2, "\t-M : the number of positive minterms in the random function [default = %d]\n", nMints ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : file to write the truth tables to\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRunSat( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pFile = NULL; + char * pFileCnf = NULL; + int c, i, fWalk = 0, fKissat = 0, nIters = 10, fVerbose = 0; + abctime clk; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Ikwvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIters < 0 ) + goto usage; + break; + case 'k': + fKissat ^= 1; + break; + case 'w': + fWalk ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( fKissat + fWalk != 1 ) { + printf( "Exactly one SAT solver should be selected.\n" ); + return 1; + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + pFileCnf = argv[globalUtilOptind]; + pFile = fopen( pFileCnf, "rb" ); + if ( pFile == NULL ) { + printf( "The file \"%s\" cannot be found.\n", pFileCnf ); + return 1; + } + fclose( pFile ); + clk = Abc_Clock(); + for ( i = 0; i < nIters; i++ ) { + char pCommand[1000]; + if ( fKissat ) + sprintf( pCommand, "kissat -q --seed=%d %s", i, pFileCnf ); + else if ( fWalk ) + sprintf( pCommand, "walk -s%d %s", i, pFileCnf ); +#if defined(__wasm) + if (1) { +#else + if (system(pCommand) == -1) { +#endif + fprintf(stdout, "Command \"%s\" did not succeed.\n", pCommand); + return 0; + } + } + printf( "Performed %d iterations of SAT solving. ", nIters ); + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + return 0; + +usage: + Abc_Print( -2, "usage: runsat [-I num] [-kwvh] \n" ); + Abc_Print( -2, "\t performs randomized iterations of SAT solving\n" ); + Abc_Print( -2, "\t-I num : the number of iterations [default = %d]\n", nIters ); + Abc_Print( -2, "\t-k : toggle using Kissat (binary name \"kissat\") [default = %s]\n", fKissat? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle using WalkSat (binary name \"walk\") [default = %s]\n", fWalk? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRunEco( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Acb_NtkRunEco( char * pFileNames[4], int nTimeout, int fCheck, int fRandom, int fInputs, int fUnitW, int fVerbose, int fVeryVerbose ); + char * pFileNames[4] = {NULL}; + int c, nTimeout = 0, fCheck = 0, fRandom = 0, fInputs = 0, fUnitW = 0, fVerbose = 0, fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Tcriuvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + nTimeout = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nTimeout < 0 ) + goto usage; + break; + case 'c': + fCheck ^= 1; + break; + case 'r': + fRandom ^= 1; + break; + case 'i': + fInputs ^= 1; + break; + case 'u': + fUnitW ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } +// pArgvNew = argv + globalUtilOptind; +// nArgcNew = argc - globalUtilOptind; + if ( argc - globalUtilOptind < 2 || argc - globalUtilOptind > 3 ) + { + Abc_Print( 1, "Expecting three file names on the command line.\n" ); + goto usage; + } + for ( c = 0; c < argc - globalUtilOptind; c++ ) + { + FILE * pFile = fopen( argv[globalUtilOptind+c], "rb" ); + if ( pFile == NULL ) + { + printf( "Cannot open input file \"%s\".\n", argv[globalUtilOptind+c] ); + return 0; + } + else + fclose( pFile ); + pFileNames[c] = argv[globalUtilOptind+c]; + } + Acb_NtkRunEco( pFileNames, nTimeout, fCheck, fRandom, fInputs, fUnitW, fVerbose, fVeryVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: runeco [-T num] [-criuvwh] \n" ); + Abc_Print( -2, "\t performs computation of patch functions during ECO,\n" ); + Abc_Print( -2, "\t as described in the following paper: A. Q. Dao et al\n" ); + Abc_Print( -2, "\t \"Efficient computation of ECO patch functions\", Proc. DAC\'18\n" ); + Abc_Print( -2, "\t https://people.eecs.berkeley.edu/~alanmi/publications/2018/dac18_eco.pdf\n" ); + Abc_Print( -2, "\t (currently only applicable to benchmarks from 2017 ICCAD CAD competition\n" ); + Abc_Print( -2, "\t http://cad-contest-2017.el.cycu.edu.tw/Problem_A/default.html as follows:\n" ); + Abc_Print( -2, "\t \"runeco unit1/F.v unit1/G.v unit1/weight.txt; cec -n out.v unit1/G.v\")\n" ); + Abc_Print( -2, "\t-T num : the timeout in seconds [default = %d]\n", nTimeout ); + Abc_Print( -2, "\t-c : toggle checking that the problem has a solution [default = %s]\n", fCheck? "yes": "no" ); + Abc_Print( -2, "\t-r : toggle using random permutation of support variables [default = %s]\n", fRandom? "yes": "no" ); + Abc_Print( -2, "\t-i : toggle using primary inputs as support variables [default = %s]\n", fInputs? "yes": "no" ); + Abc_Print( -2, "\t-u : toggle using unit weights [default = %s]\n", fUnitW? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle printing more verbose information [default = %s]\n", fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRunGen( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Acb_NtkRunGen( int nInputs, int nMints, int nFuncs, int Seed, int fVerbose, char * pScript ); + int c, nInputs = 10, nMints = 10, nFuncs = 10, Seed = 0, fVerbose = 0; char * pScript = NULL; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "IMRSCvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nInputs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + nMints = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + nFuncs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + Seed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by a script.\n" ); + goto usage; + } + pScript = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pScript == NULL ) + { + Abc_Print( -1, "Command line switch \"-C\" should be specified and followed by a string.\n" ); + goto usage; + } + Acb_NtkRunGen( nInputs, nMints, nFuncs, Seed, fVerbose, pScript ); + return 0; + +usage: + Abc_Print( -2, "usage: rungen [-IMRS num] [-C script] [-vh]\n" ); + Abc_Print( -2, "\t running the script on a set of randomly generated functions\n" ); + Abc_Print( -2, "\t-I : the number of input variables [default = %d]\n", nInputs ); + Abc_Print( -2, "\t-M : the number of positive minterms in the random function [default = %d]\n", nMints ); + Abc_Print( -2, "\t-R : the number of random functions to try [default = %d]\n", nFuncs ); + Abc_Print( -2, "\t-S : the random seed [default = %d]\n", Seed ); + Abc_Print( -2, "\t-C : the script to apply [default = provided by the user]\n" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRunTest( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Acb_NtkRunTest( char * pFileNames[4], int fFancy, int fVerbose ); + char * pFileNames[4] = {NULL}; + int c, fFancy = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "fvh" ) ) != EOF ) + { + switch ( c ) + { + case 'f': + fFancy ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc - globalUtilOptind < 2 || argc - globalUtilOptind > 5 ) + { + Abc_Print( 1, "Expecting two or three file names on the command line.\n" ); + goto usage; + } + for ( c = 0; c < argc - globalUtilOptind; c++ ) + pFileNames[c] = argv[globalUtilOptind+c]; + Acb_NtkRunTest( pFileNames, fFancy, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: xec [-fvh] \n" ); + Abc_Print( -2, "\t combinational equivalence checking with x-values\n" ); + Abc_Print( -2, "\t-f : toggle using experimental feature [default = %s]\n", fFancy? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [Orchestration synthesis] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandOrchestrate( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pDup; + int c, RetValue; + + int nNodeSizeMax; + int nConeSizeMax; + int fUpdateLevel; + int fUseZeros_rwr; + int fUseZeros_ref; + int fUseDcs; + int RS_CUT_MIN = 4;//rs option + int RS_CUT_MAX = 16;//rs option + int nCutsMax; //rs option + int nNodesMax; //rs option + int nLevelsOdc; //rs option + + int fPrecompute; //rewrite option (not enabled) + int fPlaceEnable; //rewrite option (not enabled) + + int fVerbose; //rewrite/rs/rf verbose + int fVeryVerbose; //very verbose option for all + //size_t NtkSize; + extern void Rwr_Precompute(); + + //local greedy + extern int Abc_NtkOrchLocal( Abc_Ntk_t * pNtk, int fUseZeros_rwr, int fUseZeros_ref, int fPlaceEnable, int nCutsMax, int nNodesMax, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose, int nNodeSizeMax, int nConeSizeMax, int fUseDcs ); + //priority orch + extern int Abc_NtkOchestration( Abc_Ntk_t * pNtk, Vec_Int_t **pGain_rwr, Vec_Int_t **pGain_res,Vec_Int_t **pGain_ref, int sOpsOrder, int fUseZeros_rwr, int fUseZeros_ref, int fPlaceEnable, int nCutsMax, int nNodesMax, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose, int nNodeSizeMax, int nConeSizeMax, int fUseDcs ); + // set defaults + nNodeSizeMax = 10; + nConeSizeMax = 16; + fUpdateLevel = 1; + fUseZeros_rwr = 1; + fUseZeros_ref = 1; + fUseDcs = 0; + fVerbose = 0; + fVeryVerbose = 0; + fPlaceEnable = 0; + fPrecompute = 0; + nCutsMax = 8; + nNodesMax = 1; + nLevelsOdc = 0; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KNFZzlvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nCutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCutsMax < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nNodesMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nNodesMax < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nLevelsOdc = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLevelsOdc < 0 ) + goto usage; + break; + case 'l': + fUpdateLevel ^= 1; + break; + case 'z': + fUseZeros_rwr ^= 1; + break; + case 'Z': + fUseZeros_ref ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + break; + } + } + if ( fPrecompute ) + { + Rwr_Precompute(); + return 0; + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( nCutsMax < RS_CUT_MIN || nCutsMax > RS_CUT_MAX ) + { + Abc_Print( -1, "Can only compute cuts for %d <= K <= %d.\n", RS_CUT_MIN, RS_CUT_MAX ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + Abc_Print( -1, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + return 1; + } + if ( nNodeSizeMax > 15 ) + { + Abc_Print( -1, "The cone size cannot exceed 15.\n" ); + return 1; + } + + if ( fUseDcs && nNodeSizeMax >= nConeSizeMax ) + { + Abc_Print( -1, "For don't-care to work, containing cone should be larger than collapsed node.\n" ); + return 1; + } + + // modify the current network + pDup = Abc_NtkDup( pNtk ); + RetValue = Abc_NtkOrchLocal( pNtk, fUseZeros_rwr, fUseZeros_ref, fPlaceEnable, nCutsMax, nNodesMax, nLevelsOdc, fUpdateLevel, fVerbose, fVeryVerbose, nNodeSizeMax, nConeSizeMax, fUseDcs ); + if ( RetValue == -1 ) + { + Abc_FrameReplaceCurrentNetwork( pAbc, pDup ); + printf( "An error occurred during computation. The original network is restored.\n" ); + } + else + { + Abc_NtkDelete( pDup ); + if ( RetValue == 0 ) + { + Abc_Print( 0, "Ochestration (local greedy) has failed.\n" ); + return 1; + } + } + return 0; + +usage: + Abc_Print( -2, "usage: orchestrate [-KNFZzlvwh]\n" ); + Abc_Print( -2, "\t performs technology-independent AIG synthesis using orchestration method (currently orchestrating rw/rf/rs)\n" ); + Abc_Print( -2, "\t-K : (resub)the max cut size (%d <= num <= %d) [default = %d]\n", RS_CUT_MIN, RS_CUT_MAX, nCutsMax ); + Abc_Print( -2, "\t-N : (resub)the max number of nodes to add (0 <= num <= 3) [default = %d]\n", nNodesMax ); + Abc_Print( -2, "\t-F : (resub)the number of fanout levels for ODC computation [default = %d]\n", nLevelsOdc ); + Abc_Print( -2, "\t-l : (resub/rw/refactor)toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + Abc_Print( -2, "\t-z : (rw)toggle using zero-cost replacements [default = %s]\n", fUseZeros_rwr? "yes": "no" ); + Abc_Print( -2, "\t-Z : (refactor)toggle using zero-cost replacements [default = %s]\n", fUseZeros_ref? "yes": "no" ); + Abc_Print( -2, "\t-v : (resub/rw/refactor)toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : (resub/rw/refactor)toggle detailed verbose printout [default = %s]\n", fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [AIG RTL Augmentation] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAIGAugmentation( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pDup; + int c, RetValue; + int nNodeSizeMax; + int nConeSizeMax; + int fUpdateLevel; + int fUseZeros_rwr; + int fUseZeros_ref; + int fUseDcs; + int fVerbose; + int RS_CUT_MIN = 4; + int RS_CUT_MAX = 16; + + int fPrecompute; + int fPlaceEnable; + int nNodesMax; + int nCutsMax; + int nLevelsOdc; + int fVeryVerbose; + int Rand_Seed; + //int sOpsOrder; + size_t NtkSize; + char *DecisionFile = NULL; + Vec_Int_t *DecisionMask; + Vec_Int_t *pGain_rwr; + Vec_Int_t *pGain_res; + Vec_Int_t *pGain_ref; + //FILE *maskFile; + extern void Rwr_Precompute(); + extern int Abc_NtkOrchRand( Abc_Ntk_t * pNtk, Vec_Int_t **pGain_rwr, Vec_Int_t **pGain_res,Vec_Int_t **pGain_ref, Vec_Int_t **DecisionMask, char *DecisionFile, int Rand_Seed, int fUseZeros_rwr, int fUseZeros_ref, int fPlaceEnable, int nCutsMax, int nNodesMax, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose, int nNodeSizeMax, int nConeSizeMax, int fUseDcs ); + // set defaults + nNodeSizeMax = 10; + nConeSizeMax = 16; + fUpdateLevel = 1; + fUseZeros_rwr = 0; + fUseZeros_ref = 0; + fUseDcs = 0; + fVerbose = 0; + fVeryVerbose = 0; + fPlaceEnable = 0; + fPrecompute = 0; + nCutsMax = 8; + nNodesMax = 1; + nLevelsOdc = 0; + Rand_Seed = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "zZdsh" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + break; + case 'z': + fUseZeros_rwr ^= 1; + break; + case 'Z': + fUseZeros_ref ^= 1; + break; + case 'd': + if ( globalUtilOptind >= argc ) + { + goto usage; + } + DecisionFile = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 's': + if ( globalUtilOptind >= argc ) + { + goto usage; + } + Rand_Seed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + } + } + if ( fPrecompute ) + { + Rwr_Precompute(); + return 0; + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( nCutsMax < RS_CUT_MIN || nCutsMax > RS_CUT_MAX ) + { + Abc_Print( -1, "Can only compute cuts for %d <= K <= %d.\n", RS_CUT_MIN, RS_CUT_MAX ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + Abc_Print( -1, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + return 1; + } + if ( nNodeSizeMax > 15 ) + { + Abc_Print( -1, "The cone size cannot exceed 15.\n" ); + return 1; + } + + if ( fUseDcs && nNodeSizeMax >= nConeSizeMax ) + { + Abc_Print( -1, "For don't-care to work, containing cone should be larger than collapsed node.\n" ); + return 1; + } + NtkSize = Abc_NtkObjNumMax(pNtk); + + DecisionMask = Vec_IntAlloc(1); + for (int i=0; inSize, DecisionList->pArray[0]); + if ( RetValue == -1 ) + { + Abc_FrameReplaceCurrentNetwork( pAbc, pDup ); + printf( "An error occurred during computation. The original network is restored.\n" ); + } + else + { + Abc_NtkDelete( pDup ); + if ( RetValue == 0 ) + { + Abc_Print( 0, "Orchestration evaluation for RL has failed.\n" ); + return 1; + } + } + // Vec_IntPrint(pGain_rwr); + return 0; + +usage: + Abc_Print( -2, "usage: aigaug [-s ] [-d ][-zZdsh]\n" ); + Abc_Print( -2, "\t performs technology-independent AIG random synthesis (node level) for RTL augmentation\n" ); + Abc_Print( -2, "\t-z : toggle using zero-cost replacements for rwr for aigaug [default = %s]\n", fUseZeros_rwr? "yes": "no" ); + Abc_Print( -2, "\t-Z : toggle using zero-cost replacements for ref for aigaug [default = %s]\n", fUseZeros_ref? "yes": "no" ); + Abc_Print( -2, "\t-d : record random synthesis decision made during augmentation [required filename; e.g., test.csv]\n"); + Abc_Print( -2, "\t-s : set the random seed for random augmentation\n"); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\tExample : read i10.aig;st;aigaug -s 1 -d test.csv;write i10_arg_1.aig;cec i10.aig i10_arg_1.aig\n"); + return 1; +} + + + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pDup; + int c, RetValue; + int fUpdateLevel; + int fPrecompute; + int fUseZeros; + int fVerbose; + int fVeryVerbose; + int fPlaceEnable; + // external functions + extern void Rwr_Precompute(); + + // set defaults + fUpdateLevel = 1; + fPrecompute = 0; + fUseZeros = 0; + fVerbose = 0; + fVeryVerbose = 0; + fPlaceEnable = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lxzvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUpdateLevel ^= 1; + break; + case 'x': + fPrecompute ^= 1; + break; + case 'z': + fUseZeros ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'p': + fPlaceEnable ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( fPrecompute ) + { + Rwr_Precompute(); + return 0; + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + Abc_Print( -1, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + return 1; + } + + // modify the current network + pDup = Abc_NtkDup( pNtk ); + RetValue = Abc_NtkRewrite( pNtk, fUpdateLevel, fUseZeros, fVerbose, fVeryVerbose, fPlaceEnable ); + if ( RetValue == -1 ) + { + Abc_FrameReplaceCurrentNetwork( pAbc, pDup ); + printf( "An error occurred during computation. The original network is restored.\n" ); + } + else + { + Abc_NtkDelete( pDup ); + if ( RetValue == 0 ) + { + Abc_Print( 0, "Rewriting has failed.\n" ); + return 1; + } + } + return 0; + +usage: + Abc_Print( -2, "usage: rewrite [-lzvwh]\n" ); + Abc_Print( -2, "\t performs technology-independent rewriting of the AIG\n" ); + Abc_Print( -2, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + Abc_Print( -2, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle printout subgraph statistics [default = %s]\n", fVeryVerbose? "yes": "no" ); +// Abc_Print( -2, "\t-p : toggle placement-aware rewriting [default = %s]\n", fPlaceEnable? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pDup; + int c, RetValue; + int nNodeSizeMax; + int nMinSaved; + int nConeSizeMax; + int fUpdateLevel; + int fUseZeros; + int fUseDcs; + int fVerbose; + extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nMinSaved, int nConeSizeMax, int fUpdateLevel, int fUseZeros, int fUseDcs, int fVerbose ); + + // set defaults + nNodeSizeMax = 10; + nMinSaved = 1; + nConeSizeMax = 16; + fUpdateLevel = 1; + fUseZeros = 0; + fUseDcs = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NMClzvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nNodeSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nNodeSizeMax < 0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + nMinSaved = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMinSaved < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConeSizeMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConeSizeMax < 0 ) + goto usage; + break; + case 'l': + fUpdateLevel ^= 1; + break; + case 'z': + fUseZeros ^= 1; + break; + case 'd': + fUseDcs ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( fUseZeros ) + nMinSaved = 0; + if ( nMinSaved == 0 ) + fUseZeros = 1; + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + Abc_Print( -1, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + return 1; + } + if ( nNodeSizeMax > 15 ) + { + Abc_Print( -1, "The cone size cannot exceed 15.\n" ); + return 1; + } + + if ( fUseDcs && nNodeSizeMax >= nConeSizeMax ) + { + Abc_Print( -1, "For don't-care to work, containing cone should be larger than collapsed node.\n" ); + return 1; + } + + // modify the current network + pDup = Abc_NtkDup( pNtk ); + RetValue = Abc_NtkRefactor( pNtk, nNodeSizeMax, nMinSaved, nConeSizeMax, fUpdateLevel, fUseZeros, fUseDcs, fVerbose ); + if ( RetValue == -1 ) + { + Abc_FrameReplaceCurrentNetwork( pAbc, pDup ); + printf( "An error occurred during computation. The original network is restored.\n" ); + } + else + { + Abc_NtkDelete( pDup ); + if ( RetValue == 0 ) + { + Abc_Print( 0, "Refactoring has failed.\n" ); + return 1; + } + } + return 0; + +usage: + Abc_Print( -2, "usage: refactor [-NM ] [-lzvh]\n" ); + Abc_Print( -2, "\t performs technology-independent refactoring of the AIG\n" ); + Abc_Print( -2, "\t-N : the max support of the collapsed node [default = %d]\n", nNodeSizeMax ); + Abc_Print( -2, "\t-M : the min number of nodes saved after one step (0 <= num) [default = %d]\n", nMinSaved ); +// Abc_Print( -2, "\t-C : the max support of the containing cone [default = %d]\n", nConeSizeMax ); + Abc_Print( -2, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + Abc_Print( -2, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" ); +// Abc_Print( -2, "\t-d : toggle using don't-cares [default = %s]\n", fUseDcs? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRestructure( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int nCutsMax; + int fUpdateLevel; + int fUseZeros; + int fVerbose; + extern int Abc_NtkRestructure( Abc_Ntk_t * pNtk, int nCutsMax, int fUpdateLevel, int fUseZeros, int fVerbose ); + + // set defaults + nCutsMax = 5; + fUpdateLevel = 0; + fUseZeros = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Klzvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nCutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCutsMax < 0 ) + goto usage; + break; + case 'l': + fUpdateLevel ^= 1; + break; + case 'z': + fUseZeros ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( nCutsMax < 4 || nCutsMax > CUT_SIZE_MAX ) + { + Abc_Print( -1, "Can only compute the cuts for %d <= K <= %d.\n", 4, CUT_SIZE_MAX ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + Abc_Print( -1, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + return 1; + } + + // modify the current network + if ( !Abc_NtkRestructure( pNtk, nCutsMax, fUpdateLevel, fUseZeros, fVerbose ) ) + { + Abc_Print( -1, "Refactoring has failed.\n" ); + return 1; + } + return 0; + +usage: + Abc_Print( -2, "usage: restructure [-K ] [-lzvh]\n" ); + Abc_Print( -2, "\t performs technology-independent restructuring of the AIG\n" ); + Abc_Print( -2, "\t-K : the max cut size (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, nCutsMax ); + Abc_Print( -2, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + Abc_Print( -2, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandResubstitute( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int RS_CUT_MIN = 4; + int RS_CUT_MAX = 16; + int c; + int nCutsMax; + int nNodesMax; + int nLevelsOdc; + int nMinSaved; + int fUpdateLevel; + int fUseZeros; + int fVerbose; + int fVeryVerbose; + extern int Abc_NtkResubstitute( Abc_Ntk_t * pNtk, int nCutsMax, int nNodesMax, int nMinSaved, int nLevelsOdc, int fUpdateLevel, int fVerbose, int fVeryVerbose ); + + // set defaults + nCutsMax = 8; + nNodesMax = 1; + nLevelsOdc = 0; + nMinSaved = 1; + fUpdateLevel = 1; + fUseZeros = 0; + fVerbose = 0; + fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KNMFlzvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nCutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCutsMax < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nNodesMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nNodesMax < 0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + nMinSaved = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMinSaved < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nLevelsOdc = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLevelsOdc < 0 ) + goto usage; + break; + case 'l': + fUpdateLevel ^= 1; + break; + case 'z': + fUseZeros ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( fUseZeros ) + nMinSaved = 0; + if ( nMinSaved == 0 ) + fUseZeros = 1; + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( nCutsMax < RS_CUT_MIN || nCutsMax > RS_CUT_MAX ) + { + Abc_Print( -1, "Can only compute cuts for %d <= K <= %d.\n", RS_CUT_MIN, RS_CUT_MAX ); + return 1; + } + if ( nNodesMax < 0 || nNodesMax > 3 ) + { + Abc_Print( -1, "Can only resubstitute at most 3 nodes.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + Abc_Print( -1, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + return 1; + } + + // modify the current network + if ( !Abc_NtkResubstitute( pNtk, nCutsMax, nNodesMax, nMinSaved, nLevelsOdc, fUpdateLevel, fVerbose, fVeryVerbose ) ) + { + Abc_Print( -1, "Refactoring has failed.\n" ); + return 1; + } + return 0; + +usage: + Abc_Print( -2, "usage: resub [-KNMF ] [-lzvwh]\n" ); + Abc_Print( -2, "\t performs technology-independent restructuring of the AIG\n" ); + Abc_Print( -2, "\t-K : the max cut size (%d <= num <= %d) [default = %d]\n", RS_CUT_MIN, RS_CUT_MAX, nCutsMax ); + Abc_Print( -2, "\t-N : the max number of nodes to add (0 <= num <= 3) [default = %d]\n", nNodesMax ); + Abc_Print( -2, "\t-M : the min number of nodes saved after one step (0 <= num) [default = %d]\n", nMinSaved ); + Abc_Print( -2, "\t-F : the number of fanout levels for ODC computation [default = %d]\n", nLevelsOdc ); + Abc_Print( -2, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + Abc_Print( -2, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle verbose printout of ODC computation [default = %s]\n", fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandResubUnate( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManResubUnateOne( char * pFileName, int nLimit, int nDivMax, int fWriteSol, int fVerbose ); + Gia_Man_t * pTemp; + int nLimit = 16; + int nDivMax = 50; + int fWriteSol = 0; + int fVerbose = 0, c; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "LDsvh" ) ) != EOF ) + { + switch ( c ) + { + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + nLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLimit < 0 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + nDivMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nDivMax < 0 ) + goto usage; + break; + case 's': + fWriteSol ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + { + Abc_Print( -1, "Input file should be given on the command line.\n" ); + return 1; + } + pTemp = Gia_ManResubUnateOne( argv[globalUtilOptind], nLimit, nDivMax, fWriteSol, fVerbose ); + if ( pTemp ) + { + Aig_Man_t * pMan = Gia_ManToAig( pTemp, 0 ); + Abc_Ntk_t * pNtk = Abc_NtkFromAigPhase( pMan ); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + Aig_ManStop( pMan ); + Gia_ManStop( pTemp ); + return 0; + } + Abc_Print( 0, "The networks is not generated.\n" ); + return 0; + +usage: + Abc_Print( -2, "usage: resub_unate [-LD ] [-svh] \n" ); + Abc_Print( -2, "\t solves one instance of the resub problem\n" ); + Abc_Print( -2, "\t-L num : the limit on the number of nodes [default = %d]\n", nLimit ); + Abc_Print( -2, "\t-D num : the maximum number of binate divisors to consider [default = %d]\n", nDivMax ); + Abc_Print( -2, "\t-s : toggle saving the result in the input file [default = %s]\n", fWriteSol? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : resub problem file name\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandResubCore( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Supp_ManSolveOne( char * pFileName, int nIters, int nRounds, int fWriteSol, int fVerbose ); + Gia_Man_t * pTemp; + int nIters = 1; + int nRounds = 1; + int fWriteSol = 0; + int fVerbose = 0, c; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "IRsvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIters < 0 ) + goto usage; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + nRounds = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nRounds < 0 ) + goto usage; + break; + case 's': + fWriteSol ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + { + Abc_Print( -1, "Input file should be given on the command line.\n" ); + return 1; + } + pTemp = Supp_ManSolveOne( argv[globalUtilOptind], nIters, nRounds, fWriteSol, fVerbose ); + if ( pTemp ) + { + Aig_Man_t * pMan = Gia_ManToAig( pTemp, 0 ); + Abc_Ntk_t * pNtk = Abc_NtkFromAigPhase( pMan ); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtk ); + Aig_ManStop( pMan ); + Gia_ManStop( pTemp ); + return 0; + } + Abc_Print( 0, "The networks is not generated.\n" ); + return 0; + +usage: + Abc_Print( -2, "usage: resub_core [-IR ] [-svh] \n" ); + Abc_Print( -2, "\t solves one instance of the resub problem\n" ); + Abc_Print( -2, "\t-I num : the number of iterations [default = %d]\n", nIters ); + Abc_Print( -2, "\t-R num : the number of rounds in each iteration [default = %d]\n", nRounds ); + Abc_Print( -2, "\t-s : toggle saving the result in the input file [default = %s]\n", fWriteSol? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : resub problem file name\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandResubCheck( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Res6_ManResubCheck( char * pFileNameRes, char * pFileNameSol, int fVerbose ); + extern void Res6_ManResubCheckPla( char * pFileName, int fVerbose ); + char * pFileR = NULL, * pFileS = NULL; + int fVerbose = 0, c; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc == globalUtilOptind + 2 ) + { + pFileR = argv[globalUtilOptind]; + pFileS = argv[globalUtilOptind+1]; + } + else if ( argc == globalUtilOptind + 1 ) + { + pFileR = argv[globalUtilOptind]; + pFileS = NULL; + } + else + { + Abc_Print( -1, "Incorrect number of command line arguments.\n" ); + return 1; + } + if ( !strcmp(pFileR + strlen(pFileR) - 3, "pla") ) + Res6_ManResubCheckPla( pFileR, fVerbose ); + else + Res6_ManResubCheck( pFileR, pFileS, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: resub_check [-vh] \n" ); + Abc_Print( -2, "\t checks solution to a resub problem\n" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t : resub problem file name\n"); + Abc_Print( -2, "\t : (optional) solution file name\n"); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRr( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c, Window; + int nFaninLevels; + int nFanoutLevels; + int fUseFanouts; + int fVerbose; + extern int Abc_NtkRR( Abc_Ntk_t * pNtk, int nFaninLevels, int nFanoutLevels, int fUseFanouts, int fVerbose ); + + // set defaults + nFaninLevels = 3; + nFanoutLevels = 3; + fUseFanouts = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Wfvh" ) ) != EOF ) + { + switch ( c ) + { + case 'W': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + Window = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Window < 0 ) + goto usage; + nFaninLevels = Window / 10; + nFanoutLevels = Window % 10; + break; + case 'f': + fUseFanouts ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + printf( "This command is obsolete." ); + printf( "To perform pure redudancy removal, try \"mfs -r\".\n" ); + printf( "To perform something a little stronger try \"mfs2\"\n" ); + printf( "When working with an AIG, use \"logic\" before and \"strash\" after this command.\n" ); + return 0; + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command can only be applied to an AIG (run \"strash\").\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum(pNtk) ) + { + Abc_Print( -1, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" ); + return 1; + } + + // modify the current network + if ( !Abc_NtkRR( pNtk, nFaninLevels, nFanoutLevels, fUseFanouts, fVerbose ) ) + { + Abc_Print( -1, "Redundancy removal has failed.\n" ); + return 1; + } + return 0; + +usage: + Abc_Print( -2, "usage: rr [-W NM] [-fvh]\n" ); + Abc_Print( -2, "\t removes combinational redundancies in the current network\n" ); + Abc_Print( -2, "\t-W NM : window size: TFI (N) and TFO (M) logic levels [default = %d%d]\n", nFaninLevels, nFanoutLevels ); + Abc_Print( -2, "\t-f : toggle RR w.r.t. fanouts [default = %s]\n", fUseFanouts? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCascade( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c, nLutSize; + int fCheck; + int fVerbose; + extern Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVerbose ); + pNtk = Abc_FrameReadNtk(pAbc); + + // set defaults + nLutSize = 12; + fCheck = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Kcvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutSize < 0 ) + goto usage; + break; + case 'c': + fCheck ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty neAtwork.\n" ); + return 1; + } + + if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Can only collapse a logic network or an AIG.\n" ); + return 1; + } + + // get the new network + if ( Abc_NtkIsStrash(pNtk) ) + pNtkRes = Abc_NtkCascade( pNtk, nLutSize, fCheck, fVerbose ); + else + { + pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); + pNtkRes = Abc_NtkCascade( pNtk, nLutSize, fCheck, fVerbose ); + Abc_NtkDelete( pNtk ); + } + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Cascade synthesis has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: cascade [-K ] [-cvh]\n" ); + Abc_Print( -2, "\t performs LUT cascade synthesis for the current network\n" ); + Abc_Print( -2, "\t-K : the number of LUT inputs [default = %d]\n", nLutSize ); + Abc_Print( -2, "\t-c : check equivalence after synthesis [default = %s]\n", fCheck? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t \n"); + Abc_Print( -2, " A lookup-table cascade is a programmable architecture developed by\n"); + Abc_Print( -2, " Professor Tsutomu Sasao (sasao@cse.kyutech.ac.jp) at Kyushu Institute\n"); + Abc_Print( -2, " of Technology. This work received Takeda Techno-Entrepreneurship Award:\n"); + Abc_Print( -2, " http://www.lsi-cad.com/sasao/photo/takeda.html\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandLutCasDec( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Abc_Ntk_t * Abc_NtkLutCascadeGen( int nLutSize, int nStages, int nRails, int nShared, int fVerbose ); + extern Abc_Ntk_t * Abc_NtkLutCascade2( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose, char * pGuide ); + extern void Abc_NtkLutCascadeFile( char * pFileName, int nVarNum, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose, int fVeryVerbose ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; char * pGuide = NULL, * pFileName = NULL; + int c, nVarNum = -1, nLutSize = 6, nStages = 8, nRails = 1, nShared = 2, nIters = 10, fGen = 0, fVerbose = 0, fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KMRSINFgvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutSize < 0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + nStages = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nStages < 0 ) + goto usage; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + nRails = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nRails < 0 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + nShared = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nShared < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIters < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nVarNum = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVarNum < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by a file name.\n" ); + goto usage; + } + pFileName = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'g': + fGen ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pFileName ) + { + if ( nVarNum == -1 ) + { + Abc_Print( -1, "The number of variables should be given on the command line using switch \"-N \".\n" ); + return 1; + } + Abc_NtkLutCascadeFile( pFileName, nVarNum, nLutSize, nStages, nRails, nIters, fVerbose, fVeryVerbose ); + return 1; + } + if ( fGen ) + { + pNtkRes = Abc_NtkLutCascadeGen( nLutSize, nStages, nRails, nShared, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "LUT cascade generation failed.\n" ); + return 1; + } + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkCoNum(pNtk) != 1 ) + { + Abc_Print( -1, "This command is currently applicable only to single-output networks.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Run command \"strash\" to convert the network into an AIG.\n" ); + return 1; + } + if ( Abc_NtkCiNum(pNtk) > nLutSize + (nLutSize - nRails) * (nStages - 1) ) + { + Abc_Print( -1, "Cannot decompose %d-input function into a %d-rail cascade of %d %d-LUTs (max suppose size = %d).\n", + Abc_NtkCiNum(pNtk), nRails, nStages, nLutSize, nLutSize + (nLutSize - nRails) * (nStages - 1) ); + return 1; + } + if ( argc == globalUtilOptind + 1 ) + pGuide = argv[globalUtilOptind]; + pNtkRes = Abc_NtkLutCascade2( pNtk, nLutSize, nStages, nRails, nIters, fVerbose, pGuide ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "LUT cascade mapping failed.\n" ); + return 1; + } + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: lutcasdec [-KMRSIN ] [-F ] [-vwh]\n" ); + Abc_Print( -2, "\t decomposes the primary output functions into LUT cascades\n" ); + Abc_Print( -2, "\t-K : the number of LUT inputs [default = %d]\n", nLutSize ); + Abc_Print( -2, "\t-M : the maximum delay (the number of stages) [default = %d]\n", nStages ); + Abc_Print( -2, "\t-R : the number of direct connections (rails) [default = %d]\n", nRails ); + Abc_Print( -2, "\t-S : the number of shared variables in each stage [default = %d]\n", nShared ); + Abc_Print( -2, "\t-I : the number of iterations when looking for a solution [default = %d]\n", nIters ); + Abc_Print( -2, "\t-N : the number of support variables (for truth table files only) [default = unused]\n" ); + Abc_Print( -2, "\t-F : a text file with truth tables in hexadecimal listed one per line\n"); + Abc_Print( -2, "\t-g : toggle generating random cascade with these parameters [default = %s]\n", fGen? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle additional verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandLutCas( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Abc_Ntk_t * Abc_NtkLutCascadeMap( Abc_Ntk_t * pNtk, int nLutsMax, int nIters, int fDelayLut, int fDelayRoute, int fDelayDirect, int fVerbose ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; + int c, nLutSize = 6, nLutsMax = 8, nIters = 1000, Seed = 0, fVerbose = 0; + int fDelayLut = 10, fDelayRoute = 30, fDelayDirect = 3; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KMISLWDfvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutSize < 0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + nLutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutsMax < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIters < 0 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + Seed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Seed < 0 ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + fDelayLut = atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( fDelayLut < 0 ) + goto usage; + break; + case 'W': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + fDelayRoute = atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( fDelayRoute < 0 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + fDelayDirect = atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( fDelayDirect < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "Run command \"if\" or any other LUT mapper to map the current network into LUTs.\n" ); + return 1; + } + if ( Abc_NtkGetFaninMax(pNtk) > nLutSize ) + { + Abc_Print( -1, "The current network contains nodes with fanin count (%d) exceeding the LUT size (%d).\n", Abc_NtkGetFaninMax(pNtk), nLutSize ); + return 1; + } + srand( Seed ); + pNtkRes = Abc_NtkLutCascadeMap( pNtk, nLutsMax, nIters, fDelayLut, fDelayRoute, fDelayDirect, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "LUT cascade mapping failed.\n" ); + return 1; + } + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: lutcas [-KMISLWD ] [-vh]\n" ); + Abc_Print( -2, "\t decomposes the current network into LUT cascades\n" ); + Abc_Print( -2, "\t-K : the number of LUT inputs [default = %d]\n", nLutSize ); + Abc_Print( -2, "\t-M : the maximum number of LUTs in the cascade [default = %d]\n", nLutsMax ); + Abc_Print( -2, "\t-I : the number of iterations when looking for a solution [default = %d]\n", nIters ); + Abc_Print( -2, "\t-S : the random seed used to randimize solutions [default = %d]\n", Seed ); + Abc_Print( -2, "\t-L : the intrinsic LUT delay [default = %d]\n", fDelayLut ); + Abc_Print( -2, "\t-W : the routable wire delay [default = %d]\n", fDelayRoute ); + Abc_Print( -2, "\t-D : the non-routable wire delay [default = %d]\n", fDelayDirect ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandBsEval( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_BSEvalOneTest( word * pT, int nVars, int nBVars, int fVerbose ); + extern void Abc_BSEvalBestTest( word * pIn, int nVars, int nBVars, int fShared, int fVerbose ); + extern void Abc_BSEvalBestGen( int nVars, int nBVars, int nFuncs, int nMints, int fTryAll, int fShared, int fVerbose ); + int c, nVars = 0, nBVars = 0, nSVars = 0, nFuncs = 0, nMints = 0, fTryAll = 0, fVerbose = 0; char * pTtStr = NULL; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "IBSRMavh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVars < 2 || nVars > 16 ) + goto usage; + break; + case 'B': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" ); + goto usage; + } + nBVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nBVars < 1 || nBVars > 16 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + nSVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nSVars < 0 || nSVars > 16 ) + goto usage; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + nFuncs = atoi(argv[globalUtilOptind]); + if ( nFuncs < 1 ) + goto usage; + globalUtilOptind++; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + nMints = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'a': + fTryAll ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc == globalUtilOptind + 1 ) + pTtStr = argv[globalUtilOptind]; + if ( pTtStr ) + { + nVars = Abc_Base2Log((int)strlen(pTtStr)) + 2; + if ( (1 << (nVars-2)) != (int)strlen(pTtStr) ) + { + Abc_Print( -1, "Truth table is expected to have %d hex digits (instead of %d).\n", (1 << (nVars-2)), strlen(pTtStr) ); + return 1; + } + } + if ( nVars == 0 ) + { + Abc_Print( -1, "The number of variables should be specified on the command line.\n" ); + return 1; + } + if ( nBVars == 0 ) + { + Abc_Print( -1, "The bound set size should be specified on the command line.\n" ); + return 1; + } + if ( nFuncs ) + Abc_BSEvalBestGen( nVars, nBVars, nFuncs, nMints, fTryAll, nSVars == 1, fVerbose ); + else if ( pTtStr ) + { + word pTruth[1024] = {0}; + Abc_TtReadHex( pTruth, pTtStr ); + if ( fTryAll ) + Abc_BSEvalBestTest( pTruth, nVars, nBVars, nSVars == 1, fVerbose ); + else + Abc_BSEvalOneTest( pTruth, nVars, nBVars, fVerbose ); + } + return 0; + +usage: + Abc_Print( -2, "usage: bseval [-IBSRM ] [-avh] \n" ); + Abc_Print( -2, "\t bound set evaluation\n" ); + Abc_Print( -2, "\t-I : the number of input variables [default = %d]\n", nVars ); + Abc_Print( -2, "\t-B : the number of bound set variables [default = %d]\n", nBVars ); + Abc_Print( -2, "\t-S : the number of shared variables [default = %d]\n", nSVars ); + Abc_Print( -2, "\t-R : the number of random functions to try [default = unused]\n" ); + Abc_Print( -2, "\t-M : the number of positive minterms in the random function [default = unused]\n" ); + Abc_Print( -2, "\t-a : toggle trying all bound sets of this size [default = %s]\n", fTryAll ? "yes" : "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose ? "yes" : "no" ); + Abc_Print( -2, "\t-h : print the command usage\n" ); + Abc_Print( -2, "\t : truth table in hex notation\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandExtract( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Abc_Ntk_t * Abc_NtkShareXor( Abc_Ntk_t * pNtk, int nMultiSize, int fAnd, int fVerbose ); + Abc_Ntk_t * pNtk, * pNtkRes; + int c, nMultiSize, fAnd, fVerbose; + pNtk = Abc_FrameReadNtk(pAbc); + + // set defaults + nMultiSize = 3; + fAnd = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Kavh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nMultiSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMultiSize < 0 ) + goto usage; + break; + case 'a': + fAnd ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Can only collapse a logic network or an AIG.\n" ); + return 1; + } + // get the new network + pNtkRes = Abc_NtkShareXor( pNtk, nMultiSize, fAnd, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Cascade synthesis has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: extract [-K ] [-avh]\n" ); + Abc_Print( -2, "\t extracts shared logic from multi-input gates\n" ); + Abc_Print( -2, "\t-K : the minimum gate size to consider for extraction [default = %d]\n", nMultiSize ); + Abc_Print( -2, "\t-a : toggle multi-input XOR vs multi-input AND [default = %s]\n", fAnd? "AND": "XOR" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandVarMin( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_SuppTest( int nOnes, int nVars, int fUseSimple, int fCheck, int fVerbose ); + extern void Abc_SuppReadMinTest( char * pFileName ); + int nOnes = 4; + int nVars = 20; + int fUseSimple = 0; + int fCheck = 0; + int fVerbose = 0; + int c; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "MNocvh" ) ) != EOF ) + { + switch ( c ) + { + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + nOnes = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nOnes < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVars < 0 ) + goto usage; + break; + case 'o': + fUseSimple ^= 1; + break; + case 'c': + fCheck ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + // get the file name + if ( argc == globalUtilOptind + 1 ) + { + Abc_SuppReadMinTest( argv[globalUtilOptind] ); + return 0; + } + Abc_SuppTest( nOnes, nVars, fUseSimple, fCheck, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: varmin [-MN ] [-ocvh]\n" ); + Abc_Print( -2, "\t performs support minimization\n" ); + Abc_Print( -2, "\t-M : the number of ones in the combination [default = %d]\n", nOnes ); + Abc_Print( -2, "\t-N : the number of variables in the problem [default = %d]\n", nVars ); + Abc_Print( -2, "\t-o : toggle computing reduced difference matrix [default = %s]\n", fUseSimple? "yes": "no" ); + Abc_Print( -2, "\t-c : toggle verifying the final result [default = %s]\n", fCheck? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFaultClasses( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_NtkDetectClassesTest( Abc_Ntk_t * pNtk, int fSeq, int fVerbose, int fVeryVerbose ); + extern void Abc_NtkGenFaultList( Abc_Ntk_t * pNtk, char * pFileName, int fStuckAt ); + Abc_Ntk_t * pNtk; + int c, fGen = 0, fStuckAt = 0, fSeq = 0, fVerbose = 0, fVeryVerbose = 0; + pNtk = Abc_FrameReadNtk(pAbc); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "gcsvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'g': + fGen ^= 1; + break; + case 'c': + fStuckAt ^= 1; + break; + case 's': + fSeq ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Only applicable to a logic network.\n" ); + return 1; + } + if ( fGen ) + { + char * pFileName = Extra_FileNameGenericAppend(Abc_NtkSpec(pNtk), "_faults.txt"); + Abc_NtkGenFaultList( pNtk, pFileName, fStuckAt ); + } + else + Abc_NtkDetectClassesTest( pNtk, fSeq, fVerbose, fVeryVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: faultclasses [-gcsvwh]\n" ); + Abc_Print( -2, "\t computes equivalence classes of faults in the given mapped netlist;\n" ); + Abc_Print( -2, "\t the fault list with faults in the format: \n" ); + Abc_Print( -2, "\t should be read by command \"read_fins\" before calling this command\n" ); + Abc_Print( -2, "\t-g : toggle generating a fault list for the current mapped network [default = %s]\n", fGen? "yes": "no" ); + Abc_Print( -2, "\t-c : toggle using only stuck-at faults in the generated fault list [default = %s]\n", fStuckAt? "yes": "no" ); + Abc_Print( -2, "\t-s : toggle detecting sequential equivalence classes [default = %s]\n", fSeq? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout during computation [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle printing of resulting fault equivalence classes [default = %s]\n", fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandExact( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Gia_Man_t * Gia_ManFindExact( word * pTruth, int nVars, int nFunc, int nMaxDepth, int * pArrivalTimes, int nBTLimit, int nStartGates, int fVerbose ); + + int c, nMaxDepth = -1, fMakeAIG = 0, fTest = 0, fVerbose = 0, nVars = 0, nVarsTmp, nFunc = 0, nStartGates = 1, nBTLimit = 400000; + char * p1, * p2; + word pTruth[64]; + int pArrTimeProfile[8], fHasArrTimeProfile = 0; + Abc_Ntk_t * pNtkRes; + Gia_Man_t * pGiaRes; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "DASCatvh" ) ) != EOF ) + { + switch ( c ) + { + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + nMaxDepth = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMaxDepth < 0 ) + goto usage; + break; + case 'A': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-A\" should be followed by an integer.\n" ); + goto usage; + } + fHasArrTimeProfile = 1; + p1 = p2 = argv[globalUtilOptind++]; + while ( true ) { + if ( *p2 == ',' ) + { + *p2 = '\0'; + pArrTimeProfile[nVars++] = atoi( p1 ); + *p2++ = ','; + p1 = p2; + } + else if ( *p2 == '\0' ) + { + pArrTimeProfile[nVars++] = atoi( p1 ); + break; + } + else + ++p2; + } + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + nStartGates = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nStartGates < 1 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nBTLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'a': + fMakeAIG ^= 1; + break; + case 't': + fTest ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( fTest ) + { + extern void Abc_ExactTest( int fVerbose ); + extern void Abc_ExactStoreTest( int fVerbose ); + + printf( "run test suite, ignore all other settings\n" ); + Abc_ExactTest( fVerbose ); + Abc_ExactStoreTest( fVerbose ); + return 0; + } + + if ( argc == globalUtilOptind ) + goto usage; + + memset( pTruth, 0, 64 * sizeof(word) ); + while ( globalUtilOptind < argc ) + { + if ( nFunc == 16 ) + { + Abc_Print( -1, "Too many functions (at most 16 supported).\n" ); + goto usage; + } + nVarsTmp = Abc_TtReadHex( &pTruth[nFunc << 2], argv[globalUtilOptind++] ); + nFunc++; + if ( nVars == 0 ) + nVars = nVarsTmp; + else if ( nVars > 8 ) + { + Abc_Print( -1, "Only 8-variable functions are supported.\n" ); + goto usage; + } + else if ( nVars != nVarsTmp ) + { + Abc_Print( -1, "All functions need to have the same size.\n" ); + goto usage; + } + } + + if ( fMakeAIG ) + { + pGiaRes = Gia_ManFindExact( pTruth, nVars, nFunc, nMaxDepth, fHasArrTimeProfile ? pArrTimeProfile : NULL, nBTLimit, nStartGates - 1, fVerbose ); + if ( pGiaRes ) + Abc_FrameUpdateGia( pAbc, pGiaRes ); + else + Abc_Print( 0, "Could not find AIG within given resource constraints, retry with different value for -C.\n" ); + } + else + { + pNtkRes = Abc_NtkFindExact( pTruth, nVars, nFunc, nMaxDepth, fHasArrTimeProfile ? pArrTimeProfile : NULL, nBTLimit, nStartGates - 1, fVerbose ); + if ( pNtkRes ) + { + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + Abc_FrameClearVerifStatus( pAbc ); + } + else + Abc_Print( 0, "Could not find network within given resource constraints, retry with different value for -C.\n" ); + } + return 0; + +usage: + Abc_Print( -2, "usage: exact [-DSC ] [-A ] [-atvh] ...\n" ); + Abc_Print( -2, "\t finds optimum networks using SAT-based exact synthesis for hex truth tables ...\n" ); + Abc_Print( -2, "\t-D : constrain maximum depth (if too low, algorithm may not terminate)\n" ); + Abc_Print( -2, "\t-A : input arrival times (comma separated list)\n" ); + Abc_Print( -2, "\t-S : number of start gates in search [default = %d]\n", nStartGates ); + Abc_Print( -2, "\t-C : the limit on the number of conflicts; turn off with 0 [default = %d]\n", nBTLimit ); + Abc_Print( -2, "\t-a : toggle create AIG [default = %s]\n", fMakeAIG ? "yes" : "no" ); + Abc_Print( -2, "\t-t : run test suite\n" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose ? "yes" : "no" ); + Abc_Print( -2, "\t-h : print the command usage\n" ); + Abc_Print( -2, "\t\n" ); + Abc_Print( -2, "\t This command was contributed by Mathias Soeken from EPFL in July 2016.\n" ); + Abc_Print( -2, "\t The author can be contacted as mathias.soeken at epfl.ch\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandBmsStart( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int Abc_ExactIsRunning(); + extern void Abc_ExactStart( int nBTLimit, int fMakeAIG, int fVerbose, int fVeryVerbose, const char *pFilename ); + + int c, fMakeAIG = 0, fVerbose = 0, fVeryVerbose = 0, nBTLimit = 100; + char * pFilename = NULL; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Cavwh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nBTLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'a': + fMakeAIG ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc > globalUtilOptind ) + { + pFilename = argv[globalUtilOptind++]; + } + + if ( Abc_ExactIsRunning() ) + { + Abc_Print( -1, "BMS manager is already started." ); + return 1; + } + + Abc_ExactStart( nBTLimit, fMakeAIG, fVerbose, fVeryVerbose, pFilename ); + return 0; + +usage: + Abc_Print( -2, "usage: bms_start [-C ] [-avwh] []\n" ); + Abc_Print( -2, "\t starts BMS manager for recording optimum networks\n" ); + Abc_Print( -2, "\t if is specified, store entries are read from that file\n" ); + Abc_Print( -2, "\t-C : the limit on the number of conflicts [default = %d]\n", nBTLimit ); + Abc_Print( -2, "\t-a : toggle create AIG [default = %s]\n", fMakeAIG ? "yes" : "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose ? "yes" : "no" ); + Abc_Print( -2, "\t-w : toggle very verbose printout [default = %s]\n", fVeryVerbose ? "yes" : "no" ); + Abc_Print( -2, "\t-h : print the command usage\n" ); + Abc_Print( -2, "\t\n" ); + Abc_Print( -2, "\t This command was contributed by Mathias Soeken from EPFL in July 2016.\n" ); + Abc_Print( -2, "\t The author can be contacted as mathias.soeken at epfl.ch\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandBmsStop( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int Abc_ExactIsRunning(); + extern void Abc_ExactStop( const char *pFilename ); + + int c; + char * pFilename = NULL; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc > globalUtilOptind ) + { + pFilename = argv[globalUtilOptind++]; + } + + if ( !Abc_ExactIsRunning() ) + { + Abc_Print( -1, "BMS manager is not started." ); + return 1; + } + + Abc_ExactStop( pFilename ); + return 0; + +usage: + Abc_Print( -2, "usage: bms_stop [-C ] [-vh] []\n" ); + Abc_Print( -2, "\t stops BMS manager for recording optimum networks\n" ); + Abc_Print( -2, "\t if is specified, store entries are written to that file\n" ); + Abc_Print( -2, "\t-h : print the command usage\n" ); + Abc_Print( -2, "\t\n" ); + Abc_Print( -2, "\t This command was contributed by Mathias Soeken from EPFL in July 2016.\n" ); + Abc_Print( -2, "\t The author can be contacted as mathias.soeken at epfl.ch\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandBmsPs( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int Abc_ExactIsRunning(); + extern void Abc_ExactStats(); + + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( !Abc_ExactIsRunning() ) + { + Abc_Print( -1, "BMS manager is not started." ); + return 1; + } + + Abc_ExactStats(); + return 0; + +usage: + Abc_Print( -2, "usage: bms_ps [-h]\n" ); + Abc_Print( -2, "\t shows statistics about BMS manager\n" ); + Abc_Print( -2, "\t-h : print the command usage\n" ); + Abc_Print( -2, "\t\n" ); + Abc_Print( -2, "\t This command was contributed by Mathias Soeken from EPFL in July 2016.\n" ); + Abc_Print( -2, "\t The author can be contacted as mathias.soeken at epfl.ch\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMajExact( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int Maj_ManExactSynthesis( int nVars, int nNodes, int fUseConst, int fUseLine, int fVerbose ); + extern int Maj_ManExactSynthesis2( int nVars, int nNodes, int fUseConst, int fUseLine, int fUseRand, int nRands, int fVerbose ); + int c, nVars = 3, nNodes = 1, fUseConst = 0, fUseLine = 0, fGlucose = 0, fUseRand = 0, nRands = 0, fVerbose = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "INRfcrgvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVars < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nNodes = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nNodes < 0 ) + goto usage; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + nRands = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nRands < 0 ) + goto usage; + break; + case 'f': + fUseConst ^= 1; + break; + case 'c': + fUseLine ^= 1; + break; + case 'r': + fUseRand ^= 1; + break; + case 'g': + fGlucose ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( (nVars & 1) == 0 ) + { + Abc_Print( -1, "Cannot sythesize MAJ gate with an even number of inputs (%d).\n", nVars ); + return 1; + } + if ( fGlucose ) + Maj_ManExactSynthesis( nVars, nNodes, fUseConst, fUseLine, fVerbose ); + else + Maj_ManExactSynthesis2( nVars, nNodes, fUseConst, fUseLine, fUseRand, nRands, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: majexact [-INR ] [-fcrgvh]\n" ); + Abc_Print( -2, "\t exact synthesis of multi-input MAJ using MAJ3 gates\n" ); + Abc_Print( -2, "\t-I : the number of input variables [default = %d]\n", nVars ); + Abc_Print( -2, "\t-N : the number of MAJ3 nodes [default = %d]\n", nNodes ); + Abc_Print( -2, "\t-R : the number of additional connections [default = %d]\n", nRands ); + Abc_Print( -2, "\t-f : toggle using constant fanins [default = %s]\n", fUseConst ? "yes" : "no" ); + Abc_Print( -2, "\t-c : toggle using cascade topology [default = %s]\n", fUseLine ? "yes" : "no" ); + Abc_Print( -2, "\t-r : toggle using random topology [default = %s]\n", fUseRand ? "yes" : "no" ); + Abc_Print( -2, "\t-g : toggle using Glucose 3.0 by Gilles Audemard and Laurent Simon [default = %s]\n", fGlucose ? "yes" : "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose ? "yes" : "no" ); + Abc_Print( -2, "\t-h : print the command usage\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTwoExact( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Exa_ManExactSynthesis( Bmc_EsPar_t * pPars ); + extern void Exa_ManExactSynthesis2( Bmc_EsPar_t * pPars ); + extern void Exa_ManExactSynthesis4( Bmc_EsPar_t * pPars ); + extern void Exa_ManExactSynthesis5( Bmc_EsPar_t * pPars ); + extern void Exa_ManExactSynthesis6( Bmc_EsPar_t * pPars, char * pFileName ); + extern void Exa_ManExactSynthesis7( Bmc_EsPar_t * pPars, int GateSize ); + int c, fKissat = 0, fKissat2 = 0, fUseNands = 0, GateSize = 0; + Bmc_EsPar_t Pars, * pPars = &Pars; + Bmc_EsParSetDefault( pPars ); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "INTGSabdconugklmvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nVars < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nNodes = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nNodes < 0 ) + goto usage; + break; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + pPars->RuntimeLim = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->RuntimeLim < 0 ) + goto usage; + break; + case 'G': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-G\" should be followed by an integer.\n" ); + goto usage; + } + GateSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( GateSize < 0 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by a file name.\n" ); + goto usage; + } + pPars->pGuide = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'a': + pPars->fOnlyAnd ^= 1; + break; + case 'b': + fUseNands ^= 1; + break; + case 'd': + pPars->fDynConstr ^= 1; + break; + case 'c': + pPars->fDumpCnf ^= 1; + break; + case 'o': + pPars->fFewerVars ^= 1; + break; + case 'n': + pPars->fOrderNodes ^= 1; + break; + case 'u': + pPars->fUniqFans ^= 1; + break; + case 'g': + pPars->fGlucose ^= 1; + break; + case 'k': + fKissat ^= 1; + break; + case 'l': + fKissat2 ^= 1; + break; + case 'm': + pPars->fCard ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc == globalUtilOptind + 1 ) + { + if ( strstr(argv[globalUtilOptind], ".") ) + { + Exa_ManExactSynthesis6( pPars, argv[globalUtilOptind] ); + return 0; + } + pPars->pTtStr = argv[globalUtilOptind]; + } + if ( pPars->pTtStr == NULL ) + { + Abc_Print( -1, "Truth table should be given on the command line.\n" ); + return 1; + } + if ( pPars->nVars >= 2 && (1 << (pPars->nVars-2)) != (int)strlen(pPars->pTtStr) ) + { + Abc_Print( -1, "Truth table is expected to have %d hex digits (instead of %d).\n", (1 << (pPars->nVars-2)), strlen(pPars->pTtStr) ); + return 1; + } + if ( pPars->nVars > pPars->nNodes * (2 - 1) + 1 ) + { + Abc_Print( -1, "Function with %d variales cannot be implemented with %d two-input gates.\n", pPars->nVars, pPars->nNodes ); + return 1; + } + if ( pPars->nVars > 10 ) + { + Abc_Print( -1, "Function should not have more than 10 inputs.\n" ); + return 1; + } + if ( fUseNands ) + Exa_ManExactSynthesis7( pPars, GateSize ); + else if ( fKissat || pPars->fCard ) + Exa_ManExactSynthesis4( pPars ); + else if ( fKissat2 ) + Exa_ManExactSynthesis5( pPars ); + else if ( pPars->fGlucose ) + Exa_ManExactSynthesis( pPars ); + else + Exa_ManExactSynthesis2( pPars ); + return 0; + +usage: + Abc_Print( -2, "usage: twoexact [-INTG ] [-S str] [-abdconugklmvh] \n" ); + Abc_Print( -2, "\t exact synthesis of multi-input function using two-input gates\n" ); + Abc_Print( -2, "\t-I : the number of input variables [default = %d]\n", pPars->nVars ); + Abc_Print( -2, "\t-N : the number of two-input nodes [default = %d]\n", pPars->nNodes ); + Abc_Print( -2, "\t-T : the runtime limit in seconds [default = %d]\n", pPars->RuntimeLim ); + Abc_Print( -2, "\t-G : the largest allowed gate size (NANDs only) [default = %d]\n", GateSize ); + Abc_Print( -2, "\t-S : structural guidance from the user [default = %s]\n", pPars->pGuide ? pPars->pGuide : "unknown" ); + Abc_Print( -2, "\t-a : toggle using only AND-gates (without XOR-gates) [default = %s]\n", pPars->fOnlyAnd ? "yes" : "no" ); + Abc_Print( -2, "\t-b : toggle using only NAND-gates [default = %s]\n", fUseNands ? "yes" : "no" ); + Abc_Print( -2, "\t-d : toggle using dynamic constraint addition [default = %s]\n", pPars->fDynConstr ? "yes" : "no" ); + Abc_Print( -2, "\t-c : toggle dumping CNF into a file [default = %s]\n", pPars->fDumpCnf ? "yes" : "no" ); + Abc_Print( -2, "\t-o : toggle using additional optimizations [default = %s]\n", pPars->fFewerVars ? "yes" : "no" ); + Abc_Print( -2, "\t-n : toggle ordering internal nodes [default = %s]\n", pPars->fOrderNodes ? "yes" : "no" ); + Abc_Print( -2, "\t-u : toggle using unique fanouts [default = %s]\n", pPars->fUniqFans ? "yes" : "no" ); + Abc_Print( -2, "\t-g : toggle using Glucose 3.0 by Gilles Audemard and Laurent Simon [default = %s]\n", pPars->fGlucose ? "yes" : "no" ); + Abc_Print( -2, "\t-k : toggle using Kissat by Armin Biere [default = %s]\n", fKissat ? "yes" : "no" ); + Abc_Print( -2, "\t-l : toggle using Kissat by Armin Biere [default = %s]\n", fKissat2 ? "yes" : "no" ); + Abc_Print( -2, "\t-m : toggle using CaDiCaL by Armin Biere [default = %s]\n", pPars->fCard ? "yes" : "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose ? "yes" : "no" ); + Abc_Print( -2, "\t-h : print the command usage\n" ); + Abc_Print( -2, "\t : truth table in hex notation\n" ); + Abc_Print( -2, "\t \n" ); + Abc_Print( -2, "\t For example, command line \"twoexact -g -I 5 -N 12 169AE443\"\n" ); + Abc_Print( -2, "\t synthesizes the smallest circuit composed of two-input gates\n" ); + Abc_Print( -2, "\t for the only NPN class of 5-input functions that requires 12 gates;\n" ); + Abc_Print( -2, "\t all other functions can be realized with 11 two-input gates or less\n" ); + Abc_Print( -2, "\t (see Section 7.1.2 \"Boolean evaluation\" in the book The Art of Computer Programming by Donald Knuth)\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandLutExact( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int Exa3_ManExactSynthesis( Bmc_EsPar_t * pPars ); + extern void Exa3_ManExactSynthesis2( Bmc_EsPar_t * pPars ); + extern void Exa3_ManExactSynthesisRand( Bmc_EsPar_t * pPars ); + int c; + Bmc_EsPar_t Pars, * pPars = &Pars; + Bmc_EsParSetDefault( pPars ); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "INKTSFMiaocgvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nVars < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nNodes = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nNodes < 0 ) + goto usage; + break; + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nLutSize < 0 ) + goto usage; + break; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + pPars->RuntimeLim = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->RuntimeLim < 0 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + pPars->pSymStr = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nRandFuncs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nMintNum = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'i': + pPars->fUseIncr ^= 1; + break; + case 'a': + pPars->fOnlyAnd ^= 1; + break; + case 'o': + pPars->fFewerVars ^= 1; + break; + case 'c': + pPars->fLutCascade ^= 1; + break; + case 'g': + pPars->fGlucose ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc == globalUtilOptind + 1 ) + pPars->pTtStr = argv[globalUtilOptind]; + if ( pPars->pTtStr == NULL && pPars->pSymStr == NULL && pPars->nRandFuncs == 0 ) + { + Abc_Print( -1, "Truth table should be given on the command line.\n" ); + return 1; + } + if ( pPars->pTtStr && (1 << (pPars->nVars-2)) != (int)strlen(pPars->pTtStr) ) + { + Abc_Print( -1, "Truth table is expected to have %d hex digits (instead of %d).\n", (1 << (pPars->nVars-2)), strlen(pPars->pTtStr) ); + return 1; + } + if ( pPars->pSymStr && pPars->nVars+1 != strlen(pPars->pSymStr) ) + { + Abc_Print( -1, "The char string of the %d-variable symmetric function should have %d zeros and ones (instead of %d).\n", pPars->nVars, pPars->nVars+1, strlen(pPars->pSymStr) ); + return 1; + } + if ( pPars->nVars > pPars->nNodes * (pPars->nLutSize - 1) + 1 ) + { + Abc_Print( -1, "Function with %d variales cannot be implemented with %d %d-input LUTs.\n", pPars->nVars, pPars->nNodes, pPars->nLutSize ); + return 1; + } + if ( pPars->nVars > 10 ) + { + Abc_Print( -1, "Function should not have more than 10 inputs.\n" ); + return 1; + } + if ( pPars->nLutSize > 6 ) + { + Abc_Print( -1, "Node size should not be more than 6 inputs.\n" ); + return 1; + } + if ( pPars->nRandFuncs ) { + pPars->fGlucose = 1; + Exa3_ManExactSynthesisRand( pPars ); + } + else if ( pPars->fGlucose ) + Exa3_ManExactSynthesis( pPars ); + else + Exa3_ManExactSynthesis2( pPars ); + return 0; + +usage: + Abc_Print( -2, "usage: lutexact [-INKTFM ] [-S string] [-iaocgvh] \n" ); + Abc_Print( -2, "\t exact synthesis of I-input function using N K-input gates\n" ); + Abc_Print( -2, "\t-I : the number of input variables [default = %d]\n", pPars->nVars ); + Abc_Print( -2, "\t-N : the number of K-input nodes [default = %d]\n", pPars->nNodes ); + Abc_Print( -2, "\t-K : the number of node fanins [default = %d]\n", pPars->nLutSize ); + Abc_Print( -2, "\t-T : the runtime limit in seconds [default = %d]\n", pPars->RuntimeLim ); + Abc_Print( -2, "\t-F : the number of random functions to try [default = unused]\n" ); + Abc_Print( -2, "\t-M : the number of positive minterms in the random function [default = unused]\n" ); + Abc_Print( -2, "\t-S : charasteristic string of a symmetric function [default = %d]\n", pPars->pSymStr ); + Abc_Print( -2, "\t-i : toggle using incremental solving [default = %s]\n", pPars->fUseIncr ? "yes" : "no" ); + Abc_Print( -2, "\t-a : toggle using only AND-gates when K = 2 [default = %s]\n", pPars->fOnlyAnd ? "yes" : "no" ); + Abc_Print( -2, "\t-o : toggle using additional optimizations [default = %s]\n", pPars->fFewerVars ? "yes" : "no" ); + Abc_Print( -2, "\t-c : toggle synthesizing a single-rail cascade [default = %s]\n", pPars->fLutCascade ? "yes" : "no" ); + Abc_Print( -2, "\t-g : toggle using Glucose 3.0 by Gilles Audemard and Laurent Simon [default = %s]\n", pPars->fGlucose ? "yes" : "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose ? "yes" : "no" ); + Abc_Print( -2, "\t-h : print the command usage\n" ); + Abc_Print( -2, "\t : truth table in hex notation\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAllExact( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Zyx_ManExactSynthesis( Bmc_EsPar_t * pPars ); + int c; + Bmc_EsPar_t Pars, * pPars = &Pars; + Bmc_EsParSetDefault( pPars ); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "MINKianegvh" ) ) != EOF ) + { + switch ( c ) + { + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nMajSupp = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nMajSupp < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nVars < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nNodes = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nNodes < 0 ) + goto usage; + break; + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nLutSize < 0 ) + goto usage; + break; + case 'i': + pPars->fUseIncr ^= 1; + break; + case 'a': + pPars->fOnlyAnd ^= 1; + break; + case 'n': + pPars->fOrderNodes ^= 1; + break; + case 'e': + pPars->fEnumSols ^= 1; + break; + case 'g': + pPars->fGlucose ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pPars->nMajSupp > 0 ) + { + if ( pPars->nMajSupp != 5 && pPars->nMajSupp != 7 && pPars->nMajSupp != 9 ) + { + Abc_Print( -1, "Currently only support majority with 5, 7 or 9 inputs.\n" ); + return 1; + } + pPars->nVars = pPars->nMajSupp; + pPars->nLutSize = 3; + pPars->fMajority = 1; + pPars->fUseIncr = 1; + if ( pPars->nNodes == 0 ) + { + if ( pPars->nMajSupp == 5 ) + pPars->nNodes = 4; + if ( pPars->nMajSupp == 7 ) + pPars->nNodes = 7; + if ( pPars->nMajSupp == 9 ) + pPars->nNodes = 10; + } + } + else + { + if ( pPars->nVars == 0 ) + { + Abc_Print( -1, "The number of variables (-I num) needs to be specified on the command line.\n" ); + return 1; + } + if ( pPars->nNodes == 0 ) + { + Abc_Print( -1, "The number of nodes (-N num) needs to be specified on the command line.\n" ); + return 1; + } + if ( argc == globalUtilOptind + 1 ) + pPars->pTtStr = argv[globalUtilOptind]; + if ( pPars->pTtStr == NULL ) + { + Abc_Print( -1, "Truth table should be given on the command line.\n" ); + return 1; + } + if ( (1 << (pPars->nVars-2)) != (int)strlen(pPars->pTtStr) ) + { + Abc_Print( -1, "Truth table is expected to have %d hex digits (instead of %d).\n", (1 << (pPars->nVars-2)), strlen(pPars->pTtStr) ); + return 1; + } + } + if ( pPars->nVars > pPars->nNodes * (pPars->nLutSize - 1) + 1 ) + { + Abc_Print( -1, "Function with %d variales cannot be implemented with %d %d-input LUTs.\n", pPars->nVars, pPars->nNodes, pPars->nLutSize ); + return 1; + } + if ( pPars->nVars > 10 ) + { + Abc_Print( -1, "Function should not have more than 10 inputs.\n" ); + return 1; + } + if ( pPars->nLutSize > 6 ) + { + Abc_Print( -1, "Node size should not be more than 6 inputs.\n" ); + return 1; + } + if ( !pPars->fUseIncr ) + { + if ( pPars->fMajority ) + { + Abc_Print( -1, "Cannot synthesize majority in the non-incremental mode (use \'-i\').\n" ); + return 1; + } + if ( pPars->nLutSize > 3 ) + { + Abc_Print( -1, "Cannot synthesize LUT4 and larger in non-incremental mode (use \'-i\').\n" ); + return 1; + } + } + Zyx_ManExactSynthesis( pPars ); + return 0; + +usage: + Abc_Print( -2, "usage: allexact [-MIKN ] [-ianevh] \n" ); + Abc_Print( -2, "\t exact synthesis of I-input function using N K-input gates\n" ); + Abc_Print( -2, "\t-M : the majority support size (overrides -I and -K) [default = %d]\n", pPars->nMajSupp ); + Abc_Print( -2, "\t-I : the number of input variables [default = %d]\n", pPars->nVars ); + Abc_Print( -2, "\t-K : the number of node fanins [default = %d]\n", pPars->nLutSize ); + Abc_Print( -2, "\t-N : the number of K-input nodes [default = %d]\n", pPars->nNodes ); + Abc_Print( -2, "\t-i : toggle using incremental solving [default = %s]\n", pPars->fUseIncr ? "yes" : "no" ); + Abc_Print( -2, "\t-a : toggle using only AND-gates when K = 2 [default = %s]\n", pPars->fOnlyAnd ? "yes" : "no" ); + Abc_Print( -2, "\t-n : toggle using node ordering by fanins [default = %s]\n", pPars->fOrderNodes ? "yes" : "no" ); + Abc_Print( -2, "\t-e : toggle enumerating all solutions [default = %s]\n", pPars->fEnumSols ? "yes" : "no" ); +// Abc_Print( -2, "\t-g : toggle using Glucose 3.0 by Gilles Audemard and Laurent Simon [default = %s]\n", pPars->fGlucose ? "yes" : "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose ? "yes" : "no" ); + Abc_Print( -2, "\t-h : print the command usage\n" ); + Abc_Print( -2, "\t : truth table in hex notation\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTestExact( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Zyx_TestExact( char * pFileName ); + char * pFileName = NULL; + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc == globalUtilOptind + 1 ) + pFileName = argv[globalUtilOptind]; + if ( pFileName == NULL ) + { + Abc_Print( -1, "File name is not given on the command line.\n" ); + return 1; + } + Zyx_TestExact( pFileName ); + return 0; + +usage: + Abc_Print( -2, "usage: testexact \n" ); + Abc_Print( -2, "\t tests solution of the exact synthesis problem\n" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose ? "yes" : "no" ); + Abc_Print( -2, "\t-h : print the command usage\n" ); + Abc_Print( -2, "\t : file name in the specified format\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMajGen( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int Gem_Enumerate( int nVars, int fDump, int fVerbose ); + int c, nVars = 8, fDump = 0, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Ndvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVars < 0 ) + goto usage; + break; + case 'd': + fDump ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + Gem_Enumerate( nVars, fDump, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: majgen [-N ] [-dvh]>\n" ); + Abc_Print( -2, "\t generates networks for majority gates\n" ); + Abc_Print( -2, "\t-N : the maximum number of variables [default = %d]\n", nVars ); + Abc_Print( -2, "\t-d : toggle dumping functions into a file [default = %s]\n", fVerbose ? "yes" : "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose ? "yes" : "no" ); + Abc_Print( -2, "\t-h : print the command usage\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandLogic( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash( pNtk ) ) + { + Abc_Print( -1, "This command is only applicable to strashed networks.\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkToLogic( pNtk ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Converting to a logic network has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: logic [-h]\n" ); + Abc_Print( -2, "\t transforms an AIG into a logic network with SOPs\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandComb( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int fRemoveLatches; + int nLatchesToAdd; + extern void Abc_NtkMakeSeq( Abc_Ntk_t * pNtk, int nLatchesToAdd ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + fRemoveLatches = 0; + nLatchesToAdd = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Llh" ) ) != EOF ) + { + switch ( c ) + { + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + nLatchesToAdd = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLatchesToAdd < 0 ) + goto usage; + break; + case 'l': + fRemoveLatches ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkIsComb(pNtk) && nLatchesToAdd == 0 ) + { + Abc_Print( -1, "The network is already combinational.\n" ); + return 0; + } + if ( !Abc_NtkIsComb(pNtk) && nLatchesToAdd != 0 ) + { + Abc_Print( -1, "The network is already combinational.\n" ); + return 0; + } + + // get the new network + pNtkRes = Abc_NtkDup( pNtk ); + if ( nLatchesToAdd ) + Abc_NtkMakeSeq( pNtkRes, nLatchesToAdd ); + else + Abc_NtkMakeComb( pNtkRes, fRemoveLatches ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: comb [-L ] [-lh]\n" ); + Abc_Print( -2, "\t converts comb network into seq, and vice versa\n" ); + Abc_Print( -2, "\t-L : number of latches to add to comb network (0 = do not add) [default = %d]\n", nLatchesToAdd ); + Abc_Print( -2, "\t-l : toggle converting latches to PIs/POs or removing them [default = %s]\n", fRemoveLatches? "remove": "convert" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMiter( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + char Buffer[32]; + Abc_Ntk_t * pNtk, * pNtk1, * pNtk2, * pNtkRes; + int fDelete1, fDelete2; + char ** pArgvNew; + int nArgcNew; + int c; + int fCheck; + int fComb; + int fImplic; + int fMulti; + int nPartSize; + int fTrans; + int fIgnoreNames; + + pNtk = Abc_FrameReadNtk(pAbc); + + // set defaults + fComb = 0; + fCheck = 1; + fImplic = 0; + fMulti = 0; + nPartSize = 0; + fTrans = 0; + fIgnoreNames = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Pcmitnh" ) ) != EOF ) + { + switch ( c ) + { + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + nPartSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nPartSize < 0 ) + goto usage; + break; + case 'c': + fComb ^= 1; + break; + case 'm': + fMulti ^= 1; + break; + case 'i': + fImplic ^= 1; + break; + case 't': + fTrans ^= 1; + break; + case 'n': + fIgnoreNames ^= 1; + break; + default: + goto usage; + } + } + + if ( fTrans ) + { + if ( (Abc_NtkPoNum(pNtk) & 1) == 1 ) + { + Abc_Print( -1, "Abc_CommandMiter(): The number of outputs should be even.\n" ); + return 0; + } + // replace the current network + pNtkRes = Abc_NtkDupTransformMiter( pNtk ); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + Abc_Print( 1, "The miter (current network) is transformed by XORing POs pair-wise.\n" ); + return 0; + } + + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( !Abc_NtkPrepareTwoNtks( stdout, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2, 1 ) ) + return 1; + + if ( fIgnoreNames ) + { + if ( !fDelete1 ) + { + pNtk1 = Abc_NtkStrash( pNtk1, 0, 1, 0 ); + fDelete1 = 1; + } + if ( !fDelete2 ) + { + pNtk2 = Abc_NtkStrash( pNtk2, 0, 1, 0 ); + fDelete2 = 1; + } + Abc_NtkShortNames( pNtk1 ); + Abc_NtkShortNames( pNtk2 ); + } + // compute the miter + pNtkRes = Abc_NtkMiter( pNtk1, pNtk2, fComb, nPartSize, fImplic, fMulti ); + if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); + if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); + + // get the new network + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Miter computation has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + if ( nPartSize == 0 ) + strcpy( Buffer, "unused" ); + else + sprintf(Buffer, "%d", nPartSize ); + Abc_Print( -2, "usage: miter [-P ] [-cimtnh] \n" ); + Abc_Print( -2, "\t computes the miter of the two circuits\n" ); + Abc_Print( -2, "\t-P : output partition size [default = %s]\n", Buffer ); + Abc_Print( -2, "\t-c : toggles deriving combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" ); + Abc_Print( -2, "\t-i : toggles deriving implication miter (file1 => file2) [default = %s]\n", fImplic? "yes": "no" ); + Abc_Print( -2, "\t-m : toggles creating multi-output miter [default = %s]\n", fMulti? "yes": "no" ); + Abc_Print( -2, "\t-t : toggle XORing pair-wise POs of the miter [default = %s]\n", fTrans? "yes": "no" ); + Abc_Print( -2, "\t-n : toggle ignoring names when matching CIs/COs [default = %s]\n", fIgnoreNames? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\tfile1 : (optional) the file with the first network\n"); + Abc_Print( -2, "\tfile2 : (optional) the file with the second network\n"); + Abc_Print( -2, "\t if no files are given, uses the current network and its spec\n"); + Abc_Print( -2, "\t if one file is given, uses the current network and the file\n\n"); + Abc_Print( -2, "\t Please note that, when used without \"-n\", this command tries to match\n" ); + Abc_Print( -2, "\t primary inputs by name and, to achieve this, it will order them alphabetically,\n" ); + Abc_Print( -2, "\t which results in incorrect QBF miters and confusing counter-examples.\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMiter2( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Vec_Ptr_t * Abc_NtkReadNodeNames( Abc_Ntk_t * pNtk, char * pFileName ); + extern Abc_Ntk_t * Abc_NtkSpecialMiter( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes ); + + Abc_Ntk_t * pNtk, * pNtkRes; + Vec_Ptr_t * vNodes; + char * pFileName; + int c, fVerbose = 0; + pNtk = Abc_FrameReadNtk(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + // get the second network + if ( argc != globalUtilOptind + 1 ) + { + Abc_Print( -1, "The file with node names is not given.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "The base network should be logic network from BLIF file.\n" ); + return 1; + } + // read the second network + pFileName = argv[globalUtilOptind]; + if ( (vNodes = Abc_NtkReadNodeNames(pNtk, pFileName)) == NULL ) + { + Abc_Print( -1, "Cannot read node names from file \"%s\".\n", pFileName ); + return 1; + } + pNtkRes = Abc_NtkSpecialMiter( pNtk, vNodes ); + Vec_PtrFree( vNodes ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: miter2 [-h] \n" ); + Abc_Print( -2, "\t derives specialized miter\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : file name with node names\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDemiter( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c, fDual, fVerbose; + extern int Abc_NtkDarDemiter( Abc_Ntk_t * pNtk ); + extern int Abc_NtkDarDemiterDual( Abc_Ntk_t * pNtk, int fVerbose ); + // set defaults + fDual = 0; + fVerbose = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dvh" ) ) != EOF ) + { + switch ( c ) + { + case 'd': + fDual ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "The network is not strashed.\n" ); + return 1; + } + + if ( fDual ) + { + if ( (Abc_NtkPoNum(pNtk) & 1) ) + { + Abc_Print( -1, "The number of POs should be even.\n" ); + return 0; + } + if ( !Abc_NtkDarDemiterDual( pNtk, fVerbose ) ) + { + Abc_Print( -1, "Demitering has failed.\n" ); + return 1; + } + return 0; + } +/* + if ( Abc_NtkPoNum(pNtk) != 1 ) + { + Abc_Print( -1, "The network is not a single-output miter.\n" ); + return 1; + } + if ( !Abc_NodeIsExorType(Abc_ObjFanin0(Abc_NtkPo(pNtk,0))) ) + { + Abc_Print( -1, "The miter's PO is not an EXOR.\n" ); + return 1; + } + if ( !Abc_NtkDemiter( pNtk ) ) + { + Abc_Print( -1, "Demitering has failed.\n" ); + return 1; + } +*/ + // get the new network + if ( !Abc_NtkDarDemiter( pNtk ) ) + { + Abc_Print( -1, "Demitering has failed.\n" ); + return 1; + } + // replace the current network +// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: demiter [-dvh]\n" ); + Abc_Print( -2, "\t splits sequential miter into two circuits\n" ); + Abc_Print( -2, "\t-d : expects a dual-output miter (without XORs) [default = %s]\n", fDual? "yes": "no" ); + Abc_Print( -2, "\t-v : toggles outputting verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandOrPos( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);//, * pNtkRes; + int fReverse = 0; + int fComb = 0; + int fXor = 0; + int c; + extern int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd, int fXor ); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "rxh" ) ) != EOF ) + { + switch ( c ) + { + case 'r': + fReverse ^= 1; + break; + case 'x': + fXor ^= 1; + break; + case 'c': + fComb ^= 1; + break; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "The network is not strashed.\n" ); + return 1; + } + // get the new network + if ( fReverse ) + { + extern Aig_Man_t * Abc_NtkToDarBmc( Abc_Ntk_t * pNtk, Vec_Int_t ** pvMap ); + Aig_Man_t * pMan = Abc_NtkToDarBmc( pNtk, NULL ); + Abc_Ntk_t * pNtkRes = Abc_NtkFromAigPhase( pMan ); + Aig_ManStop( pMan ); + // perform expansion + if ( Abc_NtkPoNum(pNtk) != Abc_NtkPoNum(pNtkRes) ) + Abc_Print( 1,"Expanded %d outputs into %d outputs using OR decomposition.\n", Abc_NtkPoNum(pNtk), Abc_NtkPoNum(pNtkRes) ); + else + Abc_Print( 1,"The output(s) cannot be structurally decomposed.\n" ); + // clear counter-example + if ( pAbc->pCex ) + ABC_FREE( pAbc->pCex ); + // replace the current network + ABC_FREE( pNtkRes->pName ); + pNtkRes->pName = Extra_UtilStrsav(pNtk->pName); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + } + else + { + if ( !Abc_NtkCombinePos( pNtk, 0, fXor ) ) + { + Abc_Print( -1, "ORing the POs has failed.\n" ); + return 1; + } + // update counter-example + if ( pAbc->pCex ) + pAbc->pCex->iPo = 0; + // replace the current network + // Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + } + return 0; + +usage: + Abc_Print( -2, "usage: orpos [-rxh]\n" ); + Abc_Print( -2, "\t creates single-output miter by ORing the POs of the current network\n" ); + Abc_Print( -2, "\t-r : performs the reverse transform (OR decomposition) [default = %s]\n", fReverse? "yes": "no" ); + Abc_Print( -2, "\t-x : toggles combining the PO using XOR [default = %s]\n", fXor? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAndPos( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);//, * pNtkRes; + int fComb = 0; + int c; + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fComb ^= 1; + break; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "The network is not strashed.\n" ); + return 1; + } + + if ( Abc_NtkPoNum(pNtk) == 1 ) + { + Abc_Print( -1, "The network already has one PO.\n" ); + return 1; + } + + if ( Abc_NtkLatchNum(pNtk) ) + { + Abc_Print( -1, "The miter has latches. ORing is not performed.\n" ); + return 1; + } + + // get the new network + if ( !Abc_NtkCombinePos( pNtk, 1, 0 ) ) + { + Abc_Print( -1, "ANDing the POs has failed.\n" ); + return 1; + } + // replace the current network +// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: andpos [-h]\n" ); + Abc_Print( -2, "\t creates single-output miter by ANDing the POs of the current network\n" ); +// Abc_Print( -2, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandZeroPo( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);//, * pNtkRes = NULL; + int c, iOutput = -1; + int fSkipSweep = 0; + int fUseConst1 = 0; + extern void Abc_NtkDropOneOutput( Abc_Ntk_t * pNtk, int iOutput, int fSkipSweep, int fUseConst1 ); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nsoh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + iOutput = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( iOutput < 0 ) + goto usage; + break; + case 's': + fSkipSweep ^= 1; + break; + case 'o': + fUseConst1 ^= 1; + break; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "The network is not strashed.\n" ); + return 1; + } + if ( iOutput < 0 ) + { + Abc_Print( -1, "The output index is not specified.\n" ); + return 1; + } + if ( iOutput >= Abc_NtkPoNum(pNtk) ) + { + Abc_Print( -1, "The output index is larger than the allowed POs.\n" ); + return 1; + } + + // get the new network +// pNtkRes = Abc_NtkDup( pNtk ); +// Abc_NtkDropOneOutput( pNtkRes, iOutput ); +// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + Abc_NtkDropOneOutput( pNtk, iOutput, fSkipSweep, fUseConst1 ); + return 0; + +usage: + Abc_Print( -2, "usage: zeropo [-N ] [-soh]\n" ); + Abc_Print( -2, "\t replaces the PO driver by constant 0\n" ); + Abc_Print( -2, "\t-N : the zero-based index of the PO to replace [default = %d]\n", iOutput ); + Abc_Print( -2, "\t-s : performs comb sweep after removimg a PO [default = %s]\n", !fSkipSweep? "yes": "no" ); + Abc_Print( -2, "\t-o : toggles using const 1 instead of const 0 [default = %s]\n", fUseConst1? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSwapPos( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes; + int c, iOutput = -1; + extern void Abc_NtkSwapOneOutput( Abc_Ntk_t * pNtk, int iOutput ); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + iOutput = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( iOutput < 0 ) + goto usage; + break; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "The network is not strashed.\n" ); + return 1; + } + if ( iOutput < 0 ) + { + Abc_Print( -1, "The output index is not specified.\n" ); + return 1; + } + if ( iOutput >= Abc_NtkPoNum(pNtk) ) + { + Abc_Print( -1, "The output index is larger than the allowed POs.\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkDup( pNtk ); + Abc_NtkSwapOneOutput( pNtkRes, iOutput ); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: swappos [-N ] [-h]\n" ); + Abc_Print( -2, "\t swap the 0-th PO with the -th PO\n" ); + Abc_Print( -2, "\t-N : the zero-based index of the PO to swap [default = %d]\n", iOutput ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRemovePo( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc);//, * pNtkRes = NULL; + int c, iOutput = -1; + int fRemoveConst0 = 1; + extern void Abc_NtkRemovePo( Abc_Ntk_t * pNtk, int iOutput, int fRemoveConst0 ); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nzh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + iOutput = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( iOutput < 0 ) + goto usage; + break; + case 'z': + fRemoveConst0 ^= 1; + break; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "The network is not strashed.\n" ); + return 1; + } + if ( iOutput < 0 ) + { + Abc_Print( -1, "The output index is not specified.\n" ); + return 1; + } + if ( iOutput >= Abc_NtkPoNum(pNtk) ) + { + Abc_Print( -1, "The output index is larger than the allowed POs.\n" ); + return 1; + } + + // get the new network +// pNtkRes = Abc_NtkDup( pNtk ); +// Abc_NtkRemovePo( pNtkRes, iOutput ); +// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + Abc_NtkRemovePo( pNtk, iOutput, fRemoveConst0 ); + return 0; + +usage: + Abc_Print( -2, "usage: removepo [-N ] [-zh]\n" ); + Abc_Print( -2, "\t remove PO with number if it is const0\n" ); + Abc_Print( -2, "\t-N : the zero-based index of the PO to remove [default = %d]\n", iOutput ); + Abc_Print( -2, "\t-z : toggle removing const1 instead of const0 [default = %s]\n", fRemoveConst0? "const0": "const1" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDropSat( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_NtkDropSatOutputs( Abc_Ntk_t * pNtk, Vec_Ptr_t * vCexes, int fVerbose ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtkRes = NULL; + int fNoSweep = 0; + int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF ) + { + switch ( c ) + { + case 's': + fNoSweep ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for AIGs (run \"strash\").\n" ); + return 1; + } + if ( pAbc->vCexVec == NULL ) + { + Abc_Print( -1, "CEX array is not defined. Run \"bmc3 -az\", \"sim3 -az\", or \"pdr -az\".\n" ); + return 1; + } + if ( Vec_PtrSize(pAbc->vCexVec) != Abc_NtkPoNum(pNtk) ) + { + Abc_Print( -1, "CEX array size (%d) does not match the number of outputs (%d).\n", Vec_PtrSize(pAbc->vCexVec), Abc_NtkPoNum(pNtk) ); + return 1; + } + Abc_NtkDropSatOutputs( pNtk, pAbc->vCexVec, fVerbose ); + if ( !fNoSweep ) + { + pNtkRes = Abc_NtkDarLatchSweep( pNtk, 1, 1, 1, 0, -1, -1, 0, 0 ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Removing SAT outputs has failed.\n" ); + return 1; + } + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + } + return 0; + +usage: + Abc_Print( -2, "usage: dropsat [-sh]\n" ); + Abc_Print( -2, "\t replaces satisfiable POs by constant 0 and cleans up the AIG\n" ); + Abc_Print( -2, "\t-s : toggles skipping sequential sweep [default = %s]\n", fNoSweep? "yes": "no" ); + Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAddPi( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + // get the new network + if ( Abc_NtkPiNum(pNtk) == 0 ) + { + Abc_Ntk_t * pNtkRes = Abc_NtkDup( pNtk ); + Abc_Obj_t * pObj = Abc_NtkCreatePi( pNtkRes ); + Abc_ObjAssignName( pObj, "dummy_pi", NULL ); + Abc_NtkOrderCisCos( pNtkRes ); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + } + return 0; + +usage: + Abc_Print( -2, "usage: addpi [-h]\n" ); + Abc_Print( -2, "\t if the network has no PIs, add one dummy PI\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAddFlop( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -2, "The current network is not an AIG (run \"strash\").\n"); + return 0; + } + // get the new network + if ( Abc_NtkLatchNum(pNtk) == 0 ) + { + Abc_Ntk_t * pNtkRes = Abc_NtkDup( pNtk ); + Abc_NtkAddLatch( pNtkRes, Abc_AigConst1(pNtkRes), ABC_INIT_ONE ); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + } + return 0; + +usage: + Abc_Print( -2, "usage: addflop [-h]\n" ); + Abc_Print( -2, "\t if the network has no flops, add one dummy flop\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAppend( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtk2; + char * FileName; + int fComb = 0; + int c; + pNtk = Abc_FrameReadNtk(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fComb ^= 1; + break; + default: + goto usage; + } + } + + // get the second network + if ( argc != globalUtilOptind + 1 ) + { + Abc_Print( -1, "The network to append is not given.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "The base network should be strashed for the appending to work.\n" ); + return 1; + } + + // read the second network + FileName = argv[globalUtilOptind]; + pNtk2 = Io_Read( FileName, Io_ReadFileType(FileName), 1, 0 ); + if ( pNtk2 == NULL ) + return 1; + + // check if the second network is combinational + if ( Abc_NtkLatchNum(pNtk2) ) + { + Abc_NtkDelete( pNtk2 ); + Abc_Print( -1, "The second network has latches. Appending does not work for such networks.\n" ); + return 0; + } + + // get the new network + if ( !Abc_NtkAppend( pNtk, pNtk2, 1 ) ) + { + Abc_NtkDelete( pNtk2 ); + Abc_Print( -1, "Appending the networks failed.\n" ); + return 1; + } + Abc_NtkDelete( pNtk2 ); + // sweep dangling logic + Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc ); + // replace the current network +// Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: append [-h] \n" ); + Abc_Print( -2, "\t appends a combinational network on top of the current network\n" ); +// Abc_Print( -2, "\t-c : computes combinational miter (latches as POs) [default = %s]\n", fComb? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : file name with the second network\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPutOnTop( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Abc_Ntk_t * Abc_NtkPutOnTop( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtk2 ); + + Abc_Ntk_t * pNtk, * pNtk2, * pNtkRes = NULL; + char * FileName; + int fComb = 0; + int c; + pNtk = Abc_FrameReadNtk(pAbc); + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ch" ) ) != EOF ) + { + switch ( c ) + { + case 'c': + fComb ^= 1; + break; + default: + goto usage; + } + } + + if ( argc > globalUtilOptind + 1 ) + { + for ( c = 1; c < argc; c++ ) + { + Abc_Ntk_t * pTemp, * pLogic = Io_Read( argv[c], Io_ReadFileType(argv[c]), 1, 0 ); + if ( pLogic == NULL ) + return 1; + if ( Abc_NtkIsStrash(pLogic) ) + { + pLogic = Abc_NtkToLogic( pTemp = pLogic ); + Abc_NtkDelete( pTemp ); + } + if ( pLogic == NULL ) + return 1; + if ( pNtkRes == NULL ) + pNtkRes = pLogic; + else + { + pNtkRes = Abc_NtkPutOnTop( pTemp = pNtkRes, pLogic ); + Abc_NtkDelete( pTemp ); + Abc_NtkDelete( pLogic ); + if ( pNtkRes == NULL ) + return 1; + } + } + assert( Abc_NtkIsLogic(pNtkRes) ); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + } + + // get the second network + if ( argc != globalUtilOptind + 1 ) + { + Abc_Print( -1, "The network to append is not given.\n" ); + return 1; + } + + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "The base network should be in the logic form.\n" ); + return 1; + } + + // check if the second network is combinational + if ( Abc_NtkLatchNum(pNtk) ) + { + Abc_Print( -1, "The current network has latches. This command does not work for such networks.\n" ); + return 0; + } + + // read the second network + FileName = argv[globalUtilOptind]; + pNtk2 = Io_Read( FileName, Io_ReadFileType(FileName), 1, 0 ); + if ( pNtk2 == NULL ) + return 1; + + // check if the second network is combinational + if ( Abc_NtkLatchNum(pNtk2) ) + { + Abc_NtkDelete( pNtk2 ); + Abc_Print( -1, "The second network has latches. This command does not work for such networks.\n" ); + return 0; + } + // compare inputs/outputs + if ( Abc_NtkPoNum(pNtk) != Abc_NtkPiNum(pNtk2) ) + { + Abc_NtkDelete( pNtk2 ); + Abc_Print( -1, "The PO count (%d) of the first network is not equal to PI count (%d) of the second network.\n", Abc_NtkPoNum(pNtk), Abc_NtkPiNum(pNtk2) ); + return 0; + } + + // get the new network + if ( Abc_NtkIsLogic(pNtk2) ) + pNtkRes = Abc_NtkPutOnTop( pNtk, pNtk2 ); + else if ( Abc_NtkIsStrash(pNtk2) ) + { + Abc_Ntk_t * pLogic = Abc_NtkToLogic( pNtk2 ); + pNtkRes = Abc_NtkPutOnTop( pNtk, pLogic ); + Abc_NtkDelete( pLogic ); + } + else assert( 0 ); + Abc_NtkDelete( pNtk2 ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: putontop [-h] \n" ); + Abc_Print( -2, "\t connects PIs of network in to POs of current network\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : file name with the second network\n"); + Abc_Print( -2, "\t : (given several files, all networks are stacked on top of each other)\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFrames( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkTemp, * pNtkRes; + int nFrames; + int fInitial; + int fVerbose; + int c; + pNtk = Abc_FrameReadNtk(pAbc); + + // set defaults + nFrames = 5; + fInitial = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Fivh" ) ) != EOF ) + { + switch ( c ) + { + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFrames <= 0 ) + goto usage; + break; + case 'i': + fInitial ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + // get the new network + if ( !Abc_NtkIsStrash(pNtk) ) + { + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); + pNtkRes = Abc_NtkFrames( pNtkTemp, nFrames, fInitial, fVerbose ); + Abc_NtkDelete( pNtkTemp ); + } + else + pNtkRes = Abc_NtkFrames( pNtk, nFrames, fInitial, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Unrolling the network has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: frames [-F ] [-ivh]\n" ); + Abc_Print( -2, "\t unrolls the network for a number of time frames\n" ); + Abc_Print( -2, "\t-F : the number of frames to unroll [default = %d]\n", nFrames ); + Abc_Print( -2, "\t-i : toggles initializing the first frame [default = %s]\n", fInitial? "yes": "no" ); + Abc_Print( -2, "\t-v : toggles outputting verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDFrames( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkTemp, * pNtkRes; + int nPrefix; + int nFrames; + int fInitial; + int fVerbose; + int c; + + extern Abc_Ntk_t * Abc_NtkDarFrames( Abc_Ntk_t * pNtk, int nPrefix, int nFrames, int fInitial, int fVerbose ); + pNtk = Abc_FrameReadNtk(pAbc); + + // set defaults + nPrefix = 5; + nFrames = 5; + fInitial = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NFivh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nPrefix = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nPrefix <= 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFrames <= 0 ) + goto usage; + break; + case 'i': + fInitial ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( nPrefix > nFrames ) + { + Abc_Print( -1, "Prefix (%d) cannot be more than the number of frames (%d).\n", nPrefix, nFrames ); + return 1; + } + + // get the new network + if ( !Abc_NtkIsStrash(pNtk) ) + { + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); + pNtkRes = Abc_NtkDarFrames( pNtkTemp, nPrefix, nFrames, fInitial, fVerbose ); + Abc_NtkDelete( pNtkTemp ); + } + else + pNtkRes = Abc_NtkDarFrames( pNtk, nPrefix, nFrames, fInitial, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Unrolling the network has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: dframes [-NF ] [-ivh]\n" ); + Abc_Print( -2, "\t unrolls the network with simplification\n" ); + Abc_Print( -2, "\t-N num : the number of frames to use as prefix [default = %d]\n", nPrefix ); + Abc_Print( -2, "\t-F num : the number of frames to unroll [default = %d]\n", nFrames ); + Abc_Print( -2, "\t-i : toggles initializing the first frame [default = %s]\n", fInitial? "yes": "no" ); + Abc_Print( -2, "\t-v : toggles outputting verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSop( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_NtkFaninSort( Abc_Ntk_t * pNtk ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c, fCubeSort = 1, fMode = -1, nCubeLimit = 1000000; + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Csdnh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nCubeLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCubeLimit < 0 ) + goto usage; + break; + case 's': + fCubeSort ^= 1; + break; + case 'd': + fMode = 1; + break; + case 'n': + fMode = 0; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "Converting to SOP is possible only for logic networks.\n" ); + return 1; + } + if ( fCubeSort && Abc_NtkHasSop(pNtk) ) + { + Abc_NtkSortSops(pNtk); + return 0; + } + if ( !fCubeSort && Abc_NtkHasBdd(pNtk) && !Abc_NtkBddToSop(pNtk, -1, ABC_INFINITY, 0) ) + { + Abc_Print( -1, "Converting to SOP has failed.\n" ); + return 0; + } + if ( !Abc_NtkToSop(pNtk, fMode, nCubeLimit) ) + { + Abc_Print( -1, "Converting to SOP has failed.\n" ); + return 0; + } + if ( !fCubeSort ) + Abc_NtkFaninSort( pNtk ); + return 0; + +usage: + Abc_Print( -2, "usage: sop [-C num] [-sdnh]\n" ); + Abc_Print( -2, "\t converts node functions to SOP\n" ); + Abc_Print( -2, "\t-C num : the limit on the number of cubes at a node [default = %d]\n", nCubeLimit ); + Abc_Print( -2, "\t-s : toggles cube sort when converting from BDDs [default = %s]\n", fCubeSort ? "yes": "no" ); + Abc_Print( -2, "\t-d : toggles using only positive polarity [default = %s]\n", fMode == 1 ? "yes": "no" ); + Abc_Print( -2, "\t-n : toggles using only negative polarity [default = %s]\n", fMode == 0 ? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandBdd( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int fReorder = 1, fBdd2Sop = 0; + int c; + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "rsh" ) ) != EOF ) + { + switch ( c ) + { + case 'r': + fReorder ^= 1; + break; + case 's': + fBdd2Sop ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "Converting to BDD is possible only for logic networks.\n" ); + return 1; + } + if ( fBdd2Sop && Abc_NtkHasSop(pNtk) ) + return !Abc_NtkSopToBdd(pNtk); + if ( Abc_NtkIsBddLogic(pNtk) ) + { + Abc_Print( -1, "The logic network is already in the BDD form.\n" ); + return 0; + } + if ( !Abc_NtkToBdd(pNtk) ) + { + Abc_Print( -1, "Converting to BDD has failed.\n" ); + return 1; + } + return 0; + +usage: + Abc_Print( -2, "usage: bdd [-rsh]\n" ); + Abc_Print( -2, "\t converts node functions to BDD\n" ); + Abc_Print( -2, "\t-r : toggles enabling dynamic variable reordering [default = %s]\n", fReorder? "yes": "no" ); + Abc_Print( -2, "\t-s : toggles constructing BDDs directly from SOPs [default = %s]\n", fBdd2Sop? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAig( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "Converting to AIG is possible only for logic networks.\n" ); + return 1; + } + if ( Abc_NtkIsAigLogic(pNtk) ) + { + Abc_Print( -1, "The logic network is already in the AIG form.\n" ); + return 0; + } + if ( !Abc_NtkToAig(pNtk) ) + { + Abc_Print( -1, "Converting to AIG has failed.\n" ); + return 1; + } + return 0; + +usage: + Abc_Print( -2, "usage: aig [-h]\n" ); + Abc_Print( -2, "\t converts node functions to AIG\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandReorder( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fVerbose; + extern void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose ); + + // set defaults + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + // get the new network + if ( !Abc_NtkIsBddLogic(pNtk) ) + { + Abc_Print( -1, "Variable reordering is possible when node functions are BDDs (run \"bdd\").\n" ); + return 1; + } + Abc_NtkBddReorder( pNtk, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: reorder [-vh]\n" ); + Abc_Print( -2, "\t reorders local functions of the nodes using sifting\n" ); + Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandBidec( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fVerbose; + extern void Abc_NtkBidecResyn( Abc_Ntk_t * pNtk, int fVerbose ); + + // set defaults + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + // get the new network + if ( !Abc_NtkIsAigLogic(pNtk) ) + { + Abc_Print( -1, "Bi-decomposition only works when node functions are AIGs (run \"aig\").\n" ); + return 1; + } + Abc_NtkBidecResyn( pNtk, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: bidec [-vh]\n" ); + Abc_Print( -2, "\t applies bi-decomposition to local functions of the nodes\n" ); + Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandOrder( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pFile; + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + char * pFileName; + int c; + int fReverse; + int fVerbose; + extern void Abc_NtkImplementCiOrder( Abc_Ntk_t * pNtk, char * pFileName, int fReverse, int fVerbose ); + extern void Abc_NtkFindCiOrder( Abc_Ntk_t * pNtk, int fReverse, int fVerbose ); + + // set defaults + fReverse = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "rvh" ) ) != EOF ) + { + switch ( c ) + { + case 'r': + fReverse ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } +// if ( Abc_NtkLatchNum(pNtk) > 0 ) +// { +// Abc_Print( -1, "Currently this procedure does not work for sequential networks.\n" ); +// return 1; +// } + + // if the var order file is given, implement this order + pFileName = NULL; + if ( argc == globalUtilOptind + 1 ) + { + pFileName = argv[globalUtilOptind]; + pFile = fopen( pFileName, "r" ); + if ( pFile == NULL ) + { + Abc_Print( -1, "Cannot open file \"%s\" with the BDD variable order.\n", pFileName ); + return 1; + } + fclose( pFile ); + } + if ( pFileName ) + Abc_NtkImplementCiOrder( pNtk, pFileName, fReverse, fVerbose ); + else + Abc_NtkFindCiOrder( pNtk, fReverse, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: order [-rvh] \n" ); + Abc_Print( -2, "\t computes a good static CI variable order\n" ); + Abc_Print( -2, "\t-r : toggle reverse ordering [default = %s]\n", fReverse? "yes": "no" ); + Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : (optional) file with the given variable order\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMuxes( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c, fGlobal = 0, fUseAdd = 0, Limit = 1000000; + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Bgah" ) ) != EOF ) + { + switch ( c ) + { + case 'B': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" ); + goto usage; + } + Limit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Limit < 0 ) + goto usage; + break; + case 'g': + fGlobal ^= 1; + break; + case 'a': + fUseAdd ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( fGlobal ) + { + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "The current network should be an AIG.\n" ); + return 1; + } + } + else + { + if ( !Abc_NtkIsBddLogic(pNtk) ) + { + Abc_Print( -1, "Only a BDD logic network can be converted to MUXes.\n" ); + return 1; + } + } + + // get the new network + pNtkRes = Abc_NtkBddToMuxes( pNtk, fGlobal, Limit, fUseAdd ); + if ( pNtkRes == NULL ) + { + Abc_Print( 0, "Converting to MUXes has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: muxes [-B num] [-gah]\n" ); + Abc_Print( -2, "\t converts the current network into a network derived by\n" ); + Abc_Print( -2, "\t replacing all nodes by DAGs isomorphic to the local BDDs\n" ); + Abc_Print( -2, "\t-B : limit on live BDD nodes during collapsing [default = %d]\n", Limit ); + Abc_Print( -2, "\t-g : toggle visualizing the global BDDs of primary outputs [default = %s].\n", fGlobal? "yes": "no" ); + Abc_Print( -2, "\t-a : toggle using ADDs instead of BDDs [default = %s].\n", fUseAdd? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCubes( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Abc_Ntk_t * Abc_NtkSopToCubes( Abc_Ntk_t * pNtk, int fXor ); + Abc_Ntk_t * pNtk, * pNtkRes; + int c, fXor = 0; + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "xh" ) ) != EOF ) + { + switch ( c ) + { + case 'x': + fXor ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsSopLogic(pNtk) ) + { + Abc_Print( -1, "Only a SOP logic network can be transformed into cubes.\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkSopToCubes( pNtk, fXor ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Converting to cubes has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: cubes [-xh]\n" ); + Abc_Print( -2, "\t converts the current network into a network derived by creating\n" ); + Abc_Print( -2, "\t a separate node for each product and sum in the local SOPs\n" ); + Abc_Print( -2, "\t-x : toggle using XOR instead of OR [default = %s]\n", fXor? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandExpand( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_NtkExpandCubes( Abc_Ntk_t * pNtk, Gia_Man_t * pGia, int fVerbose ); + Abc_Ntk_t * pStrash, * pNtk2, * pNtk = Abc_FrameReadNtk(pAbc); + Gia_Man_t * pGia; int c, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsSopLogic(pNtk) ) + { + Abc_Print( -1, "Only a SOP logic network can be transformed into cubes.\n" ); + return 1; + } + if ( Abc_NtkLevel(pNtk) > 1 ) + { + Abc_Print( -1, "The number of logic levels is more than 1 (collapse the network and try again).\n" ); + return 1; + } + // read the offset representation + if ( argc != globalUtilOptind + 1 ) + { + Abc_Print( 0, "Using the complement of the current network as its offset.\n" ); + pNtk2 = Abc_NtkDup( pNtk ); + } + else + { + char * FileName = argv[globalUtilOptind]; + pNtk2 = Io_Read( FileName, Io_ReadFileType(FileName), 1, 0 ); + if ( pNtk2 == NULL ) + { + Abc_Print( -1, "Failed to read the current network from file \"%s\".\n", FileName ); + return 1; + } + } + // strash the network + pStrash = Abc_NtkStrash( pNtk2, 0, 1, 0 ); + Abc_NtkDelete( pNtk2 ); + // convert it into an AIG + pGia = Abc_NtkClpGia( pStrash ); + //Gia_AigerWrite( pGia, "aig_dump.aig", 0, 0, 0 ); + Abc_NtkDelete( pStrash ); + // get the new network + Abc_NtkExpandCubes( pNtk, pGia, fVerbose ); + Gia_ManStop( pGia ); + return 0; + +usage: + Abc_Print( -2, "usage: expand [-vh] \n" ); + Abc_Print( -2, "\t expands cubes against the offset\n" ); + Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\tfile : (optional) representation of on-set plus dc-set\n"); + + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSplitSop( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Abc_Ntk_t * Abc_NtkSplitSop( Abc_Ntk_t * pNtk, int nCubesMax, int fVerbose ); + Abc_Ntk_t * pNtk, * pNtkRes; + int c, fVerbose = 0, nCubesMax = 100; + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nCubesMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCubesMax < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsSopLogic(pNtk) ) + { + Abc_Print( -1, "Only a SOP logic network can be transformed into cubes.\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkSplitSop( pNtk, nCubesMax, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Converting to cubes has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: splitsop [-N num] [-vh]\n" ); + Abc_Print( -2, "\t splits nodes whose SOP size is larger than the given one\n" ); + Abc_Print( -2, "\t-N num : the maximum number of cubes after splitting [default = %d]\n", nCubesMax ); + Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandExtSeqDcs( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fVerbose; + extern int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNet, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkLatchNum(pNtk) == 0 ) + { + Abc_Print( -1, "The current network has no latches.\n" ); + return 0; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Extracting sequential don't-cares works only for AIGs (run \"strash\").\n" ); + return 0; + } + if ( !Abc_NtkExtractSequentialDcs( pNtk, fVerbose ) ) + { + Abc_Print( -1, "Extracting sequential don't-cares has failed.\n" ); + return 1; + } + return 0; + +usage: + Abc_Print( -2, "usage: ext_seq_dcs [-vh]\n" ); + Abc_Print( -2, "\t create EXDC network using unreachable states\n" ); + Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandReach( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Saig_ParBbr_t Pars, * pPars = &Pars; + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + char * pLogFileName = NULL; + + extern int Abc_NtkDarReach( Abc_Ntk_t * pNtk, Saig_ParBbr_t * pPars ); + + // set defaults + Bbr_ManSetDefaultParams( pPars ); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "TBFLproyvh" ) ) != EOF ) + { + switch ( c ) + { + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + pPars->TimeLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->TimeLimit < 0 ) + goto usage; + break; + case 'B': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-B\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nBddMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nBddMax < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nIterMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nIterMax < 0 ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" ); + goto usage; + } + pLogFileName = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'p': + pPars->fPartition ^= 1; + break; + case 'r': + pPars->fReorder ^= 1; + break; + case 'o': + pPars->fReorderImage ^= 1; + break; + case 'y': + pPars->fSkipOutCheck ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkLatchNum(pNtk) == 0 ) + { + Abc_Print( -1, "The current network has no latches.\n" ); + return 0; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Reachability analysis works only for AIGs (run \"strash\").\n" ); + return 1; + } + if ( pAbc->fBatchMode && (pAbc->Status == 0 || pAbc->Status == 1) ) + { + Abc_Print( 1, "The miters is already solved; skipping the command.\n" ); + return 0; + } + pAbc->Status = Abc_NtkDarReach( pNtk, pPars ); + pAbc->nFrames = pPars->iFrame; + Abc_FrameReplaceCex( pAbc, &pNtk->pSeqModel ); + if ( pLogFileName ) + Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "reach" ); + return 0; + +usage: + Abc_Print( -2, "usage: reach [-TBF num] [-L file] [-proyvh]\n" ); + Abc_Print( -2, "\t verifies sequential miter using BDD-based reachability\n" ); + Abc_Print( -2, "\t-T num : approximate time limit in seconds (0=infinite) [default = %d]\n", pPars->TimeLimit ); + Abc_Print( -2, "\t-B num : max number of nodes in the intermediate BDDs [default = %d]\n", pPars->nBddMax ); + Abc_Print( -2, "\t-F num : max number of reachability iterations [default = %d]\n", pPars->nIterMax ); + Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" ); + Abc_Print( -2, "\t-p : enable partitioned image computation [default = %s]\n", pPars->fPartition? "yes": "no" ); + Abc_Print( -2, "\t-r : enable dynamic BDD variable reordering [default = %s]\n", pPars->fReorder? "yes": "no" ); + Abc_Print( -2, "\t-o : toggles BDD variable reordering during image computation [default = %s]\n", pPars->fReorderImage? "yes": "no" ); + Abc_Print( -2, "\t-y : skip checking property outputs [default = %s]\n", pPars->fSkipOutCheck? "yes": "no" ); + Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", pPars->fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +Vec_Int_t * Vec_IntReadList( char * pStr, char Separ ) +{ + Vec_Int_t * vRes = Vec_IntAlloc( 10 ); + Vec_IntPush( vRes, atoi(pStr) ); + for ( int c = 0; c < strlen(pStr); c++ ) + if ( pStr[c] == Separ ) + Vec_IntPush( vRes, atoi(pStr+c+1) ); + return vRes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCone( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + Abc_Obj_t * pNode, * pNodeCo; + Vec_Int_t * vPoIds = NULL; + int c; + int fUseAllCis; + int fUseMffc; + int Output; + int nRange; + + extern Abc_Ntk_t * Abc_NtkSelectPos( Abc_Ntk_t * pNtkInit, Vec_Int_t * vPoIds ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + fUseAllCis = 0; + fUseMffc = 0; + Output = -1; + nRange = -1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ORNmah" ) ) != EOF ) + { + switch ( c ) + { + case 'O': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" ); + goto usage; + } + Output = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Output < 0 ) + goto usage; + break; + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + nRange = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nRange < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + vPoIds = Vec_IntReadList( argv[globalUtilOptind], ',' ); + globalUtilOptind++; + if ( vPoIds == NULL ) + goto usage; + break; + case 'm': + fUseMffc ^= 1; + break; + case 'a': + fUseAllCis ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Currently can only be applied to the logic network or an AIG.\n" ); + return 1; + } + + if ( argc > globalUtilOptind + 1 ) + { + Abc_Print( -1, "Wrong number of auguments.\n" ); + goto usage; + } + + pNodeCo = NULL; + if ( argc == globalUtilOptind + 1 ) + { + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + if ( fUseMffc ) + pNtkRes = Abc_NtkCreateMffc( pNtk, pNode, argv[globalUtilOptind] ); + else + pNtkRes = Abc_NtkCreateCone( pNtk, pNode, argv[globalUtilOptind], fUseAllCis ); + } + else if ( vPoIds ) + { + pNtkRes = Abc_NtkSelectPos( pNtk, vPoIds ); + Vec_IntFree( vPoIds ); + } + else if ( nRange > 0 ) + { + if ( Output == -1 ) + { + Abc_Print( -1, "The starting PO ID is not specified.\n" ); + return 1; + } + if ( Output >= Abc_NtkPoNum(pNtk) ) + { + Abc_Print( -1, "The 0-based output number (%d) is larger than the number of primary outputs (%d).\n", Output, Abc_NtkPoNum(pNtk) ); + return 1; + } assert( vPoIds == NULL ); + vPoIds = Vec_IntAlloc( nRange ); + for ( c = Output; c < Output + nRange; c++ ) + Vec_IntPush( vPoIds, c ); + pNtkRes = Abc_NtkSelectPos( pNtk, vPoIds ); + Vec_IntFree( vPoIds ); + } + else if ( Output >= 0 ) + { + if ( Output >= Abc_NtkPoNum(pNtk) ) + { + Abc_Print( -1, "The 0-based output number (%d) is larger than the number of primary outputs (%d).\n", Output, Abc_NtkPoNum(pNtk) ); + return 1; + } assert( vPoIds == NULL ); + vPoIds = Vec_IntAlloc( 1 ); + Vec_IntPush( vPoIds, Output ); + pNtkRes = Abc_NtkSelectPos( pNtk, vPoIds ); + Vec_IntFree( vPoIds ); + } + else + { + if ( Output == -1 ) + { + Abc_Print( -1, "The starting PO ID is not specified.\n" ); + return 1; + } + if ( Output >= Abc_NtkCoNum(pNtk) ) + { + Abc_Print( -1, "The 0-based output number (%d) is larger than the number of combinational outputs (%d).\n", Output, Abc_NtkCoNum(pNtk) ); + return 1; + } + pNodeCo = Abc_NtkCo( pNtk, Output ); + if ( fUseMffc ) + pNtkRes = Abc_NtkCreateMffc( pNtk, Abc_ObjFanin0(pNodeCo), Abc_ObjName(pNodeCo) ); + else + pNtkRes = Abc_NtkCreateCone( pNtk, Abc_ObjFanin0(pNodeCo), Abc_ObjName(pNodeCo), fUseAllCis ); + } + if ( pNodeCo && Abc_ObjFaninC0(pNodeCo) ) + { + Abc_NtkPo(pNtkRes, 0)->fCompl0 ^= 1; +// Abc_Print( -1, "The extracted cone represents the complement function of the CO.\n" ); + } + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Writing the logic cone of one node has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: cone [-ORN num] [-amh] \n" ); + Abc_Print( -2, "\t replaces the current network by one or more logic cones\n" ); + Abc_Print( -2, "\t-a : toggle keeping all CIs or structral support only [default = %s]\n", fUseAllCis? "all": "structural" ); + Abc_Print( -2, "\t-m : toggle keeping only MFFC or complete TFI cone [default = %s]\n", fUseMffc? "MFFC": "TFI cone" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t-O num : (optional) the 0-based number of the CO to extract\n"); + Abc_Print( -2, "\t-R num : (optional) the number of outputs to extract\n"); + Abc_Print( -2, "\t-N : (optional) a comma-separated list of zero-based primary output indexes\n"); + Abc_Print( -2, "\tname : (optional) the name of the node to extract\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandNode( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + Abc_Obj_t * pNode; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "Currently can only be applied to a logic network.\n" ); + return 1; + } + + if ( argc != globalUtilOptind + 1 ) + { + Abc_Print( -1, "Wrong number of auguments.\n" ); + goto usage; + } + + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + + pNtkRes = Abc_NtkCreateFromNode( pNtk, pNode ); +// pNtkRes = Abc_NtkDeriveFromBdd( pNtk->pManFunc, pNode->pData, NULL, NULL ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Splitting one node has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: node [-h] \n" ); + Abc_Print( -2, "\t replaces the current network by the network composed of one node\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\tname : the node name\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRange( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + pNtk = Abc_FrameReadNtk(pAbc); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Currently can only be applied to an AIG.\n" ); + return 1; + } + pNtkRes = Abc_NtkCreateFromRange( pNtk ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Deriving the network has failed.\n" ); + return 1; + } + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: range [-h]\n" ); + Abc_Print( -2, "\t computes the range of output values as one node\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCof( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk; + Abc_Obj_t * pNode; + int c, Const; + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "Currently can only be applied to a logic network.\n" ); + return 1; + } + + if ( argc != globalUtilOptind + 2 ) + { + Abc_Print( -1, "Wrong number of auguments.\n" ); + goto usage; + } + pNode = Abc_NtkFindCi( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + pNode = Abc_NtkFindNode( pNtk, argv[globalUtilOptind] ); + if ( pNode == NULL ) + { + Abc_Print( -1, "Cannot find node \"%s\".\n", argv[globalUtilOptind] ); + return 1; + } + Const = atoi( argv[globalUtilOptind+1] ); + if ( Const != 0 && Const != 1 ) + { + Abc_Print( -1, "Constant should be 0 or 1.\n", argv[globalUtilOptind+1] ); + return 1; + } + Abc_ObjReplaceByConstant( pNode, Const ); + return 0; + +usage: + Abc_Print( -2, "usage: cof [-h] \n" ); + Abc_Print( -2, "\t replaces one node in a logic network by constant 0 or 1\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : the node to replace\n"); + Abc_Print( -2, "\t : the constant to replace the node with\n"); + Abc_Print( -2, "\tname : the node name\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTopmost( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c, nLevels; + extern Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + nLevels = 10; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nLevels = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLevels < 0 ) + goto usage; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" ); + return 0; + } + + if ( Abc_NtkLatchNum(pNtk) > 0 ) + { + Abc_Print( -1, "Currently only works for combinational circuits.\n" ); + return 0; + } + + pNtkRes = Abc_NtkTopmost( pNtk, nLevels ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "The command has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: topmost [-N num] [-h]\n" ); + Abc_Print( -2, "\t replaces the current network by several of its topmost levels\n" ); + Abc_Print( -2, "\t-N num : max number of levels [default = %d]\n", nLevels ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\tname : the node name\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandBottommost( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c, nLevels; + extern Abc_Ntk_t * Abc_NtkBottommost( Abc_Ntk_t * pNtk, int nLevels ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + nLevels = 10; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nLevels = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLevels < 0 ) + goto usage; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" ); + return 0; + } + + if ( Abc_NtkLatchNum(pNtk) > 0 ) + { + Abc_Print( -1, "Currently only works for combinational circuits.\n" ); + return 0; + } + + pNtkRes = Abc_NtkBottommost( pNtk, nLevels ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "The command has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: bottommost [-N num] [-h]\n" ); + Abc_Print( -2, "\t replaces the current network by several of its bottommost levels\n" ); + Abc_Print( -2, "\t-N num : max number of levels [default = %d]\n", nLevels ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\tname : the node name\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTopAnd( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + extern Abc_Ntk_t * Abc_NtkTopAnd( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Currently only works for structurally hashed circuits.\n" ); + return 0; + } + + if ( Abc_NtkLatchNum(pNtk) > 0 ) + { + Abc_Print( -1, "Currently can only works for combinational circuits.\n" ); + return 0; + } + if ( Abc_NtkPoNum(pNtk) != 1 ) + { + Abc_Print( -1, "Currently expects a single-output miter.\n" ); + return 0; + } + if ( Abc_ObjFaninC0(Abc_NtkPo(pNtk, 0)) ) + { + Abc_Print( -1, "The PO driver is complemented. AND-decomposition is impossible.\n" ); + return 0; + } + if ( !Abc_ObjIsNode(Abc_ObjChild0(Abc_NtkPo(pNtk, 0))) ) + { + Abc_Print( -1, "The PO driver is not a node. AND-decomposition is impossible.\n" ); + return 0; + } + pNtkRes = Abc_NtkTopAnd( pNtk ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "The command has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: topand [-h]\n" ); + Abc_Print( -2, "\t performs AND-decomposition of single-output combinational miter\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\tname : the node name\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTrim( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + Gia_Man_t * pGia, * pNew; + Aig_Man_t * pAig; + int c; + pNtk = Abc_FrameReadNtk(pAbc); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nh" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Trimming works only for AIGs (run \"strash\").\n" ); + return 1; + } + // convert to GIA + pAig = Abc_NtkToDar( pNtk, 0, 1 ); + pGia = Gia_ManFromAigSimple( pAig ); + Aig_ManStop( pAig ); + // perform trimming + pNew = Gia_ManDupTrimmed( pGia, 1, 1, 0, -1 ); + Gia_ManStop( pGia ); + // convert back + pAig = Gia_ManToAigSimple( pNew ); + Gia_ManStop( pNew ); + pNtkRes = Abc_NtkFromAigPhase( pAig ); + Aig_ManStop( pAig ); + // duplicate the name and the spec + ABC_FREE( pNtkRes->pName ); + ABC_FREE( pNtkRes->pSpec ); + pNtkRes->pName = Extra_UtilStrsav(pNtk->pName); + pNtkRes->pSpec = Extra_UtilStrsav(pNtk->pSpec); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: trim [-h]\n" ); + Abc_Print( -2, "\t removes POs fed by constants and PIs w/o fanout\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandShortNames( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c, fKeepIo = 0; + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "kh" ) ) != EOF ) + { + switch ( c ) + { + case 'k': + fKeepIo ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( fKeepIo ) + Abc_NtkCleanNames( pNtk ); + else + Abc_NtkShortNames( pNtk ); + return 0; + +usage: + Abc_Print( -2, "usage: short_names [-kh]\n" ); + Abc_Print( -2, "\t replaces PI/PO/latch names by short char strings\n" ); + Abc_Print( -2, "\t-k : toggle keeping PI/PO names unchanged [default = %s]\n", fKeepIo? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMoveNames( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_NtkMoveNames( Abc_Ntk_t * pNtk, Abc_Ntk_t * pOld ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Abc_Ntk_t * pNtk2; + char * FileName; + int c; + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + // get the second network + if ( argc != globalUtilOptind + 1 ) + { + Abc_Print( -1, "The network to take names from is not given.\n" ); + return 1; + } + + // read the second network + FileName = argv[globalUtilOptind]; + pNtk2 = Io_Read( FileName, Io_ReadFileType(FileName), 1, 0 ); + if ( pNtk2 == NULL ) + return 1; + + // compare inputs/outputs + if ( Abc_NtkPiNum(pNtk) != Abc_NtkPiNum(pNtk2) ) + { + Abc_NtkDelete( pNtk2 ); + Abc_Print( -1, "The PI count (%d) of the first network is not equal to PI count (%d) of the second network.\n", Abc_NtkPiNum(pNtk), Abc_NtkPiNum(pNtk2) ); + return 0; + } + // compare inputs/outputs + if ( Abc_NtkPoNum(pNtk) != Abc_NtkPoNum(pNtk2) ) + { + Abc_NtkDelete( pNtk2 ); + Abc_Print( -1, "The PO count (%d) of the first network is not equal to PO count (%d) of the second network.\n", Abc_NtkPoNum(pNtk), Abc_NtkPoNum(pNtk2) ); + return 0; + } + // compare inputs/outputs + if ( Abc_NtkLatchNum(pNtk) != Abc_NtkLatchNum(pNtk2) ) + { + Abc_NtkDelete( pNtk2 ); + Abc_Print( -1, "The flop count (%d) of the first network is not equal to flop count (%d) of the second network.\n", Abc_NtkLatchNum(pNtk), Abc_NtkLatchNum(pNtk2) ); + return 0; + } + Abc_NtkMoveNames( pNtk, pNtk2 ); + Abc_NtkDelete( pNtk2 ); + return 0; + +usage: + Abc_Print( -2, "usage: move_names [-h] \n" ); + Abc_Print( -2, "\t moves PI/PO/latch names from the other network\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : file with network that has required names\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandExdcFree( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( pNtk->pExdc == NULL ) + { + Abc_Print( -1, "The network has no EXDC.\n" ); + return 1; + } + + Abc_NtkDelete( pNtk->pExdc ); + pNtk->pExdc = NULL; + + // replace the current network + pNtkRes = Abc_NtkDup( pNtk ); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: exdc_free [-h]\n" ); + Abc_Print( -2, "\t frees the EXDC network of the current network\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandExdcGet( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( pNtk->pExdc == NULL ) + { + Abc_Print( -1, "The network has no EXDC.\n" ); + return 1; + } + + // replace the current network + pNtkRes = Abc_NtkDup( pNtk->pExdc ); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: exdc_get [-h]\n" ); + Abc_Print( -2, "\t replaces the current network by the EXDC of the current network\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandExdcSet( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pFile; + Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes; + char * FileName; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + + // get the input file name + FileName = argv[globalUtilOptind]; + if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); + if ( (FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" )) ) + Abc_Print( 1, "Did you mean \"%s\"?", FileName ); + Abc_Print( 1, "\n" ); + return 1; + } + fclose( pFile ); + + // set the new network + pNtkNew = Io_Read( FileName, Io_ReadFileType(FileName), 1, 0 ); + if ( pNtkNew == NULL ) + { + Abc_Print( -1, "Reading network from file has failed.\n" ); + return 1; + } + + // replace the EXDC + if ( pNtk->pExdc ) + { + Abc_NtkDelete( pNtk->pExdc ); + pNtk->pExdc = NULL; + } + pNtkRes = Abc_NtkDup( pNtk ); + pNtkRes->pExdc = pNtkNew; + + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: exdc_set [-h] \n" ); + Abc_Print( -2, "\t sets the network from file as EXDC for the current network\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : file with the new EXDC network\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCareSet( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * pFile; + Abc_Ntk_t * pNtk, * pNtkNew, * pNtkRes; + char * FileName; + int c; + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + + // get the input file name + FileName = argv[globalUtilOptind]; + if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); + if ( (FileName = Extra_FileGetSimilarName( FileName, ".mv", ".blif", ".pla", ".eqn", ".bench" )) ) + Abc_Print( 1, "Did you mean \"%s\"?", FileName ); + Abc_Print( 1, "\n" ); + return 1; + } + fclose( pFile ); + + // set the new network + pNtkNew = Io_Read( FileName, Io_ReadFileType(FileName), 1, 0 ); + if ( pNtkNew == NULL ) + { + Abc_Print( -1, "Reading network from file has failed.\n" ); + return 1; + } + + // replace the EXDC + if ( pNtk->pExcare ) + { + Abc_NtkDelete( (Abc_Ntk_t *)pNtk->pExcare ); + pNtk->pExcare = NULL; + } + pNtkRes = Abc_NtkDup( pNtk ); + pNtkRes->pExcare = pNtkNew; + + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: care_set [-h] \n" ); + Abc_Print( -2, "\t sets the network from file as a care for the current network\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : file with the new care network\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCut( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Cut_Params_t Params, * pParams = &Params; + Cut_Man_t * pCutMan; + Cut_Oracle_t * pCutOracle = NULL; + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fOracle; + extern Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ); + extern void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * pCutOracle ); + + // set defaults + fOracle = 0; + memset( pParams, 0, sizeof(Cut_Params_t) ); + pParams->nVarsMax = 5; // the max cut size ("k" of the k-feasible cuts) + pParams->nKeepMax = 1000; // the max number of cuts kept at a node + pParams->fTruth = 1; // compute truth tables + pParams->fFilter = 1; // filter dominated cuts + pParams->fDrop = 0; // drop cuts on the fly + pParams->fDag = 1; // compute DAG cuts + pParams->fTree = 0; // compute tree cuts + pParams->fGlobal = 0; // compute global cuts + pParams->fLocal = 0; // compute local cuts + pParams->fFancy = 0; // compute something fancy + pParams->fRecordAig = 1; // compute something fancy + pParams->fMap = 0; // compute mapping delay + pParams->fAdjust = 0; // removes useless fanouts + pParams->fNpnSave = 0; // enables dumping truth tables + pParams->fVerbose = 0; // the verbosiness flag + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KMtfdxyglzamjvosh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nVarsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nVarsMax < 0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nKeepMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nKeepMax < 0 ) + goto usage; + break; + case 't': + pParams->fTruth ^= 1; + break; + case 'f': + pParams->fFilter ^= 1; + break; + case 'd': + pParams->fDrop ^= 1; + break; + case 'x': + pParams->fDag ^= 1; + break; + case 'y': + pParams->fTree ^= 1; + break; + case 'g': + pParams->fGlobal ^= 1; + break; + case 'l': + pParams->fLocal ^= 1; + break; + case 'z': + pParams->fFancy ^= 1; + break; + case 'a': + pParams->fRecordAig ^= 1; + break; + case 'm': + pParams->fMap ^= 1; + break; + case 'j': + pParams->fAdjust ^= 1; + break; + case 'v': + pParams->fVerbose ^= 1; + break; + case 'o': + fOracle ^= 1; + break; + case 's': + pParams->fNpnSave ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Cut computation is available only for AIGs (run \"strash\").\n" ); + return 1; + } + if ( pParams->nVarsMax < CUT_SIZE_MIN || pParams->nVarsMax > CUT_SIZE_MAX ) + { + Abc_Print( -1, "Can only compute the cuts for %d <= K <= %d.\n", CUT_SIZE_MIN, CUT_SIZE_MAX ); + return 1; + } + if ( pParams->fDag && pParams->fTree ) + { + Abc_Print( -1, "Cannot compute both DAG cuts and tree cuts at the same time.\n" ); + return 1; + } + + if ( pParams->fNpnSave ) + { + pParams->nVarsMax = 6; + pParams->fTruth = 1; + } + + if ( fOracle ) + pParams->fRecord = 1; + pCutMan = Abc_NtkCuts( pNtk, pParams ); + if ( fOracle ) + pCutOracle = Cut_OracleStart( pCutMan ); + Cut_ManStop( pCutMan ); + if ( fOracle ) + { + assert(pCutOracle); + Abc_NtkCutsOracle( pNtk, pCutOracle ); + Cut_OracleStop( pCutOracle ); + } + return 0; + +usage: + Abc_Print( -2, "usage: cut [-K num] [-M num] [-tfdcovamjsvh]\n" ); + Abc_Print( -2, "\t computes k-feasible cuts for the AIG\n" ); + Abc_Print( -2, "\t-K num : max number of leaves (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, pParams->nVarsMax ); + Abc_Print( -2, "\t-M num : max number of cuts stored at a node [default = %d]\n", pParams->nKeepMax ); + Abc_Print( -2, "\t-t : toggle truth table computation [default = %s]\n", pParams->fTruth? "yes": "no" ); + Abc_Print( -2, "\t-f : toggle filtering of duplicated/dominated [default = %s]\n", pParams->fFilter? "yes": "no" ); + Abc_Print( -2, "\t-d : toggle dropping when fanouts are done [default = %s]\n", pParams->fDrop? "yes": "no" ); + Abc_Print( -2, "\t-x : toggle computing only DAG cuts [default = %s]\n", pParams->fDag? "yes": "no" ); + Abc_Print( -2, "\t-y : toggle computing only tree cuts [default = %s]\n", pParams->fTree? "yes": "no" ); + Abc_Print( -2, "\t-g : toggle computing only global cuts [default = %s]\n", pParams->fGlobal? "yes": "no" ); + Abc_Print( -2, "\t-l : toggle computing only local cuts [default = %s]\n", pParams->fLocal? "yes": "no" ); + Abc_Print( -2, "\t-z : toggle fancy computations [default = %s]\n", pParams->fFancy? "yes": "no" ); + Abc_Print( -2, "\t-a : toggle recording cut functions [default = %s]\n", pParams->fRecordAig?"yes": "no" ); + Abc_Print( -2, "\t-m : toggle delay-oriented FPGA mapping [default = %s]\n", pParams->fMap? "yes": "no" ); + Abc_Print( -2, "\t-j : toggle removing fanouts due to XOR/MUX [default = %s]\n", pParams->fAdjust? "yes": "no" ); + Abc_Print( -2, "\t-s : toggle creating library of 6-var functions [default = %s]\n", pParams->fNpnSave? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandScut( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Cut_Params_t Params, * pParams = &Params; + Cut_Man_t * pCutMan; + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + extern Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams ); + + // set defaults + memset( pParams, 0, sizeof(Cut_Params_t) ); + pParams->nVarsMax = 5; // the max cut size ("k" of the k-feasible cuts) + pParams->nKeepMax = 1000; // the max number of cuts kept at a node + pParams->fTruth = 0; // compute truth tables + pParams->fFilter = 1; // filter dominated cuts + pParams->fSeq = 1; // compute sequential cuts + pParams->fVerbose = 0; // the verbosiness flag + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KMtvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nVarsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nVarsMax < 0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nKeepMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nKeepMax < 0 ) + goto usage; + break; + case 't': + pParams->fTruth ^= 1; + break; + case 'v': + pParams->fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } +/* + if ( !Abc_NtkIsSeq(pNtk) ) + { + Abc_Print( -1, "Sequential cuts can be computed for sequential AIGs (run \"seq\").\n" ); + return 1; + } +*/ + if ( pParams->nVarsMax < CUT_SIZE_MIN || pParams->nVarsMax > CUT_SIZE_MAX ) + { + Abc_Print( -1, "Can only compute the cuts for %d <= K <= %d.\n", CUT_SIZE_MIN, CUT_SIZE_MAX ); + return 1; + } + + pCutMan = Abc_NtkSeqCuts( pNtk, pParams ); + Cut_ManStop( pCutMan ); + return 0; + +usage: + Abc_Print( -2, "usage: scut [-K num] [-M num] [-tvh]\n" ); + Abc_Print( -2, "\t computes k-feasible cuts for the sequential AIG\n" ); + Abc_Print( -2, "\t-K num : max number of leaves (%d <= num <= %d) [default = %d]\n", CUT_SIZE_MIN, CUT_SIZE_MAX, pParams->nVarsMax ); + Abc_Print( -2, "\t-M num : max number of cuts stored at a node [default = %d]\n", pParams->nKeepMax ); + Abc_Print( -2, "\t-t : toggle truth table computation [default = %s]\n", pParams->fTruth? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandEspresso( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fVerbose; + extern void Abc_NtkEspresso( Abc_Ntk_t * pNtk, int fVerbose ); + + if ( argc == 2 && !strcmp(argv[1], "-h") ) + { + Abc_Print( -2, "The espresso command is currently disabled.\n" ); + return 1; + } + + Abc_Print( -1, "This command is currently disabled.\n" ); + return 0; + + // set defaults + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "SOP minimization is possible for logic networks (run \"renode\").\n" ); + return 1; + } +// Abc_NtkEspresso( pNtk, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: espresso [-vh]\n" ); + Abc_Print( -2, "\t minimizes SOPs of the local functions using Espresso\n" ); + Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandGen( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ +// Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int nVars; // the number of variables + int nArgs; // the number of arguments + int nLutSize = -1; // the size of LUTs + int nLuts = -1; // the number of LUTs + int fAdder; + int fAdderTree; + int fSorter; + int fMesh; + int fMulti; + int fBooth; + int fFpga; + int fOneHot; + int fRandom; + int fGraph; + int fVerbose; + char * FileName; + char Command[1000]; + extern void Abc_GenAdder( char * pFileName, int nVars ); + extern void Abc_GenSorter( char * pFileName, int nVars ); + extern void Abc_GenMesh( char * pFileName, int nVars ); + extern void Abc_GenMulti( char * pFileName, int nVars ); + extern void Abc_GenBooth( char * pFileName, int nVars ); + extern void Abc_GenFpga( char * pFileName, int nLutSize, int nLuts, int nVars ); + extern void Abc_GenOneHot( char * pFileName, int nVars ); + extern void Abc_GenRandom( char * pFileName, int nPis ); + extern void Abc_GenGraph( char * pFileName, int nPis ); + extern void Abc_GenAdderTree( char * pFileName, int nArgs, int nBits ); + + // set defaults + nVars = 8; + nArgs = 8; + fAdder = 0; + fAdderTree = 0; + fSorter = 0; + fMesh = 0; + fMulti = 0; + fBooth = 0; + fFpga = 0; + fOneHot = 0; + fRandom = 0; + fGraph = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NAKLatsembfnrgvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVars < 0 ) + goto usage; + break; + case 'A': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-A\" should be followed by an integer.\n" ); + goto usage; + } + nArgs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nArgs < 0 ) + goto usage; + break; + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutSize < 0 ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + nLuts = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLuts < 0 ) + goto usage; + break; + case 'a': + fAdder ^= 1; + break; + case 't': + fAdderTree ^= 1; + break; + case 's': + fSorter ^= 1; + break; + case 'e': + fMesh ^= 1; + break; + case 'm': + fMulti ^= 1; + break; + case 'b': + fBooth ^= 1; + break; + case 'f': + fFpga ^= 1; + break; + case 'n': + fOneHot ^= 1; + break; + case 'r': + fRandom ^= 1; + break; + case 'g': + fGraph ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + if ( nVars < 1 ) + { + Abc_Print( -1, "The number of variables should be a positive integer.\n" ); + return 0; + } + // get the input file name + FileName = argv[globalUtilOptind]; + if ( fAdder ) + Abc_GenAdder( FileName, nVars ); + else if ( fSorter ) + Abc_GenSorter( FileName, nVars ); + else if ( fMesh ) + Abc_GenMesh( FileName, nVars ); + else if ( fMulti ) + Abc_GenMulti( FileName, nVars ); + else if ( fBooth ) + Abc_GenBooth( FileName, nVars ); + else if ( fFpga ) + Abc_GenFpga( FileName, nLutSize, nLuts, nVars ); +// Abc_GenFpga( FileName, 2, 2, 3 ); +// Abc_GenFpga( FileName, 3, 2, 5 ); + else if ( fOneHot ) + Abc_GenOneHot( FileName, nVars ); + else if ( fRandom ) + Abc_GenRandom( FileName, nVars ); + else if ( fGraph ) + Abc_GenGraph( FileName, nVars ); + else if ( fAdderTree ) + { + printf( "Generating adder tree with %d arguments and %d bits.\n", nArgs, nVars ); + Abc_GenAdderTree( FileName, nArgs, nVars ); + sprintf( Command, "%%read %s; %%blast; &put", FileName ); + Cmd_CommandExecute( pAbc, Command ); + return 0; + } + else + { + Abc_Print( -1, "Type of circuit is not specified.\n" ); + return 0; + } + // read the file just produced + sprintf(Command, "read %s", FileName ); + Cmd_CommandExecute( pAbc, Command ); + return 0; + +usage: + Abc_Print( -2, "usage: gen [-NAKL num] [-atsembfnrgvh] \n" ); + Abc_Print( -2, "\t generates simple circuits\n" ); + Abc_Print( -2, "\t-N num : the number of variables [default = %d]\n", nVars ); + Abc_Print( -2, "\t-A num : the number of arguments (for adder tree) [default = %d]\n", nArgs ); + Abc_Print( -2, "\t-K num : the LUT size (to be used with switch -f) [default = %d]\n", nLutSize ); + Abc_Print( -2, "\t-L num : the LUT count (to be used with switch -f) [default = %d]\n", nLuts ); + Abc_Print( -2, "\t-a : generate ripple-carry adder [default = %s]\n", fAdder? "yes": "no" ); + Abc_Print( -2, "\t-t : generate an adder tree [default = %s]\n", fAdderTree? "yes": "no" ); + Abc_Print( -2, "\t-s : generate a sorter [default = %s]\n", fSorter? "yes": "no" ); + Abc_Print( -2, "\t-e : generate a mesh [default = %s]\n", fMesh? "yes": "no" ); + Abc_Print( -2, "\t-m : generate a multiplier [default = %s]\n", fMulti? "yes": "no" ); + Abc_Print( -2, "\t-b : generate a signed Booth multiplier [default = %s]\n", fBooth? "yes": "no" ); + Abc_Print( -2, "\t-f : generate a LUT FPGA structure [default = %s]\n", fFpga? "yes": "no" ); + Abc_Print( -2, "\t-g : generate a graph structure [default = %s]\n", fGraph? "yes": "no" ); + Abc_Print( -2, "\t-n : generate one-hotness conditions [default = %s]\n", fOneHot? "yes": "no" ); + Abc_Print( -2, "\t-r : generate random single-output function [default = %s]\n", fRandom? "yes": "no" ); + Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : output file name\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandGenTF( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_GenThresh( char * pFileName, int nBits, Vec_Int_t * vNums, int nLutSize, char * pArch ); + int c, nBits = 0, nLutSize = -1, fVerbose = 0, nSum = 0; + char Command[1000], * pFileName = "out.blif", * pArch = NULL; + Vec_Int_t * vNums = NULL; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "WKAvh" ) ) != EOF ) + { + switch ( c ) + { + case 'W': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + nBits = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nBits < 0 ) + goto usage; + break; + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nLutSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLutSize < 0 ) + goto usage; + break; + case 'A': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-A\" should be followed by a file name.\n" ); + goto usage; + } + pArch = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc == globalUtilOptind ) + goto usage; + if ( nBits == 0 ) + { + Abc_Print( -1, "Bit-width should be specified.\n" ); + return 0; + } + if ( nLutSize != -1 && nLutSize != 4 && nLutSize != 6 ) + { + Abc_Print( -1, "LUT size %d is not supported.\n", nLutSize ); + return 0; + } + if ( pArch ) + { + int Counts[2] = {0}; + for ( c = 0; c < strlen(pArch); c++ ) + if ( pArch[c] == '(' ) + Counts[0]++; + else if ( pArch[c] == ')' ) + Counts[1]++; + else if ( pArch[c] >= '1' && pArch[c] <= '9' ) + nSum += pArch[c] - '0'; + else if ( pArch[c] >= 'A' && pArch[c] <= 'Z' ) + nSum += pArch[c] - 'A' + 10; + else { + Abc_Print( -1, "Architecture description contains a wrong symbol (%c).\n", pArch[c] ); + return 0; + } + if ( Counts[0] != Counts[1] ) + { + Abc_Print( -1, "Mismatching number of opening and closing parentheses (%d and %d).\n", Counts[0], Counts[1] ); + return 0; + } + } + vNums = Vec_IntAlloc( argc ); + for ( c = globalUtilOptind; c < argc; c++ ) + Vec_IntPush( vNums, atoi(argv[c]) ); + if ( Vec_IntSize(vNums) < 3 ) { + Abc_Print( -1, "Expecting that at least two weights and a threshold are specified on the command line.\n" ); + Vec_IntFree( vNums ); + return 0; + } + if ( pArch && nSum != Vec_IntSize(vNums)-1 ) { + Abc_Print( -1, "The architecture assumes %d sum inputs while there are %d weights.\n", nSum, Vec_IntSize(vNums)-1 ); + Vec_IntFree( vNums ); + return 0; + } + printf( "Generating threshold function with %d inputs and bit-width %d.\n", Vec_IntSize(vNums)-1, nBits ); + Abc_GenThresh( pFileName, nBits, vNums, nLutSize, pArch ); + if ( nLutSize == 4 || nLutSize == 6 ) + sprintf(Command, "read %s; strash; if -K %d -am; mfs2 -W 10 -L 10 -M 1000", pFileName, nLutSize ); + else + sprintf(Command, "read %s", pFileName ); + Cmd_CommandExecute( pAbc, Command ); + Vec_IntFree( vNums ); + return 0; + +usage: + Abc_Print( -2, "usage: gentf [-WK num] [-A str] [-vh] ... \n" ); + Abc_Print( -2, "\t generates threshold function\n" ); + Abc_Print( -2, "\t-W num : the bit-width [default = none]\n" ); + Abc_Print( -2, "\t-K num : the LUT size [default = none]\n" ); + Abc_Print( -2, "\t-A str : the circuit architecture [default = none]\n"); + Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : weights and threshold\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandGenAT( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_GenAT( char * pFileName, Vec_Int_t * vNums ); + extern void Abc_GenATDual( char * pFileName, Vec_Int_t * vNums ); + int c, fDual = 0, fVerbose = 0; + char Command[1000], * pFileName = "out.blif"; + Vec_Int_t * vNums = NULL; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dvh" ) ) != EOF ) + { + switch ( c ) + { + case 'd': + fDual ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc == globalUtilOptind ) + goto usage; + vNums = Vec_IntAlloc( argc ); + for ( c = globalUtilOptind; c < argc; c++ ) + Vec_IntPush( vNums, atoi(argv[c]) ); + if ( fDual ) + Abc_GenATDual( pFileName, vNums ); + else + Abc_GenAT( pFileName, vNums ); + sprintf(Command, "read %s", pFileName ); + Cmd_CommandExecute( pAbc, Command ); + Vec_IntFree( vNums ); + return 0; + +usage: + Abc_Print( -2, "usage: genat [-dvh] ... \n" ); + Abc_Print( -2, "\t generates the adder tree\n" ); + Abc_Print( -2, "\t-d : toggle building dual tree [default = %s]\n", fDual? "yes": "no" ); + Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : input counts by rank\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandGenFsm( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_GenFsm( char * pFileName, int nIns, int nOuts, int nStates, int nLines, int ProbI, int ProbO ); + int c, nIns, nOuts, nStates, nLines, ProbI, ProbO, fVerbose; + char * FileName; + // set defaults + nIns = 30; + nOuts = 1; + nStates = 20; + nLines = 100; + ProbI = 10; + ProbO = 100; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "IOSLPQvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nIns = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIns < 0 ) + goto usage; + break; + case 'O': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-O\" should be followed by an integer.\n" ); + goto usage; + } + nOuts = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nOuts < 0 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + nStates = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nStates < 0 ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + nLines = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLines < 0 ) + goto usage; + break; + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + ProbI = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( ProbI < 0 ) + goto usage; + break; + case 'Q': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-Q\" should be followed by an integer.\n" ); + goto usage; + } + ProbO = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( ProbO < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( argc != globalUtilOptind + 1 ) + { + goto usage; + } + if ( nIns < 1 || nStates < 1 || nLines < 1 || ProbI < 1 || ProbO < 1 ) + { + Abc_Print( -1, "The number of inputs. states, lines, and probablity should be positive integers.\n" ); + goto usage; + } + // get the input file name + FileName = argv[globalUtilOptind]; + Abc_GenFsm( FileName, nIns, nOuts, nStates, nLines, ProbI, ProbO ); + return 0; + +usage: + Abc_Print( -2, "usage: genfsm [-IOSLPQ num] [-vh] \n" ); + Abc_Print( -2, "\t generates random FSM in KISS format\n" ); + Abc_Print( -2, "\t-I num : the number of input variables [default = %d]\n", nIns ); + Abc_Print( -2, "\t-O num : the number of output variables [default = %d]\n", nOuts ); + Abc_Print( -2, "\t-S num : the number of state variables [default = %d]\n", nStates ); + Abc_Print( -2, "\t-L num : the number of lines (product terms) [default = %d]\n", nLines ); + Abc_Print( -2, "\t-P num : percentage propability of a variable present in the input cube [default = %d]\n", ProbI ); + Abc_Print( -2, "\t-Q num : percentage propability of a variable present in the output cube [default = %d]\n", ProbO ); + Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : output file name\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCover( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int fVerbose; + int fUseSop; + int fUseEsop; + int fUseInvs; + int nFaninMax; + int nCubesMax; + pNtk = Abc_FrameReadNtk(pAbc); + + // set defaults + fUseSop = 1; + fUseEsop = 0; + fVerbose = 0; + fUseInvs = 1; + nFaninMax = 8; + nCubesMax = 8; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "IPsxivh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nFaninMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFaninMax < 0 ) + goto usage; + break; + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + nCubesMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCubesMax < 0 ) + goto usage; + break; + case 's': + fUseSop ^= 1; + break; + case 'x': + fUseEsop ^= 1; + break; + case 'i': + fUseInvs ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Only works for strashed networks.\n" ); + return 1; + } + + // run the command + pNtkRes = Abc_NtkSopEsopCover( pNtk, nFaninMax, nCubesMax, fUseEsop, fUseSop, fUseInvs, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: cover [-IP num] [-sxvh]\n" ); + Abc_Print( -2, "\t decomposition into a network of SOP/ESOP PLAs\n" ); + Abc_Print( -2, "\t (this command is known to have bugs)\n"); + Abc_Print( -2, "\t-I num : maximum number of inputs [default = %d]\n", nFaninMax ); + Abc_Print( -2, "\t-P num : maximum number of products [default = %d]\n", nCubesMax ); + Abc_Print( -2, "\t-s : toggle the use of SOPs [default = %s]\n", fUseSop? "yes": "no" ); + Abc_Print( -2, "\t-x : toggle the use of ESOPs [default = %s]\n", fUseEsop? "yes": "no" ); +// Abc_Print( -2, "\t-i : toggle the use of interters [default = %s]\n", fUseInvs? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandInter( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtk1, * pNtk2, * pNtkRes = NULL; + char ** pArgvNew; + int nArgcNew; + int c, fDelete1, fDelete2; + int fRelation; + int fVerbose; + extern Abc_Ntk_t * Abc_NtkInter( Abc_Ntk_t * pNtkOn, Abc_Ntk_t * pNtkOff, int fRelation, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + fRelation = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "rvh" ) ) != EOF ) + { + switch ( c ) + { + case 'r': + fRelation ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( !Abc_NtkPrepareTwoNtks( stdout, pNtk, pArgvNew, nArgcNew, &pNtk1, &pNtk2, &fDelete1, &fDelete2, 1 ) ) + return 1; + if ( nArgcNew == 0 ) + { + Abc_Obj_t * pObj; + int i; + Abc_Print( -1, "Deriving new circuit structure for the current network.\n" ); + Abc_NtkForEachPo( pNtk2, pObj, i ) + Abc_ObjXorFaninC( pObj, 0 ); + } + if ( fRelation && Abc_NtkCoNum(pNtk1) != 1 ) + { + Abc_Print( -1, "Computation of interplants as a relation only works for single-output functions.\n" ); + Abc_Print( -1, "Use command \"cone\" to extract one output cone from the multi-output network.\n" ); + } + else + pNtkRes = Abc_NtkInter( pNtk1, pNtk2, fRelation, fVerbose ); + if ( fDelete1 ) Abc_NtkDelete( pNtk1 ); + if ( fDelete2 ) Abc_NtkDelete( pNtk2 ); + + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 0; + } + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: inter [-rvh] \n" ); + Abc_Print( -2, "\t derives interpolant of two networks representing onset and offset;\n" ); + Abc_Print( -2, "\t-r : toggle computing interpolant as a relation [default = %s]\n", fRelation? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t \n" ); + Abc_Print( -2, "\t Comments:\n" ); + Abc_Print( -2, "\t \n" ); + Abc_Print( -2, "\t The networks given on the command line should have the same CIs/COs.\n" ); + Abc_Print( -2, "\t If only one network is given on the command line, this network\n" ); + Abc_Print( -2, "\t is assumed to be the offset, while the current network is the onset.\n" ); + Abc_Print( -2, "\t If no network is given on the command line, the current network is\n" ); + Abc_Print( -2, "\t assumed to be the onset and its complement is taken to be the offset.\n" ); + Abc_Print( -2, "\t The resulting interpolant is stored as the current network.\n" ); + Abc_Print( -2, "\t To verify that the interpolant agrees with the onset and the offset,\n" ); + Abc_Print( -2, "\t save it in file \"inter.blif\" and run the following:\n" ); + Abc_Print( -2, "\t (a) \"miter -i ; iprove\"\n" ); + Abc_Print( -2, "\t (b) \"miter -i ; iprove\"\n" ); + Abc_Print( -2, "\t where is the network derived by complementing the\n" ); + Abc_Print( -2, "\t outputs of : \"r ; st -i; w \"\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDouble( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int nFrames; + int fVerbose; + extern Abc_Ntk_t * Abc_NtkDouble( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + nFrames = 50; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + nFrames = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nFrames < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsSopLogic(pNtk) ) + { + Abc_Print( -1, "Only works for logic SOP networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkDouble( pNtk ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 0; + } + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: double [-vh]\n" ); + Abc_Print( -2, "\t puts together two parallel copies of the current network\n" ); +// Abc_Print( -2, "\t-F num : the number of frames to simulate [default = %d]\n", nFrames ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandBb2Wb( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_NtkConvertBb2Wb( char * pFileNameIn, char * pFileNameOut, int fSeq, int fVerbose ); + int c; + int fSeq; + int fVerbose; + // set defaults + fSeq = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "svh" ) ) != EOF ) + { + switch ( c ) + { + case 's': + fSeq ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 2 ) + { + Abc_Print( -1, "Expecting two files names on the command line.\n" ); + goto usage; + } + Abc_NtkConvertBb2Wb( argv[globalUtilOptind], argv[globalUtilOptind+1], fSeq, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: bb2wb [-svh] \n" ); + Abc_Print( -2, "\t replaces black boxes by white boxes with AND functions\n" ); + Abc_Print( -2, "\t (file names should have standard extensions, e.g. \"blif\")\n" ); + Abc_Print( -2, "\t-s : toggle using sequential white boxes [default = %s]\n", fSeq? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : input file with design containing black boxes\n"); + Abc_Print( -2, "\t : output file with design containing white boxes\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandOutdec( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Abc_Ntk_t * Abc_NtkDarOutdec( Abc_Ntk_t * pNtk, int nLits, int fVerbose ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Abc_Ntk_t * pNtkRes; + int c, nLits = 1; + int fVerbose = 0; + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Lvh" ) ) != EOF ) + { + switch ( c ) + { + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + nLits = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLits < 1 || nLits > 2 ) + { + Abc_Print( 1,"Currently, command \"outdec\" works for 1-lit and 2-lit primes only.\n" ); + goto usage; + } + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Only works for strashed networks.\n" ); + return 1; + } + pNtkRes = Abc_NtkDarOutdec( pNtk, nLits, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 0; + } + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: outdec [-Lvh]\n" ); + Abc_Print( -2, "\t performs prime decomposition of the first output\n" ); + Abc_Print( -2, "\t-L num : the number of literals in the primes [default = %d]\n", nLits ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandNodeDup( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern Abc_Ntk_t * Abc_NtkNodeDup( Abc_Ntk_t * pNtk, int nLimit, int fVerbose ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Abc_Ntk_t * pNtkRes; + int c, nLimit = 30; + int fVerbose = 0; + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Nvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Only works for logic networks.\n" ); + return 1; + } + if ( nLimit < 2 ) + { + Abc_Print( -1, "The fanout limit should be more than 1.\n" ); + return 1; + } + pNtkRes = Abc_NtkNodeDup( pNtk, nLimit, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 0; + } + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: nodedup [-Nvh]\n" ); + Abc_Print( -2, "\t duplicates internal nodes with high fanout\n" ); + Abc_Print( -2, "\t-N num : the number of fanouts to start duplication [default = %d]\n", nLimit ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandWrap( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + char * pFileName = NULL, * pFileName2 = NULL; + FILE * pFile = NULL, * pFile2 = NULL; + int c; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 2 ) + { + Abc_Print( 1,"Two file names are expected on the command line.\n" ); + return 0; + } + pFileName = argv[globalUtilOptind]; + pFileName2 = argv[globalUtilOptind+1]; + pFile = fopen( pFileName, "rb" ); + pFile2 = fopen( pFileName2, "wb" ); + if ( pFile && pFile2 ) + { + char Buffer[1000]; + while ( fgets( Buffer, 1000, pFile ) != NULL ) + { + if ( Buffer[strlen(Buffer)-1] == '\n' ) + Buffer[strlen(Buffer)-1] = 0; + if ( Buffer[strlen(Buffer)-1] == '\r' ) + Buffer[strlen(Buffer)-1] = 0; + fprintf( pFile2, " printf(\"%s\\n\");\n", Buffer ); + } + } + if ( pFile ) fclose(pFile); + if ( pFile2 ) fclose(pFile2); + return 0; + +usage: + Abc_Print( -2, "usage: wrap [-h] \n" ); + Abc_Print( -2, "\t wrapping lines\n" ); + Abc_Print( -2, "\t : input text file\n"); + Abc_Print( -2, "\t : output text file\n"); + return 1; + +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTestColor( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_ColorTest(); + Abc_ColorTest(); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandTest( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Gia_Gen2CodeTest(); + extern void Dau_NetworkEnumTest(); + //Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int nCutMax = 1; + int nLeafMax = 4; + int nDivMax = 2; + int nDecMax = 3; + int nNumOnes = 0; + int fNewAlgo = 0; + int fNewOrder = 0; + int fVerbose = 0; + int fVeryVerbose = 0; + int c; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "CKDNMaovwh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nCutMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCutMax < 0 ) + goto usage; + break; + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nLeafMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLeafMax < 0 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + nDivMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nDivMax < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nDecMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nDecMax < 0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + nNumOnes = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nNumOnes < 0 ) + goto usage; + break; + case 'a': + fNewAlgo ^= 1; + break; + case 'o': + fNewOrder ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } +/* + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } +*/ +/* + if ( Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for logic networks.\n" ); + return 1; + } +*/ +/* + if ( Abc_NtkLatchNum(pNtk) == 0 ) + { + Abc_Print( -1, "Only works for sequential networks.\n" ); + return 1; + } +*/ + +/* + if ( pNtk ) + { + extern Abc_Ntk_t * Au_ManPerformTest( Abc_Ntk_t * p, int nCutMax, int nLeafMax, int nDivMax, int nDecMax, int fVerbose, int fVeryVerbose ); + Abc_Ntk_t * pNtkRes = Au_ManPerformTest( pNtk, nCutMax, nLeafMax, nDivMax, nDecMax, fVerbose, fVeryVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 1; + } + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + } +*/ +/* + if ( pNtk ) + { + Aig_Man_t * pAig = Abc_NtkToDar( pNtk, 0, 1 ); + Saig_ManBmcTerSimTestPo( pAig ); + Aig_ManStop( pAig ); + } +*/ +/* + if ( !Abc_NtkIsTopo(pNtk) ) + { + Abc_Print( -1, "Current network is not in a topological order.\n" ); + return 1; + } +*/ +// if ( pNtk ) +// Abc_NtkMakeLegit( pNtk ); + { +// extern void Ifd_ManDsdTest(); +// Ifd_ManDsdTest(); + } +/* + { + extern void Abc_EnumerateCubeStates(); + extern void Abc_EnumerateCubeStatesZdd(); + if ( fNewAlgo ) + Abc_EnumerateCubeStatesZdd(); + else + Abc_EnumerateCubeStates(); + return 0; + } +*/ + { +// extern void Abc_EnumerateFuncs( int nDecMax, int nDivMax, int fVerbose ); +// Abc_EnumerateFuncs( 4, 7, 0 ); + } +/* + if ( fNewAlgo ) + { + extern void Abc_SuppTest( int nOnes, int nVars, int fUseSimple, int fCheck, int fVerbose ); + Abc_SuppTest( nNumOnes, nDecMax, fNewOrder, 0, fVerbose ); + } + else + { + extern void Bmc_EcoMiterTest(); + Bmc_EcoMiterTest(); + } +*/ + + { +// extern void Nf_ManPrepareLibraryTest(); +// Nf_ManPrepareLibraryTest(); +// return 0; + } +/* + if ( pNtk ) + { +// extern Abc_Ntk_t * Abc_NtkBarBufsOnOffTest( Abc_Ntk_t * pNtk ); +// Abc_Ntk_t * pNtkRes = Abc_NtkBarBufsOnOffTest( pNtk ); + extern Abc_Ntk_t * Abc_NtkPcmTest( Abc_Ntk_t * pNtk, int fNewAlgo, int fVerbose ); +// extern Abc_Ntk_t * Abc_NtkPcmTestAig( Abc_Ntk_t * pNtk, int fVerbose ); + Abc_Ntk_t * pNtkRes; +// if ( Abc_NtkIsLogic(pNtk) ) + pNtkRes = Abc_NtkPcmTest( pNtk, fNewAlgo, fVerbose ); +// else +// pNtkRes = Abc_NtkPcmTestAig( pNtk, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 1; + } + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + } +*/ +/* + { + extern void Abc_IsopTestNew(); + Abc_IsopTestNew(); + } +*/ + { +// extern void Cba_PrsReadBlifTest(); +// Cba_PrsReadBlifTest(); + } +// Abc_NtkComputePaths( Abc_FrameReadNtk(pAbc) ); + //Dau_NetworkEnumTest(); + //Extra_SimulationTest( nDivMax, nNumOnes, fNewOrder ); + //Mnist_ExperimentWithScaling( nDecMax ); + //Gyx_ProblemSolveTest(); +/* + { + extern Abc_Ntk_t * Abc_NtkFromArray(); + Abc_Ntk_t * pNtkRes = Abc_NtkFromArray(); + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + } +*/ + //Gia_ManTestProblem(); + //Abc_ReadPlaTest( "resub2.pla" ); + return 0; +usage: + Abc_Print( -2, "usage: test [-CKDNM] [-aovwh] \n" ); + Abc_Print( -2, "\t testbench for new procedures\n" ); + Abc_Print( -2, "\t-C num : the max number of cuts [default = %d]\n", nCutMax ); + Abc_Print( -2, "\t-K num : the max number of leaves [default = %d]\n", nLeafMax ); + Abc_Print( -2, "\t-D num : the max number of divisors [default = %d]\n", nDivMax ); + Abc_Print( -2, "\t-N num : the max number of node inputs [default = %d]\n", nDecMax ); + Abc_Print( -2, "\t-M num : the max number of ones in the vector [default = %d]\n", nNumOnes ); + Abc_Print( -2, "\t-a : toggle using new algorithm [default = %s]\n", fNewAlgo? "yes": "no" ); + Abc_Print( -2, "\t-o : toggle using new ordering [default = %s]\n", fNewOrder? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle printing very verbose information [default = %s]\n", fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandQuaVar( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c, iVar, fUniv, fVerbose, RetValue; + extern int Abc_NtkQuantify( Abc_Ntk_t * pNtk, int fUniv, int iVar, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + iVar = 0; + fUniv = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Iuvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + iVar = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( iVar < 0 ) + goto usage; + break; + case 'u': + fUniv ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum( pNtk ) ) + { + Abc_Print( -1, "This command cannot be applied to an AIG with choice nodes.\n" ); + return 1; + } + + // get the strashed network + pNtkRes = Abc_NtkStrash( pNtk, 0, 1, 0 ); + RetValue = Abc_NtkQuantify( pNtkRes, fUniv, iVar, fVerbose ); + // clean temporary storage for the cofactors + Abc_NtkCleanData( pNtkRes ); + Abc_AigCleanup( (Abc_Aig_t *)pNtkRes->pManFunc ); + // check the result + if ( !RetValue ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: qvar [-I num] [-uvh]\n" ); + Abc_Print( -2, "\t quantifies one variable using the AIG\n" ); + Abc_Print( -2, "\t-I num : the zero-based index of a variable to quantify [default = %d]\n", iVar ); + Abc_Print( -2, "\t-u : toggle universal quantification [default = %s]\n", fUniv? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandQuaRel( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c, iVar, fInputs, fVerbose; + extern Abc_Ntk_t * Abc_NtkTransRel( Abc_Ntk_t * pNtk, int fInputs, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + iVar = 0; + fInputs = 1; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Iqvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + iVar = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( iVar < 0 ) + goto usage; + break; + case 'q': + fInputs ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum( pNtk ) ) + { + Abc_Print( -1, "This command cannot be applied to an AIG with choice nodes.\n" ); + return 1; + } + if ( Abc_NtkIsComb(pNtk) ) + { + Abc_Print( -1, "This command works only for sequential circuits.\n" ); + return 1; + } + + // get the strashed network + if ( !Abc_NtkIsStrash(pNtk) ) + { + pNtk = Abc_NtkStrash( pNtk, 0, 1, 0 ); + pNtkRes = Abc_NtkTransRel( pNtk, fInputs, fVerbose ); + Abc_NtkDelete( pNtk ); + } + else + pNtkRes = Abc_NtkTransRel( pNtk, fInputs, fVerbose ); + // check if the result is available + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: qrel [-qvh]\n" ); + Abc_Print( -2, "\t computes transition relation of the sequential network\n" ); +// Abc_Print( -2, "\t-I num : the zero-based index of a variable to quantify [default = %d]\n", iVar ); + Abc_Print( -2, "\t-q : perform quantification of inputs [default = %s]\n", fInputs? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandQuaReach( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c, nIters, fVerbose; + extern Abc_Ntk_t * Abc_NtkReachability( Abc_Ntk_t * pNtk, int nIters, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + nIters = 256; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Ivh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIters < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum( pNtk ) ) + { + Abc_Print( -1, "This command cannot be applied to an AIG with choice nodes.\n" ); + return 1; + } + if ( !Abc_NtkIsComb(pNtk) ) + { + Abc_Print( -1, "This command works only for combinational transition relations.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for strashed networks.\n" ); + return 1; + } + if ( Abc_NtkPoNum(pNtk) > 1 ) + { + Abc_Print( -1, "The transition relation should have one output.\n" ); + return 1; + } + if ( Abc_NtkPiNum(pNtk) % 2 != 0 ) + { + Abc_Print( -1, "The transition relation should have an even number of inputs.\n" ); + return 1; + } + + pNtkRes = Abc_NtkReachability( pNtk, nIters, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: qreach [-I num] [-vh]\n" ); + Abc_Print( -2, "\t computes unreachable states using AIG-based quantification\n" ); + Abc_Print( -2, "\t assumes that the current network is a transition relation\n" ); + Abc_Print( -2, "\t assumes that the initial state is composed of all zeros\n" ); + Abc_Print( -2, "\t-I num : the number of image computations to perform [default = %d]\n", nIters ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSenseInput( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + Vec_Int_t * vResult; + int c, nConfLim, fVerbose; + + extern Vec_Int_t * Abc_NtkSensitivity( Abc_Ntk_t * pNtk, int nConfLim, int fVerbose ); + // set defaults + nConfLim = 1000; + fVerbose = 1; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Cvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfLim = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfLim < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkGetChoiceNum( pNtk ) ) + { + Abc_Print( -1, "This command cannot be applied to an AIG with choice nodes.\n" ); + return 1; + } + if ( !Abc_NtkIsComb(pNtk) ) + { + Abc_Print( -1, "This command works only for combinational transition relations.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for strashed networks.\n" ); + return 1; + } + if ( Abc_NtkPoNum(pNtk) < 2 ) + { + Abc_Print( -1, "The network should have at least two outputs.\n" ); + return 1; + } + + vResult = Abc_NtkSensitivity( pNtk, nConfLim, fVerbose ); + Vec_IntFree( vResult ); + return 0; + +usage: + Abc_Print( -2, "usage: senseinput [-C num] [-vh]\n" ); + Abc_Print( -2, "\t computes sensitivity of POs to PIs under constraint\n" ); + Abc_Print( -2, "\t constraint should be represented as the last PO\n" ); + Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", nConfLim ); + Abc_Print( -2, "\t-v : toggle printing verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandIStrash( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes, * pNtkTemp; + int c; + extern Abc_Ntk_t * Abc_NtkIvyStrash( Abc_Ntk_t * pNtk ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + pNtkTemp = Abc_NtkStrash( pNtk, 0, 1, 0 ); + pNtkRes = Abc_NtkIvyStrash( pNtkTemp ); + Abc_NtkDelete( pNtkTemp ); + } + else + pNtkRes = Abc_NtkIvyStrash( pNtk ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: istrash [-h]\n" ); + Abc_Print( -2, "\t perform sequential structural hashing\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandICut( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c, nInputs; + extern void Abc_NtkIvyCuts( Abc_Ntk_t * pNtk, int nInputs ); + + // set defaults + nInputs = 5; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Kh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nInputs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nInputs < 0 ) + goto usage; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for strashed networks.\n" ); + return 1; + } + + Abc_NtkIvyCuts( pNtk, nInputs ); + return 0; + +usage: + Abc_Print( -2, "usage: icut [-K num] [-h]\n" ); + Abc_Print( -2, "\t computes sequential cuts of the given size\n" ); + Abc_Print( -2, "\t-K num : the number of cut inputs (2 <= num <= 6) [default = %d]\n", nInputs ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandIRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c, fUpdateLevel, fUseZeroCost, fVerbose; + extern Abc_Ntk_t * Abc_NtkIvyRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeroCost, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + fUpdateLevel = 1; + fUseZeroCost = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lzvh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUpdateLevel ^= 1; + break; + case 'z': + fUseZeroCost ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for strashed networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkIvyRewrite( pNtk, fUpdateLevel, fUseZeroCost, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: irw [-lzvh]\n" ); + Abc_Print( -2, "\t perform combinational AIG rewriting\n" ); + Abc_Print( -2, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + Abc_Print( -2, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeroCost? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDRewrite( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + Dar_RwrPar_t Pars, * pPars = &Pars; + int c; + + extern Abc_Ntk_t * Abc_NtkDRewrite( Abc_Ntk_t * pNtk, Dar_RwrPar_t * pPars ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + Dar_ManDefaultRwrParams( pPars ); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "CNMflzrvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nCutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nCutsMax < 0 ) + goto usage; + break; + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nSubgMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nSubgMax < 0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nMinSaved = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nMinSaved < 0 ) + goto usage; + break; + case 'f': + pPars->fFanout ^= 1; + break; + case 'l': + pPars->fUpdateLevel ^= 1; + break; + case 'z': + pPars->fUseZeros ^= 1; + break; + case 'r': + pPars->fRecycle ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'w': + pPars->fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pPars->fUseZeros ) + pPars->nMinSaved = 0; + if ( pPars->nMinSaved == 0 ) + pPars->fUseZeros = 1; + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for strashed networks.\n" ); + return 1; + } + pNtkRes = Abc_NtkDRewrite( pNtk, pPars ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: drw [-C num] [-NM num] [-lfzrvwh]\n" ); + Abc_Print( -2, "\t performs combinational AIG rewriting\n" ); + Abc_Print( -2, "\t-C num : the max number of cuts at a node [default = %d]\n", pPars->nCutsMax ); + Abc_Print( -2, "\t-N num : the max number of subgraphs tried [default = %d]\n", pPars->nSubgMax ); + Abc_Print( -2, "\t-M num : the min number of nodes saved after one step (0 <= num) [default = %d]\n", pPars->nMinSaved ); + Abc_Print( -2, "\t-l : toggle preserving the number of levels [default = %s]\n", pPars->fUpdateLevel? "yes": "no" ); + Abc_Print( -2, "\t-f : toggle representing fanouts [default = %s]\n", pPars->fFanout? "yes": "no" ); + Abc_Print( -2, "\t-z : toggle using zero-cost replacements [default = %s]\n", pPars->fUseZeros? "yes": "no" ); + Abc_Print( -2, "\t-r : toggle using cut recycling [default = %s]\n", pPars->fRecycle? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle very verbose printout [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDRefactor( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + Dar_RefPar_t Pars, * pPars = &Pars; + int c; + + extern Abc_Ntk_t * Abc_NtkDRefactor( Abc_Ntk_t * pNtk, Dar_RefPar_t * pPars ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + Dar_ManDefaultRefParams( pPars ); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "MKCelzvwh" ) ) != EOF ) + { + switch ( c ) + { + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nMffcMin = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nMffcMin < 0 ) + goto usage; + break; + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nLeafMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nLeafMax < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nCutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nCutsMax < 0 ) + goto usage; + break; + case 'e': + pPars->fExtend ^= 1; + break; + case 'l': + pPars->fUpdateLevel ^= 1; + break; + case 'z': + pPars->fUseZeros ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'w': + pPars->fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for strashed networks.\n" ); + return 1; + } + if ( pPars->nLeafMax < 4 || pPars->nLeafMax > 15 ) + { + Abc_Print( -1, "This command only works for cut sizes 4 <= K <= 15.\n" ); + return 1; + } + pNtkRes = Abc_NtkDRefactor( pNtk, pPars ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: drf [-M num] [-K num] [-C num] [-elzvwh]\n" ); + Abc_Print( -2, "\t performs combinational AIG refactoring\n" ); + Abc_Print( -2, "\t-M num : the min MFFC size to attempt refactoring [default = %d]\n", pPars->nMffcMin ); + Abc_Print( -2, "\t-K num : the max number of cuts leaves [default = %d]\n", pPars->nLeafMax ); + Abc_Print( -2, "\t-C num : the max number of cuts to try at a node [default = %d]\n", pPars->nCutsMax ); + Abc_Print( -2, "\t-e : toggle extending tbe cut below MFFC [default = %s]\n", pPars->fExtend? "yes": "no" ); + Abc_Print( -2, "\t-l : toggle preserving the number of levels [default = %s]\n", pPars->fUpdateLevel? "yes": "no" ); + Abc_Print( -2, "\t-z : toggle using zero-cost replacements [default = %s]\n", pPars->fUseZeros? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : toggle very verbose printout [default = %s]\n", pPars->fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDc2( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int fBalance, fVerbose, fUpdateLevel, fFanout, fPower, c; + + extern Abc_Ntk_t * Abc_NtkDC2( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fFanout, int fPower, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + fBalance = 0; + fVerbose = 0; + fUpdateLevel = 0; + fFanout = 1; + fPower = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "blfpvh" ) ) != EOF ) + { + switch ( c ) + { + case 'b': + fBalance ^= 1; + break; + case 'l': + fUpdateLevel ^= 1; + break; + case 'f': + fFanout ^= 1; + break; + case 'p': + fPower ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for strashed networks.\n" ); + return 1; + } + pNtkRes = Abc_NtkDC2( pNtk, fBalance, fUpdateLevel, fFanout, fPower, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: dc2 [-blfpvh]\n" ); + Abc_Print( -2, "\t performs combinational AIG optimization\n" ); + Abc_Print( -2, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" ); + Abc_Print( -2, "\t-l : toggle updating level [default = %s]\n", fUpdateLevel? "yes": "no" ); + Abc_Print( -2, "\t-f : toggle representing fanouts [default = %s]\n", fFanout? "yes": "no" ); + Abc_Print( -2, "\t-p : toggle power-aware rewriting [default = %s]\n", fPower? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDChoice( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int fBalance, fVerbose, fUpdateLevel, fConstruct, c; + int nConfMax, nLevelMax; + + extern Abc_Ntk_t * Abc_NtkDChoice( Abc_Ntk_t * pNtk, int fBalance, int fUpdateLevel, int fConstruct, int nConfMax, int nLevelMax, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + fBalance = 1; + fUpdateLevel = 1; + fConstruct = 0; + nConfMax = 1000; + nLevelMax = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "CLblcvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfMax < 0 ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + nLevelMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLevelMax < 0 ) + goto usage; + break; + case 'b': + fBalance ^= 1; + break; + case 'l': + fUpdateLevel ^= 1; + break; + case 'c': + fConstruct ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for strashed networks.\n" ); + return 1; + } + pNtkRes = Abc_NtkDChoice( pNtk, fBalance, fUpdateLevel, fConstruct, nConfMax, nLevelMax, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: dchoice [-C num] [-L num] [-blcvh]\n" ); + Abc_Print( -2, "\t performs partitioned choicing using new AIG package\n" ); + Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", nConfMax ); + Abc_Print( -2, "\t-L num : the max level of nodes to consider (0 = not used) [default = %d]\n", nLevelMax ); + Abc_Print( -2, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" ); + Abc_Print( -2, "\t-l : toggle updating level [default = %s]\n", fUpdateLevel? "yes": "no" ); + Abc_Print( -2, "\t-c : toggle constructive computation of choices [default = %s]\n", fConstruct? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDch( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Dch_Pars_t Pars, * pPars = &Pars; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + extern Abc_Ntk_t * Abc_NtkDch( Abc_Ntk_t * pNtk, Dch_Pars_t * pPars ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + Dch_ManSetDefaultParams( pPars ); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "WCSsptgcfrxvh" ) ) != EOF ) + { + switch ( c ) + { + case 'W': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-W\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nWords = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nWords < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nBTLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nBTLimit < 0 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + pPars->nSatVarMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nSatVarMax < 0 ) + goto usage; + break; + case 's': + pPars->fSynthesis ^= 1; + break; + case 'p': + pPars->fPower ^= 1; + break; + case 't': + pPars->fSimulateTfo ^= 1; + break; + case 'g': + pPars->fUseGia ^= 1; + break; + case 'c': + pPars->fUseCSat ^= 1; + break; + case 'f': + pPars->fLightSynth ^= 1; + break; + case 'r': + pPars->fSkipRedSupp ^= 1; + break; + case 'x': + pPars->fUseNew ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for strashed networks.\n" ); + return 1; + } + pNtkRes = Abc_NtkDch( pNtk, pPars ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: dch [-WCS num] [-sptgcfrxvh]\n" ); + Abc_Print( -2, "\t computes structural choices using a new approach\n" ); + Abc_Print( -2, "\t-W num : the max number of simulation words [default = %d]\n", pPars->nWords ); + Abc_Print( -2, "\t-C num : the max number of conflicts at a node [default = %d]\n", pPars->nBTLimit ); + Abc_Print( -2, "\t-S num : the max number of SAT variables [default = %d]\n", pPars->nSatVarMax ); + Abc_Print( -2, "\t-s : toggle synthesizing three snapshots [default = %s]\n", pPars->fSynthesis? "yes": "no" ); + Abc_Print( -2, "\t-p : toggle power-aware rewriting [default = %s]\n", pPars->fPower? "yes": "no" ); + Abc_Print( -2, "\t-t : toggle simulation of the TFO classes [default = %s]\n", pPars->fSimulateTfo? "yes": "no" ); + Abc_Print( -2, "\t-g : toggle using GIA to prove equivalences [default = %s]\n", pPars->fUseGia? "yes": "no" ); + Abc_Print( -2, "\t-c : toggle using circuit-based SAT vs. MiniSat [default = %s]\n", pPars->fUseCSat? "yes": "no" ); + Abc_Print( -2, "\t-f : toggle using faster logic synthesis [default = %s]\n", pPars->fLightSynth? "yes": "no" ); + Abc_Print( -2, "\t-r : toggle skipping choices with redundant support [default = %s]\n", pPars->fSkipRedSupp? "yes": "no" ); + Abc_Print( -2, "\t-x : toggle using new choice computation [default = %s]\n", pPars->fUseNew? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", pPars->fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDrwsat( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int fBalance, fVerbose, c; + + extern Abc_Ntk_t * Abc_NtkDrwsat( Abc_Ntk_t * pNtk, int fBalance, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + fBalance = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "bvh" ) ) != EOF ) + { + switch ( c ) + { + case 'b': + fBalance ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for strashed networks.\n" ); + return 1; + } + pNtkRes = Abc_NtkDrwsat( pNtk, fBalance, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: drwsat [-bvh]\n" ); + Abc_Print( -2, "\t performs combinational AIG optimization for SAT\n" ); + Abc_Print( -2, "\t-b : toggle internal balancing [default = %s]\n", fBalance? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandIRewriteSeq( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c, fUpdateLevel, fUseZeroCost, fVerbose; + extern Abc_Ntk_t * Abc_NtkIvyRewriteSeq( Abc_Ntk_t * pNtk, int fUseZeroCost, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + fUpdateLevel = 0; + fUseZeroCost = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lzvh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUpdateLevel ^= 1; + break; + case 'z': + fUseZeroCost ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for strashed networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkIvyRewriteSeq( pNtk, fUseZeroCost, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: irws [-zvh]\n" ); + Abc_Print( -2, "\t perform sequential AIG rewriting\n" ); +// Abc_Print( -2, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + Abc_Print( -2, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeroCost? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandIResyn( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c, fUpdateLevel, fVerbose; + extern Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + fUpdateLevel = 1; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "lzvh" ) ) != EOF ) + { + switch ( c ) + { + case 'l': + fUpdateLevel ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for strashed networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkIvyResyn( pNtk, fUpdateLevel, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: iresyn [-lvh]\n" ); + Abc_Print( -2, "\t performs combinational resynthesis\n" ); + Abc_Print( -2, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandISat( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c, fUpdateLevel, fVerbose; + int nConfLimit; + + extern Abc_Ntk_t * Abc_NtkIvySat( Abc_Ntk_t * pNtk, int nConfLimit, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + nConfLimit = 100000; + fUpdateLevel = 1; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Clzvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfLimit < 0 ) + goto usage; + break; + case 'l': + fUpdateLevel ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for strashed networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkIvySat( pNtk, nConfLimit, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: isat [-C num] [-vh]\n" ); + Abc_Print( -2, "\t tries to prove the miter constant 0\n" ); + Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); +// Abc_Print( -2, "\t-l : toggle preserving the number of levels [default = %s]\n", fUpdateLevel? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandIFraig( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c, fProve, fVerbose, fDoSparse; + int nConfLimit; + int nPartSize; + int nLevelMax; + + extern Abc_Ntk_t * Abc_NtkIvyFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fVerbose ); + extern Abc_Ntk_t * Abc_NtkDarFraigPart( Abc_Ntk_t * pNtk, int nPartSize, int nConfLimit, int nLevelMax, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + nPartSize = 0; + nLevelMax = 0; + nConfLimit = 100; + fDoSparse = 1; + fProve = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "PCLspvh" ) ) != EOF ) + { + switch ( c ) + { + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + nPartSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nPartSize < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfLimit < 0 ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by an integer.\n" ); + goto usage; + } + nLevelMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLevelMax < 0 ) + goto usage; + break; + case 's': + fDoSparse ^= 1; + break; + case 'p': + fProve ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for strashed networks.\n" ); + return 1; + } + + if ( nPartSize > 0 ) + pNtkRes = Abc_NtkDarFraigPart( pNtk, nPartSize, nConfLimit, nLevelMax, fVerbose ); + else + pNtkRes = Abc_NtkIvyFraig( pNtk, nConfLimit, fDoSparse, fProve, 0, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: ifraig [-P num] [-C num] [-L num] [-spvh]\n" ); + Abc_Print( -2, "\t performs fraiging using a new method\n" ); + Abc_Print( -2, "\t-P num : partition size (0 = partitioning is not used) [default = %d]\n", nPartSize ); + Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); + Abc_Print( -2, "\t-L num : limit on node level to fraig (0 = fraig all nodes) [default = %d]\n", nLevelMax ); + Abc_Print( -2, "\t-s : toggle considering sparse functions [default = %s]\n", fDoSparse? "yes": "no" ); + Abc_Print( -2, "\t-p : toggle proving the miter outputs [default = %s]\n", fProve? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDFraig( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c, nConfLimit, fDoSparse, fProve, fSpeculate, fChoicing, fVerbose; + + extern Abc_Ntk_t * Abc_NtkDarFraig( Abc_Ntk_t * pNtk, int nConfLimit, int fDoSparse, int fProve, int fTransfer, int fSpeculate, int fChoicing, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + nConfLimit = 100; + fDoSparse = 1; + fProve = 0; + fSpeculate = 0; + fChoicing = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Csprcvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfLimit < 0 ) + goto usage; + break; + case 's': + fDoSparse ^= 1; + break; + case 'p': + fProve ^= 1; + break; + case 'r': + fSpeculate ^= 1; + break; + case 'c': + fChoicing ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for strashed networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkDarFraig( pNtk, nConfLimit, fDoSparse, fProve, 0, fSpeculate, fChoicing, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: dfraig [-C num] [-sprcvh]\n" ); + Abc_Print( -2, "\t performs fraiging using a new method\n" ); + Abc_Print( -2, "\t-C num : limit on the number of conflicts [default = %d]\n", nConfLimit ); + Abc_Print( -2, "\t-s : toggle considering sparse functions [default = %s]\n", fDoSparse? "yes": "no" ); + Abc_Print( -2, "\t-p : toggle proving the miter outputs [default = %s]\n", fProve? "yes": "no" ); + Abc_Print( -2, "\t-r : toggle speculative reduction [default = %s]\n", fSpeculate? "yes": "no" ); + Abc_Print( -2, "\t-c : toggle accumulation of choices [default = %s]\n", fChoicing? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandCSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c, nCutsMax, nLeafMax, fVerbose; + + extern Abc_Ntk_t * Abc_NtkCSweep( Abc_Ntk_t * pNtk, int nCutsMax, int nLeafMax, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + nCutsMax = 8; + nLeafMax = 6; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "CKvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nCutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCutsMax < 0 ) + goto usage; + break; + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nLeafMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nLeafMax < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( nCutsMax < 2 ) + { + Abc_Print( -1, "The number of cuts cannot be less than 2.\n" ); + return 1; + } + + if ( nLeafMax < 3 || nLeafMax > 16 ) + { + Abc_Print( -1, "The number of leaves is infeasible.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for strashed networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkCSweep( pNtk, nCutsMax, nLeafMax, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: csweep [-C num] [-K num] [-vh]\n" ); + Abc_Print( -2, "\t performs cut sweeping using a new method\n" ); + Abc_Print( -2, "\t-C num : limit on the number of cuts (C >= 2) [default = %d]\n", nCutsMax ); + Abc_Print( -2, "\t-K num : limit on the cut size (3 <= K <= 16) [default = %d]\n", nLeafMax ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandIProve( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Prove_Params_t Params, * pParams = &Params; + Abc_Ntk_t * pNtk, * pNtkTemp; + int c, RetValue, iOut = -1; + char * pLogFileName = NULL; + abctime clk; + + extern int Abc_NtkIvyProve( Abc_Ntk_t ** ppNtk, void * pPars ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + Prove_ParamsSetDefault( pParams ); + pParams->fUseRewriting = 1; + pParams->fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NCFGMILrfbvh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nItersMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nItersMax < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nMiteringLimitStart = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nMiteringLimitStart < 0 ) + goto usage; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nFraigingLimitStart = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nFraigingLimitStart < 0 ) + goto usage; + break; + case 'G': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-G\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nFraigingLimitMulti = (float)atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nFraigingLimitMulti < 0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nMiteringLimitLast = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nMiteringLimitLast < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nTotalInspectLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nTotalInspectLimit < 0 ) + goto usage; + break; + case 'L': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" ); + goto usage; + } + pLogFileName = argv[globalUtilOptind]; + globalUtilOptind++; + break; + case 'r': + pParams->fUseRewriting ^= 1; + break; + case 'f': + pParams->fUseFraiging ^= 1; + break; + case 'b': + pParams->fUseBdds ^= 1; + break; + case 'v': + pParams->fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( Abc_NtkLatchNum(pNtk) > 0 ) + { + Abc_Print( -1, "The network has registers. Use \"dprove\".\n" ); + return 1; + } + + clk = Abc_Clock(); + + if ( Abc_NtkIsStrash(pNtk) ) + pNtkTemp = Abc_NtkDup( pNtk ); + else + pNtkTemp = Abc_NtkStrash( pNtk, 0, 0, 0 ); + + RetValue = Abc_NtkIvyProve( &pNtkTemp, pParams ); + + // verify that the pattern is correct + if ( RetValue == 0 ) + { + Abc_Obj_t * pObj; + int i; + int * pSimInfo = Abc_NtkVerifySimulatePattern( pNtk, pNtkTemp->pModel ); + Abc_NtkForEachCo( pNtk, pObj, i ) + if ( pSimInfo[i] == 1 ) + { + iOut = i; + break; + } + if ( i == Abc_NtkCoNum(pNtk) ) + Abc_Print( 1, "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" ); + ABC_FREE( pSimInfo ); + } + pAbc->Status = RetValue; + if ( RetValue == -1 ) + Abc_Print( 1, "UNDECIDED " ); + else if ( RetValue == 0 ) + Abc_Print( 1, "SATISFIABLE (output = %d) ", iOut ); + else + Abc_Print( 1, "UNSATISFIABLE " ); + //Abc_Print( -1, "\n" ); + + Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkTemp ); + // update counter example + if ( RetValue == 0 && Abc_NtkLatchNum(pNtkTemp) == 0 ) + { + Abc_Cex_t * pCex = Abc_CexDeriveFromCombModel( pNtkTemp->pModel, Abc_NtkPiNum(pNtkTemp), 0, iOut ); + Abc_FrameReplaceCex( pAbc, &pCex ); + } + if ( pLogFileName ) + Abc_NtkWriteLogFile( pLogFileName, pAbc->pCex, pAbc->Status, pAbc->nFrames, "iprove" ); + return 0; + +usage: + Abc_Print( -2, "usage: iprove [-NCFGMI num] [-L file] [-rfbvh]\n" ); + Abc_Print( -2, "\t performs CEC using a new method\n" ); + Abc_Print( -2, "\t-N num : max number of iterations [default = %d]\n", pParams->nItersMax ); + Abc_Print( -2, "\t-C num : max starting number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitStart ); + Abc_Print( -2, "\t-F num : max starting number of conflicts in fraiging [default = %d]\n", pParams->nFraigingLimitStart ); + Abc_Print( -2, "\t-G num : multiplicative coefficient for fraiging [default = %d]\n", (int)pParams->nFraigingLimitMulti ); + Abc_Print( -2, "\t-M num : max last-gasp number of conflicts in mitering [default = %d]\n", pParams->nMiteringLimitLast ); + Abc_Print( -2, "\t-I num : max number of clause inspections in all SAT calls [default = %d]\n", (int)pParams->nTotalInspectLimit ); + Abc_Print( -2, "\t-L file: the log file name [default = %s]\n", pLogFileName ? pLogFileName : "no logging" ); + Abc_Print( -2, "\t-r : toggle the use of rewriting [default = %s]\n", pParams->fUseRewriting? "yes": "no" ); + Abc_Print( -2, "\t-f : toggle the use of FRAIGing [default = %s]\n", pParams->fUseFraiging? "yes": "no" ); + Abc_Print( -2, "\t-b : toggle the use of BDDs [default = %s]\n", pParams->fUseBdds? "yes": "no" ); + Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", pParams->fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +/* +int Abc_CommandHaig( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + FILE * stdout, * pErr; + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int nIters; + int nSteps; + int fRetimingOnly; + int fAddBugs; + int fUseCnf; + int fVerbose; + + extern Abc_Ntk_t * Abc_NtkDarHaigRecord( Abc_Ntk_t * pNtk, int nIters, int nSteps, int fRetimingOnly, int fAddBugs, int fUseCnf, int fVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + + + + // set defaults + nIters = 3; + nSteps = 3000; + fRetimingOnly = 0; + fAddBugs = 0; + fUseCnf = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ISrbcvh" ) ) != EOF ) + { + switch ( c ) + { + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by a positive integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIters < 0 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by a positive integer.\n" ); + goto usage; + } + nSteps = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nSteps < 0 ) + goto usage; + break; + case 'r': + fRetimingOnly ^= 1; + break; + case 'b': + fAddBugs ^= 1; + break; + case 'c': + fUseCnf ^= 1; + break; + case 'v': + fUseCnf ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for strashed networks.\n" ); + return 1; + } + + pNtkRes = Abc_NtkDarHaigRecord( pNtk, nIters, nSteps, fRetimingOnly, fAddBugs, fUseCnf, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Command has failed.\n" ); + return 0; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: haig [-IS num] [-rbcvh]\n" ); + Abc_Print( -2, "\t run a few rounds of comb+seq synthesis to test HAIG recording\n" ); + Abc_Print( -2, "\t the current network is set to be the result of synthesis performed\n" ); + Abc_Print( -2, "\t (this network can be verified using command \"dsec\")\n" ); + Abc_Print( -2, "\t HAIG is written out into the file \"haig.blif\"\n" ); + Abc_Print( -2, "\t (this HAIG can be proved using \"r haig.blif; st; dprove -abc -F 16\")\n" ); + Abc_Print( -2, "\t-I num : the number of rounds of comb+seq synthesis [default = %d]\n", nIters ); + Abc_Print( -2, "\t-S num : the number of forward retiming moves performed [default = %d]\n", nSteps ); + Abc_Print( -2, "\t-r : toggle the use of retiming only [default = %s]\n", fRetimingOnly? "yes": "no" ); + Abc_Print( -2, "\t-b : toggle bug insertion [default = %s]\n", fAddBugs? "yes": "no" ); + Abc_Print( -2, "\t-c : enable CNF-based proof (no speculative reduction) [default = %s]\n", fUseCnf? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} +*/ + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandQbf( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int nPars; + int nIters; + int fDumpCnf; + int fVerbose; + + extern void Abc_NtkQbf( Abc_Ntk_t * pNtk, int nPars, int nIters, int fDumpCnf, int fVerbose ); + // set defaults + nPars = -1; + nIters = 500; + fDumpCnf = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "PIdvh" ) ) != EOF ) + { + switch ( c ) + { + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + nPars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nPars < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIters < 0 ) + goto usage; + break; + case 'd': + fDumpCnf ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsComb(pNtk) ) + { + Abc_Print( -1, "Works only for combinational networks.\n" ); + return 1; + } + if ( Abc_NtkPoNum(pNtk) != 1 ) + { + Abc_Print( -1, "The miter should have one primary output.\n" ); + return 1; + } + if ( !(nPars > 0 && nPars < Abc_NtkPiNum(pNtk)) ) + { + Abc_Print( -1, "The number of parameter variables is invalid (should be > 0 and < PI num).\n" ); + return 1; + } + if ( Abc_NtkIsStrash(pNtk) ) + Abc_NtkQbf( pNtk, nPars, nIters, fDumpCnf, fVerbose ); + else + { + pNtk = Abc_NtkStrash( pNtk, 0, 1, 0 ); + Abc_NtkQbf( pNtk, nPars, nIters, fDumpCnf, fVerbose ); + Abc_NtkDelete( pNtk ); + } + return 0; + +usage: + Abc_Print( -2, "usage: qbf [-PI num] [-dvh]\n" ); + Abc_Print( -2, "\t solves QBF problem EpVxM(p,x)\n" ); + Abc_Print( -2, "\t-P num : number of parameters p (should be the first PIs) [default = %d]\n", nPars ); + Abc_Print( -2, "\t-I num : quit after the given iteration even if unsolved [default = %d]\n", nIters ); + Abc_Print( -2, "\t-d : toggle dumping QDIMACS file instead of solving [default = %s]\n", fDumpCnf? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t\n" ); + Abc_Print( -2, "\t Consider specification of the two-input XOR and its implementation in the form of a 4:1 MUX:\n\n" ); + Abc_Print( -2, "\t > # file s.blif\n" ); + Abc_Print( -2, "\t > .model xor2\n" ); + Abc_Print( -2, "\t > .inputs d0 d1 d2 d3 a b\n" ); + Abc_Print( -2, "\t > .outputs F\n" ); + Abc_Print( -2, "\t > .names a b F\n" ); + Abc_Print( -2, "\t > 01 1\n" ); + Abc_Print( -2, "\t > 10 1\n" ); + Abc_Print( -2, "\t > .end\n\n" ); + Abc_Print( -2, "\t > # file i.blif\n" ); + Abc_Print( -2, "\t > .model mux21\n" ); + Abc_Print( -2, "\t > .inputs d0 d1 d2 d3 a b\n" ); + Abc_Print( -2, "\t > .outputs F\n" ); + Abc_Print( -2, "\t > .names d0 d1 d2 d3 a b F\n" ); + Abc_Print( -2, "\t > 1---00 1\n" ); + Abc_Print( -2, "\t > -1--10 1\n" ); + Abc_Print( -2, "\t > --1-01 1\n" ); + Abc_Print( -2, "\t > ---111 1\n" ); + Abc_Print( -2, "\t > .end\n\n" ); + Abc_Print( -2, "\t The following run shows how to assign data inputs to the MUX (the first 4 inputs of the miter) to get the XOR:\n\n" ); + Abc_Print( -2, "\t > abc 51> miter -n i.blif s.blif; st -i; ps\n" ); + Abc_Print( -2, "\t > i_s_miter: i/o = 6/ 1 lat = 0 and = 15 lev = 6\n\n" ); + Abc_Print( -2, "\t > abc 53> qbf -P 4\n" ); + Abc_Print( -2, "\t > Parameters: 0110 Statistics: 0=2 1=2\n" ); + Abc_Print( -2, "\t > Solved after 1 iterations. Total runtime = 0.00 sec\n\n" ); + Abc_Print( -2, "\t > abc 53> &get; &qbf -P 4\n" ); + Abc_Print( -2, "\t > Parameters: 0110 Statistics: 0=2 1=2\n" ); + Abc_Print( -2, "\t > The problem is SAT after 2 iterations. Time = 0.00 sec\n\n" ); + Abc_Print( -2, "\t What we synthesized is the truth table of the XOR gate!\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandNpnLoad( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Npn_ManLoad( char * pFileName ); + char * pFileName; + int c; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + pFileName = argv[globalUtilOptind]; + Npn_ManLoad( pFileName ); + return 0; + +usage: + Abc_Print( -2, "usage: npnload \n" ); + Abc_Print( -2, "\t loads previously saved 6-input function library from file\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandNpnSave( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Npn_ManSave( char * pFileName ); + char * pFileName; + int c; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 1 ) + goto usage; + pFileName = argv[globalUtilOptind]; + Npn_ManSave( pFileName ); + return 0; + +usage: + Abc_Print( -2, "usage: npnsave \n" ); + Abc_Print( -2, "\t saves current 6-input function library into file\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSendAig( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ +// const int BRIDGE_NETLIST = 106; +// const int BRIDGE_ABS_NETLIST = 107; + + int c, fAndSpace = 1, fAbsNetlist = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ah" ) ) != EOF ) + { + switch ( c ) + { + case 'a': + fAndSpace ^= 1; + break; + case 'b': + fAbsNetlist ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_FrameIsBridgeMode() ) + { + Abc_Print( -1, "The bridge mode is not available.\n" ); + return 1; + } + if ( fAndSpace ) + { + if ( pAbc->pGia == NULL ) + { + Abc_Print( -1, "There is no AIG in the &-space.\n" ); + return 1; + } + Gia_ManToBridgeAbsNetlist( stdout, pAbc->pGia, fAbsNetlist ? BRIDGE_ABS_NETLIST : BRIDGE_NETLIST ); + } + else + { + Aig_Man_t * pAig; + Gia_Man_t * pGia; + if ( pAbc->pNtkCur == NULL ) + { + Abc_Print( -1, "There is no network in the main-space.\n" ); + return 1; + } + if ( !Abc_NtkIsStrash(pAbc->pNtkCur) ) + { + Abc_Print( -1, "The main-space network is not an AIG.\n" ); + return 1; + } + pAig = Abc_NtkToDar( pAbc->pNtkCur, 0, 1 ); + pGia = Gia_ManFromAig( pAig ); + Aig_ManStop( pAig ); + Gia_ManToBridgeAbsNetlist( stdout, pGia, fAbsNetlist ? BRIDGE_ABS_NETLIST : BRIDGE_NETLIST ); + Gia_ManStop( pGia ); + } + return 0; + +usage: + Abc_Print( -2, "usage: send_aig -a\n" ); + Abc_Print( -2, "\t sends current AIG to the bridge\n" ); + Abc_Print( -2, "\t-a : toggle sending AIG from &-space [default = %s]\n", fAndSpace? "yes": "no" ); + Abc_Print( -2, "\t-b : toggle sending netlist tagged as \"abstraction\". [default = %s]\n", fAbsNetlist? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandSendStatus( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern int Gia_ManToBridgeResult( FILE * pFile, int Result, Abc_Cex_t * pCex, int iPoProved ); + int c; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_FrameIsBridgeMode() ) + { + Abc_Print( -1, "The bridge mode is not available.\n" ); + return 1; + } + if ( pAbc->Status == 0 && pAbc->pCex == NULL ) + { + Abc_Print( -1, "Status is \"sat\", but current CEX is not available.\n" ); + return 1; + } + Gia_ManToBridgeResult( stdout, pAbc->Status, pAbc->pCex, 0 ); + return 0; + +usage: + Abc_Print( -2, "usage: send_status\n" ); + Abc_Print( -2, "\t sends current status to the bridge\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandBackup( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( pAbc->pNtkBackup ) + Abc_NtkDelete( pAbc->pNtkBackup ); + pAbc->pNtkBackup = Abc_NtkDup( pNtk ); + return 0; + +usage: + Abc_Print( -2, "usage: backup [-h]\n" ); + Abc_Print( -2, "\t backs up the current network\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} +int Abc_CommandRestore( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + int c; + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pAbc->pNtkBackup == NULL ) + { + Abc_Print( -1, "There is no backup network.\n" ); + return 1; + } + Abc_FrameReplaceCurrentNetwork( pAbc, Abc_NtkDup(pAbc->pNtkBackup) ); + pAbc->nFrames = -1; + pAbc->Status = -1; + return 0; + +usage: + Abc_Print( -2, "usage: restore [-h]\n" ); + Abc_Print( -2, "\t restores the current network\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMinisat( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ +#ifdef USE_MINISAT22 + extern int MainSat(int argc, char** argv); + MainSat( argc, argv ); +#else + printf( "This command is currently disabled.\n" ); +#endif + return 1; +} +int Abc_CommandMinisimp( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ +#ifdef USE_MINISAT22 + extern int MainSimp(int argc, char** argv); + MainSimp( argc, argv ); +#else + printf( "This command is currently disabled.\n" ); +#endif + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFraig( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + char Buffer[100]; + Fraig_Params_t Params, * pParams = &Params; + Abc_Ntk_t * pNtk, * pNtkRes; + int fAllNodes; + int fExdc; + int c; + int fPartition = 0; + extern void Abc_NtkFraigPartitionedTime( Abc_Ntk_t * pNtk, void * pParams ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + fExdc = 0; + fAllNodes = 0; + memset( pParams, 0, sizeof(Fraig_Params_t) ); + pParams->nPatsRand = 2048; // the number of words of random simulation info + pParams->nPatsDyna = 2048; // the number of words of dynamic simulation info + pParams->nBTLimit = 100; // the max number of backtracks to perform + pParams->fFuncRed = 1; // performs only one level hashing + pParams->fFeedBack = 1; // enables solver feedback + pParams->fDist1Pats = 1; // enables distance-1 patterns + pParams->fDoSparse = 1; // performs equiv tests for sparse functions + pParams->fChoicing = 0; // enables recording structural choices + pParams->fTryProve = 0; // tries to solve the final miter + pParams->fVerbose = 0; // the verbosiness flag + pParams->fVerboseP = 0; // the verbosiness flag + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "RDCrscptvaeh" ) ) != EOF ) + { + switch ( c ) + { + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nPatsRand = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nPatsRand < 0 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nPatsDyna = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nPatsDyna < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + pParams->nBTLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pParams->nBTLimit < 0 ) + goto usage; + break; + + case 'r': + pParams->fFuncRed ^= 1; + break; + case 's': + pParams->fDoSparse ^= 1; + break; + case 'c': + pParams->fChoicing ^= 1; + break; + case 'p': + pParams->fTryProve ^= 1; + break; + case 'v': + pParams->fVerbose ^= 1; + break; + case 't': + fPartition ^= 1; + break; + case 'a': + fAllNodes ^= 1; + break; + case 'e': + fExdc ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Can only fraig a logic network or an AIG.\n" ); + return 1; + } + + // report the proof + pParams->fVerboseP = pParams->fTryProve; + + // get the new network + if ( fPartition ) + { + pNtkRes = Abc_NtkDup( pNtk ); + if ( Abc_NtkIsStrash(pNtk) ) + Abc_NtkFraigPartitionedTime( pNtk, &Params ); + else + { + pNtk = Abc_NtkStrash( pNtk, fAllNodes, !fAllNodes, 0 ); + Abc_NtkFraigPartitionedTime( pNtk, &Params ); + Abc_NtkDelete( pNtk ); + } + } + else + { + if ( Abc_NtkIsStrash(pNtk) ) + pNtkRes = Abc_NtkFraig( pNtk, &Params, fAllNodes, fExdc ); + else + { + pNtk = Abc_NtkStrash( pNtk, fAllNodes, !fAllNodes, 0 ); + pNtkRes = Abc_NtkFraig( pNtk, &Params, fAllNodes, fExdc ); + Abc_NtkDelete( pNtk ); + } + } + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Fraiging has failed.\n" ); + return 1; + } + + if ( pParams->fTryProve ) // report the result + Abc_NtkMiterReport( pNtkRes ); + + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + sprintf(Buffer, "%d", pParams->nBTLimit ); + Abc_Print( -2, "usage: fraig [-R num] [-D num] [-C num] [-rscpvtah]\n" ); + Abc_Print( -2, "\t transforms a logic network into a functionally reduced AIG\n" ); + Abc_Print( -2, "\t (known bugs: takes an UNSAT miter and returns a SAT one)\n"); + Abc_Print( -2, "\t (there are newer fraiging commands, \"ifraig\" and \"dfraig\")\n" ); + Abc_Print( -2, "\t-R num : number of random patterns (127 < num < 32769) [default = %d]\n", pParams->nPatsRand ); + Abc_Print( -2, "\t-D num : number of systematic patterns (127 < num < 32769) [default = %d]\n", pParams->nPatsDyna ); + Abc_Print( -2, "\t-C num : number of backtracks for one SAT problem [default = %s]\n", pParams->nBTLimit==-1? "infinity" : Buffer ); + Abc_Print( -2, "\t-r : toggle functional reduction [default = %s]\n", pParams->fFuncRed? "yes": "no" ); + Abc_Print( -2, "\t-s : toggle considering sparse functions [default = %s]\n", pParams->fDoSparse? "yes": "no" ); + Abc_Print( -2, "\t-c : toggle accumulation of choices [default = %s]\n", pParams->fChoicing? "yes": "no" ); + Abc_Print( -2, "\t-p : toggle proving the miter outputs [default = %s]\n", pParams->fTryProve? "yes": "no" ); + Abc_Print( -2, "\t-v : toggle verbose output [default = %s]\n", pParams->fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-e : toggle functional sweeping using EXDC [default = %s]\n", fExdc? "yes": "no" ); + Abc_Print( -2, "\t-a : toggle between all nodes and DFS nodes [default = %s]\n", fAllNodes? "all": "dfs" ); + Abc_Print( -2, "\t-t : toggle using partitioned representation [default = %s]\n", fPartition? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFraigTrust( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int fDuplicate; + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + fDuplicate = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'd': + fDuplicate ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkFraigTrust( pNtk ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Fraiging in the trust mode has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: fraig_trust [-h]\n" ); + Abc_Print( -2, "\t transforms the current network into an AIG assuming it is FRAIG with choices\n" ); +// Abc_Print( -2, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFraigStore( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fDuplicate; + + // set defaults + fDuplicate = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'd': + fDuplicate ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + // get the new network + if ( !Abc_NtkFraigStore( pNtk ) ) + { + Abc_Print( -1, "Fraig storing has failed.\n" ); + return 1; + } + return 0; + +usage: + Abc_Print( -2, "usage: fraig_store [-h]\n" ); + Abc_Print( -2, "\t saves the current network in the AIG database\n" ); +// Abc_Print( -2, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFraigRestore( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + int c; + int nPatsRand = 0; // the number of words of random simulation info + int nPatsDyna = 0; // the number of words of dynamic simulation info + int nBTLimit = 1000; // the max number of backtracks to perform + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "RDCh" ) ) != EOF ) + { + switch ( c ) + { + case 'R': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-R\" should be followed by an integer.\n" ); + goto usage; + } + nPatsRand = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nPatsRand < 0 ) + goto usage; + break; + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by an integer.\n" ); + goto usage; + } + nPatsDyna = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nPatsDyna < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nBTLimit = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nBTLimit < 0 ) + goto usage; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + // get the new network + pNtkRes = Abc_NtkFraigRestore( nPatsRand, nPatsDyna, nBTLimit ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Fraig restoring has failed.\n" ); + return 1; + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: fraig_restore [-RDC num] [-h]\n" ); + Abc_Print( -2, "\t makes the current network by fraiging the AIG database\n" ); + Abc_Print( -2, "\t-R num : number of random patterns (127 < num < 32769) [default = design-dependent]\n" ); + Abc_Print( -2, "\t-D num : number of systematic patterns (127 < num < 32769) [default = design-dependent]\n" ); + Abc_Print( -2, "\t-C num : number of backtracks for one SAT problem [default = %d]\n", nBTLimit ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFraigClean( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ +// Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fDuplicate; + // set defaults + fDuplicate = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'd': + fDuplicate ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + Abc_NtkFraigStoreClean(); + return 0; + +usage: + Abc_Print( -2, "usage: fraig_clean [-h]\n" ); + Abc_Print( -2, "\t cleans the internal FRAIG storage\n" ); +// Abc_Print( -2, "\t-d : toggle duplication of logic [default = %s]\n", fDuplicate? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFraigSweep( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fUseInv; + int fExdc; + int fVerbose; + int fVeryVerbose; + extern int Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose ); + // set defaults + fUseInv = 1; + fExdc = 0; + fVerbose = 0; + fVeryVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ievwh" ) ) != EOF ) + { + switch ( c ) + { + case 'i': + fUseInv ^= 1; + break; + case 'e': + fExdc ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'w': + fVeryVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "Cannot sweep AIGs (use \"fraig\").\n" ); + return 1; + } + if ( !Abc_NtkIsLogic(pNtk) ) + { + Abc_Print( -1, "Transform the current network into a logic network.\n" ); + return 1; + } + // modify the current network + if ( !Abc_NtkFraigSweep( pNtk, fUseInv, fExdc, fVerbose, fVeryVerbose ) ) + { + Abc_Print( -1, "Sweeping has failed.\n" ); + return 1; + } + return 0; + +usage: + Abc_Print( -2, "usage: fraig_sweep [-evwh]\n" ); + Abc_Print( -2, "\t performs technology-dependent sweep\n" ); + Abc_Print( -2, "\t-e : toggle functional sweeping using EXDC [default = %s]\n", fExdc? "yes": "no" ); + Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-w : prints equivalence class information [default = %s]\n", fVeryVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandFraigDress( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_NtkDress( Abc_Ntk_t * pNtk, char * pFileName, int fVerbose ); + extern void Abc_NtkDress2( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nConflictLimit, int fVerbose ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc), * pNtk2; + char * pFileName; + int c; + int nConfs; + int fVerbose; + // set defaults + nConfs = 1000; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Cvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfs < 0 ) + goto usage; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works only for logic networks.\n" ); + return 1; + } + if ( argc != globalUtilOptind && argc != globalUtilOptind + 1 ) + goto usage; + if ( argc == globalUtilOptind && Abc_NtkSpec(pNtk) == NULL ) + { + Abc_Print( -1, "The current network has no spec.\n" ); + return 1; + } + // get the input file name + pFileName = (argc == globalUtilOptind + 1) ? argv[globalUtilOptind] : Abc_NtkSpec(pNtk); + // modify the current network +// Abc_NtkDress( pNtk, pFileName, fVerbose ); + pNtk2 = Io_Read( pFileName, Io_ReadFileType(pFileName), 1, 0 ); + Abc_NtkDress2( pNtk, pNtk2, nConfs, fVerbose ); + Abc_NtkDelete( pNtk2 ); + return 0; + +usage: + Abc_Print( -2, "usage: dress [-C num] [-vh] \n" ); + Abc_Print( -2, "\t transfers internal node names from file to the current network\n" ); + Abc_Print( -2, "\t : network with names (if not given, the current network spec is used)\n" ); + Abc_Print( -2, "\t-C num : the maximum number of conflicts at each node [default = %d]\n", nConfs ); + Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandDumpEquiv( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_NtkDumpEquiv( Abc_Ntk_t * pNtks[2], char * pFileName, int nConfs, int fByName, int fVerbose ); + Abc_Ntk_t * pNtks[2] = {NULL}; + char * pFileName[2], * pFileNameOut; + int c, nConfs = 1000, fByName = 1, fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "Cnvh" ) ) != EOF ) + { + switch ( c ) + { + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nConfs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nConfs < 0 ) + goto usage; + break; + case 'n': + fByName ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( argc != globalUtilOptind + 3 ) + { + Abc_Print( -1, "Expecting three file names on the command line.\n" ); + goto usage; + } + pFileName[0] = argv[globalUtilOptind]; + pFileName[1] = argv[globalUtilOptind+1]; + pFileNameOut = argv[globalUtilOptind+2]; + for ( c = 0; c < 2; c++ ) + { + pNtks[c] = Io_Read( pFileName[c], Io_ReadFileType(pFileName[c]), 1, 0 ); + if ( pNtks[c] == NULL ) + goto usage; + Abc_NtkToAig( pNtks[c] ); + } +// if ( Abc_NtkCiNum(pNtks[0]) != Abc_NtkCiNum(pNtks[1]) ) +// Abc_Print( -1, "The number of primary inputs of networks \"%s\" and \"%s\" does not match.\n", Abc_NtkName(pNtks[0]), Abc_NtkName(pNtks[1]) ); +// else if ( Abc_NtkCoNum(pNtks[0]) != Abc_NtkCoNum(pNtks[1]) ) +// Abc_Print( -1, "The number of primary outputs of networks \"%s\" and \"%s\" does not match.\n", Abc_NtkName(pNtks[0]), Abc_NtkName(pNtks[1]) ); +// else + Abc_NtkDumpEquiv( pNtks, pFileNameOut, nConfs, fByName, fVerbose ); + Abc_NtkDelete( pNtks[0] ); + Abc_NtkDelete( pNtks[1] ); + return 0; + +usage: + Abc_Print( -2, "usage: dump_equiv [-C num] [-nvh] \n" ); + Abc_Print( -2, "\t computes equivalence classes of nodes in and \n" ); + Abc_Print( -2, "\t By default this procedure performs matching of primary inputs by name.\n" ); + Abc_Print( -2, "\t Those inputs that cannot be matched are treated as free variables.\n" ); + Abc_Print( -2, "\t There is no effort to match primary outputs. Indeed, if two outputs\n" ); + Abc_Print( -2, "\t are equivalent, they will belong to the same equivalence class in the end.\n" ); + Abc_Print( -2, "\t-C num : the maximum number of conflicts at each node [default = %d]\n", nConfs ); + Abc_Print( -2, "\t-n : enable matching of primary inputs by name [default = %s]\n", fByName? "yes": "no" ); + Abc_Print( -2, "\t-v : prints verbose information [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : first network whose nodes are considered\n" ); + Abc_Print( -2, "\t : second network whose nodes are considered\n" ); + Abc_Print( -2, "\t : text file with node equivalence classes\n" ); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecStart3( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + char * FileName, * pTemp; + char ** pArgvNew; + int c, nArgcNew; + FILE * pFile; + Gia_Man_t * pGia = NULL; + int nVars = 6; + int nCuts = 32; + int fFuncOnly = 0; + int fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "KCfvh" ) ) != EOF ) + { + switch ( c ) + { + case 'K': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-K\" should be followed by an integer.\n" ); + goto usage; + } + nVars = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nVars < 1 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by an integer.\n" ); + goto usage; + } + nCuts = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nCuts < 1 ) + goto usage; + break; + case 'f': + fFuncOnly ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !(nVars >= 3 && nVars <= 16) ) + { + Abc_Print( -1, "The range of allowed values is 3 <= K <= 16.\n" ); + return 0; + } + if ( Abc_NtkRecIsRunning3() ) + { + Abc_Print( -1, "The AIG subgraph recording is already started.\n" ); + return 0; + } + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew != 1 ) + Abc_Print( 1, "File name is not given on the command line. Starting a new record.\n" ); + else + { + // get the input file name + FileName = pArgvNew[0]; + // fix the wrong symbol + for ( pTemp = FileName; *pTemp; pTemp++ ) + if ( *pTemp == '>' ) + *pTemp = '\\'; + if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); + if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", NULL, NULL, NULL, NULL )) ) + Abc_Print( 1, "Did you mean \"%s\"?", FileName ); + Abc_Print( 1, "\n" ); + return 1; + } + fclose( pFile ); + pGia = Gia_AigerRead( FileName, 0, 1, 0 ); + if ( pGia == NULL ) + { + Abc_Print( -1, "Reading AIGER has failed.\n" ); + return 0; + } + } + Abc_NtkRecStart3( pGia, nVars, nCuts, fFuncOnly, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: rec_start3 [-K num] [-C num] [-fvh] \n" ); + Abc_Print( -2, "\t starts recording AIG subgraphs (should be called for\n" ); + Abc_Print( -2, "\t an empty network or after reading in a previous record)\n" ); + Abc_Print( -2, "\t-K num : the largest number of inputs [default = %d]\n", nVars ); + Abc_Print( -2, "\t-C num : the max number of cuts used at a node (0 < num < 2^12) [default = %d]\n", nCuts ); + Abc_Print( -2, "\t-f : toggles recording functions without AIG subgraphs [default = %s]\n", fFuncOnly? "yes": "no" ); + Abc_Print( -2, "\t-v : toggles additional verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : AIGER file with the library\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecStop3( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + int c; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkRecIsRunning3() ) + { + Abc_Print( -1, "This command works only after calling \"rec_start3\".\n" ); + return 0; + } + Abc_NtkRecStop3(); + return 0; + +usage: + Abc_Print( -2, "usage: rec_stop3 [-h]\n" ); + Abc_Print( -2, "\t cleans the internal storage for AIG subgraphs\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecPs3( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + int c, fPrintLib = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "ph" ) ) != EOF ) + { + switch ( c ) + { + case 'p': + fPrintLib ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkRecIsRunning3() ) + { + Abc_Print( -1, "This command works for AIGs only after calling \"rec_start3\".\n" ); + return 0; + } + Abc_NtkRecPs3(fPrintLib); + return 0; + +usage: + Abc_Print( -2, "usage: rec_ps3 [-h]\n" ); + Abc_Print( -2, "\t prints statistics about the recorded AIG subgraphs\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecAdd3( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int c; + int fUseSOPB = 0; + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "gh" ) ) != EOF ) + { + switch ( c ) + { + case 'g': + fUseSOPB = 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkIsStrash(pNtk) ) + { + Abc_Print( -1, "This command works for AIGs.\n" ); + return 0; + } + if ( !Abc_NtkRecIsRunning3() ) + { + Abc_Print( -1, "This command works for AIGs after calling \"rec_start3\".\n" ); + return 0; + } + Abc_NtkRecAdd3( pNtk, fUseSOPB ); + return 0; + +usage: + Abc_Print( -2, "usage: rec_add3 [-h]\n" ); + Abc_Print( -2, "\t adds subgraphs from the current network to the set\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecDump3( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_NtkRecDumpTt3( char * pFileName, int fBinary ); + char * FileName; + char ** pArgvNew; + int nArgcNew; + Gia_Man_t * pGia; + int fAscii = 0; + int fBinary = 0; + int c; + + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "abh" ) ) != EOF ) + { + switch ( c ) + { + case 'a': + fAscii ^= 1; + break; + case 'b': + fBinary ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkRecIsRunning3() ) + { + Abc_Print( -1, "The AIG subgraph recording is not started.\n" ); + return 1; + } + + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew != 1 ) + { + Abc_Print( -1, "File name is not given on the command line.\n" ); + return 1; + } + // get the input file name + FileName = pArgvNew[0]; + if ( fAscii ) + Abc_NtkRecDumpTt3( FileName, 0 ); + else if ( fBinary ) + Abc_NtkRecDumpTt3( FileName, 1 ); + else + { + pGia = Abc_NtkRecGetGia3(); + if( pGia == NULL ) + { + Abc_Print( 0, "Library AIG is not available.\n" ); + return 1; + } + if( Gia_ManPoNum(pGia) == 0 ) + { + Abc_Print( 0, "No structure in the library.\n" ); + return 1; + } + Gia_AigerWrite( pGia, FileName, 0, 0, 0 ); + } + return 0; + +usage: + Abc_Print( -2, "usage: rec_dump3 [-abh] \n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t-a : toggles dumping TTs into an ASCII file [default = %s]\n", fAscii? "yes": "no" ); + Abc_Print( -2, "\t-b : toggles dumping TTs into a binary file [default = %s]\n", fBinary? "yes": "no" ); + Abc_Print( -2, "\t : AIGER file to write the library\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandRecMerge3( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + int c; + char * FileName, * pTemp; + char ** pArgvNew; + int nArgcNew; + FILE * pFile; + Gia_Man_t * pGia = NULL; + + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "dh" ) ) != EOF ) + { + switch ( c ) + { + case 'h': + goto usage; + default: + goto usage; + } + } + if ( !Abc_NtkRecIsRunning3() ) + { + Abc_Print( -1, "This command works for AIGs only after calling \"rec_start3\".\n" ); + return 0; + } + pArgvNew = argv + globalUtilOptind; + nArgcNew = argc - globalUtilOptind; + if ( nArgcNew != 1 ) + { + Abc_Print( -1, "File name is not given on the command line.\n" ); + return 1; + } + else + { + // get the input file name + FileName = pArgvNew[0]; + // fix the wrong symbol + for ( pTemp = FileName; *pTemp; pTemp++ ) + if ( *pTemp == '>' ) + *pTemp = '\\'; + if ( (pFile = fopen( FileName, "r" )) == NULL ) + { + Abc_Print( -1, "Cannot open input file \"%s\". ", FileName ); + if ( (FileName = Extra_FileGetSimilarName( FileName, ".aig", NULL, NULL, NULL, NULL )) ) + Abc_Print( 1, "Did you mean \"%s\"?", FileName ); + Abc_Print( 1, "\n" ); + return 1; + } + fclose( pFile ); + pGia = Gia_AigerRead( FileName, 0, 1, 0 ); + if ( pGia == NULL ) + { + Abc_Print( -1, "Reading AIGER has failed.\n" ); + return 0; + } + } + Abc_NtkRecLibMerge3(pGia); + Gia_ManStop( pGia ); + return 0; + +usage: + Abc_Print( -2, "usage: rec_merge3 [-h] \n" ); + Abc_Print( -2, "\t merge libraries\n" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + Abc_Print( -2, "\t : AIGER file with the library\n"); + return 1; +} + + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandMap( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk, * pNtkRes; + char Buffer[100]; + double DelayTarget; + double AreaMulti; + double DelayMulti; + float LogFan = 0; + float Slew = 0; // choose based on the library + float Gain = 250; + int nGatesMin = 0; + int fAreaOnly; + int fRecovery; + int fSweep; + int fSwitching; + int fSkipFanout; + int fUseProfile; + int fUseBuffs; + int fVerbose; + int c; + extern Abc_Ntk_t * Abc_NtkMap( Abc_Ntk_t * pNtk, Mio_Library_t* userLib, double DelayTarget, double AreaMulti, double DelayMulti, float LogFan, float Slew, float Gain, int nGatesMin, int fRecovery, int fSwitching, int fSkipFanout, int fUseProfile, int fUseBuffs, int fVerbose ); + extern int Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + DelayTarget =-1; + AreaMulti = 0; + DelayMulti = 0; + fAreaOnly = 0; + fRecovery = 1; + fSweep = 0; + fSwitching = 0; + fSkipFanout = 0; + fUseProfile = 0; + fUseBuffs = 0; + fVerbose = 0; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "DABFSGMarspfuovh" ) ) != EOF ) + { + switch ( c ) + { + case 'D': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-D\" should be followed by a floating point number.\n" ); + goto usage; + } + DelayTarget = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( DelayTarget <= 0.0 ) + goto usage; + break; + case 'A': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-A\" should be followed by a floating point number.\n" ); + goto usage; + } + AreaMulti = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'B': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-B\" should be followed by a floating point number.\n" ); + goto usage; + } + DelayMulti = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; + break; + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by a floating point number.\n" ); + goto usage; + } + LogFan = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( LogFan < 0.0 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by a floating point number.\n" ); + goto usage; + } + Slew = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Slew <= 0.0 ) + goto usage; + break; + case 'G': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-G\" should be followed by a floating point number.\n" ); + goto usage; + } + Gain = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Gain <= 0.0 ) + goto usage; + break; + case 'M': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-M\" should be followed by a positive integer.\n" ); + goto usage; + } + nGatesMin = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nGatesMin < 0 ) + goto usage; + break; + case 'a': + fAreaOnly ^= 1; + break; + case 'r': + fRecovery ^= 1; + break; + case 's': + fSweep ^= 1; + break; + case 'p': + fSwitching ^= 1; + break; + case 'f': + fSkipFanout ^= 1; + break; + case 'u': + fUseProfile ^= 1; + break; + case 'o': + fUseBuffs ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( fAreaOnly ) + DelayTarget = ABC_INFINITY; + + if ( !Abc_NtkIsStrash(pNtk) ) + { + pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); + if ( pNtk == NULL ) + { + Abc_Print( -1, "Strashing before mapping has failed.\n" ); + return 1; + } + pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 ); + Abc_NtkDelete( pNtkRes ); + if ( pNtk == NULL ) + { + Abc_Print( -1, "Balancing before mapping has failed.\n" ); + return 1; + } + Abc_Print( 0, "The network was strashed and balanced before mapping.\n" ); + // get the new network + pNtkRes = Abc_NtkMap( pNtk, /*userLib=*/NULL, DelayTarget, AreaMulti, DelayMulti, LogFan, Slew, Gain, nGatesMin, fRecovery, fSwitching, fSkipFanout, fUseProfile, fUseBuffs, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_NtkDelete( pNtk ); + Abc_Print( -1, "Mapping has failed.\n" ); + return 1; + } + Abc_NtkDelete( pNtk ); + } + else + { + // get the new network + pNtkRes = Abc_NtkMap( pNtk, /*userLib=*/NULL, DelayTarget, AreaMulti, DelayMulti, LogFan, Slew, Gain, nGatesMin, fRecovery, fSwitching, fSkipFanout, fUseProfile, fUseBuffs, fVerbose ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Mapping has failed.\n" ); + return 1; + } + } + + if ( fSweep ) + { + Abc_NtkFraigSweep( pNtkRes, 0, 0, 0, 0 ); + if ( Abc_NtkHasMapping(pNtkRes) ) + { + pNtkRes = Abc_NtkDupDfs( pNtk = pNtkRes ); + Abc_NtkDelete( pNtk ); + } + } + + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + if ( DelayTarget == -1 ) + sprintf(Buffer, "not used" ); + else + sprintf(Buffer, "%.3f", DelayTarget ); + Abc_Print( -2, "usage: map [-DABFSG float] [-M num] [-arspfuovh]\n" ); + Abc_Print( -2, "\t performs standard cell mapping of the current network\n" ); + Abc_Print( -2, "\t-D float : sets the global required times [default = %s]\n", Buffer ); + Abc_Print( -2, "\t-A float : \"area multiplier\" to bias gate selection [default = %.2f]\n", AreaMulti ); + Abc_Print( -2, "\t-B float : \"delay multiplier\" to bias gate selection [default = %.2f]\n", DelayMulti ); + Abc_Print( -2, "\t-F float : the logarithmic fanout delay parameter [default = %.2f]\n", LogFan ); + Abc_Print( -2, "\t-S float : the slew parameter used to generate the library [default = %.2f]\n", Slew ); + Abc_Print( -2, "\t-G float : the gain parameter used to generate the library [default = %.2f]\n", Gain ); + Abc_Print( -2, "\t-M num : skip gate classes whose size is less than this [default = %d]\n", nGatesMin ); + Abc_Print( -2, "\t-a : toggles area-only mapping [default = %s]\n", fAreaOnly? "yes": "no" ); + Abc_Print( -2, "\t-r : toggles area recovery [default = %s]\n", fRecovery? "yes": "no" ); + Abc_Print( -2, "\t-s : toggles sweep after mapping [default = %s]\n", fSweep? "yes": "no" ); + Abc_Print( -2, "\t-p : optimizes power by minimizing switching [default = %s]\n", fSwitching? "yes": "no" ); + Abc_Print( -2, "\t-f : do not use large gates to map high-fanout nodes [default = %s]\n", fSkipFanout? "yes": "no" ); + Abc_Print( -2, "\t-u : use standard-cell profile [default = %s]\n", fUseProfile? "yes": "no" ); + Abc_Print( -2, "\t-o : toggles using buffers to decouple combinational outputs [default = %s]\n", fUseBuffs? "yes": "no" ); + Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandAmap( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Amap_Par_t Pars, * pPars = &Pars; + Abc_Ntk_t * pNtk, * pNtkRes; + int fSweep; + int c; + extern Abc_Ntk_t * Abc_NtkDarAmap( Abc_Ntk_t * pNtk, Amap_Par_t * pPars ); + extern int Abc_NtkFraigSweep( Abc_Ntk_t * pNtk, int fUseInv, int fExdc, int fVerbose, int fVeryVerbose ); + + pNtk = Abc_FrameReadNtk(pAbc); + // set defaults + fSweep = 0; + Amap_ManSetDefaultParams( pPars ); + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "FACEQmxisvh" ) ) != EOF ) + { + switch ( c ) + { + case 'F': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-F\" should be followed by a floating point number.\n" ); + goto usage; + } + pPars->nIterFlow = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nIterFlow < 0 ) + goto usage; + break; + case 'A': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-A\" should be followed by a floating point number.\n" ); + goto usage; + } + pPars->nIterArea = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nIterArea < 0 ) + goto usage; + break; + case 'C': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-C\" should be followed by a floating point number.\n" ); + goto usage; + } + pPars->nCutsMax = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->nCutsMax < 0 ) + goto usage; + break; + case 'E': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-E\" should be followed by a floating point number.\n" ); + goto usage; + } + pPars->fEpsilon = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->fEpsilon < 0.0 || pPars->fEpsilon > 1.0 ) + goto usage; + break; + case 'Q': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-Q\" should be followed by a floating point number.\n" ); + goto usage; + } + pPars->fADratio = (float)atof(argv[globalUtilOptind]); + globalUtilOptind++; + if ( pPars->fADratio < 0.0 ) + goto usage; + break; + case 'm': + pPars->fUseMuxes ^= 1; + break; + case 'x': + pPars->fUseXors ^= 1; + break; + case 'i': + pPars->fFreeInvs ^= 1; + break; + case 's': + fSweep ^= 1; + break; + case 'v': + pPars->fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + + if ( !Abc_NtkIsStrash(pNtk) ) + { + pNtk = Abc_NtkStrash( pNtk, 0, 0, 0 ); + if ( pNtk == NULL ) + { + Abc_Print( -1, "Strashing before mapping has failed.\n" ); + return 1; + } + pNtk = Abc_NtkBalance( pNtkRes = pNtk, 0, 0, 1 ); + Abc_NtkDelete( pNtkRes ); + if ( pNtk == NULL ) + { + Abc_Print( -1, "Balancing before mapping has failed.\n" ); + return 1; + } + Abc_Print( 0, "The network was strashed and balanced before mapping.\n" ); + // get the new network + pNtkRes = Abc_NtkDarAmap( pNtk, pPars ); + if ( pNtkRes == NULL ) + { + Abc_NtkDelete( pNtk ); + Abc_Print( -1, "Mapping has failed.\n" ); + return 1; + } + Abc_NtkDelete( pNtk ); + } + else + { + // get the new network + pNtkRes = Abc_NtkDarAmap( pNtk, pPars ); + if ( pNtkRes == NULL ) + { + Abc_Print( -1, "Mapping has failed.\n" ); + return 1; + } + } + + if ( fSweep ) + { + Abc_NtkFraigSweep( pNtkRes, 0, 0, 0, 0 ); + if ( Abc_NtkHasMapping(pNtkRes) ) + { + pNtkRes = Abc_NtkDupDfs( pNtk = pNtkRes ); + Abc_NtkDelete( pNtk ); + } + } + // replace the current network + Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes ); + return 0; + +usage: + Abc_Print( -2, "usage: amap [-FAC ] [-EQ ] [-mxisvh]\n" ); + Abc_Print( -2, "\t performs standard cell mapping of the current network\n" ); + Abc_Print( -2, "\t-F num : the number of iterations of area flow [default = %d]\n", pPars->nIterFlow ); + Abc_Print( -2, "\t-A num : the number of iterations of exact area [default = %d]\n", pPars->nIterArea ); + Abc_Print( -2, "\t-C num : the maximum number of cuts at a node [default = %d]\n", pPars->nCutsMax ); + Abc_Print( -2, "\t-E float : sets epsilon used for tie-breaking [default = %f]\n", pPars->fEpsilon ); + Abc_Print( -2, "\t-Q float : area/delay preference ratio [default = %.2f (area-only)] \n", pPars->fADratio ); + Abc_Print( -2, "\t-m : toggles using MUX matching [default = %s]\n", pPars->fUseMuxes? "yes": "no" ); + Abc_Print( -2, "\t-x : toggles using XOR matching [default = %s]\n", pPars->fUseXors? "yes": "no" ); + Abc_Print( -2, "\t-i : toggles assuming inverters are free [default = %s]\n", pPars->fFreeInvs? "yes": "no" ); + Abc_Print( -2, "\t-s : toggles sweep after mapping [default = %s]\n", fSweep? "yes": "no" ); + Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", pPars->fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandPhaseMap( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + extern void Abc_NtkChangePerform( Abc_Ntk_t * pNtk, int fVerbose ); + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + int fVerbose = 0, c; + // set defaults + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "vh" ) ) != EOF ) + { + switch ( c ) + { + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + + if ( pNtk == NULL ) + { + Abc_Print( -1, "Empty network.\n" ); + return 1; + } + if ( !Abc_NtkHasMapping(pNtk) ) + { + Abc_Print( -1, "Cannot unmap the network that is not mapped.\n" ); + return 1; + } + Abc_NtkChangePerform( pNtk, fVerbose ); + return 0; + +usage: + Abc_Print( -2, "usage: phase_map [-vh]\n" ); + Abc_Print( -2, "\t tries to replace each gate by its complement (area-only)\n" ); + Abc_Print( -2, "\t-v : toggles verbose output [default = %s]\n", fVerbose? "yes": "no" ); + Abc_Print( -2, "\t-h : print the command usage\n"); + return 1; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Abc_CommandStochMap( Abc_Frame_t * pAbc, int argc, char ** argv ) +{ + Abc_Ntk_t * pNtk = Abc_FrameReadNtk(pAbc); + extern void Abc_NtkStochMap( int nSuppMax, int nIters, int TimeOut, int Seed, int fOverlap, int fVerbose, char * pScript, int nProcs ); + int c, nMaxSize = 14, nIters = 1, TimeOut = 0, Seed = 0, nProcs = 1, fOverlap = 0, fVerbose = 0; char * pScript; + Extra_UtilGetoptReset(); + while ( ( c = Extra_UtilGetopt( argc, argv, "NITSPovh" ) ) != EOF ) + { + switch ( c ) + { + case 'N': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-N\" should be followed by an integer.\n" ); + goto usage; + } + nMaxSize = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nMaxSize < 0 ) + goto usage; + break; + case 'I': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-I\" should be followed by an integer.\n" ); + goto usage; + } + nIters = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nIters < 0 ) + goto usage; + break; + case 'T': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-T\" should be followed by an integer.\n" ); + goto usage; + } + TimeOut = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( TimeOut < 0 ) + goto usage; + break; + case 'S': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-S\" should be followed by an integer.\n" ); + goto usage; + } + Seed = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( Seed < 0 ) + goto usage; + break; + case 'P': + if ( globalUtilOptind >= argc ) + { + Abc_Print( -1, "Command line switch \"-P\" should be followed by an integer.\n" ); + goto usage; + } + nProcs = atoi(argv[globalUtilOptind]); + globalUtilOptind++; + if ( nProcs < 0 ) + goto usage; + break; + case 'o': + fOverlap ^= 1; + break; + case 'v': + fVerbose ^= 1; + break; + case 'h': + goto usage; + default: + goto usage; + } + } + if ( pNtk == NULL ) + { + Abc_Print( -1, "Abc_CommandStochMap(): There is no AIG.\n" ); + return 0; + } + if ( !Abc_NtkIsMappedLogic(pNtk) ) + { + Abc_Print( -1, "Abc_CommandStochMap(): Expecting a mapped current newtork as input.\n" ); + return 0; + } + if ( argc != globalUtilOptind + 1 ) + { + printf( "Expecting a synthesis script in quotes on the command line (for example: \"&st; &dch; &if\").\n" ); + goto usage; + } + pScript = Abc_UtilStrsav( argv[globalUtilOptind] ); + Abc_NtkStochMap( nMaxSize, nIters, TimeOut, Seed, fOverlap, fVerbose, pScript, nProcs ); + ABC_FREE( pScript ); + return 0; + +usage: + Abc_Print( -2, "usage: stochmap [-NITSP ] [-ovh]