Update the enumeration methods to set their width test attributes correctly

This commit is contained in:
Cary R 2017-11-17 13:07:18 -08:00
parent 21418c6a41
commit d23b046203
2 changed files with 26 additions and 94 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2017 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -3141,6 +3141,25 @@ unsigned PEIdent::test_width_method_(Design*des, NetScope*scope, width_mode_t&)
}
}
// Look for the enumeration attributes.
if (const netenum_t*netenum = net->enumeration()) {
if (member_name == "num") {
expr_type_ = IVL_VT_BOOL;
expr_width_ = 32;
min_width_ = 32;
signed_flag_= true;
return 32;
}
if ((member_name == "first") || (member_name == "last") ||
(member_name == "next") || (member_name == "prev")) {
expr_type_ = netenum->base_type();
expr_width_ = netenum->packed_width();;
min_width_ = expr_width_;
signed_flag_ = netenum->get_signed();
return expr_width_;
}
}
return 0;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2017 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -570,11 +570,10 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag, const NetExpr*le, const NetExpr*r
const verinum::V ne_res = ne_flag? verinum::V1 : verinum::V0;
verinum::V res = eq_res;
unsigned top = lv.len();
if (rv.len() < top)
top = rv.len();
for (unsigned idx = 0 ; idx < top ; idx += 1) {
assert(lv.len() == rv.len());
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1) {
bool x_bit_present = false;
@ -611,60 +610,6 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag, const NetExpr*le, const NetExpr*r
}
}
if (res != verinum::Vx) {
verinum::V lpad = verinum::V0;
verinum::V rpad = verinum::V0;
if (lv.has_sign() && lv.get(lv.len()-1) == verinum::V1)
lpad = verinum::V1;
if (rv.has_sign() && rv.get(rv.len()-1) == verinum::V1)
rpad = verinum::V1;
for (unsigned idx = top ; idx < lv.len() ; idx += 1)
switch (lv.get(idx)) {
case verinum::Vx:
case verinum::Vz:
res = verinum::Vx;
break;
case verinum::V0:
if (res != verinum::Vx && rpad != verinum::V0)
res = ne_res;
break;
case verinum::V1:
if (res != verinum::Vx && rpad != verinum::V1)
res = ne_res;
break;
default:
break;
}
for (unsigned idx = top ; idx < rv.len() ; idx += 1)
switch (rv.get(idx)) {
case verinum::Vx:
case verinum::Vz:
res = verinum::Vx;
break;
case verinum::V0:
if (res != verinum::Vx && lpad != verinum::V0)
res = ne_res;
break;
case verinum::V1:
if (res != verinum::Vx && lpad != verinum::V1)
res = ne_res;
break;
default:
break;
}
}
NetEConst*result = new NetEConst(verinum(res, 1));
ivl_assert(*this, result);
return result;
@ -681,46 +626,14 @@ NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr
verinum::V res = verinum::V1;
// Find the smallest argument length.
unsigned cnt = lv.len();
if (cnt > rv.len()) cnt = rv.len();
assert(lv.len() == rv.len());
// Check the common bits.
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1)
if (lv.get(idx) != rv.get(idx)) {
res = verinum::V0;
break;
}
bool is_signed = lv.has_sign() && rv.has_sign();
// If the left value is longer check it against the pad bit.
if (res == verinum::V1) {
verinum::V pad = verinum::V0;
if (is_signed)
pad = rv.get(rv.len()-1);
for (unsigned idx = cnt ; idx < lv.len() ; idx += 1)
if (lv.get(idx) != pad) {
res = verinum::V0;
break;
}
}
// If the right value is longer check it against the pad bit.
if (res == verinum::V1) {
verinum::V pad = verinum::V0;
if (is_signed)
pad = lv.get(lv.len()-1);
for (unsigned idx = cnt ; idx < rv.len() ; idx += 1) {
if (rv.get(idx) != pad) {
res = verinum::V0;
break;
}
}
}
if (ne_flag) {
if (res == verinum::V0) res = verinum::V1;
else res = verinum::V0;