From 4a05cad7f8a6ee57292e5360eb06305e13fc308b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Fri, 24 Jul 2020 17:01:26 +0200 Subject: async2sync: Support all FF types. --- kernel/ff.h | 46 ++++++++ passes/sat/async2sync.cc | 260 ++++++++++++++++++++++++++++------------------ passes/sat/clk2fflogic.cc | 47 +-------- 3 files changed, 208 insertions(+), 145 deletions(-) diff --git a/kernel/ff.h b/kernel/ff.h index 8dc83eb49..0aecbaa2a 100644 --- a/kernel/ff.h +++ b/kernel/ff.h @@ -323,6 +323,52 @@ struct FfData { return res; } + void unmap_ce(Module *module) { + if (!has_en) + return; + log_assert(has_clk); + if (has_srst && ce_over_srst) + unmap_srst(module); + + if (!is_fine) { + if (pol_en) + sig_d = module->Mux(NEW_ID, sig_q, sig_d, sig_en); + else + sig_d = module->Mux(NEW_ID, sig_d, sig_q, sig_en); + } else { + if (pol_en) + sig_d = module->MuxGate(NEW_ID, sig_q, sig_d, sig_en); + else + sig_d = module->MuxGate(NEW_ID, sig_d, sig_q, sig_en); + } + has_en = false; + } + + void unmap_srst(Module *module) { + if (!has_srst) + return; + if (has_en && !ce_over_srst) + unmap_ce(module); + + if (!is_fine) { + if (pol_srst) + sig_d = module->Mux(NEW_ID, sig_d, val_srst, sig_srst); + else + sig_d = module->Mux(NEW_ID, val_srst, sig_d, sig_srst); + } else { + if (pol_srst) + sig_d = module->MuxGate(NEW_ID, sig_d, val_srst[0], sig_srst); + else + sig_d = module->MuxGate(NEW_ID, val_srst[0], sig_d, sig_srst); + } + has_srst = false; + } + + void unmap_ce_srst(Module *module) { + unmap_ce(module); + unmap_srst(module); + } + Cell *emit(Module *module, IdString name) { if (!width) return nullptr; diff --git a/passes/sat/async2sync.cc b/passes/sat/async2sync.cc index 970469fa0..3fa5a614c 100644 --- a/passes/sat/async2sync.cc +++ b/passes/sat/async2sync.cc @@ -20,6 +20,7 @@ #include "kernel/yosys.h" #include "kernel/sigtools.h" #include "kernel/ffinit.h" +#include "kernel/ff.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -67,121 +68,178 @@ struct Async2syncPass : public Pass { for (auto cell : vector(module->selected_cells())) { - if (cell->type.in(ID($adff))) - { - // bool clk_pol = cell->parameters[ID::CLK_POLARITY].as_bool(); - bool arst_pol = cell->parameters[ID::ARST_POLARITY].as_bool(); - Const arst_val = cell->parameters[ID::ARST_VALUE]; - - // SigSpec sig_clk = cell->getPort(ID::CLK); - SigSpec sig_arst = cell->getPort(ID::ARST); - SigSpec sig_d = cell->getPort(ID::D); - SigSpec sig_q = cell->getPort(ID::Q); - - log("Replacing %s.%s (%s): ARST=%s, D=%s, Q=%s\n", - log_id(module), log_id(cell), log_id(cell->type), - log_signal(sig_arst), log_signal(sig_d), log_signal(sig_q)); - - Const init_val = initvals(sig_q); - initvals.remove_init(sig_q); - - Wire *new_d = module->addWire(NEW_ID, GetSize(sig_d)); - Wire *new_q = module->addWire(NEW_ID, GetSize(sig_q)); - initvals.set_init(new_q, init_val); + if (!RTLIL::builtin_ff_cell_types().count(cell->type)) + continue; - if (arst_pol) { - module->addMux(NEW_ID, sig_d, arst_val, sig_arst, new_d); - module->addMux(NEW_ID, new_q, arst_val, sig_arst, sig_q); - } else { - module->addMux(NEW_ID, arst_val, sig_d, sig_arst, new_d); - module->addMux(NEW_ID, arst_val, new_q, sig_arst, sig_q); - } + FfData ff(&initvals, cell); - cell->setPort(ID::D, new_d); - cell->setPort(ID::Q, new_q); - cell->unsetPort(ID::ARST); - cell->unsetParam(ID::ARST_POLARITY); - cell->unsetParam(ID::ARST_VALUE); - cell->type = ID($dff); + // Skip for $_FF_ and $ff cells. + if (ff.has_d && !ff.has_clk && !ff.has_en) continue; - } - if (cell->type.in(ID($dffsr))) + if (ff.has_clk) { - // bool clk_pol = cell->parameters[ID::CLK_POLARITY].as_bool(); - bool set_pol = cell->parameters[ID::SET_POLARITY].as_bool(); - bool clr_pol = cell->parameters[ID::CLR_POLARITY].as_bool(); - - // SigSpec sig_clk = cell->getPort(ID::CLK); - SigSpec sig_set = cell->getPort(ID::SET); - SigSpec sig_clr = cell->getPort(ID::CLR); - SigSpec sig_d = cell->getPort(ID::D); - SigSpec sig_q = cell->getPort(ID::Q); - - log("Replacing %s.%s (%s): SET=%s, CLR=%s, D=%s, Q=%s\n", - log_id(module), log_id(cell), log_id(cell->type), - log_signal(sig_set), log_signal(sig_clr), log_signal(sig_d), log_signal(sig_q)); - - Const init_val = initvals(sig_q); - initvals.remove_init(sig_q); - - Wire *new_d = module->addWire(NEW_ID, GetSize(sig_d)); - Wire *new_q = module->addWire(NEW_ID, GetSize(sig_q)); - initvals.set_init(new_q, init_val); - - if (!set_pol) - sig_set = module->Not(NEW_ID, sig_set); - - if (clr_pol) - sig_clr = module->Not(NEW_ID, sig_clr); - - SigSpec tmp = module->Or(NEW_ID, sig_d, sig_set); - module->addAnd(NEW_ID, tmp, sig_clr, new_d); - - tmp = module->Or(NEW_ID, new_q, sig_set); - module->addAnd(NEW_ID, tmp, sig_clr, sig_q); - - cell->setPort(ID::D, new_d); - cell->setPort(ID::Q, new_q); - cell->unsetPort(ID::SET); - cell->unsetPort(ID::CLR); - cell->unsetParam(ID::SET_POLARITY); - cell->unsetParam(ID::CLR_POLARITY); - cell->type = ID($dff); - continue; + if (!ff.has_sr && !ff.has_arst) + continue; + + if (ff.has_sr) { + ff.unmap_ce_srst(module); + + log("Replacing %s.%s (%s): SET=%s, CLR=%s, D=%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_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); + + SigSpec sig_set = ff.sig_set; + SigSpec sig_clr = ff.sig_clr; + + if (!ff.pol_set) { + if (!ff.is_fine) + sig_set = module->Not(NEW_ID, sig_set); + else + sig_set = module->NotGate(NEW_ID, sig_set); + } + + if (ff.pol_clr) { + if (!ff.is_fine) + sig_clr = module->Not(NEW_ID, sig_clr); + else + sig_clr = module->NotGate(NEW_ID, sig_clr); + } + + if (!ff.is_fine) { + SigSpec tmp = module->Or(NEW_ID, ff.sig_d, sig_set); + module->addAnd(NEW_ID, tmp, sig_clr, new_d); + + tmp = module->Or(NEW_ID, new_q, sig_set); + module->addAnd(NEW_ID, tmp, sig_clr, ff.sig_q); + } else { + SigSpec tmp = module->OrGate(NEW_ID, ff.sig_d, sig_set); + module->addAndGate(NEW_ID, tmp, sig_clr, new_d); + + tmp = module->OrGate(NEW_ID, new_q, sig_set); + module->addAndGate(NEW_ID, tmp, sig_clr, ff.sig_q); + } + + ff.sig_d = new_d; + ff.sig_q = new_q; + ff.has_sr = false; + } else if (ff.has_arst) { + ff.unmap_srst(module); + + log("Replacing %s.%s (%s): ARST=%s, D=%s, Q=%s\n", + log_id(module), log_id(cell), log_id(cell->type), + log_signal(ff.sig_arst), log_signal(ff.sig_d), log_signal(ff.sig_q)); + + initvals.remove_init(ff.sig_q); + + Wire *new_q = module->addWire(NEW_ID, ff.width); + + if (ff.pol_arst) { + if (!ff.is_fine) + module->addMux(NEW_ID, new_q, ff.val_arst, ff.sig_arst, ff.sig_q); + else + module->addMuxGate(NEW_ID, new_q, ff.val_arst[0], ff.sig_arst, ff.sig_q); + } else { + if (!ff.is_fine) + module->addMux(NEW_ID, ff.val_arst, new_q, ff.sig_arst, ff.sig_q); + else + module->addMuxGate(NEW_ID, ff.val_arst[0], new_q, ff.sig_arst, ff.sig_q); + } + + ff.sig_q = new_q; + ff.has_arst = false; + ff.has_srst = true; + ff.val_srst = ff.val_arst; + ff.sig_srst = ff.sig_arst; + ff.pol_srst = ff.pol_arst; + } } - - if (cell->type.in(ID($dlatch))) + else { - bool en_pol = cell->parameters[ID::EN_POLARITY].as_bool(); - - SigSpec sig_en = cell->getPort(ID::EN); - SigSpec sig_d = cell->getPort(ID::D); - SigSpec sig_q = cell->getPort(ID::Q); - + // 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(sig_en), log_signal(sig_d), log_signal(sig_q)); - - Const init_val = initvals(sig_q); - initvals.remove_init(sig_q); - - Wire *new_q = module->addWire(NEW_ID, GetSize(sig_q)); - initvals.set_init(new_q, init_val); + log_signal(ff.sig_en), log_signal(ff.sig_d), 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) { + new_d = module->addWire(NEW_ID, ff.width); + if (ff.pol_en) { + if (!ff.is_fine) + module->addMux(NEW_ID, new_q, ff.sig_d, ff.sig_en, new_d); + else + module->addMuxGate(NEW_ID, new_q, ff.sig_d, ff.sig_en, new_d); + } else { + if (!ff.is_fine) + module->addMux(NEW_ID, ff.sig_d, new_q, ff.sig_en, new_d); + else + module->addMuxGate(NEW_ID, ff.sig_d, new_q, ff.sig_en, new_d); + } + } else { + new_d = new_q; + } - if (en_pol) { - module->addMux(NEW_ID, new_q, sig_d, sig_en, sig_q); + if (ff.has_sr) { + SigSpec sig_set = ff.sig_set; + SigSpec sig_clr = ff.sig_clr; + + if (!ff.pol_set) { + if (!ff.is_fine) + sig_set = module->Not(NEW_ID, sig_set); + else + sig_set = module->NotGate(NEW_ID, sig_set); + } + + if (ff.pol_clr) { + if (!ff.is_fine) + sig_clr = module->Not(NEW_ID, sig_clr); + else + sig_clr = module->NotGate(NEW_ID, sig_clr); + } + + if (!ff.is_fine) { + SigSpec tmp = module->Or(NEW_ID, new_d, sig_set); + module->addAnd(NEW_ID, tmp, sig_clr, ff.sig_q); + } else { + SigSpec tmp = module->OrGate(NEW_ID, new_d, sig_set); + module->addAndGate(NEW_ID, tmp, sig_clr, ff.sig_q); + } + } else if (ff.has_arst) { + if (ff.pol_arst) { + if (!ff.is_fine) + module->addMux(NEW_ID, new_d, ff.val_arst, ff.sig_arst, ff.sig_q); + else + module->addMuxGate(NEW_ID, new_d, ff.val_arst[0], ff.sig_arst, ff.sig_q); + } else { + if (!ff.is_fine) + module->addMux(NEW_ID, ff.val_arst, new_d, ff.sig_arst, ff.sig_q); + else + module->addMuxGate(NEW_ID, ff.val_arst[0], new_d, ff.sig_arst, ff.sig_q); + } } else { - module->addMux(NEW_ID, sig_d, new_q, sig_en, sig_q); + module->connect(ff.sig_q, new_d); } - cell->setPort(ID::D, sig_q); - cell->setPort(ID::Q, new_q); - cell->unsetPort(ID::EN); - cell->unsetParam(ID::EN_POLARITY); - cell->type = ID($ff); - continue; + ff.sig_d = new_d; + ff.sig_q = new_q; + ff.has_en = false; + ff.has_arst = false; + ff.has_sr = false; + ff.has_d = true; } + + IdString name = cell->name; + module->remove(cell); + ff.emit(module, name); } } } diff --git a/passes/sat/clk2fflogic.cc b/passes/sat/clk2fflogic.cc index f2a3dd0bf..2cb91c009 100644 --- a/passes/sat/clk2fflogic.cc +++ b/passes/sat/clk2fflogic.cc @@ -186,48 +186,7 @@ struct Clk2fflogicPass : public Pass { initvals.set_init(past_q, ff.val_init); if (ff.has_clk) { - SigSpec sig_d = ff.sig_d; - if (ff.has_srst && ff.has_en && ff.ce_over_srst) { - if (!ff.is_fine) { - if (ff.pol_srst) - sig_d = module->Mux(NEW_ID, sig_d, ff.val_srst, ff.sig_srst); - else - sig_d = module->Mux(NEW_ID, ff.val_srst, sig_d, ff.sig_srst); - } else { - if (ff.pol_srst) - sig_d = module->MuxGate(NEW_ID, sig_d, ff.val_srst[0], ff.sig_srst); - else - sig_d = module->MuxGate(NEW_ID, ff.val_srst[0], sig_d, ff.sig_srst); - } - } - - if (ff.has_en) { - if (!ff.is_fine) { - if (ff.pol_en) - sig_d = module->Mux(NEW_ID, ff.sig_q, sig_d, ff.sig_en); - else - sig_d = module->Mux(NEW_ID, sig_d, ff.sig_q, ff.sig_en); - } else { - if (ff.pol_en) - sig_d = module->MuxGate(NEW_ID, ff.sig_q, sig_d, ff.sig_en); - else - sig_d = module->MuxGate(NEW_ID, sig_d, ff.sig_q, ff.sig_en); - } - } - - if (ff.has_srst && !(ff.has_en && ff.ce_over_srst)) { - if (!ff.is_fine) { - if (ff.pol_srst) - sig_d = module->Mux(NEW_ID, sig_d, ff.val_srst, ff.sig_srst); - else - sig_d = module->Mux(NEW_ID, ff.val_srst, sig_d, ff.sig_srst); - } else { - if (ff.pol_srst) - sig_d = module->MuxGate(NEW_ID, sig_d, ff.val_srst[0], ff.sig_srst); - else - sig_d = module->MuxGate(NEW_ID, ff.val_srst[0], sig_d, ff.sig_srst); - } - } + ff.unmap_ce_srst(module); Wire *past_clk = module->addWire(NEW_ID); initvals.set_init(past_clk, ff.pol_clk ? State::S1 : State::S0); @@ -255,9 +214,9 @@ struct Clk2fflogicPass : public Pass { Wire *past_d = module->addWire(NEW_ID, ff.width); if (!ff.is_fine) - module->addFf(NEW_ID, sig_d, past_d); + module->addFf(NEW_ID, ff.sig_d, past_d); else - module->addFfGate(NEW_ID, sig_d, past_d); + module->addFfGate(NEW_ID, ff.sig_d, past_d); if (!ff.val_init.is_fully_undef()) initvals.set_init(past_d, ff.val_init); -- cgit v1.2.3