Support subtraction as well
authorEddie Hung <eddie@fpgeh.com>
Tue, 10 Sep 2019 04:39:42 +0000 (21:39 -0700)
committerEddie Hung <eddie@fpgeh.com>
Tue, 10 Sep 2019 04:39:42 +0000 (21:39 -0700)
passes/pmgen/xilinx_dsp.cc

index 23f342a2b9c24e38b47ffba9b8479a2e60b6262f..7bac1b974233666771e9e6fe6a1cf97479bda66b 100644 (file)
@@ -59,10 +59,11 @@ static Cell* addDsp(Module *module) {
 
 void pack_xilinx_simd(Module *module, const std::vector<Cell*> &selected_cells)
 {
-       std::deque<Cell*> simd12, simd24;
+       std::deque<Cell*> simd12_add, simd12_sub;
+       std::deque<Cell*> simd24_add, simd24_sub;
 
        for (auto cell : selected_cells) {
-               if (!cell->type.in("$add"))
+               if (!cell->type.in("$add", "$sub"))
                        continue;
                SigSpec Y = cell->getPort("\\Y");
                if (!Y.is_chunk())
@@ -78,24 +79,26 @@ void pack_xilinx_simd(Module *module, const std::vector<Cell*> &selected_cells)
                                continue;
                        if (GetSize(B) > 12)
                                continue;
-                       simd12.push_back(cell);
+                       if (cell->type == "$add")
+                               simd12_add.push_back(cell);
+                       else if (cell->type == "$sub")
+                               simd12_sub.push_back(cell);
                }
                else if (GetSize(Y) <= 25) {
                        if (GetSize(A) > 24)
                                continue;
                        if (GetSize(B) > 24)
                                continue;
-                       simd24.push_back(cell);
+                       if (cell->type == "$add")
+                               simd24_add.push_back(cell);
+                       else if (cell->type == "$sub")
+                               simd24_sub.push_back(cell);
                }
                else
                        log_abort();
        }
 
-       SigSpec AB;
-       SigSpec C;
-       SigSpec P;
-       SigSpec CARRYOUT;
-       auto f12 = [&AB,&C,&P,&CARRYOUT,module](Cell *lane) {
+       auto f12 = [module](SigSpec &AB, SigSpec &C, SigSpec &P, SigSpec &CARRYOUT, Cell *lane) {
                SigSpec A = lane->getPort("\\A");
                SigSpec B = lane->getPort("\\B");
                SigSpec Y = lane->getPort("\\Y");
@@ -110,84 +113,86 @@ void pack_xilinx_simd(Module *module, const std::vector<Cell*> &selected_cells)
                P.append(Y.extract(0, 12));
                CARRYOUT.append(Y[12]);
        };
-       while (simd12.size() > 1) {
-               AB = SigSpec();
-               C = SigSpec();
-               P = SigSpec();
-               CARRYOUT = SigSpec();
-
-               Cell *lane1 = simd12.front();
-               simd12.pop_front();
-               Cell *lane2 = simd12.front();
-               simd12.pop_front();
-               Cell *lane3 = nullptr;
-               Cell *lane4 = nullptr;
-
-               if (!simd12.empty()) {
-                       lane3 = simd12.front();
+       auto g12 = [&f12,module](std::deque<Cell*> &simd12) {
+               while (simd12.size() > 1) {
+                       SigSpec AB, C, P, CARRYOUT;
+
+                       Cell *lane1 = simd12.front();
+                       simd12.pop_front();
+                       Cell *lane2 = simd12.front();
                        simd12.pop_front();
+                       Cell *lane3 = nullptr;
+                       Cell *lane4 = nullptr;
+
                        if (!simd12.empty()) {
-                               lane4 = simd12.front();
+                               lane3 = simd12.front();
                                simd12.pop_front();
+                               if (!simd12.empty()) {
+                                       lane4 = simd12.front();
+                                       simd12.pop_front();
+                               }
                        }
-               }
 
-               log("Analysing %s.%s for Xilinx DSP SIMD12 packing.\n", log_id(module), log_id(lane1));
-
-               Cell *cell = addDsp(module);
-               cell->setParam("\\USE_SIMD", Const("FOUR12"));
-               // X = A:B
-               // Y = 0
-               // Z = C
-               cell->setPort("\\OPMODE", Const::from_string("0110011"));
-
-               log_assert(lane1);
-               log_assert(lane2);
-               f12(lane1);
-               f12(lane2);
-               if (lane3) {
-                       f12(lane3);
-                       if (lane4)
-                               f12(lane4);
+                       log("Analysing %s.%s for Xilinx DSP SIMD12 packing.\n", log_id(module), log_id(lane1));
+
+                       Cell *cell = addDsp(module);
+                       cell->setParam("\\USE_SIMD", Const("FOUR12"));
+                       // X = A:B
+                       // Y = 0
+                       // Z = C
+                       cell->setPort("\\OPMODE", Const::from_string("0110011"));
+
+                       log_assert(lane1);
+                       log_assert(lane2);
+                       f12(AB, C, P, CARRYOUT, lane1);
+                       f12(AB, C, P, CARRYOUT, lane2);
+                       if (lane3) {
+                               f12(AB, C, P, CARRYOUT, lane3);
+                               if (lane4)
+                                       f12(AB, C, P, CARRYOUT, lane4);
+                               else {
+                                       AB.append(Const(0, 12));
+                                       C.append(Const(0, 12));
+                                       P.append(module->addWire(NEW_ID, 12));
+                                       CARRYOUT.append(module->addWire(NEW_ID, 1));
+                               }
+                       }
                        else {
-                               AB.append(Const(0, 12));
-                               C.append(Const(0, 12));
-                               P.append(module->addWire(NEW_ID, 12));
-                               CARRYOUT.append(module->addWire(NEW_ID, 1));
+                               AB.append(Const(0, 24));
+                               C.append(Const(0, 24));
+                               P.append(module->addWire(NEW_ID, 24));
+                               CARRYOUT.append(module->addWire(NEW_ID, 2));
                        }
+                       log_assert(GetSize(AB) == 48);
+                       log_assert(GetSize(C) == 48);
+                       log_assert(GetSize(P) == 48);
+                       log_assert(GetSize(CARRYOUT) == 4);
+                       cell->setPort("\\A", AB.extract(18, 30));
+                       cell->setPort("\\B", AB.extract(0, 18));
+                       cell->setPort("\\C", C);
+                       cell->setPort("\\P", P);
+                       cell->setPort("\\CARRYOUT", CARRYOUT);
+                       if (lane1->type == "$sub")
+                               cell->setPort("\\ALUMODE", Const::from_string("0011"));
+
+                       module->remove(lane1);
+                       module->remove(lane2);
+                       if (lane3) module->remove(lane3);
+                       if (lane4) module->remove(lane4);
+
+                       module->design->select(module, cell);
                }
-               else {
-                       AB.append(Const(0, 24));
-                       C.append(Const(0, 24));
-                       P.append(module->addWire(NEW_ID, 24));
-                       CARRYOUT.append(module->addWire(NEW_ID, 2));
-               }
-               log_assert(GetSize(AB) == 48);
-               log_assert(GetSize(C) == 48);
-               log_assert(GetSize(P) == 48);
-               log_assert(GetSize(CARRYOUT) == 4);
-               cell->setPort("\\A", AB.extract(18, 30));
-               cell->setPort("\\B", AB.extract(0, 18));
-               cell->setPort("\\C", C);
-               cell->setPort("\\P", P);
-               cell->setPort("\\CARRYOUT", CARRYOUT);
-
-               module->remove(lane1);
-               module->remove(lane2);
-               if (lane3) module->remove(lane3);
-               if (lane4) module->remove(lane4);
-
-               module->design->select(module, cell);
-       }
+       };
+       g12(simd12_add);
+       g12(simd12_sub);
 
-       auto f24 = [&AB,&C,&P,&CARRYOUT,module](Cell *lane) {
+       auto f24 = [module](SigSpec &AB, SigSpec &C, SigSpec &P, SigSpec &CARRYOUT, Cell *lane) {
                SigSpec A = lane->getPort("\\A");
                SigSpec B = lane->getPort("\\B");
                SigSpec Y = lane->getPort("\\Y");
                A.extend_u0(24, lane->getParam("\\A_SIGNED").as_bool());
                B.extend_u0(24, lane->getParam("\\B_SIGNED").as_bool());
-               AB.append(A);
-               C.append(B);
+               AB.append(B);
                if (GetSize(Y) < 25)
                        Y.append(module->addWire(NEW_ID, 25-GetSize(Y)));
                else
@@ -196,45 +201,51 @@ void pack_xilinx_simd(Module *module, const std::vector<Cell*> &selected_cells)
                CARRYOUT.append(module->addWire(NEW_ID)); // TWO24 uses every other bit
                CARRYOUT.append(Y[24]);
        };
-       while (simd24.size() > 1) {
-               AB = SigSpec();
-               C = SigSpec();
-               P = SigSpec();
-               CARRYOUT = SigSpec();
-
-               Cell *lane1 = simd24.front();
-               simd24.pop_front();
-               Cell *lane2 = simd24.front();
-               simd24.pop_front();
-
-               log("Analysing %s.%s for Xilinx DSP SIMD24 packing.\n", log_id(module), log_id(lane1));
-
-               Cell *cell = addDsp(module);
-               cell->setParam("\\USE_SIMD", Const("TWO24"));
-               // X = A:B
-               // Y = 0
-               // Z = C
-               cell->setPort("\\OPMODE", Const::from_string("0110011"));
-
-               log_assert(lane1);
-               log_assert(lane2);
-               f24(lane1);
-               f24(lane2);
-               log_assert(GetSize(AB) == 48);
-               log_assert(GetSize(C) == 48);
-               log_assert(GetSize(P) == 48);
-               log_assert(GetSize(CARRYOUT) == 4);
-               cell->setPort("\\A", AB.extract(18, 30));
-               cell->setPort("\\B", AB.extract(0, 18));
-               cell->setPort("\\C", C);
-               cell->setPort("\\P", P);
-               cell->setPort("\\CARRYOUT", CARRYOUT);
-
-               module->remove(lane1);
-               module->remove(lane2);
-
-               module->design->select(module, cell);
-       }
+       auto g24 = [&f24,module](std::deque<Cell*> &simd24) {
+               while (simd24.size() > 1) {
+                       SigSpec AB;
+                       SigSpec C;
+                       SigSpec P;
+                       SigSpec CARRYOUT;
+
+                       Cell *lane1 = simd24.front();
+                       simd24.pop_front();
+                       Cell *lane2 = simd24.front();
+                       simd24.pop_front();
+
+                       log("Analysing %s.%s for Xilinx DSP SIMD24 packing.\n", log_id(module), log_id(lane1));
+
+                       Cell *cell = addDsp(module);
+                       cell->setParam("\\USE_SIMD", Const("TWO24"));
+                       // X = A:B
+                       // Y = 0
+                       // Z = C
+                       cell->setPort("\\OPMODE", Const::from_string("0110011"));
+
+                       log_assert(lane1);
+                       log_assert(lane2);
+                       f24(AB, C, P, CARRYOUT, lane1);
+                       f24(AB, C, P, CARRYOUT, lane2);
+                       log_assert(GetSize(AB) == 48);
+                       log_assert(GetSize(C) == 48);
+                       log_assert(GetSize(P) == 48);
+                       log_assert(GetSize(CARRYOUT) == 4);
+                       cell->setPort("\\A", AB.extract(18, 30));
+                       cell->setPort("\\B", AB.extract(0, 18));
+                       cell->setPort("\\C", C);
+                       cell->setPort("\\P", P);
+                       cell->setPort("\\CARRYOUT", CARRYOUT);
+                       if (lane1->type == "$sub")
+                               cell->setPort("\\ALUMODE", Const::from_string("0011"));
+
+                       module->remove(lane1);
+                       module->remove(lane2);
+
+                       module->design->select(module, cell);
+               }
+       };
+       g24(simd24_add);
+       g24(simd24_sub);
 }