Added proper === and !== support in constant expressions
authorClifford Wolf <clifford@clifford.at>
Fri, 27 Dec 2013 12:50:08 +0000 (13:50 +0100)
committerClifford Wolf <clifford@clifford.at>
Fri, 27 Dec 2013 12:50:08 +0000 (13:50 +0100)
frontends/ast/ast.cc
frontends/ast/ast.h
frontends/ast/genrtlil.cc
frontends/ast/simplify.cc
frontends/verilog/lexer.l
frontends/verilog/parser.y
kernel/calc.cc
kernel/rtlil.h
tests/simple/undef_eqx_nex.v [new file with mode: 0644]

index 0e65f1cb7d3020c60f7e46635d55ad7aa184afdf..2015848850c14738eea1b380907d704f09333584 100644 (file)
@@ -103,6 +103,8 @@ std::string AST::type2str(AstNodeType type)
        X(AST_LE)
        X(AST_EQ)
        X(AST_NE)
+       X(AST_EQX)
+       X(AST_NEX)
        X(AST_GE)
        X(AST_GT)
        X(AST_ADD)
@@ -539,6 +541,8 @@ void AstNode::dumpVlog(FILE *f, std::string indent)
        if (0) { case AST_LE:           txt = "<=";  }
        if (0) { case AST_EQ:           txt = "==";  }
        if (0) { case AST_NE:           txt = "!=";  }
+       if (0) { case AST_EQX:          txt = "===";  }
+       if (0) { case AST_NEX:          txt = "!==";  }
        if (0) { case AST_GE:           txt = ">=";  }
        if (0) { case AST_GT:           txt = ">";   }
        if (0) { case AST_ADD:          txt = "+";   }
index f8e27927418ff2213c159ec1905a8de84e4eaa21..22853d0f9b08f95d4bb0e21d30eb8f0a569a6808 100644 (file)
@@ -82,6 +82,8 @@ namespace AST
                AST_LE,
                AST_EQ,
                AST_NE,
+               AST_EQX,
+               AST_NEX,
                AST_GE,
                AST_GT,
                AST_ADD,
index 269752df53dccf94e0350d668cfcfa4081a568ee..36ca1432b250dacd95d4a3dd77bb3cd1d3e9b810 100644 (file)
@@ -728,6 +728,8 @@ void AstNode::detectSignWidthWorker(int &width_hint, bool &sign_hint)
        case AST_LE:
        case AST_EQ:
        case AST_NE:
+       case AST_EQX:
+       case AST_NEX:
        case AST_GE:
        case AST_GT:
                width_hint = std::max(width_hint, 1);
@@ -1113,12 +1115,14 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
                }
 
        // generate cells for binary operations: $lt, $le, $eq, $ne, $ge, $gt
-       if (0) { case AST_LT: type_name = "$lt"; }
-       if (0) { case AST_LE: type_name = "$le"; }
-       if (0) { case AST_EQ: type_name = "$eq"; }
-       if (0) { case AST_NE: type_name = "$ne"; }
-       if (0) { case AST_GE: type_name = "$ge"; }
-       if (0) { case AST_GT: type_name = "$gt"; }
+       if (0) { case AST_LT:  type_name = "$lt"; }
+       if (0) { case AST_LE:  type_name = "$le"; }
+       if (0) { case AST_EQ:  type_name = "$eq"; }
+       if (0) { case AST_NE:  type_name = "$ne"; }
+       if (0) { case AST_EQX: type_name = "$eq"; }
+       if (0) { case AST_NEX: type_name = "$ne"; }
+       if (0) { case AST_GE:  type_name = "$ge"; }
+       if (0) { case AST_GT:  type_name = "$gt"; }
                {
                        int width = std::max(width_hint, 1);
                        width_hint = -1, sign_hint = true;
index f6df0c170457524f108664fed84b2f8c734d174c..982d1ae3588aa734b10e0e50346ae1f91c8a2478 100644 (file)
@@ -299,6 +299,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
        case AST_LE:
        case AST_EQ:
        case AST_NE:
+       case AST_EQX:
+       case AST_NEX:
        case AST_GE:
        case AST_GT:
                width_hint = -1;
@@ -1258,12 +1260,14 @@ skip_dynamic_range_lvalue_expansion:;
                                newNode = mkconst_bits(y.bits, sign_hint);
                        }
                        break;
-               if (0) { case AST_LT: const_func = RTLIL::const_lt; }
-               if (0) { case AST_LE: const_func = RTLIL::const_le; }
-               if (0) { case AST_EQ: const_func = RTLIL::const_eq; }
-               if (0) { case AST_NE: const_func = RTLIL::const_ne; }
-               if (0) { case AST_GE: const_func = RTLIL::const_ge; }
-               if (0) { case AST_GT: const_func = RTLIL::const_gt; }
+               if (0) { case AST_LT:  const_func = RTLIL::const_lt; }
+               if (0) { case AST_LE:  const_func = RTLIL::const_le; }
+               if (0) { case AST_EQ:  const_func = RTLIL::const_eq; }
+               if (0) { case AST_NE:  const_func = RTLIL::const_ne; }
+               if (0) { case AST_EQX: const_func = RTLIL::const_eqx; }
+               if (0) { case AST_NEX: const_func = RTLIL::const_nex; }
+               if (0) { case AST_GE:  const_func = RTLIL::const_ge; }
+               if (0) { case AST_GT:  const_func = RTLIL::const_gt; }
                        if (children[0]->type == AST_CONSTANT && children[1]->type == AST_CONSTANT) {
                                int cmp_width = std::max(children[0]->bits.size(), children[1]->bits.size());
                                bool cmp_signed = children[0]->is_signed && children[1]->is_signed;
index a0deb755beef0be37e836b96429b99418dabe29b..9e606d90f7714b0ecf93c6e3d9bb57a3b15b5394 100644 (file)
@@ -232,8 +232,8 @@ supply1 { return TOK_SUPPLY1; }
 "<=" { return OP_LE; }
 ">=" { return OP_GE; }
 
-"===" { return OP_EQ; }
-"!==" { return OP_NE; }
+"===" { return OP_EQX; }
+"!==" { return OP_NEX; }
 
 "~&" { return OP_NAND; }
 "~|" { return OP_NOR;  }
index f47d1785cd0b53cedf7a91d07fcd6d422aaf03ca..874482d6ecb41753b56322e7c5b608de93d24a13 100644 (file)
@@ -117,7 +117,7 @@ static void free_attr(std::map<std::string, AstNode*> *al)
 %left '|' OP_NOR
 %left '^' OP_XNOR
 %left '&' OP_NAND
-%left OP_EQ OP_NE
+%left OP_EQ OP_NE OP_EQX OP_NEX
 %left '<' OP_LE OP_GE '>'
 %left OP_SHL OP_SHR OP_SSHL OP_SSHR
 %left '+' '-'
@@ -1161,6 +1161,14 @@ basic_expr:
                $$ = new AstNode(AST_NE, $1, $4);
                append_attr($$, $3);
        } |
+       basic_expr OP_EQX attr basic_expr {
+               $$ = new AstNode(AST_EQX, $1, $4);
+               append_attr($$, $3);
+       } |
+       basic_expr OP_NEX attr basic_expr {
+               $$ = new AstNode(AST_NEX, $1, $4);
+               append_attr($$, $3);
+       } |
        basic_expr OP_GE attr basic_expr {
                $$ = new AstNode(AST_GE, $1, $4);
                append_attr($$, $3);
index 61025104dfe95e6d2987fe4cd63548b274cff520..fc978c11a9193e37262b0007149e9790220f20ca 100644 (file)
@@ -386,6 +386,35 @@ RTLIL::Const RTLIL::const_ne(const RTLIL::Const &arg1, const RTLIL::Const &arg2,
        return result;
 }
 
+RTLIL::Const RTLIL::const_eqx(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
+{
+       RTLIL::Const arg1_ext = arg1;
+       RTLIL::Const arg2_ext = arg2;
+       RTLIL::Const result(RTLIL::State::S0, result_len);
+
+       int width = std::max(arg1_ext.bits.size(), arg2_ext.bits.size());
+       extend_u0(arg1_ext, width, signed1 && signed2);
+       extend_u0(arg2_ext, width, signed1 && signed2);
+
+       for (size_t i = 0; i < arg1_ext.bits.size(); i++) {
+               if (arg1_ext.bits.at(i) != arg2_ext.bits.at(i))
+                       return result;
+       }
+
+       result.bits.front() = RTLIL::State::S1;
+       return result;
+}
+
+RTLIL::Const RTLIL::const_nex(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
+{
+       RTLIL::Const result = RTLIL::const_eqx(arg1, arg2, signed1, signed2, result_len);
+       if (result.bits.front() == RTLIL::State::S0)
+               result.bits.front() = RTLIL::State::S1;
+       else if (result.bits.front() == RTLIL::State::S1)
+               result.bits.front() = RTLIL::State::S0;
+       return result;
+}
+
 RTLIL::Const RTLIL::const_ge(const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len)
 {
        int undef_bit_pos = -1;
index fbdab53ebf39287a0280d7ade9730faba9e628b4..91dd9d44c87c2a83df5a2f15af378812e0bdc251 100644 (file)
@@ -174,6 +174,8 @@ namespace RTLIL
        RTLIL::Const const_le          (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
        RTLIL::Const const_eq          (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
        RTLIL::Const const_ne          (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
+       RTLIL::Const const_eqx         (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
+       RTLIL::Const const_nex         (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
        RTLIL::Const const_ge          (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
        RTLIL::Const const_gt          (const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len);
 
diff --git a/tests/simple/undef_eqx_nex.v b/tests/simple/undef_eqx_nex.v
new file mode 100644 (file)
index 0000000..63912a2
--- /dev/null
@@ -0,0 +1,11 @@
+module test(y);
+output [7:0] y;
+assign y[0] = 0/0;
+assign y[1] = 0/1;
+assign y[2] = 0/0 ==  32'bx;
+assign y[3] = 0/0 !=  32'bx;
+assign y[4] = 0/0 === 32'bx;
+assign y[5] = 0/0 !== 32'bx;
+assign y[6] = 0/1 === 32'bx;
+assign y[7] = 0/1 !== 32'bx;
+endmodule