Added "check -initdrv"
authorClifford Wolf <clifford@clifford.at>
Wed, 4 Jan 2017 17:12:41 +0000 (18:12 +0100)
committerClifford Wolf <clifford@clifford.at>
Wed, 4 Jan 2017 17:12:41 +0000 (18:12 +0100)
passes/cmds/check.cc

index b3622cb191d59fa8ade8c1582ee08eb4d4453e2b..bb8fe6856c46b6a54e0085aae9bb491235806498 100644 (file)
@@ -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<IdString> 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<SigBit> 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);