Added $assert cell
[yosys.git] / frontends / ast / simplify.cc
index bc5dec7b982c5ee57ab6a2a2ea63c030f47dad79..c266800e934eabb7b060afb31291b78d159b6221 100644 (file)
@@ -966,6 +966,66 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
        }
 skip_dynamic_range_lvalue_expansion:;
 
+       if (stage > 1 && type == AST_ASSERT && current_block != NULL)
+       {
+               std::stringstream sstr;
+               sstr << "$assert$" << filename << ":" << linenum << "$" << (RTLIL::autoidx++);
+               std::string id_check = sstr.str() + "_CHECK", id_en = sstr.str() + "_EN";
+
+               AstNode *wire_check = new AstNode(AST_WIRE);
+               wire_check->str = id_check;
+               current_ast_mod->children.push_back(wire_check);
+               current_scope[wire_check->str] = wire_check;
+               while (wire_check->simplify(true, false, false, 1, -1, false)) { }
+
+               AstNode *wire_en = new AstNode(AST_WIRE);
+               wire_en->str = id_en;
+               current_ast_mod->children.push_back(wire_en);
+               current_scope[wire_en->str] = wire_en;
+               while (wire_en->simplify(true, false, false, 1, -1, false)) { }
+
+               std::vector<RTLIL::State> x_bit;
+               x_bit.push_back(RTLIL::State::Sx);
+
+               AstNode *assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_bits(x_bit, false));
+               assign_check->children[0]->str = id_check;
+
+               AstNode *assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(0, false, 1));
+               assign_en->children[0]->str = id_en;
+
+               AstNode *default_signals = new AstNode(AST_BLOCK);
+               default_signals->children.push_back(assign_check);
+               default_signals->children.push_back(assign_en);
+               current_top_block->children.insert(current_top_block->children.begin(), default_signals);
+
+               assign_check = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), new AstNode(AST_REDUCE_BOOL, children[0]->clone()));
+               assign_check->children[0]->str = id_check;
+
+               assign_en = new AstNode(AST_ASSIGN_LE, new AstNode(AST_IDENTIFIER), mkconst_int(1, false, 1));
+               assign_en->children[0]->str = id_en;
+
+               newNode = new AstNode(AST_BLOCK);
+               newNode->children.push_back(assign_check);
+               newNode->children.push_back(assign_en);
+
+               AstNode *assertnode = new AstNode(AST_ASSERT);
+               assertnode->children.push_back(new AstNode(AST_IDENTIFIER));
+               assertnode->children.push_back(new AstNode(AST_IDENTIFIER));
+               assertnode->children[0]->str = id_check;
+               assertnode->children[1]->str = id_en;
+               assertnode->attributes.swap(attributes);
+               current_ast_mod->children.push_back(assertnode);
+
+               goto apply_newNode;
+       }
+
+       if (stage > 1 && type == AST_ASSERT && children.size() == 1)
+       {
+               children[0] = new AstNode(AST_REDUCE_BOOL, children[0]->clone());
+               children.push_back(mkconst_int(1, false, 1));
+               did_something = true;
+       }
+
        // found right-hand side identifier for memory -> replace with memory read port
        if (stage > 1 && type == AST_IDENTIFIER && id2ast != NULL && id2ast->type == AST_MEMORY && !in_lvalue &&
                        children[0]->type == AST_RANGE && children[0]->children.size() == 1) {