Manage expression types for ternary a little better.

The true and false expression clauses must have compatible types,
which are not necesarily identical. In particular, VT_BOOL and
VT_LOGIC are compatible for the purposes of ternary arguments. The
test in NetETernary::synthesize was incorrect.

In the process, fix the type handling of NetConst objects to allow
for IVL_VT_BOOL constants. This is information that the downstream
may find useful, so should be handled correctly.
This commit is contained in:
Stephen Williams 2008-09-13 16:43:39 -07:00
parent 3d5998cd63
commit 804f5a94d5
7 changed files with 27 additions and 11 deletions

View File

@ -2148,8 +2148,8 @@ unsigned PETernary::test_width(Design*des, NetScope*scope,
return max(tru_wid,fal_wid);
}
static bool test_ternary_operand_compat(ivl_variable_type_t l,
ivl_variable_type_t r)
bool NetETernary::test_operand_compat(ivl_variable_type_t l,
ivl_variable_type_t r)
{
if (l == IVL_VT_LOGIC && r == IVL_VT_BOOL)
return true;
@ -2245,7 +2245,7 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
return 0;
}
if (! test_ternary_operand_compat(tru->expr_type(), fal->expr_type())) {
if (! NetETernary::test_operand_compat(tru->expr_type(), fal->expr_type())) {
cerr << get_fileline() << ": error: Data types "
<< tru->expr_type() << " and "
<< fal->expr_type() << " of ternary"

View File

@ -746,7 +746,7 @@ NetNet* NetEConst::synthesize(Design*des, NetScope*scope)
NetNet*osig = new NetNet(scope, path, NetNet::IMPLICIT, width-1,0);
osig->local_flag(true);
osig->data_type(IVL_VT_LOGIC);
osig->data_type(expr_type());
osig->set_signed(has_sign());
NetConst*con = new NetConst(scope, scope->local_symbol(), value());
connect(osig->pin(0), con->pin(0));
@ -1097,13 +1097,18 @@ NetNet* NetETernary::synthesize(Design *des, NetScope*scope)
if (csig == 0 || tsig == 0 || fsig == 0) return 0;
if (tsig->data_type() != fsig->data_type()) {
cerr << get_fileline() << ": error: True and False clauses of "
"ternary expression have different types." << endl;
if (! NetETernary::test_operand_compat(tsig->data_type(),fsig->data_type())) {
cerr << get_fileline() << ": internal error: "
<< " True and False clauses of ternary expression "
<< " have incompatible types." << endl;
cerr << get_fileline() << ": : True clause is: "
<< tsig->data_type() << endl;
<< tsig->data_type()
<< " (" << true_val_->expr_type() << "): "
<< *true_val_ << endl;
cerr << get_fileline() << ": : False clause is: "
<< fsig->data_type() << endl;
<< fsig->data_type()
<< " (" << false_val_->expr_type() << "): "
<< *false_val_ << endl;
des->errors += 1;
return 0;
} else if (tsig->data_type() == IVL_VT_NO_TYPE) {

View File

@ -502,7 +502,8 @@ extern ivl_net_const_t ivl_design_const(ivl_design_t, unsigned idx);
* ivl_const_bits
* This returns a pointer to an array of constant characters,
* each byte a '0', '1', 'x' or 'z'. The array is *not* nul
* terminated.
* terminated. This value is only value if ivl_const_type is
* IVL_VT_LOGIC or IVL_VT_BOOL. It returns nil otherwise.
*
* ivl_const_nex
* Return the ivl_nexus_t of the output for the constant.

View File

@ -3565,6 +3565,9 @@ class NetETernary : public NetExpr {
virtual void dump(ostream&) const;
virtual NetNet*synthesize(Design*, NetScope*scope);
public:
static bool test_operand_compat(ivl_variable_type_t tru, ivl_variable_type_t fal);
private:
NetExpr*cond_;
NetExpr*true_val_;

View File

@ -118,6 +118,7 @@ extern "C" const char*ivl_const_bits(ivl_net_const_t net)
assert(net);
switch (net->type) {
case IVL_VT_BOOL:
case IVL_VT_LOGIC:
if (net->width_ <= sizeof(net->b.bit_))
return net->b.bit_;

View File

@ -2199,7 +2199,7 @@ bool dll_target::net_const(const NetConst*net)
struct ivl_net_const_s *obj = new struct ivl_net_const_s;
obj->type = IVL_VT_LOGIC;
obj->type = IVL_VT_BOOL;
/* constants have a single vector output. */
assert(net->pin_count() == 1);
@ -2223,9 +2223,13 @@ bool dll_target::net_const(const NetConst*net)
bits[idx] = '1';
break;
case verinum::Vx:
if (obj->type == IVL_VT_BOOL)
obj->type = IVL_VT_LOGIC;
bits[idx] = 'x';
break;
case verinum::Vz:
if (obj->type == IVL_VT_BOOL)
obj->type = IVL_VT_LOGIC;
bits[idx] = 'z';
break;
}

View File

@ -1058,8 +1058,10 @@ static void signal_nexus_const(ivl_signal_t sig,
fprintf(out, " const-");
switch (ivl_const_type(con)) {
case IVL_VT_BOOL:
case IVL_VT_LOGIC:
bits = ivl_const_bits(con);
assert(bits);
for (idx = 0 ; idx < width ; idx += 1) {
fprintf(out, "%c", bits[width-idx-1]);
}