X(AST_LE)
X(AST_EQ)
X(AST_NE)
+ X(AST_EQX)
+ X(AST_NEX)
X(AST_GE)
X(AST_GT)
X(AST_ADD)
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 = "+"; }
AST_LE,
AST_EQ,
AST_NE,
+ AST_EQX,
+ AST_NEX,
AST_GE,
AST_GT,
AST_ADD,
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);
}
// 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;
case AST_LE:
case AST_EQ:
case AST_NE:
+ case AST_EQX:
+ case AST_NEX:
case AST_GE:
case AST_GT:
width_hint = -1;
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;
"<=" { return OP_LE; }
">=" { return OP_GE; }
-"===" { return OP_EQ; }
-"!==" { return OP_NE; }
+"===" { return OP_EQX; }
+"!==" { return OP_NEX; }
"~&" { return OP_NAND; }
"~|" { return OP_NOR; }
%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 '+' '-'
$$ = 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);
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;
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);
--- /dev/null
+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