mirror of https://github.com/YosysHQ/yosys.git
Support subtraction as well
This commit is contained in:
parent
31e60353ac
commit
02cf9933b9
|
@ -59,10 +59,11 @@ static Cell* addDsp(Module *module) {
|
||||||
|
|
||||||
void pack_xilinx_simd(Module *module, const std::vector<Cell*> &selected_cells)
|
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) {
|
for (auto cell : selected_cells) {
|
||||||
if (!cell->type.in("$add"))
|
if (!cell->type.in("$add", "$sub"))
|
||||||
continue;
|
continue;
|
||||||
SigSpec Y = cell->getPort("\\Y");
|
SigSpec Y = cell->getPort("\\Y");
|
||||||
if (!Y.is_chunk())
|
if (!Y.is_chunk())
|
||||||
|
@ -78,24 +79,26 @@ void pack_xilinx_simd(Module *module, const std::vector<Cell*> &selected_cells)
|
||||||
continue;
|
continue;
|
||||||
if (GetSize(B) > 12)
|
if (GetSize(B) > 12)
|
||||||
continue;
|
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) {
|
else if (GetSize(Y) <= 25) {
|
||||||
if (GetSize(A) > 24)
|
if (GetSize(A) > 24)
|
||||||
continue;
|
continue;
|
||||||
if (GetSize(B) > 24)
|
if (GetSize(B) > 24)
|
||||||
continue;
|
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
|
else
|
||||||
log_abort();
|
log_abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
SigSpec AB;
|
auto f12 = [module](SigSpec &AB, SigSpec &C, SigSpec &P, SigSpec &CARRYOUT, Cell *lane) {
|
||||||
SigSpec C;
|
|
||||||
SigSpec P;
|
|
||||||
SigSpec CARRYOUT;
|
|
||||||
auto f12 = [&AB,&C,&P,&CARRYOUT,module](Cell *lane) {
|
|
||||||
SigSpec A = lane->getPort("\\A");
|
SigSpec A = lane->getPort("\\A");
|
||||||
SigSpec B = lane->getPort("\\B");
|
SigSpec B = lane->getPort("\\B");
|
||||||
SigSpec Y = lane->getPort("\\Y");
|
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));
|
P.append(Y.extract(0, 12));
|
||||||
CARRYOUT.append(Y[12]);
|
CARRYOUT.append(Y[12]);
|
||||||
};
|
};
|
||||||
while (simd12.size() > 1) {
|
auto g12 = [&f12,module](std::deque<Cell*> &simd12) {
|
||||||
AB = SigSpec();
|
while (simd12.size() > 1) {
|
||||||
C = SigSpec();
|
SigSpec AB, C, P, CARRYOUT;
|
||||||
P = SigSpec();
|
|
||||||
CARRYOUT = SigSpec();
|
|
||||||
|
|
||||||
Cell *lane1 = simd12.front();
|
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();
|
|
||||||
simd12.pop_front();
|
simd12.pop_front();
|
||||||
|
Cell *lane2 = simd12.front();
|
||||||
|
simd12.pop_front();
|
||||||
|
Cell *lane3 = nullptr;
|
||||||
|
Cell *lane4 = nullptr;
|
||||||
|
|
||||||
if (!simd12.empty()) {
|
if (!simd12.empty()) {
|
||||||
lane4 = simd12.front();
|
lane3 = simd12.front();
|
||||||
simd12.pop_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));
|
log("Analysing %s.%s for Xilinx DSP SIMD12 packing.\n", log_id(module), log_id(lane1));
|
||||||
|
|
||||||
Cell *cell = addDsp(module);
|
Cell *cell = addDsp(module);
|
||||||
cell->setParam("\\USE_SIMD", Const("FOUR12"));
|
cell->setParam("\\USE_SIMD", Const("FOUR12"));
|
||||||
// X = A:B
|
// X = A:B
|
||||||
// Y = 0
|
// Y = 0
|
||||||
// Z = C
|
// Z = C
|
||||||
cell->setPort("\\OPMODE", Const::from_string("0110011"));
|
cell->setPort("\\OPMODE", Const::from_string("0110011"));
|
||||||
|
|
||||||
log_assert(lane1);
|
log_assert(lane1);
|
||||||
log_assert(lane2);
|
log_assert(lane2);
|
||||||
f12(lane1);
|
f12(AB, C, P, CARRYOUT, lane1);
|
||||||
f12(lane2);
|
f12(AB, C, P, CARRYOUT, lane2);
|
||||||
if (lane3) {
|
if (lane3) {
|
||||||
f12(lane3);
|
f12(AB, C, P, CARRYOUT, lane3);
|
||||||
if (lane4)
|
if (lane4)
|
||||||
f12(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 {
|
else {
|
||||||
AB.append(Const(0, 12));
|
AB.append(Const(0, 24));
|
||||||
C.append(Const(0, 12));
|
C.append(Const(0, 24));
|
||||||
P.append(module->addWire(NEW_ID, 12));
|
P.append(module->addWire(NEW_ID, 24));
|
||||||
CARRYOUT.append(module->addWire(NEW_ID, 1));
|
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));
|
g12(simd12_add);
|
||||||
C.append(Const(0, 24));
|
g12(simd12_sub);
|
||||||
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);
|
auto f24 = [module](SigSpec &AB, SigSpec &C, SigSpec &P, SigSpec &CARRYOUT, Cell *lane) {
|
||||||
module->remove(lane2);
|
|
||||||
if (lane3) module->remove(lane3);
|
|
||||||
if (lane4) module->remove(lane4);
|
|
||||||
|
|
||||||
module->design->select(module, cell);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto f24 = [&AB,&C,&P,&CARRYOUT,module](Cell *lane) {
|
|
||||||
SigSpec A = lane->getPort("\\A");
|
SigSpec A = lane->getPort("\\A");
|
||||||
SigSpec B = lane->getPort("\\B");
|
SigSpec B = lane->getPort("\\B");
|
||||||
SigSpec Y = lane->getPort("\\Y");
|
SigSpec Y = lane->getPort("\\Y");
|
||||||
A.extend_u0(24, lane->getParam("\\A_SIGNED").as_bool());
|
A.extend_u0(24, lane->getParam("\\A_SIGNED").as_bool());
|
||||||
B.extend_u0(24, lane->getParam("\\B_SIGNED").as_bool());
|
B.extend_u0(24, lane->getParam("\\B_SIGNED").as_bool());
|
||||||
AB.append(A);
|
AB.append(B);
|
||||||
C.append(B);
|
|
||||||
if (GetSize(Y) < 25)
|
if (GetSize(Y) < 25)
|
||||||
Y.append(module->addWire(NEW_ID, 25-GetSize(Y)));
|
Y.append(module->addWire(NEW_ID, 25-GetSize(Y)));
|
||||||
else
|
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(module->addWire(NEW_ID)); // TWO24 uses every other bit
|
||||||
CARRYOUT.append(Y[24]);
|
CARRYOUT.append(Y[24]);
|
||||||
};
|
};
|
||||||
while (simd24.size() > 1) {
|
auto g24 = [&f24,module](std::deque<Cell*> &simd24) {
|
||||||
AB = SigSpec();
|
while (simd24.size() > 1) {
|
||||||
C = SigSpec();
|
SigSpec AB;
|
||||||
P = SigSpec();
|
SigSpec C;
|
||||||
CARRYOUT = SigSpec();
|
SigSpec P;
|
||||||
|
SigSpec CARRYOUT;
|
||||||
|
|
||||||
Cell *lane1 = simd24.front();
|
Cell *lane1 = simd24.front();
|
||||||
simd24.pop_front();
|
simd24.pop_front();
|
||||||
Cell *lane2 = simd24.front();
|
Cell *lane2 = simd24.front();
|
||||||
simd24.pop_front();
|
simd24.pop_front();
|
||||||
|
|
||||||
log("Analysing %s.%s for Xilinx DSP SIMD24 packing.\n", log_id(module), log_id(lane1));
|
log("Analysing %s.%s for Xilinx DSP SIMD24 packing.\n", log_id(module), log_id(lane1));
|
||||||
|
|
||||||
Cell *cell = addDsp(module);
|
Cell *cell = addDsp(module);
|
||||||
cell->setParam("\\USE_SIMD", Const("TWO24"));
|
cell->setParam("\\USE_SIMD", Const("TWO24"));
|
||||||
// X = A:B
|
// X = A:B
|
||||||
// Y = 0
|
// Y = 0
|
||||||
// Z = C
|
// Z = C
|
||||||
cell->setPort("\\OPMODE", Const::from_string("0110011"));
|
cell->setPort("\\OPMODE", Const::from_string("0110011"));
|
||||||
|
|
||||||
log_assert(lane1);
|
log_assert(lane1);
|
||||||
log_assert(lane2);
|
log_assert(lane2);
|
||||||
f24(lane1);
|
f24(AB, C, P, CARRYOUT, lane1);
|
||||||
f24(lane2);
|
f24(AB, C, P, CARRYOUT, lane2);
|
||||||
log_assert(GetSize(AB) == 48);
|
log_assert(GetSize(AB) == 48);
|
||||||
log_assert(GetSize(C) == 48);
|
log_assert(GetSize(C) == 48);
|
||||||
log_assert(GetSize(P) == 48);
|
log_assert(GetSize(P) == 48);
|
||||||
log_assert(GetSize(CARRYOUT) == 4);
|
log_assert(GetSize(CARRYOUT) == 4);
|
||||||
cell->setPort("\\A", AB.extract(18, 30));
|
cell->setPort("\\A", AB.extract(18, 30));
|
||||||
cell->setPort("\\B", AB.extract(0, 18));
|
cell->setPort("\\B", AB.extract(0, 18));
|
||||||
cell->setPort("\\C", C);
|
cell->setPort("\\C", C);
|
||||||
cell->setPort("\\P", P);
|
cell->setPort("\\P", P);
|
||||||
cell->setPort("\\CARRYOUT", CARRYOUT);
|
cell->setPort("\\CARRYOUT", CARRYOUT);
|
||||||
|
if (lane1->type == "$sub")
|
||||||
|
cell->setPort("\\ALUMODE", Const::from_string("0011"));
|
||||||
|
|
||||||
module->remove(lane1);
|
module->remove(lane1);
|
||||||
module->remove(lane2);
|
module->remove(lane2);
|
||||||
|
|
||||||
module->design->select(module, cell);
|
module->design->select(module, cell);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
g24(simd24_add);
|
||||||
|
g24(simd24_sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue