diff --git a/elab_expr.cc b/elab_expr.cc index 4fe9dadf9..b2f741d4d 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -3166,7 +3166,7 @@ unsigned PENumber::test_width(Design*, NetScope*, width_mode_t&mode) min_width_ = 1; signed_flag_ = value_->has_sign(); - if ((mode < LOSSLESS) && !value_->has_len()) + if ((mode < LOSSLESS) && !value_->has_len() && !value_->is_single()) mode = LOSSLESS; return expr_width_; diff --git a/lexor.lex b/lexor.lex index 48ad58070..f254245ac 100644 --- a/lexor.lex +++ b/lexor.lex @@ -329,6 +329,14 @@ TU [munpf] return BASED_NUMBER; } \'[sS]?[hH][ \t]*[0-9a-fA-FxzXZ_\?]+ { yylval.number = make_unsized_hex(yytext); return BASED_NUMBER; } +\'[01xzXZ] { + if (generation_flag < GN_VER2005_SV) { + cerr << yylloc.text << ":" << yylloc.first_line << ": warning: " + << "Using SystemVerilog 'N bit vector. Use at least " + << "-g2005-sv to remove this warning." << endl; + } + yylval.number = make_unsized_binary(yytext); + return BASED_NUMBER; } [0-9][0-9_]* { yylval.number = make_unsized_dec(yytext); @@ -684,6 +692,7 @@ void lex_end_table() verinum*make_unsized_binary(const char*txt) { bool sign_flag = false; + bool single_flag = false; const char*ptr = txt; assert(*ptr == '\''); ptr += 1; @@ -693,8 +702,13 @@ verinum*make_unsized_binary(const char*txt) ptr += 1; } - assert(tolower(*ptr) == 'b'); - ptr += 1; + assert((tolower(*ptr) == 'b') || (generation_flag >= GN_VER2005_SV)); + if (tolower(*ptr) == 'b') { + ptr += 1; + } else { + assert(sign_flag == false); + single_flag = true; + } while (*ptr && ((*ptr == ' ') || (*ptr == '\t'))) ptr += 1; @@ -734,6 +748,7 @@ verinum*make_unsized_binary(const char*txt) verinum*out = new verinum(bits, size, false); out->has_sign(sign_flag); + out->is_single(single_flag); delete[]bits; return out; } diff --git a/verinum.cc b/verinum.cc index 1b576c224..0c4629e4a 100644 --- a/verinum.cc +++ b/verinum.cc @@ -43,12 +43,12 @@ extern "C" long int lround(double x) static verinum::V add_with_carry(verinum::V l, verinum::V r, verinum::V&c); verinum::verinum() -: bits_(0), nbits_(0), has_len_(false), has_sign_(false), string_flag_(false) +: bits_(0), nbits_(0), has_len_(false), has_sign_(false), is_single_(false), string_flag_(false) { } verinum::verinum(const V*bits, unsigned nbits, bool has_len__) -: has_len_(has_len__), has_sign_(false), string_flag_(false) +: has_len_(has_len__), has_sign_(false), is_single_(false), string_flag_(false) { nbits_ = nbits; bits_ = new V [nbits]; @@ -111,7 +111,7 @@ static string process_verilog_string_quotes(const string&str) } verinum::verinum(const string&s) -: has_len_(true), has_sign_(false), string_flag_(true) +: has_len_(true), has_sign_(false), is_single_(false), string_flag_(true) { string str = process_verilog_string_quotes(s); nbits_ = str.length() * 8; @@ -149,7 +149,7 @@ verinum::verinum(const string&s) } verinum::verinum(verinum::V val, unsigned n, bool h) -: has_len_(h), has_sign_(false), string_flag_(false) +: has_len_(h), has_sign_(false), is_single_(false), string_flag_(false) { nbits_ = n; bits_ = new V[nbits_]; @@ -158,7 +158,7 @@ verinum::verinum(verinum::V val, unsigned n, bool h) } verinum::verinum(uint64_t val, unsigned n) -: has_len_(true), has_sign_(false), string_flag_(false) +: has_len_(true), has_sign_(false), is_single_(false), string_flag_(false) { nbits_ = n; bits_ = new V[nbits_]; @@ -171,7 +171,7 @@ verinum::verinum(uint64_t val, unsigned n) /* The second argument is not used! It is there to make this * constructor unique. */ verinum::verinum(double val, bool) -: has_len_(false), has_sign_(true), string_flag_(false) +: has_len_(false), has_sign_(true), is_single_(false), string_flag_(false) { bool is_neg = false; double fraction; @@ -281,6 +281,7 @@ verinum::verinum(const verinum&that) bits_ = new V[nbits_]; has_len_ = that.has_len_; has_sign_ = that.has_sign_; + is_single_ = that.is_single_; for (unsigned idx = 0 ; idx < nbits_ ; idx += 1) bits_[idx] = that.bits_[idx]; } @@ -292,6 +293,7 @@ verinum::verinum(const verinum&that, unsigned nbits) bits_ = new V[nbits_]; has_len_ = true; has_sign_ = that.has_sign_; + is_single_ = false; unsigned copy = nbits; if (copy > that.nbits_) @@ -300,7 +302,7 @@ verinum::verinum(const verinum&that, unsigned nbits) bits_[idx] = that.bits_[idx]; if (copy < nbits_) { - if (has_sign_) { + if (has_sign_ || that.is_single_) { for (unsigned idx = copy ; idx < nbits_ ; idx += 1) bits_[idx] = bits_[idx-1]; } else { @@ -311,7 +313,7 @@ verinum::verinum(const verinum&that, unsigned nbits) } verinum::verinum(int64_t that) -: has_len_(false), has_sign_(true), string_flag_(false) +: has_len_(false), has_sign_(true), is_single_(false), string_flag_(false) { int64_t tmp; @@ -348,6 +350,7 @@ verinum& verinum::operator= (const verinum&that) has_len_ = that.has_len_; has_sign_ = that.has_sign_; + is_single_ = that.is_single_; string_flag_ = that.string_flag_; return *this; } @@ -570,9 +573,9 @@ verinum pad_to_width(const verinum&that, unsigned width) } verinum::V pad = that[that.len()-1]; - if (pad==verinum::V1 && !that.has_sign()) + if (pad==verinum::V1 && !that.has_sign() && !that.is_single()) pad = verinum::V0; - if (that.has_len() && !that.has_sign()) { + if (that.has_len() && !that.has_sign() && !that.is_single()) { if (pad==verinum::Vx) pad = verinum::V0; if (pad==verinum::Vz) @@ -606,9 +609,9 @@ verinum cast_to_width(const verinum&that, unsigned width) } verinum::V pad = that[that.len()-1]; - if (pad==verinum::V1 && !that.has_sign()) + if (pad==verinum::V1 && !that.has_sign() && !that.is_single()) pad = verinum::V0; - if (that.has_len() && !that.has_sign()) { + if (that.has_len() && !that.has_sign() && !that.is_single()) { if (pad==verinum::Vx) pad = verinum::V0; if (pad==verinum::Vz) diff --git a/verinum.h b/verinum.h index acab1d673..24ea075d7 100644 --- a/verinum.h +++ b/verinum.h @@ -70,6 +70,10 @@ class verinum { bool has_sign(bool flag) { has_sign_ = flag; return has_sign_; } bool has_sign() const { return has_sign_; } + // A number "is single" if it comes from a SystemVerilog 'N bit vector + bool is_single(bool flag) { is_single_ = flag; return is_single_; } + bool is_single() const { return is_single_; } + // A number is "defined" if there are no x or z bits in its value. bool is_defined() const; bool is_zero() const; @@ -103,6 +107,7 @@ class verinum { unsigned nbits_; bool has_len_; bool has_sign_; + bool is_single_; // These are some convenience flags that help us do a better // job of pretty-printing values.