diff options
Diffstat (limited to 'backends/cxxrtl')
-rw-r--r-- | backends/cxxrtl/cxxrtl.h | 36 | ||||
-rw-r--r-- | backends/cxxrtl/cxxrtl_backend.cc | 18 |
2 files changed, 53 insertions, 1 deletions
diff --git a/backends/cxxrtl/cxxrtl.h b/backends/cxxrtl/cxxrtl.h index 3e1357498..b4ffa87cd 100644 --- a/backends/cxxrtl/cxxrtl.h +++ b/backends/cxxrtl/cxxrtl.h @@ -457,6 +457,42 @@ struct value : public expr_base<value<Bits>> { return shr<AmountBits, /*Signed=*/true>(amount); } + template<size_t ResultBits, size_t SelBits> + value<ResultBits> bmux(const value<SelBits> &sel) const { + static_assert(ResultBits << SelBits == Bits, "invalid sizes used in bmux()"); + size_t amount = sel.data[0] * ResultBits; + size_t shift_chunks = amount / chunk::bits; + size_t shift_bits = amount % chunk::bits; + value<ResultBits> result; + chunk::type carry = 0; + if (ResultBits % chunk::bits + shift_bits > chunk::bits) + carry = data[result.chunks + shift_chunks] << (chunk::bits - shift_bits); + for (size_t n = 0; n < result.chunks; n++) { + result.data[result.chunks - 1 - n] = carry | (data[result.chunks + shift_chunks - 1 - n] >> shift_bits); + carry = (shift_bits == 0) ? 0 + : data[result.chunks + shift_chunks - 1 - n] << (chunk::bits - shift_bits); + } + return result; + } + + template<size_t ResultBits, size_t SelBits> + value<ResultBits> demux(const value<SelBits> &sel) const { + static_assert(Bits << SelBits == ResultBits, "invalid sizes used in demux()"); + size_t amount = sel.data[0] * Bits; + size_t shift_chunks = amount / chunk::bits; + size_t shift_bits = amount % chunk::bits; + value<ResultBits> result; + chunk::type carry = 0; + for (size_t n = 0; n < chunks; n++) { + result.data[shift_chunks + n] = (data[n] << shift_bits) | carry; + carry = (shift_bits == 0) ? 0 + : data[n] >> (chunk::bits - shift_bits); + } + if (Bits % chunk::bits + shift_bits > chunk::bits) + result.data[shift_chunks + chunks] = carry; + return result; + } + size_t ctpop() const { size_t count = 0; for (size_t n = 0; n < chunks; n++) { diff --git a/backends/cxxrtl/cxxrtl_backend.cc b/backends/cxxrtl/cxxrtl_backend.cc index 7a336f8c1..404755b1e 100644 --- a/backends/cxxrtl/cxxrtl_backend.cc +++ b/backends/cxxrtl/cxxrtl_backend.cc @@ -198,7 +198,7 @@ bool is_extending_cell(RTLIL::IdString type) bool is_inlinable_cell(RTLIL::IdString type) { return is_unary_cell(type) || is_binary_cell(type) || type.in( - ID($mux), ID($concat), ID($slice), ID($pmux)); + ID($mux), ID($concat), ID($slice), ID($pmux), ID($bmux), ID($demux)); } bool is_ff_cell(RTLIL::IdString type) @@ -1154,6 +1154,22 @@ struct CxxrtlWorker { for (int part = 0; part < s_width; part++) { f << ")"; } + // Big muxes + } else if (cell->type == ID($bmux)) { + dump_sigspec_rhs(cell->getPort(ID::A), for_debug); + f << ".bmux<"; + f << cell->getParam(ID::WIDTH).as_int(); + f << ">("; + dump_sigspec_rhs(cell->getPort(ID::S), for_debug); + f << ").val()"; + // Demuxes + } else if (cell->type == ID($demux)) { + dump_sigspec_rhs(cell->getPort(ID::A), for_debug); + f << ".demux<"; + f << GetSize(cell->getPort(ID::Y)); + f << ">("; + dump_sigspec_rhs(cell->getPort(ID::S), for_debug); + f << ").val()"; // Concats } else if (cell->type == ID($concat)) { dump_sigspec_rhs(cell->getPort(ID::B), for_debug); |