Further improve extract_fa (but still buggy)
authorClifford Wolf <clifford@clifford.at>
Sat, 2 Sep 2017 14:37:42 +0000 (16:37 +0200)
committerClifford Wolf <clifford@clifford.at>
Sat, 2 Sep 2017 14:39:17 +0000 (16:39 +0200)
passes/techmap/extract_fa.cc

index b95ec26c3defb947c8386efc8f0043d13dd46c03..a68cc5e2ed3aa6fad62b9cd532693341e369dac9 100644 (file)
@@ -326,6 +326,8 @@ struct ExtractFaWorker
                                log("\n");
                        }
 
+                       dict<int, tuple<SigBit, SigBit, Cell*>> facache;
+
                        for (auto &it : func3_maj_info)
                        {
                                int func = it.first;
@@ -357,33 +359,64 @@ struct ExtractFaWorker
                                        log(" %s", log_signal(bit));
                                log("\n");
 
-                               Cell *cell = module->addCell(NEW_ID, "$fa");
-                               cell->setParam("\\WIDTH", 1);
+                               int fakey = 0;
+                               if (f3i.inv_a) fakey |= 1;
+                               if (f3i.inv_b) fakey |= 2;
+                               if (f3i.inv_c) fakey |= 4;
+
+                               int fakey_inv = fakey ^ 7;
+                               bool invert_xy = false;
+                               SigBit X, Y;
+
+                               if (facache.count(fakey))
+                               {
+                                       auto &fa = facache.at(fakey);
+                                       X = get<0>(fa);
+                                       Y = get<1>(fa);
+                                       log("      Reusing $fa cell %s.\n", log_id(get<2>(fa)));
+                               }
+                               else
+                               if (facache.count(fakey_inv))
+                               {
+                                       auto &fa = facache.at(fakey_inv);
+                                       invert_xy = true;
+                                       X = get<0>(fa);
+                                       Y = get<1>(fa);
+                                       log("      Reusing $fa cell %s.\n", log_id(get<2>(fa)));
+                               }
+                               else
+                               {
+                                       Cell *cell = module->addCell(NEW_ID, "$fa");
+                                       cell->setParam("\\WIDTH", 1);
+
+                                       log("      Created $fa cell %s.\n", log_id(cell));
 
-                               log("      Created $fa cell %s.\n", log_id(cell));
+                                       cell->setPort("\\A", f3i.inv_a ? module->NotGate(NEW_ID, A) : A);
+                                       cell->setPort("\\B", f3i.inv_b ? module->NotGate(NEW_ID, B) : B);
+                                       cell->setPort("\\C", f3i.inv_c ? module->NotGate(NEW_ID, C) : C);
 
-                               cell->setPort("\\A", f3i.inv_a ? module->NotGate(NEW_ID, A) : A);
-                               cell->setPort("\\B", f3i.inv_b ? module->NotGate(NEW_ID, B) : B);
-                               cell->setPort("\\C", f3i.inv_c ? module->NotGate(NEW_ID, C) : C);
+                                       X = module->addWire(NEW_ID);
+                                       Y = module->addWire(NEW_ID);
 
-                               SigBit X = module->addWire(NEW_ID);
-                               SigBit Y = module->addWire(NEW_ID);
+                                       cell->setPort("\\X", X);
+                                       cell->setPort("\\Y", Y);
 
-                               cell->setPort("\\X", X);
-                               cell->setPort("\\Y", Y);
+                                       facache[fakey] = make_tuple(X, Y, cell);
+                               }
 
                                if (func3.at(key).count(xor3_func)) {
+                                       SigBit YY = invert_xy ? module->NotGate(NEW_ID, Y) : Y;
                                        for (auto bit : func3.at(key).at(xor3_func))
-                                               assign_new_driver(bit, Y);
+                                               assign_new_driver(bit, YY);
                                }
 
                                if (func3.at(key).count(xnor3_func)) {
-                                       SigBit YN = module->NotGate(NEW_ID, Y);
+                                       SigBit YY = invert_xy ? Y : module->NotGate(NEW_ID, Y);
                                        for (auto bit : func3.at(key).at(xnor3_func))
-                                               assign_new_driver(bit, YN);
+                                               assign_new_driver(bit, YY);
                                }
 
-                               SigBit XX = f3i.inv_y ? module->NotGate(NEW_ID, X) : X;
+                               SigBit XX = invert_xy != f3i.inv_y ? module->NotGate(NEW_ID, X) : X;
 
                                for (auto bit : func3.at(key).at(func))
                                        assign_new_driver(bit, XX);
@@ -408,6 +441,8 @@ struct ExtractFaWorker
                                log("\n");
                        }
 
+                       dict<int, tuple<SigBit, SigBit, Cell*>> facache;
+
                        for (auto &it : func2_and_info)
                        {
                                int func = it.first;
@@ -431,33 +466,61 @@ struct ExtractFaWorker
                                        log(" %s", log_signal(bit));
                                log("\n");
 
-                               Cell *cell = module->addCell(NEW_ID, "$fa");
-                               cell->setParam("\\WIDTH", 1);
+                               int fakey = 0;
+                               if (f2i.inv_a) fakey |= 1;
+                               if (f2i.inv_b) fakey |= 2;
 
-                               log("      Created $fa cell %s.\n", log_id(cell));
+                               int fakey_inv = fakey ^ 3;
+                               bool invert_xy = false;
+                               SigBit X, Y;
 
-                               cell->setPort("\\A", f2i.inv_a ? module->NotGate(NEW_ID, A) : A);
-                               cell->setPort("\\B", f2i.inv_b ? module->NotGate(NEW_ID, B) : B);
-                               cell->setPort("\\C", State::S0);
+                               if (facache.count(fakey))
+                               {
+                                       auto &fa = facache.at(fakey);
+                                       X = get<0>(fa);
+                                       Y = get<1>(fa);
+                                       log("      Reusing $fa cell %s.\n", log_id(get<2>(fa)));
+                               }
+                               else
+                               if (facache.count(fakey_inv))
+                               {
+                                       auto &fa = facache.at(fakey_inv);
+                                       invert_xy = true;
+                                       X = get<0>(fa);
+                                       Y = get<1>(fa);
+                                       log("      Reusing $fa cell %s.\n", log_id(get<2>(fa)));
+                               }
+                               else
+                               {
+                                       Cell *cell = module->addCell(NEW_ID, "$fa");
+                                       cell->setParam("\\WIDTH", 1);
+
+                                       log("      Created $fa cell %s.\n", log_id(cell));
 
-                               SigBit X = module->addWire(NEW_ID);
-                               SigBit Y = module->addWire(NEW_ID);
+                                       cell->setPort("\\A", f2i.inv_a ? module->NotGate(NEW_ID, A) : A);
+                                       cell->setPort("\\B", f2i.inv_b ? module->NotGate(NEW_ID, B) : B);
+                                       cell->setPort("\\C", State::S0);
 
-                               cell->setPort("\\X", X);
-                               cell->setPort("\\Y", Y);
+                                       X = module->addWire(NEW_ID);
+                                       Y = module->addWire(NEW_ID);
+
+                                       cell->setPort("\\X", X);
+                                       cell->setPort("\\Y", Y);
+                               }
 
                                if (func2.at(key).count(xor2_func)) {
+                                       SigBit YY = invert_xy ? module->NotGate(NEW_ID, Y) : Y;
                                        for (auto bit : func2.at(key).at(xor2_func))
-                                               assign_new_driver(bit, Y);
+                                               assign_new_driver(bit, YY);
                                }
 
                                if (func2.at(key).count(xnor2_func)) {
-                                       SigBit YN = module->NotGate(NEW_ID, Y);
+                                       SigBit YY = invert_xy ? Y : module->NotGate(NEW_ID, Y);
                                        for (auto bit : func2.at(key).at(xnor2_func))
-                                               assign_new_driver(bit, YN);
+                                               assign_new_driver(bit, YY);
                                }
 
-                               SigBit XX = f2i.inv_y ? module->NotGate(NEW_ID, X) : X;
+                               SigBit XX = invert_xy != f2i.inv_y ? module->NotGate(NEW_ID, X) : X;
 
                                for (auto bit : func2.at(key).at(func))
                                        assign_new_driver(bit, XX);