Added $lut support in test_cell, techmap, satgen
authorClifford Wolf <clifford@clifford.at>
Sun, 31 Aug 2014 15:06:36 +0000 (17:06 +0200)
committerClifford Wolf <clifford@clifford.at>
Sun, 31 Aug 2014 15:43:31 +0000 (17:43 +0200)
kernel/rtlil.cc
kernel/satgen.h
passes/tests/test_cell.cc
techlibs/common/techmap.v

index 72eced914e613c2613cc5d495cca44cd203764cb..403bb6d28fcdc990c8c797c588269faa8f22c16c 100644 (file)
@@ -1768,8 +1768,7 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed)
                        type.substr(0, 9) == "$verific$" || type.substr(0, 7) == "$array:" || type.substr(0, 8) == "$extern:")
                return;
 
-       if (type == "$mux" || type == "$pmux")
-       {
+       if (type == "$mux" || type == "$pmux") {
                parameters["\\WIDTH"] = SIZE(connections_["\\Y"]);
                if (type == "$pmux")
                        parameters["\\S_WIDTH"] = SIZE(connections_["\\S"]);
@@ -1777,7 +1776,12 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed)
                return;
        }
 
-       bool signedness_ab = type != "$slice" && type != "$concat";
+       if (type == "$lut") {
+               parameters["\\WIDTH"] = SIZE(connections_["\\A"]);
+               return;
+       }
+
+       bool signedness_ab = !type.in("$slice", "$concat");
 
        if (connections_.count("\\A")) {
                if (signedness_ab) {
index c02900a6c7f34edd7c70eb891d27790608ba452b..5d1c11c9ebc88b89e499709fa8e07e85a278233f 100644 (file)
@@ -841,6 +841,56 @@ struct SatGen
                        return true;
                }
 
+               if (cell->type == "$lut")
+               {
+                       std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep);
+                       std::vector<int> y = importDefSigSpec(cell->getPort("\\Y"), timestep);
+
+                       std::vector<int> lut;
+                       for (auto bit : cell->getParam("\\LUT").bits)
+                               lut.push_back(bit == RTLIL::S1 ? ez->TRUE : ez->FALSE);
+                       while (SIZE(lut) < (1 << SIZE(a)))
+                               lut.push_back(ez->FALSE);
+                       lut.resize(1 << SIZE(a));
+
+                       if (model_undef)
+                       {
+                               std::vector<int> undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep);
+                               std::vector<int> t(lut), u(SIZE(t), ez->FALSE);
+
+                               for (int i = SIZE(a)-1; i >= 0; i--)
+                               {
+                                       std::vector<int> t0(t.begin(), t.begin() + SIZE(t)/2);
+                                       std::vector<int> t1(t.begin() + SIZE(t)/2, t.end());
+
+                                       std::vector<int> u0(u.begin(), u.begin() + SIZE(u)/2);
+                                       std::vector<int> u1(u.begin() + SIZE(u)/2, u.end());
+
+                                       t = ez->vec_ite(a[i], t1, t0);
+                                       u = ez->vec_ite(undef_a[i], ez->vec_or(ez->vec_xor(t0, t1), ez->vec_or(u0, u1)), ez->vec_ite(a[i], u1, u0));
+                               }
+
+                               log_assert(SIZE(t) == 1);
+                               log_assert(SIZE(u) == 1);
+                               undefGating(y, t, u);
+                               ez->assume(ez->vec_eq(importUndefSigSpec(cell->getPort("\\Y"), timestep), u));
+                       }
+                       else
+                       {
+                               std::vector<int> t = lut;
+                               for (int i = SIZE(a)-1; i >= 0; i--)
+                               {
+                                       std::vector<int> t0(t.begin(), t.begin() + SIZE(t)/2);
+                                       std::vector<int> t1(t.begin() + SIZE(t)/2, t.end());
+                                       t = ez->vec_ite(a[i], t1, t0);
+                               }
+
+                               log_assert(SIZE(t) == 1);
+                               ez->assume(ez->vec_eq(y, t));
+                       }
+                       return true;
+               }
+
                if (cell->type == "$slice")
                {
                        RTLIL::SigSpec a = cell->getPort("\\A");
@@ -903,4 +953,3 @@ struct SatGen
 };
 
 #endif
-
index a4b8be0c12e76b55b69e5e00a543e6c0722a2697..4a2af304d0b923a80949c17bfd45f6320c308c58 100644 (file)
@@ -30,20 +30,41 @@ static uint32_t xorshift32(uint32_t limit) {
        return xorshift32_state % limit;
 }
 
-static void create_gold_module(RTLIL::Design *design, std::string cell_type, std::string cell_type_flags)
+static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type, std::string cell_type_flags)
 {
        RTLIL::Module *module = design->addModule("\\gold");
        RTLIL::Cell *cell = module->addCell("\\UUT", cell_type);
+       RTLIL::Wire *wire;
+
+       if (cell_type == "$lut")
+       {
+               int width = 1 + xorshift32(6);
+
+               wire = module->addWire("\\A");
+               wire->width = width;
+               wire->port_input = true;
+               cell->setPort("\\A", wire);
+
+               wire = module->addWire("\\Y");
+               wire->port_output = true;
+               cell->setPort("\\Y", wire);
+
+               RTLIL::SigSpec config;
+               for (int i = 0; i < (1 << width); i++)
+                       config.append(xorshift32(2) ? RTLIL::S1 : RTLIL::S0);
+
+               cell->setParam("\\LUT", config.as_const());
+       }
 
        if (cell_type_flags.find('A') != std::string::npos) {
-               RTLIL::Wire *wire = module->addWire("\\A");
+               wire = module->addWire("\\A");
                wire->width = 1 + xorshift32(8);
                wire->port_input = true;
                cell->setPort("\\A", wire);
        }
 
        if (cell_type_flags.find('B') != std::string::npos) {
-               RTLIL::Wire *wire = module->addWire("\\B");
+               wire = module->addWire("\\B");
                if (cell_type_flags.find('h') != std::string::npos)
                        wire->width = 1 + xorshift32(6);
                else
@@ -67,7 +88,7 @@ static void create_gold_module(RTLIL::Design *design, std::string cell_type, std
        }
 
        if (cell_type_flags.find('Y') != std::string::npos) {
-               RTLIL::Wire *wire = module->addWire("\\Y");
+               wire = module->addWire("\\Y");
                wire->width = 1 + xorshift32(8);
                wire->port_output = true;
                cell->setPort("\\Y", wire);
@@ -188,9 +209,11 @@ struct TestCellPass : public Pass {
                // cell_types["$pmux"] = "A";
                // cell_types["$slice"] = "A";
                // cell_types["$concat"] = "A";
-               // cell_types["$lut"] = "A";
                // cell_types["$assert"] = "A";
 
+               cell_types["$lut"] = "*";
+               // cell_types["$alu"] = "*";
+
                for (; argidx < SIZE(args); argidx++)
                {
                        if (args[argidx].rfind("-", 0) == 0)
index d6b24945694280fa1c8dafb3f87b41b80276ae47..c0645267d609630074747a8c3b22337dde2cd206 100644 (file)
@@ -841,3 +841,20 @@ module \$pmux (A, B, S, Y);
        assign Y = |S ? Y_B : A;
 endmodule
 
+
+// --------------------------------------------------------
+// LUTs
+// --------------------------------------------------------
+
+`ifndef NOLUT
+module \$lut (A, Y);
+       parameter WIDTH = 1;
+       parameter LUT = 0;
+
+       input [WIDTH-1:0] A;
+       output Y;
+
+       assign Y = LUT[A];
+endmodule
+`endif
+