summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2014-08-31 17:06:36 +0200
committerClifford Wolf <clifford@clifford.at>2014-08-31 17:43:31 +0200
commit8649b57b6f4c3a4322acaf73f5c02d5119629c1e (patch)
treeb32def8c7c0e44d3abf2890165431c24292cdf8b
parent2a1b08aeb34b7d5f2df1a43c9ef1f99abacb9cae (diff)
Added $lut support in test_cell, techmap, satgen
-rw-r--r--kernel/rtlil.cc10
-rw-r--r--kernel/satgen.h51
-rw-r--r--passes/tests/test_cell.cc33
-rw-r--r--techlibs/common/techmap.v17
4 files changed, 102 insertions, 9 deletions
diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc
index 72eced91..403bb6d2 100644
--- a/kernel/rtlil.cc
+++ b/kernel/rtlil.cc
@@ -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) {
diff --git a/kernel/satgen.h b/kernel/satgen.h
index c02900a6..5d1c11c9 100644
--- a/kernel/satgen.h
+++ b/kernel/satgen.h
@@ -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
-
diff --git a/passes/tests/test_cell.cc b/passes/tests/test_cell.cc
index a4b8be0c..4a2af304 100644
--- a/passes/tests/test_cell.cc
+++ b/passes/tests/test_cell.cc
@@ -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)
diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v
index d6b24945..c0645267 100644
--- a/techlibs/common/techmap.v
+++ b/techlibs/common/techmap.v
@@ -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
+