Improved parsing of large integer constants
authorClifford Wolf <clifford@clifford.at>
Sun, 15 Jun 2014 06:48:17 +0000 (08:48 +0200)
committerClifford Wolf <clifford@clifford.at>
Sun, 15 Jun 2014 06:48:17 +0000 (08:48 +0200)
frontends/verilog/const2ast.cc

index c95ce5dc4a97af7c83320c65ec60f22cceb05e35..8491a6b479d0655ba632082cfc5fc2cb71c62d67 100644 (file)
@@ -52,6 +52,8 @@ static int my_decimal_div_by_two(std::vector<uint8_t> &digits)
                carry = digits[i] % 2;
                digits[i] /= 2;
        }
+       while (!digits.empty() && !digits.front())
+               digits.erase(digits.begin());
        return carry;
 }
 
@@ -90,10 +92,15 @@ static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int le
 
        if (base == 10) {
                data.clear();
-               if (len_in_bits < 0)
-                       len_in_bits = ceil(digits.size()/log10(2));
-               for (int i = 0; i < len_in_bits; i++)
-                       data.push_back(my_decimal_div_by_two(digits) ? RTLIL::S1 : RTLIL::S0);
+               if (len_in_bits < 0) {
+                       while (!digits.empty())
+                               data.push_back(my_decimal_div_by_two(digits) ? RTLIL::S1 : RTLIL::S0);
+                       while (data.size() < 32)
+                               data.push_back(RTLIL::S0);
+               } else {
+                       for (int i = 0; i < len_in_bits; i++)
+                               data.push_back(my_decimal_div_by_two(digits) ? RTLIL::S1 : RTLIL::S0);
+               }
                return;
        }
 
@@ -151,20 +158,24 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type)
        str = code.c_str();
 
        char *endptr;
-       long intval = strtol(str, &endptr, 10);
+       long len_in_bits = strtol(str, &endptr, 10);
+
+       // Simple base-10 integer
+       if (*endptr == 0) {
+               std::vector<RTLIL::State> data;
+               my_strtobin(data, str, -1, 10, case_type);
+               if (data.back() == RTLIL::S1)
+                       data.push_back(RTLIL::S0);
+               return AstNode::mkconst_bits(data, true);
+       }
 
-       // Simple 32 bit integer
-       if (*endptr == 0)
-               return AstNode::mkconst_int(intval, true);
-       
        // unsized constant
        if (str == endptr)
-               intval = -1;
+               len_in_bits = -1;
 
        // The "<bits>'s?[bodh]<digits>" syntax
        if (*endptr == '\'')
        {
-               int len_in_bits = intval;
                std::vector<RTLIL::State> data;
                bool is_signed = false;
                if (*(endptr+1) == 's') {
@@ -188,6 +199,12 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type)
                default:
                        return NULL;
                }
+               if (len_in_bits < 0) {
+                       if (is_signed && data.back() == RTLIL::S1)
+                               data.push_back(RTLIL::S0);
+                       while (data.size() < 32)
+                               data.push_back(RTLIL::S0);
+               }
                return AstNode::mkconst_bits(data, is_signed);
        }