Add -no-rw-check option to memory_dff + memory + synth_{ice40,ecp5,gowin}.
authorMarcelina Kościelnicka <mwk@0x04.net>
Thu, 2 Jun 2022 15:15:28 +0000 (17:15 +0200)
committerMarcelina Kościelnicka <mwk@0x04.net>
Thu, 2 Jun 2022 21:16:12 +0000 (23:16 +0200)
passes/memory/memory.cc
passes/memory/memory_dff.cc
techlibs/common/synth.cc
techlibs/ecp5/synth_ecp5.cc
techlibs/gowin/synth_gowin.cc
techlibs/ice40/synth_ice40.cc

index e34cc927e5383fb2fe6c1835be92b9770292341f..d5dec61987920245dc03e8c7de956af800feea7b 100644 (file)
@@ -31,7 +31,7 @@ struct MemoryPass : public Pass {
        {
                //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
                log("\n");
-               log("    memory [-norom] [-nomap] [-nordff] [-nowiden] [-nosat] [-memx] [-bram <bram_rules>] [selection]\n");
+               log("    memory [-norom] [-nomap] [-nordff] [-nowiden] [-nosat] [-memx] [-no-rw-check] [-bram <bram_rules>] [selection]\n");
                log("\n");
                log("This pass calls all the other memory_* passes in a useful order:\n");
                log("\n");
@@ -39,7 +39,7 @@ struct MemoryPass : public Pass {
                log("    opt_mem_priority\n");
                log("    opt_mem_feedback\n");
                log("    memory_bmux2rom                     (skipped if called with -norom)\n");
-               log("    memory_dff                          (skipped if called with -nordff or -memx)\n");
+               log("    memory_dff [-no-rw-check]           (skipped if called with -nordff or -memx)\n");
                log("    opt_clean\n");
                log("    memory_share [-nowiden] [-nosat]\n");
                log("    opt_mem_widen\n");
@@ -59,6 +59,7 @@ struct MemoryPass : public Pass {
                bool flag_nomap = false;
                bool flag_nordff = false;
                bool flag_memx = false;
+               string memory_dff_opts;
                string memory_bram_opts;
                string memory_share_opts;
 
@@ -92,6 +93,10 @@ struct MemoryPass : public Pass {
                                memory_share_opts += " -nosat";
                                continue;
                        }
+                       if (args[argidx] == "-no-rw-check") {
+                               memory_dff_opts += " -no-rw-check";
+                               continue;
+                       }
                        if (argidx+1 < args.size() && args[argidx] == "-bram") {
                                memory_bram_opts += " -rules " + args[++argidx];
                                continue;
@@ -106,7 +111,7 @@ struct MemoryPass : public Pass {
                if (!flag_norom)
                        Pass::call(design, "memory_bmux2rom");
                if (!flag_nordff)
-                       Pass::call(design, "memory_dff");
+                       Pass::call(design, "memory_dff" + memory_dff_opts);
                Pass::call(design, "opt_clean");
                Pass::call(design, "memory_share" + memory_share_opts);
                Pass::call(design, "opt_mem_widen");
index dd3d8a8f3543b775ae140c946c4105ad8f75f1ca..998e86491c4ae50d1c4c481e93f809face418b57 100644 (file)
@@ -220,8 +220,9 @@ struct MemoryDffWorker
        ModWalker modwalker;
        FfInitVals initvals;
        FfMergeHelper merger;
+       bool flag_no_rw_check;
 
-       MemoryDffWorker(Module *module) : module(module), modwalker(module->design)
+       MemoryDffWorker(Module *module, bool flag_no_rw_check) : module(module), modwalker(module->design), flag_no_rw_check(flag_no_rw_check)
        {
                modwalker.setup(module);
                initvals.set(&modwalker.sigmap, module);
@@ -358,7 +359,7 @@ struct MemoryDffWorker
                }
 
                // Check for no_rw_check
-               bool no_rw_check = mem.get_bool_attribute(ID::no_rw_check);
+               bool no_rw_check = flag_no_rw_check || mem.get_bool_attribute(ID::no_rw_check);
                for (auto attr: {ID::ram_block, ID::rom_block, ID::ram_style, ID::rom_style, ID::ramstyle, ID::romstyle, ID::syn_ramstyle, ID::syn_romstyle}) {
                        if (mem.get_string_attribute(attr) == "no_rw_check") {
                                no_rw_check = true;
@@ -628,25 +629,35 @@ struct MemoryDffPass : public Pass {
        {
                //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
                log("\n");
-               log("    memory_dff [options] [selection]\n");
+               log("    memory_dff [-no-rw-check] [selection]\n");
                log("\n");
                log("This pass detects DFFs at memory read ports and merges them into the memory port.\n");
                log("I.e. it consumes an asynchronous memory port and the flip-flops at its\n");
                log("interface and yields a synchronous memory port.\n");
                log("\n");
+               log("    -no-rw-check\n");
+               log("        marks all recognized read ports as \"return don't-care value on\n");
+               log("        read/write collision\" (same result as setting the no_rw_check\n");
+               log("        attribute on all memories).\n");
+               log("\n");
        }
        void execute(std::vector<std::string> args, RTLIL::Design *design) override
        {
+               bool flag_no_rw_check = false;
                log_header(design, "Executing MEMORY_DFF pass (merging $dff cells to $memrd).\n");
 
                size_t argidx;
                for (argidx = 1; argidx < args.size(); argidx++) {
+                       if (args[argidx] == "-no-rw-check") {
+                               flag_no_rw_check = true;
+                               continue;
+                       }
                        break;
                }
                extra_args(args, argidx, design);
 
                for (auto mod : design->selected_modules()) {
-                       MemoryDffWorker worker(mod);
+                       MemoryDffWorker worker(mod, flag_no_rw_check);
                        worker.run();
                }
        }
index 79e5933e0968cdf818764b0807268f0208910b87..63395c368026b4be7909483ddcb4abe5045f8230 100644 (file)
@@ -81,6 +81,11 @@ struct SynthPass : public ScriptPass
                log("    -flowmap\n");
                log("        use FlowMap LUT techmapping instead of ABC\n");
                log("\n");
+               log("    -no-rw-check\n");
+               log("        marks all recognized read ports as \"return don't-care value on\n");
+               log("        read/write collision\" (same result as setting the no_rw_check\n");
+               log("        attribute on all memories).\n");
+               log("\n");
                log("\n");
                log("The following commands are executed by this synthesis command:\n");
                help_script();
@@ -175,6 +180,10 @@ struct SynthPass : public ScriptPass
                                flowmap = true;
                                continue;
                        }
+                       if (args[argidx] == "-no-rw-check") {
+                               memory_opts += " -no-rw-check";
+                               continue;
+                       }
                        break;
                }
                extra_args(args, argidx, design);
index 8c7ea5b396b9796f35bac0441dd26246d8779486..f2dc534f90e79b9dbdd18c17aaefbc66f31bd2b3 100644 (file)
@@ -103,6 +103,11 @@ struct SynthEcp5Pass : public ScriptPass
                log("    -nodsp\n");
                log("        do not map multipliers to MULT18X18D\n");
                log("\n");
+               log("    -no-rw-check\n");
+               log("        marks all recognized read ports as \"return don't-care value on\n");
+               log("        read/write collision\" (same result as setting the no_rw_check\n");
+               log("        attribute on all memories).\n");
+               log("\n");
                log("\n");
                log("The following commands are executed by this synthesis command:\n");
                help_script();
@@ -110,7 +115,7 @@ struct SynthEcp5Pass : public ScriptPass
        }
 
        string top_opt, blif_file, edif_file, json_file;
-       bool noccu2, nodffe, nobram, nolutram, nowidelut, asyncprld, flatten, dff, retime, abc2, abc9, nodsp, vpr;
+       bool noccu2, nodffe, nobram, nolutram, nowidelut, asyncprld, flatten, dff, retime, abc2, abc9, nodsp, vpr, no_rw_check;
 
        void clear_flags() override
        {
@@ -131,6 +136,7 @@ struct SynthEcp5Pass : public ScriptPass
                vpr = false;
                abc9 = false;
                nodsp = false;
+               no_rw_check = false;
        }
 
        void execute(std::vector<std::string> args, RTLIL::Design *design) override
@@ -221,6 +227,10 @@ struct SynthEcp5Pass : public ScriptPass
                                nodsp = true;
                                continue;
                        }
+                       if (args[argidx] == "-no-rw-check") {
+                               no_rw_check = true;
+                               continue;
+                       }
                        break;
                }
                extra_args(args, argidx, design);
@@ -241,6 +251,12 @@ struct SynthEcp5Pass : public ScriptPass
 
        void script() override
        {
+               std::string no_rw_check_opt = "";
+               if (no_rw_check)
+                       no_rw_check_opt = " -no-rw-check";
+               if (help_mode)
+                       no_rw_check_opt = " [-no-rw-check]";
+
                if (check_label("begin"))
                {
                        run("read_verilog -lib -specify +/ecp5/cells_sim.v +/ecp5/cells_bb.v");
@@ -273,7 +289,7 @@ struct SynthEcp5Pass : public ScriptPass
                        }
                        run("alumacc");
                        run("opt");
-                       run("memory -nomap");
+                       run("memory -nomap" + no_rw_check_opt);
                        run("opt_clean");
                }
 
index d900bd255670fe353078a65bce1ae0de5f21e2f7..15a0c41e0d0d05123a458b9d3fb1ae8bba6d4ee8 100644 (file)
@@ -81,6 +81,11 @@ struct SynthGowinPass : public ScriptPass
                log("    -abc9\n");
                log("        use new ABC9 flow (EXPERIMENTAL)\n");
                log("\n");
+               log("    -no-rw-check\n");
+               log("        marks all recognized read ports as \"return don't-care value on\n");
+               log("        read/write collision\" (same result as setting the no_rw_check\n");
+               log("        attribute on all memories).\n");
+               log("\n");
                log("\n");
                log("The following commands are executed by this synthesis command:\n");
                help_script();
@@ -88,7 +93,7 @@ struct SynthGowinPass : public ScriptPass
        }
 
        string top_opt, vout_file, json_file;
-       bool retime, nobram, nolutram, flatten, nodffe, nowidelut, abc9, noiopads, noalu;
+       bool retime, nobram, nolutram, flatten, nodffe, nowidelut, abc9, noiopads, noalu, no_rw_check;
 
        void clear_flags() override
        {
@@ -104,6 +109,7 @@ struct SynthGowinPass : public ScriptPass
                abc9 = false;
                noiopads = false;
                noalu = false;
+               no_rw_check = false;
        }
 
        void execute(std::vector<std::string> args, RTLIL::Design *design) override
@@ -172,6 +178,10 @@ struct SynthGowinPass : public ScriptPass
                                noiopads = true;
                                continue;
                        }
+                       if (args[argidx] == "-no-rw-check") {
+                               no_rw_check = true;
+                               continue;
+                       }
                        break;
                }
                extra_args(args, argidx, design);
@@ -189,6 +199,12 @@ struct SynthGowinPass : public ScriptPass
 
        void script() override
        {
+               std::string no_rw_check_opt = "";
+               if (no_rw_check)
+                       no_rw_check_opt = " -no-rw-check";
+               if (help_mode)
+                       no_rw_check_opt = " [-no-rw-check]";
+
                if (check_label("begin"))
                {
                        run("read_verilog -specify -lib +/gowin/cells_sim.v");
@@ -205,7 +221,7 @@ struct SynthGowinPass : public ScriptPass
 
                if (check_label("coarse"))
                {
-                       run("synth -run coarse");
+                       run("synth -run coarse" + no_rw_check_opt);
                }
 
                if (check_label("map_ram"))
index c10b7003eecc2cddf22feeda1f16e610bc220e5e..1174f6e04e6f0d129df72279db04b94bdf759303 100644 (file)
@@ -112,6 +112,11 @@ struct SynthIce40Pass : public ScriptPass
                log("    -flowmap\n");
                log("        use FlowMap LUT techmapping instead of abc (EXPERIMENTAL)\n");
                log("\n");
+               log("    -no-rw-check\n");
+               log("        marks all recognized read ports as \"return don't-care value on\n");
+               log("        read/write collision\" (same result as setting the no_rw_check\n");
+               log("        attribute on all memories).\n");
+               log("\n");
                log("\n");
                log("The following commands are executed by this synthesis command:\n");
                help_script();
@@ -119,7 +124,7 @@ struct SynthIce40Pass : public ScriptPass
        }
 
        string top_opt, blif_file, edif_file, json_file, device_opt;
-       bool nocarry, nodffe, nobram, spram, dsp, flatten, retime, noabc, abc2, vpr, abc9, dff, flowmap;
+       bool nocarry, nodffe, nobram, spram, dsp, flatten, retime, noabc, abc2, vpr, abc9, dff, flowmap, no_rw_check;
        int min_ce_use;
 
        void clear_flags() override
@@ -142,6 +147,7 @@ struct SynthIce40Pass : public ScriptPass
                abc9 = false;
                flowmap = false;
                device_opt = "hx";
+               no_rw_check = false;
        }
 
        void execute(std::vector<std::string> args, RTLIL::Design *design) override
@@ -244,6 +250,10 @@ struct SynthIce40Pass : public ScriptPass
                                flowmap = true;
                                continue;
                        }
+                       if (args[argidx] == "-no-rw-check") {
+                               no_rw_check = true;
+                               continue;
+                       }
                        break;
                }
                extra_args(args, argidx, design);
@@ -279,6 +289,12 @@ struct SynthIce40Pass : public ScriptPass
                        define = "-D ICE40_U";
                else
                        define = "-D ICE40_HX";
+               std::string no_rw_check_opt = "";
+               if (no_rw_check)
+                       no_rw_check_opt = " -no-rw-check";
+               if (help_mode)
+                       no_rw_check_opt = " [-no-rw-check]";
+
                if (check_label("begin"))
                {
                        run("read_verilog " + define + " -lib -specify +/ice40/cells_sim.v");
@@ -311,7 +327,7 @@ struct SynthIce40Pass : public ScriptPass
                        run("opt_expr");
                        run("opt_clean");
                        if (help_mode || dsp) {
-                               run("memory_dff"); // ice40_dsp will merge registers, reserve memory port registers first
+                               run("memory_dff" + no_rw_check_opt); // ice40_dsp will merge registers, reserve memory port registers first
                                run("wreduce t:$mul");
                                run("techmap -map +/mul2dsp.v -map +/ice40/dsp_map.v -D DSP_A_MAXWIDTH=16 -D DSP_B_MAXWIDTH=16 "
                                                "-D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_Y_MINWIDTH=11 "
@@ -326,7 +342,7 @@ struct SynthIce40Pass : public ScriptPass
                        }
                        run("alumacc");
                        run("opt");
-                       run("memory -nomap");
+                       run("memory -nomap" + no_rw_check_opt);
                        run("opt_clean");
                }