Fix multiple issues in wreduce FF handling, fixes #835

Signed-off-by: Clifford Wolf <clifford@clifford.at>
This commit is contained in:
Clifford Wolf 2019-02-28 17:24:46 -08:00
parent f505a41b76
commit e847690bda
1 changed files with 24 additions and 5 deletions

View File

@ -53,6 +53,7 @@ struct WreduceWorker
std::set<Cell*, IdString::compare_ptr_by_name<Cell>> work_queue_cells;
std::set<SigBit> work_queue_bits;
pool<SigBit> keep_bits;
dict<SigBit, State> init_bits;
WreduceWorker(WreduceConfig *config, Module *module) :
config(config), module(module), mi(module) { }
@ -141,6 +142,7 @@ struct WreduceWorker
SigSpec sig_d = mi.sigmap(cell->getPort("\\D"));
SigSpec sig_q = mi.sigmap(cell->getPort("\\Q"));
Const initval;
int width_before = GetSize(sig_q);
@ -150,16 +152,24 @@ struct WreduceWorker
bool zero_ext = sig_d[GetSize(sig_d)-1] == State::S0;
bool sign_ext = !zero_ext;
for (int i = 0; i < GetSize(sig_q); i++) {
SigBit bit = sig_q[i];
if (init_bits.count(bit))
initval.bits.push_back(init_bits.at(bit));
else
initval.bits.push_back(State::Sx);
}
for (int i = GetSize(sig_q)-1; i >= 0; i--)
{
if (zero_ext && sig_d[i] == State::S0) {
if (zero_ext && sig_d[i] == State::S0 && (initval[i] == State::S0 || initval[i] == State::Sx)) {
module->connect(sig_q[i], State::S0);
sig_d.remove(i);
sig_q.remove(i);
continue;
}
if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1]) {
if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1] && initval[i] == initval[i-1]) {
module->connect(sig_q[i], sig_q[i-1]);
sig_d.remove(i);
sig_q.remove(i);
@ -167,7 +177,7 @@ struct WreduceWorker
}
auto info = mi.query(sig_q[i]);
if (!info->is_output && GetSize(info->ports) <= 1 && !keep_bits.count(mi.sigmap(sig_q[i]))) {
if (!info->is_output && GetSize(info->ports) == 1 && !keep_bits.count(mi.sigmap(sig_q[i]))) {
sig_d.remove(i);
sig_q.remove(i);
zero_ext = false;
@ -183,10 +193,11 @@ struct WreduceWorker
if (GetSize(sig_q) == 0) {
log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type));
module->remove(cell);
return;
}
log("Removed top %d bits (of %d) from mux cell %s.%s (%s).\n", width_before - GetSize(sig_q), width_before,
log("Removed top %d bits (of %d) from FF cell %s.%s (%s).\n", width_before - GetSize(sig_q), width_before,
log_id(module), log_id(cell), log_id(cell->type));
for (auto bit : sig_d)
@ -376,10 +387,18 @@ struct WreduceWorker
void run()
{
for (auto w : module->wires())
for (auto w : module->wires()) {
if (w->get_bool_attribute("\\keep"))
for (auto bit : mi.sigmap(w))
keep_bits.insert(bit);
if (w->attributes.count("\\init")) {
Const initval = w->attributes.at("\\init");
SigSpec initsig = mi.sigmap(w);
int width = std::min(GetSize(initval), GetSize(initsig));
for (int i = 0; i < width; i++)
init_bits[initsig[i]] = initval[i];
}
}
for (auto c : module->selected_cells())
work_queue_cells.insert(c);