diff --git a/passes/cmds/check.cc b/passes/cmds/check.cc index b3622cb19..bb8fe6856 100644 --- a/passes/cmds/check.cc +++ b/passes/cmds/check.cc @@ -44,6 +44,9 @@ struct CheckPass : public Pass { log("When called with -noinit then this command also checks for wires which have\n"); log("the 'init' attribute set.\n"); log("\n"); + log("When called with -initdrv then this command also checks for wires which have\n"); + log("the 'init' attribute set and aren't driven by a FF cell type.\n"); + log("\n"); log("When called with -assert then the command will produce an error if any\n"); log("problems are found in the current design.\n"); log("\n"); @@ -52,6 +55,7 @@ struct CheckPass : public Pass { { int counter = 0; bool noinit = false; + bool initdrv = false; bool assert_mode = false; size_t argidx; @@ -60,6 +64,10 @@ struct CheckPass : public Pass { noinit = true; continue; } + if (args[argidx] == "-initdrv") { + initdrv = true; + continue; + } if (args[argidx] == "-assert") { assert_mode = true; continue; @@ -70,6 +78,49 @@ struct CheckPass : public Pass { log_header(design, "Executing CHECK pass (checking for obvious problems).\n"); + pool fftypes; + fftypes.insert("$sr"); + fftypes.insert("$ff"); + fftypes.insert("$dff"); + fftypes.insert("$dffe"); + fftypes.insert("$dffsr"); + fftypes.insert("$adff"); + fftypes.insert("$dlatch"); + fftypes.insert("$dlatchsr"); + fftypes.insert("$_DFFE_NN_"); + fftypes.insert("$_DFFE_NP_"); + fftypes.insert("$_DFFE_PN_"); + fftypes.insert("$_DFFE_PP_"); + fftypes.insert("$_DFFSR_NNN_"); + fftypes.insert("$_DFFSR_NNP_"); + fftypes.insert("$_DFFSR_NPN_"); + fftypes.insert("$_DFFSR_NPP_"); + fftypes.insert("$_DFFSR_PNN_"); + fftypes.insert("$_DFFSR_PNP_"); + fftypes.insert("$_DFFSR_PPN_"); + fftypes.insert("$_DFFSR_PPP_"); + fftypes.insert("$_DFF_NN0_"); + fftypes.insert("$_DFF_NN1_"); + fftypes.insert("$_DFF_NP0_"); + fftypes.insert("$_DFF_NP1_"); + fftypes.insert("$_DFF_N_"); + fftypes.insert("$_DFF_PN0_"); + fftypes.insert("$_DFF_PN1_"); + fftypes.insert("$_DFF_PP0_"); + fftypes.insert("$_DFF_PP1_"); + fftypes.insert("$_DFF_P_"); + fftypes.insert("$_DLATCHSR_NNN_"); + fftypes.insert("$_DLATCHSR_NNP_"); + fftypes.insert("$_DLATCHSR_NPN_"); + fftypes.insert("$_DLATCHSR_NPP_"); + fftypes.insert("$_DLATCHSR_PNN_"); + fftypes.insert("$_DLATCHSR_PNP_"); + fftypes.insert("$_DLATCHSR_PPN_"); + fftypes.insert("$_DLATCHSR_PPP_"); + fftypes.insert("$_DLATCH_N_"); + fftypes.insert("$_DLATCH_P_"); + fftypes.insert("$_FF_"); + for (auto module : design->selected_whole_modules_warn()) { if (module->has_processes_warn()) @@ -109,6 +160,8 @@ struct CheckPass : public Pass { if (bit.wire) wire_drivers_count[bit]++; } + pool init_bits; + for (auto wire : module->wires()) { if (wire->port_input) { SigSpec sig = sigmap(wire); @@ -121,9 +174,15 @@ struct CheckPass : public Pass { if (wire->port_input && !wire->port_output) for (auto bit : sigmap(wire)) if (bit.wire) wire_drivers_count[bit]++; - if (noinit && wire->attributes.count("\\init")) { - log_warning("Wire %s.%s has an unprocessed 'init' attribute.\n", log_id(module), log_id(wire)); - counter++; + if (wire->attributes.count("\\init")) { + Const initval = wire->attributes.at("\\init"); + for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++) + if (initval[i] == State::S0 || initval[i] == State::S1) + init_bits.insert(sigmap(SigBit(wire, i))); + if (noinit) { + log_warning("Wire %s.%s has an unprocessed 'init' attribute.\n", log_id(module), log_id(wire)); + counter++; + } } } @@ -150,6 +209,26 @@ struct CheckPass : public Pass { log_warning("%s", message.c_str()); counter++; } + + if (initdrv) + { + for (auto cell : module->cells()) + { + if (fftypes.count(cell->type) == 0) + continue; + + for (auto bit : sigmap(cell->getPort("\\Q"))) + init_bits.erase(bit); + } + + SigSpec init_sig(init_bits); + init_sig.sort_and_unify(); + + for (auto chunk : init_sig.chunks()) { + log_warning("Wire %s.%s has 'init' attribute and is not driven by an FF cell.\n", log_id(module), log_signal(chunk)); + counter++; + } + } } log("found and reported %d problems.\n", counter);