From d46bac330520f91ee5bf8027abe98a8f9389f696 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 8 Sep 2014 12:15:39 +0200 Subject: Added "$fa" cell type --- kernel/celltypes.h | 1 + kernel/consteval.h | 25 +++++++++++++++++++++++++ kernel/rtlil.cc | 15 +++++++++++++++ kernel/satgen.h | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+) (limited to 'kernel') diff --git a/kernel/celltypes.h b/kernel/celltypes.h index 74e9f1fd..b42cf4e9 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 f995c9cc..7423f950 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 97a2946a..b5cede8b 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 3429f823..4aabe437 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); -- cgit v1.2.3