From 64ccbf8510d33f08af7743974d061db166da1832 Mon Sep 17 00:00:00 2001 From: Florian Zeitz Date: Mon, 17 Aug 2015 15:27:35 +0200 Subject: [PATCH] Warn on literals exceeding the specified bit width --- frontends/verilog/const2ast.cc | 73 ++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/frontends/verilog/const2ast.cc b/frontends/verilog/const2ast.cc index ebecb92f2..6a9326898 100644 --- a/frontends/verilog/const2ast.cc +++ b/frontends/verilog/const2ast.cc @@ -96,44 +96,51 @@ static void my_strtobin(std::vector &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(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); } -- 2.30.2