/* 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 #include 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; }