diff options
author | Marcelina KoĆcielnicka <mwk@0x04.net> | 2021-10-01 23:50:48 +0200 |
---|---|---|
committer | Marcelina KoĆcielnicka <mwk@0x04.net> | 2021-10-02 20:19:48 +0200 |
commit | 63b9df8693840d17def8abcb0e848112283b0231 (patch) | |
tree | 7cb46fa0119760ef17d9d8d3999090cb71342d40 /passes/sat | |
parent | ec2b5548fe9b8d291365a84a0c3fc87654643359 (diff) | |
download | yosys-63b9df8693840d17def8abcb0e848112283b0231.tar.gz yosys-63b9df8693840d17def8abcb0e848112283b0231.tar.bz2 yosys-63b9df8693840d17def8abcb0e848112283b0231.zip |
kernel/ff: Refactor FfData to enable FFs with async load.
- *_en is split into *_ce (clock enable) and *_aload (async load aka
latch gate enable), so both can be present at once
- has_d is removed
- has_gclk is added (to have a clear marker for $ff)
- d_is_const and val_d leftovers are removed
- async2sync, clk2fflogic, opt_dff are updated to operate correctly on
FFs with async load
Diffstat (limited to 'passes/sat')
-rw-r--r-- | passes/sat/async2sync.cc | 61 | ||||
-rw-r--r-- | passes/sat/clk2fflogic.cc | 34 |
2 files changed, 64 insertions, 31 deletions
diff --git a/passes/sat/async2sync.cc b/passes/sat/async2sync.cc index a2b51677e..f1b93d084 100644 --- a/passes/sat/async2sync.cc +++ b/passes/sat/async2sync.cc @@ -41,8 +41,6 @@ struct Async2syncPass : public Pass { log("reset value in the next cycle regardless of the data-in value at the time of\n"); log("the clock edge.\n"); log("\n"); - log("Currently only $adff, $dffsr, and $dlatch cells are supported by this pass.\n"); - log("\n"); } void execute(std::vector<std::string> args, RTLIL::Design *design) override { @@ -74,14 +72,11 @@ struct Async2syncPass : public Pass { FfData ff(&initvals, cell); // Skip for $_FF_ and $ff cells. - if (ff.has_d && !ff.has_clk && !ff.has_en) + if (ff.has_gclk) continue; if (ff.has_clk) { - if (!ff.has_sr && !ff.has_arst) - continue; - if (ff.has_sr) { ff.unmap_ce_srst(module); @@ -128,6 +123,39 @@ struct Async2syncPass : public Pass { ff.sig_d = new_d; ff.sig_q = new_q; ff.has_sr = false; + } else if (ff.has_aload) { + ff.unmap_ce_srst(module); + + log("Replacing %s.%s (%s): ALOAD=%s, AD=%s, D=%s, Q=%s\n", + log_id(module), log_id(cell), log_id(cell->type), + log_signal(ff.sig_aload), log_signal(ff.sig_ad), log_signal(ff.sig_d), log_signal(ff.sig_q)); + + initvals.remove_init(ff.sig_q); + + Wire *new_d = module->addWire(NEW_ID, ff.width); + Wire *new_q = module->addWire(NEW_ID, ff.width); + + if (ff.pol_aload) { + if (!ff.is_fine) { + module->addMux(NEW_ID, new_q, ff.sig_ad, ff.sig_aload, ff.sig_q); + module->addMux(NEW_ID, ff.sig_d, ff.sig_ad, ff.sig_aload, new_d); + } else { + module->addMuxGate(NEW_ID, new_q, ff.sig_ad, ff.sig_aload, ff.sig_q); + module->addMuxGate(NEW_ID, ff.sig_d, ff.sig_ad, ff.sig_aload, new_d); + } + } else { + if (!ff.is_fine) { + module->addMux(NEW_ID, ff.sig_ad, new_q, ff.sig_aload, ff.sig_q); + module->addMux(NEW_ID, ff.sig_ad, ff.sig_d, ff.sig_aload, new_d); + } else { + module->addMuxGate(NEW_ID, ff.sig_ad, new_q, ff.sig_aload, ff.sig_q); + module->addMuxGate(NEW_ID, ff.sig_ad, ff.sig_d, ff.sig_aload, new_d); + } + } + + ff.sig_d = new_d; + ff.sig_q = new_q; + ff.has_aload = false; } else if (ff.has_arst) { ff.unmap_srst(module); @@ -154,9 +182,12 @@ struct Async2syncPass : public Pass { ff.sig_q = new_q; ff.has_arst = false; ff.has_srst = true; + ff.ce_over_srst = false; ff.val_srst = ff.val_arst; ff.sig_srst = ff.sig_arst; ff.pol_srst = ff.pol_arst; + } else { + continue; } } else @@ -164,25 +195,25 @@ struct Async2syncPass : public Pass { // Latch. log("Replacing %s.%s (%s): EN=%s, D=%s, Q=%s\n", log_id(module), log_id(cell), log_id(cell->type), - log_signal(ff.sig_en), log_signal(ff.sig_d), log_signal(ff.sig_q)); + log_signal(ff.sig_aload), log_signal(ff.sig_ad), log_signal(ff.sig_q)); initvals.remove_init(ff.sig_q); Wire *new_q = module->addWire(NEW_ID, ff.width); Wire *new_d; - if (ff.has_d) { + if (ff.has_aload) { new_d = module->addWire(NEW_ID, ff.width); - if (ff.pol_en) { + if (ff.pol_aload) { if (!ff.is_fine) - module->addMux(NEW_ID, new_q, ff.sig_d, ff.sig_en, new_d); + module->addMux(NEW_ID, new_q, ff.sig_ad, ff.sig_aload, new_d); else - module->addMuxGate(NEW_ID, new_q, ff.sig_d, ff.sig_en, new_d); + module->addMuxGate(NEW_ID, new_q, ff.sig_ad, ff.sig_aload, new_d); } else { if (!ff.is_fine) - module->addMux(NEW_ID, ff.sig_d, new_q, ff.sig_en, new_d); + module->addMux(NEW_ID, ff.sig_ad, new_q, ff.sig_aload, new_d); else - module->addMuxGate(NEW_ID, ff.sig_d, new_q, ff.sig_en, new_d); + module->addMuxGate(NEW_ID, ff.sig_ad, new_q, ff.sig_aload, new_d); } } else { new_d = new_q; @@ -231,10 +262,10 @@ struct Async2syncPass : public Pass { ff.sig_d = new_d; ff.sig_q = new_q; - ff.has_en = false; + ff.has_aload = false; ff.has_arst = false; ff.has_sr = false; - ff.has_d = true; + ff.has_gclk = true; } IdString name = cell->name; diff --git a/passes/sat/clk2fflogic.cc b/passes/sat/clk2fflogic.cc index 062083972..d90206b46 100644 --- a/passes/sat/clk2fflogic.cc +++ b/passes/sat/clk2fflogic.cc @@ -148,7 +148,7 @@ struct Clk2fflogicPass : public Pass { if (RTLIL::builtin_ff_cell_types().count(cell->type)) { FfData ff(&initvals, cell); - if (ff.has_d && !ff.has_clk && !ff.has_en) { + if (ff.has_gclk) { // Already a $ff or $_FF_ cell. continue; } @@ -202,25 +202,27 @@ struct Clk2fflogicPass : public Pass { qval = module->Mux(NEW_ID, past_q, past_d, clock_edge); else qval = module->MuxGate(NEW_ID, past_q, past_d, clock_edge); - } else if (ff.has_d) { - - log("Replacing %s.%s (%s): EN=%s, D=%s, Q=%s\n", - log_id(module), log_id(cell), log_id(cell->type), - log_signal(ff.sig_en), log_signal(ff.sig_d), log_signal(ff.sig_q)); + } else { + if (ff.has_aload) { + log("Replacing %s.%s (%s): EN=%s, D=%s, Q=%s\n", + log_id(module), log_id(cell), log_id(cell->type), + log_signal(ff.sig_aload), log_signal(ff.sig_ad), log_signal(ff.sig_q)); + } else { + // $sr. + log("Replacing %s.%s (%s): SET=%s, CLR=%s, Q=%s\n", + log_id(module), log_id(cell), log_id(cell->type), + log_signal(ff.sig_set), log_signal(ff.sig_clr), log_signal(ff.sig_q)); + } + qval = past_q; + } - SigSpec sig_en = wrap_async_control(module, ff.sig_en, ff.pol_en); + if (ff.has_aload) { + SigSpec sig_aload = wrap_async_control(module, ff.sig_aload, ff.pol_aload); if (!ff.is_fine) - qval = module->Mux(NEW_ID, past_q, ff.sig_d, sig_en); + qval = module->Mux(NEW_ID, qval, ff.sig_ad, sig_aload); else - qval = module->MuxGate(NEW_ID, past_q, ff.sig_d, sig_en); - } else { - - log("Replacing %s.%s (%s): SET=%s, CLR=%s, Q=%s\n", - log_id(module), log_id(cell), log_id(cell->type), - log_signal(ff.sig_set), log_signal(ff.sig_clr), log_signal(ff.sig_q)); - - qval = past_q; + qval = module->MuxGate(NEW_ID, qval, ff.sig_ad, sig_aload); } if (ff.has_sr) { |