From 247613e649b49424a69fb19dbbde25b6bbf90684 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Thu, 31 Aug 2023 13:17:21 +0200 Subject: [PATCH] synth_nexus to synth_lattice --- techlibs/lattice/Makefile.inc | 22 +- .../arith_map.v => lattice/arith_map_nexus.v} | 0 .../brams_map.v => lattice/brams_map_nexus.v} | 0 .../brams.txt => lattice/brams_nexus.txt} | 0 .../cells_xtra.v => lattice/cells_bb_nexus.v} | 0 .../cells_map.v => lattice/cells_map_nexus.v} | 0 .../{cells_map.v => cells_map_trellis.v} | 0 .../cells_sim.v => lattice/cells_sim_nexus.v} | 0 .../cells_xtra_nexus.py} | 4 +- .../dsp_map.v => lattice/dsp_map_nexus.v} | 0 .../lrams_map.v => lattice/lrams_map_nexus.v} | 0 .../lrams.txt => lattice/lrams_nexus.txt} | 0 .../lutrams_map_nexus.v} | 0 .../{lutrams_map.v => lutrams_map_trellis.v} | 0 .../lutrams.txt => lattice/lutrams_nexus.txt} | 0 .../{lutrams.txt => lutrams_trellis.txt} | 0 techlibs/{nexus => lattice}/parse_init.vh | 0 techlibs/lattice/synth_lattice.cc | 166 +++++-- techlibs/nexus/Makefile.inc | 16 - techlibs/nexus/latches_map.v | 11 - techlibs/nexus/synth_nexus.cc | 417 ------------------ 21 files changed, 160 insertions(+), 476 deletions(-) rename techlibs/{nexus/arith_map.v => lattice/arith_map_nexus.v} (100%) rename techlibs/{nexus/brams_map.v => lattice/brams_map_nexus.v} (100%) rename techlibs/{nexus/brams.txt => lattice/brams_nexus.txt} (100%) rename techlibs/{nexus/cells_xtra.v => lattice/cells_bb_nexus.v} (100%) rename techlibs/{nexus/cells_map.v => lattice/cells_map_nexus.v} (100%) rename techlibs/lattice/{cells_map.v => cells_map_trellis.v} (100%) rename techlibs/{nexus/cells_sim.v => lattice/cells_sim_nexus.v} (100%) rename techlibs/{nexus/cells_xtra.py => lattice/cells_xtra_nexus.py} (98%) rename techlibs/{nexus/dsp_map.v => lattice/dsp_map_nexus.v} (100%) rename techlibs/{nexus/lrams_map.v => lattice/lrams_map_nexus.v} (100%) rename techlibs/{nexus/lrams.txt => lattice/lrams_nexus.txt} (100%) rename techlibs/{nexus/lutrams_map.v => lattice/lutrams_map_nexus.v} (100%) rename techlibs/lattice/{lutrams_map.v => lutrams_map_trellis.v} (100%) rename techlibs/{nexus/lutrams.txt => lattice/lutrams_nexus.txt} (100%) rename techlibs/lattice/{lutrams.txt => lutrams_trellis.txt} (100%) rename techlibs/{nexus => lattice}/parse_init.vh (100%) delete mode 100644 techlibs/nexus/Makefile.inc delete mode 100644 techlibs/nexus/latches_map.v delete mode 100644 techlibs/nexus/synth_nexus.cc diff --git a/techlibs/lattice/Makefile.inc b/techlibs/lattice/Makefile.inc index 7cb034f4e..9084472cf 100644 --- a/techlibs/lattice/Makefile.inc +++ b/techlibs/lattice/Makefile.inc @@ -4,28 +4,40 @@ OBJS += techlibs/lattice/lattice_gsr.o $(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_ff.vh)) $(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_io.vh)) -$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_map.v)) +$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_map_trellis.v)) +$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_map_nexus.v)) $(eval $(call add_share_file,share/lattice,techlibs/lattice/common_sim.vh)) +$(eval $(call add_share_file,share/lattice,techlibs/lattice/parse_init.vh)) $(eval $(call add_share_file,share/lattice,techlibs/lattice/ccu2d_sim.vh)) $(eval $(call add_share_file,share/lattice,techlibs/lattice/ccu2c_sim.vh)) $(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_sim_ecp5.v)) $(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_sim_xo2.v)) $(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_sim_xo3.v)) $(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_sim_xo3d.v)) +$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_sim_nexus.v)) $(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_bb_ecp5.v)) $(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_bb_xo2.v)) $(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_bb_xo3.v)) $(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_bb_xo3d.v)) -$(eval $(call add_share_file,share/lattice,techlibs/lattice/lutrams_map.v)) -$(eval $(call add_share_file,share/lattice,techlibs/lattice/lutrams.txt)) +$(eval $(call add_share_file,share/lattice,techlibs/lattice/cells_bb_nexus.v)) +$(eval $(call add_share_file,share/lattice,techlibs/lattice/lutrams_map_trellis.v)) +$(eval $(call add_share_file,share/lattice,techlibs/lattice/lutrams_trellis.txt)) +$(eval $(call add_share_file,share/lattice,techlibs/lattice/lutrams_map_nexus.v)) +$(eval $(call add_share_file,share/lattice,techlibs/lattice/lutrams_nexus.txt)) +$(eval $(call add_share_file,share/lattice,techlibs/lattice/lrams_map_nexus.v)) +$(eval $(call add_share_file,share/lattice,techlibs/lattice/lrams_nexus.txt)) $(eval $(call add_share_file,share/lattice,techlibs/lattice/brams_map_16kd.v)) $(eval $(call add_share_file,share/lattice,techlibs/lattice/brams_16kd.txt)) $(eval $(call add_share_file,share/lattice,techlibs/lattice/brams_map_8kc.v)) $(eval $(call add_share_file,share/lattice,techlibs/lattice/brams_8kc.txt)) +$(eval $(call add_share_file,share/lattice,techlibs/lattice/brams_map_nexus.v)) +$(eval $(call add_share_file,share/lattice,techlibs/lattice/brams_nexus.txt)) $(eval $(call add_share_file,share/lattice,techlibs/lattice/arith_map_ccu2c.v)) $(eval $(call add_share_file,share/lattice,techlibs/lattice/arith_map_ccu2d.v)) +$(eval $(call add_share_file,share/lattice,techlibs/lattice/arith_map_nexus.v)) $(eval $(call add_share_file,share/lattice,techlibs/lattice/latches_map.v)) $(eval $(call add_share_file,share/lattice,techlibs/lattice/dsp_map_18x18.v)) +$(eval $(call add_share_file,share/lattice,techlibs/lattice/dsp_map_nexus.v)) $(eval $(call add_share_file,share/ecp5,techlibs/lattice/cells_ff.vh)) @@ -34,3 +46,7 @@ $(eval $(call add_share_file,share/ecp5,techlibs/lattice/common_sim.vh)) $(eval $(call add_share_file,share/ecp5,techlibs/lattice/ccu2c_sim.vh)) $(eval $(call add_share_file_and_rename,share/ecp5,techlibs/lattice/cells_sim_ecp5.v,cells_sim.v)) $(eval $(call add_share_file_and_rename,share/ecp5,techlibs/lattice/cells_bb_ecp5.v,cells_bb.v)) + +$(eval $(call add_share_file,share/nexus,techlibs/lattice/parse_init.vh)) +$(eval $(call add_share_file_and_rename,share/nexus,techlibs/lattice/cells_sim_nexus.v,cells_sim.v)) +$(eval $(call add_share_file_and_rename,share/nexus,techlibs/lattice/cells_bb_nexus.v,cells_xtra.v)) diff --git a/techlibs/nexus/arith_map.v b/techlibs/lattice/arith_map_nexus.v similarity index 100% rename from techlibs/nexus/arith_map.v rename to techlibs/lattice/arith_map_nexus.v diff --git a/techlibs/nexus/brams_map.v b/techlibs/lattice/brams_map_nexus.v similarity index 100% rename from techlibs/nexus/brams_map.v rename to techlibs/lattice/brams_map_nexus.v diff --git a/techlibs/nexus/brams.txt b/techlibs/lattice/brams_nexus.txt similarity index 100% rename from techlibs/nexus/brams.txt rename to techlibs/lattice/brams_nexus.txt diff --git a/techlibs/nexus/cells_xtra.v b/techlibs/lattice/cells_bb_nexus.v similarity index 100% rename from techlibs/nexus/cells_xtra.v rename to techlibs/lattice/cells_bb_nexus.v diff --git a/techlibs/nexus/cells_map.v b/techlibs/lattice/cells_map_nexus.v similarity index 100% rename from techlibs/nexus/cells_map.v rename to techlibs/lattice/cells_map_nexus.v diff --git a/techlibs/lattice/cells_map.v b/techlibs/lattice/cells_map_trellis.v similarity index 100% rename from techlibs/lattice/cells_map.v rename to techlibs/lattice/cells_map_trellis.v diff --git a/techlibs/nexus/cells_sim.v b/techlibs/lattice/cells_sim_nexus.v similarity index 100% rename from techlibs/nexus/cells_sim.v rename to techlibs/lattice/cells_sim_nexus.v diff --git a/techlibs/nexus/cells_xtra.py b/techlibs/lattice/cells_xtra_nexus.py similarity index 98% rename from techlibs/nexus/cells_xtra.py rename to techlibs/lattice/cells_xtra_nexus.py index 6ced76950..c7be64cef 100644 --- a/techlibs/nexus/cells_xtra.py +++ b/techlibs/lattice/cells_xtra_nexus.py @@ -280,7 +280,7 @@ if __name__ == '__main__': for device, cells in devices: xtract_cells_decl(device, cells, dirs, out) - with open('cells_xtra.v', 'w') as f: - f.write('// Created by cells_xtra.py from Lattice models\n') + with open('cells_bb_nexus.v', 'w') as f: + f.write('// Created by cells_xtra_nexus.py from Lattice models\n') f.write('\n') f.write(out.getvalue()) diff --git a/techlibs/nexus/dsp_map.v b/techlibs/lattice/dsp_map_nexus.v similarity index 100% rename from techlibs/nexus/dsp_map.v rename to techlibs/lattice/dsp_map_nexus.v diff --git a/techlibs/nexus/lrams_map.v b/techlibs/lattice/lrams_map_nexus.v similarity index 100% rename from techlibs/nexus/lrams_map.v rename to techlibs/lattice/lrams_map_nexus.v diff --git a/techlibs/nexus/lrams.txt b/techlibs/lattice/lrams_nexus.txt similarity index 100% rename from techlibs/nexus/lrams.txt rename to techlibs/lattice/lrams_nexus.txt diff --git a/techlibs/nexus/lutrams_map.v b/techlibs/lattice/lutrams_map_nexus.v similarity index 100% rename from techlibs/nexus/lutrams_map.v rename to techlibs/lattice/lutrams_map_nexus.v diff --git a/techlibs/lattice/lutrams_map.v b/techlibs/lattice/lutrams_map_trellis.v similarity index 100% rename from techlibs/lattice/lutrams_map.v rename to techlibs/lattice/lutrams_map_trellis.v diff --git a/techlibs/nexus/lutrams.txt b/techlibs/lattice/lutrams_nexus.txt similarity index 100% rename from techlibs/nexus/lutrams.txt rename to techlibs/lattice/lutrams_nexus.txt diff --git a/techlibs/lattice/lutrams.txt b/techlibs/lattice/lutrams_trellis.txt similarity index 100% rename from techlibs/lattice/lutrams.txt rename to techlibs/lattice/lutrams_trellis.txt diff --git a/techlibs/nexus/parse_init.vh b/techlibs/lattice/parse_init.vh similarity index 100% rename from techlibs/nexus/parse_init.vh rename to techlibs/lattice/parse_init.vh diff --git a/techlibs/lattice/synth_lattice.cc b/techlibs/lattice/synth_lattice.cc index cb22fe907..399dccf0c 100644 --- a/techlibs/lattice/synth_lattice.cc +++ b/techlibs/lattice/synth_lattice.cc @@ -35,13 +35,32 @@ struct SynthLatticePass : public ScriptPass RTLIL::constpad["synth_lattice.abc9.W"] = "300"; } + struct DSPRule { + int a_maxwidth; + int b_maxwidth; + int a_minwidth; + int b_minwidth; + std::string prim; + }; + + const std::vector dsp_rules_nexus = { + {36, 36, 22, 22, "$__NX_MUL36X36"}, + {36, 18, 22, 10, "$__NX_MUL36X18"}, + {18, 18, 10, 4, "$__NX_MUL18X18"}, + {18, 18, 4, 10, "$__NX_MUL18X18"}, + { 9, 9, 4, 4, "$__NX_MUL9X9"}, + }; + const std::vector dsp_rules_ecp5 = { + {18, 18, 2, 2, "$__MUL18X18"}, + }; + void help() override { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); log(" synth_lattice [options]\n"); log("\n"); - log("This command runs synthesis for Lattice FPGAs (excluding iCE40 and Nexus).\n"); + log("This command runs synthesis for Lattice FPGAs (excluding iCE40).\n"); log("\n"); log(" -top \n"); log(" use the specified module as top module\n"); @@ -54,6 +73,8 @@ struct SynthLatticePass : public ScriptPass log(" - xo2: MachXO2\n"); log(" - xo3: MachXO3L/LF\n"); log(" - xo3d: MachXO3D\n"); + log(" - lifcl: CrossLink-NX\n"); + log(" - lfd2nx: Certus-NX\n"); //log(" - xo: MachXO (EXPERIMENTAL)\n"); //log(" - pm: Platform Manager (EXPERIMENTAL)\n"); //log(" - pm2: Platform Manager 2 (EXPERIMENTAL)\n"); @@ -118,9 +139,13 @@ struct SynthLatticePass : public ScriptPass log("\n"); log(" -iopad\n"); log(" insert IO buffers\n"); + log(" (by default enabled on Nexus FPGAs)\n"); + log("\n"); + log(" -noiopad\n"); + log(" do not insert IO buffers\n"); log("\n"); log(" -nodsp\n"); - log(" do not map multipliers to MULT18X18D\n"); + log(" do not infer DSP multipliers\n"); log("\n"); log(" -no-rw-check\n"); log(" marks all recognized read ports as \"return don't-care value on\n"); @@ -140,7 +165,9 @@ struct SynthLatticePass : public ScriptPass string top_opt, edif_file, json_file, family; bool noccu2, nodffe, nobram, nolutram, nowidelut, asyncprld, flatten, dff, retime, abc2, abc9, iopad, nodsp, no_rw_check, have_dsp; bool cmp2softlogic; - string postfix, arith_map, brams_map, dsp_map; + string postfix, arith_map, brams_map, dsp_map, cells_map, map_ram_default, widelut_abc; + bool is_nexus; + std::vector dsp_rules; void clear_flags() override { @@ -168,6 +195,10 @@ struct SynthLatticePass : public ScriptPass dsp_map = ""; have_dsp = false; cmp2softlogic = false; + is_nexus = false; + map_ram_default = ""; + cells_map = ""; + widelut_abc = "4:7"; } void execute(std::vector args, RTLIL::Design *design) override @@ -175,6 +206,7 @@ struct SynthLatticePass : public ScriptPass string run_from, run_to; bool force_abc9 = false; bool force_widelut = false; + bool force_iopad = false; clear_flags(); size_t argidx; @@ -266,6 +298,12 @@ struct SynthLatticePass : public ScriptPass } if (args[argidx] == "-iopad") { iopad = true; + force_iopad = true; + continue; + } + if (args[argidx] == "-noiopad") { + iopad = false; + force_iopad = true; continue; } if (args[argidx] == "-nodsp") { @@ -292,7 +330,9 @@ struct SynthLatticePass : public ScriptPass arith_map = "_ccu2c"; brams_map = "_16kd"; dsp_map = "_18x18"; + dsp_rules = dsp_rules_ecp5; have_dsp = true; + cells_map = "_trellis"; } else if (family == "xo2" || family == "xo3" || family == "xo3d" /* || @@ -300,9 +340,24 @@ struct SynthLatticePass : public ScriptPass postfix = "_" + family; arith_map = "_ccu2d"; brams_map = "_8kc"; + cells_map = "_trellis"; have_dsp = false; if (!force_widelut) nowidelut = true; if (!force_abc9) abc9 = false; + } else if (family == "lifcl" || + family == "lfd2nx") { + is_nexus = true; + postfix = "_nexus"; + arith_map = "_nexus"; + brams_map = "_nexus"; + dsp_map = "_nexus"; + dsp_rules = dsp_rules_nexus; + have_dsp = true; + map_ram_default = " -no-auto-huge"; + cells_map = "_nexus"; + widelut_abc = "4:5"; + if (!force_iopad) iopad = true; + if (!force_abc9) abc9 = false; /* } else if (family == "xo" || family == "pm") { } else if (family == "xp" || @@ -366,10 +421,19 @@ struct SynthLatticePass : public ScriptPass run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4"); run("opt_expr"); run("opt_clean"); - if (have_dsp && !nodsp) { - run("techmap -map +/mul2dsp.v -map +/lattice/dsp_map" + dsp_map + ".v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18 -D DSP_A_MINWIDTH=2 -D DSP_B_MINWIDTH=2 -D DSP_NAME=$__MUL18X18", "(unless -nodsp)"); - run("chtype -set $mul t:$__soft_mul", "(unless -nodsp)"); + + if (help_mode) { + run("techmap -map +/mul2dsp.v [...]", "(unless -nodsp)"); + run("techmap -map +/lattice/dsp_map" + dsp_map + ".v", "(unless -nodsp)"); + } else if (have_dsp && !nodsp) { + for (const auto &rule : dsp_rules) { + run(stringf("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=%d -D DSP_B_MAXWIDTH=%d -D DSP_A_MINWIDTH=%d -D DSP_B_MINWIDTH=%d -D DSP_NAME=%s", + rule.a_maxwidth, rule.b_maxwidth, rule.a_minwidth, rule.b_minwidth, rule.prim.c_str())); + run("chtype -set $mul t:$__soft_mul"); + } + run("techmap -map +/lattice/dsp_map" + dsp_map + ".v"); } + run("alumacc"); run("opt"); run("memory -nomap" + no_rw_check_opt); @@ -378,15 +442,20 @@ struct SynthLatticePass : public ScriptPass if (check_label("map_ram")) { - std::string args = ""; + std::string args = map_ram_default; if (nobram) args += " -no-auto-block"; if (nolutram) args += " -no-auto-distributed"; if (help_mode) args += " [-no-auto-block] [-no-auto-distributed]"; - run("memory_libmap -lib +/lattice/lutrams.txt -lib +/lattice/brams" + brams_map + ".txt" + args, "(-no-auto-block if -nobram, -no-auto-distributed if -nolutram)"); - run("techmap -map +/lattice/lutrams_map.v -map +/lattice/brams_map" + brams_map + ".v"); + if (!is_nexus) { + run("memory_libmap -lib +/lattice/lutrams" + cells_map + ".txt -lib +/lattice/brams" + brams_map + ".txt" + args, "(-no-auto-block if -nobram, -no-auto-distributed if -nolutram)"); + run("techmap -map +/lattice/lutrams_map" + cells_map + ".v -map +/lattice/brams_map" + brams_map + ".v"); + } else { + run("memory_libmap -lib +/lattice/lutrams" + cells_map + ".txt -lib +/lattice/brams" + brams_map + ".txt -lib +/lattice/lrams_nexus.txt" + args, "(-no-auto-block if -nobram, -no-auto-distributed if -nolutram)"); + run("techmap -map +/lattice/lutrams_map" + cells_map + ".v -map +/lattice/brams_map" + brams_map + ".v -map +/lattice/lrams_map_nexus.v"); + } } if (check_label("map_ffram")) @@ -415,27 +484,37 @@ struct SynthLatticePass : public ScriptPass if (check_label("map_ffs")) { run("opt_clean"); - std::string dfflegalize_args = " -cell $_DFF_?_ 01 -cell $_DFF_?P?_ r -cell $_SDFF_?P?_ r"; - if (help_mode) { - dfflegalize_args += " [-cell $_DFFE_??_ 01 -cell $_DFFE_?P??_ r -cell $_SDFFE_?P??_ r]"; - } else if (!nodffe) { - dfflegalize_args += " -cell $_DFFE_??_ 01 -cell $_DFFE_?P??_ r -cell $_SDFFE_?P??_ r"; - } - if (help_mode) { - dfflegalize_args += " [-cell $_ALDFF_?P_ x -cell $_ALDFFE_?P?_ x] [-cell $_DLATCH_?_ x]"; - } else if (asyncprld) { - dfflegalize_args += " -cell $_ALDFF_?P_ x -cell $_ALDFFE_?P?_ x"; + if (!is_nexus) { + std::string dfflegalize_args = " -cell $_DFF_?_ 01 -cell $_DFF_?P?_ r -cell $_SDFF_?P?_ r"; + if (help_mode) { + dfflegalize_args += " [-cell $_DFFE_??_ 01 -cell $_DFFE_?P??_ r -cell $_SDFFE_?P??_ r]"; + } else if (!nodffe) { + dfflegalize_args += " -cell $_DFFE_??_ 01 -cell $_DFFE_?P??_ r -cell $_SDFFE_?P??_ r"; + } + if (help_mode) { + dfflegalize_args += " [-cell $_ALDFF_?P_ x -cell $_ALDFFE_?P?_ x] [-cell $_DLATCH_?_ x]"; + } else if (asyncprld) { + dfflegalize_args += " -cell $_ALDFF_?P_ x -cell $_ALDFFE_?P?_ x"; + } else { + dfflegalize_args += " -cell $_DLATCH_?_ x"; + } + run("dfflegalize" + dfflegalize_args, "($_ALDFF_*_ only if -asyncprld, $_DLATCH_* only if not -asyncprld, $_*DFFE_* only if not -nodffe)"); } else { - dfflegalize_args += " -cell $_DLATCH_?_ x"; - } - run("dfflegalize" + dfflegalize_args, "($_ALDFF_*_ only if -asyncprld, $_DLATCH_* only if not -asyncprld, $_*DFFE_* only if not -nodffe)"); + std::string dfflegalize_args = " -cell $_DFF_P_ 01 -cell $_DFF_PP?_ r -cell $_SDFF_PP?_ r -cell $_DLATCH_?_ x"; + if (help_mode) { + dfflegalize_args += " [-cell $_DFFE_PP_ 01 -cell $_DFFE_PP?P_ r -cell $_SDFFE_PP?P_ r]"; + } else if (!nodffe) { + dfflegalize_args += " -cell $_DFFE_PP_ 01 -cell $_DFFE_PP?P_ r -cell $_SDFFE_PP?P_ r"; + } + run("dfflegalize" + dfflegalize_args, "($_*DFFE_* only if not -nodffe)"); + } run("opt_merge"); if ((abc9 && dff) || help_mode) run("zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$_SDFF*", "(only if -abc9 and -dff)"); - run("techmap -D NO_LUT -map +/lattice/cells_map.v"); + run("techmap -D NO_LUT -map +/lattice/cells_map" + cells_map + ".v"); run("opt_expr -undriven -mux_undef"); run("simplemap"); - run("lattice_gsr"); + if (!is_nexus) run("lattice_gsr"); run("attrmvcp -copy -attr syn_useioff"); run("opt_clean"); } @@ -466,7 +545,7 @@ struct SynthLatticePass : public ScriptPass if (nowidelut) abc_args += " -lut 4"; else - abc_args += " -lut 4:7"; + abc_args += " -lut " + widelut_abc; if (dff) abc_args += " -dff"; run("abc" + abc_args); @@ -476,8 +555,14 @@ struct SynthLatticePass : public ScriptPass if (check_label("map_cells")) { - run("techmap -map +/lattice/cells_map.v"); - run("opt_lut_ins -tech lattice"); + run("techmap -map +/lattice/cells_map" + cells_map + ".v"); + if (is_nexus) { + // This is needed for Radiant, but perhaps not optimal for nextpnr... + run("setundef -zero"); + run("hilomap -singleton -hicell VHI Z -locell VLO Z"); + } else { + run("opt_lut_ins -tech lattice"); + } run("clean"); } @@ -504,6 +589,33 @@ struct SynthLatticePass : public ScriptPass } } SynthLatticePass; +struct SynthNexusPass : public Pass +{ + SynthNexusPass() : Pass("synth_nexus", "synthesis for Nexus FPGAs") { } + + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" synth_nexus [options]\n"); + log("\n"); + log("This command runs synthesis for Nexus FPGAs.\n"); + log("\n"); + log("This is a wrapper pass, for details take a look at help message for synth_lattice.\n"); + log("\n"); + } + + void execute(std::vector args, RTLIL::Design *design) override + { + args[0] = "synth_lattice"; + args.insert(args.begin()+1, std::string()); + args.insert(args.begin()+1, std::string()); + args[1] = "-family"; + args[2] = "lifcl"; + Pass::call(design, args); + } +} SynthNexusPass; + struct SynthEcp5Pass : public Pass { SynthEcp5Pass() : Pass("synth_ecp5", "synthesis for ECP5 FPGAs") { } diff --git a/techlibs/nexus/Makefile.inc b/techlibs/nexus/Makefile.inc deleted file mode 100644 index 8121d1d8a..000000000 --- a/techlibs/nexus/Makefile.inc +++ /dev/null @@ -1,16 +0,0 @@ -OBJS += techlibs/nexus/synth_nexus.o - -$(eval $(call add_share_file,share/nexus,techlibs/nexus/cells_map.v)) -$(eval $(call add_share_file,share/nexus,techlibs/nexus/cells_sim.v)) -$(eval $(call add_share_file,share/nexus,techlibs/nexus/parse_init.vh)) -$(eval $(call add_share_file,share/nexus,techlibs/nexus/cells_xtra.v)) -$(eval $(call add_share_file,share/nexus,techlibs/nexus/lutrams_map.v)) -$(eval $(call add_share_file,share/nexus,techlibs/nexus/lutrams.txt)) -$(eval $(call add_share_file,share/nexus,techlibs/nexus/brams_map.v)) -$(eval $(call add_share_file,share/nexus,techlibs/nexus/brams.txt)) -$(eval $(call add_share_file,share/nexus,techlibs/nexus/lrams_map.v)) -$(eval $(call add_share_file,share/nexus,techlibs/nexus/lrams.txt)) -$(eval $(call add_share_file,share/nexus,techlibs/nexus/arith_map.v)) -$(eval $(call add_share_file,share/nexus,techlibs/nexus/latches_map.v)) -$(eval $(call add_share_file,share/nexus,techlibs/nexus/dsp_map.v)) - diff --git a/techlibs/nexus/latches_map.v b/techlibs/nexus/latches_map.v deleted file mode 100644 index c28f88cf7..000000000 --- a/techlibs/nexus/latches_map.v +++ /dev/null @@ -1,11 +0,0 @@ -module \$_DLATCH_N_ (E, D, Q); - wire [1023:0] _TECHMAP_DO_ = "simplemap; opt"; - input E, D; - output Q = !E ? D : Q; -endmodule - -module \$_DLATCH_P_ (E, D, Q); - wire [1023:0] _TECHMAP_DO_ = "simplemap; opt"; - input E, D; - output Q = E ? D : Q; -endmodule diff --git a/techlibs/nexus/synth_nexus.cc b/techlibs/nexus/synth_nexus.cc deleted file mode 100644 index 6fd15ba55..000000000 --- a/techlibs/nexus/synth_nexus.cc +++ /dev/null @@ -1,417 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2020 gatecat - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include "kernel/register.h" -#include "kernel/celltypes.h" -#include "kernel/rtlil.h" -#include "kernel/log.h" - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -struct SynthNexusPass : public ScriptPass -{ - SynthNexusPass() : ScriptPass("synth_nexus", "synthesis for Lattice Nexus FPGAs") { } - - void on_register() override - { - RTLIL::constpad["synth_nexus.abc9.W"] = "300"; - } - - void help() override - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" synth_nexus [options]\n"); - log("\n"); - log("This command runs synthesis for Lattice Nexus FPGAs.\n"); - log("\n"); - log(" -top \n"); - log(" use the specified module as top module\n"); - log("\n"); - log(" -family \n"); - log(" run synthesis for the specified Nexus device\n"); - log(" supported values: lifcl, lfd2nx\n"); - log("\n"); - log(" -json \n"); - log(" write the design to the specified JSON file. writing of an output file\n"); - log(" is omitted if this parameter is not specified.\n"); - log("\n"); - log(" -vm \n"); - log(" write the design to the specified structural Verilog file. writing of\n"); - log(" an output file is omitted if this parameter is not specified.\n"); - log("\n"); - log(" -run :\n"); - log(" only run the commands between the labels (see below). an empty\n"); - log(" from label is synonymous to 'begin', and empty to label is\n"); - log(" synonymous to the end of the command list.\n"); - log("\n"); - log(" -noflatten\n"); - log(" do not flatten design before synthesis\n"); - log("\n"); - log(" -dff\n"); - log(" run 'abc'/'abc9' with -dff option\n"); - log("\n"); - log(" -retime\n"); - log(" run 'abc' with '-dff -D 1' options\n"); - log("\n"); - log(" -noccu2\n"); - log(" do not use CCU2 cells in output netlist\n"); - log("\n"); - log(" -nodffe\n"); - log(" do not use flipflops with CE in output netlist\n"); - log("\n"); - log(" -nolram\n"); - log(" do not use large RAM cells in output netlist\n"); - log(" note that large RAM must be explicitly requested with a (* lram *)\n"); - log(" attribute on the memory.\n"); - log("\n"); - log(" -nobram\n"); - log(" do not use block RAM cells in output netlist\n"); - log("\n"); - log(" -nolutram\n"); - log(" do not use LUT RAM cells in output netlist\n"); - log("\n"); - log(" -nowidelut\n"); - log(" do not use PFU muxes to implement LUTs larger than LUT4s\n"); - log("\n"); - log(" -noiopad\n"); - log(" do not insert IO buffers\n"); - log("\n"); - log(" -nodsp\n"); - log(" do not infer DSP multipliers\n"); - log("\n"); - log(" -abc9\n"); - log(" use new ABC9 flow (EXPERIMENTAL)\n"); - log("\n"); - log("The following commands are executed by this synthesis command:\n"); - help_script(); - log("\n"); - } - - string top_opt, json_file, vm_file, family; - bool noccu2, nodffe, nolram, nobram, nolutram, nowidelut, noiopad, nodsp, flatten, dff, retime, abc9; - - void clear_flags() override - { - top_opt = "-auto-top"; - family = "lifcl"; - json_file = ""; - vm_file = ""; - noccu2 = false; - nodffe = false; - nolram = false; - nobram = false; - nolutram = false; - nowidelut = false; - noiopad = false; - nodsp = false; - flatten = true; - dff = false; - retime = false; - } - - void execute(std::vector args, RTLIL::Design *design) override - { - string run_from, run_to; - clear_flags(); - - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) - { - if (args[argidx] == "-top" && argidx+1 < args.size()) { - top_opt = "-top " + args[++argidx]; - continue; - } - if (args[argidx] == "-json" && argidx+1 < args.size()) { - json_file = args[++argidx]; - continue; - } - if (args[argidx] == "-vm" && argidx+1 < args.size()) { - vm_file = args[++argidx]; - continue; - } - if (args[argidx] == "-run" && argidx+1 < args.size()) { - size_t pos = args[argidx+1].find(':'); - if (pos == std::string::npos) - break; - run_from = args[++argidx].substr(0, pos); - run_to = args[argidx].substr(pos+1); - continue; - } - if ((args[argidx] == "-family") && argidx+1 < args.size()) { - family = args[++argidx]; - continue; - } - if (args[argidx] == "-flatten") { - flatten = true; - continue; - } - if (args[argidx] == "-noflatten") { - flatten = false; - continue; - } - if (args[argidx] == "-dff") { - dff = true; - continue; - } - if (args[argidx] == "-nodsp") { - nodsp = true; - continue; - } - if (args[argidx] == "-retime") { - retime = true; - continue; - } - if (args[argidx] == "-noccu2") { - noccu2 = true; - continue; - } - if (args[argidx] == "-nodffe") { - nodffe = true; - continue; - } - if (args[argidx] == "-nolram") { - nolram = true; - continue; - } - if (args[argidx] == "-nobram") { - nobram = true; - continue; - } - if (args[argidx] == "-nolutram") { - nolutram = true; - continue; - } - if (args[argidx] == "-nowidelut") { - nowidelut = true; - continue; - } - if (args[argidx] == "-noiopad") { - noiopad = true; - continue; - } - if (args[argidx] == "-abc9") { - abc9 = true; - continue; - } - break; - } - extra_args(args, argidx, design); - - if (!design->full_selection()) - log_cmd_error("This command only operates on fully selected designs!\n"); - - if (abc9 && retime) - log_cmd_error("-retime option not currently compatible with -abc9!\n"); - - log_header(design, "Executing SYNTH_NEXUS pass.\n"); - log_push(); - - run_script(design, run_from, run_to); - - log_pop(); - } - - struct DSPRule { - int a_maxwidth; - int b_maxwidth; - int a_minwidth; - int b_minwidth; - std::string prim; - }; - - const std::vector dsp_rules = { - {36, 36, 22, 22, "$__NX_MUL36X36"}, - {36, 18, 22, 10, "$__NX_MUL36X18"}, - {18, 18, 10, 4, "$__NX_MUL18X18"}, - {18, 18, 4, 10, "$__NX_MUL18X18"}, - { 9, 9, 4, 4, "$__NX_MUL9X9"}, - }; - - void script() override - { - - if (family != "lifcl" && family != "lfd2nx") - log_cmd_error("Invalid Nexus -family setting: '%s'.\n", family.c_str()); - - if (check_label("begin")) - { - run("read_verilog -lib -specify +/nexus/cells_sim.v +/nexus/cells_xtra.v"); - run(stringf("hierarchy -check %s", help_mode ? "-top " : top_opt.c_str())); - } - - if (check_label("coarse")) - { - run("proc"); - if (flatten || help_mode) - run("flatten"); - run("tribuf -logic"); - run("deminout"); - run("opt_expr"); - run("opt_clean"); - run("check"); - run("opt -nodffe -nosdff"); - run("fsm"); - run("opt"); - run("wreduce"); - run("peepopt"); - run("opt_clean"); - run("share"); - run("techmap -map +/cmp2lut.v -D LUT_WIDTH=4"); - run("opt_expr"); - run("opt_clean"); - - if (help_mode) { - run("techmap -map +/mul2dsp.v [...]", "(unless -nodsp)"); - run("techmap -map +/nexus/dsp_map.v", "(unless -nodsp)"); - } else if (!nodsp) { - for (const auto &rule : dsp_rules) { - run(stringf("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=%d -D DSP_B_MAXWIDTH=%d -D DSP_A_MINWIDTH=%d -D DSP_B_MINWIDTH=%d -D DSP_NAME=%s", - rule.a_maxwidth, rule.b_maxwidth, rule.a_minwidth, rule.b_minwidth, rule.prim.c_str())); - run("chtype -set $mul t:$__soft_mul"); - } - run("techmap -map +/nexus/dsp_map.v"); - } - - run("alumacc"); - run("opt"); - run("memory -nomap"); - run("opt_clean"); - } - - if (check_label("map_ram")) - { - std::string args = ""; - args += " -no-auto-huge"; - if (nobram) - args += " -no-auto-block"; - if (nolutram) - args += " -no-auto-distributed"; - if (help_mode) - args += " [-no-auto-block] [-no-auto-distributed]"; - run("memory_libmap -lib +/nexus/lutrams.txt -lib +/nexus/brams.txt -lib +/nexus/lrams.txt" + args, "(-no-auto-block if -nobram, -no-auto-distributed if -nolutram)"); - run("techmap -map +/nexus/lutrams_map.v -map +/nexus/brams_map.v -map +/nexus/lrams_map.v"); - } - - if (check_label("map_ffram")) - { - run("opt -fast -mux_undef -undriven -fine"); - run("memory_map"); - run("opt -undriven -fine"); - } - - if (check_label("map_gates")) - { - if (noccu2) - run("techmap"); - else - run("techmap -map +/techmap.v -map +/nexus/arith_map.v"); - if (help_mode || !noiopad) - run("iopadmap -bits -outpad OB I:O -inpad IB O:I -toutpad OBZ ~T:I:O -tinoutpad BB ~T:O:I:B A:top", "(skip if '-noiopad')"); - run("opt -fast"); - if (retime || help_mode) - run("abc -dff -D 1", "(only if -retime)"); - } - - if (check_label("map_ffs")) - { - run("opt_clean"); - std::string dfflegalize_args = " -cell $_DFF_P_ 01 -cell $_DFF_PP?_ r -cell $_SDFF_PP?_ r -cell $_DLATCH_?_ x"; - if (help_mode) { - dfflegalize_args += " [-cell $_DFFE_PP_ 01 -cell $_DFFE_PP?P_ r -cell $_SDFFE_PP?P_ r]"; - } else if (!nodffe) { - dfflegalize_args += " -cell $_DFFE_PP_ 01 -cell $_DFFE_PP?P_ r -cell $_SDFFE_PP?P_ r"; - } - run("dfflegalize" + dfflegalize_args, "($_*DFFE_* only if not -nodffe)"); - if ((abc9 && dff) || help_mode) - run("zinit -all w:* t:$_DFF_?_ t:$_DFFE_??_ t:$_SDFF*", "(only if -abc9 and -dff"); - run("techmap -D NO_LUT -map +/nexus/cells_map.v"); - run("opt_expr -undriven -mux_undef"); - run("simplemap"); - run("attrmvcp -copy -attr syn_useioff"); - run("opt_clean"); - } - - if (check_label("map_luts")) - { - run("techmap -map +/nexus/latches_map.v"); - - if (abc9) { - std::string abc9_opts; - if (nowidelut) - abc9_opts += " -maxlut 4"; - std::string k = "synth_nexus.abc9.W"; - if (active_design && active_design->scratchpad.count(k)) - abc9_opts += stringf(" -W %s", active_design->scratchpad_get_string(k).c_str()); - else - abc9_opts += stringf(" -W %s", RTLIL::constpad.at(k).c_str()); - if (nowidelut) - abc9_opts += " -maxlut 4"; - if (dff) - abc9_opts += " -dff"; - run("abc9" + abc9_opts); - } else { - std::string abc_args = " -dress"; - if (nowidelut) - abc_args += " -lut 4"; - else - abc_args += " -lut 4:5"; - if (dff) - abc_args += " -dff"; - run("abc" + abc_args); - } - run("clean"); - } - - if (check_label("map_cells")) - { - run("techmap -map +/nexus/cells_map.v"); - - // This is needed for Radiant, but perhaps not optimal for nextpnr... - run("setundef -zero"); - - run("hilomap -singleton -hicell VHI Z -locell VLO Z"); - run("clean"); - } - - if (check_label("check")) - { - run("autoname"); - run("hierarchy -check"); - run("stat"); - run("check -noinit"); - run("blackbox =A:whitebox"); - } - - if (check_label("json")) - { - if (!json_file.empty() || help_mode) - run(stringf("write_json %s", help_mode ? "" : json_file.c_str())); - } - - if (check_label("vm")) - { - if (!vm_file.empty() || help_mode) - run(stringf("write_verilog %s", help_mode ? "" : vm_file.c_str())); - } - } -} SynthNexusPass; - -PRIVATE_NAMESPACE_END