Added support for bufif0/bufif1 primitives
authorClifford Wolf <clifford@clifford.at>
Mon, 19 Aug 2013 17:50:04 +0000 (19:50 +0200)
committerClifford Wolf <clifford@clifford.at>
Mon, 19 Aug 2013 17:50:04 +0000 (19:50 +0200)
frontends/ast/simplify.cc
frontends/verilog/lexer.l

index 440d386180b165429385305b6dea7a80fe8b1728..1d381740b7973494c7f2ceca5dced915151c566a 100644 (file)
@@ -498,39 +498,65 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage)
                }
                children.clear();
 
-               AstNodeType op_type = AST_NONE;
-               bool invert_results = false;
-
-               if (str == "and")
-                       op_type = AST_BIT_AND;
-               if (str == "nand")
-                       op_type = AST_BIT_AND, invert_results = true;
-               if (str == "or")
-                       op_type = AST_BIT_OR;
-               if (str == "nor")
-                       op_type = AST_BIT_OR, invert_results = true;
-               if (str == "xor")
-                       op_type = AST_BIT_XOR;
-               if (str == "xnor")
-                       op_type = AST_BIT_XOR, invert_results = true;
-               if (str == "buf")
-                       op_type = AST_POS;
-               if (str == "not")
-                       op_type = AST_POS, invert_results = true;
-               assert(op_type != AST_NONE);
-
-               AstNode *node = children_list[1];
-               if (op_type != AST_POS)
-                       for (size_t i = 2; i < children_list.size(); i++)
-                               node = new AstNode(op_type, node, children_list[i]);
-               if (invert_results)
-                       node = new AstNode(AST_BIT_NOT, node);
+               if (str == "bufif0" || str == "bufif1")
+               {
+                       if (children_list.size() != 3)
+                               log_error("Invalid number of arguments for primitive `%s' at %s:%d!\n",
+                                               str.c_str(), filename.c_str(), linenum);
 
-               str.clear();
-               type = AST_ASSIGN;
-               children.push_back(children_list[0]);
-               children.push_back(node);
-               did_something = true;
+                       std::vector<RTLIL::State> z_const(1, RTLIL::State::Sz);
+
+                       AstNode *node = new AstNode(AST_TERNARY, children_list.at(2));
+                       if (str == "bufif0") {
+                               node->children.push_back(AstNode::mkconst_bits(z_const, false));
+                               node->children.push_back(children_list.at(1));
+                       } else {
+                               node->children.push_back(children_list.at(1));
+                               node->children.push_back(AstNode::mkconst_bits(z_const, false));
+                       }
+
+                       str.clear();
+                       type = AST_ASSIGN;
+                       children.push_back(children_list.at(0));
+                       children.push_back(node);
+                       did_something = true;
+               }
+               else
+               {
+                       AstNodeType op_type = AST_NONE;
+                       bool invert_results = false;
+
+                       if (str == "and")
+                               op_type = AST_BIT_AND;
+                       if (str == "nand")
+                               op_type = AST_BIT_AND, invert_results = true;
+                       if (str == "or")
+                               op_type = AST_BIT_OR;
+                       if (str == "nor")
+                               op_type = AST_BIT_OR, invert_results = true;
+                       if (str == "xor")
+                               op_type = AST_BIT_XOR;
+                       if (str == "xnor")
+                               op_type = AST_BIT_XOR, invert_results = true;
+                       if (str == "buf")
+                               op_type = AST_POS;
+                       if (str == "not")
+                               op_type = AST_POS, invert_results = true;
+                       assert(op_type != AST_NONE);
+
+                       AstNode *node = children_list[1];
+                       if (op_type != AST_POS)
+                               for (size_t i = 2; i < children_list.size(); i++)
+                                       node = new AstNode(op_type, node, children_list[i]);
+                       if (invert_results)
+                               node = new AstNode(AST_BIT_NOT, node);
+
+                       str.clear();
+                       type = AST_ASSIGN;
+                       children.push_back(children_list[0]);
+                       children.push_back(node);
+                       did_something = true;
+               }
        }
 
        // replace dynamic ranges in left-hand side expressions (e.g. "foo[bar] <= 1'b1;") with
index cc7590ca564fe1ac980c1f6ac73953030b18b3d9..e873f9d91a140a118ce2245b4515a8397949c964 100644 (file)
@@ -169,7 +169,7 @@ namespace VERILOG_FRONTEND {
 }
 <STRING>.      { yymore(); }
 
-and|nand|or|nor|xor|xnor|not|buf {
+and|nand|or|nor|xor|xnor|not|buf|bufif0|bufif1 {
        frontend_verilog_yylval.string = new std::string(yytext);
        return TOK_PRIMITIVE;
 }