Warn on literals exceeding the specified bit width
authorFlorian Zeitz <florob@babelmonkeys.de>
Mon, 17 Aug 2015 13:27:35 +0000 (15:27 +0200)
committerFlorian Zeitz <florob@babelmonkeys.de>
Mon, 17 Aug 2015 13:27:35 +0000 (15:27 +0200)
frontends/verilog/const2ast.cc

index ebecb92f2fbfbf61bf55903a1cd53d7aec0ca9bc..6a9326898fe3ccec4dacd8d2c9b06c5437c061bb 100644 (file)
@@ -96,44 +96,51 @@ static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int le
        if (base == 10 && GetSize(digits) == 1 && digits.front() >= 0xf0)
                base = 2;
 
+       data.clear();
+
        if (base == 10) {
-               data.clear();
-               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);
+               while (!digits.empty())
+                       data.push_back(my_decimal_div_by_two(digits) ? RTLIL::S1 : RTLIL::S0);
+       } else {
+               int bits_per_digit = my_ilog2(base-1);
+               for (auto it = digits.rbegin(), e = digits.rend(); it != e; it++) {
+                       for (int i = 0; i < bits_per_digit; i++) {
+                               int bitmask = 1 << i;
+                               if (*it == 0xf0)
+                                       data.push_back(case_type == 'x' ? RTLIL::Sa : RTLIL::Sx);
+                               else if (*it == 0xf1)
+                                       data.push_back(case_type == 'x' || case_type == 'z' ? RTLIL::Sa : RTLIL::Sz);
+                               else if (*it == 0xf2)
+                                       data.push_back(RTLIL::Sa);
+                               else
+                                       data.push_back((*it & bitmask) ? RTLIL::S1 : RTLIL::S0);
+                       }
                }
-               return;
        }
 
-       int bits_per_digit = my_ilog2(base-1);
-       if (len_in_bits < 0)
-               len_in_bits = std::max<int>(digits.size() * bits_per_digit, 32);
+       int len = GetSize(data);
+       RTLIL::State msb = data.back();
 
-       data.clear();
-       data.resize(len_in_bits);
-
-       for (int i = 0; i < len_in_bits; i++) {
-               int bitmask = 1 << (i % bits_per_digit);
-               int digitidx = digits.size() - (i / bits_per_digit) - 1;
-               if (digitidx < 0) {
-                       if (i > 0 && (data[i-1] == RTLIL::Sz || data[i-1] == RTLIL::Sx || data[i-1] == RTLIL::Sa))
-                               data[i] = data[i-1];
-                       else
-                               data[i] = RTLIL::S0;
-               } else if (digits[digitidx] == 0xf0)
-                       data[i] = case_type == 'x' ? RTLIL::Sa : RTLIL::Sx;
-               else if (digits[digitidx] == 0xf1)
-                       data[i] = case_type == 'x' || case_type == 'z' ? RTLIL::Sa : RTLIL::Sz;
-               else if (digits[digitidx] == 0xf2)
-                       data[i] = RTLIL::Sa;
-               else
-                       data[i] = (digits[digitidx] & bitmask) ? RTLIL::S1 : RTLIL::S0;
+       if (len_in_bits < 0) {
+               if (len < 32)
+                       data.resize(32, msb == RTLIL::S0 || msb == RTLIL::S1 ? RTLIL::S0 : msb);
+               return;
+       }
+
+       for (len = len - 1; len >= 0; len--)
+               if (data[len] == RTLIL::S1)
+                       break;
+       if (msb == RTLIL::S0 || msb == RTLIL::S1) {
+               len += 1;
+               data.resize(len_in_bits, RTLIL::S0);
+       } else {
+               len += 2;
+               data.resize(len_in_bits, msb);
        }
+
+       if (len > len_in_bits)
+               log_warning("(Literal has a width of %d bit, but value requires %d bit. (%s:%d)\n",
+                       len_in_bits, len, current_filename.c_str(), get_line_num());
 }
 
 // convert the Verilog code for a constant to an AST node
@@ -220,8 +227,6 @@ AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn
                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);
        }