Skip to content

Commit

Permalink
Add functions to compute minimum number of bits required to store int…
Browse files Browse the repository at this point in the history
…eger values

Separate functions are implemented for signed and unsigned integers.

Note that the current use of ceil_log2(x) for x >= 0 may be incorrect in
some cases; the minimum number of bits required to store x is really
ceil_log2(x + 1).
  • Loading branch information
daglem committed Mar 7, 2024
1 parent 8882f95 commit 9a0559c
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 0 deletions.
38 changes: 38 additions & 0 deletions kernel/yosys.cc
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@
#include <limits.h>
#include <errno.h>

#if __cplusplus >= 202002L
# include <bit>
#endif

#include "libs/json11/json11.hpp"

YOSYS_NAMESPACE_BEGIN
Expand Down Expand Up @@ -175,6 +179,40 @@ int ceil_log2(int x)
#endif
}

// Calculate the minimum number of bits required to store an unsigned integer value.
// Note that min_bit_width(0u) == 0.
int min_bit_width(unsigned x)
{
#if __cplusplus >= 202002L
return std::bit_width(x);
#else
int width = 0;
while (x) {
width += 1;
x >>= 1;
}
return width;
#endif
}

// Calculate the minimum number of bits required to store a signed integer value,
// using two's complement representation for negative values.
// Note that the sign bit is included in the width for all values except 0.
int min_bit_width(int x)
{
if (x < 0) {
// Compute two's complement of negative value.
// Negative numbers are represented in two's complement form
// in SystemVerilog, and this is also guaranteed by C++20.
// C++20 also makes integral conversion of unsigned integers
// to signed integers well defined.
x = -(unsigned)x;
}
// Add a bit for sign, except for 0 and the most negative number, whose
// two's complement is equal to itself, i.e. the sign bit is still set.
return (x > 0) + min_bit_width((unsigned)x);
}

int readsome(std::istream &f, char *s, int n)
{
int rc = int(f.readsome(s, n));
Expand Down
2 changes: 2 additions & 0 deletions kernel/yosys.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@ inline void memhasher() { if (memhasher_active) memhasher_do(); }

void yosys_banner();
int ceil_log2(int x) YS_ATTRIBUTE(const);
int min_bit_width(unsigned x);
int min_bit_width(int x);

inline std::string vstringf(const char *fmt, va_list ap)
{
Expand Down

0 comments on commit 9a0559c

Please sign in to comment.