zinit: Refactor to use FfData.
authorMarcelina Kościelnicka <mwk@0x04.net>
Fri, 1 Oct 2021 22:05:22 +0000 (00:05 +0200)
committerMarcelina Kościelnicka <mwk@0x04.net>
Sat, 2 Oct 2021 18:19:48 +0000 (20:19 +0200)
passes/techmap/zinit.cc

index 7c5b73c90d5b38b2b6a4a9f8380ca9d71b970536..8fcc47570a56de74d67dea3fc92f1e07a58da47d 100644 (file)
 #include "kernel/yosys.h"
 #include "kernel/sigtools.h"
 #include "kernel/ffinit.h"
+#include "kernel/ff.h"
 
 USING_YOSYS_NAMESPACE
 PRIVATE_NAMESPACE_BEGIN
 
+State invert(State s) {
+       switch (s) {
+               case State::S0: return State::S1;
+               case State::S1: return State::S0;
+               default: return s;
+       }
+}
+
 struct ZinitPass : public Pass {
        ZinitPass() : Pass("zinit", "add inverters so all FF are zero-initialized") { }
        void help() override
@@ -60,123 +69,51 @@ struct ZinitPass : public Pass {
                        SigMap sigmap(module);
                        FfInitVals initvals(&sigmap, module);
 
-                       pool<IdString> dff_types = {
-                                                               // FIXME: It would appear that supporting
-                                                               //    $dffsr/$_DFFSR_* would require a new
-                                                               //    cell type where S has priority over R
-                               ID($ff), ID($dff), ID($dffe), /*ID($dffsr),*/ ID($adff), ID($adffe),
-                               ID($sdff), ID($sdffe), ID($sdffce),
-                               ID($_FF_), ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_),
-                               /*ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_),
-                               ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_),*/
-                               ID($_DFF_N_), ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
-                               ID($_DFF_P_), ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_),
-                               // Async set/reset
-                               ID($_DFFE_NN0P_), ID($_DFFE_NN1P_), ID($_DFFE_NP0P_), ID($_DFFE_NP1P_),
-                               ID($_DFFE_PN0P_), ID($_DFFE_PN1P_), ID($_DFFE_PP0P_), ID($_DFFE_PP1P_),
-                               ID($_DFFE_NN0N_), ID($_DFFE_NN1N_), ID($_DFFE_NP0N_), ID($_DFFE_NP1N_),
-                               ID($_DFFE_PN0N_), ID($_DFFE_PN1N_), ID($_DFFE_PP0N_), ID($_DFFE_PP1N_),
-                               // Sync set/reset
-                               ID($_SDFF_NN0_), ID($_SDFF_NN1_), ID($_SDFF_NP0_), ID($_SDFF_NP1_),
-                               ID($_SDFF_PN0_), ID($_SDFF_PN1_), ID($_SDFF_PP0_), ID($_SDFF_PP1_),
-                               ID($_SDFFE_NN0P_), ID($_SDFFE_NN1P_), ID($_SDFFE_NP0P_), ID($_SDFFE_NP1P_),
-                               ID($_SDFFE_PN0P_), ID($_SDFFE_PN1P_), ID($_SDFFE_PP0P_), ID($_SDFFE_PP1P_),
-                               ID($_SDFFE_NN0N_), ID($_SDFFE_NN1N_), ID($_SDFFE_NP0N_), ID($_SDFFE_NP1N_),
-                               ID($_SDFFE_PN0N_), ID($_SDFFE_PN1N_), ID($_SDFFE_PP0N_), ID($_SDFFE_PP1N_),
-                               ID($_SDFFCE_NN0P_), ID($_SDFFCE_NN1P_), ID($_SDFFCE_NP0P_), ID($_SDFFCE_NP1P_),
-                               ID($_SDFFCE_PN0P_), ID($_SDFFCE_PN1P_), ID($_SDFFCE_PP0P_), ID($_SDFFCE_PP1P_),
-                               ID($_SDFFCE_NN0N_), ID($_SDFFCE_NN1N_), ID($_SDFFCE_NP0N_), ID($_SDFFCE_NP1N_),
-                               ID($_SDFFCE_PN0N_), ID($_SDFFCE_PN1N_), ID($_SDFFCE_PP0N_), ID($_SDFFCE_PP1N_)
-                       };
-
                        for (auto cell : module->selected_cells())
                        {
-                               if (!dff_types.count(cell->type))
+                               if (!RTLIL::builtin_ff_cell_types().count(cell->type))
                                        continue;
 
-                               SigSpec sig_d = sigmap(cell->getPort(ID::D));
-                               SigSpec sig_q = sigmap(cell->getPort(ID::Q));
+                               FfData ff(&initvals, cell);
+                               if (!ff.width)
+                                       continue;
 
-                               if (GetSize(sig_d) < 1 || GetSize(sig_q) < 1)
+                               // Supporting those would require a new cell type where S has priority over R.
+                               if (ff.has_sr)
                                        continue;
 
-                               Const initval = initvals(sig_q);
-                               Const newval = initval;
-                               initvals.remove_init(sig_q);
+                               Wire *new_q = module->addWire(NEW_ID, ff.width);
 
-                               Wire *initwire = module->addWire(NEW_ID, GetSize(sig_q));
+                               log("FF init value for cell %s (%s): %s = %s\n", log_id(cell), log_id(cell->type),
+                                               log_signal(ff.sig_q), log_signal(ff.val_init));
 
-                               for (int i = 0; i < GetSize(initwire); i++)
-                                       if (initval[i] == State::S1)
+                               IdString name = cell->name;
+                               module->remove(cell);
+                               initvals.remove_init(ff.sig_q);
+
+                               for (int i = 0; i < ff.width; i++)
+                                       if (ff.val_init[i] == State::S1)
                                        {
-                                               sig_d[i] = module->NotGate(NEW_ID, sig_d[i]);
-                                               module->addNotGate(NEW_ID, SigSpec(initwire, i), sig_q[i]);
-                                               newval[i] = State::S0;
+                                               if (ff.has_clk || ff.has_gclk)
+                                                       ff.sig_d[i] = module->NotGate(NEW_ID, ff.sig_d[i]);
+                                               if (ff.has_aload)
+                                                       ff.sig_ad[i] = module->NotGate(NEW_ID, ff.sig_ad[i]);
+                                               if (ff.has_arst)
+                                                       ff.val_arst[i] = invert(ff.val_arst[i]);
+                                               if (ff.has_srst)
+                                                       ff.val_srst[i] = invert(ff.val_srst[i]);
+                                               module->addNotGate(NEW_ID, SigSpec(new_q, i), ff.sig_q[i]);
+                                               ff.val_init[i] = State::S0;
                                        }
                                        else
                                        {
-                                               module->connect(sig_q[i], SigSpec(initwire, i));
+                                               module->connect(ff.sig_q[i], SigSpec(new_q, i));
                                                if (all_mode)
-                                                       newval[i] = State::S0;
+                                                       ff.val_init[i] = State::S0;
                                        }
 
-                               initvals.set_init(initwire, newval);
-
-                               log("FF init value for cell %s (%s): %s = %s\n", log_id(cell), log_id(cell->type),
-                                               log_signal(sig_q), log_signal(initval));
-
-                               cell->setPort(ID::D, sig_d);
-                               cell->setPort(ID::Q, initwire);
-
-                               if (cell->type.in(ID($adff), ID($adffe))) {
-                                       auto val = cell->getParam(ID::ARST_VALUE);
-                                       for (int i = 0; i < GetSize(initwire); i++)
-                                               if (initval[i] == State::S1)
-                                                       val[i] = (val[i] == State::S1 ? State::S0 : State::S1);
-                                       cell->setParam(ID::ARST_VALUE, std::move(val));
-                               }
-                               else if (cell->type.in(ID($sdff), ID($sdffe), ID($sdffce))) {
-                                       auto val = cell->getParam(ID::SRST_VALUE);
-                                       for (int i = 0; i < GetSize(initwire); i++)
-                                               if (initval[i] == State::S1)
-                                                       val[i] = (val[i] == State::S1 ? State::S0 : State::S1);
-                                       cell->setParam(ID::SRST_VALUE, std::move(val));
-                               }
-                               else if (initval == State::S1) {
-                                       std::string t = cell->type.str();
-                                       if (cell->type.in(ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_),
-                                                               ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_)))
-                                       {
-                                               t[8] = (t[8] == '0' ? '1' : '0');
-                                       }
-                                       else if (cell->type.in(ID($_SDFF_NN0_), ID($_SDFF_NN1_), ID($_SDFF_NP0_), ID($_SDFF_NP1_),
-                                                               ID($_SDFF_PN0_), ID($_SDFF_PN1_), ID($_SDFF_PP0_), ID($_SDFF_PP1_)))
-                                       {
-                                               t[9] = (t[9] == '0' ? '1' : '0');
-                                       }
-                                       else if (cell->type.in(ID($_DFFE_NN0P_), ID($_DFFE_NN1P_), ID($_DFFE_NP0P_), ID($_DFFE_NP1P_),
-                                                               ID($_DFFE_PN0P_), ID($_DFFE_PN1P_), ID($_DFFE_PP0P_), ID($_DFFE_PP1P_),
-                                                               ID($_DFFE_NN0N_), ID($_DFFE_NN1N_), ID($_DFFE_NP0N_), ID($_DFFE_NP1N_),
-                                                               ID($_DFFE_PN0N_), ID($_DFFE_PN1N_), ID($_DFFE_PP0N_), ID($_DFFE_PP1N_)))
-                                       {
-                                               t[9] = (t[9] == '0' ? '1' : '0');
-                                       }
-                                       else if (cell->type.in(ID($_SDFFE_NN0P_), ID($_SDFFE_NN1P_), ID($_SDFFE_NP0P_), ID($_SDFFE_NP1P_),
-                                                               ID($_SDFFE_PN0P_), ID($_SDFFE_PN1P_), ID($_SDFFE_PP0P_), ID($_SDFFE_PP1P_),
-                                                               ID($_SDFFE_NN0N_), ID($_SDFFE_NN1N_), ID($_SDFFE_NP0N_), ID($_SDFFE_NP1N_),
-                                                               ID($_SDFFE_PN0N_), ID($_SDFFE_PN1N_), ID($_SDFFE_PP0N_), ID($_SDFFE_PP1N_)))
-                                       {
-                                               t[10] = (t[10] == '0' ? '1' : '0');
-                                       }
-                                       else if (cell->type.in(ID($_SDFFCE_NN0P_), ID($_SDFFCE_NN1P_), ID($_SDFFCE_NP0P_), ID($_SDFFCE_NP1P_),
-                                                               ID($_SDFFCE_PN0P_), ID($_SDFFCE_PN1P_), ID($_SDFFCE_PP0P_), ID($_SDFFCE_PP1P_),
-                                                               ID($_SDFFCE_NN0N_), ID($_SDFFCE_NN1N_), ID($_SDFFCE_NP0N_), ID($_SDFFCE_NP1N_),
-                                                               ID($_SDFFCE_PN0N_), ID($_SDFFCE_PN1N_), ID($_SDFFCE_PP0N_), ID($_SDFFCE_PP1N_)))
-                                       {
-                                               t[11] = (t[11] == '0' ? '1' : '0');
-                                       }
-                                       cell->type = t;
-                               }
+                               ff.sig_q = new_q;
+                               ff.emit(module, name);
                        }
                }
        }