diff --git a/passes/opt/opt_dff.cc b/passes/opt/opt_dff.cc index 8539432c0..05d759cb7 100644 --- a/passes/opt/opt_dff.cc +++ b/passes/opt/opt_dff.cc @@ -61,6 +61,9 @@ struct OptDffWorker // Used as a queue. std::vector dff_cells; + std::map ce_cache; + std::map srst_cache; + OptDffWorker(const OptDffOptions &opt, Module *mod) : opt(opt), module(mod), sigmap(mod), initvals(&sigmap, mod) { // Gathering two kinds of information here for every sigmapped SigBit: // @@ -630,6 +633,8 @@ struct OptDffWorker } for (auto &it : groups) { + if (ff.has_srst && srst_cache[cell] == it.first) + continue; FfData new_ff = ff.slice(it.second); new_ff.val_srst = Const(); for (int i = 0; i < new_ff.width; i++) { @@ -644,8 +649,10 @@ struct OptDffWorker if (new_ff.has_ce) new_ff.ce_over_srst = true; Cell *new_cell = new_ff.emit(); - if (new_cell) + if (new_cell) { dff_cells.push_back(new_cell); + srst_cache[new_cell] = it.first; + } log("Adding SRST signal on %s (%s) from module %s (D = %s, Q = %s, rval = %s).\n", log_id(cell), log_id(cell->type), log_id(module), log_signal(new_ff.sig_d), log_signal(new_ff.sig_q), log_signal(new_ff.val_srst)); } @@ -699,6 +706,8 @@ struct OptDffWorker } for (auto &it : groups) { + if (ff.has_ce && ce_cache[cell] == it.first.first) + continue; FfData new_ff = ff.slice(it.second); ctrl_t en = make_patterns_logic(it.first.first, it.first.second, ff.is_fine); @@ -707,8 +716,10 @@ struct OptDffWorker new_ff.pol_ce = en.second; new_ff.ce_over_srst = false; Cell *new_cell = new_ff.emit(); - if (new_cell) + if (new_cell){ dff_cells.push_back(new_cell); + ce_cache[new_cell] = it.first.first; + } log("Adding EN signal on %s (%s) from module %s (D = %s, Q = %s).\n", log_id(cell), log_id(cell->type), log_id(module), log_signal(new_ff.sig_d), log_signal(new_ff.sig_q)); } diff --git a/tests/opt/bug4979.ys b/tests/opt/bug4979.ys new file mode 100644 index 000000000..c43f72529 --- /dev/null +++ b/tests/opt/bug4979.ys @@ -0,0 +1,36 @@ +read_verilog << EOT +module a ( + input b, + input h, + input i, + output reg o +); + wire c, j, k, e, g; + + reg l, n, d, f; + + always @(posedge b or negedge c) begin + if (c) begin + o = j > l; + l = (l | j) ? k ? h : i ? 0 : n : 0; + end + end + + always @(h) begin + d = k; + end + + always @(e or g or f) begin + if (e) begin + l = 0; + end else begin + d = g; + l = f; + end + end + +endmodule +EOT + +synth -run coarse +opt -undriven