diff options
Diffstat (limited to 'frontends/verilog/const2ast.cc')
-rw-r--r-- | frontends/verilog/const2ast.cc | 93 |
1 files changed, 53 insertions, 40 deletions
diff --git a/frontends/verilog/const2ast.cc b/frontends/verilog/const2ast.cc index 735bc5f99..4a58357bf 100644 --- a/frontends/verilog/const2ast.cc +++ b/frontends/verilog/const2ast.cc @@ -2,11 +2,11 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at> - * + * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. - * + * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR @@ -48,7 +48,9 @@ static int my_decimal_div_by_two(std::vector<uint8_t> &digits) { int carry = 0; for (size_t i = 0; i < digits.size(); i++) { - log_assert(digits[i] < 10); + if (digits[i] >= 10) + log_error("Invalid use of [a-fxz?] in decimal constant at %s:%d.\n", + current_filename.c_str(), get_line_num()); digits[i] += carry * 10; carry = digits[i] % 2; digits[i] /= 2; @@ -91,54 +93,67 @@ static void my_strtobin(std::vector<RTLIL::State> &data, const char *str, int le str++; } + 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++) { + if (*it > (base-1) && *it < 0xf0) + log_error("Digit larger than %d used in in base-%d constant at %s:%d.\n", + base-1, base, current_filename.c_str(), get_line_num()); + 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.empty() ? RTLIL::S0 : 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 +// convert the Verilog code for a constant to an AST node AstNode *VERILOG_FRONTEND::const2ast(std::string code, char case_type, bool warn_z) { if (warn_z) { AstNode *ret = const2ast(code, case_type); if (std::find(ret->bits.begin(), ret->bits.end(), RTLIL::State::Sz) != ret->bits.end()) - log_warning("Yosys does not support tri-state logic at the moment. (%s:%d)\n", - current_filename.c_str(), frontend_verilog_yyget_lineno()); + log_warning("Yosys has only limited support for tri-state logic at the moment. (%s:%d)\n", + current_filename.c_str(), get_line_num()); return ret; } @@ -215,8 +230,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); } |