diff --git a/passes/cmds/check.cc b/passes/cmds/check.cc index fb0e070ad..15d7583fc 100644 --- a/passes/cmds/check.cc +++ b/passes/cmds/check.cc @@ -143,10 +143,9 @@ struct CheckPass : public Pass { // latch-only mode only flags latches, skipping the (potentially false-positive mid-flow) undriven/driver/loop checks below if (latchonly) { for (auto cell : module->cells()) - if (( + if (!cell->get_bool_attribute(ID::always_latch) && ( cell->type.in(ID($dlatch), ID($adlatch), ID($dlatchsr)) || - cell->type.begins_with("$_DLATCH_") || cell->type.begins_with("$_DLATCHSR_") - ) && !cell->get_bool_attribute(ID::always_latch)) { + cell->type.begins_with("$_DLATCH_") || cell->type.begins_with("$_DLATCHSR_"))) { log_warning("Cell %s.%s is a latch of type %s.\n", module, cell, cell->type.unescape()); counter++; } @@ -299,10 +298,9 @@ struct CheckPass : public Pass { } if ( - nolatches && ( + nolatches && !cell->get_bool_attribute(ID::always_latch) && ( cell->type.in(ID($dlatch), ID($adlatch), ID($dlatchsr)) || - cell->type.begins_with("$_DLATCH_") || cell->type.begins_with("$_DLATCHSR_")) && - !cell->get_bool_attribute(ID::always_latch) + cell->type.begins_with("$_DLATCH_") || cell->type.begins_with("$_DLATCHSR_")) ) { log_warning("Cell %s.%s is a latch of type %s.\n", module, cell, cell->type.unescape()); counter++; diff --git a/passes/proc/proc.cc b/passes/proc/proc.cc index d781d9047..1f25c5608 100644 --- a/passes/proc/proc.cc +++ b/passes/proc/proc.cc @@ -69,7 +69,7 @@ struct ProcPass : public Pass { log(" -noopt\n"); log(" Will omit the opt_expr pass.\n"); log("\n"); - log(" -latches \n"); + log(" -latches \n"); log(" controls how the inference of a latch is reported.\n"); log("\n"); } diff --git a/techlibs/analogdevices/synth_analogdevices.cc b/techlibs/analogdevices/synth_analogdevices.cc index aa27c78b6..8653fbf32 100644 --- a/techlibs/analogdevices/synth_analogdevices.cc +++ b/techlibs/analogdevices/synth_analogdevices.cc @@ -108,13 +108,20 @@ struct SynthAnalogDevicesPass : public ScriptPass log(" -noabc9\n"); log(" disable use of new ABC9 flow\n"); log("\n"); + log(" -latches \n"); + log(" select the behaviour for latches that cannot be mapped to a\n"); + log(" dedicated hardware primitive and are implemented using LUTs\n"); + log(" instead. 'error' (the default) aborts synthesis, 'warn' only\n"); + log(" prints a warning, and 'info' permits them with an info-level message.\n"); + log(" Latches explicitly requested with 'always_latch' are always permitted.\n"); + log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); help_script(); log("\n"); } - std::string top_opt, edif_file, json_file, tech, tech_param; + std::string top_opt, edif_file, json_file, tech, tech_param, latches; bool flatten, retime, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp; bool abc9, dff; bool flatten_before_abc; @@ -127,6 +134,7 @@ struct SynthAnalogDevicesPass : public ScriptPass edif_file.clear(); tech = "t16ffc"; tech_param = " -D IS_T16FFC"; + latches = "error"; flatten = true; retime = false; noiopad = false; @@ -244,10 +252,17 @@ struct SynthAnalogDevicesPass : public ScriptPass json_file = args[++argidx]; continue; } + if (args[argidx] == "-latches" && argidx+1 < args.size()) { + latches = args[++argidx]; + continue; + } break; } extra_args(args, argidx, design); + if (latches != "info" && latches != "warn" && latches != "error") + log_cmd_error("Invalid value '%s' for -latches (expected info, warn or error)\n", latches.c_str()); + if (!(tech == "t16ffc" || tech == "t40lp")) log_cmd_error("Invalid ADI -tech setting: '%s'.\n", tech); @@ -276,7 +291,7 @@ struct SynthAnalogDevicesPass : public ScriptPass } if (check_label("prepare")) { - run("proc"); + run("proc -latches " + latches); if (flatten || help_mode) { run("check"); run("flatten", "(with '-flatten')"); @@ -439,6 +454,8 @@ struct SynthAnalogDevicesPass : public ScriptPass } if (check_label("map_ffs")) { + if (latches == "error" || help_mode) + run("check -latchonly -assert", "(only if -latches error, the default)"); run("dfflegalize -cell $_DFFE_?P?P_ r -cell $_SDFFE_?P?P_ r"); if (abc9 || help_mode) { if (dff || help_mode) diff --git a/techlibs/common/synth.cc b/techlibs/common/synth.cc index 31986f25b..cfe8e1b8d 100644 --- a/techlibs/common/synth.cc +++ b/techlibs/common/synth.cc @@ -78,7 +78,7 @@ struct SynthPass : public ScriptPass { log(" -nordff\n"); log(" passed to 'memory'. prohibits merging of FFs into memory read ports\n"); log("\n"); - log(" -latches \n"); + log(" -latches \n"); log(" controls how the inference of a latch is reported.\n"); log("\n"); log(" -noshare\n"); diff --git a/techlibs/intel_alm/synth_intel_alm.cc b/techlibs/intel_alm/synth_intel_alm.cc index 95dbb6e35..869399f42 100644 --- a/techlibs/intel_alm/synth_intel_alm.cc +++ b/techlibs/intel_alm/synth_intel_alm.cc @@ -72,12 +72,19 @@ struct SynthIntelALMPass : public ScriptPass { log(" -noclkbuf\n"); log(" do not insert global clock buffers\n"); log("\n"); + log(" -latches \n"); + log(" select the behaviour for latches that cannot be mapped to a\n"); + log(" dedicated hardware primitive and are implemented using LUTs\n"); + log(" instead. 'error' (the default) aborts synthesis, 'warn' only\n"); + log(" prints a warning, and 'info' permits them with an info-level message.\n"); + log(" Latches explicitly requested with 'always_latch' are always permitted.\n"); + log("\n"); log("The following commands are executed by this synthesis command:\n"); help_script(); log("\n"); } - string top_opt, family_opt, bram_type; + string top_opt, family_opt, bram_type, latches; bool flatten, nolutram, nobram, dff, nodsp, noiopad, noclkbuf; void clear_flags() override @@ -85,6 +92,7 @@ struct SynthIntelALMPass : public ScriptPass { top_opt = "-auto-top"; family_opt = "cyclonev"; bram_type = "m10k"; + latches = "error"; flatten = true; nolutram = false; nobram = false; @@ -145,10 +153,17 @@ struct SynthIntelALMPass : public ScriptPass { noclkbuf = true; continue; } + if (args[argidx] == "-latches" && argidx + 1 < args.size()) { + latches = args[++argidx]; + continue; + } break; } extra_args(args, argidx, design); + if (latches != "info" && latches != "warn" && latches != "error") + log_cmd_error("Invalid value '%s' for -latches (expected info, warn or error)\n", latches.c_str()); + if (!design->full_selection()) log_cmd_error("This command only operates on fully selected designs!\n"); @@ -183,7 +198,7 @@ struct SynthIntelALMPass : public ScriptPass { } if (check_label("coarse")) { - run("proc"); + run("proc -latches " + latches); if (flatten || help_mode) { run("check"); run("flatten", "(skip if -noflatten)"); @@ -241,6 +256,8 @@ struct SynthIntelALMPass : public ScriptPass { } if (check_label("map_ffs")) { + if (latches == "error" || help_mode) + run("check -latchonly -assert", "(only if -latches error, the default)"); run("techmap"); run("dfflegalize -cell $_DFFE_PN0P_ 0 -cell $_SDFFCE_PP0P_ 0"); run("techmap -map +/intel_alm/common/dff_map.v");