From 3d3ea5099d50a3de7b76ea47189b5700956b2703 Mon Sep 17 00:00:00 2001 From: whitequark Date: Sun, 20 Dec 2020 14:48:16 +0000 Subject: [PATCH 1/3] cxxrtl: use `static inline` instead of `inline` in the C API. In C, non-static inline functions require an implementation elsewhere (even though the body is right there in the header). It is basically never desirable to use those as opposed to static inline ones. --- backends/cxxrtl/cxxrtl_capi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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); From 40ca9d038b1e657b9b9ac17e7e5a2969c9922e00 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 21 Dec 2020 00:22:50 +0000 Subject: [PATCH 2/3] cxxrtl: speed up commits on clang. On Minerva SoC SRAM compiled with clang-11, this change cuts commit time in half (!) and overall time by 20%. When compiled with gcc-10, there is no difference. --- backends/cxxrtl/cxxrtl_backend.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backends/cxxrtl/cxxrtl_backend.cc b/backends/cxxrtl/cxxrtl_backend.cc index 9875aba60..3b2fb4985 100644 --- a/backends/cxxrtl/cxxrtl_backend.cc +++ b/backends/cxxrtl/cxxrtl_backend.cc @@ -1702,19 +1702,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"; From b9721bedf01ca1f536bbf13ba761333c6867bd29 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 21 Dec 2020 02:15:55 +0000 Subject: [PATCH 3/3] cxxrtl: speed up bit repeats (sign extends, etc). On Minerva SoC SRAM, depending on the compiler, this change improves overall time by 4-7%. --- backends/cxxrtl/cxxrtl.h | 8 ++++++++ backends/cxxrtl/cxxrtl_backend.cc | 25 ++++++++++++++++++++----- 2 files changed, 28 insertions(+), 5 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> { return sext_cast()(*this); } + // Bit replication is far more efficient than the equivalent concatenation. + template + CXXRTL_ALWAYS_INLINE + value repeat() const { + static_assert(Bits == 1, "repeat() is implemented only for 1-bit values"); + return *this ? value().bit_not() : value(); + } + // 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 3b2fb4985..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; }