244 lines
7.0 KiB
C++
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;
|
|
}
|