Improved maccmap tree bit packing

This commit is contained in:
Clifford Wolf 2014-09-15 12:00:19 +02:00
parent 2cbdbaad1f
commit fcbda07411
1 changed files with 50 additions and 16 deletions

View File

@ -126,14 +126,14 @@ struct MaccmapWorker
int tree_bit_slots(int n) int tree_bit_slots(int n)
{ {
#if 0 #if 0
int retval = 0; int retval = 1;
while (n > 2) { while (n > 2) {
retval += n / 3; retval += n / 3;
n = 2*(n / 3) + (n % 3); n = 2*(n / 3) + (n % 3);
} }
return retval; return retval;
#else #else
return std::max(n - 2, 0); return std::max(n - 1, 0);
#endif #endif
} }
@ -142,6 +142,7 @@ struct MaccmapWorker
std::vector<RTLIL::SigSpec> summands; std::vector<RTLIL::SigSpec> summands;
std::vector<RTLIL::SigBit> tree_sum_bits; std::vector<RTLIL::SigBit> tree_sum_bits;
int unique_tree_bits = 0; int unique_tree_bits = 0;
int count_tree_words = 0;
while (1) while (1)
{ {
@ -160,27 +161,55 @@ struct MaccmapWorker
break; break;
summands.push_back(summand); summands.push_back(summand);
while (1)
{
int free_bit_slots = tree_bit_slots(SIZE(summands)) - SIZE(tree_sum_bits); int free_bit_slots = tree_bit_slots(SIZE(summands)) - SIZE(tree_sum_bits);
for (int i = 0; i < width && (1 << i) <= free_bit_slots; i++) int max_depth = 0, max_position = 0;
while (!bits.at(i).empty() && (1 << i) <= free_bit_slots) { for (int i = 0; i < width; i++)
if (max_depth <= SIZE(bits.at(i))) {
max_depth = SIZE(bits.at(i));
max_position = i;
}
if (max_depth == 0 || max_position > 4)
break;
int required_bits = 0;
for (int i = 0; i <= max_position; i++)
if (SIZE(bits.at(i)) == max_depth)
required_bits += 1 << i;
if (required_bits > free_bit_slots)
break;
for (int i = 0; i <= max_position; i++)
if (SIZE(bits.at(i)) == max_depth) {
auto it = bits.at(i).begin(); auto it = bits.at(i).begin();
RTLIL::SigBit bit = *it; RTLIL::SigBit bit = *it;
bits.at(i).erase(it);
for (int k = 0; k < (1 << i); k++, free_bit_slots--) for (int k = 0; k < (1 << i); k++, free_bit_slots--)
tree_sum_bits.push_back(bit); tree_sum_bits.push_back(bit);
bits.at(i).erase(it);
unique_tree_bits++; unique_tree_bits++;
} }
count_tree_words++;
}
} }
if (!tree_sum_bits.empty()) if (!tree_sum_bits.empty())
log(" packed %d (%d) bits into adder tree\n", SIZE(tree_sum_bits), unique_tree_bits); log(" packed %d (%d) bits / %d words into adder tree\n", SIZE(tree_sum_bits), unique_tree_bits, count_tree_words);
if (SIZE(summands) == 0) if (SIZE(summands) == 0) {
log_assert(tree_sum_bits.empty());
return RTLIL::SigSpec(0, width); return RTLIL::SigSpec(0, width);
}
if (SIZE(summands) == 1) if (SIZE(summands) == 1) {
log_assert(tree_sum_bits.empty());
return summands.front(); return summands.front();
}
while (SIZE(summands) > 2) while (SIZE(summands) > 2)
{ {
@ -206,7 +235,6 @@ struct MaccmapWorker
summands.swap(new_summands); summands.swap(new_summands);
} }
log_assert(tree_sum_bits.empty());
RTLIL::Cell *c = module->addCell(NEW_ID, "$alu"); RTLIL::Cell *c = module->addCell(NEW_ID, "$alu");
c->setPort("\\A", summands.front()); c->setPort("\\A", summands.front());
@ -218,6 +246,12 @@ struct MaccmapWorker
c->setPort("\\CO", module->addWire(NEW_ID, width)); c->setPort("\\CO", module->addWire(NEW_ID, width));
c->fixup_parameters(); c->fixup_parameters();
if (!tree_sum_bits.empty()) {
c->setPort("\\CI", tree_sum_bits.back());
tree_sum_bits.pop_back();
}
log_assert(tree_sum_bits.empty());
return c->getPort("\\Y"); return c->getPort("\\Y");
} }
}; };