Added support for non-const === and !== (for miter circuits)
authorClifford Wolf <clifford@clifford.at>
Fri, 27 Dec 2013 13:20:15 +0000 (14:20 +0100)
committerClifford Wolf <clifford@clifford.at>
Fri, 27 Dec 2013 13:20:15 +0000 (14:20 +0100)
backends/verilog/verilog_backend.cc
frontends/ast/genrtlil.cc
kernel/celltypes.h
kernel/rtlil.cc
kernel/satgen.h
passes/extract/extract.cc
passes/opt/opt_const.cc
passes/proc/proc_arst.cc
techlibs/common/simlib.v
techlibs/common/stdcells.v

index ff41c2e3c4a97b8ed92491503856bf3e18c31421..d8160c97b1e01cdcd1dd1e2f02984475a1fcbf64 100644 (file)
@@ -506,12 +506,14 @@ bool dump_cell_expr(FILE *f, std::string indent, RTLIL::Cell *cell)
        HANDLE_BINOP("$sshl", "<<<")
        HANDLE_BINOP("$sshr", ">>>")
 
-       HANDLE_BINOP("$lt", "<")
-       HANDLE_BINOP("$le", "<=")
-       HANDLE_BINOP("$eq", "==")
-       HANDLE_BINOP("$ne", "!=")
-       HANDLE_BINOP("$ge", ">=")
-       HANDLE_BINOP("$gt", ">")
+       HANDLE_BINOP("$lt",  "<")
+       HANDLE_BINOP("$le",  "<=")
+       HANDLE_BINOP("$eq",  "==")
+       HANDLE_BINOP("$ne",  "!=")
+       HANDLE_BINOP("$eqx", "===")
+       HANDLE_BINOP("$nex", "!==")
+       HANDLE_BINOP("$ge",  ">=")
+       HANDLE_BINOP("$gt",  ">")
 
        HANDLE_BINOP("$add", "+")
        HANDLE_BINOP("$sub", "-")
index 36ca1432b250dacd95d4a3dd77bb3cd1d3e9b810..1b6fc1d8bccb139afa1b301a1bcf3f3dfab4e740 100644 (file)
@@ -1119,8 +1119,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
        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_EQX: type_name = "$eqx"; }
+       if (0) { case AST_NEX: type_name = "$nex"; }
        if (0) { case AST_GE:  type_name = "$ge"; }
        if (0) { case AST_GT:  type_name = "$gt"; }
                {
index e59f74d6615512774224cfa8cfabee92de867a72..29eb490f8786c05700bd111f1cd0cb75155b39dd 100644 (file)
@@ -78,6 +78,8 @@ struct CellTypes
                cell_types.insert("$le");
                cell_types.insert("$eq");
                cell_types.insert("$ne");
+               cell_types.insert("$eqx");
+               cell_types.insert("$nex");
                cell_types.insert("$ge");
                cell_types.insert("$gt");
                cell_types.insert("$add");
@@ -237,6 +239,8 @@ struct CellTypes
                HANDLE_CELL_TYPE(le)
                HANDLE_CELL_TYPE(eq)
                HANDLE_CELL_TYPE(ne)
+               HANDLE_CELL_TYPE(eqx)
+               HANDLE_CELL_TYPE(nex)
                HANDLE_CELL_TYPE(ge)
                HANDLE_CELL_TYPE(gt)
                HANDLE_CELL_TYPE(add)
index 9dfe196dc027b8253d8b1b1808fd464b1b544404..47dc098a4c665812c258218c54b24267f409f9ab 100644 (file)
@@ -408,7 +408,7 @@ namespace {
                        }
 
                        if (cell->type == "$lt" || cell->type == "$le" || cell->type == "$eq" || cell->type == "$ne" ||
-                                       cell->type == "$ge" || cell->type == "$gt") {
+                                       cell->type == "$eqx" || cell->type == "$nex" || cell->type == "$ge" || cell->type == "$gt") {
                                param("\\A_SIGNED");
                                param("\\B_SIGNED");
                                port("\\A", param("\\A_WIDTH"));
index 35e15aa6cdb567980d60b46ceaa35ba389c6c74a..c0807f550e92c6f7cb31802f6dff844f81d0e4ea 100644 (file)
@@ -451,7 +451,7 @@ struct SatGen
                        return true;
                }
 
-               if (cell->type == "$lt" || cell->type == "$le" || cell->type == "$eq" || cell->type == "$ne" || cell->type == "$ge" || cell->type == "$gt")
+               if (cell->type == "$lt" || cell->type == "$le" || cell->type == "$eq" || cell->type == "$ne" || cell->type == "$eqx" || cell->type == "$nex" || cell->type == "$ge" || cell->type == "$gt")
                {
                        bool is_signed = cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool();
                        std::vector<int> a = importDefSigSpec(cell->connections.at("\\A"), timestep);
@@ -465,9 +465,9 @@ struct SatGen
                                ez->SET(is_signed ? ez->vec_lt_signed(a, b) : ez->vec_lt_unsigned(a, b), yy.at(0));
                        if (cell->type == "$le")
                                ez->SET(is_signed ? ez->vec_le_signed(a, b) : ez->vec_le_unsigned(a, b), yy.at(0));
-                       if (cell->type == "$eq")
+                       if (cell->type == "$eq" || cell->type == "$eqx")
                                ez->SET(ez->vec_eq(a, b), yy.at(0));
-                       if (cell->type == "$ne")
+                       if (cell->type == "$ne" || cell->type == "$nex")
                                ez->SET(ez->vec_ne(a, b), yy.at(0));
                        if (cell->type == "$ge")
                                ez->SET(is_signed ? ez->vec_ge_signed(a, b) : ez->vec_ge_unsigned(a, b), yy.at(0));
@@ -476,7 +476,19 @@ struct SatGen
                        for (size_t i = 1; i < y.size(); i++)
                                ez->SET(ez->FALSE, yy.at(i));
 
-                       if (model_undef && (cell->type == "$eq" || cell->type == "$ne"))
+                       if (model_undef && (cell->type == "$eqx" || cell->type == "$nex"))
+                       {
+                               std::vector<int> undef_a = importUndefSigSpec(cell->connections.at("\\A"), timestep);
+                               std::vector<int> undef_b = importUndefSigSpec(cell->connections.at("\\B"), timestep);
+                               std::vector<int> undef_y = importUndefSigSpec(cell->connections.at("\\Y"), timestep);
+                               yy.at(0) = ez->AND(yy.at(0), ez->vec_eq(undef_a, undef_b));
+
+                               for (size_t i = 0; i < y.size(); i++)
+                                       ez->SET(ez->FALSE, undef_y.at(i));
+
+                               ez->assume(ez->vec_eq(y, yy));
+                       }
+                       else if (model_undef && (cell->type == "$eq" || cell->type == "$ne"))
                        {
                                std::vector<int> undef_a = importUndefSigSpec(cell->connections.at("\\A"), timestep);
                                std::vector<int> undef_b = importUndefSigSpec(cell->connections.at("\\B"), timestep);
index 0c639aeda3dbdd28bf71b07682bdff00b621dc1e..aa21e573afd4253aaebb5f4ebde9cfa1250361a7 100644 (file)
@@ -499,6 +499,8 @@ struct ExtractPass : public Pass {
                        solver.addSwappablePorts("$xnor",      "\\A", "\\B");
                        solver.addSwappablePorts("$eq",        "\\A", "\\B");
                        solver.addSwappablePorts("$ne",        "\\A", "\\B");
+                       solver.addSwappablePorts("$eqx",       "\\A", "\\B");
+                       solver.addSwappablePorts("$nex",       "\\A", "\\B");
                        solver.addSwappablePorts("$add",       "\\A", "\\B");
                        solver.addSwappablePorts("$mul",       "\\A", "\\B");
                        solver.addSwappablePorts("$logic_and", "\\A", "\\B");
index b7b361e95097f0f9e9447548d491da887cbfae71..30d85588cd307692ea4c7f0ab2b5093506492a5f 100644 (file)
@@ -144,7 +144,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 #endif
                }
 
-               if (cell->type == "$eq" || cell->type == "$ne")
+               if (cell->type == "$eq" || cell->type == "$ne" || cell->type == "$eqx" || cell->type == "$nex")
                {
                        RTLIL::SigSpec a = cell->connections["\\A"];
                        RTLIL::SigSpec b = cell->connections["\\B"];
@@ -160,10 +160,12 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons
 
                        assert(a.chunks.size() == b.chunks.size());
                        for (size_t i = 0; i < a.chunks.size(); i++) {
-                               if (a.chunks[i].wire == NULL && a.chunks[i].data.bits[0] > RTLIL::State::S1)
-                                       continue;
-                               if (b.chunks[i].wire == NULL && b.chunks[i].data.bits[0] > RTLIL::State::S1)
-                                       continue;
+                               if (cell->type == "$eq" || cell->type == "$ne") {
+                                       if (a.chunks[i].wire == NULL && a.chunks[i].data.bits[0] > RTLIL::State::S1)
+                                               continue;
+                                       if (b.chunks[i].wire == NULL && b.chunks[i].data.bits[0] > RTLIL::State::S1)
+                                               continue;
+                               }
                                new_a.append(a.chunks[i]);
                                new_b.append(b.chunks[i]);
                        }
index 65dc97bdd2a919518975ee6cd9e85ab681804dff..5719465737e39bfc86d98f678e6c3eeb85c292b9 100644 (file)
@@ -47,7 +47,7 @@ static bool check_signal(RTLIL::Module *mod, RTLIL::SigSpec signal, RTLIL::SigSp
                        polarity = !polarity;
                        return check_signal(mod, cell->connections["\\A"], ref, polarity);
                }
-               if (cell->type == "$eq" && cell->connections["\\Y"] == signal) {
+               if ((cell->type == "$eq" || cell->type == "$eqx") && cell->connections["\\Y"] == signal) {
                        if (cell->connections["\\A"].is_fully_const()) {
                                if (!cell->connections["\\A"].as_bool())
                                        polarity = !polarity;
@@ -59,7 +59,7 @@ static bool check_signal(RTLIL::Module *mod, RTLIL::SigSpec signal, RTLIL::SigSp
                                return check_signal(mod, cell->connections["\\A"], ref, polarity);
                        }
                }
-               if (cell->type == "$ne" && cell->connections["\\Y"] == signal) {
+               if ((cell->type == "$ne" || cell->type == "$nex") && cell->connections["\\Y"] == signal) {
                        if (cell->connections["\\A"].is_fully_const()) {
                                if (cell->connections["\\A"].as_bool())
                                        polarity = !polarity;
index b4440ea8dc8df1f875c848a83529de7c687e3cc3..034244ca62e9fcc76b6df8dcd52ddc89d6b58134 100644 (file)
@@ -376,6 +376,42 @@ endmodule
 
 // --------------------------------------------------------
 
+module \$eqx (A, B, Y);
+
+parameter A_SIGNED = 0;
+parameter B_SIGNED = 0;
+parameter A_WIDTH = 0;
+parameter B_WIDTH = 0;
+parameter Y_WIDTH = 0;
+
+`INPUT_A
+`INPUT_B
+output [Y_WIDTH-1:0] Y;
+
+assign Y = A_BUF.val === B_BUF.val;
+
+endmodule
+
+// --------------------------------------------------------
+
+module \$nex (A, B, Y);
+
+parameter A_SIGNED = 0;
+parameter B_SIGNED = 0;
+parameter A_WIDTH = 0;
+parameter B_WIDTH = 0;
+parameter Y_WIDTH = 0;
+
+`INPUT_A
+`INPUT_B
+output [Y_WIDTH-1:0] Y;
+
+assign Y = A_BUF.val !== B_BUF.val;
+
+endmodule
+
+// --------------------------------------------------------
+
 module \$ge (A, B, Y);
 
 parameter A_SIGNED = 0;
index ef4b96f71ee792526c6edf9a2ef12f88f870c928..c7efa240e935ed6ae2dbf58067f8e9fdcfbe3d09 100644 (file)
@@ -572,6 +572,56 @@ endmodule
 
 // --------------------------------------------------------
 
+module \$eqx (A, B, Y);
+
+parameter A_SIGNED = 0;
+parameter B_SIGNED = 0;
+parameter A_WIDTH = 1;
+parameter B_WIDTH = 1;
+parameter Y_WIDTH = 1;
+
+parameter WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH;
+
+input [A_WIDTH-1:0] A;
+input [B_WIDTH-1:0] B;
+output [Y_WIDTH-1:0] Y;
+
+wire carry, carry_sign;
+wire [WIDTH-1:0] A_buf, B_buf;
+\$pos #(.A_SIGNED(A_SIGNED && B_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf));
+\$pos #(.A_SIGNED(A_SIGNED && B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf));
+
+assign Y = ~|(A_buf ^ B_buf);
+
+endmodule
+
+// --------------------------------------------------------
+
+module \$nex (A, B, Y);
+
+parameter A_SIGNED = 0;
+parameter B_SIGNED = 0;
+parameter A_WIDTH = 1;
+parameter B_WIDTH = 1;
+parameter Y_WIDTH = 1;
+
+parameter WIDTH = A_WIDTH > B_WIDTH ? A_WIDTH : B_WIDTH;
+
+input [A_WIDTH-1:0] A;
+input [B_WIDTH-1:0] B;
+output [Y_WIDTH-1:0] Y;
+
+wire carry, carry_sign;
+wire [WIDTH-1:0] A_buf, B_buf;
+\$pos #(.A_SIGNED(A_SIGNED && B_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(WIDTH)) A_conv (.A(A), .Y(A_buf));
+\$pos #(.A_SIGNED(A_SIGNED && B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(WIDTH)) B_conv (.A(B), .Y(B_buf));
+
+assign Y = |(A_buf ^ B_buf);
+
+endmodule
+
+// --------------------------------------------------------
+
 module \$ge (A, B, Y);
 
 parameter A_SIGNED = 0;