3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-13 04:28:18 +00:00
This commit is contained in:
Eddie Hung 2019-03-16 12:49:46 -07:00
parent fadeadb8c8
commit d6d9ef0fee

View file

@ -95,7 +95,7 @@ struct ShregmapTechGreenpak4 : ShregmapTech
struct ShregmapTechXilinx7 : ShregmapTech struct ShregmapTechXilinx7 : ShregmapTech
{ {
dict<SigBit, Cell*> sigbit_to_shiftx; dict<SigBit, std::pair<Cell*,int>> sigbit_to_shiftx_offset;
const ShregmapOptions &opts; const ShregmapOptions &opts;
ShregmapTechXilinx7(const ShregmapOptions &opts) : opts(opts) {} ShregmapTechXilinx7(const ShregmapOptions &opts) : opts(opts) {}
@ -106,19 +106,21 @@ struct ShregmapTechXilinx7 : ShregmapTech
auto cell = i.second; auto cell = i.second;
if (cell->type != "$shiftx") continue; if (cell->type != "$shiftx") continue;
if (cell->getParam("\\Y_WIDTH") != 1) continue; if (cell->getParam("\\Y_WIDTH") != 1) continue;
int j = 0;
for (auto bit : sigmap(cell->getPort("\\A"))) for (auto bit : sigmap(cell->getPort("\\A")))
sigbit_to_shiftx[bit] = cell; sigbit_to_shiftx_offset[bit] = std::make_pair(cell, j++);
log_assert(j == cell->getParam("\\A_WIDTH").as_int());
} }
} }
virtual void non_chain_user(const SigBit &bit, const Cell *cell, IdString port) override virtual void non_chain_user(const SigBit &bit, const Cell *cell, IdString port) override
{ {
auto it = sigbit_to_shiftx.find(bit); auto it = sigbit_to_shiftx_offset.find(bit);
if (it == sigbit_to_shiftx.end()) if (it == sigbit_to_shiftx_offset.end())
return; return;
if (cell->type == "$shiftx" && port == "\\A") if (cell->type == "$shiftx" && port == "\\A")
return; return;
it->second = nullptr; it->second = std::make_pair(nullptr, 0);
} }
virtual bool analyze(vector<int> &taps, const vector<SigBit> &qbits) override virtual bool analyze(vector<int> &taps, const vector<SigBit> &qbits) override
@ -130,32 +132,34 @@ struct ShregmapTechXilinx7 : ShregmapTech
return false; return false;
Cell *shiftx = nullptr; Cell *shiftx = nullptr;
int offset = 0;
for (int i = 0; i < GetSize(taps); ++i) { for (int i = 0; i < GetSize(taps); ++i) {
// Check taps are sequential // Check taps are sequential
if (i != taps[i]) if (i != taps[i])
return false; return false;
// Check taps are not connected to a shift register, // Check taps are not connected to a shift register,
// or sequential to the same shift register // or sequential to the same shift register
auto it = sigbit_to_shiftx.find(qbits[i]); auto it = sigbit_to_shiftx_offset.find(qbits[i]);
if (i == 0) { if (i == 0) {
if (it != sigbit_to_shiftx.end()) { if (it != sigbit_to_shiftx_offset.end()) {
shiftx = it->second; shiftx = it->second.first;
// NULL indicates there are non-shiftx users // NULL indicates there are non-shiftx users
if (shiftx == nullptr) if (shiftx == nullptr)
return false; return false;
offset = qbits[i].offset; int offset = it->second.second;
if (offset != i)
return false;
} }
} }
else { else {
if (it == sigbit_to_shiftx.end()) { if (it == sigbit_to_shiftx_offset.end()) {
if (shiftx != nullptr) if (shiftx != nullptr)
return false; return false;
} }
else { else {
if (shiftx != it->second) if (shiftx != it->second.first)
return false; return false;
if (qbits[i].offset != offset + i) int offset = it->second.second;
if (offset != i)
return false; return false;
} }
} }
@ -178,36 +182,22 @@ struct ShregmapTechXilinx7 : ShregmapTech
{ {
const auto &tap = *taps.begin(); const auto &tap = *taps.begin();
auto bit = tap.second; auto bit = tap.second;
auto it = sigbit_to_shiftx.find(bit); auto it = sigbit_to_shiftx_offset.find(bit);
if (it == sigbit_to_shiftx.end()) // If fixed-length, no fixup necessary
if (it == sigbit_to_shiftx_offset.end())
return true; return true;
Cell* shiftx = it->second; auto cell_q = cell->getPort("\\Q");
auto shiftx_a = shiftx->getPort("\\A").bits(); log_assert(cell_q.is_bit());
auto cell_q = cell->getPort("\\Q").as_bit();
int offset = 0;
#ifndef NDEBUG
for (auto bit : shiftx_a) {
if (bit == cell_q)
break;
++offset;
}
offset -= taps.size() - 1;
log_assert(offset == 0);
#endif
for (size_t i = offset; i < offset + taps.size(); ++i)
shiftx_a[i] = cell_q;
Cell* shiftx = it->second.first;
// FIXME: Hack to ensure that $shiftx gets optimised away // FIXME: Hack to ensure that $shiftx gets optimised away
// Without this, Yosys will refuse to optimise away a $shiftx // Without this, Yosys will refuse to optimise away a $shiftx
// where \\A 's width is not perfectly \\B_WIDTH ** 2 // where \\A 's width is not perfectly \\B_WIDTH ** 2
// See YosysHQ/yosys#878 // See YosysHQ/yosys#878
auto shiftx_bwidth = shiftx->getParam("\\B_WIDTH").as_int(); auto shiftx_bwidth = shiftx->getParam("\\B_WIDTH").as_int();
shiftx_a.resize(1 << shiftx_bwidth, shiftx_a.back()); shiftx->setPort("\\A", cell_q.repeat(1 << shiftx_bwidth));
shiftx->setPort("\\A", shiftx_a); shiftx->setParam("\\A_WIDTH", 1 << shiftx_bwidth);
shiftx->setParam("\\A_WIDTH", shiftx_a.size());
cell->setPort("\\L", shiftx->getPort("\\B")); cell->setPort("\\L", shiftx->getPort("\\B"));