diff options
author | whitequark <whitequark@whitequark.org> | 2020-12-21 04:32:18 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-21 04:32:18 +0000 |
commit | a679a761b51ca67b61dc8b2c7316949b41ef9dd2 (patch) | |
tree | 7edd9e357c51b398a82a77134f5d21a863986403 | |
parent | b90d51e35ddcb4b25814acac9bf6e09b4478b6ef (diff) | |
parent | b9721bedf01ca1f536bbf13ba761333c6867bd29 (diff) | |
download | yosys-a679a761b51ca67b61dc8b2c7316949b41ef9dd2.tar.gz yosys-a679a761b51ca67b61dc8b2c7316949b41ef9dd2.tar.bz2 yosys-a679a761b51ca67b61dc8b2c7316949b41ef9dd2.zip |
Merge pull request #2496 from whitequark/cxxrtl-fixes
cxxrtl: various improvements
-rw-r--r-- | backends/cxxrtl/cxxrtl.h | 8 | ||||
-rw-r--r-- | backends/cxxrtl/cxxrtl_backend.cc | 31 | ||||
-rw-r--r-- | backends/cxxrtl/cxxrtl_capi.h | 2 |
3 files changed, 32 insertions, 9 deletions
diff --git a/backends/cxxrtl/cxxrtl.h b/backends/cxxrtl/cxxrtl.h index 3c315c7df..0a6bcb849 100644 --- a/backends/cxxrtl/cxxrtl.h +++ b/backends/cxxrtl/cxxrtl.h @@ -317,6 +317,14 @@ struct value : public expr_base<value<Bits>> { return sext_cast<NewBits>()(*this); } + // Bit replication is far more efficient than the equivalent concatenation. + template<size_t Count> + CXXRTL_ALWAYS_INLINE + value<Bits * Count> repeat() const { + static_assert(Bits == 1, "repeat() is implemented only for 1-bit values"); + return *this ? value<Bits * Count>().bit_not() : value<Bits * Count>(); + } + // Operations with run-time parameters (offsets, amounts, etc). // // These operations are used for computations. diff --git a/backends/cxxrtl/cxxrtl_backend.cc b/backends/cxxrtl/cxxrtl_backend.cc index 9875aba60..916303bfe 100644 --- a/backends/cxxrtl/cxxrtl_backend.cc +++ b/backends/cxxrtl/cxxrtl_backend.cc @@ -832,11 +832,26 @@ struct CxxrtlWorker { } else if (sig.is_chunk()) { return dump_sigchunk(sig.as_chunk(), is_lhs, for_debug); } else { - dump_sigchunk(*sig.chunks().rbegin(), is_lhs, for_debug); - for (auto it = sig.chunks().rbegin() + 1; it != sig.chunks().rend(); ++it) { - f << ".concat("; - dump_sigchunk(*it, is_lhs, for_debug); - f << ")"; + bool first = true; + auto chunks = sig.chunks(); + for (auto it = chunks.rbegin(); it != chunks.rend(); it++) { + if (!first) + f << ".concat("; + bool is_complex = dump_sigchunk(*it, is_lhs, for_debug); + if (!is_lhs && it->width == 1) { + size_t repeat = 1; + while ((it + repeat) != chunks.rend() && *(it + repeat) == *it) + repeat++; + if (repeat > 1) { + if (is_complex) + f << ".val()"; + f << ".repeat<" << repeat << ">()"; + } + it += repeat - 1; + } + if (!first) + f << ")"; + first = false; } return true; } @@ -1702,19 +1717,19 @@ struct CxxrtlWorker { continue; } if (!module->get_bool_attribute(ID(cxxrtl_blackbox)) || wire->port_id != 0) - f << indent << "changed |= " << mangle(wire) << ".commit();\n"; + f << indent << "if (" << mangle(wire) << ".commit()) changed = true;\n"; } if (!module->get_bool_attribute(ID(cxxrtl_blackbox))) { for (auto memory : module->memories) { if (!writable_memories[memory.second]) continue; - f << indent << "changed |= " << mangle(memory.second) << ".commit();\n"; + f << indent << "if (" << mangle(memory.second) << ".commit()) changed = true;\n"; } for (auto cell : module->cells()) { if (is_internal_cell(cell->type)) continue; const char *access = is_cxxrtl_blackbox_cell(cell) ? "->" : "."; - f << indent << "changed |= " << mangle(cell) << access << "commit();\n"; + f << indent << "if (" << mangle(cell) << access << "commit()) changed = true;\n"; } } f << indent << "return changed;\n"; diff --git a/backends/cxxrtl/cxxrtl_capi.h b/backends/cxxrtl/cxxrtl_capi.h index 7d9c60ac5..2df2b7287 100644 --- a/backends/cxxrtl/cxxrtl_capi.h +++ b/backends/cxxrtl/cxxrtl_capi.h @@ -272,7 +272,7 @@ struct cxxrtl_object *cxxrtl_get_parts(cxxrtl_handle handle, const char *name, s // This function is a shortcut for the most common use of `cxxrtl_get_parts`. It asserts that, // if the object exists, it consists of a single part. If assertions are disabled, it returns NULL // for multi-part objects. -inline struct cxxrtl_object *cxxrtl_get(cxxrtl_handle handle, const char *name) { +static inline struct cxxrtl_object *cxxrtl_get(cxxrtl_handle handle, const char *name) { size_t parts = 0; struct cxxrtl_object *object = cxxrtl_get_parts(handle, name, &parts); assert(object == NULL || parts == 1); |