Add support for a constant $countbits() function

This commit is contained in:
Cary R 2018-09-03 15:58:05 -07:00
parent 1da9b2cea0
commit e6f957b0b6
2 changed files with 76 additions and 22 deletions

View File

@ -1908,17 +1908,16 @@ NetExpr* NetESFunc::evaluate_min_max_(ID id, const NetExpr*arg0_,
return res; return res;
} }
static void no_string_arg(const NetESFunc*info) static void no_string_arg(const NetESFunc*info, unsigned arg_num)
{ {
cerr << info->get_fileline() << ": error: constant function " cerr << info->get_fileline() << ": error: constant function "
<< info->name() << "() does not support a string argument." << info->name() << "() does not support a string argument ("
<< endl; << arg_num+1 << ")." << endl;
} }
NetEConst* NetESFunc::evaluate_countbits_(const NetExpr* arg, NetEConst* NetESFunc::evaluate_countbits_() const
const NetExpr* /*arg1*/) const
{ {
const NetEConst*tmpi = dynamic_cast<const NetEConst*>(arg); const NetEConst*tmpi = dynamic_cast<const NetEConst*>(parms_[0]);
NetEConst*res = 0; NetEConst*res = 0;
@ -1926,13 +1925,63 @@ NetEConst* NetESFunc::evaluate_countbits_(const NetExpr* arg,
verinum value = tmpi->value(); verinum value = tmpi->value();
if (value.is_string()) { if (value.is_string()) {
no_string_arg(this); no_string_arg(this, 0);
return 0; return 0;
} }
cerr << get_fileline() << ": error: constant function " /* Find which values need to be counted. */
<< name_ << "() is not currently supported." bool count_0 = false;
<< endl; bool count_1 = false;
bool count_z = false;
bool count_x = false;
for (unsigned arg=1; arg < parms_.size(); ++arg) {
const NetEConst*argi = dynamic_cast<const NetEConst*>(parms_[arg]);
if (! argi) return 0;
verinum check_for = argi->value();
if (check_for.is_string()) {
no_string_arg(this, arg);
return 0;
}
switch (check_for[0]) {
case verinum::V0:
count_0 = true;
break;
case verinum::V1:
count_1 = true;
break;
case verinum::Vz:
count_z = true;
break;
case verinum::Vx:
count_x = true;
break;
}
}
/* Search each bit of the vector looking for the values to
* be counted. */
int count = 0;
for (unsigned bit=0; bit < value.len(); ++bit) {
switch (value[bit]) {
case verinum::V0:
if (count_0) ++count;
break;
case verinum::V1:
if (count_1) ++count;
break;
case verinum::Vz:
if (count_z) ++count;
break;
case verinum::Vx:
if (count_x) ++count;
break;
}
}
verinum tmp (count, integer_width);
tmp.has_sign(true);
res = new NetEConst(tmp);
ivl_assert(*this, res);
} }
return res; return res;
@ -1949,12 +1998,12 @@ NetEConst* NetESFunc::evaluate_countones_(const NetExpr* arg) const
int count = 0; int count = 0;
if (value.is_string()) { if (value.is_string()) {
no_string_arg(this); no_string_arg(this, 0);
return 0; return 0;
} }
for (unsigned bit=0; bit < value.len(); ++bit) { for (unsigned bit=0; bit < value.len(); ++bit) {
if (value[bit] == verinum::V1) count += 1; if (value[bit] == verinum::V1) ++count;
} }
verinum tmp (count, integer_width); verinum tmp (count, integer_width);
@ -1997,7 +2046,7 @@ NetEConst* NetESFunc::evaluate_isunknown_(const NetExpr* arg) const
unsigned is_unknown = 1; unsigned is_unknown = 1;
if (value.is_string()) { if (value.is_string()) {
no_string_arg(this); no_string_arg(this, 0);
return 0; return 0;
} }
@ -2038,7 +2087,7 @@ NetEConst* NetESFunc::evaluate_onehot_(const NetExpr* arg) const
verinum value = tmpi->value(); verinum value = tmpi->value();
if (value.is_string()) { if (value.is_string()) {
no_string_arg(this); no_string_arg(this, 0);
return 0; return 0;
} }
@ -2061,7 +2110,7 @@ NetEConst* NetESFunc::evaluate_onehot0_(const NetExpr* arg) const
verinum value = tmpi->value(); verinum value = tmpi->value();
if (value.is_string()) { if (value.is_string()) {
no_string_arg(this); no_string_arg(this, 0);
return 0; return 0;
} }
@ -2243,7 +2292,7 @@ NetExpr* NetESFunc::evaluate_two_arg_(ID id, const NetExpr*arg0,
{ {
switch (id) { switch (id) {
case CTBITS: case CTBITS:
return evaluate_countbits_(arg0, arg1); return evaluate_countbits_();
/* The array functions are handled together. */ /* The array functions are handled together. */
case HIGH: case HIGH:
case INCR: case INCR:
@ -2381,10 +2430,16 @@ NetExpr* NetESFunc::eval_tree()
<< " arguments." << endl; << " arguments." << endl;
return 0; return 0;
} }
// HERE: Need to add support for a multi argument $countbits(). if (id == CTBITS) {
cerr << get_fileline() << ": sorry: constant functions with " for (unsigned bit = 0; bit < parms_.size(); ++bit) {
<< parms_.size() << " arguments are not supported: " eval_expr(parms_[bit]);
<< name_ << "()." << endl; }
return evaluate_countbits_();
} else {
cerr << get_fileline() << ": sorry: constant functions with "
<< parms_.size() << " arguments are not supported: "
<< name_ << "()." << endl;
}
return 0; return 0;
} }
} }

View File

@ -4657,8 +4657,7 @@ class NetESFunc : public NetExpr {
NetEConst* evaluate_array_funcs_(ID id, NetEConst* evaluate_array_funcs_(ID id,
const NetExpr*arg0, const NetExpr*arg0,
const NetExpr*arg1) const; const NetExpr*arg1) const;
NetEConst* evaluate_countbits_(const NetExpr*arg0, NetEConst* evaluate_countbits_(void) const;
const NetExpr*arg1) const;
public: public:
bool is_built_in() const { return built_in_id_() != NOT_BUILT_IN; }; bool is_built_in() const { return built_in_id_() != NOT_BUILT_IN; };