Add "dffinit -noreinit" parameter
authorIcenowy Zheng <icenowy@aosc.io>
Tue, 18 Dec 2018 15:10:40 +0000 (23:10 +0800)
committerIcenowy Zheng <icenowy@aosc.io>
Tue, 18 Dec 2018 15:10:40 +0000 (23:10 +0800)
Sometimes the FF cell might be initialized during the map process, e.g.
some FPGA platforms (Anlogic Eagle and Lattice ECP5 for example) has
only a "SR" pin for a FF for async reset, that resets the FF to the
initial value, which means the async reset value should be set as the
initial value. In this case the DFFINIT pass shouldn't reinitialize it
to a different value, which will lead to error.

Add a "-noreinit" parameter for the safeguard. If a FF is not
technically initialized before DFFINIT pass, the default value should be
set to x.

Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
passes/techmap/dffinit.cc

index 4fa15a35bf676839f824a2d4eb8e2ee7ec67cedb..48390488eff98faddc995c4b4f7a43e143bfef41 100644 (file)
@@ -48,13 +48,18 @@ struct DffinitPass : public Pass {
                log("        initial value of 1 or 0. (multi-bit values are not supported in this\n");
                log("        mode.)\n");
                log("\n");
+               log("    -noreinit\n");
+               log("        fail if the FF cell has already a defined initial value set in other\n");
+               log("        passes and the initial value of the net it drives is not equal to\n");
+               log("        the already defined initial value.\n");
+               log("\n");
        }
        void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
        {
                log_header(design, "Executing DFFINIT pass (set INIT param on FF cells).\n");
 
                dict<IdString, dict<IdString, IdString>> ff_types;
-               bool highlow_mode = false;
+               bool highlow_mode = false, noreinit = false;
                std::string high_string, low_string;
 
                size_t argidx;
@@ -78,6 +83,10 @@ struct DffinitPass : public Pass {
                                ff_types[cell_name][output_port] = init_param;
                                continue;
                        }
+                       if (args[argidx] == "-noreinit") {
+                               noreinit = true;
+                               continue;
+                       }
                        break;
                }
                extra_args(args, argidx, design);
@@ -126,6 +135,10 @@ struct DffinitPass : public Pass {
                                                        continue;
                                                while (GetSize(value.bits) <= i)
                                                        value.bits.push_back(State::S0);
+                                               if (noreinit && value.bits[i] != State::Sx && value.bits[i] != init_bits.at(sig[i]))
+                                                       log_error("Trying to assign a different init value for %s.%s.%s which technically "
+                                                                       "have a conflicted init value.\n",
+                                                                       log_id(module), log_id(cell), log_id(it.second));
                                                value.bits[i] = init_bits.at(sig[i]);
                                                cleanup_bits.insert(sig[i]);
                                        }