Add (* gclk *) attribute support
authorClifford Wolf <clifford@clifford.at>
Fri, 1 Jun 2018 11:25:42 +0000 (13:25 +0200)
committerClifford Wolf <clifford@clifford.at>
Fri, 1 Jun 2018 11:25:42 +0000 (13:25 +0200)
Signed-off-by: Clifford Wolf <clifford@clifford.at>
README.md
frontends/ast/genrtlil.cc
frontends/verific/verific.cc
frontends/verific/verific.h

index 704948e2d121a41f3dd936b35ea84fa8a7ea9211..c02691d94d624ab6f3d1581448e6821be3b38006 100644 (file)
--- a/README.md
+++ b/README.md
@@ -418,7 +418,9 @@ Non-standard or SystemVerilog features for formal verification
   supported in any clocked block.
 
 - The syntax ``@($global_clock)`` can be used to create FFs that have no
-  explicit clock input ($ff cells).
+  explicit clock input ($ff cells). The same can be achieved by using
+  ``@(posedge <netname>)`` or ``@(negedge <netname>)`` when ``<netname>``
+  is marked with the ``(* gclk *)`` Verilog attribute.
 
 
 Supported features from SystemVerilog
index 57ba9668d02c4e78efe536ba37c3f34a74814530..40cbbc2a3e9224ab23d4809fce246a42c685dbe8 100644 (file)
@@ -223,12 +223,18 @@ struct AST_INTERNAL::ProcessGenerator
                bool found_global_syncs = false;
                bool found_anyedge_syncs = false;
                for (auto child : always->children)
+               {
+                       if ((child->type == AST_POSEDGE || child->type == AST_NEGEDGE) && GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER &&
+                                       child->children.at(0)->id2ast && child->children.at(0)->id2ast->type == AST_WIRE && child->children.at(0)->id2ast->get_bool_attribute("\\gclk")) {
+                               found_global_syncs = true;
+                       }
                        if (child->type == AST_EDGE) {
                                if (GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER && child->children.at(0)->str == "\\$global_clock")
                                        found_global_syncs = true;
                                else
                                        found_anyedge_syncs = true;
                        }
+               }
 
                if (found_anyedge_syncs) {
                        if (found_global_syncs)
@@ -242,6 +248,9 @@ struct AST_INTERNAL::ProcessGenerator
                bool found_clocked_sync = false;
                for (auto child : always->children)
                        if (child->type == AST_POSEDGE || child->type == AST_NEGEDGE) {
+                               if (GetSize(child->children) == 1 && child->children.at(0)->type == AST_IDENTIFIER && child->children.at(0)->id2ast &&
+                                               child->children.at(0)->id2ast->type == AST_WIRE && child->children.at(0)->id2ast->get_bool_attribute("\\gclk"))
+                                       continue;
                                found_clocked_sync = true;
                                if (found_global_syncs || found_anyedge_syncs)
                                        log_error("Found non-synthesizable event list at %s:%d!\n", always->filename.c_str(), always->linenum);
index 12f2fdd7fd76e0cb83fc3c4bc3678b3b35310bf8..f67337754d9fe6944ce1bd69659eecec8f0d6b74 100644 (file)
@@ -1470,6 +1470,10 @@ VerificClocking::VerificClocking(VerificImporter *importer, Net *net, bool sva_a
 
        clock_net = net;
        clock_sig = importer->net_map_at(clock_net);
+
+       const char *gclk_attr = clock_net->GetAttValue("gclk");
+       if (gclk_attr != nullptr && (!strcmp(gclk_attr, "1") || !strcmp(gclk_attr, "'1'")))
+               gclk = true;
 }
 
 Cell *VerificClocking::addDff(IdString name, SigSpec sig_d, SigSpec sig_q, Const init_value)
@@ -1492,15 +1496,20 @@ Cell *VerificClocking::addDff(IdString name, SigSpec sig_d, SigSpec sig_q, Const
                sig_d = module->Mux(NEW_ID, sig_q, sig_d, enable_sig);
 
        if (disable_sig != State::S0) {
+               log_assert(gclk == false);
                log_assert(GetSize(sig_q) == GetSize(init_value));
                return module->addAdff(name, clock_sig, disable_sig, sig_d, sig_q, init_value, posedge);
        }
 
+       if (gclk)
+               return module->addFf(name, sig_d, sig_q);
+
        return module->addDff(name, clock_sig, sig_d, sig_q, posedge);
 }
 
 Cell *VerificClocking::addAdff(IdString name, RTLIL::SigSpec sig_arst, SigSpec sig_d, SigSpec sig_q, Const arst_value)
 {
+       log_assert(gclk == false);
        log_assert(disable_sig == State::S0);
 
        if (enable_sig != State::S1)
@@ -1511,6 +1520,7 @@ Cell *VerificClocking::addAdff(IdString name, RTLIL::SigSpec sig_arst, SigSpec s
 
 Cell *VerificClocking::addDffsr(IdString name, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr, SigSpec sig_d, SigSpec sig_q)
 {
+       log_assert(gclk == false);
        log_assert(disable_sig == State::S0);
 
        if (enable_sig != State::S1)
index 714b7c82abf5602b38acd8b11b081a6b315d65d0..86a743ea16b6a32189cfb0eda218bdaa2fcbb7ca 100644 (file)
@@ -40,6 +40,7 @@ struct VerificClocking {
        SigBit enable_sig = State::S1;
        SigBit disable_sig = State::S0;
        bool posedge = true;
+       bool gclk = false;
 
        VerificClocking() { }
        VerificClocking(VerificImporter *importer, Verific::Net *net, bool sva_at_only = false);