diff options
author | Clifford Wolf <clifford@clifford.at> | 2014-08-16 18:18:30 +0200 |
---|---|---|
committer | Clifford Wolf <clifford@clifford.at> | 2014-08-16 18:29:39 +0200 |
commit | 47c2637a961839f1eb1a0386f7e54d94be50bc10 (patch) | |
tree | 2db3bfbabf1ad7ca21176c2639b565720655fb8b /kernel | |
parent | 56a30cf42c6a40f265a67df6e2c5fa74657fbf5b (diff) | |
download | yosys-47c2637a961839f1eb1a0386f7e54d94be50bc10.tar.gz yosys-47c2637a961839f1eb1a0386f7e54d94be50bc10.tar.bz2 yosys-47c2637a961839f1eb1a0386f7e54d94be50bc10.zip |
Added additional gate types: $_NAND_ $_NOR_ $_XNOR_ $_AOI3_ $_OAI3_ $_AOI4_ $_OAI4_
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/celltypes.h | 49 | ||||
-rw-r--r-- | kernel/consteval.h | 17 | ||||
-rw-r--r-- | kernel/rtlil.cc | 17 | ||||
-rw-r--r-- | kernel/satgen.h | 88 |
4 files changed, 152 insertions, 19 deletions
diff --git a/kernel/celltypes.h b/kernel/celltypes.h index ad5eae2e8..8c2e9a48e 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -131,9 +131,16 @@ struct CellTypes { setup_type("$_NOT_", {"\\A"}, {"\\Y"}, true); setup_type("$_AND_", {"\\A", "\\B"}, {"\\Y"}, true); + setup_type("$_NAND_", {"\\A", "\\B"}, {"\\Y"}, true); setup_type("$_OR_", {"\\A", "\\B"}, {"\\Y"}, true); + setup_type("$_NOR_", {"\\A", "\\B"}, {"\\Y"}, true); setup_type("$_XOR_", {"\\A", "\\B"}, {"\\Y"}, true); + setup_type("$_XNOR_", {"\\A", "\\B"}, {"\\Y"}, true); setup_type("$_MUX_", {"\\A", "\\B", "\\S"}, {"\\Y"}, true); + setup_type("$_AOI3_", {"\\A", "\\B", "\\C"}, {"\\Y"}, true); + setup_type("$_OAI3_", {"\\A", "\\B", "\\C"}, {"\\Y"}, true); + setup_type("$_AOI4_", {"\\A", "\\B", "\\C", "\\D"}, {"\\Y"}, true); + setup_type("$_OAI4_", {"\\A", "\\B", "\\C", "\\D"}, {"\\Y"}, true); } void setup_stdcells_mem() @@ -194,6 +201,14 @@ struct CellTypes return it != cell_types.end() && it->second.is_evaluable; } + static RTLIL::Const eval_not(RTLIL::Const v) + { + for (auto &bit : v.bits) + if (bit == RTLIL::S0) bit = RTLIL::S1; + else if (bit == RTLIL::S1) bit = RTLIL::S0; + return v; + } + static RTLIL::Const eval(RTLIL::IdString type, const RTLIL::Const &arg1, const RTLIL::Const &arg2, bool signed1, bool signed2, int result_len) { if (type == "$sshr" && !signed1) @@ -247,13 +262,19 @@ struct CellTypes #undef HANDLE_CELL_TYPE if (type == "$_NOT_") - return const_not(arg1, arg2, false, false, 1); + return eval_not(arg1); if (type == "$_AND_") return const_and(arg1, arg2, false, false, 1); + if (type == "$_NAND_") + return eval_not(const_and(arg1, arg2, false, false, 1)); if (type == "$_OR_") return const_or(arg1, arg2, false, false, 1); + if (type == "$_NOR_") + return eval_not(const_and(arg1, arg2, false, false, 1)); if (type == "$_XOR_") return const_xor(arg1, arg2, false, false, 1); + if (type == "$_XNOR_") + return const_xnor(arg1, arg2, false, false, 1); log_abort(); } @@ -280,21 +301,37 @@ struct CellTypes return eval(cell->type, arg1, arg2, signed_a, signed_b, result_len); } - static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &sel) + static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3) { - if (cell->type == "$mux" || cell->type == "$pmux" || cell->type == "$_MUX_") { + if (cell->type.in("$mux", "$pmux", "$_MUX_")) { RTLIL::Const ret = arg1; - for (size_t i = 0; i < sel.bits.size(); i++) - if (sel.bits[i] == RTLIL::State::S1) { + for (size_t i = 0; i < arg3.bits.size(); i++) + if (arg3.bits[i] == RTLIL::State::S1) { std::vector<RTLIL::State> bits(arg2.bits.begin() + i*arg1.bits.size(), arg2.bits.begin() + (i+1)*arg1.bits.size()); ret = RTLIL::Const(bits); } return ret; } - log_assert(sel.bits.size() == 0); + if (cell->type == "$_AOI3_") + return eval_not(const_or(const_and(arg1, arg2, false, false, 1), arg3, false, false, 1)); + if (cell->type == "$_OAI3_") + return eval_not(const_and(const_or(arg1, arg2, false, false, 1), arg3, false, false, 1)); + + log_assert(arg3.bits.size() == 0); return eval(cell, arg1, arg2); } + + static RTLIL::Const eval(RTLIL::Cell *cell, const RTLIL::Const &arg1, const RTLIL::Const &arg2, const RTLIL::Const &arg3, const RTLIL::Const &arg4) + { + if (cell->type == "$_AOI4_") + return eval_not(const_or(const_and(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1)); + if (cell->type == "$_OAI4_") + return eval_not(const_and(const_or(arg1, arg2, false, false, 1), const_and(arg3, arg4, false, false, 1), false, false, 1)); + + log_assert(arg4.bits.size() == 0); + return eval(cell, arg1, arg2, arg3); + } }; #endif diff --git a/kernel/consteval.h b/kernel/consteval.h index dbe13ea7e..d42c2b0f1 100644 --- a/kernel/consteval.h +++ b/kernel/consteval.h @@ -156,11 +156,26 @@ struct ConstEval } else { + RTLIL::SigSpec sig_c, sig_d; + + if (cell->type.in("$_AOI3_", "$_OAI3_", "$_AOI4_", "$_OAI4_")) { + if (cell->hasPort("\\C")) + sig_c = cell->getPort("\\C"); + if (cell->hasPort("\\D")) + sig_d = cell->getPort("\\D"); + } + if (sig_a.size() > 0 && !eval(sig_a, undef, cell)) return false; if (sig_b.size() > 0 && !eval(sig_b, undef, cell)) return false; - set(sig_y, CellTypes::eval(cell, sig_a.as_const(), sig_b.as_const())); + if (sig_c.size() > 0 && !eval(sig_c, undef, cell)) + return false; + if (sig_d.size() > 0 && !eval(sig_d, undef, cell)) + return false; + + set(sig_y, CellTypes::eval(cell, sig_a.as_const(), sig_b.as_const(), + sig_c.as_const(), sig_d.as_const())); } return true; diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index d118b6257..3df7d83c4 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -758,11 +758,18 @@ namespace { return; } - if (cell->type == "$_NOT_") { check_gate("AY"); return; } - if (cell->type == "$_AND_") { check_gate("ABY"); return; } - if (cell->type == "$_OR_") { check_gate("ABY"); return; } - if (cell->type == "$_XOR_") { check_gate("ABY"); return; } - if (cell->type == "$_MUX_") { check_gate("ABSY"); return; } + if (cell->type == "$_NOT_") { check_gate("AY"); return; } + if (cell->type == "$_AND_") { check_gate("ABY"); return; } + if (cell->type == "$_NAND_") { check_gate("ABY"); return; } + if (cell->type == "$_OR_") { check_gate("ABY"); return; } + if (cell->type == "$_NOR_") { check_gate("ABY"); return; } + if (cell->type == "$_XOR_") { check_gate("ABY"); return; } + if (cell->type == "$_XNOR_") { check_gate("ABY"); return; } + if (cell->type == "$_MUX_") { check_gate("ABSY"); return; } + if (cell->type == "$_AOI3_") { check_gate("ABCY"); return; } + if (cell->type == "$_OAI3_") { check_gate("ABCY"); return; } + if (cell->type == "$_AOI4_") { check_gate("ABCDY"); return; } + if (cell->type == "$_OAI4_") { check_gate("ABCDY"); return; } if (cell->type == "$_SR_NN_") { check_gate("SRQ"); return; } if (cell->type == "$_SR_NP_") { check_gate("SRQ"); return; } diff --git a/kernel/satgen.h b/kernel/satgen.h index b57edd9fe..c02900a6c 100644 --- a/kernel/satgen.h +++ b/kernel/satgen.h @@ -175,6 +175,11 @@ struct SatGen } } + void undefGating(int y, int yy, int undef) + { + ez->assume(ez->OR(undef, ez->IFF(y, yy))); + } + bool importCell(RTLIL::Cell *cell, int timestep = -1) { bool arith_undef_handled = false; @@ -211,9 +216,8 @@ struct SatGen arith_undef_handled = true; } - if (cell->type == "$_AND_" || cell->type == "$_OR_" || cell->type == "$_XOR_" || - cell->type == "$and" || cell->type == "$or" || cell->type == "$xor" || cell->type == "$xnor" || - cell->type == "$add" || cell->type == "$sub") + if (cell->type.in("$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_", + "$and", "$or", "$xor", "$xnor", "$add", "$sub")) { std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep); std::vector<int> b = importDefSigSpec(cell->getPort("\\B"), timestep); @@ -224,11 +228,15 @@ struct SatGen if (cell->type == "$and" || cell->type == "$_AND_") ez->assume(ez->vec_eq(ez->vec_and(a, b), yy)); + if (cell->type == "$_NAND_") + ez->assume(ez->vec_eq(ez->vec_not(ez->vec_and(a, b)), yy)); if (cell->type == "$or" || cell->type == "$_OR_") ez->assume(ez->vec_eq(ez->vec_or(a, b), yy)); + if (cell->type == "$_NOR_") + ez->assume(ez->vec_eq(ez->vec_not(ez->vec_or(a, b)), yy)); if (cell->type == "$xor" || cell->type == "$_XOR_") ez->assume(ez->vec_eq(ez->vec_xor(a, b), yy)); - if (cell->type == "$xnor") + if (cell->type == "$xnor" || cell->type == "$_XNOR_") ez->assume(ez->vec_eq(ez->vec_not(ez->vec_xor(a, b)), yy)); if (cell->type == "$add") ez->assume(ez->vec_eq(ez->vec_add(a, b), yy)); @@ -242,19 +250,19 @@ struct SatGen std::vector<int> undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep); extendSignalWidth(undef_a, undef_b, undef_y, cell, false); - if (cell->type == "$and" || cell->type == "$_AND_") { + if (cell->type.in("$and", "$_AND_", "$_NAND_")) { std::vector<int> a0 = ez->vec_and(ez->vec_not(a), ez->vec_not(undef_a)); std::vector<int> b0 = ez->vec_and(ez->vec_not(b), ez->vec_not(undef_b)); std::vector<int> yX = ez->vec_and(ez->vec_or(undef_a, undef_b), ez->vec_not(ez->vec_or(a0, b0))); ez->assume(ez->vec_eq(yX, undef_y)); } - else if (cell->type == "$or" || cell->type == "$_OR_") { + else if (cell->type.in("$or", "$_OR_", "$_NOR_")) { std::vector<int> a1 = ez->vec_and(a, ez->vec_not(undef_a)); std::vector<int> b1 = ez->vec_and(b, ez->vec_not(undef_b)); std::vector<int> yX = ez->vec_and(ez->vec_or(undef_a, undef_b), ez->vec_not(ez->vec_or(a1, b1))); ez->assume(ez->vec_eq(yX, undef_y)); } - else if (cell->type == "$xor" || cell->type == "$_XOR_" || cell->type == "$xnor") { + else if (cell->type.in("$xor", "$xnor", "$_XOR_", "$_XNOR_")) { std::vector<int> yX = ez->vec_or(undef_a, undef_b); ez->assume(ez->vec_eq(yX, undef_y)); } @@ -271,6 +279,72 @@ struct SatGen return true; } + if (cell->type.in("$_AOI3_", "$_OAI3_", "$_AOI4_", "$_OAI4_")) + { + bool aoi_mode = cell->type.in("$_AOI3_", "$_AOI4_"); + bool three_mode = cell->type.in("$_AOI3_", "$_OAI3_"); + + int a = importDefSigSpec(cell->getPort("\\A"), timestep).at(0); + int b = importDefSigSpec(cell->getPort("\\B"), timestep).at(0); + int c = importDefSigSpec(cell->getPort("\\C"), timestep).at(0); + int d = three_mode ? (aoi_mode ? ez->TRUE : ez->FALSE) : importDefSigSpec(cell->getPort("\\D"), timestep).at(0); + int y = importDefSigSpec(cell->getPort("\\Y"), timestep).at(0); + int yy = model_undef ? ez->literal() : y; + + if (cell->type.in("$_AOI3_", "$_AOI4_")) + ez->assume(ez->IFF(ez->NOT(ez->OR(ez->AND(a, b), ez->AND(c, d))), yy)); + else + ez->assume(ez->IFF(ez->NOT(ez->AND(ez->OR(a, b), ez->OR(c, d))), yy)); + + if (model_undef) + { + int undef_a = importUndefSigSpec(cell->getPort("\\A"), timestep).at(0); + int undef_b = importUndefSigSpec(cell->getPort("\\B"), timestep).at(0); + int undef_c = importUndefSigSpec(cell->getPort("\\C"), timestep).at(0); + int undef_d = three_mode ? ez->FALSE : importUndefSigSpec(cell->getPort("\\D"), timestep).at(0); + int undef_y = importUndefSigSpec(cell->getPort("\\Y"), timestep).at(0); + + if (aoi_mode) + { + int a0 = ez->AND(ez->NOT(a), ez->NOT(undef_a)); + int b0 = ez->AND(ez->NOT(b), ez->NOT(undef_b)); + int c0 = ez->AND(ez->NOT(c), ez->NOT(undef_c)); + int d0 = ez->AND(ez->NOT(d), ez->NOT(undef_d)); + + int ab = ez->AND(a, b), cd = ez->AND(c, d); + int undef_ab = ez->AND(ez->OR(undef_a, undef_b), ez->NOT(ez->OR(a0, b0))); + int undef_cd = ez->AND(ez->OR(undef_c, undef_d), ez->NOT(ez->OR(c0, d0))); + + int ab1 = ez->AND(ab, ez->NOT(undef_ab)); + int cd1 = ez->AND(cd, ez->NOT(undef_cd)); + int yX = ez->AND(ez->OR(undef_ab, undef_cd), ez->NOT(ez->OR(ab1, cd1))); + + ez->assume(ez->IFF(yX, undef_y)); + } + else + { + int a1 = ez->AND(a, ez->NOT(undef_a)); + int b1 = ez->AND(b, ez->NOT(undef_b)); + int c1 = ez->AND(c, ez->NOT(undef_c)); + int d1 = ez->AND(d, ez->NOT(undef_d)); + + int ab = ez->OR(a, b), cd = ez->OR(c, d); + int undef_ab = ez->AND(ez->OR(undef_a, undef_b), ez->NOT(ez->OR(a1, b1))); + int undef_cd = ez->AND(ez->OR(undef_c, undef_d), ez->NOT(ez->OR(c1, d1))); + + int ab0 = ez->AND(ez->NOT(ab), ez->NOT(undef_ab)); + int cd0 = ez->AND(ez->NOT(cd), ez->NOT(undef_cd)); + int yX = ez->AND(ez->OR(undef_ab, undef_cd), ez->NOT(ez->OR(ab0, cd0))); + + ez->assume(ez->IFF(yX, undef_y)); + } + + undefGating(y, yy, undef_y); + } + + return true; + } + if (cell->type == "$_NOT_" || cell->type == "$not") { std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep); |