OpenFPGA/libs/librtlnumber/src/rtl_utils.cpp

244 lines
7.0 KiB
C++

/* Authors: Aaron Graham (aaron.graham@unb.ca, aarongraham9@gmail.com),
* Jean-Philippe Legault (jlegault@unb.ca, jeanphilippe.legault@gmail.com),
* Alexandrea Demmings (alexandrea.demmings@unb.ca, lxdemmings@gmail.com) and
* Dr. Kenneth B. Kent (ken@unb.ca)
* for the Reconfigurable Computing Research Lab at the
* Univerity of New Brunswick in Fredericton, New Brunswick, Canada
*/
#include "rtl_utils.hpp"
#include <algorithm>
#include <iostream>
static const char *base_10_digits = "0123456789";
static uint8_t _to_decimal(char digit, const char *FUNCT, int LINE)
{
switch(std::tolower(digit))
{
case '0': return 0;
case '1': return 1;
case '2': return 2;
case '3': return 3;
case '4': return 4;
case '5': return 5;
case '6': return 6;
case '7': return 7;
case '8': return 8;
case '9': return 9;
default:
_assert_Werr( false, FUNCT, LINE,
"INVALID BIT INPUT: " + std::string(1,digit)
);
break;
}
return 10;
}
#define to_decimal(num) _to_decimal(num,__func__, __LINE__)
static std::string _radix_digit_to_bits_str(const char digit, size_t radix, const char *FUNCT, int LINE)
{
switch(radix)
{
case 2:
{
switch(std::tolower(digit))
{
case '0': return "0";
case '1': return "1";
case 'x': return "x";
case 'z': return "z";
default:
_assert_Werr( false, FUNCT, LINE,
"INVALID BIT INPUT: " + std::string(1,digit)
);
break;
}
break;
}
case 8:
{
switch(std::tolower(digit))
{
case '0': return "000";
case '1': return "001";
case '2': return "010";
case '3': return "011";
case '4': return "100";
case '5': return "101";
case '6': return "110";
case '7': return "111";
case 'x': return "xxx";
case 'z': return "zzz";
default:
_assert_Werr( false, FUNCT, LINE,
"INVALID BIT INPUT: " + std::string(1,digit)
);
break;
}
break;
}
case 16:
{
switch(std::tolower(digit))
{
case '0': return "0000";
case '1': return "0001";
case '2': return "0010";
case '3': return "0011";
case '4': return "0100";
case '5': return "0101";
case '6': return "0110";
case '7': return "0111";
case '8': return "1000";
case '9': return "1001";
case 'a': return "1010";
case 'b': return "1011";
case 'c': return "1100";
case 'd': return "1101";
case 'e': return "1110";
case 'f': return "1111";
case 'x': return "xxxx";
case 'z': return "zzzz";
default:
_assert_Werr( false, FUNCT, LINE,
"INVALID BIT INPUT: " + std::string(1,digit)
);
break;
}
break;
}
case 256:
{
std::string bitstring = "";
char temp = digit;
// 8 bit per char
for(int i=0; i<8; i++)
{
char value = temp % 2;
temp = temp / 2;
bitstring.insert(bitstring.begin(), (value)? '1': '0');
}
return bitstring;
}
default:
{
_assert_Werr( false, FUNCT, LINE,
"Invalid base " + std::to_string(radix)
);
break;
}
}
std::abort();
}
#define radix_digit_to_bits(num,radix) _radix_digit_to_bits(num,radix,__func__, __LINE__)
static std::string _radix_digit_to_bits(const char digit, size_t radix, const char *FUNCT, int LINE)
{
std::string result = _radix_digit_to_bits_str(digit, radix, FUNCT, LINE);
return result;
}
/**********************
* convert from different radix to bitstring
*/
std::string string_of_radix_to_bitstring(std::string orig_string, size_t radix)
{
std::string result = "";
switch(radix)
{
case 2:
assert_Werr(!orig_string.empty(), "INVALID BIT INPUT: empty string");
assert_Werr(std::string::npos == orig_string.find_first_not_of("xXzZ01"),
"INVALID BIT INPUT: " + orig_string + "for radix 2"
);
break;
case 8:
assert_Werr(!orig_string.empty(), "INVALID BIT INPUT: empty string");
assert_Werr(std::string::npos == orig_string.find_first_not_of("xXzZ01234567"),
"INVALID BIT INPUT: " + orig_string + "for radix 8"
);
break;
case 10:
assert_Werr(!orig_string.empty(), "INVALID BIT INPUT: empty string");
assert_Werr(std::string::npos == orig_string.find_first_not_of("0123456789"),
"INVALID BIT INPUT: " + orig_string + "for radix 10"
);
break;
case 16:
assert_Werr(!orig_string.empty(), "INVALID BIT INPUT: empty string");
assert_Werr(std::string::npos == orig_string.find_first_not_of("xZzZ0123456789aAbBcCdDeEfF"),
"INVALID BIT INPUT: " + orig_string + "for radix 16"
);
break;
case 256:
// allow all chars
break;
default:
assert_Werr(false,
"invalid radix: " + std::to_string(radix)
);
break;
}
while(!orig_string.empty())
{
switch(radix)
{
case 10:
{
std::string new_number = "";
uint8_t rem_digit = 0;
for(char current_digit : orig_string)
{
uint8_t new_pair = (rem_digit *10) + to_decimal(current_digit);
new_number.push_back(base_10_digits[(new_pair/2)]);
rem_digit = new_pair%2;
}
result.insert(result.begin(),base_10_digits[rem_digit]);
while( new_number.size() > 1
&& new_number[0] == '0' )
{
new_number.erase(0,1);
}
if( new_number == "0" )
{
orig_string = "";
}
else
{
orig_string = new_number;
}
break;
}
default:
{
result = radix_digit_to_bits(orig_string.back(), radix) + result;
orig_string.pop_back();
break;
}
}
}
result.insert(result.begin(),'0');
return result;
}