Add latch detection for use_case_method in part-select write, fixes #2040
authorClaire Wolf <claire@symbioticeda.com>
Thu, 4 Jun 2020 21:10:03 +0000 (23:10 +0200)
committerClaire Wolf <claire@symbioticeda.com>
Thu, 4 Jun 2020 21:25:59 +0000 (23:25 +0200)
Signed-off-by: Claire Wolf <claire@symbioticeda.com>
frontends/ast/ast.h
frontends/ast/simplify.cc

index 6d556fae2d3b383721fc817d775abb11ac8a1554..b8f24ee1484d270b5a40748c27d7b6c60dc5cdb7 100644 (file)
@@ -257,6 +257,7 @@ namespace AST
                bool mem2reg_check(pool<AstNode*> &mem2reg_set);
                void mem2reg_remove(pool<AstNode*> &mem2reg_set, vector<AstNode*> &delnodes);
                void meminfo(int &mem_width, int &mem_size, int &addr_bits);
+               bool detect_latch(const std::string &var);
 
                // additional functionality for evaluating constant functions
                struct varinfo_t { RTLIL::Const val; int offset; bool is_signed; };
index e88331621b6fde20a3c36e029f0c580520b6fceb..1d80a5dc41a3cec5a350ff223415d9671b954121 100644 (file)
@@ -2017,6 +2017,9 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
                                use_case_method = true;
                }
 
+               if (!use_case_method && current_always->detect_latch(children[0]->str))
+                       use_case_method = true;
+
                if (use_case_method)
                {
                        // big case block
@@ -4085,6 +4088,60 @@ void AstNode::meminfo(int &mem_width, int &mem_size, int &addr_bits)
                addr_bits++;
 }
 
+bool AstNode::detect_latch(const std::string &var)
+{
+       switch (type)
+       {
+       case AST_ALWAYS:
+               for (auto &c : children)
+               {
+                       switch (c->type)
+                       {
+                       case AST_POSEDGE:
+                       case AST_NEGEDGE:
+                               return false;
+                       case AST_BLOCK:
+                               if (!c->detect_latch(var))
+                                       return false;
+                               break;
+                       default:
+                               log_abort();
+                       }
+               }
+               return true;
+       case AST_BLOCK:
+               for (auto &c : children)
+                       if (!c->detect_latch(var))
+                               return false;
+               return true;
+       case AST_CASE:
+               {
+                       bool r = true;
+                       for (auto &c : children) {
+                               if (c->type == AST_COND) {
+                                       if (c->children.at(1)->detect_latch(var))
+                                               return true;
+                                       r = false;
+                               }
+                               if (c->type == AST_DEFAULT) {
+                                       if (c->children.at(0)->detect_latch(var))
+                                               return true;
+                                       r = false;
+                               }
+                       }
+                       return r;
+               }
+       case AST_ASSIGN_EQ:
+       case AST_ASSIGN_LE:
+               if (children.at(0)->type == AST_IDENTIFIER &&
+                               children.at(0)->children.empty() && children.at(0)->str == var)
+                       return false;
+               return true;
+       default:
+               return true;
+       }
+}
+
 bool AstNode::has_const_only_constructs(bool &recommend_const_eval)
 {
        if (type == AST_FOR)