From 8649b57b6f4c3a4322acaf73f5c02d5119629c1e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 31 Aug 2014 17:06:36 +0200 Subject: [PATCH] Added $lut support in test_cell, techmap, satgen --- kernel/rtlil.cc | 10 +++++--- kernel/satgen.h | 51 ++++++++++++++++++++++++++++++++++++++- passes/tests/test_cell.cc | 33 +++++++++++++++++++++---- techlibs/common/techmap.v | 17 +++++++++++++ 4 files changed, 102 insertions(+), 9 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 72eced914..403bb6d28 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 c02900a6c..5d1c11c9e 100644 --- a/kernel/satgen.h +++ b/kernel/satgen.h @@ -841,6 +841,56 @@ struct SatGen return true; } + if (cell->type == "$lut") + { + std::vector a = importDefSigSpec(cell->getPort("\\A"), timestep); + std::vector y = importDefSigSpec(cell->getPort("\\Y"), timestep); + + std::vector 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 undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep); + std::vector t(lut), u(SIZE(t), ez->FALSE); + + for (int i = SIZE(a)-1; i >= 0; i--) + { + std::vector t0(t.begin(), t.begin() + SIZE(t)/2); + std::vector t1(t.begin() + SIZE(t)/2, t.end()); + + std::vector u0(u.begin(), u.begin() + SIZE(u)/2); + std::vector 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 t = lut; + for (int i = SIZE(a)-1; i >= 0; i--) + { + std::vector t0(t.begin(), t.begin() + SIZE(t)/2); + std::vector 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 a4b8be0c1..4a2af304d 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 d6b249456..c0645267d 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 + -- 2.30.2