From 4cd2e04da41fd4e53c17c0b695f1d61060e19856 Mon Sep 17 00:00:00 2001 From: Philippe Sauter Date: Thu, 19 Sep 2024 18:06:42 +0200 Subject: [PATCH 1/3] rtlil: add Const::compress helper function Compresses the current bits to the minimum width representation by removing leading bits. --- kernel/rtlil.cc | 24 ++++++++++++++++++++++++ kernel/rtlil.h | 3 +++ 2 files changed, 27 insertions(+) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 2d3135378..0a3d2082d 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -280,6 +280,30 @@ int RTLIL::Const::as_int(bool is_signed) const return ret; } +void RTLIL::Const::compress(bool is_signed) +{ + if (bits.empty()) return; + + // back to front (MSB to LSB) + RTLIL::State leading_bit; + if(is_signed) + leading_bit = (bits.back() == RTLIL::State::Sx) ? RTLIL::State::S0 : bits.back(); + else + leading_bit = RTLIL::State::S0; + + size_t idx = bits.size(); + while (idx > 0 && bits[idx -1] == leading_bit) { + --idx; + } + + // signed needs one leading bit + if (is_signed && idx < bits.size()) { + ++idx; + } + + bits.erase(bits.begin() + idx, bits.end()); +} + std::string RTLIL::Const::as_string() const { std::string ret; diff --git a/kernel/rtlil.h b/kernel/rtlil.h index c49734cd0..7f47bf288 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -703,6 +703,9 @@ struct RTLIL::Const return ret; } + // compress representation to the minimum required bits + void compress(bool is_signed = false); + void extu(int width) { bits.resize(width, RTLIL::State::S0); } From 07fb8af05baa2f47ebcbacfe8f036196ae8a8ba7 Mon Sep 17 00:00:00 2001 From: Philippe Sauter Date: Fri, 20 Sep 2024 13:56:14 +0200 Subject: [PATCH 2/3] rtlil: handle all-zeros case in Const::compress --- kernel/rtlil.cc | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 0a3d2082d..4403b5382 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -286,20 +286,22 @@ void RTLIL::Const::compress(bool is_signed) // back to front (MSB to LSB) RTLIL::State leading_bit; - if(is_signed) + if (is_signed) leading_bit = (bits.back() == RTLIL::State::Sx) ? RTLIL::State::S0 : bits.back(); else leading_bit = RTLIL::State::S0; - size_t idx = bits.size(); - while (idx > 0 && bits[idx -1] == leading_bit) { - --idx; - } + size_t idx = bits.size(); + while (idx > 0 && bits[idx -1] == leading_bit) { + idx--; + } // signed needs one leading bit if (is_signed && idx < bits.size()) { - ++idx; - } + idx++; + } + // must be at least one bit + idx = (idx == 0) ? 1 : idx; bits.erase(bits.begin() + idx, bits.end()); } From c53c87e1f46634ebeff2ffe2a0dd1275760c208b Mon Sep 17 00:00:00 2001 From: Philippe Sauter Date: Mon, 23 Sep 2024 13:57:07 +0200 Subject: [PATCH 3/3] rtlil: add Const:: as_int_compressed function --- kernel/rtlil.cc | 27 ++++++++++++++++++++++++--- kernel/rtlil.h | 5 +++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 4403b5382..0d2ddf428 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -28,6 +28,7 @@ #include #include +#include YOSYS_NAMESPACE_BEGIN @@ -280,9 +281,9 @@ int RTLIL::Const::as_int(bool is_signed) const return ret; } -void RTLIL::Const::compress(bool is_signed) +size_t RTLIL::Const::get_min_size(bool is_signed) const { - if (bits.empty()) return; + if (bits.empty()) return 0; // back to front (MSB to LSB) RTLIL::State leading_bit; @@ -301,11 +302,31 @@ void RTLIL::Const::compress(bool is_signed) idx++; } // must be at least one bit - idx = (idx == 0) ? 1 : idx; + return (idx == 0) ? 1 : idx; +} +void RTLIL::Const::compress(bool is_signed) +{ + size_t idx = get_min_size(is_signed); bits.erase(bits.begin() + idx, bits.end()); } +std::optional RTLIL::Const::as_int_compress(bool is_signed) const +{ + size_t size = get_min_size(is_signed); + if(size == 0 || size > 32) + return std::nullopt; + + int32_t ret = 0; + for (size_t i = 0; i < size && i < 32; i++) + if (bits[i] == State::S1) + ret |= 1 << i; + if (is_signed && bits[size-1] == State::S1) + for (size_t i = size; i < 32; i++) + ret |= 1 << i; + return ret; +} + std::string RTLIL::Const::as_string() const { std::string ret; diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 7f47bf288..c5a024585 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -703,9 +703,14 @@ struct RTLIL::Const return ret; } + // find the MSB without redundant leading bits + size_t get_min_size(bool is_signed) const; + // compress representation to the minimum required bits void compress(bool is_signed = false); + std::optional as_int_compress(bool is_signed) const; + void extu(int width) { bits.resize(width, RTLIL::State::S0); }