diff options
author | Clifford Wolf <clifford@clifford.at> | 2014-09-08 13:28:23 +0200 |
---|---|---|
committer | Clifford Wolf <clifford@clifford.at> | 2014-09-08 13:31:04 +0200 |
commit | af0c8873bbc13eea10b3d705061b4cf68fe27c17 (patch) | |
tree | a295ce024870762e0388cd9fcd28c458d86fa0d3 /kernel | |
parent | 48b00dcceab8bb046258cd6f0912636a6e5b232c (diff) | |
download | yosys-af0c8873bbc13eea10b3d705061b4cf68fe27c17.tar.gz yosys-af0c8873bbc13eea10b3d705061b4cf68fe27c17.tar.bz2 yosys-af0c8873bbc13eea10b3d705061b4cf68fe27c17.zip |
Added $lcu cell type
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/celltypes.h | 1 | ||||
-rw-r--r-- | kernel/consteval.h | 37 | ||||
-rw-r--r-- | kernel/rtlil.cc | 14 | ||||
-rw-r--r-- | kernel/satgen.h | 32 |
4 files changed, 84 insertions, 0 deletions
diff --git a/kernel/celltypes.h b/kernel/celltypes.h index b42cf4e9a..85c21ef3c 100644 --- a/kernel/celltypes.h +++ b/kernel/celltypes.h @@ -105,6 +105,7 @@ struct CellTypes for (auto type : std::vector<RTLIL::IdString>({"$mux", "$pmux"})) setup_type(type, {"\\A", "\\B", "\\S"}, {"\\Y"}, true); + setup_type("$lcu", {"\\P", "\\G", "\\CI"}, {"\\CO"}, true); setup_type("$alu", {"\\A", "\\B", "\\CI", "\\BI"}, {"\\X", "\\Y", "\\CO"}, true); setup_type("$fa", {"\\A", "\\B", "\\C"}, {"\\X", "\\Y"}, true); diff --git a/kernel/consteval.h b/kernel/consteval.h index 7423f950f..6e507bd51 100644 --- a/kernel/consteval.h +++ b/kernel/consteval.h @@ -86,6 +86,43 @@ struct ConstEval bool eval(RTLIL::Cell *cell, RTLIL::SigSpec &undef) { + if (cell->type == "$lcu") + { + RTLIL::SigSpec sig_p = cell->getPort("\\P"); + RTLIL::SigSpec sig_g = cell->getPort("\\G"); + RTLIL::SigSpec sig_ci = cell->getPort("\\CI"); + RTLIL::SigSpec sig_co = values_map(assign_map(cell->getPort("\\CO"))); + + if (sig_co.is_fully_const()) + return true; + + if (!eval(sig_p, undef, cell)) + return false; + + if (!eval(sig_g, undef, cell)) + return false; + + if (!eval(sig_ci, undef, cell)) + return false; + + if (sig_p.is_fully_def() && sig_g.is_fully_def() && sig_ci.is_fully_def()) + { + RTLIL::Const coval(RTLIL::Sx, SIZE(sig_co)); + bool carry = sig_ci.as_bool(); + + for (int i = 0; i < SIZE(coval); i++) { + carry = (sig_g[i] == RTLIL::S1) || (sig_p[i] == RTLIL::S1 && carry); + coval.bits[i] = carry ? RTLIL::S1 : RTLIL::S0; + } + + set(sig_co, coval); + } + else + set(sig_co, RTLIL::Const(RTLIL::Sx, SIZE(sig_co))); + + return true; + } + RTLIL::SigSpec sig_a, sig_b, sig_s, sig_y; log_assert(cell->hasPort("\\Y")); diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index b5cede8b2..ec4375f2f 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -630,6 +630,15 @@ namespace { return; } + if (cell->type == "$lcu") { + port("\\P", param("\\WIDTH")); + port("\\G", param("\\WIDTH")); + port("\\CI", 1); + port("\\CO", param("\\WIDTH")); + check_expected(); + return; + } + if (cell->type == "$alu") { param_bool("\\A_SIGNED"); param_bool("\\B_SIGNED"); @@ -1808,6 +1817,11 @@ void RTLIL::Cell::fixup_parameters(bool set_a_signed, bool set_b_signed) return; } + if (type == "$lcu") { + parameters["\\WIDTH"] = SIZE(connections_["\\CO"]); + return; + } + bool signedness_ab = !type.in("$slice", "$concat", "$macc"); if (connections_.count("\\A")) { diff --git a/kernel/satgen.h b/kernel/satgen.h index 4aabe4378..91f8ab40d 100644 --- a/kernel/satgen.h +++ b/kernel/satgen.h @@ -1012,6 +1012,38 @@ struct SatGen return true; } + if (cell->type == "$lcu") + { + std::vector<int> p = importDefSigSpec(cell->getPort("\\P"), timestep); + std::vector<int> g = importDefSigSpec(cell->getPort("\\G"), timestep); + std::vector<int> ci = importDefSigSpec(cell->getPort("\\CI"), timestep); + std::vector<int> co = importDefSigSpec(cell->getPort("\\CO"), timestep); + + std::vector<int> yy = model_undef ? ez->vec_var(co.size()) : co; + + for (int i = 0; i < SIZE(co); i++) + ez->SET(yy[i], ez->OR(g[i], ez->AND(p[i], i ? yy[i-1] : ci[0]))); + + if (model_undef) + { + std::vector<int> undef_p = importUndefSigSpec(cell->getPort("\\P"), timestep); + std::vector<int> undef_g = importUndefSigSpec(cell->getPort("\\G"), timestep); + std::vector<int> undef_ci = importUndefSigSpec(cell->getPort("\\CI"), timestep); + std::vector<int> undef_co = importUndefSigSpec(cell->getPort("\\CO"), timestep); + + int undef_any_p = ez->expression(ezSAT::OpOr, undef_p); + int undef_any_g = ez->expression(ezSAT::OpOr, undef_g); + int undef_any_ci = ez->expression(ezSAT::OpOr, undef_ci); + int undef_co_bit = ez->OR(undef_any_p, undef_any_g, undef_any_ci); + + std::vector<int> undef_co_bits(undef_co.size(), undef_co_bit); + ez->assume(ez->vec_eq(undef_co_bits, undef_co)); + + undefGating(co, yy, undef_co); + } + return true; + } + if (cell->type == "$alu") { std::vector<int> a = importDefSigSpec(cell->getPort("\\A"), timestep); |