From 71dfbf33b292b6920ff1bab308c0c10b737bf763 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Thu, 2 Jun 2022 17:15:28 +0200 Subject: [PATCH] Add -no-rw-check option to memory_dff + memory + synth_{ice40,ecp5,gowin}. --- passes/memory/memory.cc | 11 ++++++++--- passes/memory/memory_dff.cc | 19 +++++++++++++++---- techlibs/common/synth.cc | 9 +++++++++ techlibs/ecp5/synth_ecp5.cc | 20 ++++++++++++++++++-- techlibs/gowin/synth_gowin.cc | 20 ++++++++++++++++++-- techlibs/ice40/synth_ice40.cc | 22 +++++++++++++++++++--- 6 files changed, 87 insertions(+), 14 deletions(-) diff --git a/passes/memory/memory.cc b/passes/memory/memory.cc index e34cc927e..d5dec6198 100644 --- a/passes/memory/memory.cc +++ b/passes/memory/memory.cc @@ -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 ] [selection]\n"); + log(" memory [-norom] [-nomap] [-nordff] [-nowiden] [-nosat] [-memx] [-no-rw-check] [-bram ] [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"); diff --git a/passes/memory/memory_dff.cc b/passes/memory/memory_dff.cc index dd3d8a8f3..998e86491 100644 --- a/passes/memory/memory_dff.cc +++ b/passes/memory/memory_dff.cc @@ -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 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(); } } diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index 79e5933e0..63395c368 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -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); diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc index 8c7ea5b39..f2dc534f9 100644 --- a/techlibs/ecp5/synth_ecp5.cc +++ b/techlibs/ecp5/synth_ecp5.cc @@ -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 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"); } diff --git a/techlibs/gowin/synth_gowin.cc b/techlibs/gowin/synth_gowin.cc index d900bd255..15a0c41e0 100644 --- a/techlibs/gowin/synth_gowin.cc +++ b/techlibs/gowin/synth_gowin.cc @@ -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 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")) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index c10b7003e..1174f6e04 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -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 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"); } -- 2.30.2