From 32a268d745a14716a898dfe88f1609c9dcbcdfd4 Mon Sep 17 00:00:00 2001 From: nella Date: Thu, 18 Jun 2026 17:07:24 +0200 Subject: [PATCH] Emit errors before dfflegalize. --- .../macro_commands/synth_ice40.ys | 2 +- passes/cmds/check.cc | 22 +++++++++++++++++-- techlibs/efinix/synth_efinix.cc | 11 ++++++---- techlibs/fabulous/synth_fabulous.cc | 11 ++++++---- techlibs/ice40/synth_ice40.cc | 11 ++++++---- techlibs/lattice/synth_lattice.cc | 11 ++++++---- techlibs/nanoxplore/synth_nanoxplore.cc | 11 ++++++---- techlibs/quicklogic/synth_quicklogic.cc | 11 ++++++---- tests/various/check_nolatches.ys | 16 ++++++++++++++ tests/various/synth_latch_warning.ys | 3 ++- 10 files changed, 81 insertions(+), 28 deletions(-) diff --git a/docs/source/code_examples/macro_commands/synth_ice40.ys b/docs/source/code_examples/macro_commands/synth_ice40.ys index b3fca3e78..a829c197c 100644 --- a/docs/source/code_examples/macro_commands/synth_ice40.ys +++ b/docs/source/code_examples/macro_commands/synth_ice40.ys @@ -67,7 +67,7 @@ map_ffs: map_luts: abc ice40_opt - select + check techmap simplemap techmap diff --git a/passes/cmds/check.cc b/passes/cmds/check.cc index 479b2ee81..de077415f 100644 --- a/passes/cmds/check.cc +++ b/passes/cmds/check.cc @@ -124,12 +124,27 @@ struct CheckPass : public Pass { } extra_args(args, argidx, design); + bool latchonly = design->scratchpad_get_bool("check.latchonly", false); + log_header(design, "Executing CHECK pass (checking for obvious problems).\n"); for (auto module : design->selected_whole_modules_warn()) { log("Checking module %s...\n", module); + // 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 ( + cell->type.in(ID($dlatch), ID($adlatch), ID($dlatchsr)) || + 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++; + } + continue; + } + SigMap sigmap(module); dict> wire_drivers; dict driver_cells; @@ -275,8 +290,11 @@ struct CheckPass : public Pass { cell_allowed:; } - if (nolatches && (cell->type.in(ID($dlatch), ID($adlatch), ID($dlatchsr)) || - cell->type.begins_with("$_DLATCH_") || cell->type.begins_with("$_DLATCHSR_"))) { + if ( + nolatches && ( + cell->type.in(ID($dlatch), ID($adlatch), ID($dlatchsr)) || + 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/techlibs/efinix/synth_efinix.cc b/techlibs/efinix/synth_efinix.cc index 70b05c88d..dcb822426 100644 --- a/techlibs/efinix/synth_efinix.cc +++ b/techlibs/efinix/synth_efinix.cc @@ -160,7 +160,7 @@ struct SynthEfinixPass : public ScriptPass if (flatten && check_label("flatten", "(unless -noflatten)")) { - run("proc -latches " + (latches == "error" ? std::string("auto") : latches)); + run("proc -latches " + (latches == "auto" ? std::string("auto") : std::string("warn"))); run("check"); run("flatten"); run("tribuf -logic"); @@ -204,9 +204,12 @@ struct SynthEfinixPass : public ScriptPass { run("dfflegalize -cell $_DFFE_????_ 0 -cell $_SDFFE_????_ 0 -cell $_SDFFCE_????_ 0 -cell $_DLATCH_?_ x"); if (help_mode) - run("select -assert-none t:$_DLATCH_* t:$_DLATCHSR_*", "(only if -latches error, the default)"); - else if (latches == "error") - run("select -assert-none t:$_DLATCH_* t:$_DLATCHSR_*"); + run("check -assert", "(only if -latches error, the default)"); + else if (latches == "error") { + active_design->scratchpad_set_bool("check.latchonly", true); + run("check -assert"); + active_design->scratchpad_unset("check.latchonly"); + } run("techmap -D NO_LUT -map +/efinix/cells_map.v"); run("opt_expr -mux_undef"); run("simplemap"); diff --git a/techlibs/fabulous/synth_fabulous.cc b/techlibs/fabulous/synth_fabulous.cc index 56505b5f9..680928391 100644 --- a/techlibs/fabulous/synth_fabulous.cc +++ b/techlibs/fabulous/synth_fabulous.cc @@ -292,7 +292,7 @@ struct SynthPass : public ScriptPass run("hierarchy -check"); } else run(stringf("hierarchy -check -top %s", top_module)); - run("proc -latches " + (latches == "error" ? std::string("auto") : latches)); + run("proc -latches " + (latches == "auto" ? std::string("auto") : std::string("warn"))); } @@ -373,9 +373,12 @@ struct SynthPass : public ScriptPass run("dfflegalize -cell $_DFF_P_ 0 -cell $_DLATCH_?_ x", "without -complex-dff"); } if (help_mode) - run("select -assert-none t:$_DLATCH_* t:$_DLATCHSR_*", "(only if -latches error, the default)"); - else if (latches == "error") - run("select -assert-none t:$_DLATCH_* t:$_DLATCHSR_*"); + run("check -assert", "(only if -latches error, the default)"); + else if (latches == "error") { + active_design->scratchpad_set_bool("check.latchonly", true); + run("check -assert"); + active_design->scratchpad_unset("check.latchonly"); + } run("techmap -map +/fabulous/latches_map.v"); run("techmap -map +/fabulous/ff_map.v"); if (help_mode) { diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 9993a0d50..71e1a5ff9 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -316,7 +316,7 @@ struct SynthIce40Pass : public ScriptPass { run("read_verilog " + define + " -lib -specify +/ice40/cells_sim.v"); run(stringf("hierarchy -check %s", help_mode ? "-top " : top_opt)); - run("proc -latches " + (latches == "error" ? std::string("auto") : latches)); + run("proc -latches " + (latches == "auto" ? std::string("auto") : std::string("warn"))); } if (check_label("flatten", "(unless -noflatten)")) @@ -420,9 +420,12 @@ struct SynthIce40Pass : public ScriptPass run("ice40_opt", "(only if -abc2)"); } if (help_mode) - run("select -assert-none t:$_DLATCH_* t:$_DLATCHSR_*", "(only if -latches error, the default)"); - else if (latches == "error") - run("select -assert-none t:$_DLATCH_* t:$_DLATCHSR_*"); + run("check -assert", "(only if -latches error, the default)"); + else if (latches == "error") { + active_design->scratchpad_set_bool("check.latchonly", true); + run("check -assert"); + active_design->scratchpad_unset("check.latchonly"); + } run("techmap -map +/ice40/latches_map.v"); if (noabc || flowmap || help_mode) { run("simplemap", " (if -noabc or -flowmap)"); diff --git a/techlibs/lattice/synth_lattice.cc b/techlibs/lattice/synth_lattice.cc index 56d34d6f4..505f3a88d 100644 --- a/techlibs/lattice/synth_lattice.cc +++ b/techlibs/lattice/synth_lattice.cc @@ -416,7 +416,7 @@ struct SynthLatticePass : public ScriptPass if (check_label("coarse")) { - run("proc -latches " + ((asyncprld || latches == "error") ? std::string("auto") : latches)); + run("proc -latches " + ((asyncprld || latches == "auto") ? std::string("auto") : std::string("warn"))); if (flatten || help_mode) { run("check"); run("flatten"); @@ -548,9 +548,12 @@ struct SynthLatticePass : public ScriptPass run("abc", " (only if -abc2)"); if (!asyncprld || help_mode) { if (help_mode) - run("select -assert-none t:$_DLATCH_* t:$_DLATCHSR_*", "(skip if -asyncprld; only if -latches error, the default)"); - else if (latches == "error") - run("select -assert-none t:$_DLATCH_* t:$_DLATCHSR_*"); + run("check -assert", "(skip if -asyncprld; only if -latches error, the default)"); + else if (latches == "error") { + active_design->scratchpad_set_bool("check.latchonly", true); + run("check -assert"); + active_design->scratchpad_unset("check.latchonly"); + } run("techmap -map +/lattice/latches_map.v", "(skip if -asyncprld)"); } diff --git a/techlibs/nanoxplore/synth_nanoxplore.cc b/techlibs/nanoxplore/synth_nanoxplore.cc index f42784f54..9f2904a71 100644 --- a/techlibs/nanoxplore/synth_nanoxplore.cc +++ b/techlibs/nanoxplore/synth_nanoxplore.cc @@ -263,7 +263,7 @@ struct SynthNanoXplorePass : public ScriptPass if (check_label("coarse")) { - run("proc -latches " + (latches == "error" ? std::string("auto") : latches)); + run("proc -latches " + (latches == "auto" ? std::string("auto") : std::string("warn"))); if (flatten || help_mode) { run("check"); run("flatten", "(skip if -noflatten)"); @@ -340,9 +340,12 @@ struct SynthNanoXplorePass : public ScriptPass run("dfflegalize" + dfflegalize_args,"($_*DFFE_* only if not -nodffe)"); run("opt_merge"); if (help_mode) - run("select -assert-none t:$_DLATCH_* t:$_DLATCHSR_*", "(only if -latches error, the default)"); - else if (latches == "error") - run("select -assert-none t:$_DLATCH_* t:$_DLATCHSR_*"); + run("check -assert", "(only if -latches error, the default)"); + else if (latches == "error") { + active_design->scratchpad_set_bool("check.latchonly", true); + run("check -assert"); + active_design->scratchpad_unset("check.latchonly"); + } run("techmap -map +/nanoxplore/latches_map.v"); run("techmap -map +/nanoxplore/cells_map.v"); run("opt_expr -undriven -mux_undef"); diff --git a/techlibs/quicklogic/synth_quicklogic.cc b/techlibs/quicklogic/synth_quicklogic.cc index f465d0148..cab0aab7b 100644 --- a/techlibs/quicklogic/synth_quicklogic.cc +++ b/techlibs/quicklogic/synth_quicklogic.cc @@ -226,7 +226,7 @@ struct SynthQuickLogicPass : public ScriptPass { } if (check_label("prepare")) { - run("proc -latches " + ((family == "pp3" && latches != "error") ? latches : std::string("auto"))); + run("proc -latches " + ((family == "pp3" && latches != "auto") ? std::string("warn") : std::string("auto"))); if (flatten) { run("check"); run("flatten", "(unless -noflatten)"); @@ -331,9 +331,12 @@ struct SynthQuickLogicPass : public ScriptPass { if (check_label("map_luts", "(for pp3)") && (help_mode || family == "pp3")) { if (help_mode) - run("select -assert-none t:$_DLATCH_* t:$_DLATCHSR_*", "(only if -latches error, the default)"); - else if (latches == "error") - run("select -assert-none t:$_DLATCH_* t:$_DLATCHSR_*"); + run("check -assert", "(only if -latches error, the default)"); + else if (latches == "error") { + active_design->scratchpad_set_bool("check.latchonly", true); + run("check -assert"); + active_design->scratchpad_unset("check.latchonly"); + } run("techmap -map " + lib_path + family + "/latches_map.v"); if (abc9) { run("read_verilog -lib -specify -icells " + lib_path + family + "/abc9_model.v"); diff --git a/tests/various/check_nolatches.ys b/tests/various/check_nolatches.ys index 8079bd5bd..9655dcd5c 100644 --- a/tests/various/check_nolatches.ys +++ b/tests/various/check_nolatches.ys @@ -29,3 +29,19 @@ EOT proc logger -expect error "Found 1 problems in" 1 check -nolatches -assert + +design -reset + +read_verilog <