Get rid of dffsr2dff.
[yosys.git] / techlibs / ice40 / ice40_ffinit.cc
index db2100381b21141dc9ed59700ccc86338ac57126..d7715135ef894e261726a28102afc038bd43bce4 100644 (file)
@@ -25,7 +25,7 @@ PRIVATE_NAMESPACE_BEGIN
 
 struct Ice40FfinitPass : public Pass {
        Ice40FfinitPass() : Pass("ice40_ffinit", "iCE40: handle FF init values") { }
-       virtual void help()
+       void help() YS_OVERRIDE
        {
                //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
                log("\n");
@@ -35,7 +35,7 @@ struct Ice40FfinitPass : public Pass {
                log("nonzero init values.\n");
                log("\n");
        }
-       virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+       void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
        {
                log_header(design, "Executing ICE40_FFINIT pass (implement FF init values).\n");
 
@@ -57,15 +57,16 @@ struct Ice40FfinitPass : public Pass {
                        SigMap sigmap(module);
                        pool<Wire*> init_wires;
                        dict<SigBit, State> initbits;
+                       dict<SigBit, SigBit> initbit_to_wire;
                        pool<SigBit> handled_initbits;
 
                        for (auto wire : module->selected_wires())
                        {
-                               if (wire->attributes.count("\\init") == 0)
+                               if (wire->attributes.count(ID::init) == 0)
                                        continue;
 
                                SigSpec wirebits = sigmap(wire);
-                               Const initval = wire->attributes.at("\\init");
+                               Const initval = wire->attributes.at(ID::init);
                                init_wires.insert(wire);
 
                                for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++)
@@ -77,19 +78,24 @@ struct Ice40FfinitPass : public Pass {
                                                continue;
 
                                        if (initbits.count(bit)) {
-                                               if (initbits.at(bit) != val)
-                                                       log_error("Conflicting init values for signal %s.\n", log_signal(bit));
+                                               if (initbits.at(bit) != val) {
+                                                       log_warning("Conflicting init values for signal %s (%s = %s, %s = %s).\n",
+                                                                       log_signal(bit), log_signal(SigBit(wire, i)), log_signal(val),
+                                                                       log_signal(initbit_to_wire[bit]), log_signal(initbits.at(bit)));
+                                                       initbits.at(bit) = State::Sx;
+                                               }
                                                continue;
                                        }
 
                                        initbits[bit] = val;
+                                       initbit_to_wire[bit] = SigBit(wire, i);
                                }
                        }
 
                        pool<IdString> sb_dff_types = {
-                               "\\SB_DFF",    "\\SB_DFFE",   "\\SB_DFFSR",   "\\SB_DFFR",   "\\SB_DFFSS",   "\\SB_DFFS",   "\\SB_DFFESR",
-                               "\\SB_DFFER",  "\\SB_DFFESS", "\\SB_DFFES",   "\\SB_DFFN",   "\\SB_DFFNE",   "\\SB_DFFNSR", "\\SB_DFFNR",
-                               "\\SB_DFFNSS", "\\SB_DFFNS",  "\\SB_DFFNESR", "\\SB_DFFNER", "\\SB_DFFNESS", "\\SB_DFFNES"
+                               ID(SB_DFF),    ID(SB_DFFE),   ID(SB_DFFSR),   ID(SB_DFFR),   ID(SB_DFFSS),   ID(SB_DFFS),   ID(SB_DFFESR),
+                               ID(SB_DFFER),  ID(SB_DFFESS), ID(SB_DFFES),   ID(SB_DFFN),   ID(SB_DFFNE),   ID(SB_DFFNSR), ID(SB_DFFNR),
+                               ID(SB_DFFNSS), ID(SB_DFFNS),  ID(SB_DFFNESR), ID(SB_DFFNER), ID(SB_DFFNESS), ID(SB_DFFNES)
                        };
 
                        for (auto cell : module->selected_cells())
@@ -97,17 +103,27 @@ struct Ice40FfinitPass : public Pass {
                                if (!sb_dff_types.count(cell->type))
                                        continue;
 
-                               SigBit sig_d = sigmap(cell->getPort("\\D"));
-                               SigBit sig_q = sigmap(cell->getPort("\\Q"));
+                               SigSpec sig_d = cell->getPort(ID::D);
+                               SigSpec sig_q = cell->getPort(ID::Q);
 
-                               if (!initbits.count(sig_q))
+                               if (GetSize(sig_d) < 1 || GetSize(sig_q) < 1)
                                        continue;
 
-                               State val = initbits.at(sig_q);
-                               handled_initbits.insert(sig_q);
+                               SigBit bit_d = sigmap(sig_d[0]);
+                               SigBit bit_q = sigmap(sig_q[0]);
+
+                               if (!initbits.count(bit_q))
+                                       continue;
+
+                               State val = initbits.at(bit_q);
+
+                               if (val == State::Sx)
+                                       continue;
+
+                               handled_initbits.insert(bit_q);
 
                                log("FF init value for cell %s (%s): %s = %c\n", log_id(cell), log_id(cell->type),
-                                               log_signal(sig_q), val != State::S0 ? '1' : '0');
+                                               log_signal(bit_q), val != State::S0 ? '1' : '0');
 
                                if (val == State::S0)
                                        continue;
@@ -117,33 +133,33 @@ struct Ice40FfinitPass : public Pass {
                                if (type_str.back() == 'S') {
                                        type_str.back() = 'R';
                                        cell->type = type_str;
-                                       cell->setPort("\\R", cell->getPort("\\S"));
-                                       cell->unsetPort("\\S");
+                                       cell->setPort(ID::R, cell->getPort(ID::S));
+                                       cell->unsetPort(ID::S);
                                } else
                                if (type_str.back() == 'R') {
                                        type_str.back() = 'S';
                                        cell->type = type_str;
-                                       cell->setPort("\\S", cell->getPort("\\R"));
-                                       cell->unsetPort("\\R");
+                                       cell->setPort(ID::S, cell->getPort(ID::R));
+                                       cell->unsetPort(ID::R);
                                }
 
-                               Wire *new_sig_d = module->addWire(NEW_ID);
-                               Wire *new_sig_q = module->addWire(NEW_ID);
+                               Wire *new_bit_d = module->addWire(NEW_ID);
+                               Wire *new_bit_q = module->addWire(NEW_ID);
 
-                               module->addNotGate(NEW_ID, sig_d, new_sig_d);
-                               module->addNotGate(NEW_ID, new_sig_q, sig_q);
+                               module->addNotGate(NEW_ID, bit_d, new_bit_d);
+                               module->addNotGate(NEW_ID, new_bit_q, bit_q);
 
-                               cell->setPort("\\D", new_sig_d);
-                               cell->setPort("\\Q", new_sig_q);
+                               cell->setPort(ID::D, new_bit_d);
+                               cell->setPort(ID::Q, new_bit_q);
                        }
 
                        for (auto wire : init_wires)
                        {
-                               if (wire->attributes.count("\\init") == 0)
+                               if (wire->attributes.count(ID::init) == 0)
                                        continue;
 
                                SigSpec wirebits = sigmap(wire);
-                               Const &initval = wire->attributes.at("\\init");
+                               Const &initval = wire->attributes.at(ID::init);
                                bool remove_attribute = true;
 
                                for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++) {
@@ -154,7 +170,7 @@ struct Ice40FfinitPass : public Pass {
                                }
 
                                if (remove_attribute)
-                                       wire->attributes.erase("\\init");
+                                       wire->attributes.erase(ID::init);
                        }
                }
        }