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) { }
SigSpec sig_d = mi.sigmap(cell->getPort("\\D"));
SigSpec sig_q = mi.sigmap(cell->getPort("\\Q"));
+ Const initval;
int width_before = GetSize(sig_q);
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);
}
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;
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)
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);