From d46bac330520f91ee5bf8027abe98a8f9389f696 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 8 Sep 2014 12:15:39 +0200 Subject: [PATCH] Added "$fa" cell type --- kernel/celltypes.h | 1 + kernel/consteval.h | 25 ++++++++++++++++++++ kernel/rtlil.cc | 15 ++++++++++++ kernel/satgen.h | 49 +++++++++++++++++++++++++++++++++++++++ passes/techmap/maccmap.cc | 22 +++++++++++++----- passes/tests/test_cell.cc | 31 +++++++++++++++++++++++++ techlibs/common/simlib.v | 16 +++++++++++++ techlibs/common/techmap.v | 12 ++++++++++ 8 files changed, 165 insertions(+), 6 deletions(-) diff --git a/kernel/celltypes.h b/kernel/celltypes.h index 74e9f1fd5..b42cf4e9a 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -106,6 +106,7 @@ struct CellTypes setup_type(type, {"\\A", "\\B", "\\S"}, {"\\Y"}, true); setup_type("$alu", {"\\A", "\\B", "\\CI", "\\BI"}, {"\\X", "\\Y", "\\CO"}, true); + setup_type("$fa", {"\\A", "\\B", "\\C"}, {"\\X", "\\Y"}, true); setup_type("$assert", {"\\A", "\\EN"}, std::set(), true); } diff --git a/kernel/consteval.h b/kernel/consteval.h index f995c9cc2..7423f950f 100644 --- a/kernel/consteval.h +++ b/kernel/consteval.h @@ -155,6 +155,31 @@ struct ConstEval else set(sig_y, y_values.front()); } + else if (cell->type == "$fa") + { + RTLIL::SigSpec sig_c = cell->getPort("\\C"); + RTLIL::SigSpec sig_x = cell->getPort("\\X"); + int width = SIZE(sig_c); + + if (!eval(sig_a, undef, cell)) + return false; + + if (!eval(sig_b, undef, cell)) + return false; + + if (!eval(sig_c, undef, cell)) + return false; + + RTLIL::Const t1 = const_xor(sig_a.as_const(), sig_b.as_const(), false, false, width); + RTLIL::Const val_y = const_xor(t1, sig_c.as_const(), false, false, width); + + RTLIL::Const t2 = const_and(sig_a.as_const(), sig_b.as_const(), false, false, width); + RTLIL::Const t3 = const_and(sig_c.as_const(), t1, false, false, width); + RTLIL::Const val_x = const_or(t2, t3, false, false, width); + + set(sig_y, val_y); + set(sig_x, val_x); + } else if (cell->type == "$alu") { bool signed_a = cell->parameters.count("\\A_SIGNED") > 0 && cell->parameters["\\A_SIGNED"].as_bool(); diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 97a2946a6..b5cede8b2 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -620,6 +620,16 @@ namespace { return; } + if (cell->type == "$fa") { + port("\\A", param("\\WIDTH")); + port("\\B", param("\\WIDTH")); + port("\\C", param("\\WIDTH")); + port("\\X", param("\\WIDTH")); + port("\\Y", param("\\WIDTH")); + check_expected(); + return; + } + if (cell->type == "$alu") { param_bool("\\A_SIGNED"); param_bool("\\B_SIGNED"); @@ -1793,6 +1803,11 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed) return; } + if (type == "$fa") { + parameters["\\WIDTH"] = SIZE(connections_["\\Y"]); + return; + } + bool signedness_ab = !type.in("$slice", "$concat", "$macc"); if (connections_.count("\\A")) { diff --git a/kernel/satgen.h b/kernel/satgen.h index 3429f8239..4aabe4378 100644 --- a/kernel/satgen.h +++ b/kernel/satgen.h @@ -963,6 +963,55 @@ struct SatGen return true; } + if (cell->type == "$fa") + { + std::vector a = importDefSigSpec(cell->getPort("\\A"), timestep); + std::vector b = importDefSigSpec(cell->getPort("\\B"), timestep); + std::vector c = importDefSigSpec(cell->getPort("\\C"), timestep); + std::vector y = importDefSigSpec(cell->getPort("\\Y"), timestep); + std::vector x = importDefSigSpec(cell->getPort("\\X"), timestep); + + std::vector yy = model_undef ? ez->vec_var(y.size()) : y; + std::vector xx = model_undef ? ez->vec_var(x.size()) : x; + + std::vector t1 = ez->vec_xor(a, b); + ez->assume(ez->vec_eq(yy, ez->vec_xor(t1, c))); + + std::vector t2 = ez->vec_and(a, b); + std::vector t3 = ez->vec_and(c, t1); + ez->assume(ez->vec_eq(xx, ez->vec_or(t2, t3))); + + if (model_undef) + { + std::vector undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep); + std::vector undef_b = importUndefSigSpec(cell->getPort("\\B"), timestep); + std::vector undef_c = importUndefSigSpec(cell->getPort("\\C"), timestep); + + std::vector undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep); + std::vector undef_x = importUndefSigSpec(cell->getPort("\\X"), timestep); + + ez->assume(ez->vec_eq(undef_y, ez->vec_or(ez->vec_or(undef_a, undef_b), undef_c))); + + std::vector undef_t1 = ez->vec_or(undef_a, undef_b); + + std::vector a0 = ez->vec_and(ez->vec_not(a), ez->vec_not(undef_a)); + std::vector b0 = ez->vec_and(ez->vec_not(b), ez->vec_not(undef_b)); + std::vector undef_t2 = ez->vec_and(ez->vec_or(undef_a, undef_b), ez->vec_not(ez->vec_or(a0, b0))); + + std::vector c0 = ez->vec_and(ez->vec_not(c), ez->vec_not(undef_c)); + std::vector t10 = ez->vec_and(ez->vec_not(t1), ez->vec_not(undef_t1)); + std::vector undef_t3 = ez->vec_and(ez->vec_or(undef_c, undef_t1), ez->vec_not(ez->vec_or(c0, t10))); + + std::vector t21 = ez->vec_and(t2, ez->vec_not(undef_t2)); + std::vector t31 = ez->vec_and(t3, ez->vec_not(undef_t3)); + ez->assume(ez->vec_eq(undef_x, ez->vec_and(ez->vec_or(undef_t2, undef_t3), ez->vec_not(ez->vec_or(t21, t31))))); + + undefGating(y, yy, undef_y); + undefGating(x, xx, undef_x); + } + return true; + } + if (cell->type == "$alu") { std::vector a = importDefSigSpec(cell->getPort("\\A"), timestep); diff --git a/passes/techmap/maccmap.cc b/passes/techmap/maccmap.cc index a9c223fa8..c2dc9aa8a 100644 --- a/passes/techmap/maccmap.cc +++ b/passes/techmap/maccmap.cc @@ -106,12 +106,20 @@ struct MaccmapWorker in2 = in2.extract(start_index, stop_index-start_index); in3 = in3.extract(start_index, stop_index-start_index); - RTLIL::SigSpec t1 = module->Xor(NEW_ID, in1, in2); - out1 = {out_zeros_msb, module->Xor(NEW_ID, t1, in3), out_zeros_lsb}; - - RTLIL::SigSpec t2 = module->And(NEW_ID, in1, in2); - RTLIL::SigSpec t3 = module->And(NEW_ID, in3, t1); - out2 = {out_zeros_msb, module->Or(NEW_ID, t2, t3), out_zeros_lsb}; + int width = SIZE(in1); + RTLIL::Wire *w1 = module->addWire(NEW_ID, width); + RTLIL::Wire *w2 = module->addWire(NEW_ID, width); + + RTLIL::Cell *cell = module->addCell(NEW_ID, "$fa"); + cell->setParam("\\WIDTH", width); + cell->setPort("\\A", in1); + cell->setPort("\\B", in2); + cell->setPort("\\C", in3); + cell->setPort("\\Y", w1); + cell->setPort("\\X", w2); + + out1 = {out_zeros_msb, w1, out_zeros_lsb}; + out2 = {out_zeros_msb, w2, out_zeros_lsb}; } } @@ -198,6 +206,8 @@ struct MaccmapWorker summands.swap(new_summands); } + log_assert(tree_sum_bits.empty()); + return module->Add(NEW_ID, summands.front(), summands.back()); } }; diff --git a/passes/tests/test_cell.cc b/passes/tests/test_cell.cc index 310c3bdfe..72fb74d3a 100644 --- a/passes/tests/test_cell.cc +++ b/passes/tests/test_cell.cc @@ -39,6 +39,36 @@ static void create_gold_module(RTLIL::Design *design, RTLIL::IdString cell_type, RTLIL::Cell *cell = module->addCell("\\UUT", cell_type); RTLIL::Wire *wire; + if (cell_type == "$fa") + { + int width = 1 + xorshift32(8); + + wire = module->addWire("\\A"); + wire->width = width; + wire->port_input = true; + cell->setPort("\\A", wire); + + wire = module->addWire("\\B"); + wire->width = width; + wire->port_input = true; + cell->setPort("\\B", wire); + + wire = module->addWire("\\C"); + wire->width = width; + wire->port_input = true; + cell->setPort("\\C", wire); + + wire = module->addWire("\\X"); + wire->width = width; + wire->port_output = true; + cell->setPort("\\X", wire); + + wire = module->addWire("\\Y"); + wire->width = width; + wire->port_output = true; + cell->setPort("\\Y", wire); + } + if (cell_type == "$macc") { Macc macc; @@ -603,6 +633,7 @@ struct TestCellPass : public Pass { cell_types["$lut"] = "*"; cell_types["$alu"] = "ABSY"; cell_types["$macc"] = "*"; + cell_types["$fa"] = "*"; for (; argidx < SIZE(args); argidx++) { diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index 465efc0a7..c170945ea 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -443,6 +443,22 @@ endmodule // -------------------------------------------------------- +module \$fa (A, B, C, X, Y); + +parameter WIDTH = 1; + +input [WIDTH-1:0] A, B, C; +output [WIDTH-1:0] X, Y; + +wire [WIDTH-1:0] t1, t2, t3; + +assign t1 = A ^ B, t2 = A & B, t3 = C & t1; +assign Y = t1 ^ C, X = t2 | t3; + +endmodule + +// -------------------------------------------------------- + module \$alu (A, B, CI, BI, X, Y, CO); parameter A_SIGNED = 0; diff --git a/techlibs/common/techmap.v b/techlibs/common/techmap.v index dc52ca5fa..050746376 100644 --- a/techlibs/common/techmap.v +++ b/techlibs/common/techmap.v @@ -246,6 +246,18 @@ endmodule // ALU Infrastructure // -------------------------------------------------------- +module \$fa (A, B, C, X, Y); + parameter WIDTH = 1; + + input [WIDTH-1:0] A, B, C; + output [WIDTH-1:0] X, Y; + + wire [WIDTH-1:0] t1, t2, t3; + + assign t1 = A ^ B, t2 = A & B, t3 = C & t1; + assign Y = t1 ^ C, X = t2 | t3; +endmodule + module \$__alu_ripple (A, B, CI, X, Y, CO); parameter WIDTH = 1; -- 2.30.2